Show More
@@ -532,6 +532,33 b' def _imerge3(repo, mynode, orig, fcd, fc' | |||
|
532 | 532 | return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels) |
|
533 | 533 | |
|
534 | 534 | |
|
535 | @internaltool( | |
|
536 | b'mergediff', | |
|
537 | fullmerge, | |
|
538 | _( | |
|
539 | b"warning: conflicts while merging %s! " | |
|
540 | b"(edit, then use 'hg resolve --mark')\n" | |
|
541 | ), | |
|
542 | precheck=_mergecheck, | |
|
543 | ) | |
|
544 | def _imerge_diff( | |
|
545 | repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None | |
|
546 | ): | |
|
547 | """ | |
|
548 | Uses the internal non-interactive simple merge algorithm for merging | |
|
549 | files. It will fail if there are any conflicts and leave markers in | |
|
550 | the partially merged file. The marker will have two sections, one with the | |
|
551 | content from one side of the merge, and one with a diff from the base | |
|
552 | content to the content on the other side. (experimental)""" | |
|
553 | if not labels: | |
|
554 | labels = _defaultconflictlabels | |
|
555 | if len(labels) < 3: | |
|
556 | labels.append(b'base') | |
|
557 | return _merge( | |
|
558 | repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, b'mergediff' | |
|
559 | ) | |
|
560 | ||
|
561 | ||
|
535 | 562 | def _imergeauto( |
|
536 | 563 | repo, |
|
537 | 564 | mynode, |
@@ -455,6 +455,68 b' def is_not_null(ctx):' | |||
|
455 | 455 | return ctx.node() != nodemod.nullid |
|
456 | 456 | |
|
457 | 457 | |
|
458 | def _mergediff(m3, name_a, name_b, name_base): | |
|
459 | lines = [] | |
|
460 | conflicts = False | |
|
461 | for group in m3.merge_groups(): | |
|
462 | if group[0] == b'conflict': | |
|
463 | base_lines, a_lines, b_lines = group[1:] | |
|
464 | base_text = b''.join(base_lines) | |
|
465 | b_blocks = list( | |
|
466 | mdiff.allblocks( | |
|
467 | base_text, | |
|
468 | b''.join(b_lines), | |
|
469 | lines1=base_lines, | |
|
470 | lines2=b_lines, | |
|
471 | ) | |
|
472 | ) | |
|
473 | a_blocks = list( | |
|
474 | mdiff.allblocks( | |
|
475 | base_text, | |
|
476 | b''.join(a_lines), | |
|
477 | lines1=base_lines, | |
|
478 | lines2=b_lines, | |
|
479 | ) | |
|
480 | ) | |
|
481 | ||
|
482 | def matching_lines(blocks): | |
|
483 | return sum( | |
|
484 | block[1] - block[0] | |
|
485 | for block, kind in blocks | |
|
486 | if kind == b'=' | |
|
487 | ) | |
|
488 | ||
|
489 | def diff_lines(blocks, lines1, lines2): | |
|
490 | for block, kind in blocks: | |
|
491 | if kind == b'=': | |
|
492 | for line in lines1[block[0] : block[1]]: | |
|
493 | yield b' ' + line | |
|
494 | else: | |
|
495 | for line in lines1[block[0] : block[1]]: | |
|
496 | yield b'-' + line | |
|
497 | for line in lines2[block[2] : block[3]]: | |
|
498 | yield b'+' + line | |
|
499 | ||
|
500 | lines.append(b"<<<<<<<\n") | |
|
501 | if matching_lines(a_blocks) < matching_lines(b_blocks): | |
|
502 | lines.append(b"======= %s\n" % name_a) | |
|
503 | lines.extend(a_lines) | |
|
504 | lines.append(b"------- %s\n" % name_base) | |
|
505 | lines.append(b"+++++++ %s\n" % name_b) | |
|
506 | lines.extend(diff_lines(b_blocks, base_lines, b_lines)) | |
|
507 | else: | |
|
508 | lines.append(b"------- %s\n" % name_base) | |
|
509 | lines.append(b"+++++++ %s\n" % name_a) | |
|
510 | lines.extend(diff_lines(a_blocks, base_lines, a_lines)) | |
|
511 | lines.append(b"======= %s\n" % name_b) | |
|
512 | lines.extend(b_lines) | |
|
513 | lines.append(b">>>>>>>\n") | |
|
514 | conflicts = True | |
|
515 | else: | |
|
516 | lines.extend(group[1]) | |
|
517 | return lines, conflicts | |
|
518 | ||
|
519 | ||
|
458 | 520 | def simplemerge(ui, localctx, basectx, otherctx, **opts): |
|
459 | 521 | """Performs the simplemerge algorithm. |
|
460 | 522 | |
@@ -499,9 +561,15 b' def simplemerge(ui, localctx, basectx, o' | |||
|
499 | 561 | extrakwargs[b'name_base'] = name_base |
|
500 | 562 | extrakwargs[b'minimize'] = False |
|
501 | 563 | |
|
502 | lines = m3.merge_lines( | |
|
503 | name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs) | |
|
504 | ) | |
|
564 | if mode == b'mergediff': | |
|
565 | lines, conflicts = _mergediff(m3, name_a, name_b, name_base) | |
|
566 | else: | |
|
567 | lines = list( | |
|
568 | m3.merge_lines( | |
|
569 | name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs) | |
|
570 | ) | |
|
571 | ) | |
|
572 | conflicts = m3.conflicts | |
|
505 | 573 | |
|
506 | 574 | # merge flags if necessary |
|
507 | 575 | flags = localctx.flags() |
@@ -519,5 +587,5 b' def simplemerge(ui, localctx, basectx, o' | |||
|
519 | 587 | else: |
|
520 | 588 | localctx.write(mergedtext, flags) |
|
521 | 589 | |
|
522 |
if |
|
|
590 | if conflicts and not mode == b'union': | |
|
523 | 591 | return 1 |
@@ -27,6 +27,13 b'' | |||
|
27 | 27 | * The memory footprint per changeset during pull/unbundle |
|
28 | 28 | operations has been further reduced. |
|
29 | 29 | |
|
30 | * There is a new internal merge tool called `internal:mergediff` (can | |
|
31 | be set as the value for the `merge` config in the `[ui]` | |
|
32 | section). It resolves merges the same was as `internal:merge` and | |
|
33 | `internal:merge3`, but it shows conflicts differently. Instead of | |
|
34 | showing 2 or 3 snapshots of the conflicting pieces of code, it | |
|
35 | shows one snapshot and a diff. This may be useful when at least one | |
|
36 | side of the conflict is similar to the base. | |
|
30 | 37 | |
|
31 | 38 | == New Experimental Features == |
|
32 | 39 |
@@ -282,6 +282,80 b' internal:merge3' | |||
|
282 | 282 | >>>>>>> merge rev |
|
283 | 283 | Hop we are done. |
|
284 | 284 | |
|
285 | internal:mergediff | |
|
286 | ||
|
287 | $ hg co -C 1 | |
|
288 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
289 | $ cat << EOF > a | |
|
290 | > Small Mathematical Series. | |
|
291 | > 1 | |
|
292 | > 2 | |
|
293 | > 3 | |
|
294 | > 4 | |
|
295 | > 4.5 | |
|
296 | > 5 | |
|
297 | > Hop we are done. | |
|
298 | > EOF | |
|
299 | $ hg co -m 2 -t internal:mergediff | |
|
300 | merging a | |
|
301 | warning: conflicts while merging a! (edit, then use 'hg resolve --mark') | |
|
302 | 0 files updated, 0 files merged, 0 files removed, 1 files unresolved | |
|
303 | use 'hg resolve' to retry unresolved file merges | |
|
304 | [1] | |
|
305 | $ cat a | |
|
306 | Small Mathematical Series. | |
|
307 | 1 | |
|
308 | 2 | |
|
309 | 3 | |
|
310 | <<<<<<< | |
|
311 | ------- base | |
|
312 | +++++++ working copy | |
|
313 | 4 | |
|
314 | +4.5 | |
|
315 | 5 | |
|
316 | ======= destination | |
|
317 | 6 | |
|
318 | 8 | |
|
319 | >>>>>>> | |
|
320 | Hop we are done. | |
|
321 | Test the same thing as above but modify a bit more so we instead get the working | |
|
322 | copy in full and the diff from base to destination. | |
|
323 | $ hg co -C 1 | |
|
324 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
325 | $ cat << EOF > a | |
|
326 | > Small Mathematical Series. | |
|
327 | > 1 | |
|
328 | > 2 | |
|
329 | > 3.5 | |
|
330 | > 4.5 | |
|
331 | > 5.5 | |
|
332 | > Hop we are done. | |
|
333 | > EOF | |
|
334 | $ hg co -m 2 -t internal:mergediff | |
|
335 | merging a | |
|
336 | warning: conflicts while merging a! (edit, then use 'hg resolve --mark') | |
|
337 | 0 files updated, 0 files merged, 0 files removed, 1 files unresolved | |
|
338 | use 'hg resolve' to retry unresolved file merges | |
|
339 | [1] | |
|
340 | $ cat a | |
|
341 | Small Mathematical Series. | |
|
342 | 1 | |
|
343 | 2 | |
|
344 | <<<<<<< | |
|
345 | ======= working copy | |
|
346 | 3.5 | |
|
347 | 4.5 | |
|
348 | 5.5 | |
|
349 | ------- base | |
|
350 | +++++++ destination | |
|
351 | 3 | |
|
352 | -4 | |
|
353 | -5 | |
|
354 | +6 | |
|
355 | +8 | |
|
356 | >>>>>>> | |
|
357 | Hop we are done. | |
|
358 | ||
|
285 | 359 | Add some unconflicting changes on each head, to make sure we really |
|
286 | 360 | are merging, unlike :local and :other |
|
287 | 361 |
@@ -2057,6 +2057,13 b' Test dynamic list of merge tools only sh' | |||
|
2057 | 2057 | partially merged file. Marker will have three sections, one from each |
|
2058 | 2058 | side of the merge and one for the base content. |
|
2059 | 2059 | |
|
2060 | ":mergediff" | |
|
2061 | Uses the internal non-interactive simple merge algorithm for merging | |
|
2062 | files. It will fail if there are any conflicts and leave markers in the | |
|
2063 | partially merged file. The marker will have two sections, one with the | |
|
2064 | content from one side of the merge, and one with a diff from the base | |
|
2065 | content to the content on the other side. (experimental) | |
|
2066 | ||
|
2060 | 2067 | ":other" |
|
2061 | 2068 | Uses the other 'p2()' version of files as the merged version. |
|
2062 | 2069 |
General Comments 0
You need to be logged in to leave comments.
Login now