Skip to content

Commit e1e2e87

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: [skip ci] Updated translations via Crowdin Refactor the usage of batch catfile (go-gitea#31754) Fix agit automerge (go-gitea#31207)
2 parents 17fe70a + d1426de commit e1e2e87

22 files changed

+358
-96
lines changed

models/fixtures/repository.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
fork_id: 0
2727
is_template: false
2828
template_id: 0
29-
size: 7320
29+
size: 7597
3030
is_fsck_enabled: true
3131
close_issues_via_commit_in_any_branch: false
3232

modules/git/batch.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"bufio"
8+
"context"
9+
)
10+
11+
type Batch struct {
12+
cancel context.CancelFunc
13+
Reader *bufio.Reader
14+
Writer WriteCloserError
15+
}
16+
17+
func (repo *Repository) NewBatch(ctx context.Context) (*Batch, error) {
18+
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
19+
if err := ensureValidGitRepository(ctx, repo.Path); err != nil {
20+
return nil, err
21+
}
22+
23+
var batch Batch
24+
batch.Writer, batch.Reader, batch.cancel = catFileBatch(ctx, repo.Path)
25+
return &batch, nil
26+
}
27+
28+
func (repo *Repository) NewBatchCheck(ctx context.Context) (*Batch, error) {
29+
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
30+
if err := ensureValidGitRepository(ctx, repo.Path); err != nil {
31+
return nil, err
32+
}
33+
34+
var check Batch
35+
check.Writer, check.Reader, check.cancel = catFileBatchCheck(ctx, repo.Path)
36+
return &check, nil
37+
}
38+
39+
func (b *Batch) Close() {
40+
if b.cancel != nil {
41+
b.cancel()
42+
b.Reader = nil
43+
b.Writer = nil
44+
b.cancel = nil
45+
}
46+
}

modules/git/batch_reader.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ type WriteCloserError interface {
2626
CloseWithError(err error) error
2727
}
2828

29-
// EnsureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
29+
// ensureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
3030
// Run before opening git cat-file.
3131
// This is needed otherwise the git cat-file will hang for invalid repositories.
32-
func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
32+
func ensureValidGitRepository(ctx context.Context, repoPath string) error {
3333
stderr := strings.Builder{}
3434
err := NewCommand(ctx, "rev-parse").
3535
SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
@@ -43,8 +43,8 @@ func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
4343
return nil
4444
}
4545

46-
// CatFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
47-
func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
46+
// catFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
47+
func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
4848
batchStdinReader, batchStdinWriter := io.Pipe()
4949
batchStdoutReader, batchStdoutWriter := io.Pipe()
5050
ctx, ctxCancel := context.WithCancel(ctx)
@@ -93,8 +93,8 @@ func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
9393
return batchStdinWriter, batchReader, cancel
9494
}
9595

96-
// CatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
97-
func CatFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
96+
// catFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
97+
func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
9898
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
9999
// so let's create a batch stdin and stdout
100100
batchStdinReader, batchStdinWriter := io.Pipe()

