Merge branch 'mh/diff-indent-heuristic'
[gitweb.git] / builtin / clone.c
index ef5db7c499e72276e15251ea127ac354ed030f9b..404c5e80226c81a8f051e63fa8e40286fea95a18 100644 (file)
@@ -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,
@@ -932,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);
 
@@ -952,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_required_reference.nr)
+       if (option_required_reference.nr || option_optional_reference.nr)
                setup_reference();
 
        fetch_pattern = value.buf;