@@ -26,7 +26,6 @@ type fileInfo struct {
26
26
WorkspacePath string `json:"workspace_path"`
27
27
Hardlink bool `json:"hardlink"`
28
28
29
- Realpath string
30
29
FileInfo fs.FileInfo
31
30
}
32
31
@@ -131,9 +130,6 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
131
130
// filepath.WalkDir walks the file tree rooted at root, calling fn for each file or directory in
132
131
// the tree, including root. See https://pkg.go.dev/path/filepath#WalkDir for more info.
133
132
walkPath := file .Path
134
- if file .Realpath != "" {
135
- walkPath = file .Realpath
136
- }
137
133
return filepath .WalkDir (walkPath , func (p string , dirEntry fs.DirEntry , err error ) error {
138
134
if err != nil {
139
135
return err
@@ -157,64 +153,53 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
157
153
return err
158
154
}
159
155
156
+ f := fileInfo {
157
+ Package : file .Package ,
158
+ Path : p ,
159
+ RootPath : file .RootPath ,
160
+ ShortPath : path .Join (file .ShortPath , r ),
161
+ Workspace : file .Workspace ,
162
+ WorkspacePath : path .Join (file .WorkspacePath , r ),
163
+ Hardlink : file .Hardlink ,
164
+ FileInfo : info ,
165
+ }
166
+
167
+ outputPath , err := w .calculateOutputPath (cfg , f )
168
+ if err != nil {
169
+ return fmt .Errorf ("failed to calculate output path for %s: %w" , file .WorkspacePath , err )
170
+ }
171
+ if outputPath == "" {
172
+ // this path is excluded
173
+ return nil
174
+ }
175
+
176
+ // if file is a symlink, resolve its realpath
160
177
if info .Mode ()& os .ModeSymlink == os .ModeSymlink {
161
- // symlink to directories are intentionally never followed by filepath.Walk to avoid infinite recursion
162
- linkPath , err := common .Realpath (p )
178
+ realpath , err := common .Realpath (p )
163
179
if err != nil {
164
180
if os .IsNotExist (err ) {
165
181
return fmt .Errorf ("failed to get realpath of dangling symlink %s: %w" , p , err )
166
182
}
167
183
return fmt .Errorf ("failed to get realpath of %s: %w" , p , err )
168
184
}
169
- if srcPaths [linkPath ] {
185
+ if srcPaths [realpath ] {
170
186
// recursive symlink; silently ignore
171
187
return nil
172
188
}
173
- stat , err := os .Stat (linkPath )
189
+ stat , err := os .Stat (realpath )
174
190
if err != nil {
175
- return fmt .Errorf ("failed to stat file %s pointed to by symlink %s: %w" , linkPath , p , err )
191
+ return fmt .Errorf ("failed to stat file %s pointed to by symlink %s: %w" , realpath , p , err )
176
192
}
193
+ f .Path = realpath
194
+ f .FileInfo = stat
195
+
177
196
if stat .IsDir () {
178
197
// symlink points to a directory
179
- f := fileInfo {
180
- Package : file .Package ,
181
- Path : linkPath ,
182
- RootPath : file .RootPath ,
183
- ShortPath : file .ShortPath ,
184
- Workspace : file .Workspace ,
185
- WorkspacePath : file .WorkspacePath ,
186
- Hardlink : file .Hardlink ,
187
- FileInfo : stat ,
188
- }
189
198
return w .copyDir (cfg , srcPaths , f )
190
- } else {
191
- // symlink points to a regular file
192
- f := fileInfo {
193
- Package : file .Package ,
194
- Path : linkPath ,
195
- RootPath : file .RootPath ,
196
- ShortPath : path .Join (file .ShortPath , r ),
197
- Workspace : file .Workspace ,
198
- WorkspacePath : path .Join (file .WorkspacePath , r ),
199
- Hardlink : file .Hardlink ,
200
- FileInfo : stat ,
201
- }
202
- return w .copyPath (cfg , f )
203
199
}
204
200
}
205
201
206
- // a regular file
207
- f := fileInfo {
208
- Package : file .Package ,
209
- Path : p ,
210
- RootPath : file .RootPath ,
211
- ShortPath : path .Join (file .ShortPath , r ),
212
- Workspace : file .Workspace ,
213
- WorkspacePath : path .Join (file .WorkspacePath , r ),
214
- Hardlink : file .Hardlink ,
215
- FileInfo : info ,
216
- }
217
- return w .copyPath (cfg , f )
202
+ return w .copyPath (cfg , f , outputPath )
218
203
})
219
204
}
220
205
@@ -305,16 +290,7 @@ func (w *walker) calculateOutputPath(cfg *config, file fileInfo) (string, error)
305
290
return path .Join (cfg .Dst , outputPath ), nil
306
291
}
307
292
308
- func (w * walker ) copyPath (cfg * config , file fileInfo ) error {
309
- outputPath , err := w .calculateOutputPath (cfg , file )
310
- if err != nil {
311
- return fmt .Errorf ("failed to calculate output path %s: %w" , file .WorkspacePath , err )
312
- }
313
- if outputPath == "" {
314
- // this path is excluded
315
- return nil
316
- }
317
-
293
+ func (w * walker ) copyPath (cfg * config , file fileInfo , outputPath string ) error {
318
294
// add this file to the copy Paths
319
295
dup , exists := copySet [outputPath ]
320
296
if exists {
@@ -329,7 +305,7 @@ func (w *walker) copyPath(cfg *config, file fileInfo) error {
329
305
330
306
outputDir := path .Dir (outputPath )
331
307
if ! mkdirSet [outputDir ] {
332
- if err = os .MkdirAll (outputDir , os .ModePerm ); err != nil {
308
+ if err : = os .MkdirAll (outputDir , os .ModePerm ); err != nil {
333
309
return err
334
310
}
335
311
// https://pkg.go.dev/path#Dir
@@ -353,10 +329,27 @@ func (w *walker) copyPaths(cfg *config) error {
353
329
if err != nil {
354
330
return fmt .Errorf ("failed to lstat file %s: %w" , file .Path , err )
355
331
}
332
+ file .FileInfo = info
333
+
334
+ // if file is a directory, then short-circuit without calculating the output path
335
+ if file .FileInfo .IsDir () {
336
+ if err := w .copyDir (cfg , nil , file ); err != nil {
337
+ return err
338
+ }
339
+ continue
340
+ }
341
+
342
+ outputPath , err := w .calculateOutputPath (cfg , file )
343
+ if err != nil {
344
+ return fmt .Errorf ("failed to calculate output path for %s: %w" , file .WorkspacePath , err )
345
+ }
346
+ if outputPath == "" {
347
+ // this path is excluded
348
+ continue
349
+ }
356
350
351
+ // if file is a symlink, resolve its realpath
357
352
if info .Mode ()& os .ModeSymlink == os .ModeSymlink {
358
- // On Windows, filepath.WalkDir doesn't like directory symlinks so we must
359
- // call filepath.WalkDir on the realpath
360
353
realpath , err := common .Realpath (file .Path )
361
354
if err != nil {
362
355
if os .IsNotExist (err ) {
@@ -368,21 +361,21 @@ func (w *walker) copyPaths(cfg *config) error {
368
361
if err != nil {
369
362
return fmt .Errorf ("failed to stat file %s pointed to by symlink %s: %w" , realpath , file .Path , err )
370
363
}
371
- file .Realpath = realpath
364
+ file .Path = realpath
372
365
file .FileInfo = stat
373
- } else {
374
- file .FileInfo = info
375
- }
376
366
377
- if file .FileInfo .IsDir () {
378
- if err := w .copyDir (cfg , nil , file ); err != nil {
379
- return err
380
- }
381
- } else {
382
- if err := w .copyPath (cfg , file ); err != nil {
383
- return err
367
+ if file .FileInfo .IsDir () {
368
+ // symlink points to a directory
369
+ if err := w .copyDir (cfg , nil , file ); err != nil {
370
+ return err
371
+ }
372
+ continue
384
373
}
385
374
}
375
+
376
+ if err := w .copyPath (cfg , file , outputPath ); err != nil {
377
+ return err
378
+ }
386
379
}
387
380
return nil
388
381
}
0 commit comments