fix(build): strip Windows verbatim \?\ prefix from registry common_dir#528
Conversation
`std::fs::canonicalize` emits verbatim (`\\?\C:\...`) paths on Windows. The build path stored that string as a repo's `common_dir`; resolving `--repo <name>` then derived `worktree_root` from it and fed the verbatim path into `ignore::WalkBuilder` / `git archive`, which treat the `.git` file component as a directory and fail with ERROR_DIRECTORY (os error 267). The cwd path (no `--repo`) was unaffected because its worktree root is already plain. - orchestrator: write `common_dir` via `dunce::canonicalize` so new registry entries are plain from the start (root cause). - git_cache: `worktree_root_from_common_dir` runs `dunce::simplified` so registries already polluted with a verbatim prefix resolve correctly without a rebuild (defensive; no-op on non-Windows and on already-plain paths). - tests: cross-platform coverage plus Windows-gated cases for the verbatim disk prefix and idempotent plain-path passthrough. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Unified Code Review — PR #528Risk: MEDIUM (Windows-only; build pipeline + Root cause analysis is correct and independently confirmed: Found 1 issue:
Nit (non-blocking): PR body carries a |
…ing helper Three call sites derived the worktree root by open-coding common_dir.parent(), bypassing worktree_root_from_common_dir (and thus its dunce::simplified call). A registry holding a Windows verbatim \?\ common_dir therefore still fed a verbatim path into a filesystem walk / git subprocess, repeating os error 267: - summary.rs -> ensure_index -> any_source_newer_than -> WalkBuilder (ecp summary) - group/sync.rs -> walk_and_extract -> WalkDir (ecp group sync) - group/status.rs -> git -C repo_root (ecp group status) Route all three through git_cache::worktree_root_from_common_dir so the verbatim prefix is stripped on the read side, consistent with the main-line find / group-impact / pre_tool_use query paths. No-op on non-Windows.
ecp impact cache (0 symbols) — internal, used by
|
Problem
On Windows,
ecp <cmd> --repo <name>fails with:os error 267isERROR_DIRECTORY/ENOTDIR. The same command via cwd(
cdinto the repo, no--repo) works fine — so it is not a CJK path, not acorrupt index, and not a registry-corruption issue (
doctorreports theregistry clean).
Root cause
std::fs::canonicalizereturns a verbatim path on Windows(
\\?\C:\...).git_common_dir_string(build path) stored that verbatimstring into the registry's
common_dir:Resolving
--repo <name>derivesworktree_rootby taking the parent ofcommon_dirand hands it toensure_fresh/build_l2. The verbatim prefixflows into
ignore::WalkBuilderandgit archive, which treat the.gitfile component as a directory and bail out with
ERROR_DIRECTORY(267).The cwd path never hit this because its worktree root comes from
current_dir— a plain path.Fix
Two points, so the bug is both prevented and recoverable without a rebuild:
build/orchestrator.rscommon_dirviadunce::canonicalizegit_cache.rsworktree_root_from_common_dirrunsdunce::simplifiedupdate_repo_metaonly writescommon_diron first build, so existing reposkeep their old verbatim value — the read-side
simplifiedis what unblocksthose without forcing a rebuild. Both
duncecalls are no-ops on non-Windowsand on already-plain paths (
simplifiedreturns a borrowed sub-slice, zeroalloc).
Deliberately not touched:
head_sha_hex'sstd::fs::canonicalize(orchestrator.rs:368) only feeds an xxhash digest for cache identity — it
never reaches the build pipeline, and it must stay byte-identical to the
matching digest in
git_cache.rsso existing non-git caches remain valid.Tests
worktree_root_drops_dot_git_component,worktree_root_falls_back_when_no_parent— cross-platform.worktree_root_strips_verbatim_disk_prefix,worktree_root_leaves_plain_path_untouched—#[cfg(windows)].cargo test -p egent-code-plexusgreen;repo_selector(18) andbuild_orchestratorsuites unaffected.🤖 Generated with Claude Code