UNPKG

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