From d8e174646670896db35a4e4db13b7589dcb5b57c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 1 Mar 2022 22:41:22 +0100 Subject: [PATCH] vendor: github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 full diff: https://github.com/tonistiigi/fsutil/compare/d72af97c0eaf...b19f7f9cb274 Signed-off-by: Sebastiaan van Stijn --- vendor.mod | 2 +- vendor.sum | 4 +- .../github.com/tonistiigi/fsutil/copy/copy.go | 143 ++++++--- .../tonistiigi/fsutil/copy/copy_freebsd.go | 32 +++ .../tonistiigi/fsutil/copy/copy_linux.go | 5 +- .../tonistiigi/fsutil/copy/copy_unix.go | 9 +- .../tonistiigi/fsutil/copy/device_darwin.go | 20 ++ .../tonistiigi/fsutil/copy/device_freebsd.go | 20 ++ .../tonistiigi/fsutil/diff_containerd.go | 13 + .../tonistiigi/fsutil/diskwriter_freebsd.go | 14 + .../tonistiigi/fsutil/diskwriter_unix.go | 2 +- .../tonistiigi/fsutil/diskwriter_unixnobsd.go | 13 + .../tonistiigi/fsutil/docker-bake.hcl | 2 +- .../tonistiigi/fsutil/prefix/match.go | 45 --- vendor/github.com/tonistiigi/fsutil/walker.go | 271 +++++++++++++----- vendor/modules.txt | 3 +- 16 files changed, 426 insertions(+), 172 deletions(-) create mode 100644 vendor/github.com/tonistiigi/fsutil/copy/copy_freebsd.go create mode 100644 vendor/github.com/tonistiigi/fsutil/copy/device_darwin.go create mode 100644 vendor/github.com/tonistiigi/fsutil/copy/device_freebsd.go create mode 100644 vendor/github.com/tonistiigi/fsutil/diskwriter_freebsd.go create mode 100644 vendor/github.com/tonistiigi/fsutil/diskwriter_unixnobsd.go delete mode 100644 vendor/github.com/tonistiigi/fsutil/prefix/match.go diff --git a/vendor.mod b/vendor.mod index 7e9d14e4aa..b024669f86 100644 --- a/vendor.mod +++ b/vendor.mod @@ -72,7 +72,7 @@ require ( github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 github.com/tchap/go-patricia v2.3.0+incompatible - github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf + github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 github.com/vbatts/tar-split v0.11.2 github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae diff --git a/vendor.sum b/vendor.sum index c52e0a21a0..417dc13109 100644 --- a/vendor.sum +++ b/vendor.sum @@ -269,6 +269,7 @@ github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvv github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.3-0.20210609071616-4c2ec79bf2a8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.3-0.20211208011758-87521affb077+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= @@ -729,8 +730,9 @@ github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf h1:L0ixhsTk9j+dVnIvF6aiVCxPiaFvwTOyJxqimPq44p8= github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf/go.mod h1:lJAxK//iyZ3yGbQswdrPTxugZIDM7sd4bEsD0x3XMHk= +github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 h1:wbyZxD6IPFp0sl5uscMOJRsz5UKGFiNiD16e+MVfKZY= +github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274/go.mod h1:oPAfvw32vlUJSjyDcQ3Bu0nb2ON2B+G0dtVN/SZNJiA= github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe h1:pd7hrFSqUPxYS9IB+UMG1AB/8EXGXo17ssx0bSQ5L6Y= github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe/go.mod h1:/+MCh11CJf2oz0BXmlmqyopK/ad1rKkcOXPoYuPCJYU= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy.go b/vendor/github.com/tonistiigi/fsutil/copy/copy.go index 569b4ed885..41b82c32da 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy.go @@ -4,6 +4,7 @@ import ( "context" "io/ioutil" "os" + "path" "path/filepath" "runtime" "strings" @@ -13,6 +14,7 @@ import ( "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/fileutils" "github.com/pkg/errors" + "github.com/tonistiigi/fsutil" ) var bufferPool = &sync.Pool{ @@ -87,7 +89,7 @@ func Copy(ctx context.Context, srcRoot, src, dstRoot, dst string, opts ...Opt) e return err } - c, err := newCopier(ci.Chown, ci.Utime, ci.Mode, ci.XAttrErrorHandler, ci.IncludePatterns, ci.ExcludePatterns) + c, err := newCopier(dstRoot, ci.Chown, ci.Utime, ci.Mode, ci.XAttrErrorHandler, ci.IncludePatterns, ci.ExcludePatterns, ci.ChangeFunc) if err != nil { return err } @@ -113,8 +115,7 @@ func Copy(ctx context.Context, srcRoot, src, dstRoot, dst string, opts ...Opt) e if err != nil { return err } - skipIncludePatterns := c.includePatternMatcher == nil - if err := c.copy(ctx, srcFollowed, "", dst, false, skipIncludePatterns); err != nil { + if err := c.copy(ctx, srcFollowed, "", dst, false, fileutils.MatchInfo{}, fileutils.MatchInfo{}); err != nil { return err } } @@ -171,6 +172,7 @@ type CopyInfo struct { IncludePatterns []string // Exclude files/dir matching any of these patterns (even if they match an include pattern) ExcludePatterns []string + ChangeFunc fsutil.ChangeFunc } type Opt func(*CopyInfo) @@ -218,6 +220,12 @@ func WithExcludePattern(excludePattern string) Opt { } } +func WithChangeNotifier(fn fsutil.ChangeFunc) Opt { + return func(ci *CopyInfo) { + ci.ChangeFunc = fn + } +} + type copier struct { chown Chowner utime *time.Time @@ -227,6 +235,8 @@ type copier struct { includePatternMatcher *fileutils.PatternMatcher excludePatternMatcher *fileutils.PatternMatcher parentDirs []parentDir + changefn fsutil.ChangeFunc + root string } type parentDir struct { @@ -235,7 +245,7 @@ type parentDir struct { copied bool } -func newCopier(chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler, includePatterns, excludePatterns []string) (*copier, error) { +func newCopier(root string, chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler, includePatterns, excludePatterns []string, changeFunc fsutil.ChangeFunc) (*copier, error) { if xeh == nil { xeh = func(dst, src, key string, err error) error { return err @@ -261,6 +271,7 @@ func newCopier(chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler, i } return &copier{ + root: root, inodes: map[uint64]string{}, chown: chown, utime: tm, @@ -268,11 +279,12 @@ func newCopier(chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler, i mode: mode, includePatternMatcher: includePatternMatcher, excludePatternMatcher: excludePatternMatcher, + changefn: changeFunc, }, nil } // dest is always clean -func (c *copier) copy(ctx context.Context, src, srcComponents, target string, overwriteTargetMetadata, skipIncludePatterns bool) error { +func (c *copier) copy(ctx context.Context, src, srcComponents, target string, overwriteTargetMetadata bool, parentIncludeMatchInfo, parentExcludeMatchInfo fileutils.MatchInfo) error { select { case <-ctx.Done(): return ctx.Err() @@ -285,18 +297,24 @@ func (c *copier) copy(ctx context.Context, src, srcComponents, target string, ov } include := true + var ( + includeMatchInfo fileutils.MatchInfo + excludeMatchInfo fileutils.MatchInfo + ) if srcComponents != "" { - if !skipIncludePatterns { - include, err = c.include(srcComponents, fi) - if err != nil { - return err - } - } - exclude, err := c.exclude(srcComponents, fi) + matchesIncludePattern := false + matchesExcludePattern := false + matchesIncludePattern, includeMatchInfo, err = c.include(srcComponents, fi, parentIncludeMatchInfo) if err != nil { return err } - if exclude { + include = matchesIncludePattern + + matchesExcludePattern, excludeMatchInfo, err = c.exclude(srcComponents, fi, parentExcludeMatchInfo) + if err != nil { + return err + } + if matchesExcludePattern { include = false } } @@ -318,14 +336,19 @@ func (c *copier) copy(ctx context.Context, src, srcComponents, target string, ov } copyFileInfo := true + notify := true switch { case fi.IsDir(): - if created, err := c.copyDirectory(ctx, src, srcComponents, target, fi, overwriteTargetMetadata, skipIncludePatterns, include); err != nil { + if created, err := c.copyDirectory( + ctx, src, srcComponents, target, fi, overwriteTargetMetadata, + include, includeMatchInfo, excludeMatchInfo, + ); err != nil { return err - } else if !overwriteTargetMetadata || !skipIncludePatterns { + } else if !overwriteTargetMetadata || c.includePatternMatcher != nil { copyFileInfo = created } + notify = false case (fi.Mode() & os.ModeType) == 0: link, err := getLinkSource(target, fi, c.inodes) if err != nil { @@ -364,31 +387,45 @@ func (c *copier) copy(ctx context.Context, src, srcComponents, target string, ov return errors.Wrap(err, "failed to copy xattrs") } } + if notify { + if err := c.notifyChange(target, fi); err != nil { + return err + } + } return nil } -func (c *copier) include(path string, fi os.FileInfo) (bool, error) { - if c.includePatternMatcher == nil { - return false, nil +func (c *copier) notifyChange(target string, fi os.FileInfo) error { + if c.changefn != nil { + if err := c.changefn(fsutil.ChangeKindAdd, path.Clean(strings.TrimPrefix(target, c.root)), fi, nil); err != nil { + return errors.Wrap(err, "failed to notify file change") + } } - - m, err := c.includePatternMatcher.Matches(path) - if err != nil { - return false, errors.Wrap(err, "failed to match includepatterns") - } - return m, nil + return nil } -func (c *copier) exclude(path string, fi os.FileInfo) (bool, error) { - if c.excludePatternMatcher == nil { - return false, nil +func (c *copier) include(path string, fi os.FileInfo, parentIncludeMatchInfo fileutils.MatchInfo) (bool, fileutils.MatchInfo, error) { + if c.includePatternMatcher == nil { + return true, fileutils.MatchInfo{}, nil } - m, err := c.excludePatternMatcher.Matches(path) + m, matchInfo, err := c.includePatternMatcher.MatchesUsingParentResults(path, parentIncludeMatchInfo) if err != nil { - return false, errors.Wrap(err, "failed to match excludepatterns") + return false, matchInfo, errors.Wrap(err, "failed to match includepatterns") } - return m, nil + return m, matchInfo, nil +} + +func (c *copier) exclude(path string, fi os.FileInfo, parentExcludeMatchInfo fileutils.MatchInfo) (bool, fileutils.MatchInfo, error) { + if c.excludePatternMatcher == nil { + return false, fileutils.MatchInfo{}, nil + } + + m, matchInfo, err := c.excludePatternMatcher.MatchesUsingParentResults(path, parentExcludeMatchInfo) + if err != nil { + return false, matchInfo, errors.Wrap(err, "failed to match excludepatterns") + } + return m, matchInfo, nil } // Delayed creation of parent directories when a file or dir matches an include @@ -426,30 +463,47 @@ func (c *copier) createParentDirs(src, srcComponents, target string, overwriteTa return nil } -func (c *copier) copyDirectory(ctx context.Context, src, srcComponents, dst string, stat os.FileInfo, overwriteTargetMetadata, skipIncludePatterns, matchedExactly bool) (bool, error) { +func (c *copier) copyDirectory( + ctx context.Context, + src string, + srcComponents string, + dst string, + stat os.FileInfo, + overwriteTargetMetadata bool, + include bool, + includeMatchInfo fileutils.MatchInfo, + excludeMatchInfo fileutils.MatchInfo, +) (bool, error) { if !stat.IsDir() { return false, errors.Errorf("source is not directory") } created := false - // If there are no include patterns or this directory matched an include - // pattern exactly, go ahead and create the directory. Otherwise, delay to - // handle include patterns like a/*/c where we do not want to create a/b - // until we encounter a/b/c. - if matchedExactly || skipIncludePatterns { + parentDir := parentDir{ + srcPath: src, + dstPath: dst, + } + + // If this directory passed include/exclude matching directly, go ahead + // and create the directory. Otherwise, delay to handle include + // patterns like a/*/c where we do not want to create a/b until we + // encounter a/b/c. + if include { var err error created, err = copyDirectoryOnly(src, dst, stat, overwriteTargetMetadata) if err != nil { return created, err } + if created || overwriteTargetMetadata { + if err := c.notifyChange(dst, stat); err != nil { + return created, err + } + } + parentDir.copied = true } - c.parentDirs = append(c.parentDirs, parentDir{ - srcPath: src, - dstPath: dst, - copied: skipIncludePatterns, - }) + c.parentDirs = append(c.parentDirs, parentDir) defer func() { c.parentDirs = c.parentDirs[:len(c.parentDirs)-1] @@ -461,7 +515,12 @@ func (c *copier) copyDirectory(ctx context.Context, src, srcComponents, dst stri } for _, fi := range fis { - if err := c.copy(ctx, filepath.Join(src, fi.Name()), filepath.Join(srcComponents, fi.Name()), filepath.Join(dst, fi.Name()), true, skipIncludePatterns); err != nil { + if err := c.copy( + ctx, + filepath.Join(src, fi.Name()), filepath.Join(srcComponents, fi.Name()), + filepath.Join(dst, fi.Name()), + true, includeMatchInfo, excludeMatchInfo, + ); err != nil { return false, err } } diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_freebsd.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_freebsd.go new file mode 100644 index 0000000000..297a2c0335 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_freebsd.go @@ -0,0 +1,32 @@ +// +build freebsd + +package fs + +import ( + "io" + "os" + + "github.com/pkg/errors" +) + +func copyFile(source, target string) error { + src, err := os.Open(source) + if err != nil { + return errors.Wrapf(err, "failed to open source %s", source) + } + defer src.Close() + tgt, err := os.Create(target) + if err != nil { + return errors.Wrapf(err, "failed to open target %s", target) + } + defer tgt.Close() + + return copyFileContent(tgt, src) +} + +func copyFileContent(dst, src *os.File) error { + buf := bufferPool.Get().(*[]byte) + _, err := io.CopyBuffer(dst, src, *buf) + bufferPool.Put(buf) + return err +} diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go index 326b7ee76b..01878525cf 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go @@ -97,7 +97,10 @@ func copyFileContent(dst, src *os.File) error { buf := bufferPool.Get().(*[]byte) _, err = io.CopyBuffer(dst, src, *buf) bufferPool.Put(buf) - return errors.Wrap(err, "userspace copy failed") + if err != nil { + return errors.Wrap(err, "userspace copy failed") + } + return nil } first = false diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go index 6debee281d..22281ba5dd 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go @@ -1,3 +1,4 @@ +//go:build solaris || darwin || freebsd // +build solaris darwin freebsd package fs @@ -51,11 +52,3 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error { } return nil } - -func copyDevice(dst string, fi os.FileInfo) error { - st, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return errors.New("unsupported stat type") - } - return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) -} diff --git a/vendor/github.com/tonistiigi/fsutil/copy/device_darwin.go b/vendor/github.com/tonistiigi/fsutil/copy/device_darwin.go new file mode 100644 index 0000000000..8a06d242a4 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/copy/device_darwin.go @@ -0,0 +1,20 @@ +//go:build darwin +// +build darwin + +package fs + +import ( + "os" + "syscall" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func copyDevice(dst string, fi os.FileInfo) error { + st, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return errors.New("unsupported stat type") + } + return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) +} diff --git a/vendor/github.com/tonistiigi/fsutil/copy/device_freebsd.go b/vendor/github.com/tonistiigi/fsutil/copy/device_freebsd.go new file mode 100644 index 0000000000..64a2fe4da3 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/copy/device_freebsd.go @@ -0,0 +1,20 @@ +//go:build freebsd || solaris +// +build freebsd solaris + +package fs + +import ( + "os" + "syscall" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func copyDevice(dst string, fi os.FileInfo) error { + st, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return errors.New("unsupported stat type") + } + return unix.Mknod(dst, uint32(fi.Mode()), st.Rdev) +} diff --git a/vendor/github.com/tonistiigi/fsutil/diff_containerd.go b/vendor/github.com/tonistiigi/fsutil/diff_containerd.go index d72f4e64fe..d8619abf1c 100644 --- a/vendor/github.com/tonistiigi/fsutil/diff_containerd.go +++ b/vendor/github.com/tonistiigi/fsutil/diff_containerd.go @@ -33,6 +33,19 @@ const ( ChangeKindDelete ) +func (k ChangeKind) String() string { + switch k { + case ChangeKindAdd: + return "add" + case ChangeKindModify: + return "modify" + case ChangeKindDelete: + return "delete" + default: + return "unknown" + } +} + // ChangeFunc is the type of function called for each change // computed during a directory changes calculation. type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_freebsd.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_freebsd.go new file mode 100644 index 0000000000..6ca00618a1 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_freebsd.go @@ -0,0 +1,14 @@ +// +build freebsd + +package fsutil + +import ( + "github.com/tonistiigi/fsutil/types" + "golang.org/x/sys/unix" +) + +func createSpecialFile(path string, mode uint32, stat *types.Stat) error { + dev := unix.Mkdev(uint32(stat.Devmajor), uint32(stat.Devminor)) + + return unix.Mknod(path, mode, dev) +} diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go index aa2d298f40..36bb78895c 100644 --- a/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go +++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go @@ -45,7 +45,7 @@ func handleTarTypeBlockCharFifo(path string, stat *types.Stat) error { mode |= syscall.S_IFBLK } - if err := syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor))); err != nil { + if err := createSpecialFile(path, mode, stat); err != nil { return errors.WithStack(err) } return nil diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_unixnobsd.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_unixnobsd.go new file mode 100644 index 0000000000..9f55ad8832 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_unixnobsd.go @@ -0,0 +1,13 @@ +// +build !windows,!freebsd + +package fsutil + +import ( + "syscall" + + "github.com/tonistiigi/fsutil/types" +) + +func createSpecialFile(path string, mode uint32, stat *types.Stat) error { + return syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor))) +} diff --git a/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl b/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl index 39ef990f52..0d3c54172f 100644 --- a/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl +++ b/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl @@ -63,5 +63,5 @@ target "shfmt" { target "cross" { inherits = ["build"] - platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x"] + platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x", "darwin/amd64", "darwin/arm64", "windows/amd64", "freebsd/amd64", "freebsd/arm64"] } diff --git a/vendor/github.com/tonistiigi/fsutil/prefix/match.go b/vendor/github.com/tonistiigi/fsutil/prefix/match.go deleted file mode 100644 index 57e745c681..0000000000 --- a/vendor/github.com/tonistiigi/fsutil/prefix/match.go +++ /dev/null @@ -1,45 +0,0 @@ -package prefix - -import ( - "path" - "path/filepath" - "strings" -) - -// Match matches a path against a pattern. It returns m = true if the path -// matches the pattern, and partial = true if the pattern has more separators -// than the path and the common components match (for example, name = foo and -// pattern = foo/bar/*). slashSeparator determines whether the path and pattern -// are '/' delimited (true) or use the native path separator (false). -func Match(pattern, name string, slashSeparator bool) (m bool, partial bool) { - separator := filepath.Separator - if slashSeparator { - separator = '/' - } - count := strings.Count(name, string(separator)) - if strings.Count(pattern, string(separator)) > count { - pattern = trimUntilIndex(pattern, string(separator), count) - partial = true - } - if slashSeparator { - m, _ = path.Match(pattern, name) - } else { - m, _ = filepath.Match(pattern, name) - } - return m, partial -} - -func trimUntilIndex(str, sep string, count int) string { - s := str - i := 0 - c := 0 - for { - idx := strings.Index(s, sep) - s = s[idx+len(sep):] - i += idx + len(sep) - c++ - if c > count { - return str[:i-len(sep)] - } - } -} diff --git a/vendor/github.com/tonistiigi/fsutil/walker.go b/vendor/github.com/tonistiigi/fsutil/walker.go index cc6143db49..d0b5114b40 100644 --- a/vendor/github.com/tonistiigi/fsutil/walker.go +++ b/vendor/github.com/tonistiigi/fsutil/walker.go @@ -10,7 +10,6 @@ import ( "github.com/docker/docker/pkg/fileutils" "github.com/pkg/errors" - "github.com/tonistiigi/fsutil/prefix" "github.com/tonistiigi/fsutil/types" ) @@ -36,20 +35,15 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err return errors.WithStack(&os.PathError{Op: "walk", Path: root, Err: syscall.ENOTDIR}) } - var pm *fileutils.PatternMatcher - if opt != nil && opt.ExcludePatterns != nil { - pm, err = fileutils.NewPatternMatcher(opt.ExcludePatterns) - if err != nil { - return errors.Wrapf(err, "invalid excludepatterns: %s", opt.ExcludePatterns) - } - } + var ( + includePatterns []string + includeMatcher *fileutils.PatternMatcher + excludeMatcher *fileutils.PatternMatcher + ) - var includePatterns []string if opt != nil && opt.IncludePatterns != nil { includePatterns = make([]string, len(opt.IncludePatterns)) - for k := range opt.IncludePatterns { - includePatterns[k] = filepath.Clean(opt.IncludePatterns[k]) - } + copy(includePatterns, opt.IncludePatterns) } if opt != nil && opt.FollowPaths != nil { targets, err := FollowLinks(p, opt.FollowPaths) @@ -62,18 +56,62 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err } } - var lastIncludedDir string + patternChars := "*[]?^" + if os.PathSeparator != '\\' { + patternChars += `\` + } + + onlyPrefixIncludes := true + if len(includePatterns) != 0 { + includeMatcher, err = fileutils.NewPatternMatcher(includePatterns) + if err != nil { + return errors.Wrapf(err, "invalid includepatterns: %s", opt.IncludePatterns) + } + + for _, p := range includeMatcher.Patterns() { + if !p.Exclusion() && strings.ContainsAny(patternWithoutTrailingGlob(p), patternChars) { + onlyPrefixIncludes = false + break + } + } + + } + + onlyPrefixExcludeExceptions := true + if opt != nil && opt.ExcludePatterns != nil { + excludeMatcher, err = fileutils.NewPatternMatcher(opt.ExcludePatterns) + if err != nil { + return errors.Wrapf(err, "invalid excludepatterns: %s", opt.ExcludePatterns) + } + + for _, p := range excludeMatcher.Patterns() { + if p.Exclusion() && strings.ContainsAny(patternWithoutTrailingGlob(p), patternChars) { + onlyPrefixExcludeExceptions = false + break + } + } + } + + type visitedDir struct { + fi os.FileInfo + path string + origpath string + pathWithSep string + includeMatchInfo fileutils.MatchInfo + excludeMatchInfo fileutils.MatchInfo + calledFn bool + } + + // used only for include/exclude handling + var parentDirs []visitedDir seenFiles := make(map[uint64]string) - return filepath.Walk(root, func(path string, fi os.FileInfo, err error) (retErr error) { + return filepath.Walk(root, func(path string, fi os.FileInfo, walkErr error) (retErr error) { defer func() { if retErr != nil && isNotExist(retErr) { retErr = filepath.SkipDir } }() - if err != nil { - return err - } origpath := path path, err = filepath.Rel(root, path) @@ -85,67 +123,125 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err return nil } - if opt != nil { - if includePatterns != nil { - skip := false - if lastIncludedDir != "" { - if strings.HasPrefix(path, lastIncludedDir+string(filepath.Separator)) { - skip = true - } - } + var dir visitedDir - if !skip { - matched := false - partial := true - for _, pattern := range includePatterns { - if ok, p := prefix.Match(pattern, path, false); ok { - matched = true - if !p { - partial = false - break - } - } - } - if !matched { - if fi.IsDir() { - return filepath.SkipDir - } - return nil - } - if !partial && fi.IsDir() { - lastIncludedDir = path - } + if includeMatcher != nil || excludeMatcher != nil { + for len(parentDirs) != 0 { + lastParentDir := parentDirs[len(parentDirs)-1].pathWithSep + if strings.HasPrefix(path, lastParentDir) { + break } + parentDirs = parentDirs[:len(parentDirs)-1] } - if pm != nil { - m, err := pm.Matches(path) - if err != nil { - return errors.Wrap(err, "failed to match excludepatterns") - } - if m { - if fi.IsDir() { - if !pm.Exclusions() { - return filepath.SkipDir - } - dirSlash := path + string(filepath.Separator) - for _, pat := range pm.Patterns() { - if !pat.Exclusion() { - continue - } - patStr := pat.String() + string(filepath.Separator) - if strings.HasPrefix(patStr, dirSlash) { - goto passedFilter - } - } - return filepath.SkipDir - } - return nil + if fi.IsDir() { + dir = visitedDir{ + fi: fi, + path: path, + origpath: origpath, + pathWithSep: path + string(filepath.Separator), } } } - passedFilter: + skip := false + + if includeMatcher != nil { + var parentIncludeMatchInfo fileutils.MatchInfo + if len(parentDirs) != 0 { + parentIncludeMatchInfo = parentDirs[len(parentDirs)-1].includeMatchInfo + } + m, matchInfo, err := includeMatcher.MatchesUsingParentResults(path, parentIncludeMatchInfo) + if err != nil { + return errors.Wrap(err, "failed to match includepatterns") + } + + if fi.IsDir() { + dir.includeMatchInfo = matchInfo + } + + if !m { + if fi.IsDir() && onlyPrefixIncludes { + // Optimization: we can skip walking this dir if no include + // patterns could match anything inside it. + dirSlash := path + string(filepath.Separator) + for _, pat := range includeMatcher.Patterns() { + if pat.Exclusion() { + continue + } + patStr := patternWithoutTrailingGlob(pat) + string(filepath.Separator) + if strings.HasPrefix(patStr, dirSlash) { + goto passedIncludeFilter + } + } + return filepath.SkipDir + } + passedIncludeFilter: + skip = true + } + } + + if excludeMatcher != nil { + var parentExcludeMatchInfo fileutils.MatchInfo + if len(parentDirs) != 0 { + parentExcludeMatchInfo = parentDirs[len(parentDirs)-1].excludeMatchInfo + } + m, matchInfo, err := excludeMatcher.MatchesUsingParentResults(path, parentExcludeMatchInfo) + if err != nil { + return errors.Wrap(err, "failed to match excludepatterns") + } + + if fi.IsDir() { + dir.excludeMatchInfo = matchInfo + } + + if m { + if fi.IsDir() && onlyPrefixExcludeExceptions { + // Optimization: we can skip walking this dir if no + // exceptions to exclude patterns could match anything + // inside it. + if !excludeMatcher.Exclusions() { + return filepath.SkipDir + } + + dirSlash := path + string(filepath.Separator) + for _, pat := range excludeMatcher.Patterns() { + if !pat.Exclusion() { + continue + } + patStr := patternWithoutTrailingGlob(pat) + string(filepath.Separator) + if strings.HasPrefix(patStr, dirSlash) { + goto passedExcludeFilter + } + } + return filepath.SkipDir + } + passedExcludeFilter: + skip = true + } + } + + if walkErr != nil { + if skip && errors.Is(walkErr, os.ErrPermission) { + return nil + } + return walkErr + } + + if includeMatcher != nil || excludeMatcher != nil { + defer func() { + if fi.IsDir() { + parentDirs = append(parentDirs, dir) + } + }() + } + + if skip { + return nil + } + + dir.calledFn = true + stat, err := mkstat(origpath, path, fi, seenFiles) if err != nil { return err @@ -160,6 +256,31 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err return nil } } + for i, parentDir := range parentDirs { + if parentDir.calledFn { + continue + } + parentStat, err := mkstat(parentDir.origpath, parentDir.path, parentDir.fi, seenFiles) + if err != nil { + return err + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if opt != nil && opt.Map != nil { + if allowed := opt.Map(parentStat.Path, parentStat); !allowed { + continue + } + } + + if err := fn(parentStat.Path, &StatInfo{parentStat}, nil); err != nil { + return err + } + parentDirs[i].calledFn = true + } if err := fn(stat.Path, &StatInfo{stat}, nil); err != nil { return err } @@ -168,6 +289,16 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err }) } +func patternWithoutTrailingGlob(p *fileutils.Pattern) string { + patStr := p.String() + // We use filepath.Separator here because fileutils.Pattern patterns + // get transformed to use the native path separator: + // https://github.com/moby/moby/blob/79651b7a979b40e26af353ad283ca7ea5d67a855/pkg/fileutils/fileutils.go#L54 + patStr = strings.TrimSuffix(patStr, string(filepath.Separator)+"**") + patStr = strings.TrimSuffix(patStr, string(filepath.Separator)+"*") + return patStr +} + type StatInfo struct { *types.Stat } diff --git a/vendor/modules.txt b/vendor/modules.txt index 4ad2da6860..c870625dae 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -737,11 +737,10 @@ github.com/tchap/go-patricia/patricia # github.com/tinylib/msgp v1.1.0 ## explicit github.com/tinylib/msgp/msgp -# github.com/tonistiigi/fsutil v0.0.0-20210609172227-d72af97c0eaf +# github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 ## explicit; go 1.13 github.com/tonistiigi/fsutil github.com/tonistiigi/fsutil/copy -github.com/tonistiigi/fsutil/prefix github.com/tonistiigi/fsutil/types # github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea ## explicit