git-diff-tree
Version:
Shelling out to git-diff-tree(1) in a Node streamy fashion
118 lines (91 loc) • 2.77 kB
JavaScript
var splitStream = require('split-transform-stream');
var through = require('through2');
var parseRawDiffLine = require('./parseRawDiffLine');
var streamDiff = require('./streamDiff');
module.exports = function parseStream(inputStream, ops) {
var patchStream;
var patchStreamRes;
var outStream;
var opts = ops || {};
// don't output data for files that have more lines changed than allowed
var MAX_DIFF_LINES_PER_FILE = opts.MAX_DIFF_LINES_PER_FILE || 300;
// files that are renamed, deleted or have more than X changes
var noShow = [];
// files that have a tone of changes
var blacklist = [];
var isCut = false;
inputStream.on('end', function handleStreamEnd(limitExceeded) {
if (limitExceeded) { isCut = true; }
});
function initPatchStream() {
patchStream = through({ objectMode: true });
patchStreamRes = streamDiff(patchStream, noShow);
patchStreamRes.on('data', function processPatchChunk(data) {
outStream.emit('data', 'patch', data);
}).on('error', function handlePatchStreamError(err) {
outStream.emit(err);
});
if (blacklist.length) {
outStream.emit('data', 'noshow', blacklist);
}
}
function writeRaw(line) {
var parsed = parseRawDiffLine(line);
if (parsed.status === 'D' || parsed.similarity === 100) {
noShow.push(parsed.toFile || parsed.fromFile);
}
this.emit('data', 'raw', parseRawDiffLine(line));
}
function writePatch(line) {
if (patchStream) {
patchStream.push(line);
} else {
initPatchStream();
patchStream.push(line);
}
}
function writeStats(stats) {
var tmp = stats[3].split(' => ');
var added = parseInt(stats[1], 10);
var deleted = parseInt(stats[2], 10);
if ((added + deleted) > MAX_DIFF_LINES_PER_FILE) {
noShow.push(tmp[1] || tmp[0]);
blacklist.push(tmp[1] || tmp[0]);
}
this.emit('data', 'stats', {
added: added,
deleted: deleted,
fileA: tmp[0],
fileB: tmp[1]
});
}
var end = function end(cb) {
patchStream.emit('end');
if (isCut) {
this.emit('cut');
}
cb();
};
var type = 'raw';
var write = function write(line, enc, cb) {
if (type === 'patch') {
writePatch.call(this, line);
} else {
var stats = line.match(/^(\d+)\t(\d+)\t(.*)( => (.*))?/);
if (type !== 'patch' && stats) {
writeStats.call(this, stats);
} else if (type !== 'patch' && /^-\t-\t/.test(line)) {
// binary file
} else if (!line) {
type = 'patch';
writePatch.call(this, line);
} else {
writeRaw.call(this, line);
}
}
cb();
};
outStream = splitStream(inputStream, write, end);
return outStream;
};
;