From 0f2d65043669215aff71877db0e66938877e565d Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sat, 12 Nov 2016 22:41:17 +0000 Subject: [PATCH] Parse binary patch diffs --- src/diff-parser.js | 67 ++++++++++++++++++++---------- test/diff-parser-tests.js | 87 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 24 deletions(-) diff --git a/src/diff-parser.js b/src/diff-parser.js index 0a62963..4f3fdf6 100644 --- a/src/diff-parser.js +++ b/src/diff-parser.js @@ -32,6 +32,9 @@ var oldLine2 = null; // Used for combined diff var newLine = null; + var possibleOldName; + var possibleNewName; + /* Diff Header */ var oldFileNameHeader = '--- '; var newFileNameHeader = '+++ '; @@ -50,10 +53,23 @@ * if it has name (to avoid binary files errors) */ function saveFile() { - if (currentFile && currentFile.newName) { - files.push(currentFile); - currentFile = null; + if (currentFile) { + if (!currentFile.oldName) { + currentFile.oldName = possibleOldName; + } + + if (!currentFile.newName) { + currentFile.newName = possibleNewName; + } + + if (currentFile.newName) { + files.push(currentFile); + currentFile = null; + } } + + possibleOldName = undefined; + possibleNewName = undefined; } /* Create file structure */ @@ -196,6 +212,7 @@ var index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/; var binaryFiles = /^Binary files (.*) and (.*) differ/; + var binaryDiff = /^GIT binary patch/; /* Combined Diff */ var combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/; @@ -211,12 +228,23 @@ return; } + // Used to store regex capture groups + var values; + var prevLine = diffLines[lineIndex - 1]; var nxtLine = diffLines[lineIndex + 1]; var afterNxtLine = diffLines[lineIndex + 2]; if (utils.startsWith(line, 'diff')) { 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; return; } @@ -234,8 +262,6 @@ startFile(); } - var values; - /* * We need to make sure that we have the three lines of the header. * This avoids cases like the ones described in: @@ -328,8 +354,12 @@ currentFile.isRename = true; } else if ((values = binaryFiles.exec(line))) { currentFile.isBinary = true; - currentFile.oldName = _getFilename(null, values[1], [config.srcPrefix]); - currentFile.newName = _getFilename(null, values[2], [config.dstPrefix]); + currentFile.oldName = _getFilename(null, values[1], config.srcPrefix); + 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))) { currentFile.unchangedPercentage = values[1]; } else if ((values = dissimilarityIndex.exec(line))) { @@ -369,26 +399,19 @@ } function getSrcFilename(line, cfg) { - var prefixes = ['a/', 'i/', 'w/', 'c/', 'o/']; - - if (cfg.srcPrefix) { - prefixes.push(cfg.srcPrefix); - } - - return _getFilename('---', line, prefixes); + return _getFilename('---', line, cfg.srcPrefix); } function getDstFilename(line, cfg) { - var prefixes = ['b/', 'i/', 'w/', 'c/', 'o/']; - - if (cfg.dstPrefix) { - prefixes.push(cfg.dstPrefix); - } - - return _getFilename('\\+\\+\\+', line, prefixes); + return _getFilename('\\+\\+\\+', line, cfg.dstPrefix); } - 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; if (linePrefix) { FilenameRegExp = new RegExp('^' + linePrefix + ' "?(.+?)"?$'); diff --git a/test/diff-parser-tests.js b/test/diff-parser-tests.js index 335186a..b910868 100644 --- a/test/diff-parser-tests.js +++ b/test/diff-parser-tests.js @@ -627,10 +627,23 @@ describe('DiffParser', function() { 'diff --git "\ttardis.png" "\ttardis.png"\n' + 'new file mode 100644\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'}); - assert.equal(2, result.length); + assert.equal(3, result.length); var file1 = result[0]; assert.equal(2, file1.addedLines); @@ -644,6 +657,76 @@ describe('DiffParser', function() { var file2 = result[1]; assert.equal('/dev/null', file2.oldName); 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!;#Vf4nJ\n' + + 'za0`JjqPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n' + + 'z+Sn2Du3GS9U7qU`1*NYYlJi3u-!-_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!";', ' }', ' ']); }); }); });