Skip to content

Commit 929d9f1

Browse files
authored
Merge pull request #116 from rtfpessoa/parse-binary-patch-diff
Parse binary patch diffs
2 parents 1b9200b + 0f2d650 commit 929d9f1

File tree

2 files changed

+129
-23
lines changed

2 files changed

+129
-23
lines changed

src/diff-parser.js

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
var oldLine2 = null; // Used for combined diff
3333
var newLine = null;
3434

35+
var possibleOldName;
36+
var possibleNewName;
37+
3538
/* Diff Header */
3639
var oldFileNameHeader = '--- ';
3740
var newFileNameHeader = '+++ ';
@@ -50,10 +53,23 @@
5053
* if it has name (to avoid binary files errors)
5154
*/
5255
function saveFile() {
53-
if (currentFile && currentFile.newName) {
54-
files.push(currentFile);
55-
currentFile = null;
56+
if (currentFile) {
57+
if (!currentFile.oldName) {
58+
currentFile.oldName = possibleOldName;
59+
}
60+
61+
if (!currentFile.newName) {
62+
currentFile.newName = possibleNewName;
63+
}
64+
65+
if (currentFile.newName) {
66+
files.push(currentFile);
67+
currentFile = null;
68+
}
5669
}
70+
71+
possibleOldName = undefined;
72+
possibleNewName = undefined;
5773
}
5874

5975
/* Create file structure */
@@ -196,6 +212,7 @@
196212
var index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/;
197213

198214
var binaryFiles = /^Binary files (.*) and (.*) differ/;
215+
var binaryDiff = /^GIT binary patch/;
199216

200217
/* Combined Diff */
201218
var combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/;
@@ -211,12 +228,23 @@
211228
return;
212229
}
213230

231+
// Used to store regex capture groups
232+
var values;
233+
214234
var prevLine = diffLines[lineIndex - 1];
215235
var nxtLine = diffLines[lineIndex + 1];
216236
var afterNxtLine = diffLines[lineIndex + 2];
217237

218238
if (utils.startsWith(line, 'diff')) {
219239
startFile();
240+
241+
// diff --git a/blocked_delta_results.png b/blocked_delta_results.png
242+
var gitDiffStart = /^diff --git "?(.+)"? "?(.+)"?/;
243+
if ((values = gitDiffStart.exec(line))) {
244+
possibleOldName = _getFilename(null, values[1], config.dstPrefix);
245+
possibleNewName = _getFilename(null, values[2], config.srcPrefix);
246+
}
247+
220248
currentFile.isGitDiff = true;
221249
return;
222250
}
@@ -234,8 +262,6 @@
234262
startFile();
235263
}
236264

