@@ -1947,30 +1947,23 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
const char *update_string;
enum submodule_update_type update_type;
char *key;
- struct strbuf displaypath_sb = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
- const char *displaypath = NULL;
+ char *displaypath;
int needs_cloning = 0;
int need_free_url = 0;
+ displaypath = do_get_submodule_displaypath(ce->name,
+ suc->update_data->prefix,
+ suc->update_data->recursive_prefix);
+
if (ce_stage(ce)) {
- if (suc->update_data->recursive_prefix)
- strbuf_addf(&sb, "%s/%s", suc->update_data->recursive_prefix, ce->name);
- else
- strbuf_addstr(&sb, ce->name);
- strbuf_addf(out, _("Skipping unmerged submodule %s"), sb.buf);
+ strbuf_addf(out, _("Skipping unmerged submodule %s"), displaypath);
strbuf_addch(out, '\n');
goto cleanup;
}
sub = submodule_from_path(the_repository, null_oid(), ce->name);
- if (suc->update_data->recursive_prefix)
- displaypath = relative_path(suc->update_data->recursive_prefix,
- ce->name, &displaypath_sb);
- else
- displaypath = ce->name;
-
if (!sub) {
next_submodule_warn_missing(suc, out, displaypath);
goto cleanup;
@@ -2060,7 +2053,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
"--no-single-branch");
cleanup:
- strbuf_release(&displaypath_sb);
+ free(displaypath);
strbuf_release(&sb);
if (need_free_url)
free((void*)url);
@@ -1116,4 +1116,60 @@ test_expect_success 'submodule update --filter sets partial clone settings' '
test_cmp_config -C super-filter/submodule blob:none remote.origin.partialclonefilter
'
+# NEEDSWORK: Clean up the tests so that we can reuse the test setup.
+# Don't reuse the existing repos because the earlier tests have
+# intentionally disruptive configurations.
+test_expect_success 'setup clean recursive superproject' '
+ git init bottom &&
+ test_commit -C bottom "bottom" &&
+ git init middle &&
+ git -C middle submodule add ../bottom bottom &&
+ git -C middle commit -m "middle" &&
+ git init top &&
+ git -C top submodule add ../middle middle &&
+ git -C top commit -m "top" &&
+ git clone --recurse-submodules top top-clean
+'
+
+test_expect_success 'submodule update should skip unmerged submodules' '
+ test_when_finished "rm -fr top-cloned" &&
+ cp -r top-clean top-cloned &&
+
+ # Create an upstream commit in each repo, starting with bottom
+ test_commit -C bottom upstream_commit &&
+ # Create middle commit
+ git -C middle/bottom fetch &&
+ git -C middle/bottom checkout -f FETCH_HEAD &&
+ git -C middle add bottom &&
+ git -C middle commit -m "upstream_commit" &&
+ # Create top commit
+ git -C top/middle fetch &&
+ git -C top/middle checkout -f FETCH_HEAD &&
+ git -C top add middle &&
+ git -C top commit -m "upstream_commit" &&
+
+ # Create a downstream conflict
+ test_commit -C top-cloned/middle/bottom downstream_commit &&
+ git -C top-cloned/middle add bottom &&
+ git -C top-cloned/middle commit -m "downstream_commit" &&
+ git -C top-cloned/middle fetch --recurse-submodules origin &&
+ test_must_fail git -C top-cloned/middle merge origin/main &&
+
+ # Make the update of "middle" a no-op, otherwise we error out
+ # because of its unmerged state
+ test_config -C top-cloned submodule.middle.update !true &&
+ git -C top-cloned submodule update --recursive 2>actual.err &&
+ grep -F "Skipping unmerged submodule middle/bottom" actual.err
+'
+
+test_expect_success 'submodule update --recursive skip submodules with strategy=none' '
+ test_when_finished "rm -fr top-cloned" &&
+ cp -r top-clean top-cloned &&
+
+ test_commit -C top-cloned/middle/bottom downstream_commit &&
+ git -C top-cloned/middle config submodule.bottom.update none &&
+ git -C top-cloned submodule update --recursive 2>actual.err &&
+ grep -F "Skipping submodule ${SQ}middle/bottom${SQ}" actual.err
+'
+
test_done