Skip to content

Commit 9d943bf

Browse files
qwerty287KN4CK3R6543
authored
Add missing X-Total-Count and fix some related bugs (#17968)
* Add missing `X-Total-Count` and fix some related bugs Adds `X-Total-Count` header to APIs that return a list but doesn't have it yet. Fixed bugs: * not returned after reporting error (https://github.com/qwerty287/gitea/blob/39eb82446c6fe5da3d79124e1f701f3795625b69/routers/api/v1/user/star.go#L70) * crash with index out of bounds, API issue/issueSubscriptions I also found various endpoints that return lists but do not apply/support pagination yet: ``` /repos/{owner}/{repo}/issues/{index}/labels /repos/{owner}/{repo}/issues/comments/{id}/reactions /repos/{owner}/{repo}/branch_protections /repos/{owner}/{repo}/contents /repos/{owner}/{repo}/hooks/git /repos/{owner}/{repo}/issue_templates /repos/{owner}/{repo}/releases/{id}/assets /repos/{owner}/{repo}/reviewers /repos/{owner}/{repo}/teams /user/emails /users/{username}/heatmap ``` If this is not expected, an new issue should be opened. Closes #13043 * fmt * Update routers/api/v1/repo/issue_subscription.go Co-authored-by: KN4CK3R <[email protected]> * Use FindAndCount Co-authored-by: KN4CK3R <[email protected]> Co-authored-by: 6543 <[email protected]>
1 parent 790e6cf commit 9d943bf

24 files changed

+73
-36
lines changed

models/commit_status.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,11 @@ type CommitStatusIndex struct {
231231
}
232232

233233
// GetLatestCommitStatus returns all statuses with a unique context for a given commit.
234-
func GetLatestCommitStatus(repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, error) {
234+
func GetLatestCommitStatus(repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, int64, error) {
235235
return getLatestCommitStatus(db.GetEngine(db.DefaultContext), repoID, sha, listOptions)
236236
}
237237

238-
func getLatestCommitStatus(e db.Engine, repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, error) {
238+
func getLatestCommitStatus(e db.Engine, repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, int64, error) {
239239
ids := make([]int64, 0, 10)
240240
sess := e.Table(&CommitStatus{}).
241241
Where("repo_id = ?", repoID).And("sha = ?", sha).
@@ -244,15 +244,15 @@ func getLatestCommitStatus(e db.Engine, repoID int64, sha string, listOptions db
244244

245245
sess = db.SetSessionPagination(sess, &listOptions)
246246

247-
err := sess.Find(&ids)
247+
count, err := sess.FindAndCount(&ids)
248248
if err != nil {
249-
return nil, err
249+
return nil, count, err
250250
}
251251
statuses := make([]*CommitStatus, 0, len(ids))
252252
if len(ids) == 0 {
253-
return statuses, nil
253+
return statuses, count, nil
254254
}
255-
return statuses, e.In("id", ids).Find(&statuses)
255+
return statuses, count, e.In("id", ids).Find(&statuses)
256256
}
257257

258258
// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
@@ -340,7 +340,7 @@ func ParseCommitsWithStatus(oldCommits []*asymkey_model.SignCommit, repo *repo_m
340340
commit := &SignCommitWithStatuses{
341341
SignCommit: c,
342342
}
343-
statuses, err := GetLatestCommitStatus(repo.ID, commit.ID.String(), db.ListOptions{})
343+
statuses, _, err := GetLatestCommitStatus(repo.ID, commit.ID.String(), db.ListOptions{})
344344
if err != nil {
345345
log.Error("GetLatestCommitStatus: %v", err)
346346
} else {

models/issue.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func (issue *Issue) loadReactions(ctx context.Context) (err error) {
238238
return nil
239239
}
240240
e := db.GetEngine(ctx)
241-
reactions, err := findReactions(e, FindReactionsOptions{
241+
reactions, _, err := findReactions(e, FindReactionsOptions{
242242
IssueID: issue.ID,
243243
})
244244
if err != nil {

models/issue_comment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ func (c *Comment) loadReactions(e db.Engine, repo *repo_model.Repository) (err e
593593
if c.Reactions != nil {
594594
return nil
595595
}
596-
c.Reactions, err = findReactions(e, FindReactionsOptions{
596+
c.Reactions, _, err = findReactions(e, FindReactionsOptions{
597597
IssueID: c.IssueID,
598598
CommentID: c.ID,
599599
})

models/issue_reaction.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,38 @@ func (opts *FindReactionsOptions) toConds() builder.Cond {
7171
}
7272

7373
// FindCommentReactions returns a ReactionList of all reactions from an comment
74-
func FindCommentReactions(comment *Comment) (ReactionList, error) {
74+
func FindCommentReactions(comment *Comment) (ReactionList, int64, error) {
7575
return findReactions(db.GetEngine(db.DefaultContext), FindReactionsOptions{
7676
IssueID: comment.IssueID,
7777
CommentID: comment.ID,
7878
})
7979
}
8080

8181
// FindIssueReactions returns a ReactionList of all reactions from an issue
82-
func FindIssueReactions(issue *Issue, listOptions db.ListOptions) (ReactionList, error) {
82+
func FindIssueReactions(issue *Issue, listOptions db.ListOptions) (ReactionList, int64, error) {
8383
return findReactions(db.GetEngine(db.DefaultContext), FindReactionsOptions{
8484
ListOptions: listOptions,
8585
IssueID: issue.ID,
8686
CommentID: -1,
8787
})
8888
}
8989

90-
func findReactions(e db.Engine, opts FindReactionsOptions) ([]*Reaction, error) {
91-
e = e.
90+
func findReactions(e db.Engine, opts FindReactionsOptions) ([]*Reaction, int64, error) {
91+
sess := e.
9292
Where(opts.toConds()).
9393
In("reaction.`type`", setting.UI.Reactions).
9494
Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id")
9595
if opts.Page != 0 {
96-
e = db.SetEnginePagination(e, &opts)
96+
sess = db.SetSessionPagination(sess, &opts)
9797

9898
reactions := make([]*Reaction, 0, opts.PageSize)
99-
return reactions, e.Find(&reactions)
99+
count, err := sess.FindAndCount(&reactions)
100+
return reactions, count, err
100101
}
101102

102103
reactions := make([]*Reaction, 0, 10)
103-
return reactions, e.Find(&reactions)
104+
count, err := sess.FindAndCount(&reactions)
105+
return reactions, count, err
104106
}
105107

106108
func createReaction(e db.Engine, opts *ReactionOptions) (*Reaction, error) {
@@ -120,7 +122,7 @@ func createReaction(e db.Engine, opts *ReactionOptions) (*Reaction, error) {
120122
findOpts.CommentID = opts.Comment.ID
121123
}
122124

123-
existingR, err := findReactions(e, findOpts)
125+
existingR, _, err := findReactions(e, findOpts)
124126
if err != nil {
125127
return nil, err
126128
}

models/issue_watch.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,20 @@ func getIssueWatchers(e db.Engine, issueID int64, listOptions db.ListOptions) (I
126126
return watches, sess.Find(&watches)
127127
}
128128

129+
// CountIssueWatchers count watchers/unwatchers of a given issue
130+
func CountIssueWatchers(issueID int64) (int64, error) {
131+
return countIssueWatchers(db.GetEngine(db.DefaultContext), issueID)
132+
}
133+
134+
func countIssueWatchers(e db.Engine, issueID int64) (int64, error) {
135+
return e.
136+
Where("`issue_watch`.issue_id = ?", issueID).
137+
And("`issue_watch`.is_watching = ?", true).
138+
And("`user`.is_active = ?", true).
139+
And("`user`.prohibit_login = ?", false).
140+
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").Count(new(IssueWatch))
141+
}
142+
129143
func removeIssueWatchersByRepoID(e db.Engine, userID, repoID int64) error {
130144
_, err := e.
131145
Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", repoID).

modules/gitgraph/graph_models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func (graph *Graph) LoadAndProcessCommits(repository *repo_model.Repository, git
120120
return models.IsUserRepoAdmin(repository, user)
121121
}, &keyMap)
122122

123-
statuses, err := models.GetLatestCommitStatus(repository.ID, c.Commit.ID.String(), db.ListOptions{})
123+
statuses, _, err := models.GetLatestCommitStatus(repository.ID, c.Commit.ID.String(), db.ListOptions{})
124124
if err != nil {
125125
log.Error("GetLatestCommitStatus: %v", err)
126126
} else {

modules/indexer/code/indexer_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import (
88
"path/filepath"
99
"testing"
1010

11-
_ "code.gitea.io/gitea/models"
1211
"code.gitea.io/gitea/models/unittest"
1312

13+
_ "code.gitea.io/gitea/models"
14+
1415
"github.com/stretchr/testify/assert"
1516
)
1617

modules/indexer/issues/indexer_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import (
1111
"testing"
1212
"time"
1313

14-
_ "code.gitea.io/gitea/models"
1514
"code.gitea.io/gitea/models/unittest"
1615
"code.gitea.io/gitea/modules/setting"
1716
"code.gitea.io/gitea/modules/util"
1817

18+
_ "code.gitea.io/gitea/models"
19+
1920
"github.com/stretchr/testify/assert"
2021
"gopkg.in/ini.v1"
2122
)

modules/indexer/stats/indexer_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import (
99
"testing"
1010
"time"
1111

12-
_ "code.gitea.io/gitea/models"
1312
repo_model "code.gitea.io/gitea/models/repo"
1413
"code.gitea.io/gitea/models/unittest"
1514
"code.gitea.io/gitea/modules/setting"
1615

16+
_ "code.gitea.io/gitea/models"
17+
1718
"github.com/stretchr/testify/assert"
1819
"gopkg.in/ini.v1"
1920
)

routers/api/v1/org/team.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ func GetTeamRepos(ctx *context.APIContext) {
509509
}
510510
repos[i] = convert.ToRepo(repo, access)
511511
}
512+
ctx.SetTotalCountHeader(int64(team.NumRepos))
512513
ctx.JSON(http.StatusOK, repos)
513514
}
514515

routers/api/v1/repo/issue_reaction.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ func GetIssueCommentReactions(ctx *context.APIContext) {
6767
return
6868
}
6969

70-
reactions, err := models.FindCommentReactions(comment)
70+
reactions, _, err := models.FindCommentReactions(comment)
7171
if err != nil {
72-
ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
72+
ctx.Error(http.StatusInternalServerError, "FindCommentReactions", err)
7373
return
7474
}
7575
_, err = reactions.LoadUsers(ctx.Repo.Repository)
@@ -285,7 +285,7 @@ func GetIssueReactions(ctx *context.APIContext) {
285285
return
286286
}
287287

288-
reactions, err := models.FindIssueReactions(issue, utils.GetListOptions(ctx))
288+
reactions, count, err := models.FindIssueReactions(issue, utils.GetListOptions(ctx))
289289
if err != nil {
290290
ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
291291
return
@@ -305,6 +305,7 @@ func GetIssueReactions(ctx *context.APIContext) {
305305
})
306306
}
307307

308+
ctx.SetTotalCountHeader(count)
308309
ctx.JSON(http.StatusOK, result)
309310
}
310311

routers/api/v1/repo/issue_subscription.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,16 @@ func GetIssueSubscribers(ctx *context.APIContext) {
279279
return
280280
}
281281
apiUsers := make([]*api.User, 0, len(users))
282-
for i := range users {
283-
apiUsers[i] = convert.ToUser(users[i], ctx.User)
282+
for _, v := range users {
283+
apiUsers = append(apiUsers, convert.ToUser(v, ctx.User))
284284
}
285285

286+
count, err := models.CountIssueWatchers(issue.ID)
287+
if err != nil {
288+
ctx.Error(http.StatusInternalServerError, "CountIssueWatchers", err)
289+
return
290+
}
291+
292+
ctx.SetTotalCountHeader(count)
286293
ctx.JSON(http.StatusOK, apiUsers)
287294
}

routers/api/v1/repo/status.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
253253

254254
repo := ctx.Repo.Repository
255255

256-
statuses, err := models.GetLatestCommitStatus(repo.ID, sha, utils.GetListOptions(ctx))
256+
statuses, count, err := models.GetLatestCommitStatus(repo.ID, sha, utils.GetListOptions(ctx))
257257
if err != nil {
258258
ctx.Error(http.StatusInternalServerError, "GetLatestCommitStatus", fmt.Errorf("GetLatestCommitStatus[%s, %s]: %v", repo.FullName(), sha, err))
259259
return
@@ -266,6 +266,6 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
266266

267267
combiStatus := convert.ToCombinedStatus(statuses, convert.ToRepo(repo, ctx.Repo.AccessMode))
268268

269-
// TODO: ctx.SetTotalCountHeader(count)
269+
ctx.SetTotalCountHeader(count)
270270
ctx.JSON(http.StatusOK, combiStatus)
271271
}

routers/api/v1/repo/tree.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func GetTree(ctx *context.APIContext) {
6363
if tree, err := files_service.GetTreeBySHA(ctx.Repo.Repository, sha, ctx.FormInt("page"), ctx.FormInt("per_page"), ctx.FormBool("recursive")); err != nil {
6464
ctx.Error(http.StatusBadRequest, "", err.Error())
6565
} else {
66+
ctx.SetTotalCountHeader(int64(tree.TotalCount))
6667
ctx.JSON(http.StatusOK, tree)
6768
}
6869
}

routers/api/v1/repo/wiki.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ func ListWikiPages(ctx *context.APIContext) {
323323
pages = append(pages, convert.ToWikiPageMetaData(wikiName, c, ctx.Repo.Repository))
324324
}
325325

326+
ctx.SetTotalCountHeader(int64(len(entries)))
326327
ctx.JSON(http.StatusOK, pages)
327328
}
328329

@@ -432,6 +433,7 @@ func ListPageRevisions(ctx *context.APIContext) {
432433
return
433434
}
434435

436+
ctx.SetTotalCountHeader(commitsCount)
435437
ctx.JSON(http.StatusOK, convert.ToWikiCommitList(commitsHistory, commitsCount))
436438
}
437439

routers/api/v1/user/star.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ func GetStarredRepos(ctx *context.APIContext) {
6767
repos, err := getStarredRepos(user, private, utils.GetListOptions(ctx))
6868
if err != nil {
6969
ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
70+
return
7071
}
72+
73+
ctx.SetTotalCountHeader(int64(user.NumStars))
7174
ctx.JSON(http.StatusOK, &repos)
7275
}
7376

routers/web/repo/commit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ func Diff(ctx *context.Context) {
337337
ctx.Data["Commit"] = commit
338338
ctx.Data["Diff"] = diff
339339

340-
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, commitID, db.ListOptions{})
340+
statuses, _, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, commitID, db.ListOptions{})
341341
if err != nil {
342342
log.Error("GetLatestCommitStatus: %v", err)
343343
}

routers/web/repo/pull.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.C
339339

340340
if len(compareInfo.Commits) != 0 {
341341
sha := compareInfo.Commits[0].ID.String()
342-
commitStatuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, sha, db.ListOptions{})
342+
commitStatuses, _, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, sha, db.ListOptions{})
343343
if err != nil {
344344
ctx.ServerError("GetLatestCommitStatus", err)
345345
return nil
@@ -393,7 +393,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
393393
ctx.ServerError(fmt.Sprintf("GetRefCommitID(%s)", pull.GetGitRefName()), err)
394394
return nil
395395
}
396-
commitStatuses, err := models.GetLatestCommitStatus(repo.ID, sha, db.ListOptions{})
396+
commitStatuses, _, err := models.GetLatestCommitStatus(repo.ID, sha, db.ListOptions{})
397397
if err != nil {
398398
ctx.ServerError("GetLatestCommitStatus", err)
399399
return nil
@@ -482,7 +482,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
482482
return nil
483483
}
484484

485-
commitStatuses, err := models.GetLatestCommitStatus(repo.ID, sha, db.ListOptions{})
485+
commitStatuses, _, err := models.GetLatestCommitStatus(repo.ID, sha, db.ListOptions{})
486486
if err != nil {
487487
ctx.ServerError("GetLatestCommitStatus", err)
488488
return nil

routers/web/repo/view.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
790790
ctx.Data["LatestCommitUser"] = user_model.ValidateCommitWithEmail(latestCommit)
791791
}
792792

793-
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, ctx.Repo.Commit.ID.String(), db.ListOptions{})
793+
statuses, _, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, ctx.Repo.Commit.ID.String(), db.ListOptions{})
794794
if err != nil {
795795
log.Error("GetLatestCommitStatus: %v", err)
796796
}

services/asymkey/ssh_key_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"code.gitea.io/gitea/models/login"
1212
"code.gitea.io/gitea/models/unittest"
1313
user_model "code.gitea.io/gitea/models/user"
14+
1415
"github.com/stretchr/testify/assert"
1516
)
1617

services/mailer/mailer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"code.gitea.io/gitea/modules/setting"
12+
1213
"github.com/stretchr/testify/assert"
1314
)
1415

services/pull/commit_status.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func GetPullRequestCommitStatusState(pr *models.PullRequest) (structs.CommitStat
130130
return "", errors.Wrap(err, "LoadBaseRepo")
131131
}
132132

133-
commitStatuses, err := models.GetLatestCommitStatus(pr.BaseRepo.ID, sha, db.ListOptions{})
133+
commitStatuses, _, err := models.GetLatestCommitStatus(pr.BaseRepo.ID, sha, db.ListOptions{})
134134
if err != nil {
135135
return "", errors.Wrap(err, "GetLatestCommitStatus")
136136
}

services/pull/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ func getLastCommitStatus(gitRepo *git.Repository, pr *models.PullRequest) (statu
782782
return nil, err
783783
}
784784

785-
statusList, err := models.GetLatestCommitStatus(pr.BaseRepo.ID, sha, db.ListOptions{})
785+
statusList, _, err := models.GetLatestCommitStatus(pr.BaseRepo.ID, sha, db.ListOptions{})
786786
if err != nil {
787787
return nil, err
788788
}

services/webhook/main_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import (
88
"path/filepath"
99
"testing"
1010

11-
_ "code.gitea.io/gitea/models"
1211
"code.gitea.io/gitea/models/unittest"
12+
13+
_ "code.gitea.io/gitea/models"
1314
)
1415

1516
func TestMain(m *testing.M) {

0 commit comments

Comments
 (0)