mirror of
https://github.com/all-contributors/cli.git
synced 2025-01-10 05:56:29 +00:00
Adding contributors to config file
This commit is contained in:
parent
f2c8733e03
commit
ff7457c825
7 changed files with 281 additions and 15 deletions
28
cli.js
28
cli.js
|
@ -7,20 +7,23 @@ var assign = require('lodash.assign');
|
||||||
|
|
||||||
var generate = require('./lib/generate');
|
var generate = require('./lib/generate');
|
||||||
var markdown = require('./lib/markdown');
|
var markdown = require('./lib/markdown');
|
||||||
var getUserInfo = require('./lib/github');
|
var updateContributors = require('./lib/contributors');
|
||||||
|
|
||||||
var cwd = process.cwd();
|
var cwd = process.cwd();
|
||||||
var defaultRCFile = path.join(cwd, '.all-contributorsrc');
|
var defaultRCFile = path.join(cwd, '.all-contributorsrc');
|
||||||
|
|
||||||
var argv = require('yargs')
|
var argv = require('yargs')
|
||||||
|
.help('help')
|
||||||
|
.alias('h', 'help')
|
||||||
.command('generate', 'Generate the list of contributors')
|
.command('generate', 'Generate the list of contributors')
|
||||||
.usage('Usage: $0 generate')
|
.usage('Usage: $0 generate')
|
||||||
.command('add', 'add a new contributor')
|
.command('add', 'add a new contributor')
|
||||||
.usage('Usage: $0 add <username> <contribution>')
|
.usage('Usage: $0 add <username> <contribution>')
|
||||||
.demand(2)
|
.demand(2)
|
||||||
.default('config', defaultRCFile)
|
|
||||||
.default('file', 'README.md')
|
.default('file', 'README.md')
|
||||||
.default('contributorsPerLine', 7)
|
.default('contributorsPerLine', 7)
|
||||||
|
.default('contributors', [])
|
||||||
|
.default('config', defaultRCFile)
|
||||||
.config('config', function(configPath) {
|
.config('config', function(configPath) {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
||||||
|
@ -31,7 +34,6 @@ var argv = require('yargs')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.help('help')
|
|
||||||
.argv;
|
.argv;
|
||||||
|
|
||||||
argv.file = path.join(cwd, argv.file);
|
argv.file = path.join(cwd, argv.file);
|
||||||
|
@ -52,19 +54,19 @@ function onError(error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[0] === 'generate') {
|
var command = argv._[0];
|
||||||
|
|
||||||
|
if (command === 'generate') {
|
||||||
startGeneration(argv, onError);
|
startGeneration(argv, onError);
|
||||||
} else if (argv[0] === 'add') {
|
} else if (command === 'add') {
|
||||||
// Fetch user
|
var username = argv._[1];
|
||||||
argv.username = argv._[1];
|
var contributions = argv._[2];
|
||||||
argv.contributions = argv._[2].split(',');
|
// Add/update contributor and save him to the config file
|
||||||
getUserInfo(argv.username, function(error, user) {
|
updateContributors(argv, username, contributions, function(error, contributors) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return console.error(error);
|
return onError(error);
|
||||||
}
|
}
|
||||||
// TODO
|
argv.contributors = contributors;
|
||||||
// Add him to the contributors
|
|
||||||
// Save rc file with updated contributors key
|
|
||||||
startGeneration(argv, onError);
|
startGeneration(argv, onError);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
28
lib/configFile.js
Normal file
28
lib/configFile.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var _ = require('lodash/fp');
|
||||||
|
|
||||||
|
function formatCommaFirst(o) {
|
||||||
|
return JSON.stringify(o, null, 2)
|
||||||
|
.split(/(,\n\s+)/)
|
||||||
|
.map(function (e, i) {
|
||||||
|
return i%2 ? '\n'+e.substring(4)+', ' : e
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function readConfig(configPath) {
|
||||||
|
return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeContributors(configPath, contributors, cb) {
|
||||||
|
var config = readConfig(configPath);
|
||||||
|
var content = _.assign(config, { contributors: contributors });
|
||||||
|
return fs.writeFile(configPath, formatCommaFirst(content), cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
readConfig: readConfig,
|
||||||
|
writeContributors: writeContributors
|
||||||
|
}
|
57
lib/contributors/add.js
Normal file
57
lib/contributors/add.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('lodash/fp');
|
||||||
|
|
||||||
|
function matchContribution(type) {
|
||||||
|
return function(existing) {
|
||||||
|
return type === existing || type === existing.type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniqueTypes(contribution) {
|
||||||
|
return contribution.type || contribution;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatContributions(options, existing, newTypes) {
|
||||||
|
var types = newTypes.split(',');
|
||||||
|
if (options.url) {
|
||||||
|
return (existing || []).concat(types.map(function(type) {
|
||||||
|
return { type: type, url: options.url };
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return _.uniqBy(uniqueTypes, (existing || []).concat(types));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContributor(options, contributor, contributions) {
|
||||||
|
return _.assign(contributor, {
|
||||||
|
contributions: formatContributions(options, contributor.contributions, contributions)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateExistingContributor(options, username, contributions) {
|
||||||
|
return options.contributors.map(function(contributor, index) {
|
||||||
|
if (username !== contributor.login) {
|
||||||
|
return contributor;
|
||||||
|
}
|
||||||
|
return updateContributor(options, contributor, contributions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewContributor(options, username, contributions, infoFetcher, cb) {
|
||||||
|
infoFetcher(username, function(error, userData) {
|
||||||
|
if (error) {
|
||||||
|
return cb(error);
|
||||||
|
}
|
||||||
|
var contributor = _.assign(userData, {
|
||||||
|
contributions: formatContributions(options, [], contributions)
|
||||||
|
});
|
||||||
|
return cb(null, options.contributors.concat(contributor));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function addContributor(options, username, contributions, infoFetcher, cb) {
|
||||||
|
if (_.find({login: username}, options.contributors)) {
|
||||||
|
return cb(null, updateExistingContributor(options, username, contributions));
|
||||||
|
}
|
||||||
|
return addNewContributor(options, username, contributions, infoFetcher, cb);
|
||||||
|
}
|
161
lib/contributors/add.test.js
Normal file
161
lib/contributors/add.test.js
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
import test from 'ava';
|
||||||
|
import addContributor from './add';
|
||||||
|
|
||||||
|
function mockInfoFetcher(username, cb) {
|
||||||
|
return cb(null, {
|
||||||
|
login: username,
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixtures() {
|
||||||
|
const options = {
|
||||||
|
contributors: [{
|
||||||
|
login: 'login1',
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url',
|
||||||
|
contributions: [
|
||||||
|
'code'
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
login: 'login2',
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url',
|
||||||
|
contributions: [
|
||||||
|
{ type: 'blog', url: 'www.blog.url/path' },
|
||||||
|
'code'
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return {options};
|
||||||
|
}
|
||||||
|
|
||||||
|
test.cb('should callback with error if infoFetcher fails', t => {
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
const {options} = fixtures();
|
||||||
|
const username = 'login3';
|
||||||
|
const contributions = ['doc'];
|
||||||
|
function infoFetcher(username, cb) {
|
||||||
|
return cb(new Error('infoFetcher error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return addContributor(options, username, contributions, infoFetcher, function(error) {
|
||||||
|
t.is(error.message, 'infoFetcher error');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.cb('should add new contributor at the end of the list of contributors', t => {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
const {options} = fixtures();
|
||||||
|
const username = 'login3';
|
||||||
|
const contributions = 'doc';
|
||||||
|
|
||||||
|
return addContributor(options, username, contributions, mockInfoFetcher, function(error, contributors) {
|
||||||
|
t.notOk(error);
|
||||||
|
t.is(contributors.length, 3);
|
||||||
|
t.same(contributors[2], {
|
||||||
|
login: 'login3',
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url',
|
||||||
|
contributions: [
|
||||||
|
'doc'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.cb('should add new contributor at the end of the list of contributors with a url link', t => {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
const {options} = fixtures();
|
||||||
|
const username = 'login3';
|
||||||
|
const contributions = 'doc';
|
||||||
|
options.url = 'www.foo.bar';
|
||||||
|
|
||||||
|
return addContributor(options, username, contributions, mockInfoFetcher, function(error, contributors) {
|
||||||
|
t.notOk(error);
|
||||||
|
t.is(contributors.length, 3);
|
||||||
|
t.same(contributors[2], {
|
||||||
|
login: 'login3',
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url',
|
||||||
|
contributions: [
|
||||||
|
{ type: 'doc', url: 'www.foo.bar' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.cb(`should not update an existing contributor's contributions where nothing has changed`, t => {
|
||||||
|
t.plan(2);
|
||||||
|
|
||||||
|
const {options} = fixtures();
|
||||||
|
const username = 'login2';
|
||||||
|
const contributions = 'blog,code';
|
||||||
|
|
||||||
|
return addContributor(options, username, contributions, mockInfoFetcher, function(error, contributors) {
|
||||||
|
t.notOk(error);
|
||||||
|
t.same(contributors, options.contributors);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.cb(`should update an existing contributor's contributions if a new type is added`, t => {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
const {options} = fixtures();
|
||||||
|
const username = 'login1';
|
||||||
|
const contributions = 'bug';
|
||||||
|
|
||||||
|
return addContributor(options, username, contributions, mockInfoFetcher, function(error, contributors) {
|
||||||
|
t.notOk(error);
|
||||||
|
t.is(contributors.length, 2);
|
||||||
|
t.same(contributors[0], {
|
||||||
|
login: 'login1',
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url',
|
||||||
|
contributions: [
|
||||||
|
'code',
|
||||||
|
'bug'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.cb(`should update an existing contributor's contributions if a new type is added with a link`, t => {
|
||||||
|
t.plan(3);
|
||||||
|
|
||||||
|
const {options} = fixtures();
|
||||||
|
const username = 'login1';
|
||||||
|
const contributions = 'bug';
|
||||||
|
options.url = 'www.foo.bar';
|
||||||
|
|
||||||
|
return addContributor(options, username, contributions, mockInfoFetcher, function(error, contributors) {
|
||||||
|
t.notOk(error);
|
||||||
|
t.is(contributors.length, 2);
|
||||||
|
t.same(contributors[0], {
|
||||||
|
login: 'login1',
|
||||||
|
name: 'Some name',
|
||||||
|
avatar_url: 'www.avatar.url',
|
||||||
|
html_url: 'www.html.url',
|
||||||
|
contributions: [
|
||||||
|
'code',
|
||||||
|
{ type: 'bug', url: 'www.foo.bar' },
|
||||||
|
]
|
||||||
|
});
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,5 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('lodash/fp');
|
||||||
var request = require('request');
|
var request = require('request');
|
||||||
|
|
||||||
module.exports = function getUserInfo(username, cb) {
|
module.exports = function getUserInfo(username, cb) {
|
||||||
|
@ -12,6 +13,7 @@ module.exports = function getUserInfo(username, cb) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return cb(error);
|
return cb(error);
|
||||||
}
|
}
|
||||||
return cb(null, JSON.parse(res.body));
|
var user = JSON.parse(res.body);
|
||||||
|
return cb(null, _.pick(['login', 'name', 'avatar_url', 'html_url'], user));
|
||||||
});
|
});
|
||||||
}
|
}
|
16
lib/contributors/index.js
Normal file
16
lib/contributors/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var add = require('./add');
|
||||||
|
var github = require('./github');
|
||||||
|
var configFile = require('../configFile');
|
||||||
|
|
||||||
|
module.exports = function addContributor(options, username, contributions, cb) {
|
||||||
|
add(options, username, contributions, github, function(error, contributors) {
|
||||||
|
if (error) {
|
||||||
|
return cb(error);
|
||||||
|
}
|
||||||
|
configFile.writeContributors(options.config, contributors, function(error) {
|
||||||
|
return cb(error, contributors);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/jfmengels/all-contributors-cli#readme",
|
"homepage": "https://github.com/jfmengels/all-contributors-cli#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash": "^4.5.1",
|
"lodash": "^4.6.1",
|
||||||
"lodash.assign": "^4.0.4",
|
"lodash.assign": "^4.0.4",
|
||||||
"lodash.findindex": "^4.2.0",
|
"lodash.findindex": "^4.2.0",
|
||||||
"lodash.template": "^4.2.1",
|
"lodash.template": "^4.2.1",
|
||||||
|
|
Loading…
Reference in a new issue