Skip to content

Commit 0b5d0a9

Browse files
authored
Merge branch 'main' into fix/composer-bin-missing
2 parents ca847bf + a802508 commit 0b5d0a9

File tree

7 files changed

+84
-6
lines changed

7 files changed

+84
-6
lines changed

.github/labeler.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@ modifies/go:
7070
- any-glob-to-any-file:
7171
- "**/*.go"
7272

73-
modifies/js:
73+
modifies/frontend:
7474
- changed-files:
7575
- any-glob-to-any-file:
7676
- "**/*.js"
77+
- "**/*.ts"
7778
- "**/*.vue"
7879

7980
docs-update-needed:

models/activities/repo_activity.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type ActivityStats struct {
3434
OpenedPRAuthorCount int64
3535
MergedPRs issues_model.PullRequestList
3636
MergedPRAuthorCount int64
37+
ActiveIssues issues_model.IssueList
3738
OpenedIssues issues_model.IssueList
3839
OpenedIssueAuthorCount int64
3940
ClosedIssues issues_model.IssueList
@@ -172,7 +173,7 @@ func (stats *ActivityStats) MergedPRPerc() int {
172173

173174
// ActiveIssueCount returns total active issue count
174175
func (stats *ActivityStats) ActiveIssueCount() int {
175-
return stats.OpenedIssueCount() + stats.ClosedIssueCount()
176+
return len(stats.ActiveIssues)
176177
}
177178

178179
// OpenedIssueCount returns open issue count
@@ -285,13 +286,21 @@ func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTi
285286
stats.ClosedIssueAuthorCount = count
286287

287288
// New issues
288-
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
289+
sess = newlyCreatedIssues(ctx, repoID, fromTime)
289290
sess.OrderBy("issue.created_unix ASC")
290291
stats.OpenedIssues = make(issues_model.IssueList, 0)
291292
if err = sess.Find(&stats.OpenedIssues); err != nil {
292293
return err
293294
}
294295

296+
// Active issues
297+
sess = activeIssues(ctx, repoID, fromTime)
298+
sess.OrderBy("issue.created_unix ASC")
299+
stats.ActiveIssues = make(issues_model.IssueList, 0)
300+
if err = sess.Find(&stats.ActiveIssues); err != nil {
301+
return err
302+
}
303+
295304
// Opened issue authors
296305
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
297306
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
@@ -317,6 +326,23 @@ func (stats *ActivityStats) FillUnresolvedIssues(ctx context.Context, repoID int
317326
return sess.Find(&stats.UnresolvedIssues)
318327
}
319328

329+
func newlyCreatedIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
330+
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
331+
And("issue.is_pull = ?", false). // Retain the is_pull check to exclude pull requests
332+
And("issue.created_unix >= ?", fromTime.Unix()) // Include all issues created after fromTime
333+
334+
return sess
335+
}
336+
337+
func activeIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
338+
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
339+
And("issue.is_pull = ?", false).
340+
And("issue.created_unix >= ?", fromTime.Unix()).
341+
Or("issue.closed_unix >= ?", fromTime.Unix())
342+
343+
return sess
344+
}
345+
320346
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
321347
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
322348
And("issue.is_closed = ?", closed)

modules/httpcache/httpcache.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
7575
w.Header().Set("Etag", etag)
7676
}
7777
if lastModified != nil && !lastModified.IsZero() {
78-
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
78+
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
79+
w.Header().Set("Last-Modified", lastModified.UTC().Format(http.TimeFormat))
7980
}
8081

8182
if len(etag) > 0 {

modules/httplib/serve.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
7979
httpcache.SetCacheControlInHeader(header, duration)
8080

8181
if !opts.LastModified.IsZero() {
82+
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
8283
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
8384
}
8485
}

routers/api/packages/maven/maven.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"strings"
2121

