Something went wrong. Try again.
presents omp as codex for use with chatgpt remote
Something went wrong. Try again.
8.6 kB · 212 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213import { createHash } from "node:crypto";import { spawn } from "node:child_process";import fs from "node:fs/promises";import path from "node:path";import { promisify } from "node:util";import { execFile } from "node:child_process";
const execFileAsync = promisify(execFile);
function workspaceName(targetPath) { const digest = createHash("sha256").update(path.resolve(targetPath)).digest("hex").slice(0, 16); const base = path.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 20) || "workspace"; return `codex_${digest}_${base}`;}
function optionTakesValue(arg) { return arg === "-C" || arg === "-c" || arg === "--git-dir" || arg === "--work-tree" || arg === "--namespace" || arg === "--super-prefix" || arg === "--config-env";}
export function parseWorktreeCommand(args, initialCwd = process.cwd()) { let cwd = path.resolve(initialCwd); let commandIndex = -1;
for (let index = 0; index < args.length; index += 1) { const arg = args[index]; if (arg === "worktree") { commandIndex = index; break; } if (arg === "-C" && args[index + 1]) { cwd = path.resolve(cwd, args[index + 1]); index += 1; continue; } if (optionTakesValue(arg)) index += 1; }
if (commandIndex < 0) return null; const subcommand = args[commandIndex + 1]; if (subcommand !== "add" && subcommand !== "remove") return null;
const positional = []; const worktreeArgs = args.slice(commandIndex + 2); for (let index = 0; index < worktreeArgs.length; index += 1) { const arg = worktreeArgs[index]; if (arg === "--") { positional.push(...worktreeArgs.slice(index + 1)); break; } if (arg === "-b" || arg === "-B" || arg === "--reason") { index += 1; continue; } if (arg.startsWith("--reason=")) continue; if (arg.startsWith("-")) continue; positional.push(arg); }
return { cwd, subcommand, force: worktreeArgs.includes("-f") || worktreeArgs.includes("--force"), targetPath: positional[0] ? path.resolve(cwd, positional[0]) : null, revision: subcommand === "add" ? positional[1] || "HEAD" : null, };}
async function commandOutput(command, args, options = {}) { const { stdout } = await execFileAsync(command, args, { cwd: options.cwd, env: options.env || process.env, timeout: options.timeout || 10_000, maxBuffer: 4 * 1024 * 1024, }); return stdout.trim();}
async function findJjRoot(jj, cwd) { try { const root = await commandOutput(jj, ["root", "-R", cwd], { timeout: 3_000 }); return root ? path.resolve(root) : null; } catch { return null; }}
async function appendGitExclude(commonDir) { const excludePath = path.join(commonDir, "info", "exclude"); await fs.mkdir(path.dirname(excludePath), { recursive: true }); const current = await fs.readFile(excludePath, "utf8").catch(() => ""); const lines = new Set(current.split(/\r?\n/)); if (lines.has(".jj") && lines.has(".jj/")) return; const separator = current.length > 0 && !current.endsWith("\n") ? "\n" : ""; await fs.appendFile(excludePath, `${separator}.jj\n.jj/\n`);}
async function resolveGitCommonDir(realGit, cwd) { const raw = await commandOutput(realGit, ["-C", cwd, "rev-parse", "--git-common-dir"]); return path.resolve(cwd, raw);}
async function resolveRevision(realGit, cwd, revision) { return commandOutput(realGit, ["-C", cwd, "rev-parse", "--verify", `${revision}^{commit}`]);}
async function createJjWorkspace({ jj, realGit, jjRoot, cwd, targetPath, revision }) { if (!targetPath) throw new Error("git worktree add did not specify a destination"); if (path.resolve(targetPath) === path.resolve(jjRoot)) throw new Error("refusing to replace the source Jujutsu workspace");
const targetStat = await fs.stat(targetPath).catch(() => null); if (targetStat) { if (!targetStat.isDirectory()) throw new Error(`worktree destination is not a directory: ${targetPath}`); const entries = await fs.readdir(targetPath); if (entries.length > 0) throw new Error(`worktree destination is not empty: ${targetPath}`); await fs.rmdir(targetPath); } await fs.mkdir(path.dirname(targetPath), { recursive: true });
const commit = await resolveRevision(realGit, cwd, revision); const name = workspaceName(targetPath); const commonDir = await resolveGitCommonDir(realGit, jjRoot); const gitDir = path.join(commonDir, "worktrees", name); if (await fs.stat(gitDir).catch(() => null)) { throw new Error(`Git compatibility directory already exists: ${gitDir}`); }
let workspaceCreated = false; try { await execFileAsync(jj, ["workspace", "add", "--name", name, "-r", commit, targetPath, "-R", jjRoot], { cwd: jjRoot, timeout: 15_000, }); workspaceCreated = true;
await fs.mkdir(path.dirname(gitDir), { recursive: true }); await fs.mkdir(gitDir); await fs.writeFile(path.join(gitDir, "gitdir"), `${path.join(targetPath, ".git")}\n`); await fs.writeFile(path.join(gitDir, "commondir"), "../../\n"); await fs.writeFile(path.join(gitDir, "HEAD"), `${commit}\n`); await fs.writeFile(path.join(gitDir, "omp-codex-jj-workspace"), `${name}\n`); await fs.writeFile(path.join(targetPath, ".git"), `gitdir: ${gitDir}\n`); await appendGitExclude(commonDir); await execFileAsync(realGit, ["-C", targetPath, "reset", "--mixed", "HEAD"], { timeout: 10_000 }); process.stdout.write(`Preparing Jujutsu workspace (detached HEAD ${commit.slice(0, 12)})\n`); } catch (error) { await fs.rm(gitDir, { recursive: true, force: true }).catch(() => {}); if (workspaceCreated) { await execFileAsync(jj, ["workspace", "forget", name, "-R", jjRoot], { cwd: jjRoot, timeout: 5_000 }).catch(() => {}); await fs.rm(targetPath, { recursive: true, force: true }).catch(() => {}); } throw error; }}
async function removeJjWorkspace({ jj, realGit, jjRoot, targetPath, force }) { if (!targetPath) throw new Error("git worktree remove did not specify a destination"); if (path.resolve(targetPath) === path.resolve(jjRoot)) throw new Error("refusing to remove the source Jujutsu workspace");
const name = workspaceName(targetPath); const commonDir = await resolveGitCommonDir(realGit, jjRoot); const gitDir = path.join(commonDir, "worktrees", name); const registeredGitFile = await fs.readFile(path.join(gitDir, "gitdir"), "utf8").catch(() => ""); const expectedGitFile = path.join(targetPath, ".git"); if (path.resolve(registeredGitFile.trim()) !== path.resolve(expectedGitFile)) return false;
const markerExists = await fs.stat(path.join(gitDir, "omp-codex-jj-workspace")).then(() => true).catch(() => false); const jjPointerExists = await fs.stat(path.join(targetPath, ".jj")).then((stat) => stat.isDirectory()).catch(() => false); const gitPointer = await fs.readFile(expectedGitFile, "utf8").catch(() => ""); const ownsTarget = markerExists || (jjPointerExists && gitPointer.trim() === `gitdir: ${gitDir}`); if (!ownsTarget) return false;
if (!force && await fs.stat(targetPath).then(() => true).catch(() => false)) { const status = await commandOutput(realGit, ["-C", targetPath, "status", "--porcelain"]); if (status) throw new Error(`'${targetPath}' contains modified or untracked files; use --force to delete it`); }
await execFileAsync(jj, ["workspace", "forget", name, "-R", jjRoot], { cwd: jjRoot, timeout: 5_000 }); await fs.rm(gitDir, { recursive: true, force: true }); await fs.rm(targetPath, { recursive: true, force: true }); return true;}
function delegate(realGit, args) { return new Promise((resolve, reject) => { const child = spawn(realGit, args, { stdio: "inherit", env: process.env }); child.on("error", reject); child.on("exit", (code, signal) => { if (signal) { process.kill(process.pid, signal); return; } resolve(code ?? 1); }); });}
export async function runGitWorktreeProxy(args, options = {}) { const realGit = options.realGit || process.env.OMP_CODEX_REAL_GIT || "/usr/bin/git"; const jj = options.jj || process.env.OMP_CODEX_JJ || "jj"; const parsed = parseWorktreeCommand(args, options.cwd || process.cwd()); if (!parsed) return delegate(realGit, args);
const jjRoot = await findJjRoot(jj, parsed.cwd); if (!jjRoot) return delegate(realGit, args);
if (parsed.subcommand === "add") { await createJjWorkspace({ jj, realGit, jjRoot, ...parsed }); } else if (!await removeJjWorkspace({ jj, realGit, jjRoot, ...parsed })) { return delegate(realGit, args); } return 0;}