Skip to content

Commit 0d622f0

Browse files
MeAkibdgp1130
authored andcommitted
fix(@angular/cli): ignore registry manifests that do not match the requested version
Modern yarn returns the manifest of the latest version instead of an error when the requested version or range does not exist (for example, `yarn npm info @angular/core@99.99.99` prints the latest version with exit code 0). As a result, `ng add` and `ng update` could continue with an unrelated version instead of reporting that the requested version does not exist. Return `null` from `getRegistryManifest` when the fetched version does not satisfy the requested version or range. (cherry picked from commit 81e9eae)
1 parent 34d5391 commit 0d622f0

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

‎packages/angular/cli/src/package-managers/package-manager.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import { join, relative, resolve } from 'node:path';
1616
import npa from 'npm-package-arg';
17-
import { maxSatisfying, valid } from 'semver';
17+
import { maxSatisfying, satisfies, valid, validRange } from 'semver';
1818
import { PackageManagerError } from './error';
1919
import { Host } from './host';
2020
import { Logger } from './logger';
@@ -566,6 +566,15 @@ export class PackageManager {
566566
{ ...options, cache: this.#manifestCache, cacheKey },
567567
);
568568

569+
// Modern yarn returns the latest version instead of an error when the requested one does not exist.
570+
if (
571+
manifest &&
572+
validRange(version) &&
573+
!satisfies(manifest.version, version, { includePrerelease: true })
574+
) {
575+
return null;
576+
}
577+
569578
// If the provided version was not a specific version, also cache the specific fetched version
570579
if (manifest && manifest.version !== version) {
571580
const manifestSpecifier = `${manifest.name}@${manifest.version}`;

‎packages/angular/cli/src/package-managers/package-manager_spec.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,21 @@ describe('PackageManager', () => {
2222
});
2323

2424
describe('getRegistryManifest', () => {
25+
it('should return null when the fetched manifest does not match the requested version', async () => {
26+
// Modern yarn falls back to the latest version when the requested version does not exist.
27+
const pm = new PackageManager(host, '/tmp', SUPPORTED_PACKAGE_MANAGERS['yarn']);
28+
runCommandSpy.and.resolveTo({
29+
stdout: JSON.stringify({ name: 'foo', version: '2.0.0' }),
30+
stderr: '',
31+
});
32+
33+
expect(await pm.getRegistryManifest('foo', '99.99.99')).toBeNull();
34+
expect(await pm.getRegistryManifest('foo', '^99.0.0')).toBeNull();
35+
expect(await pm.getRegistryManifest('foo', '^2.0.0')).toEqual(
36+
jasmine.objectContaining({ version: '2.0.0' }),
37+
);
38+
});
39+
2540
it('should quote complex range specifiers when required by the host', async () => {
2641
// Simulate a quoting host
2742
Object.assign(host, { requiresQuoting: true });

0 commit comments

Comments
 (0)