Merge branch 'sb/sequencer-abort-safety'
[gitweb.git] / builtin / clone.c
index 28ce9383a14ced7ea3f135bdc0d42226aaf790af..5ef81927a629985aa4f0de6acba326f79747e7aa 100644 (file)
@@ -41,9 +41,11 @@ 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 int deepen;
+static char *option_template, *option_depth, *option_since;
 static char *option_origin = NULL;
 static char *option_branch = NULL;
+static struct string_list option_not = STRING_LIST_INIT_NODUP;
 static const char *real_git_dir;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbosity;
@@ -94,6 +96,10 @@ static struct option builtin_clone_options[] = {
                   N_("path to git-upload-pack on the remote")),
        OPT_STRING(0, "depth", &option_depth, N_("depth"),
                    N_("create a shallow clone of that depth")),
+       OPT_STRING(0, "shallow-since", &option_since, N_("time"),
+                   N_("create a shallow clone since a specific time")),
+       OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"),
+                       N_("deepen history of shallow clone, excluding rev")),
        OPT_BOOL(0, "single-branch", &option_single_branch,
                    N_("clone only one branch, HEAD or --branch")),
        OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
@@ -345,8 +351,11 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
                        continue;
                }
                abs_path = mkpathdup("%s/objects/%s", src_repo, line.buf);
-               normalize_path_copy(abs_path, abs_path);
-               add_to_alternates_file(abs_path);
+               if (!normalize_path_copy(abs_path, abs_path))
+                       add_to_alternates_file(abs_path);
+               else
+                       warning("skipping invalid relative alternate: %s/%s",
+                               src_repo, line.buf);
                free(abs_path);
        }
        strbuf_release(&line);
@@ -702,7 +711,7 @@ static int checkout(int submodule_progress)
        setup_work_tree();
 
        lock_file = xcalloc(1, sizeof(struct lock_file));
-       hold_locked_index(lock_file, 1);
+       hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
 
        memset(&opts, 0, sizeof opts);
        opts.update = 1;
@@ -861,8 +870,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                usage_msg_opt(_("You must specify a repository to clone."),
                        builtin_clone_usage, builtin_clone_options);
 
+       if (option_depth || option_since || option_not.nr)
+               deepen = 1;
        if (option_single_branch == -1)
-               option_single_branch = option_depth ? 1 : 0;
+               option_single_branch = deepen ? 1 : 0;
 
        if (option_mirror)
                option_bare = 1;
@@ -935,16 +946,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                set_git_work_tree(work_tree);
        }
 
-       junk_git_dir = git_dir;
+       junk_git_dir = real_git_dir ? real_git_dir : git_dir;
        if (safe_create_leading_directories_const(git_dir) < 0)
                die(_("could not create leading directories of '%s'"), git_dir);
 
-       set_git_dir_init(git_dir, real_git_dir, 0);
-       if (real_git_dir) {
-               git_dir = real_git_dir;
-               junk_git_dir = real_git_dir;
-       }
-
        if (0 <= option_verbosity) {
                if (option_bare)
                        fprintf(stderr, _("Cloning into bare repository '%s'...\n"), dir);
@@ -970,7 +975,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                }
        }
 
-       init_db(option_template, INIT_DB_QUIET);
+       init_db(git_dir, real_git_dir, option_template, INIT_DB_QUIET);
+
+       if (real_git_dir)
+               git_dir = real_git_dir;
+
        write_config(&option_config);
 
        git_config(git_default_config, NULL);
@@ -1008,6 +1017,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        if (is_local) {
                if (option_depth)
                        warning(_("--depth is ignored in local clones; use file:// instead."));
+               if (option_since)
+                       warning(_("--shallow-since is ignored in local clones; use file:// instead."));
+               if (option_not.nr)
+                       warning(_("--shallow-exclude is ignored in local clones; use file:// instead."));
                if (!access(mkpath("%s/shallow", path), F_OK)) {
                        if (option_local > 0)
                                warning(_("source repository is shallow, ignoring --local"));
@@ -1026,6 +1039,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        if (option_depth)
                transport_set_option(transport, TRANS_OPT_DEPTH,
                                     option_depth);
+       if (option_since)
+               transport_set_option(transport, TRANS_OPT_DEEPEN_SINCE,
+                                    option_since);
+       if (option_not.nr)
+               transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
+                                    (const char *)&option_not);
        if (option_single_branch)
                transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
 
@@ -1033,7 +1052,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                transport_set_option(transport, TRANS_OPT_UPLOADPACK,
                                     option_upload_pack);
 
-       if (transport->smart_options && !option_depth)
+       if (transport->smart_options && !deepen)
                transport->smart_options->check_self_contained_and_connected = 1;
 
        refs = transport_get_remote_refs(transport);