diff --git a/packages/cli/generators/copyright/header.js b/packages/cli/generators/copyright/header.js index cc3fd049ce8b..ed19ff4c7d07 100644 --- a/packages/cli/generators/copyright/header.js +++ b/packages/cli/generators/copyright/header.js @@ -7,6 +7,7 @@ const _ = require('lodash'); const git = require('./git'); const path = require('path'); const fs = require('fs-extra'); +const chalk = require('chalk'); const Project = require('@lerna/project'); const {promisify} = require('util'); @@ -155,7 +156,8 @@ async function ensureHeader(file, pkg, options = {}) { if (!options.dryRun) { await fs.writeFile(file, content, 'utf8'); } else { - console.log(file, header); + const log = options.log || console.log; + log(file, header); } return content; } @@ -250,14 +252,16 @@ async function updateFileHeaders(projectRoot, options = {}) { async function updateFileHeadersForSinglePackage(projectRoot, options) { debug('Options', options); debug('Project root: %s', projectRoot); + const log = options.log || console.log; const pkgFile = path.join(projectRoot, 'package.json'); const exists = await fs.exists(pkgFile); if (!exists) { - console.error('No package.json exists at %s.', projectRoot); + log(chalk.red(`No package.json exists at ${projectRoot}`)); return; } const pkg = await fs.readJson(pkgFile); - console.log( + + log( 'Updating project %s (%s)', pkg.name, path.relative(process.cwd(), projectRoot) || '.', diff --git a/packages/cli/generators/copyright/index.js b/packages/cli/generators/copyright/index.js index eac5fe78a8eb..4590fee41608 100644 --- a/packages/cli/generators/copyright/index.js +++ b/packages/cli/generators/copyright/index.js @@ -26,6 +26,12 @@ module.exports = class CopyrightGenerator extends BaseGenerator { required: false, description: g.f('License'), }); + this.option('gitOnly', { + type: Boolean, + required: false, + default: true, + description: g.f('Only update git tracked files'), + }); return super.setOptions(); } @@ -64,6 +70,8 @@ module.exports = class CopyrightGenerator extends BaseGenerator { this.headerOptions = { copyrightOwner: answers.owner || this.options.owner, license: answers.license || this.options.license, + log: this.log, + gitOnly: this.options.gitOnly, }; } diff --git a/packages/cli/test/fixtures/copyright/application.ts b/packages/cli/test/fixtures/copyright/application.ts new file mode 100644 index 000000000000..cd003e7cb1f2 --- /dev/null +++ b/packages/cli/test/fixtures/copyright/application.ts @@ -0,0 +1,6 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: myapp +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +export class MyApplication {} diff --git a/packages/cli/test/fixtures/copyright/index.js b/packages/cli/test/fixtures/copyright/index.js new file mode 100644 index 000000000000..0c16c5231588 --- /dev/null +++ b/packages/cli/test/fixtures/copyright/index.js @@ -0,0 +1,30 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +const fs = require('fs'); + +exports.SANDBOX_FILES = [ + { + path: 'src', + file: 'application.ts', + content: fs.readFileSync(require.resolve('./application.ts'), { + encoding: 'utf-8', + }), + }, + { + path: 'lib', + file: 'no-header.js', + content: fs.readFileSync(require.resolve('./no-header.js'), { + encoding: 'utf-8', + }), + }, + { + path: '', + file: 'package.json', + content: fs.readFileSync(require.resolve('./package.json.txt'), { + encoding: 'utf-8', + }), + }, +]; diff --git a/packages/cli/test/fixtures/copyright/no-header.js b/packages/cli/test/fixtures/copyright/no-header.js new file mode 100644 index 000000000000..4ed25f524c47 --- /dev/null +++ b/packages/cli/test/fixtures/copyright/no-header.js @@ -0,0 +1,2 @@ +// XYZ +exports.xyz = {}; diff --git a/packages/cli/test/fixtures/copyright/package.json.txt b/packages/cli/test/fixtures/copyright/package.json.txt new file mode 100644 index 000000000000..15f8d1b0e803 --- /dev/null +++ b/packages/cli/test/fixtures/copyright/package.json.txt @@ -0,0 +1,5 @@ +{ + "name": "myapp", + "copyright.owner": "ACME Inc.", + "license": "MIT" +} diff --git a/packages/cli/test/integration/generators/copyright.integration.js b/packages/cli/test/integration/generators/copyright.integration.js new file mode 100644 index 000000000000..86aea68b3049 --- /dev/null +++ b/packages/cli/test/integration/generators/copyright.integration.js @@ -0,0 +1,87 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +const path = require('path'); +const assert = require('yeoman-assert'); +const testlab = require('@loopback/testlab'); +const TestSandbox = testlab.TestSandbox; + +const generator = path.join(__dirname, '../../../generators/copyright'); +const SANDBOX_FILES = require('../../fixtures/copyright').SANDBOX_FILES; +const testUtils = require('../../test-utils'); + +// Test Sandbox +const SANDBOX_PATH = path.resolve(__dirname, '..', '.sandbox'); +const sandbox = new TestSandbox(SANDBOX_PATH); + +const year = new Date().getFullYear(); + +describe('lb4 copyright', function () { + // eslint-disable-next-line no-invalid-this + this.timeout(30000); + + beforeEach('reset sandbox', async () => { + await sandbox.reset(); + }); + + it('updates copyright/license headers with prompts', async () => { + await testUtils + .executeGenerator(generator) + .inDir(SANDBOX_PATH, () => + testUtils.givenLBProject(SANDBOX_PATH, { + excludePackageJSON: true, + additionalFiles: SANDBOX_FILES, + }), + ) + .withPrompts({owner: 'ACME Inc.', license: 'ISC'}) + .withOptions({gitOnly: false}); + + assertApplicationTsFileUpdated(); + assertJsFileUpdated(); + }); + + it('updates copyright/license headers with options', async () => { + await testUtils + .executeGenerator(generator) + .inDir(SANDBOX_PATH, () => + testUtils.givenLBProject(SANDBOX_PATH, { + excludePackageJSON: true, + additionalFiles: SANDBOX_FILES, + }), + ) + .withOptions({owner: 'ACME Inc.', license: 'ISC', gitOnly: false}); + + assertApplicationTsFileUpdated(); + assertJsFileUpdated(); + }); +}); + +function assertApplicationTsFileUpdated() { + const file = path.join(SANDBOX_PATH, 'src', 'application.ts'); + assertHeader(file); +} + +function assertHeader(file) { + assert.fileContent( + file, + `// Copyright ACME Inc. ${year}. All Rights Reserved.`, + ); + assert.fileContent(file, '// Node module: myapp'); + assert.fileContent( + file, + '// This file is licensed under the ISC License (ISC).', + ); + assert.fileContent( + file, + '// License text available at https://opensource.org/licenses/ISC', + ); +} + +function assertJsFileUpdated() { + const file = path.join(SANDBOX_PATH, 'lib', 'no-header.js'); + assertHeader(file); +}