UNPKG

4.73 kBJavaScriptView Raw
1var defaultToWhiteSpace, escapeRegExp, ltrim, makeString, parseFile, parseFileFallback, trimLeft;
2
3module.exports = function(input) {
4 var add, chunk, current, del, deleted_file, eof, file, files, from_file, index, j, len, line, lines, ln_add, ln_del, new_file, normal, parse, restart, schema, start, to_file;
5 if (!input) {
6 return [];
7 }
8 if (input.match(/^\s+$/)) {
9 return [];
10 }
11 lines = input.split('\n');
12 if (lines.length === 0) {
13 return [];
14 }
15 files = [];
16 file = null;
17 ln_del = 0;
18 ln_add = 0;
19 current = null;
20 start = function(line) {
21 var fileNames;
22 file = {
23 chunks: [],
24 deletions: 0,
25 additions: 0
26 };
27 files.push(file);
28 if (!file.to && !file.from) {
29 fileNames = parseFile(line);
30 if (fileNames) {
31 file.from = fileNames[0];
32 return file.to = fileNames[1];
33 }
34 }
35 };
36 restart = function() {
37 if (!file || file.chunks.length) {
38 return start();
39 }
40 };
41 new_file = function() {
42 restart();
43 file["new"] = true;
44 return file.from = '/dev/null';
45 };
46 deleted_file = function() {
47 restart();
48 file.deleted = true;
49 return file.to = '/dev/null';
50 };
51 index = function(line) {
52 restart();
53 return file.index = line.split(' ').slice(1);
54 };
55 from_file = function(line) {
56 restart();
57 return file.from = parseFileFallback(line);
58 };
59 to_file = function(line) {
60 restart();
61 return file.to = parseFileFallback(line);
62 };
63 chunk = function(line, match) {
64 var newLines, newStart, oldLines, oldStart;
65 ln_del = oldStart = +match[1];
66 oldLines = +(match[2] || 0);
67 ln_add = newStart = +match[3];
68 newLines = +(match[4] || 0);
69 current = {
70 content: line,
71 changes: [],
72 oldStart: oldStart,
73 oldLines: oldLines,
74 newStart: newStart,
75 newLines: newLines
76 };
77 return file.chunks.push(current);
78 };
79 del = function(line) {
80 current.changes.push({
81 type: 'del',
82 del: true,
83 ln: ln_del++,
84 content: line
85 });
86 return file.deletions++;
87 };
88 add = function(line) {
89 current.changes.push({
90 type: 'add',
91 add: true,
92 ln: ln_add++,
93 content: line
94 });
95 return file.additions++;
96 };
97 normal = function(line) {
98 return current.changes.push({
99 type: 'normal',
100 normal: true,
101 ln1: ln_del++,
102 ln2: ln_add++,
103 content: line
104 });
105 };
106 eof = function(line) {
107 var obj, recentChange, ref;
108 ref = current.changes, recentChange = ref[ref.length - 1];
109 return current.changes.push((
110 obj = {
111 type: recentChange.type
112 },
113 obj["" + recentChange.type] = true,
114 obj.ln1 = recentChange.ln1,
115 obj.ln2 = recentChange.ln2,
116 obj.ln = recentChange.ln,
117 obj.content = line,
118 obj
119 ));
120 };
121 schema = [[/^\s+/, normal], [/^diff\s/, start], [/^new file mode \d+$/, new_file], [/^deleted file mode \d+$/, deleted_file], [/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/, index], [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk], [/^-/, del], [/^\+/, add], [/^\\ No newline at end of file$/, eof]];
122 parse = function(line) {
123 var j, len, m, p;
124 for (j = 0, len = schema.length; j < len; j++) {
125 p = schema[j];
126 m = line.match(p[0]);
127 if (m) {
128 p[1](line, m);
129 return true;
130 }
131 }
132 return false;
133 };
134 for (j = 0, len = lines.length; j < len; j++) {
135 line = lines[j];
136 parse(line);
137 }
138 return files;
139};
140
141parseFile = function(s) {
142 var fileNames;
143 if (!s) {
144 return;
145 }
146 fileNames = s.split(' ').slice(-2);
147 fileNames.map(function(fileName, i) {
148 return fileNames[i] = fileName.replace(/^(a|b)\//, '');
149 });
150 return fileNames;
151};
152
153parseFileFallback = function(s) {
154 var t;
155 s = ltrim(s, '-');
156 s = ltrim(s, '+');
157 s = s.trim();
158 t = /\t.*|\d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d(.\d+)?\s(\+|-)\d\d\d\d/.exec(s);
159 if (t) {
160 s = s.substring(0, t.index).trim();
161 }
162 if (s.match(/^(a|b)\//)) {
163 return s.substr(2);
164 } else {
165 return s;
166 }
167};
168
169ltrim = function(s, chars) {
170 s = makeString(s);
171 if (!chars && trimLeft) {
172 return trimLeft.call(s);
173 }
174 chars = defaultToWhiteSpace(chars);
175 return s.replace(new RegExp('^' + chars + '+'), '');
176};
177
178makeString = function(s) {
179 if (s === null) {
180 return '';
181 } else {
182 return s + '';
183 }
184};
185
186trimLeft = String.prototype.trimLeft;
187
188defaultToWhiteSpace = function(chars) {
189 if (chars === null) {
190 return '\\s';
191 }
192 if (chars.source) {
193 return chars.source;
194 }
195 return '[' + escapeRegExp(chars) + ']';
196};
197
198escapeRegExp = function(s) {
199 return makeString(s).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
200};