Skip to content

Commit 04a5ff7

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: fill missing `has_code` in repository api (go-gitea#36338) Fix notifications pagination query parameters (go-gitea#36351) Fix cancel auto merge bug (go-gitea#36341) Bump appleboy/git-push-action from 1.0.0 to 1.2.0 (go-gitea#36306) Improve diff file headers (go-gitea#36215) Fix delete attachment check (go-gitea#36320) [skip ci] Updated translations via Crowdin LFS locks must belong to the intended repo (go-gitea#36344) Update chroma to v2.22.0 (go-gitea#36342) Update goldmark to v1.7.16 (go-gitea#36343) Fix some trivial problems (go-gitea#36336) Fix diff view style handling (go-gitea#36324) Refactor cat-file batch operations and support `--batch-command` approach (go-gitea#35775) Fix file-tree ui error when adding files to repo without commits (go-gitea#36312)
2 parents 15aa81e + 040fc93 commit 04a5ff7

74 files changed

Lines changed: 1465 additions & 1015 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cron-licenses.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- run: make generate-gitignore
2121
timeout-minutes: 40
2222
- name: push translations to repo
23-
uses: appleboy/git-push-action@v1.0.0
23+
uses: appleboy/git-push-action@v1.2.0
2424
with:
2525
author_email: "teabot@gitea.io"
2626
author_name: GiteaBot

.github/workflows/cron-translations.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- name: update locales
3030
run: ./build/update-locales.sh
3131
- name: push translations to repo
32-
uses: appleboy/git-push-action@v1.0.0
32+
uses: appleboy/git-push-action@v1.2.0
3333
with:
3434
author_email: "teabot@gitea.io"
3535
author_name: GiteaBot

cmd/hook.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ func (n *nilWriter) WriteString(s string) (int, error) {
163163
return len(s), nil
164164
}
165165

166+
func parseGitHookCommitRefLine(line string) (oldCommitID, newCommitID string, refFullName git.RefName, ok bool) {
167+
fields := strings.Split(line, " ")
168+
if len(fields) != 3 {
169+
return "", "", "", false
170+
}
171+
return fields[0], fields[1], git.RefName(fields[2]), true
172+
}
173+
166174
func runHookPreReceive(ctx context.Context, c *cli.Command) error {
167175
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
168176
return nil
@@ -228,14 +236,11 @@ Gitea or set your environment appropriately.`, "")
228236
continue
229237
}
230238

231-
fields := bytes.Fields(scanner.Bytes())
232-
if len(fields) != 3 {
239+
oldCommitID, newCommitID, refFullName, ok := parseGitHookCommitRefLine(scanner.Text())
240+
if !ok {
233241
continue
234242
}
235243

236-
oldCommitID := string(fields[0])
237-
newCommitID := string(fields[1])
238-
refFullName := git.RefName(fields[2])
239244
total++
240245
lastline++
241246

@@ -378,16 +383,13 @@ Gitea or set your environment appropriately.`, "")
378383
continue
379384
}
380385

