Parse binary patch diffs

This commit is contained in:
Rodrigo Fernandes 2016-11-12 22:41:17 +00:00
parent 1b9200b201
commit 0f2d650436
No known key found for this signature in database
GPG key ID: 08E3C5F38969078E
2 changed files with 130 additions and 24 deletions

View file

@ -32,6 +32,9 @@
var oldLine2 = null; // Used for combined diff var oldLine2 = null; // Used for combined diff
var newLine = null; var newLine = null;
var possibleOldName;
var possibleNewName;
/* Diff Header */ /* Diff Header */
var oldFileNameHeader = '--- '; var oldFileNameHeader = '--- ';
var newFileNameHeader = '+++ '; var newFileNameHeader = '+++ ';
@ -50,10 +53,23 @@
* if it has name (to avoid binary files errors) * if it has name (to avoid binary files errors)
*/ */
function saveFile() { function saveFile() {
if (currentFile && currentFile.newName) { if (currentFile) {
files.push(currentFile); if (!currentFile.oldName) {
currentFile = null; currentFile.oldName = possibleOldName;
}
if (!currentFile.newName) {
currentFile.newName = possibleNewName;
}
if (currentFile.newName) {
files.push(currentFile);
currentFile = null;
}
} }
possibleOldName = undefined;
possibleNewName = undefined;
} }
/* Create file structure */ /* Create file structure */
@ -196,6 +212,7 @@
var index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/; var index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/;
var binaryFiles = /^Binary files (.*) and (.*) differ/; var binaryFiles = /^Binary files (.*) and (.*) differ/;
var binaryDiff = /^GIT binary patch/;
/* Combined Diff */ /* Combined Diff */
var combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/; var combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/;
@ -211,12 +228,23 @@
return; return;
} }
// Used to store regex capture groups
var values;
var prevLine = diffLines[lineIndex - 1]; var prevLine = diffLines[lineIndex - 1];
var nxtLine = diffLines[lineIndex + 1]; var nxtLine = diffLines[lineIndex + 1];
var afterNxtLine = diffLines[lineIndex + 2]; var afterNxtLine = diffLines[lineIndex + 2];
if (utils.startsWith(line, 'diff')) { if (utils.startsWith(line, 'diff')) {
startFile(); startFile();
// diff --git a/blocked_delta_results.png b/blocked_delta_results.png
var gitDiffStart = /^diff --git "?(.+)"? "?(.+)"?/;
if ((values = gitDiffStart.exec(line))) {
possibleOldName = _getFilename(null, values[1], config.dstPrefix);
possibleNewName = _getFilename(null, values[2], config.srcPrefix);
}
currentFile.isGitDiff = true; currentFile.isGitDiff = true;
return; return;
} }
@ -234,8 +262,6 @@
startFile(); startFile();
} }
var values;
/* /*
* We need to make sure that we have the three lines of the header. * We need to make sure that we have the three lines of the header.
* This avoids cases like the ones described in: * This avoids cases like the ones described in:
@ -328,8 +354,12 @@
currentFile.isRename = true; currentFile.isRename = true;
} else if ((values = binaryFiles.exec(line))) { } else if ((values = binaryFiles.exec(line))) {
currentFile.isBinary = true; currentFile.isBinary = true;
currentFile.oldName = _getFilename(null, values[1], [config.srcPrefix]); currentFile.oldName = _getFilename(null, values[1], config.srcPrefix);
currentFile.newName = _getFilename(null, values[2], [config.dstPrefix]); currentFile.newName = _getFilename(null, values[2], config.dstPrefix);
startBlock('Binary file');
} else if ((values = binaryDiff.exec(line))) {
currentFile.isBinary = true;
startBlock(line);
} else if ((values = similarityIndex.exec(line))) { } else if ((values = similarityIndex.exec(line))) {
currentFile.unchangedPercentage = values[1]; currentFile.unchangedPercentage = values[1];
} else if ((values = dissimilarityIndex.exec(line))) { } else if ((values = dissimilarityIndex.exec(line))) {
@ -369,26 +399,19 @@
} }
function getSrcFilename(line, cfg) { function getSrcFilename(line, cfg) {
var prefixes = ['a/', 'i/', 'w/', 'c/', 'o/']; return _getFilename('---', line, cfg.srcPrefix);
if (cfg.srcPrefix) {
prefixes.push(cfg.srcPrefix);
}
return _getFilename('---', line, prefixes);
} }
function getDstFilename(line, cfg) { function getDstFilename(line, cfg) {
var prefixes = ['b/', 'i/', 'w/', 'c/', 'o/']; return _getFilename('\\+\\+\\+', line, cfg.dstPrefix);
if (cfg.dstPrefix) {
prefixes.push(cfg.dstPrefix);
}
return _getFilename('\\+\\+\\+', line, prefixes);
} }
function _getFilename(linePrefix, line, prefixes) { function _getFilename(linePrefix, line, extraPrefix) {
var prefixes = ['a/', 'b/', 'i/', 'w/', 'c/', 'o/'];
if (extraPrefix) {
prefixes.push(extraPrefix);
}
var FilenameRegExp; var FilenameRegExp;
if (linePrefix) { if (linePrefix) {
FilenameRegExp = new RegExp('^' + linePrefix + ' "?(.+?)"?$'); FilenameRegExp = new RegExp('^' + linePrefix + ' "?(.+?)"?$');

View file

@ -627,10 +627,23 @@ describe('DiffParser', function() {
'diff --git "\ttardis.png" "\ttardis.png"\n' + 'diff --git "\ttardis.png" "\ttardis.png"\n' +
'new file mode 100644\n' + 'new file mode 100644\n' +
'index 0000000..d503a29\n' + 'index 0000000..d503a29\n' +
'Binary files /dev/null and "\ttardis.png" differ\n'; 'Binary files /dev/null and "\ttardis.png" differ\n' +
'diff --git a/src/test-bar.js b/src/test-baz.js\n' +
'similarity index 98%\n' +
'rename from src/test-bar.js\n' +
'rename to src/test-baz.js\n' +
'index e01513b..f14a870 100644\n' +
'--- a/src/test-bar.js\n' +
'+++ b/src/test-baz.js\n' +
'@@ -1,4 +1,32 @@\n' +
' function foo() {\n' +
'-var bar = "Whoops!";\n' +
'+var baz = "Whoops!";\n' +
' }\n' +
' ';
var result = DiffParser.generateDiffJson(diff, {'srcPrefix': '\t', 'dstPrefix': '\t'}); var result = DiffParser.generateDiffJson(diff, {'srcPrefix': '\t', 'dstPrefix': '\t'});
assert.equal(2, result.length); assert.equal(3, result.length);
var file1 = result[0]; var file1 = result[0];
assert.equal(2, file1.addedLines); assert.equal(2, file1.addedLines);
@ -644,6 +657,76 @@ describe('DiffParser', function() {
var file2 = result[1]; var file2 = result[1];
assert.equal('/dev/null', file2.oldName); assert.equal('/dev/null', file2.oldName);
assert.equal('tardis.png', file2.newName); assert.equal('tardis.png', file2.newName);
var file3 = result[2];
assert.equal(1, file3.addedLines);
assert.equal(1, file3.deletedLines);
assert.equal('src/test-bar.js', file3.oldName);
assert.equal('src/test-baz.js', file3.newName);
assert.equal(1, file3.blocks.length);
assert.equal(5, file3.blocks[0].lines.length);
var linesContent = file3.blocks[0].lines.map(function(line) {
return line.content;
});
assert.deepEqual(linesContent,
[' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']);
});
it('should parse binary with content', function() {
var diff =
'diff --git a/favicon.png b/favicon.png\n' +
'deleted file mode 100644\n' +
'index 2a9d516a5647205d7be510dd0dff93a3663eff6f..0000000000000000000000000000000000000000\n' +
'GIT binary patch\n' +
'literal 0\n' +
'HcmV?d00001\n' +
'\n' +
'literal 471\n' +
'zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf<Z~8yL>4nJ\n' +
'za0`Jj<E6WGe}IBwC9V-A&PAz-C7Jno3L%-fsSJk3`UaNzMkcGzh!g=;$beJ?=ckpF\n' +
'zCl;kLIHu$$r7E~(7NwTw7iAYKI0u`(*t4mJfq_xq)5S5wqIc=!hrWj$cv|<b{x!c(\n' +
'z;3r#y;31Y&=1q>qPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n' +
'z+Sn2Du3GS9U7qU`1*NYYlJi3u-!<?H-eky}wyIIL;8VU@wCDrb0``&v(jQ*DWSR4K\n' +
'zPq(3;isEyho{emNa=%%!jDPE`l3u;5d=q=<+v8kO-=C`*G#t-*AiE-D>-_B#8k9H0\n' +
'zGl{FnZs<2$wz5^=Q2h-1XI^s{LQL1#T4epqNPC%Orl(tD_@!*EY++~^Lt2<2&!&%=\n' +
'z`m>(TYj6uS7jDdt=eH>iOyQg(QMR<-Fw8)Dk^ZG)XQTuzEgl{`GpS?Cfq9818R9~=\n' +
'z{&h9@9n8F^?|qusoPy{k#%tVHzu7H$t26CR`BJZk*Ixf&u36WuS=?6m2^ho-p00i_\n' +
'I>zopr0Nz-&lmGw#\n' +
'diff --git a/src/test-bar.js b/src/test-baz.js\n' +
'similarity index 98%\n' +
'rename from src/test-bar.js\n' +
'rename to src/test-baz.js\n' +
'index e01513b..f14a870 100644\n' +
'--- a/src/test-bar.js\n' +
'+++ b/src/test-baz.js\n' +
'@@ -1,4 +1,32 @@\n' +
' function foo() {\n' +
'-var bar = "Whoops!";\n' +
'+var baz = "Whoops!";\n' +
' }\n' +
' ';
var result = DiffParser.generateDiffJson(diff);
assert.equal(2, result.length);
var file1 = result[0];
assert.equal('favicon.png', file1.oldName);
assert.equal('favicon.png', file1.newName);
assert.equal(1, file1.blocks.length);
assert.equal(0, file1.blocks[0].lines.length);
var file2 = result[1];
assert.equal(1, file2.addedLines);
assert.equal(1, file2.deletedLines);
assert.equal('src/test-bar.js', file2.oldName);
assert.equal('src/test-baz.js', file2.newName);
assert.equal(1, file2.blocks.length);
assert.equal(5, file2.blocks[0].lines.length);
var linesContent = file2.blocks[0].lines.map(function(line) {
return line.content;
});
assert.deepEqual(linesContent,
[' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']);
}); });
}); });
}); });