summaryrefslogtreecommitdiff
path: root/merge-ort.c
diff options
context:
space:
mode:
Diffstat (limited to 'merge-ort.c')
-rw-r--r--merge-ort.c70
1 files changed, 51 insertions, 19 deletions
diff --git a/merge-ort.c b/merge-ort.c
index 515dc39b7f..ab42c5d847 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -32,6 +32,7 @@
#include "promisor-remote.h"
#include "revision.h"
#include "strmap.h"
+#include "submodule-config.h"
#include "submodule.h"
#include "tree.h"
#include "unpack-trees.h"
@@ -1511,7 +1512,6 @@ static int find_first_merges(struct repository *repo,
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);
@@ -1521,7 +1521,7 @@ static int find_first_merges(struct repository *repo,
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
- if (in_merge_bases(b, commit))
+ if (repo_in_merge_bases(repo, b, commit))
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
@@ -1536,7 +1536,7 @@ static int find_first_merges(struct repository *repo,
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)) {
+ if (i != j && repo_in_merge_bases(repo, m2, m1)) {
contains_another = 1;
break;
}
@@ -1557,10 +1557,12 @@ static int merge_submodule(struct merge_options *opt,
const struct object_id *b,
struct object_id *result)
{
+ struct repository subrepo;
+ struct strbuf sb = STRBUF_INIT;
+ int ret = 0;
struct commit *commit_o, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
- struct strbuf sb = STRBUF_INIT;
int i;
int search = !opt->priv->call_depth;
@@ -1576,6 +1578,10 @@ static int merge_submodule(struct merge_options *opt,
if (is_null_oid(b))
return 0;
+ /*
+ * NEEDSWORK: Remove this when all submodule object accesses are
+ * through explicitly specified repositores.
+ */
if (add_submodule_odb(path)) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s (not checked out)"),
@@ -1583,39 +1589,48 @@ static int merge_submodule(struct merge_options *opt,
return 0;
}
- if (!(commit_o = lookup_commit_reference(opt->repo, o)) ||
- !(commit_a = lookup_commit_reference(opt->repo, a)) ||
- !(commit_b = lookup_commit_reference(opt->repo, b))) {
+ if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
+ path_msg(opt, path, 0,
+ _("Failed to merge submodule %s (not checked out)"),
+ path);
+ return 0;
+ }
+
+ if (!(commit_o = lookup_commit_reference(&subrepo, o)) ||
+ !(commit_a = lookup_commit_reference(&subrepo, a)) ||
+ !(commit_b = lookup_commit_reference(&subrepo, b))) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s (commits not present)"),
path);
- return 0;
+ goto cleanup;
}
/* check whether both changes are forward */
- if (!in_merge_bases(commit_o, commit_a) ||
- !in_merge_bases(commit_o, commit_b)) {
+ if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
+ !repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
path_msg(opt, path, 0,
_("Failed to merge submodule %s "
"(commits don't follow merge-base)"),
path);
- return 0;
+ goto cleanup;
}
/* Case #1: a is contained in b or vice versa */
- if (in_merge_bases(commit_a, commit_b)) {
+ if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
oidcpy(result, b);
path_msg(opt, path, 1,
_("Note: Fast-forwarding submodule %s to %s"),
path, oid_to_hex(b));
- return 1;
+ ret = 1;
+ goto cleanup;
}
- if (in_merge_bases(commit_b, commit_a)) {
+ if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
oidcpy(result, a);
path_msg(opt, path, 1,
_("Note: Fast-forwarding submodule %s to %s"),
path, oid_to_hex(a));
- return 1;
+ ret = 1;
+ goto cleanup;
}
/*
@@ -1627,10 +1642,10 @@ static int merge_submodule(struct merge_options *opt,
/* Skip the search if makes no sense to the calling context. */
if (!search)
- return 0;
+ goto cleanup;
/* find commit which merges them */
- parent_count = find_first_merges(opt->repo, path, commit_a, commit_b,
+ parent_count = find_first_merges(&subrepo, path, commit_a, commit_b,
&merges);
switch (parent_count) {
case 0:
@@ -1664,7 +1679,9 @@ static int merge_submodule(struct merge_options *opt,
}
object_array_clear(&merges);
- return 0;
+cleanup:
+ repo_clear(&subrepo);
+ return ret;
}
static void initialize_attr_index(struct merge_options *opt)
@@ -4074,6 +4091,21 @@ static int record_conflicted_index_entries(struct merge_options *opt)
if (strmap_empty(&opt->priv->conflicted))
return 0;
+ /*
+ * We are in a conflicted state. These conflicts might be inside
+ * sparse-directory entries, so check if any entries are outside
+ * of the sparse-checkout cone preemptively.
+ *
+ * We set original_cache_nr below, but that might change if
+ * index_name_pos() calls ask for paths within sparse directories.
+ */
+ strmap_for_each_entry(&opt->priv->conflicted, &iter, e) {
+ if (!path_in_sparse_checkout(e->key, index)) {
+ ensure_full_index(index);
+ break;
+ }
+ }
+
/* If any entries have skip_worktree set, we'll have to check 'em out */
state.force = 1;
state.quiet = 1;
@@ -4081,7 +4113,7 @@ static int record_conflicted_index_entries(struct merge_options *opt)
state.istate = index;
original_cache_nr = index->cache_nr;
- /* Put every entry from paths into plist, then sort */
+ /* Append every entry from conflicted into index, then sort */
strmap_for_each_entry(&opt->priv->conflicted, &iter, e) {
const char *path = e->key;
struct conflict_info *ci = e->value;