Mercurial > public > mercurial-scm > hg
comparison mercurial/filemerge.py @ 48586:fd9fe2658cda
filemerge: pass `simplemerge.MergeInput` to tool functions
Differential Revision: https://phab.mercurial-scm.org/D12018
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Thu, 20 Jan 2022 16:16:05 -0800 |
parents | 07069fcd9a6e |
children | 3c8cc987672e |
comparison
equal
deleted
inserted
replaced
48585:07069fcd9a6e | 48586:fd9fe2658cda |
---|---|
304 if newdata != data: | 304 if newdata != data: |
305 util.writefile(file, newdata) | 305 util.writefile(file, newdata) |
306 | 306 |
307 | 307 |
308 @internaltool(b'prompt', nomerge) | 308 @internaltool(b'prompt', nomerge) |
309 def _iprompt(repo, mynode, fcd, fco, fca, toolconf, labels=None): | 309 def _iprompt(repo, mynode, local, other, base, toolconf): |
310 """Asks the user which of the local `p1()` or the other `p2()` version to | 310 """Asks the user which of the local `p1()` or the other `p2()` version to |
311 keep as the merged version.""" | 311 keep as the merged version.""" |
312 ui = repo.ui | 312 ui = repo.ui |
313 fd = fcd.path() | 313 fd = local.fctx.path() |
314 uipathfn = scmutil.getuipathfn(repo) | 314 uipathfn = scmutil.getuipathfn(repo) |
315 | 315 |
316 # Avoid prompting during an in-memory merge since it doesn't support merge | 316 # Avoid prompting during an in-memory merge since it doesn't support merge |
317 # conflicts. | 317 # conflicts. |
318 if fcd.changectx().isinmemory(): | 318 if local.fctx.changectx().isinmemory(): |
319 raise error.InMemoryMergeConflictsError( | 319 raise error.InMemoryMergeConflictsError( |
320 b'in-memory merge does not support file conflicts' | 320 b'in-memory merge does not support file conflicts' |
321 ) | 321 ) |
322 | 322 |
323 prompts = partextras(labels) | 323 prompts = partextras([local.label, other.label]) |
324 prompts[b'fd'] = uipathfn(fd) | 324 prompts[b'fd'] = uipathfn(fd) |
325 try: | 325 try: |
326 if fco.isabsent(): | 326 if other.fctx.isabsent(): |
327 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2) | 327 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2) |
328 choice = [b'local', b'other', b'unresolved'][index] | 328 choice = [b'local', b'other', b'unresolved'][index] |
329 elif fcd.isabsent(): | 329 elif local.fctx.isabsent(): |
330 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2) | 330 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2) |
331 choice = [b'other', b'local', b'unresolved'][index] | 331 choice = [b'other', b'local', b'unresolved'][index] |
332 else: | 332 else: |
333 # IMPORTANT: keep the last line of this prompt ("What do you want to | 333 # IMPORTANT: keep the last line of this prompt ("What do you want to |
334 # do?") very short, see comment next to _localchangedotherdeletedmsg | 334 # do?") very short, see comment next to _localchangedotherdeletedmsg |
345 2, | 345 2, |
346 ) | 346 ) |
347 choice = [b'local', b'other', b'unresolved'][index] | 347 choice = [b'local', b'other', b'unresolved'][index] |
348 | 348 |
349 if choice == b'other': | 349 if choice == b'other': |
350 return _iother(repo, mynode, fcd, fco, fca, toolconf, labels) | 350 return _iother(repo, mynode, local, other, base, toolconf) |
351 elif choice == b'local': | 351 elif choice == b'local': |
352 return _ilocal(repo, mynode, fcd, fco, fca, toolconf, labels) | 352 return _ilocal(repo, mynode, local, other, base, toolconf) |
353 elif choice == b'unresolved': | 353 elif choice == b'unresolved': |
354 return _ifail(repo, mynode, fcd, fco, fca, toolconf, labels) | 354 return _ifail(repo, mynode, local, other, base, toolconf) |
355 except error.ResponseExpected: | 355 except error.ResponseExpected: |
356 ui.write(b"\n") | 356 ui.write(b"\n") |
357 return _ifail(repo, mynode, fcd, fco, fca, toolconf, labels) | 357 return _ifail(repo, mynode, local, other, base, toolconf) |
358 | 358 |
359 | 359 |
360 @internaltool(b'local', nomerge) | 360 @internaltool(b'local', nomerge) |
361 def _ilocal(repo, mynode, fcd, fco, fca, toolconf, labels=None): | 361 def _ilocal(repo, mynode, local, other, base, toolconf): |
362 """Uses the local `p1()` version of files as the merged version.""" | 362 """Uses the local `p1()` version of files as the merged version.""" |
363 return 0, fcd.isabsent() | 363 return 0, local.fctx.isabsent() |
364 | 364 |
365 | 365 |
366 @internaltool(b'other', nomerge) | 366 @internaltool(b'other', nomerge) |
367 def _iother(repo, mynode, fcd, fco, fca, toolconf, labels=None): | 367 def _iother(repo, mynode, local, other, base, toolconf): |
368 """Uses the other `p2()` version of files as the merged version.""" | 368 """Uses the other `p2()` version of files as the merged version.""" |
369 if fco.isabsent(): | 369 if other.fctx.isabsent(): |
370 # local changed, remote deleted -- 'deleted' picked | 370 # local changed, remote deleted -- 'deleted' picked |
371 _underlyingfctxifabsent(fcd).remove() | 371 _underlyingfctxifabsent(local.fctx).remove() |
372 deleted = True | 372 deleted = True |
373 else: | 373 else: |
374 _underlyingfctxifabsent(fcd).write(fco.data(), fco.flags()) | 374 _underlyingfctxifabsent(local.fctx).write( |
375 other.fctx.data(), other.fctx.flags() | |
376 ) | |
375 deleted = False | 377 deleted = False |
376 return 0, deleted | 378 return 0, deleted |
377 | 379 |
378 | 380 |
379 @internaltool(b'fail', nomerge) | 381 @internaltool(b'fail', nomerge) |
380 def _ifail(repo, mynode, fcd, fco, fca, toolconf, labels=None): | 382 def _ifail(repo, mynode, local, other, base, toolconf): |
381 """ | 383 """ |
382 Rather than attempting to merge files that were modified on both | 384 Rather than attempting to merge files that were modified on both |
383 branches, it marks them as unresolved. The resolve command must be | 385 branches, it marks them as unresolved. The resolve command must be |
384 used to resolve these conflicts.""" | 386 used to resolve these conflicts.""" |
385 # for change/delete conflicts write out the changed version, then fail | 387 # for change/delete conflicts write out the changed version, then fail |
386 if fcd.isabsent(): | 388 if local.fctx.isabsent(): |
387 _underlyingfctxifabsent(fcd).write(fco.data(), fco.flags()) | 389 _underlyingfctxifabsent(local.fctx).write( |
390 other.fctx.data(), other.fctx.flags() | |
391 ) | |
388 return 1, False | 392 return 1, False |
389 | 393 |
390 | 394 |
391 def _underlyingfctxifabsent(filectx): | 395 def _underlyingfctxifabsent(filectx): |
392 """Sometimes when resolving, our fcd is actually an absentfilectx, but | 396 """Sometimes when resolving, our fcd is actually an absentfilectx, but |
397 return filectx.changectx()[filectx.path()] | 401 return filectx.changectx()[filectx.path()] |
398 else: | 402 else: |
399 return filectx | 403 return filectx |
400 | 404 |
401 | 405 |
402 def _premerge(repo, fcd, fco, fca, toolconf, backup, labels): | 406 def _premerge(repo, local, other, base, toolconf, backup): |
403 tool, toolpath, binary, symlink, scriptfn = toolconf | 407 tool, toolpath, binary, symlink, scriptfn = toolconf |
404 if symlink or fcd.isabsent() or fco.isabsent(): | 408 if symlink or local.fctx.isabsent() or other.fctx.isabsent(): |
405 return 1 | 409 return 1 |
406 | 410 |
407 ui = repo.ui | 411 ui = repo.ui |
408 | 412 |
409 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff'] | 413 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff'] |
424 mode = b'merge' | 428 mode = b'merge' |
425 if premerge == b'keep-mergediff': | 429 if premerge == b'keep-mergediff': |
426 mode = b'mergediff' | 430 mode = b'mergediff' |
427 elif premerge == b'keep-merge3': | 431 elif premerge == b'keep-merge3': |
428 mode = b'merge3' | 432 mode = b'merge3' |
429 local = simplemerge.MergeInput(fcd, labels[0]) | |
430 other = simplemerge.MergeInput(fco, labels[1]) | |
431 base = simplemerge.MergeInput(fca, labels[2]) | |
432 r = simplemerge.simplemerge( | 433 r = simplemerge.simplemerge( |
433 ui, local, base, other, quiet=True, mode=mode | 434 ui, local, base, other, quiet=True, mode=mode |
434 ) | 435 ) |
435 if not r: | 436 if not r: |
436 ui.debug(b" premerge successful\n") | 437 ui.debug(b" premerge successful\n") |
437 return 0 | 438 return 0 |
438 if premerge not in validkeep: | 439 if premerge not in validkeep: |
439 # restore from backup and try again | 440 # restore from backup and try again |
440 _restorebackup(fcd, backup) | 441 _restorebackup(local.fctx, backup) |
441 return 1 # continue merging | 442 return 1 # continue merging |
442 | 443 |
443 | 444 |
444 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf): | 445 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf): |
445 tool, toolpath, binary, symlink, scriptfn = toolconf | 446 tool, toolpath, binary, symlink, scriptfn = toolconf |
460 ) | 461 ) |
461 return False | 462 return False |
462 return True | 463 return True |
463 | 464 |
464 | 465 |
465 def _merge(repo, fcd, fco, fca, labels, mode): | 466 def _merge(repo, local, other, base, mode): |
466 """ | 467 """ |
467 Uses the internal non-interactive simple merge algorithm for merging | 468 Uses the internal non-interactive simple merge algorithm for merging |
468 files. It will fail if there are any conflicts and leave markers in | 469 files. It will fail if there are any conflicts and leave markers in |
469 the partially merged file. Markers will have two sections, one for each side | 470 the partially merged file. Markers will have two sections, one for each side |
470 of merge, unless mode equals 'union' which suppresses the markers.""" | 471 of merge, unless mode equals 'union' which suppresses the markers.""" |
471 ui = repo.ui | 472 ui = repo.ui |
472 | 473 |
473 local = simplemerge.MergeInput(fcd) | |
474 local.label = labels[0] | |
475 other = simplemerge.MergeInput(fco) | |
476 other.label = labels[1] | |
477 base = simplemerge.MergeInput(fca) | |
478 base.label = labels[2] | |
479 r = simplemerge.simplemerge(ui, local, base, other, mode=mode) | 474 r = simplemerge.simplemerge(ui, local, base, other, mode=mode) |
480 return True, r, False | 475 return True, r, False |
481 | 476 |
482 | 477 |
483 @internaltool( | 478 @internaltool( |
487 b"warning: conflicts while merging %s! " | 482 b"warning: conflicts while merging %s! " |
488 b"(edit, then use 'hg resolve --mark')\n" | 483 b"(edit, then use 'hg resolve --mark')\n" |
489 ), | 484 ), |
490 precheck=_mergecheck, | 485 precheck=_mergecheck, |
491 ) | 486 ) |
492 def _iunion(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 487 def _iunion(repo, mynode, local, other, base, toolconf, backup): |
493 """ | 488 """ |
494 Uses the internal non-interactive simple merge algorithm for merging | 489 Uses the internal non-interactive simple merge algorithm for merging |
495 files. It will use both left and right sides for conflict regions. | 490 files. It will use both left and right sides for conflict regions. |
496 No markers are inserted.""" | 491 No markers are inserted.""" |
497 return _merge(repo, fcd, fco, fca, labels, b'union') | 492 return _merge(repo, local, other, base, b'union') |
498 | 493 |
499 | 494 |
500 @internaltool( | 495 @internaltool( |
501 b'merge', | 496 b'merge', |
502 fullmerge, | 497 fullmerge, |
504 b"warning: conflicts while merging %s! " | 499 b"warning: conflicts while merging %s! " |
505 b"(edit, then use 'hg resolve --mark')\n" | 500 b"(edit, then use 'hg resolve --mark')\n" |
506 ), | 501 ), |
507 precheck=_mergecheck, | 502 precheck=_mergecheck, |
508 ) | 503 ) |
509 def _imerge(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 504 def _imerge(repo, mynode, local, other, base, toolconf, backup): |
510 """ | 505 """ |
511 Uses the internal non-interactive simple merge algorithm for merging | 506 Uses the internal non-interactive simple merge algorithm for merging |
512 files. It will fail if there are any conflicts and leave markers in | 507 files. It will fail if there are any conflicts and leave markers in |
513 the partially merged file. Markers will have two sections, one for each side | 508 the partially merged file. Markers will have two sections, one for each side |
514 of merge.""" | 509 of merge.""" |
515 return _merge(repo, fcd, fco, fca, labels, b'merge') | 510 return _merge(repo, local, other, base, b'merge') |
516 | 511 |
517 | 512 |
518 @internaltool( | 513 @internaltool( |
519 b'merge3', | 514 b'merge3', |
520 fullmerge, | 515 fullmerge, |
522 b"warning: conflicts while merging %s! " | 517 b"warning: conflicts while merging %s! " |
523 b"(edit, then use 'hg resolve --mark')\n" | 518 b"(edit, then use 'hg resolve --mark')\n" |
524 ), | 519 ), |
525 precheck=_mergecheck, | 520 precheck=_mergecheck, |
526 ) | 521 ) |
527 def _imerge3(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 522 def _imerge3(repo, mynode, local, other, base, toolconf, backup): |
528 """ | 523 """ |
529 Uses the internal non-interactive simple merge algorithm for merging | 524 Uses the internal non-interactive simple merge algorithm for merging |
530 files. It will fail if there are any conflicts and leave markers in | 525 files. It will fail if there are any conflicts and leave markers in |
531 the partially merged file. Marker will have three sections, one from each | 526 the partially merged file. Marker will have three sections, one from each |
532 side of the merge and one for the base content.""" | 527 side of the merge and one for the base content.""" |
533 return _merge(repo, fcd, fco, fca, labels, b'merge3') | 528 return _merge(repo, local, other, base, b'merge3') |
534 | 529 |
535 | 530 |
536 @internaltool( | 531 @internaltool( |
537 b'merge3-lie-about-conflicts', | 532 b'merge3-lie-about-conflicts', |
538 fullmerge, | 533 fullmerge, |
559 b"warning: conflicts while merging %s! " | 554 b"warning: conflicts while merging %s! " |
560 b"(edit, then use 'hg resolve --mark')\n" | 555 b"(edit, then use 'hg resolve --mark')\n" |
561 ), | 556 ), |
562 precheck=_mergecheck, | 557 precheck=_mergecheck, |
563 ) | 558 ) |
564 def _imerge_diff(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 559 def _imerge_diff(repo, mynode, local, other, base, toolconf, backup): |
565 """ | 560 """ |
566 Uses the internal non-interactive simple merge algorithm for merging | 561 Uses the internal non-interactive simple merge algorithm for merging |
567 files. It will fail if there are any conflicts and leave markers in | 562 files. It will fail if there are any conflicts and leave markers in |
568 the partially merged file. The marker will have two sections, one with the | 563 the partially merged file. The marker will have two sections, one with the |
569 content from one side of the merge, and one with a diff from the base | 564 content from one side of the merge, and one with a diff from the base |
570 content to the content on the other side. (experimental)""" | 565 content to the content on the other side. (experimental)""" |
571 return _merge(repo, fcd, fco, fca, labels, b'mergediff') | 566 return _merge(repo, local, other, base, b'mergediff') |
572 | 567 |
573 | 568 |
574 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck) | 569 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck) |
575 def _imergelocal(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 570 def _imergelocal(repo, mynode, local, other, base, toolconf, backup): |
576 """ | 571 """ |
577 Like :merge, but resolve all conflicts non-interactively in favor | 572 Like :merge, but resolve all conflicts non-interactively in favor |
578 of the local `p1()` changes.""" | 573 of the local `p1()` changes.""" |
579 return _merge(repo, fcd, fco, fca, labels, b'local') | 574 return _merge(repo, local, other, base, b'local') |
580 | 575 |
581 | 576 |
582 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck) | 577 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck) |
583 def _imergeother(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 578 def _imergeother(repo, mynode, local, other, base, toolconf, backup): |
584 """ | 579 """ |
585 Like :merge, but resolve all conflicts non-interactively in favor | 580 Like :merge, but resolve all conflicts non-interactively in favor |
586 of the other `p2()` changes.""" | 581 of the other `p2()` changes.""" |
587 return _merge(repo, fcd, fco, fca, labels, b'other') | 582 return _merge(repo, local, other, base, b'other') |
588 | 583 |
589 | 584 |
590 @internaltool( | 585 @internaltool( |
591 b'tagmerge', | 586 b'tagmerge', |
592 mergeonly, | 587 mergeonly, |
594 b"automatic tag merging of %s failed! " | 589 b"automatic tag merging of %s failed! " |
595 b"(use 'hg resolve --tool :merge' or another merge " | 590 b"(use 'hg resolve --tool :merge' or another merge " |
596 b"tool of your choice)\n" | 591 b"tool of your choice)\n" |
597 ), | 592 ), |
598 ) | 593 ) |
599 def _itagmerge(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 594 def _itagmerge(repo, mynode, local, other, base, toolconf, backup): |
600 """ | 595 """ |
601 Uses the internal tag merge algorithm (experimental). | 596 Uses the internal tag merge algorithm (experimental). |
602 """ | 597 """ |
603 success, status = tagmerge.merge(repo, fcd, fco, fca) | 598 success, status = tagmerge.merge(repo, local.fctx, other.fctx, base.fctx) |
604 return success, status, False | 599 return success, status, False |
605 | 600 |
606 | 601 |
607 @internaltool(b'dump', fullmerge, binary=True, symlink=True) | 602 @internaltool(b'dump', fullmerge, binary=True, symlink=True) |
608 def _idump(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 603 def _idump(repo, mynode, local, other, base, toolconf, backup): |
609 """ | 604 """ |
610 Creates three versions of the files to merge, containing the | 605 Creates three versions of the files to merge, containing the |
611 contents of local, other and base. These files can then be used to | 606 contents of local, other and base. These files can then be used to |
612 perform a merge manually. If the file to be merged is named | 607 perform a merge manually. If the file to be merged is named |
613 ``a.txt``, these files will accordingly be named ``a.txt.local``, | 608 ``a.txt``, these files will accordingly be named ``a.txt.local``, |
615 same directory as ``a.txt``. | 610 same directory as ``a.txt``. |
616 | 611 |
617 This implies premerge. Therefore, files aren't dumped, if premerge | 612 This implies premerge. Therefore, files aren't dumped, if premerge |
618 runs successfully. Use :forcedump to forcibly write files out. | 613 runs successfully. Use :forcedump to forcibly write files out. |
619 """ | 614 """ |
620 a = _workingpath(repo, fcd) | 615 a = _workingpath(repo, local.fctx) |
621 fd = fcd.path() | 616 fd = local.fctx.path() |
622 | 617 |
623 from . import context | 618 from . import context |
624 | 619 |
625 if isinstance(fcd, context.overlayworkingfilectx): | 620 if isinstance(local.fctx, context.overlayworkingfilectx): |
626 raise error.InMemoryMergeConflictsError( | 621 raise error.InMemoryMergeConflictsError( |
627 b'in-memory merge does not support the :dump tool.' | 622 b'in-memory merge does not support the :dump tool.' |
628 ) | 623 ) |
629 | 624 |
630 util.writefile(a + b".local", fcd.decodeddata()) | 625 util.writefile(a + b".local", local.fctx.decodeddata()) |
631 repo.wwrite(fd + b".other", fco.data(), fco.flags()) | 626 repo.wwrite(fd + b".other", other.fctx.data(), other.fctx.flags()) |
632 repo.wwrite(fd + b".base", fca.data(), fca.flags()) | 627 repo.wwrite(fd + b".base", base.fctx.data(), base.fctx.flags()) |
633 return False, 1, False | 628 return False, 1, False |
634 | 629 |
635 | 630 |
636 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True) | 631 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True) |
637 def _forcedump(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 632 def _forcedump(repo, mynode, local, other, base, toolconf, backup): |
638 """ | 633 """ |
639 Creates three versions of the files as same as :dump, but omits premerge. | 634 Creates three versions of the files as same as :dump, but omits premerge. |
640 """ | 635 """ |
641 return _idump(repo, mynode, fcd, fco, fca, toolconf, backup, labels=labels) | 636 return _idump(repo, mynode, local, other, base, toolconf, backup) |
642 | 637 |
643 | 638 |
644 def _xmergeimm(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): | 639 def _xmergeimm(repo, mynode, local, other, base, toolconf, backup): |
645 # In-memory merge simply raises an exception on all external merge tools, | 640 # In-memory merge simply raises an exception on all external merge tools, |
646 # for now. | 641 # for now. |
647 # | 642 # |
648 # It would be possible to run most tools with temporary files, but this | 643 # It would be possible to run most tools with temporary files, but this |
649 # raises the question of what to do if the user only partially resolves the | 644 # raises the question of what to do if the user only partially resolves the |
707 ui, tmpl, defaults=templatekw.keywords, resources=tres | 702 ui, tmpl, defaults=templatekw.keywords, resources=tres |
708 ) | 703 ) |
709 ui.status(t.renderdefault(props)) | 704 ui.status(t.renderdefault(props)) |
710 | 705 |
711 | 706 |
712 def _xmerge(repo, mynode, fcd, fco, fca, toolconf, backup, labels): | 707 def _xmerge(repo, mynode, local, other, base, toolconf, backup): |
708 fcd = local.fctx | |
709 fco = other.fctx | |
710 fca = base.fctx | |
713 tool, toolpath, binary, symlink, scriptfn = toolconf | 711 tool, toolpath, binary, symlink, scriptfn = toolconf |
714 uipathfn = scmutil.getuipathfn(repo) | 712 uipathfn = scmutil.getuipathfn(repo) |
715 if fcd.isabsent() or fco.isabsent(): | 713 if fcd.isabsent() or fco.isabsent(): |
716 repo.ui.warn( | 714 repo.ui.warn( |
717 _(b'warning: %s cannot merge change/delete conflict for %s\n') | 715 _(b'warning: %s cannot merge change/delete conflict for %s\n') |
724 with _maketempfiles( | 722 with _maketempfiles( |
725 repo, fco, fca, repo.wvfs.join(backup.path()), b"$output" in args | 723 repo, fco, fca, repo.wvfs.join(backup.path()), b"$output" in args |
726 ) as temppaths: | 724 ) as temppaths: |
727 basepath, otherpath, localoutputpath = temppaths | 725 basepath, otherpath, localoutputpath = temppaths |
728 outpath = b"" | 726 outpath = b"" |
729 mylabel, otherlabel = labels[:2] | |
730 baselabel = labels[2] | |
731 env = { | 727 env = { |
732 b'HG_FILE': fcd.path(), | 728 b'HG_FILE': fcd.path(), |
733 b'HG_MY_NODE': short(mynode), | 729 b'HG_MY_NODE': short(mynode), |
734 b'HG_OTHER_NODE': short(fco.changectx().node()), | 730 b'HG_OTHER_NODE': short(fco.changectx().node()), |
735 b'HG_BASE_NODE': short(fca.changectx().node()), | 731 b'HG_BASE_NODE': short(fca.changectx().node()), |
736 b'HG_MY_ISLINK': b'l' in fcd.flags(), | 732 b'HG_MY_ISLINK': b'l' in fcd.flags(), |
737 b'HG_OTHER_ISLINK': b'l' in fco.flags(), | 733 b'HG_OTHER_ISLINK': b'l' in fco.flags(), |
738 b'HG_BASE_ISLINK': b'l' in fca.flags(), | 734 b'HG_BASE_ISLINK': b'l' in fca.flags(), |
739 b'HG_MY_LABEL': mylabel, | 735 b'HG_MY_LABEL': local.label, |
740 b'HG_OTHER_LABEL': otherlabel, | 736 b'HG_OTHER_LABEL': other.label, |
741 b'HG_BASE_LABEL': baselabel, | 737 b'HG_BASE_LABEL': base.label, |
742 } | 738 } |
743 ui = repo.ui | 739 ui = repo.ui |
744 | 740 |
745 if b"$output" in args: | 741 if b"$output" in args: |
746 # read input from backup, write to original | 742 # read input from backup, write to original |
749 replace = { | 745 replace = { |
750 b'local': localpath, | 746 b'local': localpath, |
751 b'base': basepath, | 747 b'base': basepath, |
752 b'other': otherpath, | 748 b'other': otherpath, |
753 b'output': outpath, | 749 b'output': outpath, |
754 b'labellocal': mylabel, | 750 b'labellocal': local.label, |
755 b'labelother': otherlabel, | 751 b'labelother': other.label, |
756 b'labelbase': baselabel, | 752 b'labelbase': base.label, |
757 } | 753 } |
758 args = util.interpolate( | 754 args = util.interpolate( |
759 br'\$', | 755 br'\$', |
760 replace, | 756 replace, |
761 args, | 757 args, |
803 r = 1 | 799 r = 1 |
804 repo.ui.debug(b'merge tool returned: %d\n' % r) | 800 repo.ui.debug(b'merge tool returned: %d\n' % r) |
805 return True, r, False | 801 return True, r, False |
806 | 802 |
807 | 803 |
808 def _formatlabel(input, template, pad): | 804 def _populate_label_detail(input, template, pad): |
809 """Applies the given template to the ctx, prefixed by the label. | 805 """Applies the given template to the ctx, prefixed by the label. |
810 | 806 |
811 Pad is the minimum width of the label prefix, so that multiple markers | 807 Pad is the minimum width of the label prefix, so that multiple markers |
812 can have aligned templated parts. | 808 can have aligned templated parts. |
813 """ | 809 """ |
824 | 820 |
825 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ') | 821 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ') |
826 input.label = stringutil.ellipsis(mark, 80 - 8) | 822 input.label = stringutil.ellipsis(mark, 80 - 8) |
827 | 823 |
828 | 824 |
829 def _formatlabels(repo, inputs, tool=None): | 825 def _populate_label_details(repo, inputs, tool=None): |
830 """Formats the given labels using the conflict marker template. | 826 """Formats the given labels using the conflict marker template. |
831 | 827 |
832 Returns a list of formatted labels. | 828 Returns a list of formatted labels. |
833 """ | 829 """ |
834 ui = repo.ui | 830 ui = repo.ui |
841 ui, template, defaults=templatekw.keywords, resources=tres | 837 ui, template, defaults=templatekw.keywords, resources=tres |
842 ) | 838 ) |
843 | 839 |
844 pad = max(len(input.label) for input in inputs) | 840 pad = max(len(input.label) for input in inputs) |
845 | 841 |
846 return [_formatlabel(input, tmpl, pad) for input in inputs] | 842 for input in inputs: |
843 _populate_label_detail(input, tmpl, pad) | |
847 | 844 |
848 | 845 |
849 def partextras(labels): | 846 def partextras(labels): |
850 """Return a dictionary of extra labels for use in prompts to the user | 847 """Return a dictionary of extra labels for use in prompts to the user |
851 | 848 |
1049 base = simplemerge.MergeInput(fca, labels[2]) | 1046 base = simplemerge.MergeInput(fca, labels[2]) |
1050 if mergetype == nomerge: | 1047 if mergetype == nomerge: |
1051 return func( | 1048 return func( |
1052 repo, | 1049 repo, |
1053 mynode, | 1050 mynode, |
1054 fcd, | 1051 local, |
1055 fco, | 1052 other, |
1056 fca, | 1053 base, |
1057 toolconf, | 1054 toolconf, |
1058 [local.label, other.label, base.label], | |
1059 ) | 1055 ) |
1060 | 1056 |
1061 if orig != fco.path(): | 1057 if orig != fco.path(): |
1062 ui.status( | 1058 ui.status( |
1063 _(b"merging %s and %s to %s\n") | 1059 _(b"merging %s and %s to %s\n") |
1096 if markerstyle != b'basic': | 1092 if markerstyle != b'basic': |
1097 # respect 'tool's mergemarkertemplate (which defaults to | 1093 # respect 'tool's mergemarkertemplate (which defaults to |
1098 # command-templates.mergemarker) | 1094 # command-templates.mergemarker) |
1099 labeltool = tool | 1095 labeltool = tool |
1100 if internalmarkerstyle != b'basic' or markerstyle != b'basic': | 1096 if internalmarkerstyle != b'basic' or markerstyle != b'basic': |
1101 _formatlabels(repo, [local, other, base], tool=labeltool) | 1097 _populate_label_details( |
1098 repo, [local, other, base], tool=labeltool | |
1099 ) | |
1102 | 1100 |
1103 r = _premerge( | 1101 r = _premerge( |
1104 repo, | 1102 repo, |
1105 fcd, | 1103 local, |
1106 fco, | 1104 other, |
1107 fca, | 1105 base, |
1108 toolconf, | 1106 toolconf, |
1109 backup, | 1107 backup, |
1110 labels=[local.label, other.label, base.label], | |
1111 ) | 1108 ) |
1112 # we're done if premerge was successful (r is 0) | 1109 # we're done if premerge was successful (r is 0) |
1113 if not r: | 1110 if not r: |
1114 return r, False | 1111 return r, False |
1115 | 1112 |
1117 local.label = labels[0] | 1114 local.label = labels[0] |
1118 other.label = labels[1] | 1115 other.label = labels[1] |
1119 base.label = labels[2] | 1116 base.label = labels[2] |
1120 | 1117 |
1121 if markerstyle != b'basic': | 1118 if markerstyle != b'basic': |
1122 _formatlabels(repo, [local, other, base], tool=tool) | 1119 _populate_label_details(repo, [local, other, base], tool=tool) |
1123 | 1120 |
1124 needcheck, r, deleted = func( | 1121 needcheck, r, deleted = func( |
1125 repo, | 1122 repo, |
1126 mynode, | 1123 mynode, |
1127 fcd, | 1124 local, |
1128 fco, | 1125 other, |
1129 fca, | 1126 base, |
1130 toolconf, | 1127 toolconf, |
1131 backup, | 1128 backup, |
1132 labels=[local.label, other.label, base.label], | |
1133 ) | 1129 ) |
1134 | 1130 |
1135 if needcheck: | 1131 if needcheck: |
1136 r = _check(repo, r, ui, tool, fcd, backup) | 1132 r = _check(repo, r, ui, tool, fcd, backup) |
1137 | 1133 |