Lines 10-15
Link Here
|
10 |
*******************************************************************************/ |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.compare.internal.patch; |
11 |
package org.eclipse.compare.internal.patch; |
12 |
|
12 |
|
|
|
13 |
import java.util.ArrayList; |
13 |
import java.util.List; |
14 |
import java.util.List; |
14 |
|
15 |
|
15 |
import org.eclipse.compare.patch.PatchConfiguration; |
16 |
import org.eclipse.compare.patch.PatchConfiguration; |
Lines 167-216
Link Here
|
167 |
* The parameter shift is added to the line numbers given |
168 |
* The parameter shift is added to the line numbers given |
168 |
* in the hunk. |
169 |
* in the hunk. |
169 |
*/ |
170 |
*/ |
170 |
public boolean tryPatch(PatchConfiguration configuration, List lines, int shift) { |
171 |
public boolean tryPatch(PatchConfiguration configuration, List lines, int shift, int fuzz) { |
171 |
boolean reverse = configuration.isReversed(); |
172 |
boolean reverse = configuration.isReversed(); |
172 |
int pos= getStart(reverse) + shift; |
173 |
int pos = getStart(reverse) + shift; |
173 |
int deleteMatches= 0; |
174 |
int deleteMatches = 0; |
|
|
175 |
List contextLines = new ArrayList(); |
176 |
boolean contextLinesMatched = true; |
174 |
for (int i= 0; i < fLines.length; i++) { |
177 |
for (int i= 0; i < fLines.length; i++) { |
175 |
String s= fLines[i]; |
178 |
String s = fLines[i]; |
176 |
Assert.isTrue(s.length() > 0); |
179 |
Assert.isTrue(s.length() > 0); |
177 |
String line= s.substring(1); |
180 |
String line = s.substring(1); |
178 |
char controlChar= s.charAt(0); |
181 |
char controlChar = s.charAt(0); |
|
|
182 |
|
179 |
if (controlChar == ' ') { // context lines |
183 |
if (controlChar == ' ') { // context lines |
180 |
while (true) { |
184 |
|
181 |
if (pos < 0 || pos >= lines.size()) |
185 |
if (pos < 0 || pos >= lines.size()) // out of the file |
182 |
return false; |
|
|
183 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
184 |
pos++; |
185 |
break; |
186 |
} |
187 |
return false; |
186 |
return false; |
188 |
} |
187 |
contextLines.add(line); |
|
|
188 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
189 |
pos++; |
190 |
continue; |
191 |
} else if (fuzz > 0) { |
192 |
// doesn't match, use the fuzz factor |
193 |
contextLinesMatched = false; |
194 |
pos++; |
195 |
continue; |
196 |
} |
197 |
return false; |
189 |
} else if (isDeletedDelimeter(controlChar, reverse)) { |
198 |
} else if (isDeletedDelimeter(controlChar, reverse)) { |
190 |
// deleted lines |
199 |
// deleted lines |
191 |
while (true) { |
200 |
|
192 |
if (pos < 0 || pos >= lines.size()) |
201 |
// use the fuzz factor if needed |
193 |
return false; |
202 |
// TODO (tzarna): extract method |
194 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
203 |
if (!contextLinesMatched && fuzz > 0 && contextLines.size() > fuzz) { |
195 |
deleteMatches++; |
204 |
// three lines of context is typically the default |
196 |
pos++; |
205 |
if (contextLines.size() > 3) { |
197 |
break; |
206 |
// two "groups" of context lines -- both preceding and following |
|
|
207 |
if (contextLines.size() % 2 == 0) { |
208 |
// if the number of context lines is even treat the |
209 |
// first half part as following and the second one |
210 |
// as preceding... |
211 |
List followingContextLines = new ArrayList(contextLines.subList(0, contextLines.size() / 2 - 1)); |
212 |
if (!checkFollowingContextLines(configuration, lines, fuzz, pos, followingContextLines)) |
213 |
return false; |
214 |
List precedingContextLines = new ArrayList(contextLines.subList(contextLines.size() / 2 - 1, contextLines.size())); |
215 |
if (!checkPrecedingContextLines(configuration, lines, fuzz, pos, precedingContextLines)) |
216 |
return false; |
217 |
} else { |
218 |
// ... otherwise, if the number is odd give them two |
219 |
// tries (e.g. for 5 context lines try both 2+3 and |
220 |
// 3+2) |
221 |
List followingContextLines = new ArrayList(contextLines.subList(0, contextLines.size() / 2)); |
222 |
List precedingContextLines = new ArrayList(contextLines.subList(contextLines.size() / 2, contextLines.size())); |
223 |
if (checkPrecedingContextLines(configuration, lines, fuzz, pos, precedingContextLines) |
224 |
&& checkFollowingContextLines(configuration, lines, fuzz, pos - contextLines.size() / 2 - 1, followingContextLines)) { |
225 |
// to omit the check of following of the context lines at the end of this method |
226 |
contextLinesMatched = true; |
227 |
break; |
228 |
} |
229 |
// else give it another try |
230 |
precedingContextLines = new ArrayList(contextLines.subList(0, contextLines.size() / 2 + 1)); |
231 |
if (!checkPrecedingContextLines(configuration, lines, fuzz, pos, precedingContextLines)) |
232 |
return false; |
233 |
followingContextLines = new ArrayList(contextLines.subList(contextLines.size() / 2 + 1, contextLines.size())); |
234 |
if (!checkFollowingContextLines(configuration, lines, fuzz, pos, followingContextLines)) |
235 |
return false; |
236 |
} |
237 |
} else { |
238 |
//ignore from the beginning |
239 |
if (!checkPrecedingContextLines(configuration, lines, |
240 |
fuzz, pos, contextLines)) return false; |
198 |
} |
241 |
} |
199 |
|
242 |
} |
200 |
// We must remove all lines at once, return false if this |
243 |
// else if there is less or equal context line to the fuzz |
201 |
// fails. In other words, all lines considered for deletion |
244 |
// factor we ignore them all and treat as matching |
202 |
// must be found one by one. |
245 |
|
203 |
|
246 |
contextLines.clear(); |
204 |
// if (deleteMatches <= 0) |
247 |
|
205 |
return false; |
248 |
if (pos < 0 || pos >= lines.size()) // out of the file |
206 |
// pos++; |
249 |
return false; |
|
|
250 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
251 |
deleteMatches++; |
252 |
pos++; |
253 |
continue; // line matched, continue with the next one |
207 |
} |
254 |
} |
|
|
255 |
|
256 |
// We must remove all lines at once, return false if this |
257 |
// fails. In other words, all lines considered for deletion |
258 |
// must be found one by one. |
259 |
|
260 |
// if (deleteMatches <= 0) |
261 |
return false; |
262 |
// pos++; |
208 |
} else if (isAddedDelimeter(controlChar, reverse)) { |
263 |
} else if (isAddedDelimeter(controlChar, reverse)) { |
209 |
// added lines |
264 |
// added lines |
210 |
// we don't have to do anything for a 'try' |
265 |
// we don't have to do anything for a 'try' |
|
|
266 |
contextLines.clear(); |
211 |
} else |
267 |
} else |
212 |
Assert.isTrue(false, "tryPatch: unknown control character: " + controlChar); //$NON-NLS-1$ |
268 |
Assert.isTrue(false, "tryPatch: unknown control character: " + controlChar); //$NON-NLS-1$ |
213 |
} |
269 |
} |
|
|
270 |
if (!contextLinesMatched && fuzz > 0 && contextLines.size() > fuzz) |
271 |
if (!checkFollowingContextLines(configuration, lines, fuzz, pos, |
272 |
contextLines)) |
273 |
return false; |
274 |
return true; |
275 |
} |
276 |
|
277 |
private boolean checkPrecedingContextLines( |
278 |
PatchConfiguration configuration, List lines, int fuzz, int pos, |
279 |
List contextLines) { |
280 |
// ignore from the beginning |
281 |
for (int j = fuzz; j < contextLines.size(); j++) { |
282 |
if (!linesMatch(configuration, (String) contextLines.get(j), |
283 |
(String) lines.get(pos - contextLines.size() + j))) |
284 |
return false; |
285 |
} |
286 |
return true; |
287 |
} |
288 |
|
289 |
private boolean checkFollowingContextLines( |
290 |
PatchConfiguration configuration, List lines, int fuzz, int pos, |
291 |
List contextLines) { |
292 |
if (!contextLines.isEmpty()) { |
293 |
// ignore from the end |
294 |
for (int j = 0; j < contextLines.size() - fuzz; j++) { |
295 |
if (!linesMatch(configuration, (String) contextLines.get(j), |
296 |
(String) lines.get(pos - contextLines.size() + j))) |
297 |
return false; |
298 |
} |
299 |
} |
214 |
return true; |
300 |
return true; |
215 |
} |
301 |
} |
216 |
|
302 |
|
Lines 243-257
Link Here
|
243 |
Assert.isTrue(s.length() > 0); |
329 |
Assert.isTrue(s.length() > 0); |
244 |
String line= s.substring(1); |
330 |
String line= s.substring(1); |
245 |
char controlChar= s.charAt(0); |
331 |
char controlChar= s.charAt(0); |
|
|
332 |
// TODO (tzarna): don't process context lines as they are already |
333 |
// checked by the tryPatch method (with fuzz factor) or add the fuzz |
334 |
// factor processing here too |
246 |
if (controlChar == ' ') { // context lines |
335 |
if (controlChar == ' ') { // context lines |
247 |
while (true) { |
|
|
248 |
Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$ |
336 |
Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$ |
249 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
337 |
// if (linesMatch(configuration, line, (String) lines.get(pos))) { |
250 |
pos++; |
338 |
// pos++; |
251 |
break; |
339 |
// break; |
252 |
} |
340 |
// }else if (fuzz > 0) { |
|
|
341 |
// // doesn't match, use the fuzz factor |
342 |
// fuzz--; |
343 |
// pos++; |
344 |
// break; |
345 |
// } |
253 |
pos++; |
346 |
pos++; |
254 |
} |
347 |
// } |
255 |
} else if (isDeletedDelimeter(controlChar, reverse)) { |
348 |
} else if (isDeletedDelimeter(controlChar, reverse)) { |
256 |
// deleted lines |
349 |
// deleted lines |
257 |
while (true) { |
350 |
while (true) { |
Lines 259-264
Link Here
|
259 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
352 |
if (linesMatch(configuration, line, (String) lines.get(pos))) { |
260 |
break; |
353 |
break; |
261 |
} |
354 |
} |
|
|
355 |
// TODO (tzarna): does it ever happen? |
262 |
pos++; |
356 |
pos++; |
263 |
} |
357 |
} |
264 |
lines.remove(pos); |
358 |
lines.remove(pos); |