angular-cli/packages/angular/cli/tasks/install-package.ts
Alan Agius 548617ca4c fix(@angular/cli): updated CLI should not have analytics enabled
In the case users don't have analytics globally configured when the CLI will self update during ng update. It will prompt to configure this.

However, afterwards the update will fail with `Repository is not clean.  Please commit or stash any changes before updating.` as there would be uncommited local changed.
2019-10-29 20:21:51 -07:00

184 lines
4.7 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { logging } from '@angular-devkit/core';
import { spawnSync } from 'child_process';
import {
existsSync,
mkdtempSync,
readFileSync,
realpathSync,
} from 'fs';
import { tmpdir } from 'os';
import { join, resolve } from 'path';
import * as rimraf from 'rimraf';
import { PackageManager } from '../lib/config/schema';
import { colors } from '../utilities/color';
import { NgAddSaveDepedency } from '../utilities/package-metadata';
interface PackageManagerOptions {
silent: string;
saveDev: string;
install: string;
prefix: string;
}
export function installPackage(
packageName: string,
logger: logging.Logger,
packageManager: PackageManager = PackageManager.Npm,
save: Exclude<NgAddSaveDepedency, false> = true,
extraArgs: string[] = [],
global = false,
) {
const packageManagerArgs = getPackageManagerArguments(packageManager);
const installArgs: string[] = [
packageManagerArgs.install,
packageName,
packageManagerArgs.silent,
];
logger.info(colors.green(`Installing packages for tooling via ${packageManager}.`));
if (save === 'devDependencies') {
installArgs.push(packageManagerArgs.saveDev);
}
if (global) {
if (packageManager === PackageManager.Yarn) {
installArgs.unshift('global');
} else {
installArgs.push('--global');
}
}
const { status } = spawnSync(
packageManager,
[
...installArgs,
...extraArgs,
],
{
stdio: 'inherit',
shell: true,
},
);
if (status !== 0) {
throw new Error('Package install failed, see above.');
}
logger.info(colors.green(`Installed packages for tooling via ${packageManager}.`));
}
export function installTempPackage(
packageName: string,
logger: logging.Logger,
packageManager: PackageManager = PackageManager.Npm,
): string {
const tempPath = mkdtempSync(join(realpathSync(tmpdir()), 'angular-cli-packages-'));
// clean up temp directory on process exit
process.on('exit', () => {
try {
rimraf.sync(tempPath);
} catch { }
});
// setup prefix/global modules path
const packageManagerArgs = getPackageManagerArguments(packageManager);
const installArgs: string[] = [
packageManagerArgs.prefix,
tempPath,
];
installPackage(packageName, logger, packageManager, true, installArgs, true);
let tempNodeModules: string;
if (packageManager !== PackageManager.Yarn && process.platform !== 'win32') {
// Global installs on Unix systems go to {prefix}/lib/node_modules.
// Global installs on Windows go to {prefix}/node_modules (that is, no lib folder.)
tempNodeModules = join(tempPath, 'lib', 'node_modules');
} else {
tempNodeModules = join(tempPath, 'node_modules');
}
return tempNodeModules;
}
export function runTempPackageBin(
packageName: string,
logger: logging.Logger,
packageManager: PackageManager = PackageManager.Npm,
args: string[] = [],
): number {
const tempNodeModulesPath = installTempPackage(packageName, logger, packageManager);
// Remove version/tag etc... from package name
// Ex: @angular/cli@latest -> @angular/cli
const packageNameNoVersion = packageName.substring(0, packageName.lastIndexOf('@'));
const pkgLocation = join(tempNodeModulesPath, packageNameNoVersion);
const packageJsonPath = join(pkgLocation, 'package.json');
// Get a binary location for this package
let binPath: string | undefined;
if (existsSync(packageJsonPath)) {
const content = readFileSync(packageJsonPath, 'utf-8');
if (content) {
const { bin = {} } = JSON.parse(content);
const binKeys = Object.keys(bin);
if (binKeys.length) {
binPath = resolve(pkgLocation, bin[binKeys[0]]);
}
}
}
if (!binPath) {
throw new Error(`Cannot locate bin for temporary package: ${packageNameNoVersion}.`);
}
const argv = [
binPath,
...args,
];
const { status, error } = spawnSync('node', argv, {
stdio: 'inherit',
shell: true,
env: {
...process.env,
NG_DISABLE_VERSION_CHECK: 'true',
NG_CLI_ANALYTICS: 'false',
},
});
if (status === null && error) {
throw error;
}
return status || 0;
}
function getPackageManagerArguments(packageManager: PackageManager): PackageManagerOptions {
return packageManager === PackageManager.Yarn
? {
silent: '--silent',
saveDev: '--dev',
install: 'add',
prefix: '--global-folder',
}
: {
silent: '--quiet',
saveDev: '--save-dev',
install: 'install',
prefix: '--prefix',
};
}