From e66d33169999374f16892d666bf430f9a308a92f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= <piranna@gmail.com> Date: Thu, 29 Oct 2015 12:54:58 +0100 Subject: [PATCH 1/3] Made 'parseHunk()' function easier to understand --- src/patch/parse.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/patch/parse.js b/src/patch/parse.js index 4d0466db..cb9a33aa 100644 --- a/src/patch/parse.js +++ b/src/patch/parse.js @@ -78,23 +78,27 @@ export function parsePatch(uniDiff, options = {}) { let addCount = 0, removeCount = 0; + for (; i < diffstr.length; i++) { - let operation = diffstr[i][0]; - - if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') { - hunk.lines.push(diffstr[i]); - - if (operation === '+') { - addCount++; - } else if (operation === '-') { - removeCount++; - } else if (operation === ' ') { - addCount++; - removeCount++; - } - } else { + let line = diffstr[i], + operation = line[0]; + + // Check begin of line is NOT from a hunk, end parsing + if (operation !== '+' + && operation !== '-' + && operation !== ' ' + && operation !== '\\') { break; } + + // Line is from a hunk, add it and update counters + hunk.lines.push(line); + + switch (operation) { + case '+': addCount++; break; + case '-': removeCount++; break; + case ' ': addCount++; removeCount++; break; + } } // Handle the empty block count case From eda82e8e9d1eb040772c9dc13c314791f43260e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= <piranna@gmail.com> Date: Thu, 29 Oct 2015 13:03:18 +0100 Subject: [PATCH 2/3] Renamed 'index' object to 'diff' --- src/patch/parse.js | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/patch/parse.js b/src/patch/parse.js index cb9a33aa..0a3843e3 100644 --- a/src/patch/parse.js +++ b/src/patch/parse.js @@ -3,13 +3,15 @@ export function parsePatch(uniDiff, options = {}) { list = [], i = 0; - function parseIndex() { - let index = {}; - list.push(index); + function parseDiff() { + let diff = {}; + list.push(diff); // Ignore any leading junk while (i < diffstr.length) { if (/^(Index:|diff -r|@@)/.test(diffstr[i])) { + let line = diffstr[i]; + break; } i++; @@ -17,31 +19,35 @@ export function parsePatch(uniDiff, options = {}) { let header = (/^(?:Index:|diff(?: -r \w+)+) (.*)/.exec(diffstr[i])); if (header) { - index.index = header[1]; i++; if (/^===/.test(diffstr[i])) { i++; + diff.index = header[1]; } - parseFileHeader(index); - parseFileHeader(index); } else { // Ignore erant header components that might occur at the start of the file parseFileHeader({}); parseFileHeader({}); } - index.hunks = []; + parseFileHeader(diff); + parseFileHeader(diff); + + // Parse diff hunks + diff.hunks = []; while (i < diffstr.length) { + let line = diffstr[i]; + if (/^(Index:|diff -r)/.test(diffstr[i])) { break; - } else if (/^@@/.test(diffstr[i])) { - index.hunks.push(parseHunk()); - } else if (diffstr[i] && options.strict) { + } else if (/^@@/.test(line)) { + diff.hunks.push(parseHunk()); + } else if (line && options.strict) { // Ignore unexpected content unless in strict mode - throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(diffstr[i])); + throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(line)); } else { i++; } @@ -50,12 +56,12 @@ export function parsePatch(uniDiff, options = {}) { // Parses the --- and +++ headers, if none are found, no lines // are consumed. - function parseFileHeader(index) { - let fileHeader = (/^(\-\-\-|\+\+\+)\s(\S+)\s?(.*)/.exec(diffstr[i])); + function parseFileHeader(diff) { + let fileHeader = (/^(\-\-\-|\+\+\+)\s(\S+)\s?(.+)/.exec(diffstr[i])); if (fileHeader) { let keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; - index[keyPrefix + 'FileName'] = fileHeader[2]; - index[keyPrefix + 'Header'] = fileHeader[3]; + diff[keyPrefix + 'FileName'] = fileHeader[2]; + diff[keyPrefix + 'Header'] = fileHeader[3]; i++; } @@ -123,7 +129,7 @@ export function parsePatch(uniDiff, options = {}) { } while (i < diffstr.length) { - parseIndex(); + parseDiff(); } return list; From b9969be97bcb16edb8775b70a15b0f281aa1e9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= <piranna@gmail.com> Date: Thu, 29 Oct 2015 13:04:20 +0100 Subject: [PATCH 3/3] Use file headers to split diffs instead of 'Index:' metadata --- src/patch/parse.js | 26 +++++++++----------------- test/patch/parse.js | 4 ++-- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/patch/parse.js b/src/patch/parse.js index 0a3843e3..8c64de03 100644 --- a/src/patch/parse.js +++ b/src/patch/parse.js @@ -7,31 +7,23 @@ export function parsePatch(uniDiff, options = {}) { let diff = {}; list.push(diff); - // Ignore any leading junk - while (i < diffstr.length) { - if (/^(Index:|diff -r|@@)/.test(diffstr[i])) { + // Parse diff metadata + for (; i < diffstr.length; i++) { let line = diffstr[i]; + // File header found, end parsing diff metadata + if (/^(\-\-\-|\+\+\+|@@)/.test(line)) { break; } - i++; - } - let header = (/^(?:Index:|diff(?: -r \w+)+) (.*)/.exec(diffstr[i])); - if (header) { - i++; - - if (/^===/.test(diffstr[i])) { - i++; + // Diff index + let header = (/^(?:Index:|diff(?: -r \w+)+) (.+)/).exec(line); + if (header) { diff.index = header[1]; } - - } else { - // Ignore erant header components that might occur at the start of the file - parseFileHeader({}); - parseFileHeader({}); } + // Parse header lines twice (one for old file and another for new one) parseFileHeader(diff); parseFileHeader(diff); @@ -41,7 +33,7 @@ export function parsePatch(uniDiff, options = {}) { while (i < diffstr.length) { let line = diffstr[i]; - if (/^(Index:|diff -r)/.test(diffstr[i])) { + if (/^(Index:|diff|\-\-\-|\+\+\+)\s(.+)/.test(line)) { break; } else if (/^@@/.test(line)) { diff.hunks.push(parseHunk()); diff --git a/test/patch/parse.js b/test/patch/parse.js index a7a9cb2d..cbe0350b 100644 --- a/test/patch/parse.js +++ b/test/patch/parse.js @@ -248,8 +248,8 @@ Index: test2 }); it('should throw on invalid input in strict mode', function() { expect(function() { - parsePatch('Index: foo\nfoo', {strict: true}); - }).to['throw'](/Unknown line 2 "foo"/); + parsePatch('Index: foo\n+++', {strict: true}); + }).to['throw'](/Unknown line 2 "\+\+\+"/); }); }); });