diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 7d0b5e8c..25b7e7e1 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,6 +1,7 @@ # Mops CLI Changelog ## Next +- Fix `mops install` (and any `--lock check` flow) failing with "Mismatched number of resolved packages" when a project's resolved dependencies include multiple aliases (e.g. `base`, `base@0`, `base@0.16`) that pin to the same `name@version` ## 2.12.1 - `mops check`/`build`/`check-stable` skip migration staging when only the pending `next` migration is needed, so `moc` diagnostics reference the real `next-migration/` path. diff --git a/cli/integrity.ts b/cli/integrity.ts index 181f223d..d564e453 100644 --- a/cli/integrity.ts +++ b/cli/integrity.ts @@ -63,7 +63,8 @@ async function getResolvedMopsPackageIds(): Promise { let packageIds = Object.entries(resolvedPackages) .filter(([_, version]) => getDependencyType(version) === "mops") .map(([name, version]) => getPackageId(name, version)); - return packageIds; + // dedupe: aliases like `base@0`, `base@0.16` collapse to the same packageId + return [...new Set(packageIds)]; } // get hash of local file from '.mops' dir by fileId diff --git a/cli/tests/cli.test.ts b/cli/tests/cli.test.ts index 5dfc6998..132746ce 100644 --- a/cli/tests/cli.test.ts +++ b/cli/tests/cli.test.ts @@ -71,4 +71,25 @@ describe("install", () => { // mops add/remove/update/sync are not separately tested here because they // all route through the same checkIntegrity code path tested above. + + // Regression: aliases pinning the same package@version (e.g. `core` and + // `core@1` both at "1.0.0") inflated the resolved-packageIds count and + // tripped the lockfile integrity check with a spurious + // "Mismatched number of resolved packages" error. See issue #506. + test("integrity check passes when aliases resolve to the same package@version", async () => { + const cwd = path.join(import.meta.dirname, "install/aliases"); + const lockFile = path.join(cwd, "mops.lock"); + rmSync(lockFile, { force: true }); + try { + const result = await cli(["install"], { cwd, env: { CI: undefined } }); + expect(result.stderr).not.toMatch( + /Mismatched number of resolved packages/, + ); + expect(result.exitCode).toBe(0); + expect(existsSync(lockFile)).toBe(true); + } finally { + rmSync(lockFile, { force: true }); + rmSync(path.join(cwd, ".mops"), { recursive: true, force: true }); + } + }); }); diff --git a/cli/tests/install/aliases/mops.toml b/cli/tests/install/aliases/mops.toml new file mode 100644 index 00000000..ae55b5dc --- /dev/null +++ b/cli/tests/install/aliases/mops.toml @@ -0,0 +1,3 @@ +[dependencies] +core = "1.0.0" +"core@1" = "1.0.0"