diff --git a/__tests__/parse.spec.js b/__tests__/parse.spec.js index 6e603fc..a2a8315 100644 --- a/__tests__/parse.spec.js +++ b/__tests__/parse.spec.js @@ -28,6 +28,8 @@ index 123..456 789 const file = files[0]; expect(file.from).toBe("file"); expect(file.to).toBe("file"); + expect(file.oldMode).toBe("789"); + expect(file.newMode).toBe("789"); expect(file.deletions).toBe(1); expect(file.additions).toBe(1); expect(file.chunks.length).toBe(1); @@ -85,6 +87,8 @@ Binary files a/Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects ' expect(file.to).toBe( "Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png" ); + expect(file.oldMode).toBe("100644"); + expect(file.newMode).toBe("100644"); }); it("should parse diff with new file mode line", function () { @@ -102,6 +106,7 @@ index 0000000..db81be4 expect(files.length).toBe(1); const file = files[0]; expect(file.new).toBeTruthy(); + expect(file.newMode).toBe("100644"); expect(file.from).toBe("/dev/null"); expect(file.to).toBe("test"); expect(file.chunks[0].content).toBe("@@ -0,0 +1,2 @@"); @@ -125,6 +130,7 @@ index db81be4..0000000 expect(files.length).toBe(1); const file = files[0]; expect(file.deleted).toBeTruthy(); + expect(file.oldMode).toBe("100644"); expect(file.from).toBe("test"); expect(file.to).toBe("/dev/null"); expect(file.chunks[0].content).toBe("@@ -1,2 +0,0 @@"); @@ -133,6 +139,35 @@ index db81be4..0000000 expect(file.chunks[0].changes[1].content).toBe("-line2"); }); + it("should parse diff with old and new mode lines", function () { + const diff = `\ +diff --git a/file b/file +old mode 100644 +new mode 100755 +index 123..456 +--- a/file ++++ b/file +@@ -1,2 +1,2 @@ +- line1 ++ line2\ +`; + const files = parse(diff); + expect(files.length).toBe(1); + const file = files[0]; + expect(file.oldMode).toBe("100644"); + expect(file.newMode).toBe("100755"); + expect(file.from).toBe("file"); + expect(file.to).toBe("file"); + expect(file.deletions).toBe(1); + expect(file.additions).toBe(1); + expect(file.chunks.length).toBe(1); + const chunk = file.chunks[0]; + expect(chunk.content).toBe("@@ -1,2 +1,2 @@"); + expect(chunk.changes.length).toBe(2); + expect(chunk.changes[0].content).toBe("- line1"); + expect(chunk.changes[1].content).toBe("+ line2"); + }); + it("should parse diff with single line files", function () { const diff = `\ diff --git a/file1 b/file1 @@ -154,6 +189,7 @@ index 0000000..db81be4 expect(files.length).toBe(2); let file = files[0]; expect(file.deleted).toBeTruthy(); + expect(file.oldMode).toBe("100644"); expect(file.from).toBe("file1"); expect(file.to).toBe("/dev/null"); expect(file.chunks[0].content).toBe("@@ -1 +0,0 @@"); @@ -162,6 +198,7 @@ index 0000000..db81be4 expect(file.chunks[0].changes[0].type).toBe("del"); file = files[1]; expect(file.new).toBeTruthy(); + expect(file.newMode).toBe("100644"); expect(file.from).toBe("/dev/null"); expect(file.to).toBe("file2"); expect(file.chunks[0].content).toBe("@@ -0,0 +1 @@"); @@ -196,6 +233,8 @@ index 123..456 789 let file = files[0]; expect(file.from).toBe("file1"); expect(file.to).toBe("file1"); + expect(file.oldMode).toBe("789"); + expect(file.newMode).toBe("789"); expect(file.chunks[0].content).toBe("@@ -1,1 +1,1 @@"); expect(file.chunks[0].changes.length).toBe(2); expect(file.chunks[0].changes[0].content).toBe("- line1"); @@ -203,6 +242,8 @@ index 123..456 789 file = files[1]; expect(file.from).toBe("file2"); expect(file.to).toBe("file2"); + expect(file.oldMode).toBe("789"); + expect(file.newMode).toBe("789"); expect(file.chunks[0].content).toBe("@@ -1,1 +1,1 @@"); expect(file.chunks[0].changes.length).toBe(2); expect(file.chunks[0].changes[0].content).toBe("- line1"); @@ -226,6 +267,8 @@ index 123..456 789 const file = files[0]; expect(file.from).toBe("file1"); expect(file.to).toBe("file1"); + expect(file.oldMode).toBe("789"); + expect(file.newMode).toBe("789"); const chunk = file.chunks[0]; expect(chunk.content).toBe("@@ -1,1 +1,1 @@"); expect(chunk.changes.length).toBe(4); @@ -343,6 +386,7 @@ index 0000000..e6a2e28\ const file = files[0]; expect(file.from).toBe("/dev/null"); expect(file.to).toBe("newFile.txt"); + expect(file.newMode).toBe("100644"); }); it("should parse file names for a deleted file", function () { @@ -356,6 +400,7 @@ index e6a2e28..0000000\ const file = files[0]; expect(file.from).toBe("deletedFile.txt"); expect(file.to).toBe("/dev/null"); + expect(file.oldMode).toBe("100644"); }); it("should parse rename diff with space in path with no changes", function () { @@ -411,6 +456,8 @@ index 9daeafb..88bd214 100644 const [file] = files; expect(file.from).toBe(`file \\"space\\"`); expect(file.to).toBe(`file \\"space\\"`); + expect(file.oldMode).toBe("100644"); + expect(file.newMode).toBe("100644"); }); it("should parse files with additional '-' and '+'", function () { @@ -438,10 +485,14 @@ index 123..456 789 expect(file1.from).toBe(`file1`); expect(file1.to).toBe(`file1`); + expect(file1.oldMode).toBe("789"); + expect(file1.newMode).toBe("789"); expect(file1.chunks[0].changes.length).toBe(3); expect(file2.from).toBe(`file2`); expect(file2.to).toBe(`file2`); + expect(file2.oldMode).toBe("789"); + expect(file2.newMode).toBe("789"); expect(file2.chunks[0].changes.length).toBe(3); }); }); diff --git a/index.d.ts b/index.d.ts index a589849..3a874cc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -7,6 +7,8 @@ declare namespace parseDiff { additions: number; from?: string; to?: string; + oldMode?: string; + newMode?: string; index?: string[]; deleted?: true; new?: true; diff --git a/index.js b/index.js index 6ee7132..7a5b12e 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -"use strict";function _createForOfIteratorHelper(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return{s:F,n:function n(){if(i>=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e2){throw _e2},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e3){didErr=true;err=_e3},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_unsupportedIterableToArray(arr,i)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e2){throw _e2},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e3){didErr=true;err=_e3},f:function f(){try{if(!normalCompletion&&it["return"]!=null)it["return"]()}finally{if(didErr)throw err}}}}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_unsupportedIterableToArray(arr,i)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i { if (!currentFile || currentFile.chunks.length) start(); }; - const newFile = () => { + const newFile = (_, match) => { restart(); currentFile.new = true; + currentFile.newMode = match[1]; currentFile.from = "/dev/null"; }; - const deletedFile = () => { + const deletedFile = (_, match) => { restart(); currentFile.deleted = true; + currentFile.oldMode = match[1]; currentFile.to = "/dev/null"; }; - const index = (line) => { + const oldMode = (_, match) => { + restart(); + currentFile.oldMode = match[1]; + }; + + const newMode = (_, match) => { + restart(); + currentFile.newMode = match[1]; + }; + + const index = (line, match) => { restart(); currentFile.index = line.split(" ").slice(1); + if (match[1]) { + currentFile.oldMode = currentFile.newMode = match[1].trim(); + } }; const fromFile = (line) => { @@ -136,8 +151,10 @@ module.exports = (input) => { const schemaHeaders = [ [/^diff\s/, start], - [/^new file mode \d+$/, newFile], - [/^deleted file mode \d+$/, deletedFile], + [/^new file mode (\d+)$/, newFile], + [/^deleted file mode (\d+)$/, deletedFile], + [/^old mode (\d+)$/, oldMode], + [/^new mode (\d+)$/, newMode], [/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/, index], [/^---\s/, fromFile], [/^\+\+\+\s/, toFile],