|
25 | 25 | #include "dir.h"
|
26 | 26 | #include "ll-merge.h"
|
27 | 27 | #include "object-store.h"
|
| 28 | +#include "revision.h" |
28 | 29 | #include "strmap.h"
|
29 | 30 | #include "submodule.h"
|
30 | 31 | #include "tree.h"
|
@@ -658,7 +659,61 @@ static int find_first_merges(struct repository *repo,
|
658 | 659 | struct commit *b,
|
659 | 660 | struct object_array *result)
|
660 | 661 | {
|
661 |
| - die("Not yet implemented."); |
| 662 | + int i, j; |
| 663 | + struct object_array merges = OBJECT_ARRAY_INIT; |
| 664 | + struct commit *commit; |
| 665 | + int contains_another; |
| 666 | + |
| 667 | + char merged_revision[GIT_MAX_HEXSZ + 2]; |
| 668 | + const char *rev_args[] = { "rev-list", "--merges", "--ancestry-path", |
| 669 | + "--all", merged_revision, NULL }; |
| 670 | + struct rev_info revs; |
| 671 | + struct setup_revision_opt rev_opts; |
| 672 | + |
| 673 | + memset(result, 0, sizeof(struct object_array)); |
| 674 | + memset(&rev_opts, 0, sizeof(rev_opts)); |
| 675 | + |
| 676 | + /* get all revisions that merge commit a */ |
| 677 | + xsnprintf(merged_revision, sizeof(merged_revision), "^%s", |
| 678 | + oid_to_hex(&a->object.oid)); |
| 679 | + repo_init_revisions(repo, &revs, NULL); |
| 680 | + rev_opts.submodule = path; |
| 681 | + /* FIXME: can't handle linked worktrees in submodules yet */ |
| 682 | + revs.single_worktree = path != NULL; |
| 683 | + setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts); |
| 684 | + |
| 685 | + /* save all revisions from the above list that contain b */ |
| 686 | + if (prepare_revision_walk(&revs)) |
| 687 | + die("revision walk setup failed"); |
| 688 | + while ((commit = get_revision(&revs)) != NULL) { |
| 689 | + struct object *o = &(commit->object); |
| 690 | + if (in_merge_bases(b, commit)) |
| 691 | + add_object_array(o, NULL, &merges); |
| 692 | + } |
| 693 | + reset_revision_walk(); |
| 694 | + |
| 695 | + /* Now we've got all merges that contain a and b. Prune all |
| 696 | + * merges that contain another found merge and save them in |
| 697 | + * result. |
| 698 | + */ |
| 699 | + for (i = 0; i < merges.nr; i++) { |
| 700 | + struct commit *m1 = (struct commit *) merges.objects[i].item; |
| 701 | + |
| 702 | + contains_another = 0; |
| 703 | + for (j = 0; j < merges.nr; j++) { |
| 704 | + struct commit *m2 = (struct commit *) merges.objects[j].item; |
| 705 | + if (i != j && in_merge_bases(m2, m1)) { |
| 706 | + contains_another = 1; |
| 707 | + break; |
| 708 | + } |
| 709 | + } |
| 710 | + |
| 711 | + if (!contains_another) |
| 712 | + add_object_array(merges.objects[i].item, NULL, result); |
| 713 | + } |
| 714 | + |
| 715 | + object_array_clear(&merges); |
| 716 | + return result->nr; |
662 | 717 | }
|
663 | 718 |
|
664 | 719 | static int merge_submodule(struct merge_options *opt,
|
|
0 commit comments