UNPKG

ggit

Version:

Local promise-returning git command wrappers

136 lines (117 loc) 3.69 kB
var check = require('check-types'); var moment = require('moment'); var spawn = require('child_process').spawn; var path = require('path'); var getGitRootFolder = require('./repoRoot').getGitRootFolder; // returns commits in reverse chronological order function gitLog(filename, commits, cb, err, rootFolder) { if (err) { throw err; } check.verify.string(filename, 'missing filename'); check.verify.positiveNumber(commits, 'invalid number of commits', commits); check.verify.fn(cb, 'callback should be a function'); // use -n <number> to limit history // oe --since <date> // var args = ['log', '--no-decorate', '-n ' + commits]; var args = ['log', '--name-status', '-n ' + commits]; if (filename) { check.verify.string(rootFolder, 'could not find git root folder'); rootFolder = rootFolder.trim(); rootFolder = rootFolder.replace(/\//g, '\\'); console.log('filename', filename); console.log('repo root folder', rootFolder); var workingFolder = process.cwd(); console.log('working folder', workingFolder); var relativePath = path.relative(workingFolder, filename); // var repoPath = path.relative(rootFolder, filename); args.push(relativePath); } console.log('git log command', args); var git = spawn('git', args); commits = []; git.stdout.setEncoding('utf-8'); git.stdout.on('data', function (data) { data.trim(); // console.log('git data\n', data); var separatedData = data.split('\ncommit '); separatedData = separatedData.filter(function (str) { str.trim(); return str && str !== '\n'; }); var info = separatedData.map(parseCommit); commits = commits.concat(info); }); git.stderr.setEncoding('utf-8'); git.stderr.on('data', function (data) { throw new Error('Could not get git log for\n' + filename + '\n' + data); }); git.on('exit', function () { console.log('returning', commits.length, 'commits'); cb(commits); }); } function parseCommit(data) { check.verify.string(data, 'null commit data'); data = data.trim(); // console.log('parsing commit\n', data); var lines = data.split('\n'); console.assert(lines.length > 3, 'invalid commit\n', data); // console.log('commit lines\n', lines); var commitLine = lines[0].trim(); if (commitLine.indexOf('commit ') === 0) { commitLine = commitLine.substr('commit '.length); } var authorLine = lines[1].split(':')[1].trim(); var dateLine = lines[2]; dateLine = dateLine.substr(dateLine.indexOf(':') + 1); dateLine = dateLine.trim(); // console.log(dateLine); lines.splice(0, 3); lines = lines.filter(function (str) { return str; }); lines = lines.map(function (str) { str = str.trim(); return str; }); var files = []; lines = lines.filter(function (str) { // console.log('checking line', str); if (str.indexOf('M') === 0 || str.indexOf('A') === 0 || str.indexOf('D') === 0) { files.push({ name: str.substr(1).trim(), status: str[0] }); return false; } else { return true; } }); var description = lines.join('\n'); return { commit: '' + commitLine.trim(), author: authorLine.trim(), date: moment(dateLine), description: description.trim(), files: files }; } function getGitLog(filename, commits, cb) { if (filename) { check.verify.string(filename, 'expected filename'); filename = path.resolve(filename); console.log('fetching', commits, 'history for', filename); } commits = commits || 30; check.verify.positiveNumber(commits, 'invalid max number of commits', commits); check.verify.fn(cb, 'expect callback function, not', cb); getGitRootFolder(gitLog.bind(null, filename, commits, cb)); } module.exports = { getGitLog: getGitLog, parseCommit: parseCommit };