mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(coding-agent): refresh temporary git sources pinned to a branch ref
A temporary -e git source with a ref was treated as pinned and never refreshed, so git:host/repo@main stayed on its first checkout. Refresh refs too, skipping only a commit-hash ref that is already checked out.
This commit is contained in:
parent
cd6a8f7f3c
commit
bec60c54ba
3 changed files with 48 additions and 4 deletions
|
|
@ -1441,8 +1441,8 @@ export class DefaultPackageManager implements PackageManager {
|
|||
if (!existsSync(installedPath)) {
|
||||
const installed = await installMissing();
|
||||
if (!installed) continue;
|
||||
} else if (resolvedScope === "temporary" && !parsed.pinned && !isOfflineModeEnabled()) {
|
||||
await this.refreshTemporaryGitSource(parsed, resolvedSource);
|
||||
} else if (resolvedScope === "temporary" && !isOfflineModeEnabled()) {
|
||||
await this.refreshTemporaryGitSource(parsed, resolvedSource, installedPath);
|
||||
}
|
||||
metadata.baseDir = installedPath;
|
||||
metadata.packageRoot = installedPath;
|
||||
|
|
@ -2132,11 +2132,22 @@ export class DefaultPackageManager implements PackageManager {
|
|||
await this.cleanAndInstallGitDependencies(targetDir, markerPath);
|
||||
}
|
||||
|
||||
private async refreshTemporaryGitSource(source: GitSource, sourceStr: string): Promise<void> {
|
||||
private async refreshTemporaryGitSource(source: GitSource, sourceStr: string, installedPath: string): Promise<void> {
|
||||
if (isOfflineModeEnabled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// A ref can name a moving branch, so refresh refs too. Skip the network call only when the
|
||||
// ref is a commit hash that is already checked out.
|
||||
if (source.ref && /^[0-9a-f]{7,64}$/i.test(source.ref)) {
|
||||
const head = await this.runCommandCapture("git", ["rev-parse", "HEAD"], {
|
||||
cwd: installedPath,
|
||||
timeoutMs: NETWORK_TIMEOUT_MS,
|
||||
});
|
||||
if (head.trim().toLowerCase().startsWith(source.ref.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
await this.withProgress("pull", sourceStr, `Refreshing ${sourceStr}...`, async () => {
|
||||
await this.updateGit(source, "temporary");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export type GitSource = {
|
|||
path: string;
|
||||
/** Git ref (branch, tag, commit) if specified */
|
||||
ref?: string;
|
||||
/** True if ref was specified (package won't be auto-updated) */
|
||||
/** True if ref was specified. `pi update` reconciles the checkout to the ref but does not move the ref. */
|
||||
pinned: boolean;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2941,6 +2941,39 @@ export default function(api) { api.registerTool({ name: "test", description: "te
|
|||
});
|
||||
|
||||
// https://github.com/earendil-works/pi/issues/11375
|
||||
it("should refresh temporary git sources with a branch ref", async () => {
|
||||
const managerWithInternals = packageManager as unknown as PackageManagerInternals;
|
||||
const source = "git:github.com/example/repo@main";
|
||||
const parsed = managerWithInternals.parseSource(source);
|
||||
if (parsed.type !== "git") throw new Error("Expected git source");
|
||||
const installedPath = managerWithInternals.getGitInstallPath(parsed, "temporary");
|
||||
mkdirSync(join(installedPath, "extensions"), { recursive: true });
|
||||
writeFileSync(join(installedPath, "extensions", "index.ts"), "export default function() {};");
|
||||
|
||||
const updateGitSpy = vi.spyOn(packageManager as any, "updateGit").mockResolvedValue(undefined);
|
||||
|
||||
const result = await packageManager.resolveExtensionSources([source], { temporary: true });
|
||||
expect(updateGitSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateGitSpy.mock.calls[0][0]).toMatchObject({ ref: "main" });
|
||||
expect(result.extensions.some((r) => pathEndsWith(r.path, "extensions/index.ts") && r.enabled)).toBe(true);
|
||||
});
|
||||
|
||||
it("should not refresh temporary git sources pinned to the checked-out commit", async () => {
|
||||
const managerWithInternals = packageManager as unknown as PackageManagerInternals;
|
||||
const source = "git:github.com/example/repo@abc1234";
|
||||
const parsed = managerWithInternals.parseSource(source);
|
||||
if (parsed.type !== "git") throw new Error("Expected git source");
|
||||
mkdirSync(managerWithInternals.getGitInstallPath(parsed, "temporary"), { recursive: true });
|
||||
|
||||
vi.spyOn(packageManager as any, "runCommandCapture").mockResolvedValue(
|
||||
"ABC1234def5678901234567890123456789012345\n",
|
||||
);
|
||||
const updateGitSpy = vi.spyOn(packageManager as any, "updateGit").mockResolvedValue(undefined);
|
||||
|
||||
await packageManager.resolveExtensionSources([source], { temporary: true });
|
||||
expect(updateGitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should refresh unpinned temporary npm sources when a newer version exists", async () => {
|
||||
const managerWithInternals = packageManager as unknown as PackageManagerInternals;
|
||||
const source = "npm:example";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue