1 | var Block = require('./block').Block;
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | var Hunk = exports.Hunk = function(data_old, data_new, piece, context, file_length_difference) {
|
7 |
|
8 | var _flag_context = null;
|
9 | var self = this;
|
10 |
|
11 |
|
12 | this.blocks = [new Block(piece)];
|
13 | this.data_old = data_old;
|
14 | this.data_new = data_new;
|
15 |
|
16 | var before = file_length_difference, after = file_length_difference;
|
17 | after = after + this.blocks[0].diff_size;
|
18 | this.file_length_difference = after;
|
19 |
|
20 | var a1 = null, a2 = null;
|
21 | var b1 = null, b2 = null;
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | if(this.blocks[0].remove.length > 0) {
|
28 | a1 = this.blocks[0].remove[0].position;
|
29 | a2 = this.blocks[0].remove[this.blocks[0].remove.length - 1].position;
|
30 | }
|
31 |
|
32 | if(this.blocks[0].insert.length > 0) {
|
33 | b1 = this.blocks[0].insert[0].position;
|
34 | b2 = this.blocks[0].insert[this.blocks[0].insert.length - 1].position;
|
35 | }
|
36 |
|
37 | this.start_old = a1 || (b1 - before);
|
38 | this.start_new = b1 || (a1 + before);
|
39 | this.end_old = a2 || (b2 - after);
|
40 | this.end_new = b2 || (a2 + after);
|
41 |
|
42 |
|
43 |
|
44 | Object.defineProperty(this, "flag_context", { get: function() { return _flag_context; }, set: function(context) {
|
45 | if(context == null || context == 0) return null;
|
46 |
|
47 | var add_start = (context > self.start_old) ? self.start_old : context;
|
48 | var add_end = null;
|
49 |
|
50 | self.start_old = self.start_old - add_start;
|
51 | self.start_new = self.start_new - add_start;
|
52 |
|
53 | if((self.end_old + context) > self.data_old.length) {
|
54 | add_end = self.data_old.length - self.end_old;
|
55 | } else {
|
56 | add_end = context;
|
57 | }
|
58 |
|
59 | self.end_old = self.end_old + add_end;
|
60 | self.end_new = self.end_new + add_end;
|
61 | _flag_context = context;
|
62 | }, enumerable: true});
|
63 |
|
64 |
|
65 | this.flag_context = context;
|
66 | }
|
67 |
|
68 | Hunk.prototype.unshift = function(hunk) {
|
69 | this.start_old = hunk.start_old;
|
70 | this.start_new = hunk.start_new;
|
71 | this.blocks = hunk.blocks.concat(this.blocks);
|
72 | }
|
73 |
|
74 |
|
75 |
|
76 | Hunk.prototype.overlaps = function(hunk) {
|
77 | if(hunk == null) return null;
|
78 |
|
79 | var a = (this.start_old - hunk.end_old) <= 1;
|
80 | var b = (this.start_new - hunk.end_new) <= 1;
|
81 | return (a || b);
|
82 | }
|
83 |
|
84 | Hunk.prototype.diff = function(format) {
|
85 | if(format == "old") {
|
86 | return old_diff(this);
|
87 | } else if(format == 'unified') {
|
88 | return unified_diff(this);
|
89 | } else if(format == 'context') {
|
90 | return context_diff(this);
|
91 | } else if(format == 'ed') {
|
92 | return this;
|
93 | } else if(format == 'reverse_ed' || format == 'ed_finish') {
|
94 | return ed_diff(this, format);
|
95 | } else {
|
96 | throw "unknown diff format " + format;
|
97 | }
|
98 | }
|
99 |
|
100 | Hunk.prototype.each_old = function(block) {
|
101 | var entries = this.data_old.slice(this.start_old, this.end_old);
|
102 | entries.forEach(function(e) {
|
103 | block(e);
|
104 | });
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 | var old_diff = function(hunk) {
|
110 | if(hunk.blocks.length > 1) sys.puts("expecting only one block in an old diff hunk!");
|
111 |
|
112 | var opt_act = {'+':'a', '-':'d', '!':'c'};
|
113 | var block = hunk.blocks[0];
|
114 |
|
115 |
|
116 |
|
117 |
|
118 | var s = "" + context_rang("old") + opt_act[block.op] + context_rang("new") + "\n";
|
119 |
|
120 |
|
121 | if(block.remove.length > 0) {
|
122 | hunk.data_old.slice(hunk.start_old, hunk.end_old).forEach(function(e) {
|
123 | s = s + "< " + e + "\n";
|
124 | });
|
125 | }
|
126 |
|
127 | if(block.insert.length > 0) {
|
128 | hunk.data_new.slice(hunk.start_new, hunk.end_new).forEach(function(e) {
|
129 | s = s + "> " + e + "\n;"
|
130 | });
|
131 | }
|
132 |
|
133 | return s;
|
134 | }
|
135 |
|
136 | var unified_diff = function(hunk) {
|
137 |
|
138 | var s = "@@ -" + unified_range(hunk, 'old') + " +" + unified_range(hunk, 'new') + " @@\n";
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 | var lo = hunk.start_old;
|
150 | var hi = hunk.end_old;
|
151 | var num_added = 0;
|
152 | var num_removed = 0;
|
153 |
|
154 |
|
155 | var outlist = hunk.data_old.slice(lo, hi + 1).map(function(e) { return e.replace(/^/g, ' '); });
|
156 |
|
157 | hunk.blocks.forEach(function(block) {
|
158 | block.remove.forEach(function(item) {
|
159 | var op = item.action.toString();
|
160 | var offset = item.position - lo + num_added;
|
161 | outlist[offset] = outlist[offset].replace(/^ /g, op.toString());
|
162 | num_removed = num_removed + 1;
|
163 | })
|
164 |
|
165 | block.insert.forEach(function(item) {
|
166 | var op = item.action.toString();
|
167 | var offset = item.position - hunk.start_new + num_removed;
|
168 | outlist.splice(offset, 0, ("" + op + hunk.data_new[item.position]));
|
169 | num_added = num_added + 1;
|
170 | });
|
171 | });
|
172 |
|
173 |
|
174 | return s + outlist.join('\n');
|
175 | }
|
176 |
|
177 | var context_diff = function(hunk) {
|
178 | var s = '***************\n';
|
179 | s = s + '*** ' + context_range(hunk, 'old') + ' ****\n';
|
180 |
|
181 | var r = context_range(hunk, 'new');
|
182 | var outlist = null;
|
183 |
|
184 |
|
185 |
|
186 | var lo = hunk.start_old;
|
187 | var hi = hunk.end_old;
|
188 | var removes = hunk.blocks.filter(function(e) { return !(e.remove.length == 0); });
|
189 |
|
190 | if(removes) {
|
191 | outlist = hunk.data_old.slice(lo, hi).map(function(e) { return e.replace(/^/g, ' '); });
|
192 | removes.forEach(function(block) {
|
193 | block.remove.forEach(function(item) {
|
194 | outlist[item.position - lo] = outlist[item.position - lo].replace(/^ /g, block.op);
|
195 | });
|
196 | });
|
197 |
|
198 | s = s + outlist.join('\n');
|
199 | }
|
200 |
|
201 | s = s + '\n-- ' + r + ' ----\n';
|
202 | lo = hunk.start_new;
|
203 | hi = hunk.end_new;
|
204 | var inserts = hunk.blocks.filter(function(e) { return !(e.insert.length == 0); });
|
205 |
|
206 | if(inserts) {
|
207 | outlist = hunk.data_new.slice(lo, hi).map(function(e) { return e.replace(/^/g, ' '); });
|
208 | inserts.forEach(function(block) {
|
209 | block.insert.forEach(function(item) {
|
210 | outlist[item.position - lo] = outlist[item.position - lo].replace(/^ /g, block.op);
|
211 | });
|
212 | });
|
213 |
|
214 | s = s + outlist.join('\n');
|
215 | }
|
216 |
|
217 | return s;
|
218 | }
|
219 |
|
220 | var ed_diff = function(hunk, format) {
|
221 | var opt_act = {'+':'a', '-':'d', '!':'c'};
|
222 | if(hunk.blocks.length > 1) sys.puts("expecting only one block in an old diff hunk!");
|
223 | var s = null;
|
224 |
|
225 | if(format == 'reverse_ed') {
|
226 | s = "" + op_act[hunk.blocks[0].op] + context_range(hunk, 'old') + '\n';
|
227 | } else {
|
228 | s = "" + context_range(hunk, 'old').replace(/,/g, ' ') + op_act[hunk.blocks[0].op] + '\n';
|
229 | }
|
230 |
|
231 | if(hunk.blocks[0].insert.length > 0) {
|
232 | hunk.data_new.slice(hunk.start_new, hunk.end_new).forEach(function(e) {
|
233 | s = s + '' + e + '\n';
|
234 | });
|
235 |
|
236 | s = s + '.\n';
|
237 | }
|
238 |
|
239 | return s;
|
240 | }
|
241 |
|
242 |
|
243 |
|
244 | var context_range = function(hunk, mode) {
|
245 | var s = null, e = null;
|
246 |
|
247 | if(mode == 'old') {
|
248 | s = (hunk.start_old + 1);
|
249 | e = (hunk.end_old + 1);
|
250 | } else if(mode == 'new') {
|
251 | s = (hunk.start_new + 1);
|
252 | e = (hunk.end_new + 1);
|
253 | }
|
254 |
|
255 | return (s < e) ? ("" + s + "," + e) : ("" + e);
|
256 | }
|
257 |
|
258 |
|
259 |
|
260 |
|
261 | var unified_range = function(hunk, mode) {
|
262 | var s = null, e = null;
|
263 |
|
264 | if(mode == 'old') {
|
265 | s = (hunk.start_old + 1);
|
266 | e = (hunk.end_old + 1);
|
267 | } else if(mode == 'new') {
|
268 | s = (hunk.start_new + 1);
|
269 | e = (hunk.end_new + 1);
|
270 | }
|
271 |
|
272 | var length = e - s + 1;
|
273 | var first = (length < 2) ? e : s;
|
274 | return (length == 1) ? ("" + first) : (first + "," + length);
|
275 | }
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|