From 8fcbdb9a0a283a10359eaf9ab9464e35c6b08b95 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Fri, 1 Nov 2019 21:39:10 -0400 Subject: [PATCH] fix(@angular/cli): verify package specifier when adding a package Fixes #16029 --- packages/angular/cli/commands/add-impl.ts | 23 ++++++++++++++++--- .../e2e/tests/commands/add/add-material.ts | 20 ++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/packages/angular/cli/commands/add-impl.ts b/packages/angular/cli/commands/add-impl.ts index 8932f04dc6dc..4e9e87c2ea58 100644 --- a/packages/angular/cli/commands/add-impl.ts +++ b/packages/angular/cli/commands/add-impl.ts @@ -18,6 +18,7 @@ import { colors } from '../utilities/color'; import { getPackageManager } from '../utilities/package-manager'; import { NgAddSaveDepedency, + PackageIdentifier, PackageManifest, fetchPackageManifest, fetchPackageMetadata, @@ -50,10 +51,26 @@ export class AddCommand extends SchematicCommand { } if (packageIdentifier.registry && this.isPackageInstalled(packageIdentifier.name)) { - // Already installed so just run schematic - this.logger.info('Skipping installation: Package already installed'); + let validVersion = false; + const installedVersion = await this.findProjectVersion(packageIdentifier.name); + if (installedVersion) { + if (packageIdentifier.type === 'range') { + validVersion = satisfies(installedVersion, packageIdentifier.fetchSpec); + } else if (packageIdentifier.type === 'version') { + const v1 = valid(packageIdentifier.fetchSpec); + const v2 = valid(installedVersion); + validVersion = v1 !== null && v1 === v2; + } else if (!packageIdentifier.rawSpec) { + validVersion = true; + } + } - return this.executeSchematic(packageIdentifier.name, options['--']); + if (validVersion) { + // Already installed so just run schematic + this.logger.info('Skipping installation: Package already installed'); + + return this.executeSchematic(packageIdentifier.name, options['--']); + } } const packageManager = await getPackageManager(this.workspace.root); diff --git a/tests/legacy-cli/e2e/tests/commands/add/add-material.ts b/tests/legacy-cli/e2e/tests/commands/add/add-material.ts index 44b075a20a0a..ad0c81629ef3 100644 --- a/tests/legacy-cli/e2e/tests/commands/add/add-material.ts +++ b/tests/legacy-cli/e2e/tests/commands/add/add-material.ts @@ -8,4 +8,24 @@ export default async function () { await ng('add', '@angular/material'); await expectFileToMatch('package.json', /@angular\/material/); + + const output1 = await ng('add', '@angular/material'); + if (!output1.stdout.includes('Skipping installation: Package already installed')) { + throw new Error('Installation was not skipped'); + } + + const output2 = await ng('add', '@angular/material@latest'); + if (output2.stdout.includes('Skipping installation: Package already installed')) { + throw new Error('Installation should not have been skipped'); + } + + const output3 = await ng('add', '@angular/material@8.0.0'); + if (output3.stdout.includes('Skipping installation: Package already installed')) { + throw new Error('Installation should not have been skipped'); + } + + const output4 = await ng('add', '@angular/material@8'); + if (!output4.stdout.includes('Skipping installation: Package already installed')) { + throw new Error('Installation was not skipped'); + } }