diff --git a/cache/contenthash/path.go b/cache/contenthash/path.go index ae950f7132413..dfb6bbc667b4c 100644 --- a/cache/contenthash/path.go +++ b/cache/contenthash/path.go @@ -8,6 +8,7 @@ package contenthash import ( + "fmt" "os" "path/filepath" "strings" @@ -19,6 +20,10 @@ var errTooManyLinks = errors.New("too many links") const maxSymlinkLimit = 255 +var logFn = func(format string, v ...interface{}) { + fmt.Fprintf(os.Stderr, format, v...) +} + type onSymlinkFunc func(string, string) error // rootPath joins a path with a root, evaluating and bounding any symlink to @@ -35,9 +40,13 @@ func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (s currentPath string linksWalked int ) + logFn("rootPath(%s, %s, %v)\n", root, unsafePath, followTrailing) for unsafePath != "" { + logFn("-- loop --\ncurrentPath: %s\nunsafePath: %s\n", currentPath, unsafePath) + // Windows-specific: remove any drive letters from the path. if v := filepath.VolumeName(unsafePath); v != "" { + logFn("unsafePath %s -> [%s] %s\n", unsafePath, v, unsafePath[len(v):]) unsafePath = unsafePath[len(v):] } @@ -51,11 +60,13 @@ func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (s } else { part, unsafePath = unsafePath[:i], unsafePath[i+1:] } + logFn("unsafePath -> (%s, %s)\n", part, unsafePath) // Apply the component lexically to the path we are building. path does // not contain any symlinks, and we are lexically dealing with a single // component, so it's okay to do filepath.Clean here. nextPath := filepath.Join(string(filepath.Separator), currentPath, part) + logFn("nextPath <- %s\n", nextPath) if nextPath == string(filepath.Separator) { // If we end up back at the root, we don't need to re-evaluate /. currentPath = "" @@ -65,6 +76,7 @@ func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (s // Figure out whether the path is a symlink. fi, err := os.Lstat(fullPath) + logFn("Lstat(%s) -> %v, %v\n", fullPath, fi, err) if err != nil && !errors.Is(err, os.ErrNotExist) { return "", err } @@ -88,6 +100,7 @@ func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (s } dest, err := os.Readlink(fullPath) + logFn("Readlink(%s) -> %v, %v\n", fullPath, dest, err) if err != nil { return "", err } @@ -97,6 +110,7 @@ func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (s } } + logFn("unsafePath <- %s + %s\n", dest, unsafePath) unsafePath = dest + string(filepath.Separator) + unsafePath // Absolute symlinks reset any work we've already done. if filepath.IsAbs(dest) { diff --git a/cache/contenthash/path_test.go b/cache/contenthash/path_test.go index f59e17e6939f9..135e59858c3d6 100644 --- a/cache/contenthash/path_test.go +++ b/cache/contenthash/path_test.go @@ -12,7 +12,6 @@ import ( ) func TestRootPathSymlinks(t *testing.T) { - t.Parallel() tmpdir := t.TempDir() // Make the following tree: @@ -106,12 +105,14 @@ func TestRootPathSymlinks(t *testing.T) { } { test := test // capture range variable t.Run(fmt.Sprintf("resolve(%q,followTrailing=%v)", test.path, test.followTrailing), func(t *testing.T) { - t.Parallel() + logFn = func(fmt string, v ...interface{}) { + t.Logf(fmt, v...) + } resolvedPath, err := rootPath(tmpdir, test.path, test.followTrailing, nil) require.NoError(t, err) - expectedPath := filepath.Join(tmpdir, test.expected) + expectedPath := filepath.Join(tmpdir, filepath.FromSlash(test.expected)) require.Equal(t, expectedPath, resolvedPath) }) }