all-contributors-cli/src/cli.js
2018-02-23 15:13:41 +01:00

170 lines
4.6 KiB
JavaScript
Executable file

#!/usr/bin/env node
/* eslint-disable no-console */
const path = require('path')
const yargs = require('yargs')
const chalk = require('chalk')
const inquirer = require('inquirer')
const init = require('./init')
const generate = require('./generate')
const util = require('./util')
const repo = require('./repo')
const updateContributors = require('./contributors')
const cwd = process.cwd()
const defaultRCFile = path.join(cwd, '.all-contributorsrc')
const yargv = yargs
.help('help')
.alias('h', 'help')
.alias('v', 'version')
.version()
.command('generate', 'Generate the list of contributors')
.usage('Usage: $0 generate')
.command('add', 'add a new contributor')
.usage('Usage: $0 add <username> <contribution>')
.command('init', 'Prepare the project to be used with this tool')
.usage('Usage: $0 init')
.command(
'check',
'Compares contributors from the repository with the ones credited in .all-contributorsrc',
)
.usage('Usage: $0 check')
.boolean('commit')
.default('files', ['README.md'])
.default('contributorsPerLine', 7)
.default('contributors', [])
.default('config', defaultRCFile)
.config('config', configPath => {
try {
return util.configFile.readConfig(configPath)
} catch (error) {
if (configPath !== defaultRCFile) {
onError(error)
}
}
}).argv
function startGeneration(argv) {
return Promise.all(
argv.files.map(file => {
const filePath = path.join(cwd, file)
return util.markdown.read(filePath).then(fileContent => {
const newFileContent = generate(argv, argv.contributors, fileContent)
return util.markdown.write(filePath, newFileContent)
})
}),
)
}
function addContribution(argv) {
const username = argv._[1]
const contributions = argv._[2]
// Add or update contributor in the config file
return updateContributors(argv, username, contributions).then(data => {
argv.contributors = data.contributors
return startGeneration(argv).then(() => {
if (argv.commit) {
return util.git.commit(argv, data)
}
})
})
}
function checkContributors(argv) {
const configData = util.configFile.readConfig(argv.config)
return repo
.getContributors(configData.projectOwner, configData.projectName, configData.repoType, configData.repoHost)
.then(repoContributors => {
const checkKey = repo.getCheckKey(configData.repoType)
const knownContributions = configData.contributors.reduce((obj, item) => {
obj[item[checkKey]] = item.contributions
return obj
}, {})
const knownContributors = configData.contributors.map(
contributor => contributor[checkKey],
)
const missingInConfig = repoContributors.filter(
key => !knownContributors.includes(key),
)
const missingFromRepo = knownContributors.filter(key => {
return (
!repoContributors.includes(key) &&
(knownContributions[key].includes('code') ||
knownContributions[key].includes('test'))
)
})
if (missingInConfig.length) {
process.stdout.write(
chalk.bold('Missing contributors in .all-contributorsrc:\n'),
)
process.stdout.write(` ${missingInConfig.join(', ')}\n`)
}
if (missingFromRepo.length) {
process.stdout.write(
chalk.bold('Unknown contributors found in .all-contributorsrc:\n'),
)
process.stdout.write(`${missingFromRepo.join(', ')}\n`)
}
})
}
function onError(error) {
if (error) {
console.error(error.message)
process.exit(1)
}
process.exit(0)
}
function promptForCommand(argv) {
const questions = [
{
type: 'list',
name: 'command',
message: 'What do you want to do?',
choices: [
{
name: 'Add a new contributor or add a new contribution type',
value: 'add',
},
{
name: 'Re-generate the contributors list',
value: 'generate',
},
{
name: 'Compare contributors from the repository with the credited ones',
value: 'check',
},
],
when: !argv._[0],
default: 0,
},
]
return inquirer.prompt(questions).then(answers => {
return answers.command || argv._[0]
})
}
promptForCommand(yargv)
.then(command => {
switch (command) {
case 'init':
return init()
case 'generate':
return startGeneration(yargv)
case 'add':
return addContribution(yargv)
case 'check':
return checkContributors(yargv)
default:
throw new Error(`Unknown command ${command}`)
}
})
.catch(onError)