237-
var values;
238-
239265
/*
240266
* We need to make sure that we have the three lines of the header.
241267
* This avoids cases like the ones described in:
@@ -328,8 +354,12 @@
328354
currentFile.isRename = true;
329355
} else if ((values = binaryFiles.exec(line))) {
330356
currentFile.isBinary = true;
331-
currentFile.oldName = _getFilename(null, values[1], [config.srcPrefix]);
332-
currentFile.newName = _getFilename(null, values[2], [config.dstPrefix]);
357+
currentFile.oldName = _getFilename(null, values[1], config.srcPrefix);
358+
currentFile.newName = _getFilename(null, values[2], config.dstPrefix);
359+
startBlock('Binary file');
360+
} else if ((values = binaryDiff.exec(line))) {
361+
currentFile.isBinary = true;
362+
startBlock(line);
333363
} else if ((values = similarityIndex.exec(line))) {
334364
currentFile.unchangedPercentage = values[1];
335365
} else if ((values = dissimilarityIndex.exec(line))) {
@@ -369,26 +399,19 @@
369399
}
370400

371401
function getSrcFilename(line, cfg) {
372-
var prefixes = ['a/', 'i/', 'w/', 'c/', 'o/'];
373-
374-
if (cfg.srcPrefix) {
375-
prefixes.push(cfg.srcPrefix);
376-
}
377-
378-
return _getFilename('---', line, prefixes);
402+
return _getFilename('---', line, cfg.srcPrefix);
379403
}
380404

381405
function getDstFilename(line, cfg) {
382-
var prefixes = ['b/', 'i/', 'w/', 'c/', 'o/'];
406+
return _getFilename('\\+\\+\\+', line, cfg.dstPrefix);
407+
}
383408

384-
if (cfg.dstPrefix) {
385-
prefixes.push(cfg.dstPrefix);
409+
function _getFilename(linePrefix, line, extraPrefix) {
410+
var prefixes = ['a/', 'b/', 'i/', 'w/', 'c/', 'o/'];
411+
if (extraPrefix) {
412+
prefixes.push(extraPrefix);
386413
}
387414

388-
return _getFilename('\\+\\+\\+', line, prefixes);
389-
}
390-
391-
function _getFilename(linePrefix, line, prefixes) {
392415
var FilenameRegExp;
393416
if (linePrefix) {
394417
FilenameRegExp = new RegExp('^' + linePrefix + ' "?(.+?)"?$');

test/diff-parser-tests.js

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,10 +627,23 @@ describe('DiffParser', function() {
627627
'diff --git "\ttardis.png" "\ttardis.png"\n' +
628628
'new file mode 100644\n' +
629629
'index 0000000..d503a29\n' +
630-
'Binary files /dev/null and "\ttardis.png" differ\n';
630+
'Binary files /dev/null and "\ttardis.png" differ\n' +
631+
'diff --git a/src/test-bar.js b/src/test-baz.js\n' +
632+
'similarity index 98%\n' +
633+
'rename from src/test-bar.js\n' +
634+
'rename to src/test-baz.js\n' +
635+
'index e01513b..f14a870 100644\n' +
636+
'--- a/src/test-bar.js\n' +
637+
'+++ b/src/test-baz.js\n' +
638+
'@@ -1,4 +1,32 @@\n' +
639+
' function foo() {\n' +
640+
'-var bar = "Whoops!";\n' +
641+
'+var baz = "Whoops!";\n' +
642+
' }\n' +
643+
' ';
631644

632645
var result = DiffParser.generateDiffJson(diff, {'srcPrefix': '\t', 'dstPrefix': '\t'});
633-
assert.equal(2, result.length);
646+
assert.equal(3, result.length);
634647

635648
var file1 = result[0];
636649
assert.equal(2, file1.addedLines);
@@ -644,6 +657,76 @@ describe('DiffParser', function() {
644657
var file2 = result[1];
645658
assert.equal('/dev/null', file2.oldName);
646659
assert.equal('tardis.png', file2.newName);
660+
661+
var file3 = result[2];
662+
assert.equal(1, file3.addedLines);
663+
assert.equal(1, file3.deletedLines);
664+
assert.equal('src/test-bar.js', file3.oldName);
665+
assert.equal('src/test-baz.js', file3.newName);
666+
assert.equal(1, file3.blocks.length);
667+
assert.equal(5, file3.blocks[0].lines.length);
668+
var linesContent = file3.blocks[0].lines.map(function(line) {
669+
return line.content;
670+
});
671+
assert.deepEqual(linesContent,
672+
[' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']);
673+
});
674+
675+
it('should parse binary with content', function() {
676+
var diff =
677+
'diff --git a/favicon.png b/favicon.png\n' +
678+
'deleted file mode 100644\n' +
679+
'index 2a9d516a5647205d7be510dd0dff93a3663eff6f..0000000000000000000000000000000000000000\n' +
680+
'GIT binary patch\n' +
681+
'literal 0\n' +
682+
'HcmV?d00001\n' +
683+
'\n' +
684+
'literal 471\n' +
685+
'zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf<Z~8yL>4nJ\n' +
686+
'za0`Jj<E6WGe}IBwC9V-A&PAz-C7Jno3L%-fsSJk3`UaNzMkcGzh!g=;$beJ?=ckpF\n' +
687+
'zCl;kLIHu$$r7E~(7NwTw7iAYKI0u`(*t4mJfq_xq)5S5wqIc=!hrWj$cv|<b{x!c(\n' +
688+
'z;3r#y;31Y&=1q>qPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n' +
689+
'z+Sn2Du3GS9U7qU`1*NYYlJi3u-!<?H-eky}wyIIL;8VU@wCDrb0``&v(jQ*DWSR4K\n' +
690+
'zPq(3;isEyho{emNa=%%!jDPE`l3u;5d=q=<+v8kO-=C`*G#t-*AiE-D>-_B#8k9H0\n' +
691+
'zGl{FnZs<2$wz5^=Q2h-1XI^s{LQL1#T4epqNPC%Orl(tD_@!*EY++~^Lt2<2&!&%=\n' +
692+
'z`m>(TYj6uS7jDdt=eH>iOyQg(QMR<-Fw8)Dk^ZG)XQTuzEgl{`GpS?Cfq9818R9~=\n' +
693+
'z{&h9@9n8F^?|qusoPy{k#%tVHzu7H$t26CR`BJZk*Ixf&u36WuS=?6m2^ho-p00i_\n' +
694+
'I>zopr0Nz-&lmGw#\n' +
695+
'diff --git a/src/test-bar.js b/src/test-baz.js\n' +
696+
'similarity index 98%\n' +
697+
'rename from src/test-bar.js\n' +
698+
'rename to src/test-baz.js\n' +
699+
'index e01513b..f14a870 100644\n' +
700+
'--- a/src/test-bar.js\n' +
701+
'+++ b/src/test-baz.js\n' +
702+
'@@ -1,4 +1,32 @@\n' +
703+
' function foo() {\n' +
704+
'-var bar = "Whoops!";\n' +
705+
'+var baz = "Whoops!";\n' +
706+
' }\n' +
707+
' ';
708+
709+
var result = DiffParser.generateDiffJson(diff);
710+
assert.equal(2, result.length);
711+
712+
var file1 = result[0];
713+
assert.equal('favicon.png', file1.oldName);
714+
assert.equal('favicon.png', file1.newName);
715+
assert.equal(1, file1.blocks.length);
716+
assert.equal(0, file1.blocks[0].lines.length);
717+
718+
var file2 = result[1];
719+
assert.equal(1, file2.addedLines);
720+
assert.equal(1, file2.deletedLines);
721+
assert.equal('src/test-bar.js', file2.oldName);
722+
assert.equal('src/test-baz.js', file2.newName);
723+
assert.equal(1, file2.blocks.length);
724+
assert.equal(5, file2.blocks[0].lines.length);
725+
var linesContent = file2.blocks[0].lines.map(function(line) {
726+
return line.content;
727+
});
728+
assert.deepEqual(linesContent,
729+
[' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']);
647730
});
648731
});
649732
});

0 commit comments

Comments
 (0)