UNPKG

source-licenser

Version:

Add license information to source files.

111 lines (97 loc) 3.41 kB
/** * @license * [BSD-3-Clause](https://github.com/perki/source-licenser/blob/master/LICENSE) */ const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); const fs = require('fs'); const path = require('path'); const glob = require('fast-glob'); const logger = require('./logger'); const loadConfig = require('./loadConfig'); const substitutions = require('./substitutions'); const actions = require('./actions'); const { exit } = require('process'); (async () => { // parse command line args const argv = yargs(hideBin(process.argv)) .usage('Usage: $0 [options] <target directory>') .demandOption('c', logger.formatError('You must specify the configuration file')) .demandCommand(1, logger.formatError('You must specify the target directory')) .option('c', { alias: 'config-file', describe: 'Configuration file', type: 'string', nargs: 1 }) .help('help') .alias('v', 'version') .argv; // make sure specified files exist const configFilePath = path.resolve(argv.configFile); if (!fs.existsSync(configFilePath)) { logger.error(`Config file '${argv.configFile}' not found`); exit(1); } const targetDirPath = path.resolve(argv._[0]); if (!fs.existsSync(targetDirPath) || !fs.lstatSync(targetDirPath).isDirectory()) { logger.error(`'${argv._}' not found or not a directory`); exit(1); } logger.heading('Initializing...'); let config; try { config = loadConfig(configFilePath); } catch (e) { logger.error(`Could not load configuration file: ${e.message}`); exit(1); } substitutions.init(config.substitutions); const files = {}; try { const defaultLicense = substitutions.apply(config.license); for (const [pattern, fileActionsConfig] of Object.entries(config.files)) { files[pattern] = []; for (const [actionId, actionSettings] of Object.entries(fileActionsConfig)) { if (!actions[actionId]) { throw new Error(`Unknown action '${actionId}' for ${pattern}`); } const action = Object.create(actions[actionId]); action.init(substitutions.apply(actionSettings), defaultLicense); files[pattern].push(action); } logger.info(`✓ ${pattern}${Object.keys(fileActionsConfig).join(', ')}`); } } catch (e) { logger.error(`Initialization failed: ${e.message}`); exit(1); } logger.heading('\nGo!'); const startTime = Date.now(); let totalCount = 0; let updatedCount = 0; const globOptions = { cwd: targetDirPath, ignore: config.ignore }; for (const [pattern, fileActions] of Object.entries(files)) { const matches = await glob(pattern, globOptions); if (matches.length === 0) { logger.warning(`Found no file matching '${pattern}'`); } for (const filePath of matches) { for (const action of fileActions) { const changed = await action.apply(path.join(targetDirPath, filePath)); totalCount++; if (changed) { logger.info(`✓ ${filePath}${action.id} updated`); updatedCount++; } else { logger.debug(${filePath}${action.id} skipped (up-to-date)`); } } } } const elapsedTime = Math.round((Date.now() - startTime) / 10) / 100; logger.info(`\nUpdated ${updatedCount} out of ${totalCount} files in ${elapsedTime}s`); })();