Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
parse.js151 linesDownload Raw Back to patch
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.parsePatch = parsePatch;
4/**
5 * Parses a patch into structured data, in the same structure returned by `structuredPatch`.
6 *
7 * @return a JSON object representation of the a patch, suitable for use with the `applyPatch` method.
8 */
9function parsePatch(uniDiff) {
10    var diffstr = uniDiff.split(/\n/), list = [];
11    var i = 0;
12    function parseIndex() {
13        var index = {};
14        list.push(index);
15        // Parse diff metadata
16        while (i < diffstr.length) {
17            var line = diffstr[i];
18            // File header found, end parsing diff metadata
19            if ((/^(---|\+\+\+|@@)\s/).test(line)) {
20                break;
21            }
22            // Try to parse the line as a diff header, like
23            //     Index: README.md
24            // or
25            //     diff -r 9117c6561b0b -r 273ce12ad8f1 .hgignore
26            // or
27            //     Index: something with multiple words
28            // and extract the filename (or whatever else is used as an index name)
29            // from the end (i.e. 'README.md', '.hgignore', or
30            // 'something with multiple words' in the examples above).
31            //
32            // TODO: It seems awkward that we indiscriminately trim off trailing
33            //       whitespace here. Theoretically, couldn't that be meaningful -
34            //       e.g. if the patch represents a diff of a file whose name ends
35            //       with a space? Seems wrong to nuke it.
36            //       But this behaviour has been around since v2.2.1 in 2015, so if
37            //       it's going to change, it should be done cautiously and in a new
38            //       major release, for backwards-compat reasons.
39            //       -- ExplodingCabbage
40            var headerMatch = (/^(?:Index:|diff(?: -r \w+)+)\s+/).exec(line);
41            if (headerMatch) {
42                index.index = line.substring(headerMatch[0].length).trim();
43            }
44            i++;
45        }
46        // Parse file headers if they are defined. Unified diff requires them, but
47        // there's no technical issues to have an isolated hunk without file header
48        parseFileHeader(index);
49        parseFileHeader(index);
50        // Parse hunks
51        index.hunks = [];
52        while (i < diffstr.length) {
53            var line = diffstr[i];
54            if ((/^(Index:\s|diff\s|---\s|\+\+\+\s|===================================================================)/).test(line)) {
55                break;
56            }
57            else if ((/^@@/).test(line)) {
58                index.hunks.push(parseHunk());
59            }
60            else if (line) {
61                throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(line));
62            }
63            else {
64                i++;
65            }
66        }
67    }
68    // Parses the --- and +++ headers, if none are found, no lines
69    // are consumed.
70    function parseFileHeader(index) {
71        var fileHeaderMatch = (/^(---|\+\+\+)\s+/).exec(diffstr[i]);
72        if (fileHeaderMatch) {
73            var prefix = fileHeaderMatch[1], data = diffstr[i].substring(3).trim().split('\t', 2), header = (data[1] || '').trim();
74            var fileName = data[0].replace(/\\\\/g, '\\');
75            if (fileName.startsWith('"') && fileName.endsWith('"')) {
76                fileName = fileName.substr(1, fileName.length - 2);
77            }
78            if (prefix === '---') {
79                index.oldFileName = fileName;
80                index.oldHeader = header;
81            }
82            else {
83                index.newFileName = fileName;
84                index.newHeader = header;
85            }
86            i++;
87        }
88    }
89    // Parses a hunk
90    // This assumes that we are at the start of a hunk.
91    function parseHunk() {
92        var _a;
93        var chunkHeaderIndex = i, chunkHeaderLine = diffstr[i++], chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
94        var hunk = {
95            oldStart: +chunkHeader[1],
96            oldLines: typeof chunkHeader[2] === 'undefined' ? 1 : +chunkHeader[2],
97            newStart: +chunkHeader[3],
98            newLines: typeof chunkHeader[4] === 'undefined' ? 1 : +chunkHeader[4],
99            lines: []
100        };
101        // Unified Diff Format quirk: If the chunk size is 0,
102        // the first number is one lower than one would expect.
103        // https://www.artima.com/weblogs/viewpost.jsp?thread=164293
104        if (hunk.oldLines === 0) {
105            hunk.oldStart += 1;
106        }
107        if (hunk.newLines === 0) {
108            hunk.newStart += 1;
109        }
110        var addCount = 0, removeCount = 0;
111        for (; i < diffstr.length && (removeCount < hunk.oldLines || addCount < hunk.newLines || ((_a = diffstr[i]) === null || _a === void 0 ? void 0 : _a.startsWith('\\'))); i++) {
112            var operation = (diffstr[i].length == 0 && i != (diffstr.length - 1)) ? ' ' : diffstr[i][0];
113            if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
114                hunk.lines.push(diffstr[i]);
115                if (operation === '+') {
116                    addCount++;
117                }
118                else if (operation === '-') {
119                    removeCount++;
120                }
121                else if (operation === ' ') {
122                    addCount++;
123                    removeCount++;
124                }
125            }
126            else {
127                throw new Error("Hunk at line ".concat(chunkHeaderIndex + 1, " contained invalid line ").concat(diffstr[i]));
128            }
129        }
130        // Handle the empty block count case
131        if (!addCount && hunk.newLines === 1) {
132            hunk.newLines = 0;
133        }
134        if (!removeCount && hunk.oldLines === 1) {
135            hunk.oldLines = 0;
136        }
137        // Perform sanity checking
138        if (addCount !== hunk.newLines) {
139            throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
140        }
141        if (removeCount !== hunk.oldLines) {
142            throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
143        }
144        return hunk;
145    }
146    while (i < diffstr.length) {
147        parseIndex();
148    }
149    return list;
150}
151 
codekingpro/portable-devtools · Team Ai