fix(coding-agent): reconcile pinned git update refs

closes #4869
This commit is contained in:
Armin Ronacher
2026-05-23 00:16:07 +02:00
parent d80bcc367e
commit c85dbb1620
6 changed files with 101 additions and 24 deletions

View File

@@ -282,7 +282,7 @@ describe("DefaultPackageManager git update", () => {
});
describe("pinned sources", () => {
it("should not update pinned git sources (with @ref)", async () => {
it("should not move pinned git sources past their configured ref", async () => {
// Create remote repo first to get the initial commit
mkdirSync(remoteDir, { recursive: true });
initGitRepo(remoteDir);
@@ -301,13 +301,77 @@ describe("DefaultPackageManager git update", () => {
// Add new commit to remote
createCommit(remoteDir, "extension.ts", "// v2", "Second commit");
// Update should be skipped for pinned sources
await packageManager.update();
// Should still be on initial commit
expect(getCurrentCommit(installedDir)).toBe(initialCommit);
expect(getFileContent(installedDir, "extension.ts")).toBe("// v1");
});
it("should checkout the configured pinned git ref during full and targeted updates", async () => {
mkdirSync(remoteDir, { recursive: true });
initGitRepo(remoteDir);
const v1Commit = createCommit(remoteDir, "extension.ts", "// v1", "Initial commit");
git(["tag", "v1"], remoteDir);
const v2Commit = createCommit(remoteDir, "extension.ts", "// v2", "Second commit");
git(["tag", "v2"], remoteDir);
mkdirSync(join(agentDir, "git", "github.com", "test"), { recursive: true });
git(["clone", remoteDir, installedDir], tempDir);
git(["checkout", "v1"], installedDir);
expect(getCurrentCommit(installedDir)).toBe(v1Commit);
const pinnedSource = `${gitSource}@v2`;
settingsManager.setPackages([pinnedSource]);
await packageManager.update();
expect(getCurrentCommit(installedDir)).toBe(v2Commit);
expect(getFileContent(installedDir, "extension.ts")).toBe("// v2");
git(["checkout", "v1"], installedDir);
await packageManager.update(pinnedSource);
expect(getCurrentCommit(installedDir)).toBe(v2Commit);
expect(getFileContent(installedDir, "extension.ts")).toBe("// v2");
});
it("should not reset an annotated tag checkout that already matches the configured ref", async () => {
mkdirSync(remoteDir, { recursive: true });
initGitRepo(remoteDir);
const taggedCommit = createCommit(remoteDir, "extension.ts", "// v1", "Initial commit");
git(["tag", "-a", "v1", "-m", "v1"], remoteDir);
mkdirSync(join(agentDir, "git", "github.com", "test"), { recursive: true });
git(["clone", remoteDir, installedDir], tempDir);
git(["checkout", "v1"], installedDir);
expect(getCurrentCommit(installedDir)).toBe(taggedCommit);
settingsManager.setPackages([`${gitSource}@v1`]);
const executedCommands: string[] = [];
const managerWithInternals = packageManager as unknown as {
runCommand: (command: string, args: string[], options?: { cwd?: string }) => Promise<void>;
};
managerWithInternals.runCommand = async (command, args, options) => {
executedCommands.push(`${command} ${args.join(" ")}`);
const result = spawnSync(command, args, {
cwd: options?.cwd,
encoding: "utf-8",
});
if (result.status !== 0) {
throw new Error(`Command failed: ${command} ${args.join(" ")}\n${result.stderr}`);
}
};
await packageManager.update();
expect(executedCommands).toContain("git fetch origin v1");
expect(executedCommands.some((command) => command.startsWith("git reset --hard"))).toBe(false);
expect(executedCommands).not.toContain("git clean -fdx");
expect(getCurrentCommit(installedDir)).toBe(taggedCommit);
});
});
describe("temporary git sources", () => {