diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-09-08 21:49:50 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-09-08 21:49:50 -0700 |
commit | 02c6c14d6c304f094b680f583a1dd6e4fe75736c (patch) | |
tree | fa598c403c80413a3446045cb5a287b61e38e673 /builtin/clone.c | |
parent | 00d27937bf0348e7da615f04b65f535a58e096c1 (diff) | |
parent | 31224cbdc723d78a310b4cdbbd5abcfcbd44a4e5 (diff) | |
download | git-02c6c14d6c304f094b680f583a1dd6e4fe75736c.tar.gz git-02c6c14d6c304f094b680f583a1dd6e4fe75736c.tar.xz |
Merge branch 'sb/submodule-clone-rr'
"git clone --resurse-submodules --reference $path $URL" is a way to
reduce network transfer cost by borrowing objects in an existing
$path repository when cloning the superproject from $URL; it
learned to also peek into $path for presense of corresponding
repositories of submodules and borrow objects from there when able.
* sb/submodule-clone-rr:
clone: recursive and reference option triggers submodule alternates
clone: implement optional references
clone: clarify option_reference as required
clone: factor out checking for an alternate path
submodule--helper update-clone: allow multiple references
submodule--helper module-clone: allow multiple references
t7408: merge short tests, factor out testing method
t7408: modernize style
Diffstat (limited to 'builtin/clone.c')
-rw-r--r-- | builtin/clone.c | 83 |
1 files changed, 46 insertions, 37 deletions
diff --git a/builtin/clone.c b/builtin/clone.c index f044a8c27..404c5e802 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -50,7 +50,8 @@ static int option_verbosity; static int option_progress = -1; static enum transport_family family; static struct string_list option_config = STRING_LIST_INIT_NODUP; -static struct string_list option_reference = STRING_LIST_INIT_NODUP; +static struct string_list option_required_reference = STRING_LIST_INIT_NODUP; +static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP; static int option_dissociate; static int max_jobs = -1; @@ -79,8 +80,10 @@ static struct option builtin_clone_options[] = { N_("number of submodules cloned in parallel")), OPT_STRING(0, "template", &option_template, N_("template-directory"), N_("directory from which templates will be used")), - OPT_STRING_LIST(0, "reference", &option_reference, N_("repo"), + OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"), N_("reference repository")), + OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference, + N_("repo"), N_("reference repository")), OPT_BOOL(0, "dissociate", &option_dissociate, N_("use --reference only while cloning")), OPT_STRING('o', "origin", &option_origin, N_("name"), @@ -282,50 +285,37 @@ static void strip_trailing_slashes(char *dir) static int add_one_reference(struct string_list_item *item, void *cb_data) { - char *ref_git; - const char *repo; - struct strbuf alternate = STRBUF_INIT; - - /* Beware: read_gitfile(), real_path() and mkpath() return static buffer */ - ref_git = xstrdup(real_path(item->string)); - - repo = read_gitfile(ref_git); - if (!repo) - repo = read_gitfile(mkpath("%s/.git", ref_git)); - if (repo) { - free(ref_git); - ref_git = xstrdup(repo); - } + struct strbuf err = STRBUF_INIT; + int *required = cb_data; + char *ref_git = compute_alternate_path(item->string, &err); - if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { - char *ref_git_git = mkpathdup("%s/.git", ref_git); - free(ref_git); - ref_git = ref_git_git; - } else if (!is_directory(mkpath("%s/objects", ref_git))) { + if (!ref_git) { + if (*required) + die("%s", err.buf); + else + fprintf(stderr, + _("info: Could not add alternate for '%s': %s\n"), + item->string, err.buf); + } else { struct strbuf sb = STRBUF_INIT; - if (get_common_dir(&sb, ref_git)) - die(_("reference repository '%s' as a linked checkout is not supported yet."), - item->string); - die(_("reference repository '%s' is not a local repository."), - item->string); + strbuf_addf(&sb, "%s/objects", ref_git); + add_to_alternates_file(sb.buf); + strbuf_release(&sb); } - if (!access(mkpath("%s/shallow", ref_git), F_OK)) - die(_("reference repository '%s' is shallow"), item->string); - - if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) - die(_("reference repository '%s' is grafted"), item->string); - - strbuf_addf(&alternate, "%s/objects", ref_git); - add_to_alternates_file(alternate.buf); - strbuf_release(&alternate); + strbuf_release(&err); free(ref_git); return 0; } static void setup_reference(void) { - for_each_string_list(&option_reference, add_one_reference, NULL); + int required = 1; + for_each_string_list(&option_required_reference, + add_one_reference, &required); + required = 0; + for_each_string_list(&option_optional_reference, + add_one_reference, &required); } static void copy_alternates(struct strbuf *src, struct strbuf *dst, @@ -957,6 +947,25 @@ int cmd_clone(int argc, const char **argv, const char *prefix) else fprintf(stderr, _("Cloning into '%s'...\n"), dir); } + + if (option_recursive) { + if (option_required_reference.nr && + option_optional_reference.nr) + die(_("clone --recursive is not compatible with " + "both --reference and --reference-if-able")); + else if (option_required_reference.nr) { + string_list_append(&option_config, + "submodule.alternateLocation=superproject"); + string_list_append(&option_config, + "submodule.alternateErrorStrategy=die"); + } else if (option_optional_reference.nr) { + string_list_append(&option_config, + "submodule.alternateLocation=superproject"); + string_list_append(&option_config, + "submodule.alternateErrorStrategy=info"); + } + } + init_db(option_template, INIT_DB_QUIET); write_config(&option_config); @@ -977,7 +986,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set(key.buf, repo); strbuf_reset(&key); - if (option_reference.nr) + if (option_required_reference.nr || option_optional_reference.nr) setup_reference(); fetch_pattern = value.buf; |