Fix worktree checkout validation for existing git branch refs (#1358)

* fix(server): allow valid existing worktree branch refs (#1357)

* Fix existing branch checkout validation

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
dixonl90
2026-06-05 23:31:38 +08:00
committed by GitHub
co-authored by Mohamed Boudra
parent 44e9287389
commit d454fa3af4
2 changed files with 125 additions and 2 deletions
+23 -2
View File
@@ -206,6 +206,16 @@ export class UnknownBranchError extends Error {
}
}
export class InvalidGitBranchNameError extends Error {
readonly branchName: string;
constructor(branchName: string) {
super(`Invalid branch name: Git rejected ref name '${branchName}'`);
this.name = "InvalidGitBranchNameError";
this.branchName = branchName;
}
}
export type ReadPaseoConfigResult =
| { ok: true; config: PaseoConfig | null }
| { ok: false; configPath: string; error: unknown };
@@ -1261,7 +1271,7 @@ async function resolveWorktreeSourcePlan({
};
}
case "checkout-branch": {
validateWorktreeBranchName(source.branchName);
await validateExistingWorktreeBranchName(cwd, source.branchName);
if (!(await localBranchExists(cwd, source.branchName))) {
try {
await runGitCommand(["fetch", "origin", `${source.branchName}:${source.branchName}`], {
@@ -1284,7 +1294,7 @@ async function resolveWorktreeSourcePlan({
}
case "checkout-github-pr": {
const localBranchCandidate = source.localBranchName ?? source.headRef;
validateWorktreeBranchName(localBranchCandidate);
await validateExistingWorktreeBranchName(cwd, localBranchCandidate);
const localBranchName = await resolveUniqueLocalBranchName(cwd, localBranchCandidate);
const normalizedBaseRefName = normalizeRequiredBaseBranch(source.baseRefName);
await runGitCommand(
@@ -1350,6 +1360,17 @@ function validateWorktreeBranchName(branchName: string): void {
}
}
async function validateExistingWorktreeBranchName(cwd: string, branchName: string): Promise<void> {
const result = await runGitCommand(["check-ref-format", "--branch", branchName], {
cwd,
timeout: 30_000,
acceptExitCodes: [0, 1, 128],
});
if (result.exitCode !== 0) {
throw new InvalidGitBranchNameError(branchName);
}
}
function normalizeRequiredBaseBranch(baseBranch: string): string {
const normalizedBaseBranch = normalizeBaseRefName(baseBranch);
if (!normalizedBaseBranch) {