168 lines
18 KiB
JavaScript
168 lines
18 KiB
JavaScript
|
|
/*istanbul ignore start*/
|
||
|
|
"use strict";
|
||
|
|
|
||
|
|
Object.defineProperty(exports, "__esModule", {
|
||
|
|
value: true
|
||
|
|
});
|
||
|
|
exports.parsePatch = parsePatch;
|
||
|
|
|
||
|
|
/*istanbul ignore end*/
|
||
|
|
function parsePatch(uniDiff) {
|
||
|
|
/*istanbul ignore start*/
|
||
|
|
var
|
||
|
|
/*istanbul ignore end*/
|
||
|
|
options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
|
|
var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/),
|
||
|
|
delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [],
|
||
|
|
list = [],
|
||
|
|
i = 0;
|
||
|
|
|
||
|
|
function parseIndex() {
|
||
|
|
var index = {};
|
||
|
|
list.push(index); // Parse diff metadata
|
||
|
|
|
||
|
|
while (i < diffstr.length) {
|
||
|
|
var line = diffstr[i]; // File header found, end parsing diff metadata
|
||
|
|
|
||
|
|
if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) {
|
||
|
|
break;
|
||
|
|
} // Diff index
|
||
|
|
|
||
|
|
|
||
|
|
var headerMatch = /^(?:Index:|diff(?: -r \w+)+)\s+/.exec(line);
|
||
|
|
|
||
|
|
if (headerMatch) {
|
||
|
|
index.index = line.substring(headerMatch[0].length).trim();
|
||
|
|
}
|
||
|
|
|
||
|
|
i++;
|
||
|
|
} // Parse file headers if they are defined. Unified diff requires them, but
|
||
|
|
// there's no technical issues to have an isolated hunk without file header
|
||
|
|
|
||
|
|
|
||
|
|
parseFileHeader(index);
|
||
|
|
parseFileHeader(index); // Parse hunks
|
||
|
|
|
||
|
|
index.hunks = [];
|
||
|
|
|
||
|
|
while (i < diffstr.length) {
|
||
|
|
var _line = diffstr[i];
|
||
|
|
|
||
|
|
if (/^(Index:|diff|\-\-\-|\+\+\+)\s/.test(_line)) {
|
||
|
|
break;
|
||
|
|
} else if (/^@@/.test(_line)) {
|
||
|
|
index.hunks.push(parseHunk());
|
||
|
|
} else if (_line && options.strict) {
|
||
|
|
// Ignore unexpected content unless in strict mode
|
||
|
|
throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line));
|
||
|
|
} else {
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} // Parses the --- and +++ headers, if none are found, no lines
|
||
|
|
// are consumed.
|
||
|
|
|
||
|
|
|
||
|
|
function parseFileHeader(index) {
|
||
|
|
var fileHeaderMatch = /^(---|\+\+\+)\s+/.exec(diffstr[i]);
|
||
|
|
|
||
|
|
if (fileHeaderMatch) {
|
||
|
|
var keyPrefix = fileHeaderMatch[1] === '---' ? 'old' : 'new';
|
||
|
|
var data = diffstr[i].substring(3).trim().split('\t', 2);
|
||
|
|
var fileName = data[0].replace(/\\\\/g, '\\');
|
||
|
|
|
||
|
|
if (fileName.startsWith('"') && fileName.endsWith('"')) {
|
||
|
|
fileName = fileName.substr(1, fileName.length - 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
index[keyPrefix + 'FileName'] = fileName;
|
||
|
|
index[keyPrefix + 'Header'] = (data[1] || '').trim();
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
} // Parses a hunk
|
||
|
|
// This assumes that we are at the start of a hunk.
|
||
|
|
|
||
|
|
|
||
|
|
function parseHunk() {
|
||
|
|
var chunkHeaderIndex = i,
|
||
|
|
chunkHeaderLine = diffstr[i++],
|
||
|
|
chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
||
|
|
var hunk = {
|
||
|
|
oldStart: +chunkHeader[1],
|
||
|
|
oldLines: typeof chunkHeader[2] === 'undefined' ? 1 : +chunkHeader[2],
|
||
|
|
newStart: +chunkHeader[3],
|
||
|
|
newLines: typeof chunkHeader[4] === 'undefined' ? 1 : +chunkHeader[4],
|
||
|
|
lines: [],
|
||
|
|
linedelimiters: []
|
||
|
|
}; // Unified Diff Format quirk: If the chunk size is 0,
|
||
|
|
// the first number is one lower than one would expect.
|
||
|
|
// https://www.artima.com/weblogs/viewpost.jsp?thread=164293
|
||
|
|
|
||
|
|
if (hunk.oldLines === 0) {
|
||
|
|
hunk.oldStart += 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (hunk.newLines === 0) {
|
||
|
|
hunk.newStart += 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
var addCount = 0,
|
||
|
|
removeCount = 0;
|
||
|
|
|
||
|
|
for (; i < diffstr.length; i++) {
|
||
|
|
// Lines starting with '---' could be mistaken for the "remove line" operation
|
||
|
|
// But they could be the header for the next file. Therefore prune such cases out.
|
||
|
|
if (diffstr[i].indexOf('--- ') === 0 && i + 2 < diffstr.length && diffstr[i + 1].indexOf('+++ ') === 0 && diffstr[i + 2].indexOf('@@') === 0) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0];
|
||
|
|
|
||
|
|
if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
|
||
|
|
hunk.lines.push(diffstr[i]);
|
||
|
|
hunk.linedelimiters.push(delimiters[i] || '\n');
|
||
|
|
|
||
|
|
if (operation === '+') {
|
||
|
|
addCount++;
|
||
|
|
} else if (operation === '-') {
|
||
|
|
removeCount++;
|
||
|
|
} else if (operation === ' ') {
|
||
|
|
addCount++;
|
||
|
|
removeCount++;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} // Handle the empty block count case
|
||
|
|
|
||
|
|
|
||
|
|
if (!addCount && hunk.newLines === 1) {
|
||
|
|
hunk.newLines = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!removeCount && hunk.oldLines === 1) {
|
||
|
|
hunk.oldLines = 0;
|
||
|
|
} // Perform optional sanity checking
|
||
|
|
|
||
|
|
|
||
|
|
if (options.strict) {
|
||
|
|
if (addCount !== hunk.newLines) {
|
||
|
|
throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (removeCount !== hunk.oldLines) {
|
||
|
|
throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return hunk;
|
||
|
|
}
|
||
|
|
|
||
|
|
while (i < diffstr.length) {
|
||
|
|
parseIndex();
|
||
|
|
}
|
||
|
|
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9wYXJzZS5qcyJdLCJuYW1lcyI6WyJwYXJzZVBhdGNoIiwidW5pRGlmZiIsIm9wdGlvbnMiLCJkaWZmc3RyIiwic3BsaXQiLCJkZWxpbWl0ZXJzIiwibWF0Y2giLCJsaXN0IiwiaSIsInBhcnNlSW5kZXgiLCJpbmRleCIsInB1c2giLCJsZW5ndGgiLCJsaW5lIiwidGVzdCIsImhlYWRlck1hdGNoIiwiZXhlYyIsInN1YnN0cmluZyIsInRyaW0iLCJwYXJzZUZpbGVIZWFkZXIiLCJodW5rcyIsInBhcnNlSHVuayIsInN0cmljdCIsIkVycm9yIiwiSlNPTiIsInN0cmluZ2lmeSIsImZpbGVIZWFkZXJNYXRjaCIsImtleVByZWZpeCIsImRhdGEiLCJmaWxlTmFtZSIsInJlcGxhY2UiLCJzdGFydHNXaXRoIiwiZW5kc1dpdGgiLCJzdWJzdHIiLCJjaHVua0hlYWRlckluZGV4IiwiY2h1bmtIZWFkZXJMaW5lIiwiY2h1bmtIZWFkZXIiLCJodW5rIiwib2xkU3RhcnQiLCJvbGRMaW5lcyIsIm5ld1N0YXJ0IiwibmV3TGluZXMiLCJsaW5lcyIsImxpbmVkZWxpbWl0ZXJzIiwiYWRkQ291bnQiLCJyZW1vdmVDb3VudCIsImluZGV4T2YiLCJvcGVyYXRpb24iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFPLFNBQVNBLFVBQVQsQ0FBb0JDLE9BQXBCLEVBQTJDO0FBQUE7QUFBQTtBQUFBO0FBQWRDLEVBQUFBLE9BQWMsdUVBQUosRUFBSTtBQUNoRCxNQUFJQyxPQUFPLEdBQUdGLE9BQU8sQ0FBQ0csS0FBUixDQUFjLHFCQUFkLENBQWQ7QUFBQSxNQUNJQyxVQUFVLEdBQUdKLE9BQU8sQ0FBQ0ssS0FBUixDQUFjLHNCQUFkLEtBQXlDLEVBRDFEO0FBQUEsTUFFSUMsSUFBSSxHQUFHLEVBRlg7QUFBQSxNQUdJQyxDQUFDLEdBQUcsQ0FIUjs7QUFLQSxXQUFTQyxVQUFULEdBQXNCO0FBQ3BCLFFBQUlDLEtBQUssR0FBRyxFQUFaO0FBQ0FILElB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
|