From 4035d0b5961fcb692098f9e908faa8313c4b58b4 Mon Sep 17 00:00:00 2001 From: Min Huang <70873102+min0625@users.noreply.github.com> Date: Thu, 2 Jul 2026 06:14:21 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20update=20error=20hints=20to=20refere?= =?UTF-8?q?nce=20`subdir`=20after=20path=E2=86=92subdir=20rename?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hints in fetcher and hasher still told users to check a mistyped `path` in the manifest, but the field was renamed to `subdir` in #31. Co-Authored-By: Claude Fable 5 --- internal/fetcher/fetcher.go | 4 ++-- internal/hasher/hasher.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/fetcher/fetcher.go b/internal/fetcher/fetcher.go index 7b6844c..5e17b2a 100644 --- a/internal/fetcher/fetcher.go +++ b/internal/fetcher/fetcher.go @@ -48,7 +48,7 @@ func Fetch(ctx context.Context, cacheRoot, name, repo, commit, version, path, ds if !ok { return time.Time{}, clierr.New(clierr.CodeConfig, fmt.Sprintf("path %q of dependency %q not found at commit %.12s", path, name, commit), - "an empty or missing path is almost always a mistyped `path` — check the manifest", + "an empty or missing path is almost always a mistyped `subdir` — check the manifest", ) } } @@ -75,7 +75,7 @@ func Fetch(ctx context.Context, cacheRoot, name, repo, commit, version, path, ds if info, err := os.Stat(treeRoot); err != nil || !info.IsDir() { return time.Time{}, clierr.New(clierr.CodeConfig, fmt.Sprintf("path %q of dependency %q not found at commit %.12s", path, name, commit), - "an empty or missing path is almost always a mistyped `path` — check the manifest", + "an empty or missing path is almost always a mistyped `subdir` — check the manifest", ) } } diff --git a/internal/hasher/hasher.go b/internal/hasher/hasher.go index e72a185..5a272c1 100644 --- a/internal/hasher/hasher.go +++ b/internal/hasher/hasher.go @@ -165,7 +165,7 @@ func HashTree(root string) (string, error) { if len(digests) == 0 { return "", clierr.New(clierr.CodeConfig, "the dependency tree contains no files", - "an empty dependency is almost always a mistyped `path` — check the manifest", + "an empty dependency is almost always a mistyped `subdir` — check the manifest", ) } From c29bdcfde1f2e38cc7b24a1bf6f1f5487ee73318 Mon Sep 17 00:00:00 2001 From: Min Huang <70873102+min0625@users.noreply.github.com> Date: Thu, 2 Jul 2026 06:20:43 +0000 Subject: [PATCH 2/2] test: cover the subdir-is-a-file branch in fetcher Codecov flagged the post-checkout "not a directory" branch as the only uncovered line of the patch; exercise it with a subdir that points at a blob, which passes the ls-tree existence check. Co-Authored-By: Claude Fable 5 --- internal/fetcher/fetcher.go | 8 ++++---- internal/fetcher/fetcher_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/internal/fetcher/fetcher.go b/internal/fetcher/fetcher.go index 5e17b2a..99e8202 100644 --- a/internal/fetcher/fetcher.go +++ b/internal/fetcher/fetcher.go @@ -47,8 +47,8 @@ func Fetch(ctx context.Context, cacheRoot, name, repo, commit, version, path, ds if !ok { return time.Time{}, clierr.New(clierr.CodeConfig, - fmt.Sprintf("path %q of dependency %q not found at commit %.12s", path, name, commit), - "an empty or missing path is almost always a mistyped `subdir` — check the manifest", + fmt.Sprintf("subdir %q of dependency %q not found at commit %.12s", path, name, commit), + "an empty or missing subdir is almost always a typo — check the manifest", ) } } @@ -74,8 +74,8 @@ func Fetch(ctx context.Context, cacheRoot, name, repo, commit, version, path, ds if info, err := os.Stat(treeRoot); err != nil || !info.IsDir() { return time.Time{}, clierr.New(clierr.CodeConfig, - fmt.Sprintf("path %q of dependency %q not found at commit %.12s", path, name, commit), - "an empty or missing path is almost always a mistyped `subdir` — check the manifest", + fmt.Sprintf("subdir %q of dependency %q is not a directory at commit %.12s", path, name, commit), + "a subdir must point at a directory in the dependency repo — check the manifest", ) } } diff --git a/internal/fetcher/fetcher_test.go b/internal/fetcher/fetcher_test.go index 0c757c6..5293c78 100644 --- a/internal/fetcher/fetcher_test.go +++ b/internal/fetcher/fetcher_test.go @@ -171,6 +171,21 @@ func TestFetch_missingPath(t *testing.T) { } } +func TestFetch_pathIsFile(t *testing.T) { + t.Parallel() + + r := gittest.New(t) + r.WriteFile("a.txt", "x\n") + sha := r.Commit("first") + + // ls-tree reports the blob, so the pre-checkout existence check passes and + // the "not a directory" branch after checkout must catch it. + _, err := fetcher.Fetch(t.Context(), cacheRoot(t), depName, r.URL(), sha, "", "a.txt", fetchDst(t)) + if got := clierr.ExitCode(err); got != int(clierr.CodeConfig) { + t.Fatalf("exit code = %d, want %d (error: %v)", got, clierr.CodeConfig, err) + } +} + func TestFetch_commitGone(t *testing.T) { t.Parallel()