mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-08 21:03:51 +02:00
Add a foreground-only test-drive workflow with isolated data, provider-backed CEO bootstrap, OpenCode/OpenRouter support, worktree execution setup, reuse safeguards, and delayed browser opening. Co-Authored-By: Paperclip <noreply@paperclip.ing>
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
|
|
export type GitWorkspaceInfo = {
|
|
root: string;
|
|
commonDir: string;
|
|
gitDir: string;
|
|
hooksPath: string;
|
|
};
|
|
|
|
/**
|
|
* Resolve the repository metadata Git exposes for both primary checkouts and
|
|
* linked worktrees. Returns null outside a Git working tree.
|
|
*/
|
|
export function detectGitWorkspaceInfo(cwd: string): GitWorkspaceInfo | null {
|
|
try {
|
|
const root = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
cwd,
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
}).trim();
|
|
const commonDirRaw = execFileSync("git", ["rev-parse", "--git-common-dir"], {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
}).trim();
|
|
const gitDirRaw = execFileSync("git", ["rev-parse", "--git-dir"], {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
}).trim();
|
|
const hooksPathRaw = execFileSync("git", ["rev-parse", "--git-path", "hooks"], {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
}).trim();
|
|
return {
|
|
root: path.resolve(root),
|
|
commonDir: path.resolve(root, commonDirRaw),
|
|
gitDir: path.resolve(root, gitDirRaw),
|
|
hooksPath: path.resolve(root, hooksPathRaw),
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function isLinkedGitWorktree(cwd: string): boolean {
|
|
const workspace = detectGitWorkspaceInfo(cwd);
|
|
return Boolean(workspace && workspace.gitDir !== workspace.commonDir);
|
|
}
|