@@ -8,40 +8,160 @@ import (
88 "context"
99)
1010
11- type Batch struct {
11+ type batchCatFile struct {
1212 cancel context.CancelFunc
1313 Reader * bufio.Reader
1414 Writer WriteCloserError
1515}
1616
17+ func (b * batchCatFile ) Close () {
18+ if b .cancel != nil {
19+ b .cancel ()
20+ b .Reader = nil
21+ b .Writer = nil
22+ b .cancel = nil
23+ }
24+ }
25+
1726// NewBatch creates a new batch for the given repository, the Close must be invoked before release the batch
18- func NewBatch (ctx context.Context , repoPath string ) (* Batch , error ) {
27+ func newBatch (ctx context.Context , repoPath string ) (* batchCatFile , error ) {
1928 // 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!
2029 if err := ensureValidGitRepository (ctx , repoPath ); err != nil {
2130 return nil , err
2231 }
2332
24- var batch Batch
25- batch .Writer , batch .Reader , batch .cancel = catFileBatch (ctx , repoPath )
33+ var batch batchCatFile
34+ batch .Writer , batch .Reader , batch .cancel = catFileBatch (ctx , repoPath , "--batch" )
2635 return & batch , nil
2736}
2837
29- func NewBatchCheck (ctx context.Context , repoPath string ) (* Batch , error ) {
38+ func newBatchCheck (ctx context.Context , repoPath string ) (* batchCatFile , error ) {
3039 // 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!
3140 if err := ensureValidGitRepository (ctx , repoPath ); err != nil {
3241 return nil , err
3342 }
3443
35- var check Batch
44+ var check batchCatFile
3645 check .Writer , check .Reader , check .cancel = catFileBatchCheck (ctx , repoPath )
3746 return & check , nil
3847}
3948
40- func (b * Batch ) Close () {
41- if b .cancel != nil {
42- b .cancel ()
43- b .Reader = nil
44- b .Writer = nil
45- b .cancel = nil
49+ func newBatchCommand (ctx context.Context , repoPath string ) (* batchCatFile , error ) {
50+ // 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!
51+ if err := ensureValidGitRepository (ctx , repoPath ); err != nil {
52+ return nil , err
53+ }
54+
55+ var check batchCatFile
56+ check .Writer , check .Reader , check .cancel = catFileBatch (ctx , repoPath , "--batch-command" )
57+ return & check , nil
58+ }
59+
60+ type Batch interface {
61+ Write ([]byte ) (int , error )
62+ WriteCheck ([]byte ) (int , error )
63+ Reader () * bufio.Reader
64+ CheckReader () * bufio.Reader
65+ Close ()
66+ }
67+
68+ // batchCatFileWithCheck implements the Batch interface using the "cat-file --batch" command and "cat-file --batch-check" command
69+ // ref: https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch
70+ // To align with --batch-command, we creates the two commands both at the same time if git version is lower than 2.36
71+ type batchCatFileWithCheck struct {
72+ batch * batchCatFile
73+ batchCheck * batchCatFile
74+ }
75+
76+ var _ Batch = & batchCatFileWithCheck {}
77+
78+ func newBatchCatFileWithCheck (ctx context.Context , repoPath string ) (* batchCatFileWithCheck , error ) {
79+ batch , err := newBatch (ctx , repoPath )
80+ if err != nil {
81+ return nil , err
82+ }
83+
84+ batchCheck , err := newBatchCheck (ctx , repoPath )
85+ if err != nil {
86+ return nil , err
87+ }
88+
89+ return & batchCatFileWithCheck {
90+ batch : batch ,
91+ batchCheck : batchCheck ,
92+ }, nil
93+ }
94+
95+ func (b * batchCatFileWithCheck ) Write (bs []byte ) (int , error ) {
96+ return b .batch .Writer .Write (bs )
97+ }
98+
99+ func (b * batchCatFileWithCheck ) WriteCheck (bs []byte ) (int , error ) {
100+ return b .batchCheck .Writer .Write (bs )
101+ }
102+
103+ func (b * batchCatFileWithCheck ) Reader () * bufio.Reader {
104+ return b .batch .Reader
105+ }
106+
107+ func (b * batchCatFileWithCheck ) CheckReader () * bufio.Reader {
108+ return b .batchCheck .Reader
109+ }
110+
111+ func (b * batchCatFileWithCheck ) Close () {
112+ if b .batch != nil {
113+ b .batch .Close ()
114+ b .batch = nil
115+ }
116+ if b .batchCheck != nil {
117+ b .batchCheck .Close ()
118+ b .batchCheck = nil
119+ }
120+ }
121+
122+ // batchCommandCatFile implements the Batch interface using the "cat-file --batch-command" command
123+ // ref: https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-command
124+ type batchCommandCatFile struct {
125+ batch * batchCatFile
126+ }
127+
128+ func newBatchCommandCatFile (ctx context.Context , repoPath string ) (* batchCommandCatFile , error ) {
129+ batch , err := newBatchCommand (ctx , repoPath )
130+ if err != nil {
131+ return nil , err
132+ }
133+
134+ return & batchCommandCatFile {
135+ batch : batch ,
136+ }, nil
137+ }
138+
139+ func (b * batchCommandCatFile ) Write (bs []byte ) (int , error ) {
140+ return b .batch .Writer .Write (append ([]byte ("contents " ), bs ... ))
141+ }
142+
143+ func (b * batchCommandCatFile ) WriteCheck (bs []byte ) (int , error ) {
144+ return b .batch .Writer .Write (append ([]byte ("info " ), bs ... ))
145+ }
146+
147+ func (b * batchCommandCatFile ) Reader () * bufio.Reader {
148+ return b .batch .Reader
149+ }
150+
151+ func (b * batchCommandCatFile ) CheckReader () * bufio.Reader {
152+ return b .batch .Reader
153+ }
154+
155+ func (b * batchCommandCatFile ) Close () {
156+ if b .batch != nil {
157+ b .batch .Close ()
158+ b .batch = nil
159+ }
160+ }
161+
162+ func NewBatch (ctx context.Context , repoPath string ) (Batch , error ) {
163+ if DefaultFeatures ().SupportCatFileBatchCommand {
164+ return newBatchCommandCatFile (ctx , repoPath )
46165 }
166+ return newBatchCatFileWithCheck (ctx , repoPath )
47167}
0 commit comments