mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-11-02 15:31:50 +00:00
fix: keep native Windows paths in v2 git patches (#1492)
ACP v2 now says each `git_patch` path, once unquoted, is the same native absolute path string as the matching `changes` entry (agentclientprotocol/agent-client-protocol#2650). The v2 form converted `C:\work\App.ts` to `C:/work/App.ts`, so on Windows the patch and `changes[].path` named different strings. The v2 form now keeps the native path, which Git quoting writes as `"C:\\work\\App.ts"`. Git's own form, which the AIR extension uses, still uses forward slashes and the `a/`/`b/` prefixes.
This commit is contained in:
12
src/diff.ts
12
src/diff.ts
@@ -89,7 +89,7 @@ export type PatchForm = "air" | "v2";
|
||||
/**
|
||||
* How a git patch names its file. `git` is git's own form: the leading slash
|
||||
* dropped and the `a/` and `b/` prefixes added. `absolute` is the form of an
|
||||
* ACP v2 `git_patch`, whose paths must be absolute: the path itself.
|
||||
* ACP v2 `git_patch`, whose paths must be absolute: the native path itself.
|
||||
*/
|
||||
type GitPatchPaths = "git" | "absolute";
|
||||
|
||||
@@ -438,11 +438,11 @@ export function gitPatchText(
|
||||
}
|
||||
|
||||
function gitPatchHeader(filePath: string, change: FileChange, paths: GitPatchPaths): string[] {
|
||||
// A Windows path gets forward slashes so the header names the same file on
|
||||
// every platform.
|
||||
const slashed = filePath.replaceAll("\\", "/");
|
||||
// git drops one leading slash of an absolute path.
|
||||
const name = paths === "git" ? slashed.replace(/^\/+/u, "") : slashed;
|
||||
// git's form uses forward slashes, so the header names the same file on
|
||||
// every platform, and drops one leading slash of an absolute path. An ACP v2
|
||||
// patch keeps the native path so that, once unquoted, it equals the `changes`
|
||||
// entry: `C:\work\App.ts` is written `"C:\\work\\App.ts"`.
|
||||
const name = paths === "git" ? filePath.replaceAll("\\", "/").replace(/^\/+/u, "") : filePath;
|
||||
const oldName = quoteGitPath(paths === "git" ? "a/" : "", name);
|
||||
const newName = quoteGitPath(paths === "git" ? "b/" : "", name);
|
||||
// git ends a ---/+++ name that contains a space with a tab, for GNU patch.
|
||||
|
||||
@@ -466,6 +466,12 @@ describe("ACP v2 diffs", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps a Windows path native in a git patch, so it matches the changes entry", () => {
|
||||
expect(gitPatchText("C:\\work\\App.ts", "update", [hunk], "absolute")).toContain(
|
||||
'diff --git "C:\\\\work\\\\App.ts" "C:\\\\work\\\\App.ts"\n--- "C:\\\\work\\\\App.ts"\n+++ "C:\\\\work\\\\App.ts"\n',
|
||||
);
|
||||
});
|
||||
|
||||
it("shows no diff at tool use, where the input holds a snippet or no old text", () => {
|
||||
const renderer = new AcpToolCallRenderer(v2);
|
||||
const edit = { file_path: "/work/a.ts", old_string: "old", new_string: "new" };
|
||||
|
||||
Reference in New Issue
Block a user