2222
packages_model "code.gitea.io/gitea/models/packages"
23+
"code.gitea.io/gitea/modules/globallock"
2324
"code.gitea.io/gitea/modules/json"
2425
"code.gitea.io/gitea/modules/log"
2526
packages_module "code.gitea.io/gitea/modules/packages"
@@ -114,7 +115,9 @@ func serveMavenMetadata(ctx *context.Context, params parameters) {
114115
xmlMetadataWithHeader := append([]byte(xml.Header), xmlMetadata...)
115116

116117
latest := pds[len(pds)-1]
117-
ctx.Resp.Header().Set("Last-Modified", latest.Version.CreatedUnix.Format(http.TimeFormat))
118+
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
119+
lastModifed := latest.Version.CreatedUnix.AsTime().UTC().Format(http.TimeFormat)
120+
ctx.Resp.Header().Set("Last-Modified", lastModifed)
118121

119122
ext := strings.ToLower(filepath.Ext(params.Filename))
120123
if isChecksumExtension(ext) {
@@ -223,6 +226,10 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
223226
helper.ServePackageFile(ctx, s, u, pf, opts)
224227
}
225228

229+
func mavenPkgNameKey(packageName string) string {
230+
return "pkg_maven_" + packageName
231+
}
232+
226233
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.
227234
func UploadPackageFile(ctx *context.Context) {
228235
params, err := extractPathParameters(ctx)
@@ -241,6 +248,14 @@ func UploadPackageFile(ctx *context.Context) {
241248

242249
packageName := params.GroupID + "-" + params.ArtifactID
243250

251+
// for the same package, only one upload at a time
252+
releaser, err := globallock.Lock(ctx, mavenPkgNameKey(packageName))
253+
if err != nil {
254+
apiError(ctx, http.StatusInternalServerError, err)
255+
return
256+
}
257+
defer releaser()
258+
244259
buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body)
245260
if err != nil {
246261
apiError(ctx, http.StatusInternalServerError, err)

routers/web/repo/githttp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,8 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
395395

396396
ctx.Resp.Header().Set("Content-Type", contentType)
397397
ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
398-
ctx.Resp.Header().Set("Last-Modified", fi.ModTime().Format(http.TimeFormat))
398+
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
399+
ctx.Resp.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
399400
http.ServeFile(ctx.Resp, ctx.Req, reqFile)
400401
}
401402

tests/integration/api_packages_maven_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"strconv"
1010
"strings"
11+
"sync"
1112
"testing"
1213

1314
"code.gitea.io/gitea/models/db"
@@ -252,3 +253,35 @@ func TestPackageMaven(t *testing.T) {
252253
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
253254
})
254255
}
256+
257+
func TestPackageMavenConcurrent(t *testing.T) {
258+
defer tests.PrepareTestEnv(t)()
259+
260+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
261+
262+
groupID := "com.gitea"
263+
artifactID := "test-project"
264+
packageVersion := "1.0.1"
265+
266+
root := fmt.Sprintf("/api/packages/%s/maven/%s/%s", user.Name, strings.ReplaceAll(groupID, ".", "/"), artifactID)
267+
268+
putFile := func(t *testing.T, path, content string, expectedStatus int) {
269+
req := NewRequestWithBody(t, "PUT", root+path, strings.NewReader(content)).
270+
AddBasicAuth(user.Name)
271+
MakeRequest(t, req, expectedStatus)
272+
}
273+
274+
t.Run("Concurrent Upload", func(t *testing.T) {
275+
defer tests.PrintCurrentTest(t)()
276+
277+
var wg sync.WaitGroup
278+
for i := 0; i < 10; i++ {
279+
wg.Add(1)
280+
go func(i int) {
281+
putFile(t, fmt.Sprintf("/%s/%s.jar", packageVersion, strconv.Itoa(i)), "test", http.StatusCreated)
282+
wg.Done()
283+
}(i)
284+
}
285+
wg.Wait()
286+
})
287+
}

0 commit comments

Comments
 (0)