fix: speed up tran apply-patch

This commit is contained in:
Codex
2026-05-25 14:06:40 +00:00
parent 1d56c46546
commit c3c50c3b36
4 changed files with 112 additions and 25 deletions
+100 -21
View File
@@ -7,9 +7,11 @@ export interface ParsedSshArgs {
invocationKind: SshInvocationKind;
stdinPrefix?: string;
stdinSuffix?: string;
requiredHelpers?: SshHelperName[];
}
export type SshInvocationKind = "interactive" | "argv" | "helper" | "ssh-like";
export type SshHelperName = "apply_patch" | "glob" | "skill-discover";
export interface ParsedSshRoute {
providerId: string;
@@ -104,6 +106,65 @@ line_number_for_prefix() {
printf '%s\n' $((newline_count + 1))
}
replace_once_with_perl() {
command -v perl >/dev/null 2>&1 || return 127
perl -0777 -e '
use strict;
use warnings;
sub fail {
print STDERR "apply_patch: ", @_, "\n";
exit 1;
}
sub read_all {
my ($path, $label) = @_;
open my $fh, "<", $path or fail("failed to read $label");
binmode $fh;
local $/;
my $data = <$fh>;
close $fh;
return defined $data ? $data : "";
}
my ($target, $search_file, $replace_file, $hunk_id, $allow_loose, $out) = @ARGV;
my $old = read_all($target, $target);
my $search = read_all($search_file, "hunk search");
my $replacement = read_all($replace_file, "hunk replacement");
my $new;
if ($search eq "") {
fail("hunk $hunk_id in $target has no context; add unchanged/deleted anchor lines or pass --allow-loose after manual review") if $allow_loose ne "1";
print STDERR "apply_patch: hunk $hunk_id matched $target:1 (loose)\n";
$new = $replacement . $old;
} else {
my $pos = -1;
my $offset = 0;
my $count = 0;
while (1) {
my $found = index($old, $search, $offset);
last if $found < 0;
$pos = $found if $count == 0;
$count += 1;
last if $count > 1 && $allow_loose ne "1";
$offset = $found + length($search);
}
fail("hunk $hunk_id context not found in $target") if $count == 0;
fail("hunk $hunk_id context matched multiple locations in $target; add more unchanged context or pass --allow-loose after manual review") if $count > 1 && $allow_loose ne "1";
my $prefix = substr($old, 0, $pos);
my $suffix = substr($old, $pos + length($search));
my $line = ($prefix =~ tr/\n//) + 1;
print STDERR "apply_patch: hunk $hunk_id matched $target:$line\n";
$new = $prefix . $replacement . $suffix;
}
open my $ofh, ">", $out or fail("failed to render patched file");
binmode $ofh;
print $ofh $new or fail("failed to render patched file");
close $ofh or fail("failed to render patched file");
' "$@"
}
replace_once() {
target=$1
search_file=$2
@@ -111,6 +172,17 @@ replace_once() {
hunk_id=$4
[ -e "$target" ] || die "file not found: $target"
fast_out=$(mk_temp)
if replace_once_with_perl "$target" "$search_file" "$replace_file" "$hunk_id" "$allow_loose" "$fast_out"; then
write_file "$target" "$fast_out"
rm -f "$fast_out"
return 0
else
status=$?
fi
rm -f "$fast_out"
[ "$status" = 127 ] || exit "$status"
marker="__UNIDESK_APPLY_PATCH_EOF_$$__"
old=$(cat "$target"; printf '%s' "$marker") || die "failed to read $target"
old=${"$"}{old%"$marker"}
@@ -707,11 +779,11 @@ export function parseSshArgs(args: string[]): ParsedSshArgs {
const subcommand = args[0] ?? "";
if (isSshSkillDiscoveryArgs(args)) {
const toolArgs = subcommand === "skill" ? ["skill-discover", ...args.slice(2)] : ["skill-discover", ...args.slice(1)];
return { remoteCommand: shellArgv(toolArgs), requiresStdin: false, invocationKind: "helper" };
return { remoteCommand: shellArgv(toolArgs), requiresStdin: false, invocationKind: "helper", requiredHelpers: ["skill-discover"] };
}
if (subcommand === "apply-patch" || subcommand === "patch") {
const toolArgs = ["apply_patch", ...args.slice(1)];
return { remoteCommand: shellArgv(toolArgs), requiresStdin: true, invocationKind: "helper" };
return { remoteCommand: shellArgv(toolArgs), requiresStdin: true, invocationKind: "helper", requiredHelpers: ["apply_patch"] };
}
if (subcommand === "py") {
return { remoteCommand: buildPythonStdinCommand(args.slice(1)), requiresStdin: true, invocationKind: "helper" };
@@ -728,7 +800,7 @@ export function parseSshArgs(args: string[]): ParsedSshArgs {
return { remoteCommand: buildFindCommand(args.slice(1)), requiresStdin: false, invocationKind: "helper" };
}
if (subcommand === "glob") {
return { remoteCommand: shellArgv(["glob", ...args.slice(1)]), requiresStdin: false, invocationKind: "helper" };
return { remoteCommand: shellArgv(["glob", ...args.slice(1)]), requiresStdin: false, invocationKind: "helper", requiredHelpers: ["glob"] };
}
if (subcommand === "k3s") {
throw new Error("ssh k3s shorthand is unsupported; put k3s in the route, for example: ssh D601:k3s kubectl get nodes");
@@ -1412,27 +1484,34 @@ function buildPythonStdinCommand(args: string[]): string {
].join("; ");
}
function remoteToolBootstrapCommand(): string {
const encodedApplyPatch = Buffer.from(remoteApplyPatchSource, "utf8").toString("base64");
const encodedGlob = Buffer.from(remoteGlobSource, "utf8").toString("base64");
const encodedSkillDiscover = Buffer.from(remoteSkillDiscoverSource, "utf8").toString("base64");
return [
const remoteToolSources: Record<SshHelperName, string> = {
apply_patch: remoteApplyPatchSource,
glob: remoteGlobSource,
"skill-discover": remoteSkillDiscoverSource,
};
function remoteToolBootstrapCommand(helpers: readonly SshHelperName[] = []): string {
const uniqueHelpers = [...new Set(helpers)];
if (uniqueHelpers.length === 0) return "";
const commands = [
"UNIDESK_SSH_TOOL_DIR=/tmp/unidesk-ssh-tools",
'mkdir -p "$UNIDESK_SSH_TOOL_DIR"',
`printf %s ${shellQuote(encodedApplyPatch)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/apply_patch"`,
`printf %s ${shellQuote(encodedGlob)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/glob"`,
`printf %s ${shellQuote(encodedSkillDiscover)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/skill-discover"`,
'chmod 700 "$UNIDESK_SSH_TOOL_DIR/apply_patch"',
'chmod 700 "$UNIDESK_SSH_TOOL_DIR/glob"',
'chmod 700 "$UNIDESK_SSH_TOOL_DIR/skill-discover"',
'export PATH="$UNIDESK_SSH_TOOL_DIR:$PATH"',
].join("; ");
];
for (const helper of uniqueHelpers) {
const source = remoteToolSources[helper];
const encoded = Buffer.from(source, "utf8").toString("base64");
commands.push(`printf %s ${shellQuote(encoded)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/${helper}"`);
commands.push(`chmod 700 "$UNIDESK_SSH_TOOL_DIR/${helper}"`);
}
commands.push('export PATH="$UNIDESK_SSH_TOOL_DIR:$PATH"');
return commands.join("; ");
}
export function wrapSshRemoteCommand(command: string | null): string {
const bootstrap = remoteToolBootstrapCommand();
if (command === null) return `${bootstrap}; exec "\${SHELL:-/bin/bash}" -l`;
return `${bootstrap}; stty -echo 2>/dev/null || true; ${command}`;
export function wrapSshRemoteCommand(command: string | null, helpers: readonly SshHelperName[] = []): string {
const bootstrap = remoteToolBootstrapCommand(helpers);
const prefix = bootstrap.length > 0 ? `${bootstrap}; ` : "";
if (command === null) return `${prefix}exec "\${SHELL:-/bin/bash}" -l`;
return `${prefix}stty -echo 2>/dev/null || true; ${command}`;
}
function safeProviderId(providerId: string): string {
@@ -1615,7 +1694,7 @@ export async function runSsh(config: UniDeskConfig, providerId: string, args: st
const openTimeoutMs = Math.max(15000, Number(process.env.UNIDESK_SSH_OPEN_TIMEOUT_MS || 60000));
const payload = {
providerId: invocation.providerId,
command: wrapSshRemoteCommand(parsed.remoteCommand),
command: wrapSshRemoteCommand(parsed.remoteCommand, parsed.requiredHelpers),
cwd: invocation.route.plane === "host" ? invocation.route.workspace ?? undefined : undefined,
tty: parsed.remoteCommand === null,
stdinEotOnEnd: parsed.remoteCommand !== null,