2017-05-26 01:43:00 +03:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
2017-06-21 17:33:14 +03:00
|
|
|
const { readFile, exists } = require('mz/fs');
|
2017-05-26 01:43:00 +03:00
|
|
|
const sgf = require('staged-git-files');
|
|
|
|
const execa = require('execa');
|
|
|
|
const awaitify = require('apr-awaitify');
|
2017-06-21 17:33:14 +03:00
|
|
|
const asyncFilter = require('apr-filter');
|
2017-05-26 01:43:00 +03:00
|
|
|
const main = require('apr-main');
|
|
|
|
const map = require('apr-map');
|
2017-06-21 17:33:14 +03:00
|
|
|
const reduce = require('apr-reduce');
|
2017-05-26 01:43:00 +03:00
|
|
|
const globby = require('globby');
|
|
|
|
const path = require('path');
|
|
|
|
const uniq = require('lodash.uniq');
|
|
|
|
const argv = require('yargs').argv;
|
2017-06-21 17:33:14 +03:00
|
|
|
const checksum = require('checksum');
|
2017-09-08 12:38:32 +03:00
|
|
|
const { lstatSync, readdirSync } = require('fs');
|
|
|
|
const { join } = require('path');
|
2017-05-26 01:43:00 +03:00
|
|
|
|
|
|
|
const ROOT = path.join(__dirname, '..');
|
|
|
|
const getStaged = awaitify(sgf);
|
|
|
|
|
|
|
|
const statuses = [
|
|
|
|
'Added',
|
|
|
|
'Copied',
|
|
|
|
'Deleted',
|
|
|
|
'Modified',
|
|
|
|
'Renamed',
|
|
|
|
'Unmerged'
|
|
|
|
];
|
|
|
|
|
2017-05-30 01:04:51 +03:00
|
|
|
const exec = (args = []) =>
|
|
|
|
execa('lerna', args, {
|
|
|
|
stdio: 'inherit'
|
|
|
|
});
|
2017-05-26 01:43:00 +03:00
|
|
|
|
2017-05-26 04:22:35 +03:00
|
|
|
const lint = scope => exec(['run', 'lint', '--scope', scope]);
|
|
|
|
const test = scope => exec(['run', 'test', '--scope', scope]);
|
2017-05-26 01:43:00 +03:00
|
|
|
|
2017-05-26 04:22:35 +03:00
|
|
|
const run = async scope => {
|
2017-05-26 01:43:00 +03:00
|
|
|
if (argv.lint) {
|
|
|
|
await lint(scope);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv.test) {
|
|
|
|
await test(scope);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-06-21 17:33:14 +03:00
|
|
|
const runLint = async scope => {
|
|
|
|
await lint(scope);
|
|
|
|
};
|
|
|
|
|
|
|
|
const runTest = async scope => {
|
|
|
|
await test(scope);
|
|
|
|
};
|
|
|
|
|
|
|
|
const getUnstaged = async () => {
|
|
|
|
const unstaged = await execa('git', ['ls-files', '-m']);
|
|
|
|
return unstaged.stdout.split('\n');
|
|
|
|
};
|
|
|
|
|
|
|
|
const asyncChecksum = awaitify(checksum.file);
|
|
|
|
|
|
|
|
const add = async filename => execa('git', ['add', filename]);
|
|
|
|
|
|
|
|
const runLintAndGitAdd = async (staged, pkgs) => {
|
|
|
|
const unstaged = (await getUnstaged()).map(file => path.resolve(ROOT, file));
|
|
|
|
|
2017-10-18 05:29:47 +03:00
|
|
|
const existing = await asyncFilter(staged, ({ filename }) =>
|
|
|
|
exists(filename)
|
2017-06-21 17:33:14 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
const checksums = await map(existing, async file => {
|
|
|
|
const checksum = await asyncChecksum(file.filename);
|
|
|
|
return Object.assign({}, file, { checksum });
|
|
|
|
});
|
|
|
|
|
|
|
|
await map(pkgs.map(({ name }) => name), runLint);
|
|
|
|
|
|
|
|
const changed = await asyncFilter(
|
|
|
|
checksums,
|
|
|
|
async ({ filename, checksum }) => {
|
|
|
|
const newChecksum = await asyncChecksum(filename);
|
|
|
|
return checksum != newChecksum;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const modifieds = await reduce(
|
|
|
|
changed,
|
|
|
|
async (modifieds, file) => {
|
|
|
|
const isUnstaged = unstaged.filter(f => f === file.filename).length;
|
|
|
|
if (
|
|
|
|
(file.status === 'Modified' || file.status === 'Added') &&
|
|
|
|
isUnstaged
|
|
|
|
) {
|
|
|
|
modifieds.push(file);
|
|
|
|
} else {
|
|
|
|
await add(file.filename);
|
|
|
|
}
|
|
|
|
return modifieds;
|
|
|
|
},
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
|
|
|
|
if (modifieds.length) {
|
|
|
|
modifieds.forEach(modified =>
|
|
|
|
console.log('PARTIALLY STAGED FILE ', modified.filename)
|
|
|
|
);
|
2017-10-12 21:44:09 +03:00
|
|
|
process.exit(0);
|
2017-06-21 17:33:14 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-26 01:43:00 +03:00
|
|
|
const gather = async () => {
|
2017-09-08 12:38:32 +03:00
|
|
|
const isDirectory = source => lstatSync(source).isDirectory();
|
|
|
|
const getDirectories = source =>
|
2017-10-18 05:29:47 +03:00
|
|
|
readdirSync(source).map(name => join(source, name)).filter(isDirectory);
|
2017-09-08 12:38:32 +03:00
|
|
|
|
2017-10-18 05:29:47 +03:00
|
|
|
const locations = await globby(
|
|
|
|
[getDirectories('./packages'), getDirectories('./prototypes')],
|
|
|
|
{
|
|
|
|
cwd: ROOT
|
|
|
|
}
|
|
|
|
);
|
2017-05-26 01:43:00 +03:00
|
|
|
|
|
|
|
const staged = (await getStaged())
|
|
|
|
.filter(({ status }) => statuses.indexOf(status) >= 0)
|
2017-06-21 17:33:14 +03:00
|
|
|
// .map(({ filename }) => path.resolve(ROOT, filename));
|
|
|
|
.map(file =>
|
|
|
|
Object.assign({}, file, { filename: path.resolve(ROOT, file.filename) })
|
|
|
|
);
|
2017-05-26 01:43:00 +03:00
|
|
|
|
|
|
|
const folders = uniq(
|
|
|
|
locations
|
|
|
|
.map(folder => path.resolve(ROOT, folder))
|
2017-06-21 17:33:14 +03:00
|
|
|
.filter(folder => staged.some(i => i.filename.indexOf(folder) >= 0))
|
2017-05-26 01:43:00 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
const pkgs = await map(folders, async folder =>
|
|
|
|
JSON.parse(await readFile(path.join(folder, 'package.json'), 'utf-8'))
|
2017-05-26 04:22:35 +03:00
|
|
|
);
|
2017-05-26 01:43:00 +03:00
|
|
|
|
2017-06-21 17:33:14 +03:00
|
|
|
if (argv.lint) {
|
|
|
|
await runLintAndGitAdd(staged, pkgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv.test) {
|
|
|
|
await await map(pkgs.map(({ name }) => name), runTest);
|
|
|
|
}
|
2017-05-26 01:43:00 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
main(gather());
|