-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
filter: fix a bug with parent dirs #203
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,15 +40,24 @@ type MapFunc func(string, *types.Stat) MapResult | |
type MapResult int | ||
|
||
const ( | ||
// Keep the current path and continue. | ||
// Keep the current path and continue walking the file tree. | ||
MapResultKeep MapResult = iota | ||
|
||
// Exclude the current path and continue. | ||
// Exclude the current path and continue walking the file tree. | ||
// | ||
// If path is a dir, we'll continue walking the subtree of the directory. | ||
// If a path in that subtree is later included during the walk, the walker | ||
// will backtrack and include the dir. | ||
MapResultExclude | ||
|
||
// Exclude the current path, and skip the rest of the dir. | ||
// | ||
// Skip is used as an important performance optimization to prevent | ||
// the walker from visiting large subtrees that it doesn't need to. | ||
// | ||
// If path is a dir, skip the current directory. | ||
// If path is a file, skip the rest of the parent directory. | ||
// | ||
// (This matches the semantics of fs.SkipDir.) | ||
MapResultSkipDir | ||
) | ||
|
@@ -197,7 +206,7 @@ func (fs *filterFS) Walk(ctx context.Context, target string, fn gofs.WalkDirFunc | |
isDir = dirEntry.IsDir() | ||
} | ||
|
||
if fs.includeMatcher != nil || fs.excludeMatcher != nil { | ||
if fs.includeMatcher != nil || fs.excludeMatcher != nil || fs.mapFn != nil { | ||
for len(parentDirs) != 0 { | ||
lastParentDir := parentDirs[len(parentDirs)-1].pathWithSep | ||
if strings.HasPrefix(path, lastParentDir) { | ||
|
@@ -298,7 +307,7 @@ func (fs *filterFS) Walk(ctx context.Context, target string, fn gofs.WalkDirFunc | |
return walkErr | ||
} | ||
|
||
if fs.includeMatcher != nil || fs.excludeMatcher != nil { | ||
if fs.includeMatcher != nil || fs.excludeMatcher != nil || fs.mapFn != nil { | ||
defer func() { | ||
if isDir { | ||
parentDirs = append(parentDirs, dir) | ||
|
@@ -310,8 +319,6 @@ func (fs *filterFS) Walk(ctx context.Context, target string, fn gofs.WalkDirFunc | |
return nil | ||
} | ||
|
||
dir.calledFn = true | ||
|
||
fi, err := dirEntry.Info() | ||
if err != nil { | ||
return err | ||
|
@@ -357,7 +364,9 @@ func (fs *filterFS) Walk(ctx context.Context, target string, fn gofs.WalkDirFunc | |
if fs.mapFn != nil { | ||
result := fs.mapFn(parentStat.Path, parentStat) | ||
if result == MapResultExclude { | ||
continue | ||
// If a directory is marked excluded, but a subpath is included, | ||
// then we should still include the directory. | ||
// Otherwise Buildkit will treat this as an error. | ||
} else if result == MapResultSkipDir { | ||
parentDirs[i].skipFn = true | ||
return filepath.SkipDir | ||
|
@@ -372,6 +381,8 @@ func (fs *filterFS) Walk(ctx context.Context, target string, fn gofs.WalkDirFunc | |
return err | ||
} | ||
} | ||
|
||
dir.calledFn = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👀 this feels unrelated, were we not setting this before? Was there a case where we were calling the walk target function multiple times? Kinda confused as to why this shows up just here (definitely worth fixing). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ya, i moved this line. Before this pr, the logic went:
now, i only set calledFn to true directly before calling fn |
||
if err := fn(stat.Path, &DirEntryInfo{Stat: stat}, nil); err != nil { | ||
return err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I'm not a big fan of is that everything that gets a map goes to this more complicated code-path to support the backtracking, while most of the time the map is really used to reset uid/gid or skip paths recursively.
Would be really ugly, but smth. like
MapAllowBacktrack bool
would solve that.I don't know how big issue this is in practice though. It might be that most of our requests set includematches/excludematcher anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is your concern more about performance or debuggability?
i'd be in favor of adding a much simpler FS implementation purely focused on the reset uid/gid case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance a bit maybe, but mostly keeping the default code path simpler and preventing potential stability issues.