381-
fields := bytes.Fields(scanner.Bytes())
382-
if len(fields) != 3 {
386+
var ok bool
387+
oldCommitIDs[count], newCommitIDs[count], refFullNames[count], ok = parseGitHookCommitRefLine(scanner.Text())
388+
if !ok {
383389
continue
384390
}
385391

386392
fmt.Fprintf(out, ".")
387-
oldCommitIDs[count] = string(fields[0])
388-
newCommitIDs[count] = string(fields[1])
389-
refFullNames[count] = git.RefName(fields[2])
390-
391393
commitID, _ := git.NewIDFromString(newCommitIDs[count])
392394
if refFullNames[count] == git.BranchPrefix+"master" && !commitID.IsZero() && count == total {
393395
masterPushed = true

cmd/hook_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,17 @@ func TestPktLine(t *testing.T) {
3939
assert.NoError(t, err)
4040
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
4141
}
42+
43+
func TestParseGitHookCommitRefLine(t *testing.T) {
44+
oldCommitID, newCommitID, refName, ok := parseGitHookCommitRefLine("a b c")
45+
assert.True(t, ok)
46+
assert.Equal(t, "a", oldCommitID)
47+
assert.Equal(t, "b", newCommitID)
48+
assert.Equal(t, "c", string(refName))
49+
50+
_, _, _, ok = parseGitHookCommitRefLine("a\tb\tc")
51+
assert.False(t, ok)
52+
53+
_, _, _, ok = parseGitHookCommitRefLine("a b")
54+
assert.False(t, ok)
55+
}

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/ProtonMail/go-crypto v1.3.0
2929
github.com/PuerkitoBio/goquery v1.10.3
3030
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0
31-
github.com/alecthomas/chroma/v2 v2.21.1
31+
github.com/alecthomas/chroma/v2 v2.22.0
3232
github.com/aws/aws-sdk-go-v2/credentials v1.18.10
3333
github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.2
3434
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
@@ -113,7 +113,7 @@ require (
113113
github.com/wneessen/go-mail v0.7.2
114114
github.com/xeipuuv/gojsonschema v1.2.0
115115
github.com/yohcop/openid-go v1.0.1
116-
github.com/yuin/goldmark v1.7.13
116+
github.com/yuin/goldmark v1.7.16
117117
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
118118
github.com/yuin/goldmark-meta v1.1.0
119119
gitlab.com/gitlab-org/api/client-go v0.142.4

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0/go.mod h1:1HmmMEVsr+0R
9898
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
9999
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
100100
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
101-
github.com/alecthomas/chroma/v2 v2.21.1 h1:FaSDrp6N+3pphkNKU6HPCiYLgm8dbe5UXIXcoBhZSWA=
102-
github.com/alecthomas/chroma/v2 v2.21.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
101+
github.com/alecthomas/chroma/v2 v2.22.0 h1:PqEhf+ezz5F5owoDeOUKFzW+W3ZJDShNCaHg4sZuItI=
102+
github.com/alecthomas/chroma/v2 v2.22.0/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
103103
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
104104
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
105105
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
@@ -792,8 +792,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
792792
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
793793
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
794794
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
795-
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
796-
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
795+
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
796+
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
797797
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
798798
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
799799
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=

models/git/lfs_lock.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (
101101
return rel, nil
102102
}
103103

104-
// GetLFSLockByID returns release by given id.
105-
func GetLFSLockByID(ctx context.Context, id int64) (*LFSLock, error) {
104+
// GetLFSLockByIDAndRepo returns lfs lock by given id and repository id.
105+
func GetLFSLockByIDAndRepo(ctx context.Context, id, repoID int64) (*LFSLock, error) {
106106
lock := new(LFSLock)
107-
has, err := db.GetEngine(ctx).ID(id).Get(lock)
107+
has, err := db.GetEngine(ctx).ID(id).And("repo_id = ?", repoID).Get(lock)
108108
if err != nil {
109109
return nil, err
110110
} else if !has {
@@ -153,7 +153,7 @@ func CountLFSLockByRepoID(ctx context.Context, repoID int64) (int64, error) {
153153
// DeleteLFSLockByID deletes a lock by given ID.
154154
func DeleteLFSLockByID(ctx context.Context, id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
155155
return db.WithTx2(ctx, func(ctx context.Context) (*LFSLock, error) {
156-
lock, err := GetLFSLockByID(ctx, id)
156+
lock, err := GetLFSLockByIDAndRepo(ctx, id, repo.ID)
157157
if err != nil {
158158
return nil, err
159159
}

models/git/lfs_lock_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2026 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"fmt"
8+
"testing"
9+
"time"
10+
11+
repo_model "code.gitea.io/gitea/models/repo"
12+
"code.gitea.io/gitea/models/unittest"
13+
user_model "code.gitea.io/gitea/models/user"
14+
15+
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
17+
)
18+
19+
func createTestLock(t *testing.T, repo *repo_model.Repository, owner *user_model.User) *LFSLock {
20+
t.Helper()
21+
22+
path := fmt.Sprintf("%s-%d-%d", t.Name(), repo.ID, time.Now().UnixNano())
23+
lock, err := CreateLFSLock(t.Context(), repo, &LFSLock{
24+
OwnerID: owner.ID,
25+
Path: path,
26+
})
27+
require.NoError(t, err)
28+
return lock
29+
}
30+
31+
func TestGetLFSLockByIDAndRepo(t *testing.T) {
32+
require.NoError(t, unittest.PrepareTestDatabase())
33+
34+
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
35+
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
36+
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
37+
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
38+
39+
lockRepo1 := createTestLock(t, repo1, user2)
40+
lockRepo3 := createTestLock(t, repo3, user4)
41+
42+
fetched, err := GetLFSLockByIDAndRepo(t.Context(), lockRepo1.ID, repo1.ID)
43+
require.NoError(t, err)
44+
assert.Equal(t, lockRepo1.ID, fetched.ID)
45+
assert.Equal(t, repo1.ID, fetched.RepoID)
46+
47+
_, err = GetLFSLockByIDAndRepo(t.Context(), lockRepo1.ID, repo3.ID)
48+
assert.Error(t, err)
49+
assert.True(t, IsErrLFSLockNotExist(err))
50+
51+
_, err = GetLFSLockByIDAndRepo(t.Context(), lockRepo3.ID, repo1.ID)
52+
assert.Error(t, err)
53+
assert.True(t, IsErrLFSLockNotExist(err))
54+
}
55+
56+
func TestDeleteLFSLockByIDRequiresRepoMatch(t *testing.T) {
57+
require.NoError(t, unittest.PrepareTestDatabase())
58+
59+
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
60+
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
61+
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
62+
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
63+
64+
lockRepo1 := createTestLock(t, repo1, user2)
65+
lockRepo3 := createTestLock(t, repo3, user4)
66+
67+
_, err := DeleteLFSLockByID(t.Context(), lockRepo3.ID, repo1, user2, true)
68+
assert.Error(t, err)
69+
assert.True(t, IsErrLFSLockNotExist(err))
70+
71+
existing, err := GetLFSLockByIDAndRepo(t.Context(), lockRepo3.ID, repo3.ID)
72+
require.NoError(t, err)
73+
assert.Equal(t, lockRepo3.ID, existing.ID)
74+
75+
deleted, err := DeleteLFSLockByID(t.Context(), lockRepo3.ID, repo3, user4, true)
76+
require.NoError(t, err)
77+
assert.Equal(t, lockRepo3.ID, deleted.ID)
78+
79+
deleted, err = DeleteLFSLockByID(t.Context(), lockRepo1.ID, repo1, user2, false)
80+
require.NoError(t, err)
81+
assert.Equal(t, lockRepo1.ID, deleted.ID)
82+
}

modules/git/batch_reader.go

Lines changed: 0 additions & 57 deletions
This file was deleted.

modules/git/blob_nogogit.go

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
package git
77

88
import (
9-
"bufio"
10-
"bytes"
119
"io"
1210

1311
"code.gitea.io/gitea/modules/log"
@@ -25,39 +23,28 @@ type Blob struct {
2523

2624
// DataAsync gets a ReadCloser for the contents of a blob without reading it all.
2725
// Calling the Close function on the result will discard all unread output.
28-
func (b *Blob) DataAsync() (io.ReadCloser, error) {
26+
func (b *Blob) DataAsync() (_ io.ReadCloser, retErr error) {
2927
batch, cancel, err := b.repo.CatFileBatch(b.repo.Ctx)
3028
if err != nil {
3129
return nil, err
3230
}
31+
defer func() {
32+
// if there was an error, cancel the batch right away,
33+
// otherwise let the caller close it
34+
if retErr != nil {
35+
cancel()
36+
}
37+
}()
3338

34-
rd := batch.Reader()
35-
_, err = batch.Writer().Write([]byte(b.ID.String() + "\n"))
36-
if err != nil {
37-
cancel()
38-
return nil, err
39-
}
40-
_, _, size, err := ReadBatchLine(rd)
39+
info, contentReader, err := batch.QueryContent(b.ID.String())
4140
if err != nil {
42-
cancel()
4341
return nil, err
4442
}
4543
b.gotSize = true
46-
b.size = size
47-
48-
if size < 4096 {
49-
bs, err := io.ReadAll(io.LimitReader(rd, size))
50-
defer cancel()
51-
if err != nil {
52-
return nil, err
53-
}
54-
_, err = rd.Discard(1)
55-
return io.NopCloser(bytes.NewReader(bs)), err
56-
}
57-
44+
b.size = info.Size
5845
return &blobReader{
59-
rd: rd,
60-
n: size,
46+
rd: contentReader,
47+
n: info.Size,
6148
cancel: cancel,
6249
}, nil
6350
}
@@ -68,30 +55,24 @@ func (b *Blob) Size() int64 {
6855
return b.size
6956
}
7057

71-
batch, cancel, err := b.repo.CatFileBatchCheck(b.repo.Ctx)
58+
batch, cancel, err := b.repo.CatFileBatch(b.repo.Ctx)
7259
if err != nil {
7360
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
7461
return 0
7562
}
7663
defer cancel()
77-
_, err = batch.Writer().Write([]byte(b.ID.String() + "\n"))
64+
info, err := batch.QueryInfo(b.ID.String())
7865
if err != nil {
7966
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
8067
return 0
8168
}
82-
_, _, b.size, err = ReadBatchLine(batch.Reader())
83-
if err != nil {
84-
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
85-
return 0
86-
}
87-
8869
b.gotSize = true
89-
70+
b.size = info.Size
9071
return b.size
9172
}
9273

9374
type blobReader struct {
94-
rd *bufio.Reader
75+
rd BufferedReader
9576
n int64
9677
cancel func()
9778
}

0 commit comments

Comments
 (0)