Skip to content

Instantly share code, notes, and snippets.

@usefulthink
Created May 5, 2014 18:03
Show Gist options
  • Save usefulthink/7fad0d23ab2054a50c18 to your computer and use it in GitHub Desktop.
Save usefulthink/7fad0d23ab2054a50c18 to your computer and use it in GitHub Desktop.
practicing node streams – script generates a git commit-log, parses it and reformats into a day-by-day-log useful for time-tracking.
#!/usr/bin/env node
var fs = require('fs'),
util = require('util'),
spawn = require('child_process').spawn,
stream = require('stream');
function dateString(date) { return date.toISOString().split('T')[0]; }
function timeString(date) { return date.toTimeString().slice(0,5); }
var logParser = (function() {
var s=new stream.Transform({objectMode:true});
s._transform = function(chunk, encoding, callback) {
var buf = chunk.toString('utf-8'),
lines = buf.trim().split("\n");
lines = lines.map(function(line) {
// note: this of course correlates with git's log-format
var parts = line.split('|');
var ts = new Date(parts[0]),
date = dateString(ts),
time = timeString(ts);
return { timestamp: ts.getTime(), date: date, time: time, author: parts[1], msg: parts[2] };
});
lines.forEach(this.push.bind(this));
callback();
};
return s;
} ());
var dayAggregator = (function() {
var s = new stream.Transform({objectMode:true});
var aggregate;
function _reset() {
aggregate = { date: '', firstCommitAt: null, lastCommitAt: null, msgs: [] };
}
_reset();
s._transform = function(o, encoding, callback) {
if(o.date !== aggregate.date && aggregate.msgs.length > 0) {
aggregate.msgs = aggregate.msgs.sort(function(a,b) { return a.timestamp - b.timestamp; });
this.push(aggregate);
_reset();
}
if(!aggregate.firstCommitAt) {
aggregate.firstCommitAt = new Date(o.timestamp);
}
aggregate.date = o.date;
aggregate.lastCommitAt = new Date(o.timestamp);
aggregate.msgs.push(o);
callback();
};
return s;
} ());
var dayLogWriter = (function() {
var s = new stream.Transform({objectMode:true});
s._write = function(o, encoding, callback) {
this.push('\n\033[1;32m---- '+o.date+' ----\033[0m\n');
var msgs = o.msgs.map(function(msg) {
return '\033[36m['+msg.time+']\033[0m \033[34m' + msg.author + '\033[0m: ' + msg.msg;
});
this.push(' '+(msgs.join('\n '))+'\n\n');
this.push('First commit: '+timeString(o.firstCommitAt) + '\n');
this.push('Last commit: '+timeString(o.lastCommitAt) + '\n');
callback();
};
return s;
} ());
var dumpObjectStream = (function() {
var s = new stream.Writable({objectMode:true});
s._write = function(chunk, encoding, callback) {
console.log('dumpObjectStream:', util.inspect(chunk, {colors:true}));
callback();
};
return s;
}());
// now fetch the data and format it...
var cp = spawn('git', ['log', '--reverse', '--date-order', '--format=%ai|%ae|%s'].concat(process.argv.slice(2)));
cp.stdout.pipe(logParser).pipe(dayAggregator).pipe(dayLogWriter).pipe(process.stdout);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment