* test(#4758): failing-first — rescue must resolve a relative worktree_path against repoRoot * fix(#4758): rescue resolves a relative worktree_path against repoRoot, not process.cwd() * test(#4758): review fold-ins — t.after cleanup pattern, post-resolution reader contract comment * chore(#4758): changeset fragment * chore(#4758): backfill changeset PR number (4872) * test(#4758): windows lanes key rescue fakes on resolved path identity, not verbatim strings win32 path.resolve rewrites driveless-absolute POSIX-style fixture values to the current drive, so the rescue's (correct) resolved-path handoff stopped matching verbatim string keys: #3804/#245/#2556/B7/#2852 fakes silently skipped the rescue and my seam test compared against a POSIX literal. Fakes now key on path.resolve(repoRoot, …) identity — the same semantics the code and git -C use — so every rescue test exercises the rescue on every platform. --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -926,7 +926,19 @@ function rescueSummaryArtifacts(
|
||||
const mkdirSync = deps.mkdirSync || ((d: string, o?: { recursive?: boolean }) => fs.mkdirSync(d, o));
|
||||
const copyFileSync = deps.copyFileSync || fs.copyFileSync;
|
||||
|
||||
const summaryPaths = findSummaryFiles(worktreePath);
|
||||
// #4758: resolve the manifest's worktree_path against repoRoot once, at this
|
||||
// boundary, so every reader of the field here — the fs walker below and the
|
||||
// `git -C` calls — resolves it the way the caller's git consumers already do
|
||||
// (`-C <path>` with `{ cwd: repoRoot }`). A relative value passed to the
|
||||
// walker verbatim made `path.join` emit a relative directory whose reads
|
||||
// resolved against process.cwd(), silently walking the wrong tree.
|
||||
// With this resolution, the remaining deps-injectable readers (existsSync,
|
||||
// readFileSync, mkdirSync, copyFileSync) only ever see absolute paths:
|
||||
// `dest` is built from repoRoot, `absPath` from the walker's join off this
|
||||
// resolved base.
|
||||
const resolvedWorktreePath = path.resolve(repoRoot, worktreePath);
|
||||
|
||||
const summaryPaths = findSummaryFiles(resolvedWorktreePath);
|
||||
const rescuedRelPaths = new Set<string>();
|
||||
const failures: Array<{ relPath: string; error: string }> = [];
|
||||
|
||||
@@ -934,7 +946,7 @@ function rescueSummaryArtifacts(
|
||||
// relPath is the path relative to the worktree root (e.g. ".planning/q1-SUMMARY.md")
|
||||
// Normalize to forward slashes so the Set comparison against `git status --porcelain`
|
||||
// output works on Windows too (git always emits forward slashes in porcelain output).
|
||||
const relPath = posixNormalize(absPath.slice(worktreePath.length).replace(/^[/\\]/, ''));
|
||||
const relPath = posixNormalize(absPath.slice(resolvedWorktreePath.length).replace(/^[/\\]/, ''));
|
||||
|
||||
// #706: skip rescue when the SUMMARY is already committed on the branch.
|
||||
// Use `git cat-file -e HEAD:<relPath>` (not `ls-files --error-unmatch`) so
|
||||
@@ -953,7 +965,7 @@ function rescueSummaryArtifacts(
|
||||
// copy when the main tree already holds identical content (which is also what
|
||||
// guards the #706 merge collision). A divergent dest is overwritten, but only
|
||||
// uncommitted main-tree content could be lost (committed content is git-recoverable).
|
||||
const catFileResult = execGit(['-C', worktreePath, 'cat-file', '-e', `HEAD:${relPath}`], { cwd: repoRoot });
|
||||
const catFileResult = execGit(['-C', resolvedWorktreePath, 'cat-file', '-e', `HEAD:${relPath}`], { cwd: repoRoot });
|
||||
if (catFileResult.exitCode === 0) {
|
||||
// exit 0 → the SUMMARY is committed on HEAD; the merge will carry it, so skip rescue.
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user