addons/shared/__tests__/parse.test.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import {splitLines} from '../diff';
b69ab319import {guessIsSubmodule, parseParsedDiff, parsePatch} from '../patch/parse';
b69ab3110
b69ab3111describe('patch/parse', () => {
b69ab3112 it('should parse basic modified patch', () => {
b69ab3113 const patch = `
b69ab3114diff --git sapling/eden/scm/a sapling/eden/scm/a
b69ab3115--- sapling/eden/scm/a
b69ab3116+++ sapling/eden/scm/a
b69ab3117@@ -1,1 +1,2 @@
b69ab3118 1
b69ab3119+2
b69ab3120`;
b69ab3121 const expected = [
b69ab3122 {
b69ab3123 hunks: [
b69ab3124 {
b69ab3125 linedelimiters: ['\n', '\n'],
b69ab3126 lines: [' 1', '+2'],
b69ab3127 newLines: 2,
b69ab3128 newStart: 1,
b69ab3129 oldLines: 1,
b69ab3130 oldStart: 1,
b69ab3131 },
b69ab3132 ],
b69ab3133 newFileName: 'sapling/eden/scm/a',
b69ab3134 oldFileName: 'sapling/eden/scm/a',
b69ab3135 type: 'Modified',
b69ab3136 },
b69ab3137 ];
b69ab3138 expect(parsePatch(patch)).toEqual(expected);
b69ab3139 });
b69ab3140
b69ab3141 it('should parse rename', () => {
b69ab3142 const patch = `
b69ab3143diff --git sapling/eden/scm/a sapling/eden/scm/b
b69ab3144rename from sapling/eden/scm/a
b69ab3145rename to sapling/eden/scm/b
b69ab3146`;
b69ab3147 const expected = [
b69ab3148 {
b69ab3149 hunks: [],
b69ab3150 newFileName: 'sapling/eden/scm/b',
b69ab3151 oldFileName: 'sapling/eden/scm/a',
b69ab3152 type: 'Renamed',
b69ab3153 },
b69ab3154 ];
b69ab3155 expect(parsePatch(patch)).toEqual(expected);
b69ab3156 });
b69ab3157
b69ab3158 it('should parse rename and modify', () => {
b69ab3159 const patch = `
b69ab3160diff --git sapling/eden/addons/LICENSE sapling/eden/addons/LICENSE.bak
b69ab3161rename from sapling/eden/addons/LICENSE
b69ab3162rename to sapling/eden/addons/LICENSE.bak
b69ab3163--- sapling/eden/addons/LICENSE
b69ab3164+++ sapling/eden/addons/LICENSE.bak
b69ab3165@@ -2,6 +2,7 @@
b69ab3166
b69ab3167 Copyright (c) Meta Platforms, Inc. and its affiliates.
b69ab3168
b69ab3169+
b69ab3170`;
b69ab3171 const expected = [
b69ab3172 {
b69ab3173 hunks: [
b69ab3174 {
b69ab3175 linedelimiters: ['\n', '\n', '\n', '\n'],
b69ab3176 lines: ['', ' Copyright (c) Meta Platforms, Inc. and its affiliates.', '', '+'],
b69ab3177 newLines: 7,
b69ab3178 newStart: 2,
b69ab3179 oldLines: 6,
b69ab3180 oldStart: 2,
b69ab3181 },
b69ab3182 ],
b69ab3183 newFileName: 'sapling/eden/addons/LICENSE.bak',
b69ab3184 oldFileName: 'sapling/eden/addons/LICENSE',
b69ab3185 type: 'Renamed',
b69ab3186 },
b69ab3187 ];
b69ab3188 expect(parsePatch(patch)).toEqual(expected);
b69ab3189 });
b69ab3190
b69ab3191 it('should parse new file', () => {
b69ab3192 const patch = `
b69ab3193diff --git sapling/eden/scm/c sapling/eden/scm/c
b69ab3194new file mode 100644
b69ab3195--- /dev/null
b69ab3196+++ sapling/eden/scm/c
b69ab3197@@ -0,0 +1,1 @@
b69ab3198+1
b69ab3199`;
b69ab31100 const expected = [
b69ab31101 {
b69ab31102 hunks: [
b69ab31103 {
b69ab31104 linedelimiters: ['\n'],
b69ab31105 lines: ['+1'],
b69ab31106 newLines: 1,
b69ab31107 newStart: 1,
b69ab31108 oldLines: 0,
b69ab31109 oldStart: 1,
b69ab31110 },
b69ab31111 ],
b69ab31112 newFileName: 'sapling/eden/scm/c',
b69ab31113 newMode: '100644',
b69ab31114 oldFileName: 'sapling/eden/scm/c',
b69ab31115 type: 'Added',
b69ab31116 },
b69ab31117 ];
b69ab31118 expect(parsePatch(patch)).toEqual(expected);
b69ab31119 });
b69ab31120
b69ab31121 it('should parse new empty file', () => {
b69ab31122 const patch = `
b69ab31123diff --git sapling/eden/addons/d sapling/eden/addons/d
b69ab31124new file mode 100644
b69ab31125`;
b69ab31126 const expected = [
b69ab31127 {
b69ab31128 hunks: [],
b69ab31129 newFileName: 'sapling/eden/addons/d',
b69ab31130 newMode: '100644',
b69ab31131 oldFileName: 'sapling/eden/addons/d',
b69ab31132 type: 'Added',
b69ab31133 },
b69ab31134 ];
b69ab31135 expect(parsePatch(patch)).toEqual(expected);
b69ab31136 });
b69ab31137
b69ab31138 it('should parse deleted file', () => {
b69ab31139 const patch = `
b69ab31140diff --git sapling/eden/scm/a sapling/eden/scm/a
b69ab31141deleted file mode 100644
b69ab31142--- sapling/eden/scm/a
b69ab31143+++ /dev/null
b69ab31144@@ -1,1 +0,0 @@
b69ab31145-1
b69ab31146`;
b69ab31147 const expected = [
b69ab31148 {
b69ab31149 hunks: [
b69ab31150 {
b69ab31151 linedelimiters: ['\n'],
b69ab31152 lines: ['-1'],
b69ab31153 newLines: 0,
b69ab31154 newStart: 1,
b69ab31155 oldLines: 1,
b69ab31156 oldStart: 1,
b69ab31157 },
b69ab31158 ],
b69ab31159 newFileName: 'sapling/eden/scm/a',
b69ab31160 newMode: '100644',
b69ab31161 oldFileName: 'sapling/eden/scm/a',
b69ab31162 type: 'Removed',
b69ab31163 },
b69ab31164 ];
b69ab31165 expect(parsePatch(patch)).toEqual(expected);
b69ab31166 });
b69ab31167
b69ab31168 it('should parse copied file', () => {
b69ab31169 const patch = `
b69ab31170diff --git sapling/eden/scm/a sapling/eden/scm/b
b69ab31171copy from sapling/eden/scm/a
b69ab31172copy to sapling/eden/scm/b
b69ab31173`;
b69ab31174 const expected = [
b69ab31175 {
b69ab31176 hunks: [],
b69ab31177 newFileName: 'sapling/eden/scm/b',
b69ab31178 oldFileName: 'sapling/eden/scm/a',
b69ab31179 type: 'Copied',
b69ab31180 },
b69ab31181 ];
b69ab31182 expect(parsePatch(patch)).toEqual(expected);
b69ab31183 });
b69ab31184
b69ab31185 it('should parse multiple files', () => {
b69ab31186 const patch = `
b69ab31187diff --git sapling/eden/scm/a sapling/eden/scm/a
b69ab31188--- sapling/eden/scm/a
b69ab31189+++ sapling/eden/scm/a
b69ab31190@@ -1,1 +1,2 @@
b69ab31191 1
b69ab31192+2
b69ab31193diff --git sapling/eden/scm/a sapling/eden/scm/b
b69ab31194copy from sapling/eden/scm/a
b69ab31195copy to sapling/eden/scm/b
b69ab31196diff --git sapling/eden/scm/c sapling/eden/scm/d
b69ab31197copy from sapling/eden/scm/c
b69ab31198copy to sapling/eden/scm/d
b69ab31199`;
b69ab31200 const expected = [
b69ab31201 {
b69ab31202 hunks: [
b69ab31203 {
b69ab31204 linedelimiters: ['\n', '\n'],
b69ab31205 lines: [' 1', '+2'],
b69ab31206 newLines: 2,
b69ab31207 newStart: 1,
b69ab31208 oldLines: 1,
b69ab31209 oldStart: 1,
b69ab31210 },
b69ab31211 ],
b69ab31212 newFileName: 'sapling/eden/scm/a',
b69ab31213 oldFileName: 'sapling/eden/scm/a',
b69ab31214 type: 'Modified',
b69ab31215 },
b69ab31216 {
b69ab31217 hunks: [],
b69ab31218 newFileName: 'sapling/eden/scm/b',
b69ab31219 oldFileName: 'sapling/eden/scm/a',
b69ab31220 type: 'Copied',
b69ab31221 },
b69ab31222 {
b69ab31223 hunks: [],
b69ab31224 newFileName: 'sapling/eden/scm/d',
b69ab31225 oldFileName: 'sapling/eden/scm/c',
b69ab31226 type: 'Copied',
b69ab31227 },
b69ab31228 ];
b69ab31229 expect(parsePatch(patch)).toEqual(expected);
b69ab31230 });
b69ab31231
b69ab31232 it('should parse file mode change', () => {
b69ab31233 const patch = `
b69ab31234diff --git sapling/eden/scm/a sapling/eden/scm/a
b69ab31235old mode 100644
b69ab31236new mode 100755
b69ab31237`;
b69ab31238 const expected = [
b69ab31239 {
b69ab31240 hunks: [],
b69ab31241 newFileName: 'sapling/eden/scm/a',
b69ab31242 newMode: '100755',
b69ab31243 oldFileName: 'sapling/eden/scm/a',
b69ab31244 oldMode: '100644',
b69ab31245 type: 'Modified',
b69ab31246 },
b69ab31247 ];
b69ab31248 expect(parsePatch(patch)).toEqual(expected);
b69ab31249 });
b69ab31250
b69ab31251 it('should fail for invalid file mode format', () => {
b69ab31252 const patch = `
b69ab31253diff --git sapling/eden/scm/a sapling/eden/scm/a
b69ab31254old mode XXX
b69ab31255new mode 100755
b69ab31256`;
b69ab31257 expect(() => parsePatch(patch)).toThrow("invalid format 'old mode XXX'");
b69ab31258 });
b69ab31259});
b69ab31260
b69ab31261describe('guessSubmodule', () => {
b69ab31262 it('modified submodules', () => {
b69ab31263 const patch = `
b69ab31264diff --git a/external/brotli b/external/brotli
b69ab31265--- a/external/brotli
b69ab31266+++ b/external/brotli
b69ab31267@@ -1,1 +1,1 @@
b69ab31268-Subproject commit 892110204ccf44fcd493ae415c9a69c470c2a9cf
b69ab31269+Subproject commit 57de5cc4288565a9c3a7af978ef15f0abf0ada1b
b69ab31270diff --git a/external/rust/cxx b/external/rust/cxx
b69ab31271--- a/external/rust/cxx
b69ab31272+++ b/external/rust/cxx
b69ab31273@@ -1,1 +1,1 @@
b69ab31274-Subproject commit 862a23082a087566776280a5b1539d3b62701bcb
b69ab31275+Subproject commit 1869e93e54fa9d9425bd88bdb25073af9ed7e782
b69ab31276`;
b69ab31277 const parsed = parsePatch(patch);
b69ab31278 expect(parsed.length).toEqual(2);
b69ab31279 expect(guessIsSubmodule(parsed[0])).toEqual(true);
b69ab31280 expect(guessIsSubmodule(parsed[1])).toEqual(true);
b69ab31281 });
b69ab31282
b69ab31283 it('added submodule', () => {
b69ab31284 const patch = `
b69ab31285diff --git a/path/to/submodule b/path/to/submodule
b69ab31286new file mode 160000
b69ab31287--- /dev/null
b69ab31288+++ b/path/to/submodule
b69ab31289@@ -0,0 +1,1 @@
b69ab31290+Subproject commit 7ef4220022059b9b1e1d8ec4eea6f7abd011894f
b69ab31291`;
b69ab31292 const parsed = parsePatch(patch);
b69ab31293 expect(parsed.length).toEqual(1);
b69ab31294 expect(guessIsSubmodule(parsed[0])).toEqual(true);
b69ab31295 });
b69ab31296
b69ab31297 it('invalid file modification', () => {
b69ab31298 const patch = `
b69ab31299diff --git sapling/eden/scm/a sapling/eden/scm/a
b69ab31300--- sapling/eden/scm/a
b69ab31301+++ sapling/eden/scm/a
b69ab31302@@ -1,1 +1,2 @@
b69ab31303 Subproject commit abcdef01234556789ABCDEF
b69ab31304+Subproject commit abcdef01234556789ABCDEF
b69ab31305`;
b69ab31306 const parsed = parsePatch(patch);
b69ab31307 expect(parsed.length).toEqual(1);
b69ab31308 expect(guessIsSubmodule(parsed[0])).toEqual(false);
b69ab31309 });
b69ab31310
b69ab31311 it('invalid hash value', () => {
b69ab31312 const patch = `
b69ab31313diff --git a/external/rust/cxx b/external/rust/cxx
b69ab31314--- a/external/rust/cxx
b69ab31315+++ b/external/rust/cxx
b69ab31316@@ -1,1 +1,1 @@
b69ab31317-Subproject commit ghijklmnGHIJKLMN
b69ab31318+Subproject commit ghijklmnGHIJKLMN
b69ab31319`;
b69ab31320 const parsed = parsePatch(patch);
b69ab31321 expect(parsed.length).toEqual(1);
b69ab31322 expect(guessIsSubmodule(parsed[0])).toEqual(false);
b69ab31323 });
b69ab31324});
b69ab31325
b69ab31326describe('createParsedDiffWithLines', () => {
b69ab31327 it('return no hunks for empty lines', () => {
b69ab31328 expect(parseParsedDiff([], [], 1)).toMatchObject({hunks: []});
b69ab31329 });
b69ab31330
b69ab31331 it('returns no hunks when comparing same lines', () => {
b69ab31332 const lines = splitLines('a\nb\nc\nd\ne\n');
b69ab31333 expect(parseParsedDiff(lines, lines, 1)).toMatchObject({hunks: []});
b69ab31334 });
b69ab31335
b69ab31336 it('return all "-" for old code and "=" for new code for totally different contents', () => {
b69ab31337 const aLines = splitLines('x\ny\n');
b69ab31338 const bLines = splitLines('a\nb\nc\n');
b69ab31339 expect(parseParsedDiff(aLines, bLines, 1)).toMatchObject({
b69ab31340 hunks: [
b69ab31341 {
b69ab31342 oldStart: 1,
b69ab31343 oldLines: 2,
b69ab31344 newStart: 1,
b69ab31345 newLines: 3,
b69ab31346 lines: ['-x\n', '-y\n', '+a\n', '+b\n', '+c\n'],
b69ab31347 linedelimiters: ['\n', '\n', '\n', '\n', '\n'],
b69ab31348 },
b69ab31349 ],
b69ab31350 });
b69ab31351 });
b69ab31352
b69ab31353 it('return for when a line was changed in the middle', () => {
b69ab31354 const aLines = splitLines('a\nb\nc\nd\ne\n');
b69ab31355 const bLines = splitLines('a\nb\nc\nd1\nd2\ne\n');
b69ab31356 expect(parseParsedDiff(aLines, bLines, 1)).toMatchObject({
b69ab31357 hunks: [
b69ab31358 {
b69ab31359 oldStart: 4,
b69ab31360 oldLines: 1,
b69ab31361 newStart: 4,
b69ab31362 newLines: 2,
b69ab31363 lines: ['-d\n', '+d1\n', '+d2\n'],
b69ab31364 linedelimiters: ['\n', '\n', '\n'],
b69ab31365 },
b69ab31366 ],
b69ab31367 });
b69ab31368 });
b69ab31369});