@@ -12,6 +12,8 @@ import (
12
12
"os"
13
13
"strconv"
14
14
"strings"
15
+
16
+ "code.gitea.io/gitea/modules/log"
15
17
)
16
18
17
19
// CheckAttributeOpts represents the possible options to CheckAttribute
@@ -112,56 +114,63 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
112
114
113
115
if len (c .IndexFile ) > 0 && CheckGitVersionAtLeast ("1.7.8" ) == nil {
114
116
cmdArgs = append (cmdArgs , "--cached" )
115
- c .env = [] string { "GIT_INDEX_FILE=" + c .IndexFile }
117
+ c .env = append ( c . env , "GIT_INDEX_FILE=" + c .IndexFile )
116
118
}
117
119
118
120
if len (c .WorkTree ) > 0 && CheckGitVersionAtLeast ("1.7.8" ) == nil {
119
- c .env = [] string { "GIT_WORK_TREE=" + c .WorkTree }
121
+ c .env = append ( c . env , "GIT_WORK_TREE=" + c .WorkTree )
120
122
}
121
123
122
- if len (c .Attributes ) > 0 {
123
- cmdArgs = append (cmdArgs , c .Attributes ... )
124
- cmdArgs = append (cmdArgs , "--" )
125
- } else {
124
+ c .env = append (c .env , "GIT_FLUSH=1" )
125
+
126
+ if len (c .Attributes ) == 0 {
126
127
lw := new (nulSeparatedAttributeWriter )
127
128
lw .attributes = make (chan attributeTriple )
129
+ lw .closed = make (chan struct {})
128
130
129
131
c .stdOut = lw
130
132
c .stdOut .Close ()
131
133
return fmt .Errorf ("no provided Attributes to check" )
132
134
}
133
135
136
+ cmdArgs = append (cmdArgs , c .Attributes ... )
137
+ cmdArgs = append (cmdArgs , "--" )
138
+
134
139
c .ctx , c .cancel = context .WithCancel (ctx )
135
140
c .cmd = NewCommandContext (c .ctx , cmdArgs ... )
141
+
136
142
var err error
143
+
137
144
c .stdinReader , c .stdinWriter , err = os .Pipe ()
138
145
if err != nil {
146
+ c .cancel ()
139
147
return err
140
148
}
141
149
142
150
if CheckGitVersionAtLeast ("1.8.5" ) == nil {
143
151
lw := new (nulSeparatedAttributeWriter )
144
152
lw .attributes = make (chan attributeTriple , 5 )
145
-
153
+ lw . closed = make ( chan struct {})
146
154
c .stdOut = lw
147
155
} else {
148
156
lw := new (lineSeparatedAttributeWriter )
149
157
lw .attributes = make (chan attributeTriple , 5 )
150
-
158
+ lw . closed = make ( chan struct {})
151
159
c .stdOut = lw
152
160
}
153
161
return nil
154
162
}
155
163
156
164
// Run run cmd
157
165
func (c * CheckAttributeReader ) Run () error {
166
+ defer func () {
167
+ _ = c .Close ()
168
+ }()
158
169
stdErr := new (bytes.Buffer )
159
170
err := c .cmd .RunInDirTimeoutEnvFullPipelineFunc (c .env , - 1 , c .Repo .Path , c .stdOut , stdErr , c .stdinReader , func (_ context.Context , _ context.CancelFunc ) error {
160
171
close (c .running )
161
172
return nil
162
173
})
163
- defer c .cancel ()
164
- _ = c .stdOut .Close ()
165
174
if err != nil && c .ctx .Err () != nil && err .Error () != "signal: killed" {
166
175
return fmt .Errorf ("failed to run attr-check. Error: %w\n Stderr: %s" , err , stdErr .String ())
167
176
}
@@ -170,27 +179,31 @@ func (c *CheckAttributeReader) Run() error {
170
179
}
171
180
172
181
// CheckPath check attr for given path
173
- func (c * CheckAttributeReader ) CheckPath (path string ) (map [string ]string , error ) {
182
+ func (c * CheckAttributeReader ) CheckPath (path string ) (rs map [string ]string , err error ) {
183
+ defer func () {
184
+ if err != nil {
185
+ log .Error ("CheckPath returns error: %v" , err )
186
+ }
187
+ }()
188
+
174
189
select {
175
190
case <- c .ctx .Done ():
176
191
return nil , c .ctx .Err ()
177
192
case <- c .running :
178
193
}
179
194
180
- if _ , err : = c .stdinWriter .Write ([]byte (path + "\x00 " )); err != nil {
181
- defer c .cancel ()
195
+ if _ , err = c .stdinWriter .Write ([]byte (path + "\x00 " )); err != nil {
196
+ defer c .Close ()
182
197
return nil , err
183
198
}
184
199
185
- if err := c .stdinWriter .Sync (); err != nil {
186
- defer c .cancel ()
187
- return nil , err
188
- }
189
-
190
- rs := make (map [string ]string )
200
+ rs = make (map [string ]string )
191
201
for range c .Attributes {
192
202
select {
193
- case attr := <- c .stdOut .ReadAttribute ():
203
+ case attr , ok := <- c .stdOut .ReadAttribute ():
204
+ if ! ok {
205
+ return nil , c .ctx .Err ()
206
+ }
194
207
rs [attr .Attribute ] = attr .Value
195
208
case <- c .ctx .Done ():
196
209
return nil , c .ctx .Err ()
@@ -201,13 +214,16 @@ func (c *CheckAttributeReader) CheckPath(path string) (map[string]string, error)
201
214
202
215
// Close close pip after use
203
216
func (c * CheckAttributeReader ) Close () error {
217
+ err := c .stdinWriter .Close ()
218
+ _ = c .stdinReader .Close ()
219
+ _ = c .stdOut .Close ()
220
+ c .cancel ()
204
221
select {
205
222
case <- c .running :
206
223
default :
207
224
close (c .running )
208
225
}
209
- defer c .cancel ()
210
- return c .stdinWriter .Close ()
226
+ return err
211
227
}
212
228
213
229
type attributeWriter interface {
@@ -224,6 +240,7 @@ type attributeTriple struct {
224
240
type nulSeparatedAttributeWriter struct {
225
241
tmp []byte
226
242
attributes chan attributeTriple
243
+ closed chan struct {}
227
244
working attributeTriple
228
245
pos int
229
246
}
@@ -267,13 +284,20 @@ func (wr *nulSeparatedAttributeWriter) ReadAttribute() <-chan attributeTriple {
267
284
}
268
285
269
286
func (wr * nulSeparatedAttributeWriter ) Close () error {
287
+ select {
288
+ case <- wr .closed :
289
+ return nil
290
+ default :
291
+ }
270
292
close (wr .attributes )
293
+ close (wr .closed )
271
294
return nil
272
295
}
273
296
274
297
type lineSeparatedAttributeWriter struct {
275
298
tmp []byte
276
299
attributes chan attributeTriple
300
+ closed chan struct {}
277
301
}
278
302
279
303
func (wr * lineSeparatedAttributeWriter ) Write (p []byte ) (n int , err error ) {
@@ -356,6 +380,12 @@ func (wr *lineSeparatedAttributeWriter) ReadAttribute() <-chan attributeTriple {
356
380
}
357
381
358
382
func (wr * lineSeparatedAttributeWriter ) Close () error {
383
+ select {
384
+ case <- wr .closed :
385
+ return nil
386
+ default :
387
+ }
359
388
close (wr .attributes )
389
+ close (wr .closed )
360
390
return nil
361
391
}
0 commit comments