diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index ec41d3d698a1bcffac3b3a21489b61cc74f9d8d0..e316c4bd51a64fb9df87ce003f2edffad38b63ad 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -90,13 +90,16 @@ If you want to break the dependency of a repository cloned with `-s` on its source repository, you can simply run `git repack -a` to copy all objects from the source repository into a pack in the cloned repository. ---reference :: +--reference[-if-able] :: If the reference repository is on the local machine, automatically setup `.git/objects/info/alternates` to obtain objects from the reference repository. Using an already existing repository as an alternate will require fewer objects to be copied from the repository being cloned, reducing network and local storage costs. + When using the `--reference-if-able`, a non existing + directory is skipped with a warning instead of aborting + the clone. + *NOTE*: see the NOTE for the `--shared` option, and also the `--dissociate` option. diff --git a/builtin/clone.c b/builtin/clone.c index ef5db7c499e72276e15251ea127ac354ed030f9b..01826651f9cc283f47fba713cea8999bd7b67462 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -51,6 +51,7 @@ 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_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; @@ -81,6 +82,8 @@ static struct option builtin_clone_options[] = { N_("directory from which templates will be used")), 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"), @@ -283,24 +286,36 @@ static void strip_trailing_slashes(char *dir) static int add_one_reference(struct string_list_item *item, void *cb_data) { struct strbuf err = STRBUF_INIT; - struct strbuf sb = STRBUF_INIT; + int *required = cb_data; char *ref_git = compute_alternate_path(item->string, &err); - if (!ref_git) - die("%s", err.buf); - - strbuf_addf(&sb, "%s/objects", ref_git); - add_to_alternates_file(sb.buf); + 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; + strbuf_addf(&sb, "%s/objects", ref_git); + add_to_alternates_file(sb.buf); + strbuf_release(&sb); + } - free(ref_git); strbuf_release(&err); - strbuf_release(&sb); + free(ref_git); return 0; } static void setup_reference(void) { - for_each_string_list(&option_required_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, @@ -952,7 +967,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set(key.buf, repo); strbuf_reset(&key); - if (option_required_reference.nr) + if (option_required_reference.nr || option_optional_reference.nr) setup_reference(); fetch_pattern = value.buf;