diff --git a/apps/server/src/services/plugin-catalog/marketplace-source.ts b/apps/server/src/services/plugin-catalog/marketplace-source.ts index d75db8ea6d1..72c3de54986 100644 --- a/apps/server/src/services/plugin-catalog/marketplace-source.ts +++ b/apps/server/src/services/plugin-catalog/marketplace-source.ts @@ -335,6 +335,23 @@ async function materializeGit( source.url, checkout, ]); + const commit = await runInstallCommand("git", [ + "-C", + checkout, + "rev-parse", + "--verify", + "--end-of-options", + `${source.ref}^{commit}`, + ]).catch(() => + runInstallCommand("git", [ + "-C", + checkout, + "rev-parse", + "--verify", + "--end-of-options", + `refs/remotes/origin/${source.ref}^{commit}`, + ]), + ); await runInstallCommand("git", [ ...GIT_CLONE_ARGS, "-C", @@ -342,13 +359,7 @@ async function materializeGit( "checkout", "--quiet", "--detach", - source.ref, - ]); - const commit = await runInstallCommand("git", [ - "-C", - checkout, - "rev-parse", - "HEAD", + commit, ]); await rm(join(checkout, ".git"), { recursive: true, force: true }); return await materializeLocal(checkout, commit, dispose, warn); diff --git a/apps/server/test/services/plugin-catalog/third-party-marketplaces.test.ts b/apps/server/test/services/plugin-catalog/third-party-marketplaces.test.ts index 6c15215ac3c..b129db46b0e 100644 --- a/apps/server/test/services/plugin-catalog/third-party-marketplaces.test.ts +++ b/apps/server/test/services/plugin-catalog/third-party-marketplaces.test.ts @@ -196,6 +196,63 @@ describe("third-party marketplaces", () => { }); }); + it.each([ + "catalog-next", + "origin/catalog-next", + "catalog-release", + "commit", + ])("reads the selected catalog commit for ref %s", async (ref) => { + await run("git", ["checkout", "-qb", "catalog-next"], { cwd: repo }); + await writeFile( + join(repo, "marketplace.json"), + JSON.stringify(manifest("acme-plugins", [entry({ id: "next-notes" })])), + ); + await run("git", ["commit", "-qam", "next catalog"], { cwd: repo }); + await run("git", ["tag", "-am", "catalog release", "catalog-release"], { + cwd: repo, + }); + const commit = ( + await run("git", ["rev-parse", "HEAD"], { cwd: repo }) + ).stdout.trim(); + await run("git", ["checkout", "-q", "main"], { cwd: repo }); + const catalog = service({ fetch: marketplaceFetch({}) }); + + const added = await catalog.addMarketplace( + `git:${repo}@${ref === "commit" ? commit : ref}`, + ); + + expect(added.resolvedCommit).toBe(commit); + expect(await catalog.search("Acme Notes")).toEqual([ + expect.objectContaining({ entryId: "next-notes" }), + ]); + if (ref === "catalog-next") { + await run("git", ["checkout", "-q", "catalog-next"], { cwd: repo }); + await writeFile( + join(repo, "marketplace.json"), + JSON.stringify( + manifest("acme-plugins", [entry({ id: "refreshed-notes" })]), + ), + ); + await run("git", ["commit", "-qam", "refresh catalog"], { cwd: repo }); + const refreshedCommit = ( + await run("git", ["rev-parse", "HEAD"], { cwd: repo }) + ).stdout.trim(); + await run("git", ["checkout", "-q", "main"], { cwd: repo }); + + const [refreshed] = await catalog.refreshMarketplaces({ + name: "acme-plugins", + }); + + expect(refreshed).toMatchObject({ + ok: true, + marketplace: { resolvedCommit: refreshedCommit }, + }); + expect(await catalog.search("Acme Notes")).toEqual([ + expect.objectContaining({ entryId: "refreshed-notes" }), + ]); + } + }); + it("adds, refreshes, and removes a git marketplace read from a real checkout", async () => { const catalog = service({ fetch: marketplaceFetch({}) });