modules/git/blob_nogogit.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ type Blob struct {
2626
// DataAsync gets a ReadCloser for the contents of a blob without reading it all.
2727
// Calling the Close function on the result will discard all unread output.
2828
func (b *Blob) DataAsync() (io.ReadCloser, error) {
29-
wr, rd, cancel := b.repo.CatFileBatch(b.repo.Ctx)
29+
wr, rd, cancel, err := b.repo.CatFileBatch(b.repo.Ctx)
30+
if err != nil {
31+
return nil, err
32+
}
3033

31-
_, err := wr.Write([]byte(b.ID.String() + "\n"))
34+
_, err = wr.Write([]byte(b.ID.String() + "\n"))
3235
if err != nil {
3336
cancel()
3437
return nil, err
@@ -64,9 +67,13 @@ func (b *Blob) Size() int64 {
6467
return b.size
6568
}
6669

67-
wr, rd, cancel := b.repo.CatFileBatchCheck(b.repo.Ctx)
70+
wr, rd, cancel, err := b.repo.CatFileBatchCheck(b.repo.Ctx)
71+
if err != nil {
72+
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
73+
return 0
74+
}
6875
defer cancel()
69-
_, err := wr.Write([]byte(b.ID.String() + "\n"))
76+
_, err = wr.Write([]byte(b.ID.String() + "\n"))
7077
if err != nil {
7178
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
7279
return 0

modules/git/commit_info_nogogit.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
124124
return nil, err
125125
}
126126

127-
batchStdinWriter, batchReader, cancel := commit.repo.CatFileBatch(ctx)
127+
batchStdinWriter, batchReader, cancel, err := commit.repo.CatFileBatch(ctx)
128+
if err != nil {
129+
return nil, err
130+
}
128131
defer cancel()
129132

130133
commitsMap := map[string]*Commit{}

modules/git/pipeline/lfs_nogogit.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
4646

4747
// Next feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
4848
// so let's create a batch stdin and stdout
49-
batchStdinWriter, batchReader, cancel := repo.CatFileBatch(repo.Ctx)
49+
batchStdinWriter, batchReader, cancel, err := repo.CatFileBatch(repo.Ctx)
50+
if err != nil {
51+
return nil, err
52+
}
5053
defer cancel()
5154

5255
// We'll use a scanner for the revList because it's simpler than a bufio.Reader

modules/git/repo_base_nogogit.go

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,11 @@ type Repository struct {
2525

2626
gpgSettings *GPGSettings
2727

28-
batchInUse bool
29-
batchCancel context.CancelFunc
30-
batchReader *bufio.Reader
31-
batchWriter WriteCloserError
28+
batchInUse bool
29+
batch *Batch
3230

33-
checkInUse bool
34-
checkCancel context.CancelFunc
35-
checkReader *bufio.Reader
36-
checkWriter WriteCloserError
31+
checkInUse bool
32+
check *Batch
3733

3834
Ctx context.Context
3935
LastCommitCache *LastCommitCache
@@ -55,63 +51,75 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
5551
return nil, util.NewNotExistErrorf("no such file or directory")
5652
}
5753

58-
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
59-
if err := EnsureValidGitRepository(ctx, repoPath); err != nil {
60-
return nil, err
61-
}
62-
63-
repo := &Repository{
54+
return &Repository{
6455
Path: repoPath,
6556
tagCache: newObjectCache(),
6657
Ctx: ctx,
67-
}
68-
69-
repo.batchWriter, repo.batchReader, repo.batchCancel = CatFileBatch(ctx, repoPath)
70-
repo.checkWriter, repo.checkReader, repo.checkCancel = CatFileBatchCheck(ctx, repoPath)
71-
72-
return repo, nil
58+
}, nil
7359
}
7460

7561
// CatFileBatch obtains a CatFileBatch for this repository
76-
func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
77-
if repo.batchCancel == nil || repo.batchInUse {
78-
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
79-
return CatFileBatch(ctx, repo.Path)
62+
func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func(), error) {
63+
if repo.batch == nil {
64+
var err error
65+
repo.batch, err = repo.NewBatch(ctx)
66+
if err != nil {
67+
return nil, nil, nil, err
68+
}
8069
}
81-
repo.batchInUse = true
82-
return repo.batchWriter, repo.batchReader, func() {
83-
repo.batchInUse = false
70+
71+
if !repo.batchInUse {
72+
repo.batchInUse = true
73+
return repo.batch.Writer, repo.batch.Reader, func() {
74+
repo.batchInUse = false
75+
}, nil
8476
}
77+
78+
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
79+
tempBatch, err := repo.NewBatch(ctx)
80+
if err != nil {
81+
return nil, nil, nil, err
82+
}
83+
return tempBatch.Writer, tempBatch.Reader, tempBatch.Close, nil
8584
}
8685

8786
// CatFileBatchCheck obtains a CatFileBatchCheck for this repository
88-
func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
89-
if repo.checkCancel == nil || repo.checkInUse {
90-
log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
91-
return CatFileBatchCheck(ctx, repo.Path)
87+
func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func(), error) {
88+
if repo.check == nil {
89+
var err error
90+
repo.check, err = repo.NewBatchCheck(ctx)
91+
if err != nil {
92+
return nil, nil, nil, err
93+
}
9294
}
93-
repo.checkInUse = true
94-
return repo.checkWriter, repo.checkReader, func() {
95-
repo.checkInUse = false
95+
96+
if !repo.checkInUse {
97+
repo.checkInUse = true
98+
return repo.check.Writer, repo.check.Reader, func() {
99+
repo.checkInUse = false
100+
}, nil
101+
}
102+
103+
log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
104+
tempBatchCheck, err := repo.NewBatchCheck(ctx)
105+
if err != nil {
106+
return nil, nil, nil, err
96107
}
108+
return tempBatchCheck.Writer, tempBatchCheck.Reader, tempBatchCheck.Close, nil
97109
}
98110

99111
func (repo *Repository) Close() error {
100112
if repo == nil {
101113
return nil
102114
}
103-
if repo.batchCancel != nil {
104-
repo.batchCancel()
105-
repo.batchReader = nil
106-
repo.batchWriter = nil
107-
repo.batchCancel = nil
115+
if repo.batch != nil {
116+
repo.batch.Close()
117+
repo.batch = nil
108118
repo.batchInUse = false
109119
}
110-
if repo.checkCancel != nil {
111-
repo.checkCancel()
112-
repo.checkCancel = nil
113-
repo.checkReader = nil
114-
repo.checkWriter = nil
120+
if repo.check != nil {
121+
repo.check.Close()
122+
repo.check = nil
115123
repo.checkInUse = false
116124
}
117125
repo.LastCommitCache = nil

modules/git/repo_branch_nogogit.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ func (repo *Repository) IsObjectExist(name string) bool {
2222
return false
2323
}
2424

25-
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
25+
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
26+
if err != nil {
27+
log.Debug("Error writing to CatFileBatchCheck %v", err)
28+
return false
29+
}
2630
defer cancel()
27-
_, err := wr.Write([]byte(name + "\n"))
31+
_, err = wr.Write([]byte(name + "\n"))
2832
if err != nil {
2933
log.Debug("Error writing to CatFileBatchCheck %v", err)
3034
return false
@@ -39,9 +43,13 @@ func (repo *Repository) IsReferenceExist(name string) bool {
3943
return false
4044
}
4145

42-
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
46+
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
47+
if err != nil {
48+
log.Debug("Error writing to CatFileBatchCheck %v", err)
49+
return false
50+
}
4351
defer cancel()
44-
_, err := wr.Write([]byte(name + "\n"))
52+
_, err = wr.Write([]byte(name + "\n"))
4553
if err != nil {
4654
log.Debug("Error writing to CatFileBatchCheck %v", err)
4755
return false

modules/git/repo_commit_nogogit.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ func (repo *Repository) ResolveReference(name string) (string, error) {
3333

3434
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
3535
func (repo *Repository) GetRefCommitID(name string) (string, error) {
36-
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
36+
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
37+
if err != nil {
38+
return "", err
39+
}
3740
defer cancel()
38-
_, err := wr.Write([]byte(name + "\n"))
41+
_, err = wr.Write([]byte(name + "\n"))
3942
if err != nil {
4043
return "", err
4144
}
@@ -61,12 +64,19 @@ func (repo *Repository) RemoveReference(name string) error {
6164

6265
// IsCommitExist returns true if given commit exists in current repository.
6366
func (repo *Repository) IsCommitExist(name string) bool {
67+
if err := ensureValidGitRepository(repo.Ctx, repo.Path); err != nil {
68+
log.Error("IsCommitExist: %v", err)
69+
return false
70+
}
6471
_, _, err := NewCommand(repo.Ctx, "cat-file", "-e").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
6572
return err == nil
6673
}
6774

6875
func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
69-
wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
76+
wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
77+
if err != nil {
78+
return nil, err
79+
}
7080
defer cancel()
7181

7282
_, _ = wr.Write([]byte(id.String() + "\n"))
@@ -143,7 +153,10 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
143153
}
144154
}
145155

146-
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
156+
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
157+
if err != nil {
158+
return nil, err
159+
}
147160
defer cancel()
148161
_, err = wr.Write([]byte(commitID + "\n"))
149162
if err != nil {

modules/git/repo_language_stats_nogogit.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import (
2020
func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, error) {
2121
// We will feed the commit IDs in order into cat-file --batch, followed by blobs as necessary.
2222
// so let's create a batch stdin and stdout
23-
batchStdinWriter, batchReader, cancel := repo.CatFileBatch(repo.Ctx)
23+
batchStdinWriter, batchReader, cancel, err := repo.CatFileBatch(repo.Ctx)
24+
if err != nil {
25+
return nil, err
26+
}
2427
defer cancel()
2528

2629
writeID := func(id string) error {

modules/git/repo_tag_nogogit.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ func (repo *Repository) GetTags(skip, limit int) (tags []string, err error) {
3131

3232
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
3333
func (repo *Repository) GetTagType(id ObjectID) (string, error) {
34-
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
34+
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
35+
if err != nil {
36+
return "", err
37+
}
3538
defer cancel()
36-
_, err := wr.Write([]byte(id.String() + "\n"))
39+
_, err = wr.Write([]byte(id.String() + "\n"))
3740
if err != nil {
3841
return "", err
3942
}
@@ -89,7 +92,10 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
8992
}
9093

9194
// The tag is an annotated tag with a message.
92-
wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
95+
wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
96+
if err != nil {
97+
return nil, err
98+
}
9399
defer cancel()
94100

95101
if _, err := wr.Write([]byte(tagID.String() + "\n")); err != nil {

0 commit comments

Comments
 (0)