Skip to content

Commit 8a1811e

Browse files
fix(server): branches whose names start with a parenthesis are no longer reported as detached (#35780)
1 parent 05cc444 commit 8a1811e

4 files changed

Lines changed: 16 additions & 8 deletions

File tree

‎apps/server/src/storageCleanup.test.ts‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,17 +2618,12 @@ describe("storage cleanup reports and local file policies", () => {
26182618
it.live("compares the checked-out branch without a full status", () =>
26192619
runCleanupTest(
26202620
Effect.gen(function* () {
2621-
const { service, fs, repo, worktree, command, setThreads, fullStatusCalls } =
2622-
yield* cleanupFixture();
2621+
const { service, fs, repo, worktree, command, fullStatusCalls } = yield* cleanupFixture();
26232622
const changed = { outcome: "kept", reason: "Repository or branch changed" };
26242623
yield* command(worktree, ["checkout", "--detach"]);
26252624
expect((yield* service.runNow).entries[0]).toMatchObject(changed);
26262625
yield* command(worktree, ["switch", "--orphan", "other"]);
26272626
expect((yield* service.runNow).entries[0]).toMatchObject(changed);
2628-
yield* command(worktree, ["switch", "-c", "(feature)", "feature"]);
2629-
setThreads([shell({ branch: "(feature)", worktreePath: worktree })]);
2630-
expect((yield* service.runNow).entries[0]).toMatchObject(changed);
2631-
setThreads([shell({ branch: "feature", worktreePath: worktree })]);
26322627
yield* command(worktree, ["tag", "feature", "feature"]);
26332628
// Newer Git refuses to create a tag named HEAD, but still reads one.
26342629
yield* command(worktree, ["update-ref", "refs/tags/HEAD", "refs/heads/feature"]);

‎apps/server/src/storageCleanup.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ const make = Effect.gen(function* () {
706706
if (head === null) return true;
707707
const ref = head.exitCode === 0 ? head.stdout.trim() : "";
708708
const name = ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length).trim() : null;
709-
return (name?.startsWith("(") ? null : name) !== branch;
709+
return name !== branch;
710710
});
711711

712712
// Git status and non-forced worktree removal both skip assume-unchanged and skip-worktree files.

‎apps/server/src/vcs/GitVcsDriverCore.test.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,19 @@ it.effect("reads the project's own repository when the server inherited GIT_DIR"
709709
).pipe(Effect.provide(layerTest)),
710710
);
711711

712+
it.effect("reads a branch whose name starts with a parenthesis as attached", () =>
713+
Effect.scoped(
714+
Effect.gen(function* () {
715+
const cwd = yield* makeTmpDir();
716+
yield* initRepoWithCommit(cwd);
717+
yield* git(cwd, ["switch", "-c", "(topic"]);
718+
const driver = yield* GitVcsDriver.GitVcsDriver;
719+
const status = yield* driver.statusDetailsLocal(cwd, { includeDivergence: false });
720+
assert.equal(status.branch, "(topic");
721+
}),
722+
).pipe(Effect.provide(layerTest)),
723+
);
724+
712725
it.effect.each(["on a branch", "detached", "unborn"] as const)(
713726
"reads only the repository root for review requests that ignore the branch when %s",
714727
(state) =>

‎apps/server/src/vcs/GitVcsDriverCore.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2322,7 +2322,7 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
23222322
const line = statusRecords[index]!;
23232323
if (line.startsWith("# branch.head ")) {
23242324
const value = line.slice("# branch.head ".length).trim();
2325-
refName = value.startsWith("(") ? null : value;
2325+
refName = value === "(detached)" ? null : value;
23262326
continue;
23272327
}
23282328
if (line.startsWith("# branch.upstream ")) {

0 commit comments

Comments
 (0)