UNPKG

12.6 kBJavaScriptView Raw
1var __spreadArrays = (this && this.__spreadArrays) || function () {
2 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
3 for (var r = Array(s), k = 0, i = 0; i < il; i++)
4 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
5 r[k] = a[j];
6 return r;
7};
8import { LineType } from './types';
9import { escapeForRegExp } from './utils';
10function getExtension(filename, language) {
11 var filenameParts = filename.split('.');
12 return filenameParts.length > 1 ? filenameParts[filenameParts.length - 1] : language;
13}
14function startsWithAny(str, prefixes) {
15 return prefixes.reduce(function (startsWith, prefix) { return startsWith || str.startsWith(prefix); }, false);
16}
17var baseDiffFilenamePrefixes = ['a/', 'b/', 'i/', 'w/', 'c/', 'o/'];
18function getFilename(line, linePrefix, extraPrefix) {
19 var prefixes = extraPrefix !== undefined ? __spreadArrays(baseDiffFilenamePrefixes, [extraPrefix]) : baseDiffFilenamePrefixes;
20 var FilenameRegExp = linePrefix
21 ? new RegExp("^" + escapeForRegExp(linePrefix) + " \"?(.+?)\"?$")
22 : new RegExp('^"?(.+?)"?$');
23 var _a = FilenameRegExp.exec(line) || [], _b = _a[1], filename = _b === void 0 ? '' : _b;
24 var matchingPrefix = prefixes.find(function (p) { return filename.indexOf(p) === 0; });
25 var fnameWithoutPrefix = matchingPrefix ? filename.slice(matchingPrefix.length) : filename;
26 return fnameWithoutPrefix.replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [+-]\d{4}.*$/, '');
27}
28function getSrcFilename(line, srcPrefix) {
29 return getFilename(line, '---', srcPrefix);
30}
31function getDstFilename(line, dstPrefix) {
32 return getFilename(line, '+++', dstPrefix);
33}
34export function parse(diffInput, config) {
35 if (config === void 0) { config = {}; }
36 var files = [];
37 var currentFile = null;
38 var currentBlock = null;
39 var oldLine = null;
40 var oldLine2 = null;
41 var newLine = null;
42 var possibleOldName = null;
43 var possibleNewName = null;
44 var oldFileNameHeader = '--- ';
45 var newFileNameHeader = '+++ ';
46 var hunkHeaderPrefix = '@@';
47 var oldMode = /^old mode (\d{6})/;
48 var newMode = /^new mode (\d{6})/;
49 var deletedFileMode = /^deleted file mode (\d{6})/;
50 var newFileMode = /^new file mode (\d{6})/;
51 var copyFrom = /^copy from "?(.+)"?/;
52 var copyTo = /^copy to "?(.+)"?/;
53 var renameFrom = /^rename from "?(.+)"?/;
54 var renameTo = /^rename to "?(.+)"?/;
55 var similarityIndex = /^similarity index (\d+)%/;
56 var dissimilarityIndex = /^dissimilarity index (\d+)%/;
57 var index = /^index ([\da-z]+)\.\.([\da-z]+)\s*(\d{6})?/;
58 var binaryFiles = /^Binary files (.*) and (.*) differ/;
59 var binaryDiff = /^GIT binary patch/;
60 var combinedIndex = /^index ([\da-z]+),([\da-z]+)\.\.([\da-z]+)/;
61 var combinedMode = /^mode (\d{6}),(\d{6})\.\.(\d{6})/;
62 var combinedNewFile = /^new file mode (\d{6})/;
63 var combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/;
64 var diffLines = diffInput
65 .replace(/\\ No newline at end of file/g, '')
66 .replace(/\r\n?/g, '\n')
67 .split('\n');
68 function saveBlock() {
69 if (currentBlock !== null && currentFile !== null) {
70 currentFile.blocks.push(currentBlock);
71 currentBlock = null;
72 }
73 }
74 function saveFile() {
75 if (currentFile !== null) {
76 if (!currentFile.oldName && possibleOldName !== null) {
77 currentFile.oldName = possibleOldName;
78 }
79 if (!currentFile.newName && possibleNewName !== null) {
80 currentFile.newName = possibleNewName;
81 }
82 if (currentFile.newName) {
83 files.push(currentFile);
84 currentFile = null;
85 }
86 }
87 possibleOldName = null;
88 possibleNewName = null;
89 }
90 function startFile() {
91 saveBlock();
92 saveFile();
93 currentFile = {
94 blocks: [],
95 deletedLines: 0,
96 addedLines: 0,
97 };
98 }
99 function startBlock(line) {
100 saveBlock();
101 var values;
102 if (currentFile !== null) {
103 if ((values = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@.*/.exec(line))) {
104 currentFile.isCombined = false;
105 oldLine = parseInt(values[1], 10);
106 newLine = parseInt(values[2], 10);
107 }
108 else if ((values = /^@@@ -(\d+)(?:,\d+)? -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@@.*/.exec(line))) {
109 currentFile.isCombined = true;
110 oldLine = parseInt(values[1], 10);
111 oldLine2 = parseInt(values[2], 10);
112 newLine = parseInt(values[3], 10);
113 }
114 else {
115 if (line.startsWith(hunkHeaderPrefix)) {
116 console.error('Failed to parse lines, starting in 0!');
117 }
118 oldLine = 0;
119 newLine = 0;
120 currentFile.isCombined = false;
121 }
122 }
123 currentBlock = {
124 lines: [],
125 oldStartLine: oldLine,
126 oldStartLine2: oldLine2,
127 newStartLine: newLine,
128 header: line,
129 };
130 }
131 function createLine(line) {
132 if (currentFile === null || currentBlock === null || oldLine === null || newLine === null)
133 return;
134 var currentLine = {
135 content: line,
136 };
137 var addedPrefixes = currentFile.isCombined ? ['+ ', ' +', '++'] : ['+'];
138 var deletedPrefixes = currentFile.isCombined ? ['- ', ' -', '--'] : ['-'];
139 if (startsWithAny(line, addedPrefixes)) {
140 currentFile.addedLines++;
141 currentLine.type = LineType.INSERT;
142 currentLine.oldNumber = undefined;
143 currentLine.newNumber = newLine++;
144 }
145 else if (startsWithAny(line, deletedPrefixes)) {
146 currentFile.deletedLines++;
147 currentLine.type = LineType.DELETE;
148 currentLine.oldNumber = oldLine++;
149 currentLine.newNumber = undefined;
150 }
151 else {
152 currentLine.type = LineType.CONTEXT;
153 currentLine.oldNumber = oldLine++;
154 currentLine.newNumber = newLine++;
155 }
156 currentBlock.lines.push(currentLine);
157 }
158 function existHunkHeader(line, lineIdx) {
159 var idx = lineIdx;
160 while (idx < diffLines.length - 3) {
161 if (line.startsWith('diff')) {
162 return false;
163 }
164 if (diffLines[idx].startsWith(oldFileNameHeader) &&
165 diffLines[idx + 1].startsWith(newFileNameHeader) &&
166 diffLines[idx + 2].startsWith(hunkHeaderPrefix)) {
167 return true;
168 }
169 idx++;
170 }
171 return false;
172 }
173 diffLines.forEach(function (line, lineIndex) {
174 if (!line || line.startsWith('*')) {
175 return;
176 }
177 var values;
178 var prevLine = diffLines[lineIndex - 1];
179 var nxtLine = diffLines[lineIndex + 1];
180 var afterNxtLine = diffLines[lineIndex + 2];
181 if (line.startsWith('diff')) {
182 startFile();
183 var gitDiffStart = /^diff --git "?(.+)"? "?(.+)"?/;
184 if ((values = gitDiffStart.exec(line))) {
185 possibleOldName = getFilename(values[1], undefined, config.dstPrefix);
186 possibleNewName = getFilename(values[2], undefined, config.srcPrefix);
187 }
188 if (currentFile === null) {
189 throw new Error('Where is my file !!!');
190 }
191 currentFile.isGitDiff = true;
192 return;
193 }
194 if (!currentFile ||
195 (!currentFile.isGitDiff &&
196 currentFile &&
197 line.startsWith(oldFileNameHeader) &&
198 nxtLine.startsWith(newFileNameHeader) &&
199 afterNxtLine.startsWith(hunkHeaderPrefix))) {
200 startFile();
201 }
202 if ((line.startsWith(oldFileNameHeader) && nxtLine.startsWith(newFileNameHeader)) ||
203 (line.startsWith(newFileNameHeader) && prevLine.startsWith(oldFileNameHeader))) {
204 if (currentFile &&
205 !currentFile.oldName &&
206 line.startsWith('--- ') &&
207 (values = getSrcFilename(line, config.srcPrefix))) {
208 currentFile.oldName = values;
209 currentFile.language = getExtension(currentFile.oldName, currentFile.language);
210 return;
211 }
212 if (currentFile &&
213 !currentFile.newName &&
214 line.startsWith('+++ ') &&
215 (values = getDstFilename(line, config.dstPrefix))) {
216 currentFile.newName = values;
217 currentFile.language = getExtension(currentFile.newName, currentFile.language);
218 return;
219 }
220 }
221 if (currentFile &&
222 (line.startsWith(hunkHeaderPrefix) ||
223 (currentFile.isGitDiff && currentFile.oldName && currentFile.newName && !currentBlock))) {
224 startBlock(line);
225 return;
226 }
227 if (currentBlock && (line.startsWith('+') || line.startsWith('-') || line.startsWith(' '))) {
228 createLine(line);
229 return;
230 }
231 var doesNotExistHunkHeader = !existHunkHeader(line, lineIndex);
232 if (currentFile === null) {
233 throw new Error('Where is my file !!!');
234 }
235 if ((values = oldMode.exec(line))) {
236 currentFile.oldMode = values[1];
237 }
238 else if ((values = newMode.exec(line))) {
239 currentFile.newMode = values[1];
240 }
241 else if ((values = deletedFileMode.exec(line))) {
242 currentFile.deletedFileMode = values[1];
243 currentFile.isDeleted = true;
244 }
245 else if ((values = newFileMode.exec(line))) {
246 currentFile.newFileMode = values[1];
247 currentFile.isNew = true;
248 }
249 else if ((values = copyFrom.exec(line))) {
250 if (doesNotExistHunkHeader) {
251 currentFile.oldName = values[1];
252 }
253 currentFile.isCopy = true;
254 }
255 else if ((values = copyTo.exec(line))) {
256 if (doesNotExistHunkHeader) {
257 currentFile.newName = values[1];
258 }
259 currentFile.isCopy = true;
260 }
261 else if ((values = renameFrom.exec(line))) {
262 if (doesNotExistHunkHeader) {
263 currentFile.oldName = values[1];
264 }
265 currentFile.isRename = true;
266 }
267 else if ((values = renameTo.exec(line))) {
268 if (doesNotExistHunkHeader) {
269 currentFile.newName = values[1];
270 }
271 currentFile.isRename = true;
272 }
273 else if ((values = binaryFiles.exec(line))) {
274 currentFile.isBinary = true;
275 currentFile.oldName = getFilename(values[1], undefined, config.srcPrefix);
276 currentFile.newName = getFilename(values[2], undefined, config.dstPrefix);
277 startBlock('Binary file');
278 }
279 else if (binaryDiff.test(line)) {
280 currentFile.isBinary = true;
281 startBlock(line);
282 }
283 else if ((values = similarityIndex.exec(line))) {
284 currentFile.unchangedPercentage = parseInt(values[1], 10);
285 }
286 else if ((values = dissimilarityIndex.exec(line))) {
287 currentFile.changedPercentage = parseInt(values[1], 10);
288 }
289 else if ((values = index.exec(line))) {
290 currentFile.checksumBefore = values[1];
291 currentFile.checksumAfter = values[2];
292 values[3] && (currentFile.mode = values[3]);
293 }
294 else if ((values = combinedIndex.exec(line))) {
295 currentFile.checksumBefore = [values[2], values[3]];
296 currentFile.checksumAfter = values[1];
297 }
298 else if ((values = combinedMode.exec(line))) {
299 currentFile.oldMode = [values[2], values[3]];
300 currentFile.newMode = values[1];
301 }
302 else if ((values = combinedNewFile.exec(line))) {
303 currentFile.newFileMode = values[1];
304 currentFile.isNew = true;
305 }
306 else if ((values = combinedDeletedFile.exec(line))) {
307 currentFile.deletedFileMode = values[1];
308 currentFile.isDeleted = true;
309 }
310 });
311 saveBlock();
312 saveFile();
313 return files;
314}
315//# sourceMappingURL=diff-parser.js.map
\No newline at end of file