UNPKG

git-owner

Version:
142 lines (138 loc) 15.4 kB
import { spawn } from 'child_process'; /** * Generates statistics about the committers for a given file. */ function gitBlameStats(file, callback, _spawn) { if (_spawn === void 0) { _spawn = spawn; } var blame = _spawn('git', ['blame', '-C', '-w', file, '--line-porcelain']); var data = ''; var stderr = ''; blame.stdout.on('data', function (chunk) { return data += chunk; }); blame.stderr.on('data', function (chunk) { return stderr += chunk; }); blame.on('close', function (code) { if (code !== 0) { callback(new Error(stderr), null); } var committers = []; var committersByEmail = {}; var totalLines = 0; var pairedLines = 0; data.split('\n').forEach(function (line) { var emails = committerEmailsFromLine(line); if (emails) { totalLines++; if (emails.length > 1) { pairedLines++; } emails.forEach(function (email) { var committer = committersByEmail[email]; if (!committer) { committers.push(committersByEmail[email] = committer = { email: email, lines: 0, percentage: 0 }); } committer.lines++; }); } }); committers.forEach(function (committer) { committer.percentage = committer.lines / totalLines; }); callback(null, { committers: committers, totalLines: totalLines, pairedLines: pairedLines }); }); } var COMMITTER_MAIL = 'committer-mail'; /** * Gets the email addresses associated with this particular git-blame line. */ function committerEmailsFromLine(line) { if (line.indexOf(COMMITTER_MAIL + ' ') < 0) { return null; } var email = line.slice(COMMITTER_MAIL.length + 2, -1); var match = email.match(/^git(?:hub)?\+(.+)(@.+)$/); if (match) { var usernames = match[1]; var athostname_1 = match[2]; return usernames.split('+').map(function (username) { return username + athostname_1; }); } else { return [email]; } } var file; var format; function run() { parseArguments(); gitBlameStats(file, function (err, stats) { if (err || !stats) { throw err; } if (format === 'json') { console.log(stats.committers); } else { var maxPercentage_1 = stats.committers.reduce(function (max, committer) { return Math.max(max, committer.percentage); }, 0); stats.committers.forEach(function (committer) { var percentage = "" + committer.percentage * 100; console.log('%s%s% %s', new Array(("" + maxPercentage_1 * 100).length - percentage.length + 1).join(' '), percentage, committer.email); }); console.log(); if (stats.pairedLines > 0) { console.log('%s lines, %s paired.', stats.totalLines, stats.pairedLines); } else { console.log('%s lines.', stats.totalLines); } } }); } function parseArguments() { var args = process.argv.slice(2); var arg; while ((arg = args.shift())) { if (arg === '-h' || arg === '--help') { usage(0); } else if (arg === '-f' || arg === '--format') { var next = args.shift(); if (!next) { usage(1); } else { next = next.toLowerCase(); } if (next !== 'json') { usage(1); } format = next; } else if (arg[0] === '-') { usage(1); } else if (!file) { file = arg; } else { usage(1); } } if (!file) { usage(1); } } function usage(code) { if (code === void 0) { code = null; } console.error('git owner [-f JSON] FILE'); if (code !== null) { process.exit(code); } } export { gitBlameStats, run }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIi4uL2xpYi9naXRCbGFtZVN0YXRzLnRzIiwiLi4vbGliL2NsaS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3biB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuXG5leHBvcnQgdHlwZSBCbGFtZVN0YXRzID0ge1xuICBjb21taXR0ZXJzOiBBcnJheTxDb21taXR0ZXJTdGF0cz4sXG4gIHRvdGFsTGluZXM6IG51bWJlcixcbiAgcGFpcmVkTGluZXM6IG51bWJlclxufTtcblxudHlwZSBDb21taXR0ZXJTdGF0cyA9IHtcbiAgZW1haWw6IHN0cmluZztcbiAgbGluZXM6IG51bWJlcjtcbiAgcGVyY2VudGFnZTogbnVtYmVyO1xufTtcblxudHlwZSBzcGF3bkZ1bmN0aW9uID0gdHlwZW9mIHNwYXduO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBzdGF0aXN0aWNzIGFib3V0IHRoZSBjb21taXR0ZXJzIGZvciBhIGdpdmVuIGZpbGUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGdpdEJsYW1lU3RhdHMoZmlsZTogc3RyaW5nLCBjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHN0YXRzOiBCbGFtZVN0YXRzIHwgbnVsbCkgPT4gdm9pZCwgX3NwYXduOiBzcGF3bkZ1bmN0aW9uPXNwYXduKSB7XG4gIGxldCBibGFtZSA9IF9zcGF3bignZ2l0JywgWydibGFtZScsICctQycsICctdycsIGZpbGUsICctLWxpbmUtcG9yY2VsYWluJ10pO1xuICBsZXQgZGF0YSA9ICcnO1xuICBsZXQgc3RkZXJyID0gJyc7XG5cbiAgYmxhbWUuc3Rkb3V0Lm9uKCdkYXRhJywgY2h1bmsgPT4gZGF0YSArPSBjaHVuayk7XG4gIGJsYW1lLnN0ZGVyci5vbignZGF0YScsIGNodW5rID0+IHN0ZGVyciArPSBjaHVuayk7XG5cbiAgYmxhbWUub24oJ2Nsb3NlJywgY29kZSA9PiB7XG4gICAgaWYgKGNvZGUgIT09IDApIHtcbiAgICAgIGNhbGxiYWNrKG5ldyBFcnJvcihzdGRlcnIpLCBudWxsKTtcbiAgICB9XG5cbiAgICBsZXQgY29tbWl0dGVycyA9IFtdO1xuICAgIGxldCBjb21taXR0ZXJzQnlFbWFpbCA9IHt9O1xuICAgIGxldCB0b3RhbExpbmVzID0gMDtcbiAgICBsZXQgcGFpcmVkTGluZXMgPSAwO1xuXG4gICAgZGF0YS5zcGxpdCgnXFxuJykuZm9yRWFjaChsaW5lID0+IHtcbiAgICAgIGxldCBlbWFpbHMgPSBjb21taXR0ZXJFbWFpbHNGcm9tTGluZShsaW5lKTtcbiAgICAgIGlmIChlbWFpbHMpIHtcbiAgICAgICAgdG90YWxMaW5lcysrO1xuICAgICAgICBpZiAoZW1haWxzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBwYWlyZWRMaW5lcysrO1xuICAgICAgICB9XG5cbiAgICAgICAgZW1haWxzLmZvckVhY2goZW1haWwgPT4ge1xuICAgICAgICAgIGxldCBjb21taXR0ZXIgPSBjb21taXR0ZXJzQnlFbWFpbFtlbWFpbF07XG4gICAgICAgICAgaWYgKCFjb21taXR0ZXIpIHtcbiAgICAgICAgICAgIGNvbW1pdHRlcnMucHVzaChcbiAgICAgICAgICAgICAgY29tbWl0dGVyc0J5RW1haWxbZW1haWxdID0gY29tbWl0dGVyID0ge1xuICAgICAgICAgICAgICAgIGVtYWlsLFxuICAgICAgICAgICAgICAgIGxpbmVzOiAwLFxuICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2U6IDBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29tbWl0dGVyLmxpbmVzKys7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29tbWl0dGVycy5mb3JFYWNoKGNvbW1pdHRlciA9PiB7XG4gICAgICBjb21taXR0ZXIucGVyY2VudGFnZSA9IGNvbW1pdHRlci5saW5lcyAvIHRvdGFsTGluZXM7XG4gICAgfSk7XG5cbiAgICBjYWxsYmFjayhudWxsLCB7XG4gICAgICBjb21taXR0ZXJzLFxuICAgICAgdG90YWxMaW5lcyxcbiAgICAgIHBhaXJlZExpbmVzXG4gICAgfSk7XG4gIH0pO1xufVxuXG5jb25zdCBDT01NSVRURVJfTUFJTCA9ICdjb21taXR0ZXItbWFpbCc7XG5cbi8qKlxuICogR2V0cyB0aGUgZW1haWwgYWRkcmVzc2VzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHBhcnRpY3VsYXIgZ2l0LWJsYW1lIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGNvbW1pdHRlckVtYWlsc0Zyb21MaW5lKGxpbmU6IHN0cmluZyk6IEFycmF5PHN0cmluZz4gfCBudWxsIHtcbiAgaWYgKGxpbmUuaW5kZXhPZihDT01NSVRURVJfTUFJTCArICcgJykgPCAwKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBsZXQgZW1haWwgPSBsaW5lLnNsaWNlKENPTU1JVFRFUl9NQUlMLmxlbmd0aCArIDIsIC0xKTtcbiAgbGV0IG1hdGNoID0gZW1haWwubWF0Y2goL15naXQoPzpodWIpP1xcKyguKykoQC4rKSQvKTtcblxuICBpZiAobWF0Y2gpIHtcbiAgICBsZXQgdXNlcm5hbWVzID0gbWF0Y2hbMV07XG4gICAgbGV0IGF0aG9zdG5hbWUgPSBtYXRjaFsyXTtcbiAgICByZXR1cm4gdXNlcm5hbWVzLnNwbGl0KCcrJykubWFwKHVzZXJuYW1lID0+IHVzZXJuYW1lICsgYXRob3N0bmFtZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFtlbWFpbF07XG4gIH1cbn1cbiIsImxldCBmaWxlO1xubGV0IGZvcm1hdDtcblxuaW1wb3J0IGdpdEJsYW1lU3RhdHMgZnJvbSAnLi9naXRCbGFtZVN0YXRzJztcbmltcG9ydCB7IEJsYW1lU3RhdHMgfSBmcm9tICcuL2dpdEJsYW1lU3RhdHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBydW4oKSB7XG4gIHBhcnNlQXJndW1lbnRzKCk7XG4gIGdpdEJsYW1lU3RhdHMoZmlsZSwgKGVycjogRXJyb3IgfCBudWxsLCBzdGF0czogQmxhbWVTdGF0cyB8IG51bGwpID0+IHtcbiAgICBpZiAoZXJyIHx8ICFzdGF0cykgeyB0aHJvdyBlcnI7IH1cblxuICAgIGlmIChmb3JtYXQgPT09ICdqc29uJykge1xuICAgICAgY29uc29sZS5sb2coc3RhdHMuY29tbWl0dGVycyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG1heFBlcmNlbnRhZ2UgPSBzdGF0cy5jb21taXR0ZXJzLnJlZHVjZSgobWF4LCBjb21taXR0ZXIpID0+IE1hdGgubWF4KG1heCwgY29tbWl0dGVyLnBlcmNlbnRhZ2UpLCAwKTtcblxuICAgICAgc3RhdHMuY29tbWl0dGVycy5mb3JFYWNoKGZ1bmN0aW9uKGNvbW1pdHRlcikge1xuICAgICAgICBjb25zdCBwZXJjZW50YWdlID0gYCR7Y29tbWl0dGVyLnBlcmNlbnRhZ2UgKiAxMDB9YDtcblxuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAnJXMlcyUgJXMnLFxuICAgICAgICAgIG5ldyBBcnJheSgoYCR7bWF4UGVyY2VudGFnZSAqIDEwMH1gKS5sZW5ndGggLSBwZXJjZW50YWdlLmxlbmd0aCArIDEpLmpvaW4oJyAnKSxcbiAgICAgICAgICBwZXJjZW50YWdlLFxuICAgICAgICAgIGNvbW1pdHRlci5lbWFpbFxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnNvbGUubG9nKCk7XG4gICAgICBpZiAoc3RhdHMucGFpcmVkTGluZXMgPiAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCclcyBsaW5lcywgJXMgcGFpcmVkLicsIHN0YXRzLnRvdGFsTGluZXMsIHN0YXRzLnBhaXJlZExpbmVzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCclcyBsaW5lcy4nLCBzdGF0cy50b3RhbExpbmVzKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3VtZW50cygpIHtcbiAgY29uc3QgYXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbiAgbGV0IGFyZztcblxuICB3aGlsZSAoKGFyZyA9IGFyZ3Muc2hpZnQoKSkpIHtcbiAgICBpZiAoYXJnID09PSAnLWgnIHx8IGFyZyA9PT0gJy0taGVscCcpIHtcbiAgICAgIHVzYWdlKDApO1xuICAgIH0gZWxzZSBpZiAoYXJnID09PSAnLWYnIHx8IGFyZyA9PT0gJy0tZm9ybWF0Jykge1xuICAgICAgbGV0IG5leHQgPSBhcmdzLnNoaWZ0KCk7XG4gICAgICBpZiAoIW5leHQpIHtcbiAgICAgICAgdXNhZ2UoMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXh0ID0gbmV4dC50b0xvd2VyQ2FzZSgpO1xuICAgICAgfVxuICAgICAgaWYgKG5leHQgIT09ICdqc29uJykge1xuICAgICAgICB1c2FnZSgxKTtcbiAgICAgIH1cbiAgICAgIGZvcm1hdCA9IG5leHQ7XG4gICAgfSBlbHNlIGlmIChhcmdbMF0gPT09ICctJykge1xuICAgICAgdXNhZ2UoMSk7XG4gICAgfSBlbHNlIGlmICghZmlsZSkge1xuICAgICAgZmlsZSA9IGFyZztcbiAgICB9IGVsc2Uge1xuICAgICAgdXNhZ2UoMSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFmaWxlKSB7XG4gICAgdXNhZ2UoMSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdXNhZ2UoY29kZTogbnVtYmVyIHwgbnVsbD1udWxsKSB7XG4gIGNvbnNvbGUuZXJyb3IoJ2dpdCBvd25lciBbLWYgSlNPTl0gRklMRScpO1xuICBpZiAoY29kZSAhPT0gbnVsbCkge1xuICAgIHByb2Nlc3MuZXhpdChjb2RlKTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZ0JBOzs7QUFHQSx1QkFBc0MsSUFBWSxFQUFFLFFBQWlFLEVBQUUsTUFBMkI7SUFBM0IseUJBQUEsY0FBMkI7SUFDaEosSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDM0UsSUFBSSxJQUFJ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