Merge branch 'jk/upload-pack-hook'
[gitweb.git] / builtin / clone.c
index 8a90cad5b534adbb4d1370f8f2365de21a934248..31ea247e3f262fb19595905869a7f2d874aa898e 100644 (file)
@@ -40,6 +40,7 @@ static const char * const builtin_clone_usage[] = {
 
 static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
 static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;
+static int option_shallow_submodules;
 static char *option_template, *option_depth;
 static char *option_origin = NULL;
 static char *option_branch = NULL;
@@ -47,9 +48,11 @@ static const char *real_git_dir;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbosity;
 static int option_progress = -1;
-static struct string_list option_config;
-static struct string_list option_reference;
+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 int option_dissociate;
+static int max_jobs = -1;
 
 static struct option builtin_clone_options[] = {
        OPT__VERBOSITY(&option_verbosity),
@@ -72,6 +75,8 @@ static struct option builtin_clone_options[] = {
                    N_("initialize submodules in the clone")),
        OPT_BOOL(0, "recurse-submodules", &option_recursive,
                    N_("initialize submodules in the clone")),
+       OPT_INTEGER('j', "jobs", &max_jobs,
+                   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"),
@@ -88,17 +93,19 @@ static struct option builtin_clone_options[] = {
                    N_("create a shallow clone of that depth")),
        OPT_BOOL(0, "single-branch", &option_single_branch,
                    N_("clone only one branch, HEAD or --branch")),
+       OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
+                   N_("any cloned submodules will be shallow")),
        OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
                   N_("separate git dir from working tree")),
        OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
                        N_("set config inside the new repository")),
+       OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+                       TRANSPORT_FAMILY_IPV4),
+       OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+                       TRANSPORT_FAMILY_IPV6),
        OPT_END()
 };
 
-static const char *argv_submodule[] = {
-       "submodule", "update", "--init", "--recursive", NULL
-};
-
 static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)
 {
        static char *suffix[] = { "/.git", "", ".git/.git", ".git" };
@@ -231,8 +238,8 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
        strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
 
        if (!len || (len == 1 && *start == '/'))
-           die("No directory name could be guessed.\n"
-               "Please specify a directory on the command line");
+               die(_("No directory name could be guessed.\n"
+                     "Please specify a directory on the command line"));
 
        if (is_bare)
                dir = xstrfmt("%.*s.git", (int)len, start);
@@ -339,7 +346,7 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
        FILE *in = fopen(src->buf, "r");
        struct strbuf line = STRBUF_INIT;
 
-       while (strbuf_getline(&line, in, '\n') != EOF) {
+       while (strbuf_getline(&line, in) != EOF) {
                char *abs_path;
                if (!line.len || line.buf[0] == '#')
                        continue;
@@ -636,9 +643,11 @@ static void update_remote_refs(const struct ref *refs,
                struct strbuf head_ref = STRBUF_INIT;
                strbuf_addstr(&head_ref, branch_top);
                strbuf_addstr(&head_ref, "HEAD");
-               create_symref(head_ref.buf,
-                             remote_head_points_at->peer_ref->name,
-                             msg);
+               if (create_symref(head_ref.buf,
+                                 remote_head_points_at->peer_ref->name,
+                                 msg) < 0)
+                       die(_("unable to update %s"), head_ref.buf);
+               strbuf_release(&head_ref);
        }
 }
 
@@ -648,7 +657,8 @@ static void update_head(const struct ref *our, const struct ref *remote,
        const char *head;
        if (our && skip_prefix(our->name, "refs/heads/", &head)) {
                /* Local default branch link */
-               create_symref("HEAD", our->name, NULL);
+               if (create_symref("HEAD", our->name, NULL) < 0)
+                       die(_("unable to update HEAD"));
                if (!option_bare) {
                        update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
                                   UPDATE_REFS_DIE_ON_ERR);
@@ -724,8 +734,19 @@ static int checkout(void)
        err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
                           sha1_to_hex(sha1), "1", NULL);
 
-       if (!err && option_recursive)
-               err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
+       if (!err && option_recursive) {
+               struct argv_array args = ARGV_ARRAY_INIT;
+               argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL);
+
+               if (option_shallow_submodules == 1)
+                       argv_array_push(&args, "--depth=1");
+
+               if (max_jobs != -1)
+                       argv_array_pushf(&args, "--jobs=%d", max_jobs);
+
+               err = run_command_v_opt(args.argv, RUN_GIT_CMD);
+               argv_array_clear(&args);
+       }
 
        return err;
 }
@@ -742,7 +763,7 @@ static void write_config(struct string_list *config)
        for (i = 0; i < config->nr; i++) {
                if (git_config_parse_parameter(config->items[i].string,
                                               write_one_config, NULL) < 0)
-                       die("unable to write parameters to config file");
+                       die(_("unable to write parameters to config file"));
        }
 }
 
@@ -967,6 +988,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        remote = remote_get(option_origin);
        transport = transport_get(remote, remote->url[0]);
        transport_set_verbosity(transport, option_verbosity, option_progress);
+       transport->family = family;
 
        path = get_repo_path(remote->url[0], &is_bundle);
        is_local = option_local != 0 && path && !is_bundle;