Signed-off-by: Stefan Beller <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html