mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	User specific repoID or xorm builder conditions for issue search (#19475)
* extend models.IssuesOptions to have more specific repo filter options * use new options * unrelated refactor * rm RepoIDs
This commit is contained in:
		@@ -1194,7 +1194,8 @@ func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) {
 | 
				
			|||||||
// IssuesOptions represents options of an issue.
 | 
					// IssuesOptions represents options of an issue.
 | 
				
			||||||
type IssuesOptions struct {
 | 
					type IssuesOptions struct {
 | 
				
			||||||
	db.ListOptions
 | 
						db.ListOptions
 | 
				
			||||||
	RepoIDs            []int64 // include all repos if empty
 | 
						RepoID             int64 // overwrites RepoCond if not 0
 | 
				
			||||||
 | 
						RepoCond           builder.Cond
 | 
				
			||||||
	AssigneeID         int64
 | 
						AssigneeID         int64
 | 
				
			||||||
	PosterID           int64
 | 
						PosterID           int64
 | 
				
			||||||
	MentionedID        int64
 | 
						MentionedID        int64
 | 
				
			||||||
@@ -1285,15 +1286,15 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {
 | 
				
			|||||||
		sess.In("issue.id", opts.IssueIDs)
 | 
							sess.In("issue.id", opts.IssueIDs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(opts.RepoIDs) > 0 {
 | 
						if opts.RepoID != 0 {
 | 
				
			||||||
		applyReposCondition(sess, opts.RepoIDs)
 | 
							opts.RepoCond = builder.Eq{"issue.repo_id": opts.RepoID}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if opts.RepoCond != nil {
 | 
				
			||||||
 | 
							sess.And(opts.RepoCond)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch opts.IsClosed {
 | 
						if !opts.IsClosed.IsNone() {
 | 
				
			||||||
	case util.OptionalBoolTrue:
 | 
							sess.And("issue.is_closed=?", opts.IsClosed.IsTrue())
 | 
				
			||||||
		sess.And("issue.is_closed=?", true)
 | 
					 | 
				
			||||||
	case util.OptionalBoolFalse:
 | 
					 | 
				
			||||||
		sess.And("issue.is_closed=?", false)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if opts.AssigneeID > 0 {
 | 
						if opts.AssigneeID > 0 {
 | 
				
			||||||
@@ -1412,10 +1413,6 @@ func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organizati
 | 
				
			|||||||
	return cond
 | 
						return cond
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func applyReposCondition(sess *xorm.Session, repoIDs []int64) *xorm.Session {
 | 
					 | 
				
			||||||
	return sess.In("issue.repo_id", repoIDs)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func applyAssigneeCondition(sess *xorm.Session, assigneeID int64) *xorm.Session {
 | 
					func applyAssigneeCondition(sess *xorm.Session, assigneeID int64) *xorm.Session {
 | 
				
			||||||
	return sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
 | 
						return sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
 | 
				
			||||||
		And("issue_assignees.assignee_id = ?", assigneeID)
 | 
							And("issue_assignees.assignee_id = ?", assigneeID)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,12 +57,9 @@ func (label *Label) CalOpenIssues() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
 | 
					// CalOpenOrgIssues calculates the open issues of a label for a specific repo
 | 
				
			||||||
func (label *Label) CalOpenOrgIssues(repoID, labelID int64) {
 | 
					func (label *Label) CalOpenOrgIssues(repoID, labelID int64) {
 | 
				
			||||||
	repoIDs := []int64{repoID}
 | 
					 | 
				
			||||||
	labelIDs := []int64{labelID}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	counts, _ := CountIssuesByRepo(&IssuesOptions{
 | 
						counts, _ := CountIssuesByRepo(&IssuesOptions{
 | 
				
			||||||
		RepoIDs:  repoIDs,
 | 
							RepoID:   repoID,
 | 
				
			||||||
		LabelIDs: labelIDs,
 | 
							LabelIDs: []int64{labelID},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, count := range counts {
 | 
						for _, count := range counts {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ import (
 | 
				
			|||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestIssue_ReplaceLabels(t *testing.T) {
 | 
					func TestIssue_ReplaceLabels(t *testing.T) {
 | 
				
			||||||
@@ -157,7 +158,7 @@ func TestIssues(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			IssuesOptions{
 | 
								IssuesOptions{
 | 
				
			||||||
				RepoIDs:  []int64{1, 3},
 | 
									RepoCond: builder.In("repo_id", 1, 3),
 | 
				
			||||||
				SortType: "oldest",
 | 
									SortType: "oldest",
 | 
				
			||||||
				ListOptions: db.ListOptions{
 | 
									ListOptions: db.ListOptions{
 | 
				
			||||||
					Page:     1,
 | 
										Page:     1,
 | 
				
			||||||
@@ -344,7 +345,7 @@ func TestGetRepoIDsForIssuesOptions(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			IssuesOptions{
 | 
								IssuesOptions{
 | 
				
			||||||
				RepoIDs: []int64{1, 2},
 | 
									RepoCond: builder.In("repo_id", 1, 2),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			[]int64{1, 2},
 | 
								[]int64{1, 2},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -321,7 +321,7 @@ func populateIssueIndexer(ctx context.Context) {
 | 
				
			|||||||
// UpdateRepoIndexer add/update all issues of the repositories
 | 
					// UpdateRepoIndexer add/update all issues of the repositories
 | 
				
			||||||
func UpdateRepoIndexer(repo *repo_model.Repository) {
 | 
					func UpdateRepoIndexer(repo *repo_model.Repository) {
 | 
				
			||||||
	is, err := models.Issues(&models.IssuesOptions{
 | 
						is, err := models.Issues(&models.IssuesOptions{
 | 
				
			||||||
		RepoIDs:  []int64{repo.ID},
 | 
							RepoID:   repo.ID,
 | 
				
			||||||
		IsClosed: util.OptionalBoolNone,
 | 
							IsClosed: util.OptionalBoolNone,
 | 
				
			||||||
		IsPull:   util.OptionalBoolNone,
 | 
							IsPull:   util.OptionalBoolNone,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -175,6 +175,7 @@ func SearchIssues(ctx *context.APIContext) {
 | 
				
			|||||||
		opts.TeamID = team.ID
 | 
							opts.TeamID = team.ID
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repoCond := models.SearchRepositoryCondition(opts)
 | 
				
			||||||
	repoIDs, _, err := models.SearchRepositoryIDs(opts)
 | 
						repoIDs, _, err := models.SearchRepositoryIDs(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
 | 
							ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
 | 
				
			||||||
@@ -235,7 +236,7 @@ func SearchIssues(ctx *context.APIContext) {
 | 
				
			|||||||
				Page:     ctx.FormInt("page"),
 | 
									Page:     ctx.FormInt("page"),
 | 
				
			||||||
				PageSize: limit,
 | 
									PageSize: limit,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			RepoIDs:            repoIDs,
 | 
								RepoCond:           repoCond,
 | 
				
			||||||
			IsClosed:           isClosed,
 | 
								IsClosed:           isClosed,
 | 
				
			||||||
			IssueIDs:           issueIDs,
 | 
								IssueIDs:           issueIDs,
 | 
				
			||||||
			IncludedLabelNames: includedLabelNames,
 | 
								IncludedLabelNames: includedLabelNames,
 | 
				
			||||||
@@ -462,7 +463,7 @@ func ListIssues(ctx *context.APIContext) {
 | 
				
			|||||||
	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
 | 
						if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
 | 
				
			||||||
		issuesOpt := &models.IssuesOptions{
 | 
							issuesOpt := &models.IssuesOptions{
 | 
				
			||||||
			ListOptions:       listOptions,
 | 
								ListOptions:       listOptions,
 | 
				
			||||||
			RepoIDs:           []int64{ctx.Repo.Repository.ID},
 | 
								RepoID:            ctx.Repo.Repository.ID,
 | 
				
			||||||
			IsClosed:          isClosed,
 | 
								IsClosed:          isClosed,
 | 
				
			||||||
			IssueIDs:          issueIDs,
 | 
								IssueIDs:          issueIDs,
 | 
				
			||||||
			LabelIDs:          labelIDs,
 | 
								LabelIDs:          labelIDs,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,7 +232,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
 | 
				
			|||||||
				Page:     pager.Paginater.Current(),
 | 
									Page:     pager.Paginater.Current(),
 | 
				
			||||||
				PageSize: setting.UI.IssuePagingNum,
 | 
									PageSize: setting.UI.IssuePagingNum,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			RepoIDs:           []int64{repo.ID},
 | 
								RepoID:            repo.ID,
 | 
				
			||||||
			AssigneeID:        assigneeID,
 | 
								AssigneeID:        assigneeID,
 | 
				
			||||||
			PosterID:          posterID,
 | 
								PosterID:          posterID,
 | 
				
			||||||
			MentionedID:       mentionedID,
 | 
								MentionedID:       mentionedID,
 | 
				
			||||||
@@ -2167,6 +2167,7 @@ func SearchIssues(ctx *context.Context) {
 | 
				
			|||||||
		opts.TeamID = team.ID
 | 
							opts.TeamID = team.ID
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repoCond := models.SearchRepositoryCondition(opts)
 | 
				
			||||||
	repoIDs, _, err := models.SearchRepositoryIDs(opts)
 | 
						repoIDs, _, err := models.SearchRepositoryIDs(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err.Error())
 | 
							ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err.Error())
 | 
				
			||||||
@@ -2227,7 +2228,7 @@ func SearchIssues(ctx *context.Context) {
 | 
				
			|||||||
				Page:     ctx.FormInt("page"),
 | 
									Page:     ctx.FormInt("page"),
 | 
				
			||||||
				PageSize: limit,
 | 
									PageSize: limit,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			RepoIDs:            repoIDs,
 | 
								RepoCond:           repoCond,
 | 
				
			||||||
			IsClosed:           isClosed,
 | 
								IsClosed:           isClosed,
 | 
				
			||||||
			IssueIDs:           issueIDs,
 | 
								IssueIDs:           issueIDs,
 | 
				
			||||||
			IncludedLabelNames: includedLabelNames,
 | 
								IncludedLabelNames: includedLabelNames,
 | 
				
			||||||
@@ -2403,7 +2404,7 @@ func ListIssues(ctx *context.Context) {
 | 
				
			|||||||
	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
 | 
						if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
 | 
				
			||||||
		issuesOpt := &models.IssuesOptions{
 | 
							issuesOpt := &models.IssuesOptions{
 | 
				
			||||||
			ListOptions:       listOptions,
 | 
								ListOptions:       listOptions,
 | 
				
			||||||
			RepoIDs:           []int64{ctx.Repo.Repository.ID},
 | 
								RepoID:            ctx.Repo.Repository.ID,
 | 
				
			||||||
			IsClosed:          isClosed,
 | 
								IsClosed:          isClosed,
 | 
				
			||||||
			IssueIDs:          issueIDs,
 | 
								IssueIDs:          issueIDs,
 | 
				
			||||||
			LabelIDs:          labelIDs,
 | 
								LabelIDs:          labelIDs,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -463,13 +463,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
 | 
				
			|||||||
			// to check if it's in the team(which possible isn't the case).
 | 
								// to check if it's in the team(which possible isn't the case).
 | 
				
			||||||
			opts.User = nil
 | 
								opts.User = nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		userRepoIDs, _, err := models.SearchRepositoryIDs(repoOpts)
 | 
							opts.RepoCond = models.SearchRepositoryCondition(repoOpts)
 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			ctx.ServerError("models.SearchRepositoryIDs: %v", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		opts.RepoIDs = userRepoIDs
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// keyword holds the search term entered into the search field.
 | 
						// keyword holds the search term entered into the search field.
 | 
				
			||||||
@@ -533,7 +527,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
 | 
				
			|||||||
	// Gets set when clicking filters on the issues overview page.
 | 
						// Gets set when clicking filters on the issues overview page.
 | 
				
			||||||
	repoIDs := getRepoIDs(ctx.FormString("repos"))
 | 
						repoIDs := getRepoIDs(ctx.FormString("repos"))
 | 
				
			||||||
	if len(repoIDs) > 0 {
 | 
						if len(repoIDs) > 0 {
 | 
				
			||||||
		opts.RepoIDs = repoIDs
 | 
							opts.RepoCond = builder.In("issue.repo_id", repoIDs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ------------------------------
 | 
						// ------------------------------
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,7 +105,7 @@ func TestGiteaUploadRepo(t *testing.T) {
 | 
				
			|||||||
	assert.Len(t, releases, 1)
 | 
						assert.Len(t, releases, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	issues, err := models.Issues(&models.IssuesOptions{
 | 
						issues, err := models.Issues(&models.IssuesOptions{
 | 
				
			||||||
		RepoIDs:  []int64{repo.ID},
 | 
							RepoID:   repo.ID,
 | 
				
			||||||
		IsPull:   util.OptionalBoolFalse,
 | 
							IsPull:   util.OptionalBoolFalse,
 | 
				
			||||||
		SortType: "oldest",
 | 
							SortType: "oldest",
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user