Skip to content

Commit 77c9340

Browse files
committed
don't create a new sub process
1 parent d17784e commit 77c9340

17 files changed

+122
-262
lines changed

modules/git/batch.go

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

modules/git/batch_cat_file.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,27 @@ type BatchCatFile struct {
2828
finished process.FinishedFunc
2929
}
3030

31-
func NewBatchCatFile(ctx context.Context, repoPath string) (*BatchCatFile, error) {
31+
// NewBatchCatFile opens git cat-file --batch or --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
32+
// isCheck is true for --batch-check, false for --batch isCheck will only get metadata, --batch will get metadata and content
33+
func NewBatchCatFile(ctx context.Context, repoPath string, isCheck bool) (*BatchCatFile, error) {
34+
// 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!
35+
if err := ensureValidGitRepository(ctx, repoPath); err != nil {
36+
return nil, err
37+
}
38+
3239
callerInfo := util.CallerFuncName(1 /* util */ + 1 /* this */ + 1 /* parent */)
3340
if pos := strings.LastIndex(callerInfo, "/"); pos >= 0 {
3441
callerInfo = callerInfo[pos+1:]
3542
}
3643

44+
batchArg := util.Iif(isCheck, "--batch-check", "--batch")
45+
3746
a := make([]string, 0, 4)
3847
a = append(a, debugQuote(GitExecutable))
3948
if len(globalCommandArgs) > 0 {
4049
a = append(a, "...global...")
4150
}
42-
a = append(a, "cat-file", "--batch")
51+
a = append(a, "cat-file", batchArg)
4352
cmdLogString := strings.Join(a, " ")
4453

4554
// these logs are for debugging purposes only, so no guarantee of correctness or stability
@@ -52,7 +61,7 @@ func NewBatchCatFile(ctx context.Context, repoPath string) (*BatchCatFile, error
5261
for _, arg := range globalCommandArgs {
5362
args = append(args, string(arg))
5463
}
55-
args = append(args, "cat-file", "--batch")
64+
args = append(args, "cat-file", batchArg)
5665
cmd := exec.CommandContext(ctx, GitExecutable, args...)
5766
cmd.Env = append(os.Environ(), CommonGitCmdEnvs()...)
5867
cmd.Dir = repoPath

modules/git/batch_cat_file_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
func Test_GitBatchOperatorsNormal(t *testing.T) {
1717
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
18-
batch, err := NewBatchCatFile(context.Background(), bareRepo1Path)
18+
batch, err := NewBatchCatFile(t.Context(), bareRepo1Path, false)
1919
assert.NoError(t, err)
2020
assert.NotNil(t, batch)
2121
defer batch.Close()
@@ -99,7 +99,7 @@ func Test_GitBatchOperatorsNormal(t *testing.T) {
9999

100100
func Test_GitBatchOperatorsCancel(t *testing.T) {
101101
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
102-
batch, err := NewBatchCatFile(context.Background(), bareRepo1Path)
102+
batch, err := NewBatchCatFile(t.Context(), bareRepo1Path, false)
103103
assert.NoError(t, err)
104104
assert.NotNil(t, batch)
105105
defer batch.Close()
@@ -126,9 +126,10 @@ func Test_GitBatchOperatorsCancel(t *testing.T) {
126126
func Test_GitBatchOperatorsTimeout(t *testing.T) {
127127
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
128128

129-
ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
129+
ctx, cancel := context.WithTimeout(t.Context(), 1*time.Second)
130+
defer cancel()
130131

131-
batch, err := NewBatchCatFile(ctx, bareRepo1Path)
132+
batch, err := NewBatchCatFile(ctx, bareRepo1Path, false)
132133
assert.NoError(t, err)
133134
assert.NotNil(t, batch)
134135
defer batch.Close()

modules/git/batch_reader.go

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ import (
1313
"strings"
1414

1515
"code.gitea.io/gitea/modules/log"
16-
17-
"github.com/djherbis/buffer"
18-
"github.com/djherbis/nio/v3"
1916
)
2017

2118
// WriteCloserError wraps an io.WriteCloser with an additional CloseWithError function
@@ -40,100 +37,6 @@ func ensureValidGitRepository(ctx context.Context, repoPath string) error {
4037
return nil
4138
}
4239

43-
// catFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
44-
func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
45-
batchStdinReader, batchStdinWriter := io.Pipe()
46-
batchStdoutReader, batchStdoutWriter := io.Pipe()
47-
ctx, ctxCancel := context.WithCancel(ctx)
48-
closed := make(chan struct{})
49-
cancel := func() {
50-
ctxCancel()
51-
_ = batchStdoutReader.Close()
52-
_ = batchStdinWriter.Close()
53-
<-closed
54-
}
55-
56-
// Ensure cancel is called as soon as the provided context is cancelled
57-
go func() {
58-
<-ctx.Done()
59-
cancel()
60-
}()
61-
62-
go func() {
63-
stderr := strings.Builder{}
64-
err := NewCommand("cat-file", "--batch-check").
65-
Run(ctx, &RunOpts{
66-
Dir: repoPath,
67-
Stdin: batchStdinReader,
68-
Stdout: batchStdoutWriter,
69-
Stderr: &stderr,
70-
71-
UseContextTimeout: true,
72-
})
73-
if err != nil {
74-
_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
75-
_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
76-
} else {
77-
_ = batchStdoutWriter.Close()
78-
_ = batchStdinReader.Close()
79-
}
80-
close(closed)
81-
}()
82-
83-
// For simplicities sake we'll use a buffered reader to read from the cat-file --batch-check
84-
batchReader := bufio.NewReader(batchStdoutReader)
85-
86-
return batchStdinWriter, batchReader, cancel
87-
}
88-
89-
// catFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
90-
func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
91-
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
92-
// so let's create a batch stdin and stdout
93-
batchStdinReader, batchStdinWriter := io.Pipe()
94-
batchStdoutReader, batchStdoutWriter := nio.Pipe(buffer.New(32 * 1024))
95-
ctx, ctxCancel := context.WithCancel(ctx)
96-
closed := make(chan struct{})
97-
cancel := func() {
98-
ctxCancel()
99-
_ = batchStdinWriter.Close()
100-
_ = batchStdoutReader.Close()
101-
<-closed
102-
}
103-
104-
// Ensure cancel is called as soon as the provided context is cancelled
105-
go func() {
106-
<-ctx.Done()
107-
cancel()
108-
}()
109-
110-
go func() {
111-
stderr := strings.Builder{}
112-
err := NewCommand("cat-file", "--batch").
113-
Run(ctx, &RunOpts{
114-
Dir: repoPath,
115-
Stdin: batchStdinReader,
116-
Stdout: batchStdoutWriter,
117-
Stderr: &stderr,
118-
119-
UseContextTimeout: true,
120-
})
121-
if err != nil {
122-
_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
123-
_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
124-
} else {
125-
_ = batchStdoutWriter.Close()
126-
_ = batchStdinReader.Close()
127-
}
128-
close(closed)
129-
}()
130-
131-
// For simplicities sake we'll us a buffered reader to read from the cat-file --batch
132-
batchReader := bufio.NewReaderSize(batchStdoutReader, 32*1024)
133-
134-
return batchStdinWriter, batchReader, cancel
135-
}
136-
13740
// ReadBatchLine reads the header line from cat-file --batch
13841
// We expect: <oid> SP <type> SP <size> LF
13942
// then leaving the rest of the stream "<contents> LF" to be read

modules/git/blob_nogogit.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ 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, err := b.repo.CatFileBatch(b.repo.Ctx)
29+
batch, cancel, err := b.repo.CatFileBatch(b.repo.Ctx)
3030
if err != nil {
3131
return nil, err
3232
}
3333

34-
_, err = wr.Write([]byte(b.ID.String() + "\n"))
35-
if err != nil {
34+
rd := batch.Reader()
35+
36+
if err = batch.Input(b.ID.String()); err != nil {
3637
cancel()
3738
return nil, err
3839
}
@@ -67,18 +68,17 @@ func (b *Blob) Size() int64 {
6768
return b.size
6869
}
6970

70-
wr, rd, cancel, err := b.repo.CatFileBatchCheck(b.repo.Ctx)
71+
batch, cancel, err := b.repo.CatFileBatchCheck(b.repo.Ctx)
7172
if err != nil {
7273
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
7374
return 0
7475
}
7576
defer cancel()
76-
_, err = wr.Write([]byte(b.ID.String() + "\n"))
77-
if err != nil {
77+
if err = batch.Input(b.ID.String()); err != nil {
7878
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
7979
return 0
8080
}
81-
_, _, b.size, err = ReadBatchLine(rd)
81+
_, _, b.size, err = ReadBatchLine(batch.Reader())
8282
if err != nil {
8383
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
8484
return 0

modules/git/commit_info_nogogit.go

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

127-
batch, err := NewBatchCatFile(ctx, commit.repo.Path)
127+
batch, cancel, err := commit.repo.CatFileBatch(ctx)
128128
if err != nil {
129129
return nil, err
130130
}
131-
defer batch.Close()
131+
defer cancel()
132132

133133
rd := batch.Reader()
134134

modules/git/pipeline/lfs_nogogit.go

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@ 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, err := repo.CatFileBatch(repo.Ctx)
49+
batch, cancel, err := repo.CatFileBatch(repo.Ctx)
5050
if err != nil {
5151
return nil, err
5252
}
5353
defer cancel()
5454

55+
batchReader := batch.Reader()
5556
// We'll use a scanner for the revList because it's simpler than a bufio.Reader
5657
scan := bufio.NewScanner(revListReader)
5758
trees := [][]byte{}
@@ -63,15 +64,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
6364

6465
for scan.Scan() {
6566
// Get the next commit ID
66-
commitID := scan.Bytes()
67+
commitID := scan.Text()
6768

6869
// push the commit to the cat-file --batch process
69-
_, err := batchStdinWriter.Write(commitID)
70-
if err != nil {
71-
return nil, err
72-
}
73-
_, err = batchStdinWriter.Write([]byte{'\n'})
74-
if err != nil {
70+
if err := batch.Input(commitID); err != nil {
7571
return nil, err
7672
}
7773

@@ -92,22 +88,21 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
9288
if err != nil {
9389
return nil, err
9490
}
95-
_, err = batchStdinWriter.Write([]byte(id + "\n"))
96-
if err != nil {
91+
if err = batch.Input(id); err != nil {
9792
return nil, err
9893
}
9994
continue
10095
case "commit":
10196
// Read in the commit to get its tree and in case this is one of the last used commits
102-
curCommit, err = git.CommitFromReader(repo, git.MustIDFromString(string(commitID)), io.LimitReader(batchReader, size))
97+
curCommit, err = git.CommitFromReader(repo, git.MustIDFromString(commitID), io.LimitReader(batchReader, size))
10398
if err != nil {
10499
return nil, err
105100
}
106101
if _, err := batchReader.Discard(1); err != nil {
107102
return nil, err
108103
}
109104

110-
if _, err := batchStdinWriter.Write([]byte(curCommit.Tree.ID.String() + "\n")); err != nil {
105+
if err := batch.Input(curCommit.Tree.ID.String()); err != nil {
111106
return nil, err
112107
}
113108
curPath = ""
@@ -139,14 +134,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
139134
return nil, err
140135
}
141136
if len(trees) > 0 {
142-
_, err := batchStdinWriter.Write(trees[len(trees)-1])
143-
if err != nil {
144-
return nil, err
145-
}
146-
_, err = batchStdinWriter.Write([]byte("\n"))
147-
if err != nil {
137+
if err := batch.Input(string(trees[len(trees)-1])); err != nil {
148138
return nil, err
149139
}
140+
150141
curPath = paths[len(paths)-1]
151142
trees = trees[:len(trees)-1]
152143
paths = paths[:len(paths)-1]

0 commit comments

Comments
 (0)