fix(bins): Windows-safe GIT_CEILING join; next-version probes the full default-base chain

GIT_CEILING_DIRECTORIES was joined with ':' — git on Windows splits on
';' and drive letters contain ':', silently disabling the #2144
second-layer defense there; now path.delimiter. next-version's
default-base detection only tried origin/HEAD then 'main', diverging
from the canonical 4-step chain diff-scope uses — origin/main and
origin/master probes added, pinned by fixture repos.
This commit is contained in:
Garry Tan
2026-08-14 17:15:48 -07:00
parent 2fd506a4e0
commit c9215c438c
3 changed files with 122 additions and 5 deletions
+19 -3
View File
@@ -407,13 +407,29 @@ function parseArgs(argv: string[]): { base: string; bump: Bump; current: string;
if (help) return { base: "", bump: "micro", current: "", excludePR: null, help: true };
if (!base) {
// Detect the default branch instead of assuming main (local-only repos
// on trunk/master work like GitHub repos on main).
// on trunk/master work like GitHub repos on main). Same probe order as
// the canonical chain in bin/gstack-diff-scope and {{BASE_BRANCH_DETECT}}
// (scripts/resolvers/utility.ts): origin/HEAD -> origin/main ->
// origin/master -> literal "main". origin/HEAD is unset on plain clones
// that never ran `git remote set-head`, so the rev-parse probes matter.
try {
const head = execFileSync("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim();
base = head.replace("refs/remotes/origin/", "") || "main";
base = head.replace("refs/remotes/origin/", "");
} catch {
base = "main";
// fall through to the rev-parse probes
}
if (!base) {
for (const candidate of ["main", "master"]) {
try {
execFileSync("git", ["rev-parse", "--verify", "-q", `origin/${candidate}`], { stdio: ["ignore", "ignore", "ignore"] });
base = candidate;
break;
} catch {
// probe failed; try the next candidate
}
}
}
if (!base) base = "main";
}
if (!bump) {
console.error("Error: --bump is required (major|minor|patch|micro)");