Skip to content

Commit c2c51bf

Browse files
Merge pull request #5 from CodeBoarding/example/worktree-detect
feat(coding-agent): detect linked git worktrees (stack 1/2)
2 parents e239f5f + 31381bf commit c2c51bf

4 files changed

Lines changed: 38 additions & 2 deletions

File tree

‎packages/coding-agent/src/core/footer-data-provider.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type ExecFileException, execFile, spawnSync } from "child_process";
22
import { existsSync, type FSWatcher, readFileSync, type Stats, statSync, unwatchFile, watchFile } from "fs";
33
import { dirname, join, resolve } from "path";
44
import { closeWatcher, FS_WATCH_RETRY_DELAY_MS, watchWithErrorHandler } from "../utils/fs-watch.ts";
5+
import { linkedWorktreeName } from "./git-worktree.ts";
56

67
export type GitPaths = {
78
repoDir: string;
@@ -131,6 +132,11 @@ export class FooterDataProvider {
131132
return this.cachedBranch;
132133
}
133134

135+
/** Linked worktree name, null in the main checkout or outside a repo */
136+
getWorktreeName(): string | null {
137+
return this.gitPaths ? linkedWorktreeName(this.gitPaths) : null;
138+
}
139+
134140
/** Extension status texts set via ctx.ui.setStatus() */
135141
getExtensionStatuses(): ReadonlyMap<string, string> {
136142
return this.extensionStatuses;
@@ -384,5 +390,5 @@ export class FooterDataProvider {
384390
/** Read-only view for extensions - excludes setExtensionStatus, setAvailableProviderCount and dispose */
385391
export type ReadonlyFooterDataProvider = Pick<
386392
FooterDataProvider,
387-
"getGitBranch" | "getExtensionStatuses" | "getAvailableProviderCount" | "onBranchChange"
393+
"getGitBranch" | "getWorktreeName" | "getExtensionStatuses" | "getAvailableProviderCount" | "onBranchChange"
388394
>;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { basename, dirname, resolve } from "path";
2+
import type { GitPaths } from "./footer-data-provider.ts";
3+
4+
/**
5+
* Name of the linked worktree that `paths` belongs to, or null for the main checkout.
6+
* A linked worktree's HEAD lives under `<common>/worktrees/<name>/`, apart from the shared git dir.
7+
*/
8+
export function linkedWorktreeName(paths: GitPaths): string | null {
9+
const gitDir = resolve(dirname(paths.headPath));
10+
if (gitDir === resolve(paths.commonGitDir)) return null;
11+
return basename(paths.repoDir);
12+
}

‎packages/coding-agent/test/footer-width.test.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ function createSession(options: {
9292
return session as unknown as AgentSession;
9393
}
9494

95-
function createFooterData(providerCount: number): ReadonlyFooterDataProvider {
95+
function createFooterData(providerCount: number, worktree: string | null = null): ReadonlyFooterDataProvider {
9696
const provider = {
9797
getGitBranch: () => "main",
98+
getWorktreeName: () => worktree,
9899
getExtensionStatuses: () => new Map<string, string>(),
99100
getAvailableProviderCount: () => providerCount,
100101
onBranchChange: (callback: () => void) => {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { join } from "path";
2+
import { describe, expect, it } from "vitest";
3+
import { linkedWorktreeName } from "../src/core/git-worktree.ts";
4+
5+
describe("linkedWorktreeName", () => {
6+
it("returns null for the main checkout", () => {
7+
const repoDir = join("/repo", "app");
8+
const commonGitDir = join(repoDir, ".git");
9+
expect(linkedWorktreeName({ repoDir, commonGitDir, headPath: join(commonGitDir, "HEAD") })).toBeNull();
10+
});
11+
12+
it("names a linked worktree after its directory", () => {
13+
const commonGitDir = join("/repo", "app", ".git");
14+
const headPath = join(commonGitDir, "worktrees", "feature-x", "HEAD");
15+
expect(linkedWorktreeName({ repoDir: join("/repo", "feature-x"), commonGitDir, headPath })).toBe("feature-x");
16+
});
17+
});

0 commit comments

Comments
 (0)