|
26 | 26 | #include "ll-merge.h"
|
27 | 27 | #include "object-store.h"
|
28 | 28 | #include "strmap.h"
|
| 29 | +#include "submodule.h" |
29 | 30 | #include "tree.h"
|
30 | 31 | #include "unpack-trees.h"
|
31 | 32 | #include "xdiff-interface.h"
|
@@ -323,6 +324,13 @@ static int err(struct merge_options *opt, const char *err, ...)
|
323 | 324 | return -1;
|
324 | 325 | }
|
325 | 326 |
|
| 327 | +static void format_commit(struct strbuf *sb, |
| 328 | + int indent, |
| 329 | + struct commit *commit) |
| 330 | +{ |
| 331 | + die("Not yet implemented."); |
| 332 | +} |
| 333 | + |
326 | 334 | __attribute__((format (printf, 4, 5)))
|
327 | 335 | static void path_msg(struct merge_options *opt,
|
328 | 336 | const char *path,
|
@@ -632,14 +640,130 @@ static int collect_merge_info(struct merge_options *opt,
|
632 | 640 |
|
633 | 641 | /*** Function Grouping: functions related to threeway content merges ***/
|
634 | 642 |
|
| 643 | +static int find_first_merges(struct repository *repo, |
| 644 | + const char *path, |
| 645 | + struct commit *a, |
| 646 | + struct commit *b, |
| 647 | + struct object_array *result) |
| 648 | +{ |
| 649 | + die("Not yet implemented."); |
| 650 | +} |
| 651 | + |
635 | 652 | static int merge_submodule(struct merge_options *opt,
|
636 | 653 | const char *path,
|
637 | 654 | const struct object_id *o,
|
638 | 655 | const struct object_id *a,
|
639 | 656 | const struct object_id *b,
|
640 | 657 | struct object_id *result)
|
641 | 658 | {
|
642 |
| - die("Not yet implemented."); |
| 659 | + struct commit *commit_o, *commit_a, *commit_b; |
| 660 | + int parent_count; |
| 661 | + struct object_array merges; |
| 662 | + struct strbuf sb = STRBUF_INIT; |
| 663 | + |
| 664 | + int i; |
| 665 | + int search = !opt->priv->call_depth; |
| 666 | + |
| 667 | + /* store fallback answer in result in case we fail */ |
| 668 | + oidcpy(result, opt->priv->call_depth ? o : a); |
| 669 | + |
| 670 | + /* we can not handle deletion conflicts */ |
| 671 | + if (is_null_oid(o)) |
| 672 | + return 0; |
| 673 | + if (is_null_oid(a)) |
| 674 | + return 0; |
| 675 | + if (is_null_oid(b)) |
| 676 | + return 0; |
| 677 | + |
| 678 | + if (add_submodule_odb(path)) { |
| 679 | + path_msg(opt, path, 0, |
| 680 | + _("Failed to merge submodule %s (not checked out)"), |
| 681 | + path); |
| 682 | + return 0; |
| 683 | + } |
| 684 | + |
| 685 | + if (!(commit_o = lookup_commit_reference(opt->repo, o)) || |
| 686 | + !(commit_a = lookup_commit_reference(opt->repo, a)) || |
| 687 | + !(commit_b = lookup_commit_reference(opt->repo, b))) { |
| 688 | + path_msg(opt, path, 0, |
| 689 | + _("Failed to merge submodule %s (commits not present)"), |
| 690 | + path); |
| 691 | + return 0; |
| 692 | + } |
| 693 | + |
| 694 | + /* check whether both changes are forward */ |
| 695 | + if (!in_merge_bases(commit_o, commit_a) || |
| 696 | + !in_merge_bases(commit_o, commit_b)) { |
| 697 | + path_msg(opt, path, 0, |
| 698 | + _("Failed to merge submodule %s " |
| 699 | + "(commits don't follow merge-base)"), |
| 700 | + path); |
| 701 | + return 0; |
| 702 | + } |
| 703 | + |
| 704 | + /* Case #1: a is contained in b or vice versa */ |
| 705 | + if (in_merge_bases(commit_a, commit_b)) { |
| 706 | + oidcpy(result, b); |
| 707 | + path_msg(opt, path, 1, |
| 708 | + _("Note: Fast-forwarding submodule %s to %s"), |
| 709 | + path, oid_to_hex(b)); |
| 710 | + return 1; |
| 711 | + } |
| 712 | + if (in_merge_bases(commit_b, commit_a)) { |
| 713 | + oidcpy(result, a); |
| 714 | + path_msg(opt, path, 1, |
| 715 | + _("Note: Fast-forwarding submodule %s to %s"), |
| 716 | + path, oid_to_hex(a)); |
| 717 | + return 1; |
| 718 | + } |
| 719 | + |
| 720 | + /* |
| 721 | + * Case #2: There are one or more merges that contain a and b in |
| 722 | + * the submodule. If there is only one, then present it as a |
| 723 | + * suggestion to the user, but leave it marked unmerged so the |
| 724 | + * user needs to confirm the resolution. |
| 725 | + */ |
| 726 | + |
| 727 | + /* Skip the search if makes no sense to the calling context. */ |
| 728 | + if (!search) |
| 729 | + return 0; |
| 730 | + |
| 731 | + /* find commit which merges them */ |
| 732 | + parent_count = find_first_merges(opt->repo, path, commit_a, commit_b, |
| 733 | + &merges); |
| 734 | + switch (parent_count) { |
| 735 | + case 0: |
| 736 | + path_msg(opt, path, 0, _("Failed to merge submodule %s"), path); |
| 737 | + break; |
| 738 | + |
| 739 | + case 1: |
| 740 | + format_commit(&sb, 4, |
| 741 | + (struct commit *)merges.objects[0].item); |
| 742 | + path_msg(opt, path, 0, |
| 743 | + _("Failed to merge submodule %s, but a possible merge " |
| 744 | + "resolution exists:\n%s\n"), |
| 745 | + path, sb.buf); |
| 746 | + path_msg(opt, path, 1, |
| 747 | + _("If this is correct simply add it to the index " |
| 748 | + "for example\n" |
| 749 | + "by using:\n\n" |
| 750 | + " git update-index --cacheinfo 160000 %s \"%s\"\n\n" |
| 751 | + "which will accept this suggestion.\n"), |
| 752 | + oid_to_hex(&merges.objects[0].item->oid), path); |
| 753 | + strbuf_release(&sb); |
| 754 | + break; |
| 755 | + default: |
| 756 | + for (i = 0; i < merges.nr; i++) |
| 757 | + format_commit(&sb, 4, |
| 758 | + (struct commit *)merges.objects[i].item); |
| 759 | + path_msg(opt, path, 0, |
| 760 | + _("Failed to merge submodule %s, but multiple " |
| 761 | + "possible merges exist:\n%s"), path, sb.buf); |
| 762 | + strbuf_release(&sb); |
| 763 | + } |
| 764 | + |
| 765 | + object_array_clear(&merges); |
| 766 | + return 0; |
643 | 767 | }
|
644 | 768 |
|
645 | 769 | static int merge_3way(struct merge_options *opt,
|
|
0 commit comments