Skip to content

Commit 4204cd5

Browse files
newrengitster
authored andcommitted
merge-ort: copy find_first_merges() implementation from merge-recursive.c
Code is identical for the function body in the two files, the call signature is just slightly different in merge-ort than merge-recursive as noted a couple commits ago. Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 70f19c7 commit 4204cd5

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

merge-ort.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "dir.h"
2626
#include "ll-merge.h"
2727
#include "object-store.h"
28+
#include "revision.h"
2829
#include "strmap.h"
2930
#include "submodule.h"
3031
#include "tree.h"
@@ -658,7 +659,61 @@ static int find_first_merges(struct repository *repo,
658659
struct commit *b,
659660
struct object_array *result)
660661
{
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;
662717
}
663718

664719
static int merge_submodule(struct merge_options *opt,

0 commit comments

Comments
 (0)