refactor: dedupe runtime and helper flows
This commit is contained in:
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { ExecAllowlistEntry } from "./exec-approvals.js";
|
||||
import { resolveDispatchWrapperExecutionPlan } from "./exec-wrapper-resolution.js";
|
||||
import { resolveExecutablePath as resolveExecutableCandidatePath } from "./executable-path.js";
|
||||
import { expandHomePrefix } from "./home-dir.js";
|
||||
|
||||
export const DEFAULT_SAFE_BINS = ["jq", "cut", "uniq", "head", "tail", "tr", "wc"];
|
||||
@@ -17,21 +18,6 @@ export type CommandResolution = {
|
||||
blockedWrapper?: string;
|
||||
};
|
||||
|
||||
function isExecutableFile(filePath: string): boolean {
|
||||
try {
|
||||
const stat = fs.statSync(filePath);
|
||||
if (!stat.isFile()) {
|
||||
return false;
|
||||
}
|
||||
if (process.platform !== "win32") {
|
||||
fs.accessSync(filePath, fs.constants.X_OK);
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function parseFirstToken(command: string): string | null {
|
||||
const trimmed = command.trim();
|
||||
if (!trimmed) {
|
||||
@@ -49,44 +35,6 @@ function parseFirstToken(command: string): string | null {
|
||||
return match ? match[0] : null;
|
||||
}
|
||||
|
||||
function resolveExecutablePath(rawExecutable: string, cwd?: string, env?: NodeJS.ProcessEnv) {
|
||||
const expanded = rawExecutable.startsWith("~") ? expandHomePrefix(rawExecutable) : rawExecutable;
|
||||
if (expanded.includes("/") || expanded.includes("\\")) {
|
||||
if (path.isAbsolute(expanded)) {
|
||||
return isExecutableFile(expanded) ? expanded : undefined;
|
||||
}
|
||||
const base = cwd && cwd.trim() ? cwd.trim() : process.cwd();
|
||||
const candidate = path.resolve(base, expanded);
|
||||
return isExecutableFile(candidate) ? candidate : undefined;
|
||||
}
|
||||
const envPath = env?.PATH ?? env?.Path ?? process.env.PATH ?? process.env.Path ?? "";
|
||||
const entries = envPath.split(path.delimiter).filter(Boolean);
|
||||
const hasExtension = process.platform === "win32" && path.extname(expanded).length > 0;
|
||||
const extensions =
|
||||
process.platform === "win32"
|
||||
? hasExtension
|
||||
? [""]
|
||||
: (
|
||||
env?.PATHEXT ??
|
||||
env?.Pathext ??
|
||||
process.env.PATHEXT ??
|
||||
process.env.Pathext ??
|
||||
".EXE;.CMD;.BAT;.COM"
|
||||
)
|
||||
.split(";")
|
||||
.map((ext) => ext.toLowerCase())
|
||||
: [""];
|
||||
for (const entry of entries) {
|
||||
for (const ext of extensions) {
|
||||
const candidate = path.join(entry, expanded + ext);
|
||||
if (isExecutableFile(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function tryResolveRealpath(filePath: string | undefined): string | undefined {
|
||||
if (!filePath) {
|
||||
return undefined;
|
||||
@@ -107,7 +55,7 @@ export function resolveCommandResolution(
|
||||
if (!rawExecutable) {
|
||||
return null;
|
||||
}
|
||||
const resolvedPath = resolveExecutablePath(rawExecutable, cwd, env);
|
||||
const resolvedPath = resolveExecutableCandidatePath(rawExecutable, { cwd, env });
|
||||
const resolvedRealPath = tryResolveRealpath(resolvedPath);
|
||||
const executableName = resolvedPath ? path.basename(resolvedPath) : rawExecutable;
|
||||
return {
|
||||
@@ -132,7 +80,7 @@ export function resolveCommandResolutionFromArgv(
|
||||
if (!rawExecutable) {
|
||||
return null;
|
||||
}
|
||||
const resolvedPath = resolveExecutablePath(rawExecutable, cwd, env);
|
||||
const resolvedPath = resolveExecutableCandidatePath(rawExecutable, { cwd, env });
|
||||
const resolvedRealPath = tryResolveRealpath(resolvedPath);
|
||||
const executableName = resolvedPath ? path.basename(resolvedPath) : rawExecutable;
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user