Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- Documentation/git-clone.txt | 4 ++++ builtin/submodule--helper.c | 47 ++++++++++++++++++++++++++++++++++++++++++ t/t7408-submodule-reference.sh | 29 +++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index e316c4b..cadf138 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -103,6 +103,10 @@ objects from the source repository into a pack in the cloned repository. + *NOTE*: see the NOTE for the `--shared` option, and also the `--dissociate` option. ++ +When using --reference any submodule that is cloned +sets up a corresponding alternate at $GIT_DIR/modules if such a +an alternate exists. --dissociate:: Borrow the objects from reference repositories specified diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f360473..fc14843 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -635,6 +635,45 @@ static void next_submodule_warn_missing(struct submodule_update_clone *suc, } } +struct submodule_alternate_setup { + struct submodule_update_clone *suc; + const char *submodule_name; + struct child_process *child; + struct strbuf *out; +}; + +int add_possible_reference(struct alternate_object_database *alt, void *sas_cb) +{ + struct submodule_alternate_setup *sas = sas_cb; + + /* directory name, minus trailing slash */ + size_t namelen = alt->name - alt->base - 1; + struct strbuf name = STRBUF_INIT; + strbuf_add(&name, alt->base, namelen); + + /* + * If the alternate object store is another repository, try the + * standard layout with .git/modules/<name>/objects + */ + if (ends_with(name.buf, ".git/objects")) { + struct strbuf sb = STRBUF_INIT; + strbuf_add(&sb, name.buf, name.len - strlen("objects")); + /* + * We need to end the new path with '/' to mark it as a dir, + * otherwise a submodule name containing '/' will be broken + * as the last part of a missing submodule reference would + * be taken as a file name. + */ + strbuf_addf(&sb, "modules/%s/", sas->submodule_name); + argv_array_pushf(&sas->child->args, + "--reference-if-able=%s", sb.buf); + strbuf_release(&sb); + } + + strbuf_release(&name); + return 0; +} + /** * Determine whether 'ce' needs to be cloned. If so, prepare the 'child' to * run the clone. Returns 1 if 'ce' needs to be cloned, 0 otherwise. @@ -650,6 +689,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, const char *displaypath = NULL; char *url = NULL; int needs_cloning = 0; + struct submodule_alternate_setup sas; if (ce_stage(ce)) { if (suc->recursive_prefix) @@ -728,6 +768,13 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, for_each_string_list_item(item, &suc->references) argv_array_pushl(&child->args, "--reference", item->string, NULL); } + + sas.submodule_name = sub->name; + sas.suc = suc; + sas.child = child; + sas.out = out; + foreach_alt_odb(add_possible_reference, &sas); + if (suc->depth) argv_array_push(&child->args, suc->depth); diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index 4a1b8f0..a9b89a3 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -7,7 +7,6 @@ test_description='test clone --reference' . ./test-lib.sh base_dir=$(pwd) - test_alternate_is_used () { alternates_file="$1" && working_dir="$2" && @@ -73,4 +72,32 @@ test_expect_success 'updating superproject keeps alternates' ' test_alternate_is_used super-clone/.git/modules/sub/objects/info/alternates super-clone/sub ' +test_expect_success 'submodules use alternates when cloning a superproject' ' + test_when_finished "rm -rf super-clone" && + git clone --reference super --recursive super super-clone && + ( + cd super-clone && + # test superproject has alternates setup correctly + test_alternate_is_used .git/objects/info/alternates . && + # test submodule has correct setup + test_alternate_is_used .git/modules/sub/objects/info/alternates sub + ) +' + +test_expect_success 'cloning superproject, missing submodule alternates' ' + test_when_finished "rm -rf super-clone" && + git clone super super2 && + git clone --recursive --reference super2 super2 super-clone && + ( + cd super-clone && + # test superproject has alternates setup correctly + test_alternate_is_used .git/objects/info/alternates . && + # update of the submodule succeeds + git submodule update --init && + # and we have no alternates: + test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub && + test_path_is_file sub/file1 + ) +' + test_done -- 2.9.2.583.gd6329be.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html