Skip to content

Commit 1794de8

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: Split GetLatestCommitStatus as two functions (go-gitea#34535) Don't display error log when .git-blame-ignore-revs doesn't exist (go-gitea#34457) Add sort option recentclose for issues and pulls (go-gitea#34525) fix: return 201 Created for CreateVariable API responses (go-gitea#34517) Actions list (go-gitea#34530)
2 parents 28a749b + 688da55 commit 1794de8

27 files changed

+197
-101
lines changed

models/fixtures/commit_status.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
target_url: https://example.com/builds/
88
description: My awesome CI-service
99
context: ci/awesomeness
10+
context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7
1011
creator_id: 2
1112

1213
-
@@ -18,6 +19,7 @@
1819
target_url: https://example.com/converage/
1920
description: My awesome Coverage service
2021
context: cov/awesomeness
22+
context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe
2123
creator_id: 2
2224

2325
-
@@ -29,6 +31,7 @@
2931
target_url: https://example.com/converage/
3032
description: My awesome Coverage service
3133
context: cov/awesomeness
34+
context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe
3235
creator_id: 2
3336

3437
-
@@ -40,6 +43,7 @@
4043
target_url: https://example.com/builds/
4144
description: My awesome CI-service
4245
context: ci/awesomeness
46+
context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7
4347
creator_id: 2
4448

4549
-
@@ -51,4 +55,5 @@
5155
target_url: https://example.com/builds/
5256
description: My awesome deploy service
5357
context: deploy/awesomeness
58+
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
5459
creator_id: 2

models/git/commit_status.go

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -298,27 +298,37 @@ type CommitStatusIndex struct {
298298
MaxIndex int64 `xorm:"index"`
299299
}
300300

301+
func makeRepoCommitQuery(ctx context.Context, repoID int64, sha string) *xorm.Session {
302+
return db.GetEngine(ctx).Table(&CommitStatus{}).
303+
Where("repo_id = ?", repoID).And("sha = ?", sha)
304+
}
305+
301306
// GetLatestCommitStatus returns all statuses with a unique context for a given commit.
302-
func GetLatestCommitStatus(ctx context.Context, repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, int64, error) {
303-
getBase := func() *xorm.Session {
304-
return db.GetEngine(ctx).Table(&CommitStatus{}).
305-
Where("repo_id = ?", repoID).And("sha = ?", sha)
306-
}
307+
func GetLatestCommitStatus(ctx context.Context, repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, error) {
307308
indices := make([]int64, 0, 10)
308-
sess := getBase().Select("max( `index` ) as `index`").
309-
GroupBy("context_hash").OrderBy("max( `index` ) desc")
309+
sess := makeRepoCommitQuery(ctx, repoID, sha).
310+
Select("max( `index` ) as `index`").
311+
GroupBy("context_hash").
312+
OrderBy("max( `index` ) desc")
310313
if !listOptions.IsListAll() {
311314
sess = db.SetSessionPagination(sess, &listOptions)
312315
}
313-
count, err := sess.FindAndCount(&indices)
314-
if err != nil {
315-
return nil, count, err
316+
if err := sess.Find(&indices); err != nil {
317+
return nil, err
316318
}
317319
statuses := make([]*CommitStatus, 0, len(indices))
318320
if len(indices) == 0 {
319-
return statuses, count, nil
321+
return statuses, nil
320322
}
321-
return statuses, count, getBase().And(builder.In("`index`", indices)).Find(&statuses)
323+
err := makeRepoCommitQuery(ctx, repoID, sha).And(builder.In("`index`", indices)).Find(&statuses)
324+
return statuses, err
325+
}
326+
327+
func CountLatestCommitStatus(ctx context.Context, repoID int64, sha string) (int64, error) {
328+
return makeRepoCommitQuery(ctx, repoID, sha).
329+
Select("count(context_hash)").
330+
GroupBy("context_hash").
331+
Count()
322332
}
323333

324334
// GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs

models/git/commit_status_summary.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func GetLatestCommitStatusForRepoAndSHAs(ctx context.Context, repoSHAs []RepoSHA
5555
}
5656

5757
func UpdateCommitStatusSummary(ctx context.Context, repoID int64, sha string) error {
58-
commitStatuses, _, err := GetLatestCommitStatus(ctx, repoID, sha, db.ListOptionsAll)
58+
commitStatuses, err := GetLatestCommitStatus(ctx, repoID, sha, db.ListOptionsAll)
5959
if err != nil {
6060
return err
6161
}

models/git/commit_status_test.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestGetCommitStatuses(t *testing.T) {
2626

2727
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
2828

29-
sha1 := "1234123412341234123412341234123412341234"
29+
sha1 := "1234123412341234123412341234123412341234" // the mocked commit ID in test fixtures
3030

3131
statuses, maxResults, err := db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{
3232
ListOptions: db.ListOptions{Page: 1, PageSize: 50},
@@ -256,3 +256,26 @@ func TestCommitStatusesHideActionsURL(t *testing.T) {
256256
assert.Empty(t, statuses[0].TargetURL)
257257
assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL)
258258
}
259+
260+
func TestGetCountLatestCommitStatus(t *testing.T) {
261+
assert.NoError(t, unittest.PrepareTestDatabase())
262+
263+
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
264+
265+
sha1 := "1234123412341234123412341234123412341234" // the mocked commit ID in test fixtures
266+
267+
commitStatuses, err := git_model.GetLatestCommitStatus(db.DefaultContext, repo1.ID, sha1, db.ListOptions{
268+
Page: 1,
269+
PageSize: 2,
270+
})
271+
assert.NoError(t, err)
272+
assert.Len(t, commitStatuses, 2)
273+
assert.Equal(t, structs.CommitStatusFailure, commitStatuses[0].State)
274+
assert.Equal(t, "ci/awesomeness", commitStatuses[0].Context)
275+
assert.Equal(t, structs.CommitStatusError, commitStatuses[1].State)
276+
assert.Equal(t, "deploy/awesomeness", commitStatuses[1].Context)
277+
278+
count, err := git_model.CountLatestCommitStatus(db.DefaultContext, repo1.ID, sha1)
279+
assert.NoError(t, err)
280+
assert.EqualValues(t, 3, count)
281+
}

models/issues/issue_search.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
8888
sess.Asc("issue.created_unix").Asc("issue.id")
8989
case "recentupdate":
9090
sess.Desc("issue.updated_unix").Desc("issue.created_unix").Desc("issue.id")
91+
case "recentclose":
92+
sess.Desc("issue.closed_unix").Desc("issue.created_unix").Desc("issue.id")
9193
case "leastupdate":
9294
sess.Asc("issue.updated_unix").Asc("issue.created_unix").Asc("issue.id")
9395
case "mostcomment":

models/issues/pull_list.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ func PullRequests(ctx context.Context, baseRepoID int64, opts *PullRequestsOptio
152152
applySorts(findSession, opts.SortType, 0)
153153
findSession = db.SetSessionPagination(findSession, opts)
154154
prs := make([]*PullRequest, 0, opts.PageSize)
155-
return prs, maxResults, findSession.Find(&prs)
155+
found := findSession.Find(&prs)
156+
return prs, maxResults, found
156157
}
157158

158159
// PullRequestList defines a list of pull requests

models/issues/pull_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"code.gitea.io/gitea/modules/setting"
1515

1616
"github.com/stretchr/testify/assert"
17+
"github.com/stretchr/testify/require"
1718
)
1819

1920
func TestPullRequest_LoadAttributes(t *testing.T) {
@@ -76,6 +77,47 @@ func TestPullRequestsNewest(t *testing.T) {
7677
}
7778
}
7879

80+
func TestPullRequests_Closed_RecentSortType(t *testing.T) {
81+
// Issue ID | Closed At. | Updated At
82+
// 2 | 1707270001 | 1707270001
83+
// 3 | 1707271000 | 1707279999
84+
// 11 | 1707279999 | 1707275555
85+
tests := []struct {
86+
sortType string
87+
expectedIssueIDOrder []int64
88+
}{
89+
{"recentupdate", []int64{3, 11, 2}},
90+
{"recentclose", []int64{11, 3, 2}},
91+
}
92+
93+
assert.NoError(t, unittest.PrepareTestDatabase())
94+
_, err := db.Exec(db.DefaultContext, "UPDATE issue SET closed_unix = 1707270001, updated_unix = 1707270001, is_closed = true WHERE id = 2")
95+
require.NoError(t, err)
96+
_, err = db.Exec(db.DefaultContext, "UPDATE issue SET closed_unix = 1707271000, updated_unix = 1707279999, is_closed = true WHERE id = 3")
97+
require.NoError(t, err)
98+
_, err = db.Exec(db.DefaultContext, "UPDATE issue SET closed_unix = 1707279999, updated_unix = 1707275555, is_closed = true WHERE id = 11")
99+
require.NoError(t, err)
100+
101+
for _, test := range tests {
102+
t.Run(test.sortType, func(t *testing.T) {
103+
prs, _, err := issues_model.PullRequests(db.DefaultContext, 1, &issues_model.PullRequestsOptions{
104+
ListOptions: db.ListOptions{
105+
Page: 1,
106+
},
107+
State: "closed",
108+
SortType: test.sortType,
109+
})
110+
require.NoError(t, err)
111+
112+
if assert.Len(t, prs, len(test.expectedIssueIDOrder)) {
113+
for i := range test.expectedIssueIDOrder {
114+
assert.Equal(t, test.expectedIssueIDOrder[i], prs[i].IssueID)
115+
}
116+
}
117+
})
118+
}
119+
}
120+
79121
func TestLoadRequestedReviewers(t *testing.T) {
80122
assert.NoError(t, unittest.PrepareTestDatabase())
81123

modules/git/blame.go

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,22 @@ func (r *BlameReader) Close() error {
132132
}
133133

134134
// CreateBlameReader creates reader for given repository, commit and file
135-
func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath string, commit *Commit, file string, bypassBlameIgnore bool) (*BlameReader, error) {
136-
reader, stdout, err := os.Pipe()
137-
if err != nil {
138-
return nil, err
139-
}
135+
func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath string, commit *Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, err error) {
136+
var ignoreRevsFileName string
137+
var ignoreRevsFileCleanup func()
138+
defer func() {
139+
if err != nil && ignoreRevsFileCleanup != nil {
140+
ignoreRevsFileCleanup()
141+
}
142+
}()
140143

141144
cmd := NewCommandNoGlobals("blame", "--porcelain")
142145

143-
var ignoreRevsFileName string
144-
var ignoreRevsFileCleanup func() // TODO: maybe it should check the returned err in a defer func to make sure the cleanup could always be executed correctly
145146
if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore {
146-
ignoreRevsFileName, ignoreRevsFileCleanup = tryCreateBlameIgnoreRevsFile(commit)
147+
ignoreRevsFileName, ignoreRevsFileCleanup, err = tryCreateBlameIgnoreRevsFile(commit)
148+
if err != nil && !IsErrNotExist(err) {
149+
return nil, err
150+
}
147151
if ignoreRevsFileName != "" {
148152
// Possible improvement: use --ignore-revs-file /dev/stdin on unix
149153
// There is no equivalent on Windows. May be implemented if Gitea uses an external git backend.
@@ -154,6 +158,10 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
154158
cmd.AddDynamicArguments(commit.ID.String()).AddDashesAndList(file)
155159

156160
done := make(chan error, 1)
161+
reader, stdout, err := os.Pipe()
162+
if err != nil {
163+
return nil, err
164+
}
157165
go func() {
158166
stderr := bytes.Buffer{}
159167
// TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close"
@@ -182,33 +190,29 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
182190
}, nil
183191
}
184192

185-
func tryCreateBlameIgnoreRevsFile(commit *Commit) (string, func()) {
193+
func tryCreateBlameIgnoreRevsFile(commit *Commit) (string, func(), error) {
186194
entry, err := commit.GetTreeEntryByPath(".git-blame-ignore-revs")
187195
if err != nil {
188-
log.Error("Unable to get .git-blame-ignore-revs file: GetTreeEntryByPath: %v", err)
189-
return "", nil
196+
return "", nil, err
190197
}
191198

192199
r, err := entry.Blob().DataAsync()
193200
if err != nil {
194-
log.Error("Unable to get .git-blame-ignore-revs file data: DataAsync: %v", err)
195-
return "", nil
201+
return "", nil, err
196202
}
197203
defer r.Close()
198204

199205
f, cleanup, err := setting.AppDataTempDir("git-repo-content").CreateTempFileRandom("git-blame-ignore-revs")
200206
if err != nil {
201-
log.Error("Unable to get .git-blame-ignore-revs file data: CreateTempFileRandom: %v", err)
202-
return "", nil
207+
return "", nil, err
203208
}
204209
filename := f.Name()
205210
_, err = io.Copy(f, r)
206211
_ = f.Close()
207212
if err != nil {
208213
cleanup()
209-
log.Error("Unable to get .git-blame-ignore-revs file data: Copy: %v", err)
210-
return "", nil
214+
return "", nil, err
211215
}
212216

213-
return filename, cleanup
217+
return filename, cleanup, nil
214218
}

routers/api/v1/org/action.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,13 @@ func (Action) CreateVariable(ctx *context.APIContext) {
384384
// "$ref": "#/definitions/CreateVariableOption"
385385
// responses:
386386
// "201":
387-
// description: response when creating an org-level variable
388-
// "204":
389-
// description: response when creating an org-level variable
387+
// description: successfully created the org-level variable
390388
// "400":
391389
// "$ref": "#/responses/error"
392-
// "404":
393-
// "$ref": "#/responses/notFound"
390+
// "409":
391+
// description: variable name already exists.
392+
// "500":
393+
// "$ref": "#/responses/error"
394394

395395
opt := web.GetForm(ctx).(*api.CreateVariableOption)
396396

@@ -419,7 +419,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
419419
return
420420
}
421421

422-
ctx.Status(http.StatusNoContent)
422+
ctx.Status(http.StatusCreated)
423423
}
424424

425425
// UpdateVariable update an org-level variable

routers/api/v1/repo/action.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,12 +339,12 @@ func (Action) CreateVariable(ctx *context.APIContext) {
339339
// responses:
340340
// "201":
341341
// description: response when creating a repo-level variable
342-
// "204":
343-
// description: response when creating a repo-level variable
344342
// "400":
345343
// "$ref": "#/responses/error"
346-
// "404":
347-
// "$ref": "#/responses/notFound"
344+
// "409":
345+
// description: variable name already exists.
346+
// "500":
347+
// "$ref": "#/responses/error"
348348

349349
opt := web.GetForm(ctx).(*api.CreateVariableOption)
350350

@@ -373,7 +373,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
373373
return
374374
}
375375

376-
ctx.Status(http.StatusNoContent)
376+
ctx.Status(http.StatusCreated)
377377
}
378378

379379
// UpdateVariable update a repo-level variable

routers/api/v1/repo/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func ListPullRequests(ctx *context.APIContext) {
7373
// in: query
7474
// description: Type of sort
7575
// type: string
76-
// enum: [oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority]
76+
// enum: [oldest, recentupdate, recentclose, leastupdate, mostcomment, leastcomment, priority]
7777
// - name: milestone
7878
// in: query
7979
// description: ID of the milestone

routers/api/v1/repo/status.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,19 +258,24 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
258258

259259
repo := ctx.Repo.Repository
260260

261-
statuses, count, err := git_model.GetLatestCommitStatus(ctx, repo.ID, refCommit.Commit.ID.String(), utils.GetListOptions(ctx))
261+
statuses, err := git_model.GetLatestCommitStatus(ctx, repo.ID, refCommit.Commit.ID.String(), utils.GetListOptions(ctx))
262262
if err != nil {
263263
ctx.APIErrorInternal(fmt.Errorf("GetLatestCommitStatus[%s, %s]: %w", repo.FullName(), refCommit.CommitID, err))
264264
return
265265
}
266266

267+
count, err := git_model.CountLatestCommitStatus(ctx, repo.ID, refCommit.Commit.ID.String())
268+
if err != nil {
269+
ctx.APIErrorInternal(fmt.Errorf("CountLatestCommitStatus[%s, %s]: %w", repo.FullName(), refCommit.CommitID, err))
270+
return
271+
}
272+
ctx.SetTotalCountHeader(count)
273+
267274
if len(statuses) == 0 {
268275
ctx.JSON(http.StatusOK, &api.CombinedStatus{})
269276
return
270277
}
271278

272279
combiStatus := convert.ToCombinedStatus(ctx, statuses, convert.ToRepo(ctx, repo, ctx.Repo.Permission))
273-
274-
ctx.SetTotalCountHeader(count)
275280
ctx.JSON(http.StatusOK, combiStatus)
276281
}

0 commit comments

Comments
 (0)