Skip to content

Commit c73cda7

Browse files
newrengitster
authored andcommitted
merge-ort: copy and adapt merge_submodule() from merge-recursive.c
Take merge_submodule() from merge-recursive.c and make slight adjustments, predominantly around deferring output using path_msg() instead of using merge-recursive's output() and show() functions. There's also a fix for recursive cases (when call_depth > 0) and a slight change to argument order for find_first_merges(). find_first_merges() and format_commit() are left unimplemented for now, but will be added by subsequent commits. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent f591c47 commit c73cda7

File tree

1 file changed

+125
-1
lines changed

1 file changed

+125
-1
lines changed

merge-ort.c

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "ll-merge.h"
2727
#include "object-store.h"
2828
#include "strmap.h"
29+
#include "submodule.h"
2930
#include "tree.h"
3031
#include "unpack-trees.h"
3132
#include "xdiff-interface.h"
@@ -323,6 +324,13 @@ static int err(struct merge_options *opt, const char *err, ...)
323324
return -1;
324325
}
325326

327+
static void format_commit(struct strbuf *sb,
328+
int indent,
329+
struct commit *commit)
330+
{
331+
die("Not yet implemented.");
332+
}
333+
326334
__attribute__((format (printf, 4, 5)))
327335
static void path_msg(struct merge_options *opt,
328336
const char *path,
@@ -632,14 +640,130 @@ static int collect_merge_info(struct merge_options *opt,
632640

633641
/*** Function Grouping: functions related to threeway content merges ***/
634642

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+
635652
static int merge_submodule(struct merge_options *opt,
636653
const char *path,
637654
const struct object_id *o,
638655
const struct object_id *a,
639656
const struct object_id *b,
640657
struct object_id *result)
641658
{
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;
643767
}
644768

645769
static int merge_3way(struct merge_options *opt,

0 commit comments

Comments
 (0)