@@ -16,16 +16,12 @@ import (
1616 "code.gitea.io/gitea/modules/log"
1717)
1818
19- // writeCloserError wraps an io.WriteCloser with an additional CloseWithError function (for nio.Pipe)
20- type writeCloserError interface {
21- io.WriteCloser
22- CloseWithError (err error ) error
23- }
24-
2519type catFileBatchCommunicator struct {
2620 cancel context.CancelFunc
2721 reader * bufio.Reader
28- writer writeCloserError
22+ writer io.Writer
23+
24+ debugGitCmd * gitcmd.Command
2925}
3026
3127func (b * catFileBatchCommunicator ) Close () {
@@ -37,63 +33,41 @@ func (b *catFileBatchCommunicator) Close() {
3733 }
3834}
3935
40- // ensureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
41- // Run before opening git cat-file.
42- // This is needed otherwise the git cat-file will hang for invalid repositories.
43- // FIXME: the comment is from https://github.com/go-gitea/gitea/pull/17991 but it doesn't seem to be true.
44- // The real problem is that Golang's Cmd.Wait hangs because it waits for the pipes to be closed, but we can't close the pipes before Wait returns
45- // Need to refactor to use StdinPipe and StdoutPipe
46- func ensureValidGitRepository (ctx context.Context , repoPath string ) error {
47- stderr := strings.Builder {}
48- err := gitcmd .NewCommand ("rev-parse" ).
49- WithDir (repoPath ).
50- WithStderr (& stderr ).
51- Run (ctx )
52- if err != nil {
53- return gitcmd .ConcatenateError (err , (& stderr ).String ())
54- }
55- return nil
56- }
57-
5836// newCatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
5937func newCatFileBatch (ctx context.Context , repoPath string , cmdCatFile * gitcmd.Command ) * catFileBatchCommunicator {
6038 // We often want to feed the commits in order into cat-file --batch, followed by their trees and subtrees as necessary.
39+ ctx , ctxCancel := context .WithCancelCause (ctx )
6140
62- // so let's create a batch stdin and stdout
63- batchStdinReader , batchStdinWriter := io .Pipe ()
64- batchStdoutReader , batchStdoutWriter := io .Pipe ()
65- ctx , ctxCancel := context .WithCancel (ctx )
66- closed := make (chan struct {})
67- cancel := func () {
68- ctxCancel ()
69- _ = batchStdinWriter .Close ()
70- _ = batchStdoutReader .Close ()
71- <- closed
72- }
41+ var batchStdinWriter io.WriteCloser
42+ var batchStdoutReader io.ReadCloser
43+ stderr := strings.Builder {}
44+ cmdCatFile = cmdCatFile .
45+ WithDir (repoPath ).
46+ WithStdinWriter (& batchStdinWriter ).
47+ WithStdoutReader (& batchStdoutReader ).
48+ WithStderr (& stderr ).
49+ WithUseContextTimeout (true )
7350
74- // Ensure cancel is called as soon as the provided context is cancelled
75- go func () {
76- <- ctx .Done ()
77- cancel ()
78- }()
51+ err := cmdCatFile .Start (ctx )
52+ if err != nil {
53+ log .Error ("Unable to start git command %v: %v" , cmdCatFile .LogString (), err )
54+ // ideally here it should return the error, but it would require refactoring all callers
55+ // so just return a dummy communicator that does nothing, almost the same behavior as before, not bad
56+ return & catFileBatchCommunicator {
57+ writer : io .Discard ,
58+ reader : bufio .NewReader (bytes .NewReader (nil )),
59+ cancel : func () {
60+ ctxCancel (err )
61+ },
62+ }
63+ }
7964
8065 go func () {
81- stderr := strings.Builder {}
82- err := cmdCatFile .
83- WithDir (repoPath ).
84- WithStdin (batchStdinReader ).
85- WithStdout (batchStdoutWriter ).
86- WithStderr (& stderr ).
87- WithUseContextTimeout (true ).
88- Run (ctx )
66+ err := cmdCatFile .Wait ()
8967 if err != nil {
90- _ = batchStdoutWriter .CloseWithError (gitcmd .ConcatenateError (err , (& stderr ).String ()))
91- _ = batchStdinReader .CloseWithError (gitcmd .ConcatenateError (err , (& stderr ).String ()))
92- } else {
93- _ = batchStdoutWriter .Close ()
94- _ = batchStdinReader .Close ()
68+ log .Error ("cat-file --batch command failed in repo %s: %v - stderr: %s" , repoPath , err , stderr .String ())
9569 }
96- close ( closed )
70+ ctxCancel ( err )
9771 }()
9872
9973 // use a buffered reader to read from the cat-file --batch (StringReader.ReadString)
@@ -102,7 +76,10 @@ func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Co
10276 return & catFileBatchCommunicator {
10377 writer : batchStdinWriter ,
10478 reader : batchReader ,
105- cancel : cancel ,
79+ cancel : func () {
80+ ctxCancel (nil )
81+ },
82+ debugGitCmd : cmdCatFile ,
10683 }
10784}
10885
0 commit comments