summaryrefslogtreecommitdiff
path: root/merge-ort.c
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2021-01-01 02:34:47 (GMT)
committerJunio C Hamano <gitster@pobox.com>2021-01-04 18:40:45 (GMT)
commit4204cd591b62f3e184f617d01b282b9847298dbd (patch)
treecb8f14aac71e9999d3c874613219998f2260d9a4 /merge-ort.c
parent70f19c7fced2ec49fd9bca827370835d84d782c7 (diff)
downloadgit-4204cd591b62f3e184f617d01b282b9847298dbd.zip
git-4204cd591b62f3e184f617d01b282b9847298dbd.tar.gz
git-4204cd591b62f3e184f617d01b282b9847298dbd.tar.bz2
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 <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'merge-ort.c')
-rw-r--r--merge-ort.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/merge-ort.c b/merge-ort.c
index bf704bc..203fa98 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -25,6 +25,7 @@
#include "dir.h"
#include "ll-merge.h"
#include "object-store.h"
+#include "revision.h"
#include "strmap.h"
#include "submodule.h"
#include "tree.h"
@@ -658,7 +659,61 @@ static int find_first_merges(struct repository *repo,
struct commit *b,
struct object_array *result)
{
- die("Not yet implemented.");
+ int i, j;
+ struct object_array merges = OBJECT_ARRAY_INIT;
+ struct commit *commit;
+ int contains_another;
+
+ char merged_revision[GIT_MAX_HEXSZ + 2];
+ const char *rev_args[] = { "rev-list", "--merges", "--ancestry-path",
+ "--all", merged_revision, NULL };
+ struct rev_info revs;
+ struct setup_revision_opt rev_opts;
+
+ memset(result, 0, sizeof(struct object_array));
+ memset(&rev_opts, 0, sizeof(rev_opts));
+
+ /* get all revisions that merge commit a */
+ xsnprintf(merged_revision, sizeof(merged_revision), "^%s",
+ oid_to_hex(&a->object.oid));
+ repo_init_revisions(repo, &revs, NULL);
+ rev_opts.submodule = path;
+ /* FIXME: can't handle linked worktrees in submodules yet */
+ revs.single_worktree = path != NULL;
+ setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts);
+
+ /* save all revisions from the above list that contain b */
+ if (prepare_revision_walk(&revs))
+ die("revision walk setup failed");
+ while ((commit = get_revision(&revs)) != NULL) {
+ struct object *o = &(commit->object);
+ if (in_merge_bases(b, commit))
+ add_object_array(o, NULL, &merges);
+ }
+ reset_revision_walk();
+
+ /* Now we've got all merges that contain a and b. Prune all
+ * merges that contain another found merge and save them in
+ * result.
+ */
+ for (i = 0; i < merges.nr; i++) {
+ struct commit *m1 = (struct commit *) merges.objects[i].item;
+
+ contains_another = 0;
+ for (j = 0; j < merges.nr; j++) {
+ struct commit *m2 = (struct commit *) merges.objects[j].item;
+ if (i != j && in_merge_bases(m2, m1)) {
+ contains_another = 1;
+ break;
+ }
+ }
+
+ if (!contains_another)
+ add_object_array(merges.objects[i].item, NULL, result);
+ }
+
+ object_array_clear(&merges);
+ return result->nr;
}
static int merge_submodule(struct merge_options *opt,