UNPKG

git-owner

Version:
151 lines (145 loc) 15.8 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('child_process')) : typeof define === 'function' && define.amd ? define(['exports', 'child_process'], factory) : (factory((global.gitOwner = global.gitOwner || {}),global.child_process)); }(this, (function (exports,child_process) { 'use strict'; /** * Generates statistics about the committers for a given file. */ function gitBlameStats(file, callback, _spawn) { if (_spawn === void 0) { _spawn = child_process.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); } } exports.gitBlameStats = gitBlameStats; exports.run = run; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIi4uL2xpYi9naXRCbGFtZVN0YXRzLnRzIiwiLi4vbGliL2NsaS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3biB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuXG5leHBvcnQgdHlwZSBCbGFtZVN0YXRzID0ge1xuICBjb21taXR0ZXJzOiBBcnJheTxDb21taXR0ZXJTdGF0cz4sXG4gIHRvdGFsTGluZXM6IG51bWJlcixcbiAgcGFpcmVkTGluZXM6IG51bWJlclxufTtcblxudHlwZSBDb21taXR0ZXJTdGF0cyA9IHtcbiAgZW1haWw6IHN0cmluZztcbiAgbGluZXM6IG51bWJlcjtcbiAgcGVyY2VudGFnZTogbnVtYmVyO1xufTtcblxudHlwZSBzcGF3bkZ1bmN0aW9uID0gdHlwZW9mIHNwYXduO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBzdGF0aXN0aWNzIGFib3V0IHRoZSBjb21taXR0ZXJzIGZvciBhIGdpdmVuIGZpbGUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGdpdEJsYW1lU3RhdHMoZmlsZTogc3RyaW5nLCBjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHN0YXRzOiBCbGFtZVN0YXRzIHwgbnVsbCkgPT4gdm9pZCwgX3NwYXduOiBzcGF3bkZ1bmN0aW9uPXNwYXduKSB7XG4gIGxldCBibGFtZSA9IF9zcGF3bignZ2l0JywgWydibGFtZScsICctQycsICctdycsIGZpbGUsICctLWxpbmUtcG9yY2VsYWluJ10pO1xuICBsZXQgZGF0YSA9ICcnO1xuICBsZXQgc3RkZXJyID0gJyc7XG5cbiAgYmxhbWUuc3Rkb3V0Lm9uKCdkYXRhJywgY2h1bmsgPT4gZGF0YSArPSBjaHVuayk7XG4gIGJsYW1lLnN0ZGVyci5vbignZGF0YScsIGNodW5rID0+IHN0ZGVyciArPSBjaHVuayk7XG5cbiAgYmxhbWUub24oJ2Nsb3NlJywgY29kZSA9PiB7XG4gICAgaWYgKGNvZGUgIT09IDApIHtcbiAgICAgIGNhbGxiYWNrKG5ldyBFcnJvcihzdGRlcnIpLCBudWxsKTtcbiAgICB9XG5cbiAgICBsZXQgY29tbWl0dGVycyA9IFtdO1xuICAgIGxldCBjb21taXR0ZXJzQnlFbWFpbCA9IHt9O1xuICAgIGxldCB0b3RhbExpbmVzID0gMDtcbiAgICBsZXQgcGFpcmVkTGluZXMgPSAwO1xuXG4gICAgZGF0YS5zcGxpdCgnXFxuJykuZm9yRWFjaChsaW5lID0+IHtcbiAgICAgIGxldCBlbWFpbHMgPSBjb21taXR0ZXJFbWFpbHNGcm9tTGluZShsaW5lKTtcbiAgICAgIGlmIChlbWFpbHMpIHtcbiAgICAgICAgdG90YWxMaW5lcysrO1xuICAgICAgICBpZiAoZW1haWxzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBwYWlyZWRMaW5lcysrO1xuICAgICAgICB9XG5cbiAgICAgICAgZW1haWxzLmZvckVhY2goZW1haWwgPT4ge1xuICAgICAgICAgIGxldCBjb21taXR0ZXIgPSBjb21taXR0ZXJzQnlFbWFpbFtlbWFpbF07XG4gICAgICAgICAgaWYgKCFjb21taXR0ZXIpIHtcbiAgICAgICAgICAgIGNvbW1pdHRlcnMucHVzaChcbiAgICAgICAgICAgICAgY29tbWl0dGVyc0J5RW1haWxbZW1haWxdID0gY29tbWl0dGVyID0ge1xuICAgICAgICAgICAgICAgIGVtYWlsLFxuICAgICAgICAgICAgICAgIGxpbmVzOiAwLFxuICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2U6IDBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29tbWl0dGVyLmxpbmVzKys7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29tbWl0dGVycy5mb3JFYWNoKGNvbW1pdHRlciA9PiB7XG4gICAgICBjb21taXR0ZXIucGVyY2VudGFnZSA9IGNvbW1pdHRlci5saW5lcyAvIHRvdGFsTGluZXM7XG4gICAgfSk7XG5cbiAgICBjYWxsYmFjayhudWxsLCB7XG4gICAgICBjb21taXR0ZXJzLFxuICAgICAgdG90YWxMaW5lcyxcbiAgICAgIHBhaXJlZExpbmVzXG4gICAgfSk7XG4gIH0pO1xufVxuXG5jb25zdCBDT01NSVRURVJfTUFJTCA9ICdjb21taXR0ZXItbWFpbCc7XG5cbi8qKlxuICogR2V0cyB0aGUgZW1haWwgYWRkcmVzc2VzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHBhcnRpY3VsYXIgZ2l0LWJsYW1lIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGNvbW1pdHRlckVtYWlsc0Zyb21MaW5lKGxpbmU6IHN0cmluZyk6IEFycmF5PHN0cmluZz4gfCBudWxsIHtcbiAgaWYgKGxpbmUuaW5kZXhPZihDT01NSVRURVJfTUFJTCArICcgJykgPCAwKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBsZXQgZW1haWwgPSBsaW5lLnNsaWNlKENPTU1JVFRFUl9NQUlMLmxlbmd0aCArIDIsIC0xKTtcbiAgbGV0IG1hdGNoID0gZW1haWwubWF0Y2goL15naXQoPzpodWIpP1xcKyguKykoQC4rKSQvKTtcblxuICBpZiAobWF0Y2gpIHtcbiAgICBsZXQgdXNlcm5hbWVzID0gbWF0Y2hbMV07XG4gICAgbGV0IGF0aG9zdG5hbWUgPSBtYXRjaFsyXTtcbiAgICByZXR1cm4gdXNlcm5hbWVzLnNwbGl0KCcrJykubWFwKHVzZXJuYW1lID0+IHVzZXJuYW1lICsgYXRob3N0bmFtZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFtlbWFpbF07XG4gIH1cbn1cbiIsImxldCBmaWxlO1xubGV0IGZvcm1hdDtcblxuaW1wb3J0IGdpdEJsYW1lU3RhdHMgZnJvbSAnLi9naXRCbGFtZVN0YXRzJztcbmltcG9ydCB7IEJsYW1lU3RhdHMgfSBmcm9tICcuL2dpdEJsYW1lU3RhdHMnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBydW4oKSB7XG4gIHBhcnNlQXJndW1lbnRzKCk7XG4gIGdpdEJsYW1lU3RhdHMoZmlsZSwgKGVycjogRXJyb3IgfCBudWxsLCBzdGF0czogQmxhbWVTdGF0cyB8IG51bGwpID0+IHtcbiAgICBpZiAoZXJyIHx8ICFzdGF0cykgeyB0aHJvdyBlcnI7IH1cblxuICAgIGlmIChmb3JtYXQgPT09ICdqc29uJykge1xuICAgICAgY29uc29sZS5sb2coc3RhdHMuY29tbWl0dGVycyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG1heFBlcmNlbnRhZ2UgPSBzdGF0cy5jb21taXR0ZXJzLnJlZHVjZSgobWF4LCBjb21taXR0ZXIpID0+IE1hdGgubWF4KG1heCwgY29tbWl0dGVyLnBlcmNlbnRhZ2UpLCAwKTtcblxuICAgICAgc3RhdHMuY29tbWl0dGVycy5mb3JFYWNoKGZ1bmN0aW9uKGNvbW1pdHRlcikge1xuICAgICAgICBjb25zdCBwZXJjZW50YWdlID0gYCR7Y29tbWl0dGVyLnBlcmNlbnRhZ2UgKiAxMDB9YDtcblxuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAnJXMlcyUgJXMnLFxuICAgICAgICAgIG5ldyBBcnJheSgoYCR7bWF4UGVyY2VudGFnZSAqIDEwMH1gKS5sZW5ndGggLSBwZXJjZW50YWdlLmxlbmd0aCArIDEpLmpvaW4oJyAnKSxcbiAgICAgICAgICBwZXJjZW50YWdlLFxuICAgICAgICAgIGNvbW1pdHRlci5lbWFpbFxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnNvbGUubG9nKCk7XG4gICAgICBpZiAoc3RhdHMucGFpcmVkTGluZXMgPiAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCclcyBsaW5lcywgJXMgcGFpcmVkLicsIHN0YXRzLnRvdGFsTGluZXMsIHN0YXRzLnBhaXJlZExpbmVzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCclcyBsaW5lcy4nLCBzdGF0cy50b3RhbExpbmVzKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3VtZW50cygpIHtcbiAgY29uc3QgYXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbiAgbGV0IGFyZztcblxuICB3aGlsZSAoKGFyZyA9IGFyZ3Muc2hpZnQoKSkpIHtcbiAgICBpZiAoYXJnID09PSAnLWgnIHx8IGFyZyA9PT0gJy0taGVscCcpIHtcbiAgICAgIHVzYWdlKDApO1xuICAgIH0gZWxzZSBpZiAoYXJnID09PSAnLWYnIHx8IGFyZyA9PT0gJy0tZm9ybWF0Jykge1xuICAgICAgbGV0IG5leHQgPSBhcmdzLnNoaWZ0KCk7XG4gICAgICBpZiAoIW5leHQpIHtcbiAgICAgICAgdXNhZ2UoMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXh0ID0gbmV4dC50b0xvd2VyQ2FzZSgpO1xuICAgICAgfVxuICAgICAgaWYgKG5leHQgIT09ICdqc29uJykge1xuICAgICAgICB1c2FnZSgxKTtcbiAgICAgIH1cbiAgICAgIGZvcm1hdCA9IG5leHQ7XG4gICAgfSBlbHNlIGlmIChhcmdbMF0gPT09ICctJykge1xuICAgICAgdXNhZ2UoMSk7XG4gICAgfSBlbHNlIGlmICghZmlsZSkge1xuICAgICAgZmlsZSA9IGFyZztcbiAgICB9IGVsc2Uge1xuICAgICAgdXNhZ2UoMSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFmaWxlKSB7XG4gICAgdXNhZ2UoMSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdXNhZ2UoY29kZTogbnVtYmVyIHwgbnVsbD1udWxsKSB7XG4gIGNvbnNvbGUuZXJyb3IoJ2dpdCBvd25lciBbLWYgSlNPTl0gRklMRScpO1xuICBpZiAoY29kZSAhPT0gbnVsbCkge1xuICAgIHByb2Nlc3MuZXhpdChjb2RlKTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQWdCQTs7O0FBR0EsdUJBQXNDLElBQVksRUFBRSxRQUFpRSxFQUFFLE1BQTJCO0lBQTNCLHlCQUFBLDRCQUEyQjtJQUNoSixJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixDQUFDLENBQUMsQ0FBQztJQUMzRSxJQUFJ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