cleanup(core): remove all deps on angular-devkit from tao

This commit is contained in:
victor savkin 2020-12-02 14:56:29 -05:00 committed by Victor Savkin
parent 86c0eef9cc
commit ae397d2d10
12 changed files with 199 additions and 159 deletions

View File

@ -4,7 +4,7 @@ import { FsTree } from '@nrwl/tao/src/shared/tree';
* Creates a host for testing. * Creates a host for testing.
*/ */
export function createTreeWithEmptyWorkspace() { export function createTreeWithEmptyWorkspace() {
const tree = new FsTree('/virtual', false, console); const tree = new FsTree('/virtual', false);
tree.write( tree.write(
'/workspace.json', '/workspace.json',

View File

@ -20,7 +20,6 @@ import {
isStringLiteral, isStringLiteral,
ScriptTarget, ScriptTarget,
} from 'typescript'; } from 'typescript';
import { getLogger } from '@nrwl/tao/src/shared/logger';
const ignore = require('ignore'); const ignore = require('ignore');
export default function update(): Rule { export default function update(): Rule {
@ -33,8 +32,7 @@ export default function update(): Rule {
updateImports, updateImports,
removeObsoletePackages, removeObsoletePackages,
(_, context: SchematicContext) => { (_, context: SchematicContext) => {
const logger = getLogger(); console.info(
logger.info(
'NX We upgraded Nest.js to v7. Make sure to read the migration guide: https://docs.nestjs.com/migration-guide' 'NX We upgraded Nest.js to v7. Make sure to read the migration guide: https://docs.nestjs.com/migration-guide'
); );
}, },

View File

@ -1,5 +1,4 @@
import * as minimist from 'minimist'; import * as minimist from 'minimist';
import { getLogger } from '../shared/logger';
import { import {
combineOptionsForGenerator, combineOptionsForGenerator,
convertToCamelCase, convertToCamelCase,
@ -13,6 +12,7 @@ import { statSync, unlinkSync, writeFileSync } from 'fs';
import { mkdirpSync, rmdirSync } from 'fs-extra'; import { mkdirpSync, rmdirSync } from 'fs-extra';
import * as path from 'path'; import * as path from 'path';
import { FileChange, FsTree } from '../shared/tree'; import { FileChange, FsTree } from '../shared/tree';
import { logger } from '../shared/logger';
const chalk = require('chalk'); const chalk = require('chalk');
@ -103,14 +103,8 @@ function parseGenerateOpts(
return res; return res;
} }
export function printGenHelp( export function printGenHelp(opts: GenerateOptions, schema: Schema) {
opts: GenerateOptions, printHelp(`nx generate ${opts.collectionName}:${opts.generatorName}`, {
schema: Schema,
logger: Console
) {
printHelp(
`nx generate ${opts.collectionName}:${opts.generatorName}`,
{
...schema, ...schema,
properties: { properties: {
...schema.properties, ...schema.properties,
@ -120,9 +114,7 @@ export function printGenHelp(
description: `Runs through and reports activity without writing to disk.`, description: `Runs through and reports activity without writing to disk.`,
}, },
}, },
}, });
logger as any
);
} }
function readDefaultCollection(workspace: WorkspaceConfiguration) { function readDefaultCollection(workspace: WorkspaceConfiguration) {
@ -163,9 +155,8 @@ function printChanges(fileChanges: FileChange[]) {
} }
export async function taoNew(root: string, args: string[], isVerbose = false) { export async function taoNew(root: string, args: string[], isVerbose = false) {
const logger = getLogger(isVerbose);
const ws = new Workspaces(); const ws = new Workspaces();
return handleErrors(logger, isVerbose, async () => { return handleErrors(isVerbose, async () => {
const opts = parseGenerateOpts(args, 'new', null); const opts = parseGenerateOpts(args, 'new', null);
const { schema, implementation } = ws.readGenerator( const { schema, implementation } = ws.readGenerator(
@ -181,10 +172,14 @@ export async function taoNew(root: string, args: string[], isVerbose = false) {
schema, schema,
opts.interactive opts.interactive
); );
return (await import('./ngcli-adapter')).invokeNew(logger, root, { return (await import('./ngcli-adapter')).invokeNew(
root,
{
...opts, ...opts,
generatorOptions: combinedOpts, generatorOptions: combinedOpts,
}); },
isVerbose
);
}); });
} }
@ -193,10 +188,9 @@ export async function generate(
args: string[], args: string[],
isVerbose = false isVerbose = false
) { ) {
const logger = getLogger(isVerbose);
const ws = new Workspaces(); const ws = new Workspaces();
return handleErrors(logger, isVerbose, async () => { return handleErrors(isVerbose, async () => {
const workspaceDefinition = ws.readWorkspaceConfiguration(root); const workspaceDefinition = ws.readWorkspaceConfiguration(root);
const opts = parseGenerateOpts( const opts = parseGenerateOpts(
args, args,
@ -210,7 +204,7 @@ export async function generate(
); );
if (opts.help) { if (opts.help) {
printGenHelp(opts, schema, logger as any); printGenHelp(opts, schema);
return 0; return 0;
} }
const combinedOpts = await combineOptionsForGenerator( const combinedOpts = await combineOptionsForGenerator(
@ -223,7 +217,7 @@ export async function generate(
); );
if (ws.isNxGenerator(opts.collectionName, opts.generatorName)) { if (ws.isNxGenerator(opts.collectionName, opts.generatorName)) {
const host = new FsTree(root, isVerbose, logger); const host = new FsTree(root, isVerbose);
const task = await implementation(host, combinedOpts); const task = await implementation(host, combinedOpts);
const changes = host.listChanges(); const changes = host.listChanges();
@ -237,10 +231,14 @@ export async function generate(
logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`); logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`);
} }
} else { } else {
return (await import('./ngcli-adapter')).generate(logger, root, { return (await import('./ngcli-adapter')).generate(
root,
{
...opts, ...opts,
generatorOptions: combinedOpts, generatorOptions: combinedOpts,
}); },
isVerbose
);
} }
}); });
} }

View File

@ -1,11 +1,9 @@
import { tags } from '@angular-devkit/core';
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { getLogger } from '../shared/logger'; import { logger, stripIndent } from '../shared/logger';
export function help() { export function help() {
const logger = getLogger(true); logger.info(
stripIndent(`
logger.info(tags.stripIndent`
${chalk.bold('Nx - Extensible Dev Tools for Monorepos.')} ${chalk.bold('Nx - Extensible Dev Tools for Monorepos.')}
${chalk.bold('Create a new project.')} ${chalk.bold('Create a new project.')}
@ -30,6 +28,7 @@ export function help() {
${chalk.bold('Run migrations.')} ${chalk.bold('Run migrations.')}
nx migrate ${chalk.grey('--run-migrations=[filename]')} nx migrate ${chalk.grey('--run-migrations=[filename]')}
`); `)
);
return 0; return 0;
} }

View File

@ -1,4 +1,3 @@
import { logging } from '@angular-devkit/core';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import * as fs from 'fs'; import * as fs from 'fs';
import { readFileSync, writeFileSync } from 'fs'; import { readFileSync, writeFileSync } from 'fs';
@ -7,14 +6,15 @@ import { dirname, join } from 'path';
import { gt, lte } from 'semver'; import { gt, lte } from 'semver';
import * as stripJsonComments from 'strip-json-comments'; import * as stripJsonComments from 'strip-json-comments';
import { dirSync } from 'tmp'; import { dirSync } from 'tmp';
import { getLogger } from '../shared/logger'; import { logger } from '../shared/logger';
import { convertToCamelCase, handleErrors } from '../shared/params'; import { convertToCamelCase, handleErrors } from '../shared/params';
import { import {
detectPackageManager, detectPackageManager,
getPackageManagerCommand, getPackageManagerCommand,
} from '@nrwl/tao/src/shared/package-manager'; } from '../shared/package-manager';
import { FsTree } from '@nrwl/tao/src/shared/tree'; import { FsTree } from '../shared/tree';
import { flushChanges } from '@nrwl/tao/src/commands/generate'; import { flushChanges } from './generate';
import * as fsExtra from 'fs-extra';
export type MigrationsJson = { export type MigrationsJson = {
version: string; version: string;
@ -414,7 +414,7 @@ function versions(root: string, from: { [p: string]: string }) {
} }
// testing-fetch-start // testing-fetch-start
function createFetcher(packageManager: string, logger: logging.Logger) { function createFetcher(packageManager: string) {
const cache = {}; const cache = {};
return async function f( return async function f(
packageName: string, packageName: string,
@ -429,11 +429,7 @@ function createFetcher(packageManager: string, logger: logging.Logger) {
cwd: dir, cwd: dir,
}); });
const migrationsFilePath = packageToMigrationsFilePath( const migrationsFilePath = packageToMigrationsFilePath(packageName, dir);
logger,
packageName,
dir
);
const packageJsonPath = require.resolve(`${packageName}/package.json`, { const packageJsonPath = require.resolve(`${packageName}/package.json`, {
paths: [dir], paths: [dir],
}); });
@ -463,11 +459,7 @@ function createFetcher(packageManager: string, logger: logging.Logger) {
} }
// testing-fetch-end // testing-fetch-end
function packageToMigrationsFilePath( function packageToMigrationsFilePath(packageName: string, dir: string) {
logger: logging.Logger,
packageName: string,
dir: string
) {
const packageJsonPath = require.resolve(`${packageName}/package.json`, { const packageJsonPath = require.resolve(`${packageName}/package.json`, {
paths: [dir], paths: [dir],
}); });
@ -536,7 +528,6 @@ function updatePackageJson(
} }
async function generateMigrationsJsonAndUpdatePackageJson( async function generateMigrationsJsonAndUpdatePackageJson(
logger: logging.Logger,
root: string, root: string,
opts: { opts: {
targetPackage: string; targetPackage: string;
@ -552,7 +543,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
logger.info(`It may take a few minutes.`); logger.info(`It may take a few minutes.`);
const migrator = new Migrator({ const migrator = new Migrator({
versions: versions(root, opts.from), versions: versions(root, opts.from),
fetch: createFetcher(packageManager, logger), fetch: createFetcher(packageManager),
from: opts.from, from: opts.from,
to: opts.to, to: opts.to,
}); });
@ -603,11 +594,7 @@ async function generateMigrationsJsonAndUpdatePackageJson(
} }
} }
async function runMigrations( async function runMigrations(root: string, opts: { runMigrations: string }) {
logger: logging.Logger,
root: string,
opts: { runMigrations: string }
) {
const migrations: { const migrations: {
package: string; package: string;
name: string; name: string;
@ -620,10 +607,9 @@ async function runMigrations(
for (let m of migrations) { for (let m of migrations) {
logger.info(`Running migration ${m.name}`); logger.info(`Running migration ${m.name}`);
if (m.cli === 'nx') { if (m.cli === 'nx') {
await runNxMigration(logger, root, m.package, m.name); await runNxMigration(root, m.package, m.name);
} else { } else {
await (await import('./ngcli-adapter')).runMigration( await (await import('./ngcli-adapter')).runMigration(
logger,
root, root,
m.package, m.package,
m.name m.name
@ -634,13 +620,8 @@ async function runMigrations(
} }
} }
async function runNxMigration( async function runNxMigration(root: string, packageName: string, name: string) {
logger: logging.Logger, const collectionPath = packageToMigrationsFilePath(packageName, root);
root: string,
packageName: string,
name: string
) {
const collectionPath = packageToMigrationsFilePath(logger, packageName, root);
const collection = JSON.parse(fs.readFileSync(collectionPath).toString()); const collection = JSON.parse(fs.readFileSync(collectionPath).toString());
const g = collection.generators || collection.schematics; const g = collection.generators || collection.schematics;
const implRelativePath = g[name].implementation || g[name].factory; const implRelativePath = g[name].implementation || g[name].factory;
@ -648,21 +629,28 @@ async function runNxMigration(
paths: [dirname(collectionPath)], paths: [dirname(collectionPath)],
}); });
const fn = require(implPath).default; const fn = require(implPath).default;
const host = new FsTree(root, false, logger as any); const host = new FsTree(root, false);
await fn(host, {}); await fn(host, {});
const changes = host.listChanges(); const changes = host.listChanges();
flushChanges(root, changes); flushChanges(root, changes);
} }
export async function migrate(root: string, args: string[], isVerbose = false) { function removeNxDepsIfCaseItsFormatChanged(root: string) {
const logger = getLogger(isVerbose); try {
fsExtra.unlinkSync(
join(root, 'node_modules', '.cache', 'nx', 'nxdeps.json')
);
} catch (e) {}
}
return handleErrors(logger, isVerbose, async () => { export async function migrate(root: string, args: string[], isVerbose = false) {
return handleErrors(isVerbose, async () => {
removeNxDepsIfCaseItsFormatChanged(root);
const opts = parseMigrationsOptions(args); const opts = parseMigrationsOptions(args);
if (opts.type === 'generateMigrations') { if (opts.type === 'generateMigrations') {
await generateMigrationsJsonAndUpdatePackageJson(logger, root, opts); await generateMigrationsJsonAndUpdatePackageJson(root, opts);
} else { } else {
await runMigrations(logger, root, opts); await runMigrations(root, opts);
} }
}); });
} }

View File

@ -11,7 +11,7 @@ import {
workspaces, workspaces,
} from '@angular-devkit/core'; } from '@angular-devkit/core';
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { NodeJsSyncHost } from '@angular-devkit/core/node'; import { createConsoleLogger, NodeJsSyncHost } from '@angular-devkit/core/node';
import { RunOptions } from './run'; import { RunOptions } from './run';
import { import {
FileSystemCollectionDescription, FileSystemCollectionDescription,
@ -43,8 +43,10 @@ import * as stripJsonComments from 'strip-json-comments';
import { FileBuffer } from '@angular-devkit/core/src/virtual-fs/host/interface'; import { FileBuffer } from '@angular-devkit/core/src/virtual-fs/host/interface';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { NX_ERROR, NX_PREFIX } from '../shared/logger';
export async function run(logger: any, root: string, opts: RunOptions) { export async function run(root: string, opts: RunOptions, verbose: boolean) {
const logger = getLogger(verbose);
const fsHost = new NxScopedHost(normalize(root)); const fsHost = new NxScopedHost(normalize(root));
const { workspace } = await workspaces.readWorkspace( const { workspace } = await workspaces.readWorkspace(
workspaceConfigName(root), workspaceConfigName(root),
@ -341,10 +343,11 @@ class NxScopedHost extends virtualFs.ScopedHost<any> {
} }
export async function generate( export async function generate(
logger: logging.Logger,
root: string, root: string,
opts: GenerateOptions opts: GenerateOptions,
verbose: boolean
) { ) {
const logger = getLogger(verbose);
const fsHost = new NxScopedHost(normalize(root)); const fsHost = new NxScopedHost(normalize(root));
const workflow = createWorkflow(fsHost, root, opts); const workflow = createWorkflow(fsHost, root, opts);
const collection = getCollection(workflow, opts.collectionName); const collection = getCollection(workflow, opts.collectionName);
@ -353,7 +356,7 @@ export async function generate(
await runSchematic( await runSchematic(
root, root,
workflow, workflow,
logger, logger as any,
{ ...opts, generatorName: schematic.description.name }, { ...opts, generatorName: schematic.description.name },
schematic schematic
) )
@ -361,20 +364,19 @@ export async function generate(
} }
export async function runMigration( export async function runMigration(
logger: logging.Logger,
root: string, root: string,
collection: string, collection: string,
schematic: string schematic: string
) { ) {
const host = new NxScopedHost(normalize(root)); const host = new NxScopedHost(normalize(root));
const workflow = new MigrationsWorkflow(host, logger); const workflow = new MigrationsWorkflow(host, logger as any);
return workflow return workflow
.execute({ .execute({
collection, collection,
schematic, schematic,
options: {}, options: {},
debug: false, debug: false,
logger, logger: logger as any,
}) })
.toPromise(); .toPromise();
} }
@ -452,10 +454,11 @@ export function wrapAngularDevkitSchematic(
} }
export async function invokeNew( export async function invokeNew(
logger: logging.Logger,
root: string, root: string,
opts: GenerateOptions opts: GenerateOptions,
verbose: boolean
) { ) {
const logger = getLogger(verbose);
const fsHost = new NxScopedHost(normalize(root)); const fsHost = new NxScopedHost(normalize(root));
const workflow = createWorkflow(fsHost, root, opts); const workflow = createWorkflow(fsHost, root, opts);
const collection = getCollection(workflow, opts.collectionName); const collection = getCollection(workflow, opts.collectionName);
@ -464,9 +467,33 @@ export async function invokeNew(
await runSchematic( await runSchematic(
root, root,
workflow, workflow,
logger, logger as any,
{ ...opts, generatorName: schematic.description.name }, { ...opts, generatorName: schematic.description.name },
schematic schematic
) )
).status; ).status;
} }
let logger: logging.Logger;
export const getLogger = (isVerbose = false): any => {
if (!logger) {
logger = createConsoleLogger(isVerbose, process.stdout, process.stderr, {
warn: (s) => chalk.bold(chalk.yellow(s)),
error: (s) => {
if (s.startsWith('NX ')) {
return `\n${NX_ERROR} ${chalk.bold(chalk.red(s.substr(3)))}\n`;
}
return chalk.bold(chalk.red(s));
},
info: (s) => {
if (s.startsWith('NX ')) {
return `\n${NX_PREFIX} ${chalk.bold(s.substr(3))}\n`;
}
return chalk.white(s);
},
});
}
return logger;
};

View File

@ -1,5 +1,4 @@
import * as minimist from 'minimist'; import * as minimist from 'minimist';
import { getLogger } from '../shared/logger';
import { import {
combineOptionsForExecutor, combineOptionsForExecutor,
convertToCamelCase, convertToCamelCase,
@ -15,6 +14,7 @@ import {
} from '../shared/workspace'; } from '../shared/workspace';
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { logger } from '../shared/logger';
export interface RunOptions { export interface RunOptions {
project: string; project: string;
@ -32,8 +32,7 @@ function throwInvalidInvocation() {
function parseRunOpts( function parseRunOpts(
args: string[], args: string[],
defaultProjectName: string | null, defaultProjectName: string | null
logger: Console
): RunOptions { ): RunOptions {
const runOptions = convertToCamelCase( const runOptions = convertToCamelCase(
minimist(args, { minimist(args, {
@ -81,12 +80,8 @@ function parseRunOpts(
return res; return res;
} }
export function printRunHelp( export function printRunHelp(opts: RunOptions, schema: Schema) {
opts: RunOptions, printHelp(`nx run ${opts.project}:${opts.target}`, schema);
schema: Schema,
logger: Console
) {
printHelp(`nx run ${opts.project}:${opts.target}`, schema, logger as any);
} }
export function validateTargetAndConfiguration( export function validateTargetAndConfiguration(
@ -136,12 +131,11 @@ export interface TargetContext {
} }
export async function run(root: string, args: string[], isVerbose: boolean) { export async function run(root: string, args: string[], isVerbose: boolean) {
const logger = getLogger(isVerbose) as any;
const ws = new Workspaces(); const ws = new Workspaces();
return handleErrors(logger, isVerbose, async () => { return handleErrors(isVerbose, async () => {
const workspace = ws.readWorkspaceConfiguration(root); const workspace = ws.readWorkspaceConfiguration(root);
const opts = parseRunOpts(args, workspace.defaultProject, logger); const opts = parseRunOpts(args, workspace.defaultProject);
validateTargetAndConfiguration(workspace, opts); validateTargetAndConfiguration(workspace, opts);
const target = workspace.projects[opts.project].targets[opts.target]; const target = workspace.projects[opts.project].targets[opts.target];
@ -154,17 +148,21 @@ export async function run(root: string, args: string[], isVerbose: boolean) {
schema schema
); );
if (opts.help) { if (opts.help) {
printRunHelp(opts, schema, logger); printRunHelp(opts, schema);
return 0; return 0;
} }
if (ws.isNxExecutor(nodeModule, executor)) { if (ws.isNxExecutor(nodeModule, executor)) {
return await implementation(combinedOptions, { root, target, workspace }); return await implementation(combinedOptions, { root, target, workspace });
} else { } else {
return (await import('./ngcli-adapter')).run(logger, root, { return (await import('./ngcli-adapter')).run(
root,
{
...opts, ...opts,
runOptions: combinedOptions, runOptions: combinedOptions,
}); },
isVerbose
);
} }
}); });
} }

View File

@ -1,34 +1,44 @@
import { logging } from '@angular-devkit/core';
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { createConsoleLogger } from '@angular-devkit/core/node';
const NX_PREFIX = `${chalk.cyan('>')} ${chalk.inverse( export const NX_PREFIX = `${chalk.cyan('>')} ${chalk.inverse(
chalk.bold(chalk.cyan(' NX ')) chalk.bold(chalk.cyan(' NX '))
)}`; )}`;
const NX_ERROR = chalk.inverse(chalk.bold(chalk.red(' ERROR '))); export const NX_ERROR = chalk.inverse(chalk.bold(chalk.red(' ERROR ')));
let logger: logging.Logger; export const logger = {
export const getLogger = (isVerbose = false): any => { warn: (s) => console.warn(chalk.bold(chalk.yellow(s))),
if (!logger) {
logger = createConsoleLogger(isVerbose, process.stdout, process.stderr, {
warn: (s) => chalk.bold(chalk.yellow(s)),
error: (s) => { error: (s) => {
if (s.startsWith('NX ')) { if (s.startsWith('NX ')) {
return `\n${NX_ERROR} ${chalk.bold(chalk.red(s.substr(3)))}\n`; console.error(`\n${NX_ERROR} ${chalk.bold(chalk.red(s.substr(3)))}\n`);
} else {
console.error(chalk.bold(chalk.red(s)));
} }
return chalk.bold(chalk.red(s));
}, },
info: (s) => { info: (s) => {
if (s.startsWith('NX ')) { if (s.startsWith('NX ')) {
return `\n${NX_PREFIX} ${chalk.bold(s.substr(3))}\n`; console.info(`\n${NX_PREFIX} ${chalk.bold(s.substr(3))}\n`);
} else {
console.info(chalk.white(s));
} }
return chalk.white(s);
}, },
}); log: (...s) => {
} console.log(...s);
},
return logger; debug: (...s) => {
console.debug(...s);
},
fatal: (...s) => {
console.error(...s);
},
}; };
export function stripIndent(str: string): string {
const match = str.match(/^[ \t]*(?=\S)/gm);
if (!match) {
return str;
}
const indent = match.reduce((r, a) => Math.min(r, a.length), Infinity);
const regex = new RegExp(`^[ \\t]{${indent}}`, 'gm');
return str.replace(regex, '');
}

View File

@ -1,7 +1,7 @@
import { strings } from '@angular-devkit/core';
import { ParsedArgs } from 'minimist'; import { ParsedArgs } from 'minimist';
import { TargetConfiguration, WorkspaceConfiguration } from './workspace'; import { TargetConfiguration, WorkspaceConfiguration } from './workspace';
import * as inquirer from 'inquirer'; import * as inquirer from 'inquirer';
import { logger } from './logger';
type Properties = { type Properties = {
[p: string]: { [p: string]: {
@ -34,11 +34,7 @@ export type Options = {
[k: string]: string | number | boolean | string[] | Unmatched[]; [k: string]: string | number | boolean | string[] | Unmatched[];
}; };
export async function handleErrors( export async function handleErrors(isVerbose: boolean, fn: Function) {
logger: Console,
isVerbose: boolean,
fn: Function
) {
try { try {
return await fn(); return await fn();
} catch (err) { } catch (err) {
@ -434,13 +430,44 @@ export function lookupUnmatched(opts: Options, schema: Schema): Options {
opts['--'].forEach((unmatched) => { opts['--'].forEach((unmatched) => {
unmatched.possible = props.filter( unmatched.possible = props.filter(
(p) => strings.levenshtein(p, unmatched.name) < 3 (p) => levenshtein(p, unmatched.name) < 3
); );
}); });
} }
return opts; return opts;
} }
function levenshtein(a: string, b: string) {
if (a.length == 0) {
return b.length;
}
if (b.length == 0) {
return a.length;
}
const matrix = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
matrix[i][j - 1] + 1,
matrix[i - 1][j] + 1
);
}
}
}
return matrix[b.length][a.length];
}
function isTTY(): boolean { function isTTY(): boolean {
return !!process.stdout.isTTY && process.env['CI'] !== 'true'; return !!process.stdout.isTTY && process.env['CI'] !== 'true';
} }

View File

@ -1,6 +1,6 @@
import { logging, tags } from '@angular-devkit/core';
import { Schema } from './params'; import { Schema } from './params';
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { logger, stripIndent } from '../shared/logger';
function formatOption(name: string, description: string) { function formatOption(name: string, description: string) {
return ` --${(name + ' ').substr(0, 22)}${chalk.grey( return ` --${(name + ' ').substr(0, 22)}${chalk.grey(
@ -8,11 +8,7 @@ function formatOption(name: string, description: string) {
)}`; )}`;
} }
export function printHelp( export function printHelp(header: string, schema: Schema) {
header: string,
schema: Schema,
logger: logging.Logger
) {
const allPositional = Object.keys(schema.properties).filter((key) => { const allPositional = Object.keys(schema.properties).filter((key) => {
const p = schema.properties[key]; const p = schema.properties[key];
return p['$default'] && p['$default']['$source'] === 'argv'; return p['$default'] && p['$default']['$source'] === 'argv';
@ -26,11 +22,13 @@ export function printHelp(
}) })
.join('\n'); .join('\n');
logger.info(tags.stripIndent` logger.info(
stripIndent(`
${chalk.bold(header + positional + ' [options,...]')} ${chalk.bold(header + positional + ' [options,...]')}
${chalk.bold('Options')}: ${chalk.bold('Options')}:
${args} ${args}
${formatOption('help', 'Show available options for project target.')} ${formatOption('help', 'Show available options for project target.')}
`); `)
);
} }

View File

@ -22,7 +22,7 @@ describe('tree', () => {
'child content' 'child content'
); );
tree = new FsTree(dir, false, console); tree = new FsTree(dir, false);
}); });
afterEach(() => { afterEach(() => {

View File

@ -7,6 +7,7 @@ import {
writeFileSync, writeFileSync,
} from 'fs'; } from 'fs';
import { mkdirpSync, rmdirSync } from 'fs-extra'; import { mkdirpSync, rmdirSync } from 'fs-extra';
import { logger } from './logger';
const chalk = require('chalk'); const chalk = require('chalk');
/** /**
@ -84,11 +85,7 @@ export class FsTree implements Tree {
[path: string]: { content: Buffer | null; isDeleted: boolean }; [path: string]: { content: Buffer | null; isDeleted: boolean };
} = {}; } = {};
constructor( constructor(readonly root: string, private readonly isVerbose: boolean) {}
readonly root: string,
private readonly isVerbose: boolean,
private readonly logger: Console
) {}
read(filePath: string): Buffer | null { read(filePath: string): Buffer | null {
try { try {
@ -99,7 +96,7 @@ export class FsTree implements Tree {
} }
} catch (e) { } catch (e) {
if (this.isVerbose) { if (this.isVerbose) {
this.logger.error(e); logger.error(e);
} }
return null; return null;
} }
@ -113,7 +110,7 @@ export class FsTree implements Tree {
}; };
} catch (e) { } catch (e) {
if (this.isVerbose) { if (this.isVerbose) {
this.logger.error(e); logger.error(e);
} }
} }
} }