Skip to content

Commit 7a8f00c

Browse files
authored
fix: exclude files in copy_to_directory before checking their realpath (#857)
1 parent f30debb commit 7a8f00c

File tree

1 file changed

+61
-68
lines changed

1 file changed

+61
-68
lines changed

tools/copy_to_directory/main.go

+61-68
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ type fileInfo struct {
2626
WorkspacePath string `json:"workspace_path"`
2727
Hardlink bool `json:"hardlink"`
2828

29-
Realpath string
3029
FileInfo fs.FileInfo
3130
}
3231

@@ -131,9 +130,6 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
131130
// filepath.WalkDir walks the file tree rooted at root, calling fn for each file or directory in
132131
// the tree, including root. See https://pkg.go.dev/path/filepath#WalkDir for more info.
133132
walkPath := file.Path
134-
if file.Realpath != "" {
135-
walkPath = file.Realpath
136-
}
137133
return filepath.WalkDir(walkPath, func(p string, dirEntry fs.DirEntry, err error) error {
138134
if err != nil {
139135
return err
@@ -157,64 +153,53 @@ func (w *walker) copyDir(cfg *config, srcPaths pathSet, file fileInfo) error {
157153
return err
158154
}
159155

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
160177
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)
163179
if err != nil {
164180
if os.IsNotExist(err) {
165181
return fmt.Errorf("failed to get realpath of dangling symlink %s: %w", p, err)
166182
}
167183
return fmt.Errorf("failed to get realpath of %s: %w", p, err)
168184
}
169-
if srcPaths[linkPath] {
185+
if srcPaths[realpath] {
170186
// recursive symlink; silently ignore
171187
return nil
172188
}
173-
stat, err := os.Stat(linkPath)
189+
stat, err := os.Stat(realpath)
174190
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)
176192
}
193+
f.Path = realpath
194+
f.FileInfo = stat
195+
177196
if stat.IsDir() {
178197
// 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-
}
189198
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)
203199
}
204200
}
205201

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)
218203
})
219204
}
220205

@@ -305,16 +290,7 @@ func (w *walker) calculateOutputPath(cfg *config, file fileInfo) (string, error)
305290
return path.Join(cfg.Dst, outputPath), nil
306291
}
307292

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 {
318294
// add this file to the copy Paths
319295
dup, exists := copySet[outputPath]
320296
if exists {
@@ -329,7 +305,7 @@ func (w *walker) copyPath(cfg *config, file fileInfo) error {
329305

330306
outputDir := path.Dir(outputPath)
331307
if !mkdirSet[outputDir] {
332-
if err = os.MkdirAll(outputDir, os.ModePerm); err != nil {
308+
if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
333309
return err
334310
}
335311
// https://pkg.go.dev/path#Dir
@@ -353,10 +329,27 @@ func (w *walker) copyPaths(cfg *config) error {
353329
if err != nil {
354330
return fmt.Errorf("failed to lstat file %s: %w", file.Path, err)
355331
}
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+
}
356350

351+
// if file is a symlink, resolve its realpath
357352
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
360353
realpath, err := common.Realpath(file.Path)
361354
if err != nil {
362355
if os.IsNotExist(err) {
@@ -368,21 +361,21 @@ func (w *walker) copyPaths(cfg *config) error {
368361
if err != nil {
369362
return fmt.Errorf("failed to stat file %s pointed to by symlink %s: %w", realpath, file.Path, err)
370363
}
371-
file.Realpath = realpath
364+
file.Path = realpath
372365
file.FileInfo = stat
373-
} else {
374-
file.FileInfo = info
375-
}
376366

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
384373
}
385374
}
375+
376+
if err := w.copyPath(cfg, file, outputPath); err != nil {
377+
return err
378+
}
386379
}
387380
return nil
388381
}

0 commit comments

Comments
 (0)