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 "\+\+\+"/);
     });
   });
 });