From 41fab55e0d18540b64bdd7878880d911a0995e5f Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Mon, 9 Mar 2026 10:44:48 +0100 Subject: [PATCH] fix: set fetch and derive repo name --- package.json | 2 +- src/commands/add.ts | 8 ++++++-- src/commands/clone.test.ts | 2 +- src/commands/clone.ts | 13 +++++++++++-- src/commands/remove.ts | 5 +++-- src/repo.ts | 10 +++++++++- src/workspace.ts | 12 +++++++----- 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index f681fa5..0803b64 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "git-witty", "bin": { - "git-witty": "./src/index.ts" + "git-witty": "dist/git-witty" }, "module": "src/index.ts", "type": "module", diff --git a/src/commands/add.ts b/src/commands/add.ts index 8a1111d..05c6d8e 100644 --- a/src/commands/add.ts +++ b/src/commands/add.ts @@ -1,12 +1,16 @@ import { join } from "node:path"; import { $ } from "bun"; -import { getRepoRoot } from "../repo"; +import { getRepoName, getRepoRoot } from "../repo"; import { addFolder } from "../workspace"; export async function add({ branch }: { branch: string }) { const root = await getRepoRoot(); + const repoName = await getRepoName(); const worktreePath = join(root, branch); await $`git worktree add ${worktreePath}`; - await addFolder(root, worktreePath); + await $`git -C ${worktreePath} branch --set-upstream-to=origin/${branch}` + .quiet() + .nothrow(); + await addFolder(root, repoName, worktreePath); } diff --git a/src/commands/clone.test.ts b/src/commands/clone.test.ts index ba6f6ce..17039a4 100644 --- a/src/commands/clone.test.ts +++ b/src/commands/clone.test.ts @@ -92,7 +92,7 @@ test("clone creates a workspace file", async () => { await sh`git -C ${target}/.bare symbolic-ref --short HEAD`.text() ).trim(); - const wsFile = Bun.file(join(tempDir, target, `${target}.code-workspace`)); + const wsFile = Bun.file(join(tempDir, target, `${origin}.code-workspace`)); expect(await wsFile.exists()).toBe(true); const workspace = await wsFile.json(); diff --git a/src/commands/clone.ts b/src/commands/clone.ts index 94f4c05..de092d8 100644 --- a/src/commands/clone.ts +++ b/src/commands/clone.ts @@ -4,7 +4,8 @@ import { addFolder } from "../workspace"; import { installHook } from "./init"; export async function clone({ url, name }: { url: string; name?: string }) { - name ??= repoNameFromUrl(url); + const repoName = repoNameFromUrl(url); + name ??= repoName; const root = resolve(name); const bareDir = `${root}/.bare`; @@ -12,6 +13,13 @@ export async function clone({ url, name }: { url: string; name?: string }) { console.log(`Cloning ${url} into ${root}...`); await $`git clone --bare ${url} ${bareDir}`; + // Bare clones need this to fetch all branches + await $`git -C ${bareDir} config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"`; + await $`git -C ${bareDir} fetch origin`; + + // Make the setup portable (can move the folder) + await $`git -C ${bareDir} config worktree.useRelativePaths true`; + // Create .git file pointing to the bare repo await Bun.write(`${root}/.git`, "gitdir: ./.bare\n"); @@ -23,7 +31,8 @@ export async function clone({ url, name }: { url: string; name?: string }) { // Create the first worktree const worktreePath = resolve(root, primaryBranch); await $`git -C ${bareDir} worktree add ${worktreePath}`; - await addFolder(root, worktreePath); + await $`git -C ${worktreePath} branch --set-upstream-to=origin/${primaryBranch}`; + await addFolder(root, repoName, worktreePath); // Install git-witty hooks await installHook({ bareDir }); diff --git a/src/commands/remove.ts b/src/commands/remove.ts index ccbd56e..74f970f 100644 --- a/src/commands/remove.ts +++ b/src/commands/remove.ts @@ -1,12 +1,13 @@ import { join } from "node:path"; import { $ } from "bun"; -import { getRepoRoot } from "../repo"; +import { getRepoName, getRepoRoot } from "../repo"; import { removeFolder } from "../workspace"; export async function remove({ branch }: { branch: string }) { const root = await getRepoRoot(); + const repoName = await getRepoName(); const worktreePath = join(root, branch); await $`git worktree remove ${worktreePath}`; - await removeFolder(root, worktreePath); + await removeFolder(root, repoName, worktreePath); } diff --git a/src/repo.ts b/src/repo.ts index 3b68b76..4c4287c 100644 --- a/src/repo.ts +++ b/src/repo.ts @@ -1,4 +1,4 @@ -import { dirname } from "node:path"; +import { basename, dirname } from "node:path"; import { $ } from "bun"; /** @@ -10,3 +10,11 @@ export async function getRepoRoot(): Promise { // gitCommonDir points to .bare — the repo root is its parent return dirname(gitCommonDir); } + +/** + * Returns the repository name derived from the remote origin URL. + */ +export async function getRepoName(): Promise { + const url = (await $`git remote get-url origin`.text()).trim(); + return basename(url).replace(/\.git$/, ""); +} diff --git a/src/workspace.ts b/src/workspace.ts index 9c76edf..46ee7ab 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -1,4 +1,4 @@ -import { basename, relative } from "node:path"; +import { relative } from "node:path"; interface WorkspaceFolder { path: string; @@ -9,8 +9,8 @@ interface WorkspaceFile { [key: string]: unknown; } -export function workspacePath(root: string): string { - return `${root}/${basename(root)}.code-workspace`; +export function workspacePath(root: string, repoName: string): string { + return `${root}/${repoName}.code-workspace`; } async function read(path: string): Promise { @@ -27,9 +27,10 @@ async function write(path: string, workspace: WorkspaceFile): Promise { export async function addFolder( root: string, + repoName: string, worktreePath: string, ): Promise { - const wsPath = workspacePath(root); + const wsPath = workspacePath(root, repoName); const workspace = await read(wsPath); const rel = relative(root, worktreePath); @@ -44,9 +45,10 @@ export async function addFolder( export async function removeFolder( root: string, + repoName: string, worktreePath: string, ): Promise { - const wsPath = workspacePath(root); + const wsPath = workspacePath(root, repoName); const workspace = await read(wsPath); const rel = relative(root, worktreePath);