mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-23 18:38:14 +00:00
85 lines
2.0 KiB
JavaScript
85 lines
2.0 KiB
JavaScript
import { execFileSync, spawnSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
function isExecutable(filePath) {
|
|
try {
|
|
fs.accessSync(filePath, fs.constants.X_OK);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function pathEntries(env) {
|
|
return String(env.PATH ?? "")
|
|
.split(path.delimiter)
|
|
.filter(Boolean);
|
|
}
|
|
|
|
export function plainGhEnv(env = process.env) {
|
|
const next = { ...env };
|
|
delete next.CLICOLOR;
|
|
delete next.CLICOLOR_FORCE;
|
|
delete next.COLORTERM;
|
|
delete next.GH_FORCE_TTY;
|
|
next.NO_COLOR = "1";
|
|
next.FORCE_COLOR = "0";
|
|
next.CLICOLOR = "0";
|
|
next.CLICOLOR_FORCE = "0";
|
|
return next;
|
|
}
|
|
|
|
export function resolvePlainGhBin(env = process.env) {
|
|
if (env.OPENCLAW_GH_BIN) {
|
|
if (isExecutable(env.OPENCLAW_GH_BIN)) {
|
|
return env.OPENCLAW_GH_BIN;
|
|
}
|
|
throw new Error(`OPENCLAW_GH_BIN is not executable: ${env.OPENCLAW_GH_BIN}`);
|
|
}
|
|
|
|
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
if (isExecutable(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
const homeBin = env.HOME ? path.join(env.HOME, "bin") : "";
|
|
for (const entry of pathEntries(env)) {
|
|
if (homeBin && entry === homeBin) {
|
|
continue;
|
|
}
|
|
const candidate = path.join(entry, process.platform === "win32" ? "gh.exe" : "gh");
|
|
if (isExecutable(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
for (const entry of pathEntries(env)) {
|
|
const candidate = path.join(entry, process.platform === "win32" ? "gh.exe" : "gh");
|
|
if (isExecutable(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
throw new Error("missing required command: gh");
|
|
}
|
|
|
|
export function execPlainGh(args, options = {}) {
|
|
const env = plainGhEnv(options.env ?? process.env);
|
|
const ghBin = resolvePlainGhBin(env);
|
|
return execFileSync(ghBin, args, {
|
|
...options,
|
|
env,
|
|
});
|
|
}
|
|
|
|
export function spawnPlainGh(args, options = {}) {
|
|
const env = plainGhEnv(options.env ?? process.env);
|
|
const ghBin = resolvePlainGhBin(env);
|
|
return spawnSync(ghBin, args, {
|
|
...options,
|
|
env,
|
|
});
|
|
}
|