Merge branch 'jt/submodule-pull-recurse-rebase'
[gitweb.git] / builtin / submodule--helper.c
index 4f35c98bb970328bca5135bd66fdaf3a9fce0d16..bd250ca2164b31356fb42406351761cd2381d115 100644 (file)
 #include "run-command.h"
 #include "remote.h"
 #include "refs.h"
+#include "refspec.h"
 #include "connect.h"
 #include "revision.h"
 #include "diffcore.h"
 #include "diff.h"
+#include "object-store.h"
 
 #define OPT_QUIET (1 << 0)
 #define OPT_CACHED (1 << 1)
@@ -454,7 +456,7 @@ static void init_submodule(const char *path, const char *prefix,
 
        displaypath = get_submodule_displaypath(path, prefix);
 
-       sub = submodule_from_path(&null_oid, path);
+       sub = submodule_from_path(the_repository, &null_oid, path);
 
        if (!sub)
                die(_("No url found for submodule path '%s' in .gitmodules"),
@@ -595,8 +597,12 @@ static void print_status(unsigned int flags, char state, const char *path,
 
        printf("%c%s %s", state, oid_to_hex(oid), displaypath);
 
-       if (state == ' ' || state == '+')
-               printf(" (%s)", compute_rev_name(path, oid_to_hex(oid)));
+       if (state == ' ' || state == '+') {
+               const char *name = compute_rev_name(path, oid_to_hex(oid));
+
+               if (name)
+                       printf(" (%s)", name);
+       }
 
        printf("\n");
 }
@@ -621,7 +627,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
        struct rev_info rev;
        int diff_files_result;
 
-       if (!submodule_from_path(&null_oid, path))
+       if (!submodule_from_path(the_repository, &null_oid, path))
                die(_("no submodule mapping found in .gitmodules for path '%s'"),
                      path);
 
@@ -654,9 +660,13 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
                             displaypath);
        } else if (!(flags & OPT_CACHED)) {
                struct object_id oid;
+               struct ref_store *refs = get_submodule_ref_store(path);
 
-               if (refs_head_ref(get_submodule_ref_store(path),
-                                 handle_submodule_head_ref, &oid))
+               if (!refs) {
+                       print_status(flags, '-', path, ce_oid, displaypath);
+                       goto cleanup;
+               }
+               if (refs_head_ref(refs, handle_submodule_head_ref, &oid))
                        die(_("could not resolve HEAD ref inside the "
                              "submodule '%s'"), path);
 
@@ -741,7 +751,7 @@ static int module_name(int argc, const char **argv, const char *prefix)
        if (argc != 2)
                usage(_("git submodule--helper name <path>"));
 
-       sub = submodule_from_path(&null_oid, argv[1]);
+       sub = submodule_from_path(the_repository, &null_oid, argv[1]);
 
        if (!sub)
                die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@ -772,7 +782,7 @@ static void sync_submodule(const char *path, const char *prefix,
        if (!is_submodule_active(the_repository, path))
                return;
 
-       sub = submodule_from_path(&null_oid, path);
+       sub = submodule_from_path(the_repository, &null_oid, path);
 
        if (sub && sub->url) {
                if (starts_with_dot_dot_slash(sub->url) ||
@@ -925,7 +935,7 @@ static void deinit_submodule(const char *path, const char *prefix,
        struct strbuf sb_config = STRBUF_INIT;
        char *sub_git_dir = xstrfmt("%s/.git", path);
 
-       sub = submodule_from_path(&null_oid, path);
+       sub = submodule_from_path(the_repository, &null_oid, path);
 
        if (!sub || !sub->name)
                goto cleanup;
@@ -1056,7 +1066,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 }
 
 static int clone_submodule(const char *path, const char *gitdir, const char *url,
-                          const char *depth, struct string_list *reference,
+                          const char *depth, struct string_list *reference, int dissociate,
                           int quiet, int progress)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
@@ -1075,6 +1085,8 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
                        argv_array_pushl(&cp.args, "--reference",
                                         item->string, NULL);
        }
+       if (dissociate)
+               argv_array_push(&cp.args, "--dissociate");
        if (gitdir && *gitdir)
                argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
 
@@ -1190,6 +1202,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
        char *p, *path = NULL, *sm_gitdir;
        struct strbuf sb = STRBUF_INIT;
        struct string_list reference = STRING_LIST_INIT_NODUP;
+       int dissociate = 0;
        char *sm_alternate = NULL, *error_strategy = NULL;
 
        struct option module_clone_options[] = {
@@ -1208,6 +1221,8 @@ static int module_clone(int argc, const char **argv, const char *prefix)
                OPT_STRING_LIST(0, "reference", &reference,
                           N_("repo"),
                           N_("reference repository")),
+               OPT_BOOL(0, "dissociate", &dissociate,
+                          N_("use --reference only while cloning")),
                OPT_STRING(0, "depth", &depth,
                           N_("string"),
                           N_("depth for shallow clones")),
@@ -1247,7 +1262,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 
                prepare_possible_alternates(name, &reference);
 
-               if (clone_submodule(path, sm_gitdir, url, depth, &reference,
+               if (clone_submodule(path, sm_gitdir, url, depth, &reference, dissociate,
                                    quiet, progress))
                        die(_("clone of '%s' into submodule path '%s' failed"),
                            url, path);
@@ -1259,8 +1274,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
                strbuf_reset(&sb);
        }
 
-       /* Connect module worktree and git dir */
-       connect_work_tree_and_git_dir(path, sm_gitdir);
+       connect_work_tree_and_git_dir(path, sm_gitdir, 0);
 
        p = git_pathdup_submodule(path, "config");
        if (!p)
@@ -1300,6 +1314,7 @@ struct submodule_update_clone {
        int quiet;
        int recommend_shallow;
        struct string_list references;
+       int dissociate;
        const char *depth;
        const char *recursive_prefix;
        const char *prefix;
@@ -1315,7 +1330,7 @@ struct submodule_update_clone {
        int failed_clones_nr, failed_clones_alloc;
 };
 #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
-       SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, \
+       SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \
        NULL, NULL, NULL, \
        STRING_LIST_INIT_DUP, 0, NULL, 0, 0}
 
@@ -1367,7 +1382,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                goto cleanup;
        }
 
-       sub = submodule_from_path(&null_oid, ce->name);
+       sub = submodule_from_path(the_repository, &null_oid, ce->name);
 
        if (suc->recursive_prefix)
                displaypath = relative_path(suc->recursive_prefix,
@@ -1442,6 +1457,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
                for_each_string_list_item(item, &suc->references)
                        argv_array_pushl(&child->args, "--reference", item->string, NULL);
        }
+       if (suc->dissociate)
+               argv_array_push(&child->args, "--dissociate");
        if (suc->depth)
                argv_array_push(&child->args, suc->depth);
 
@@ -1575,6 +1592,8 @@ static int update_clone(int argc, const char **argv, const char *prefix)
                           N_("rebase, merge, checkout or none")),
                OPT_STRING_LIST(0, "reference", &suc.references, N_("repo"),
                           N_("reference repository")),
+               OPT_BOOL(0, "dissociate", &suc.dissociate,
+                          N_("use --reference only while cloning")),
                OPT_STRING(0, "depth", &suc.depth, "<depth>",
                           N_("Create a shallow clone truncated to the "
                              "specified number of revisions")),
@@ -1650,7 +1669,7 @@ static const char *remote_submodule_branch(const char *path)
        const char *branch = NULL;
        char *key;
 
-       sub = submodule_from_path(&null_oid, path);
+       sub = submodule_from_path(the_repository, &null_oid, path);
        if (!sub)
                return NULL;
 
@@ -1735,13 +1754,14 @@ static int push_check(int argc, const char **argv, const char *prefix)
 
        /* Check the refspec */
        if (argc > 2) {
-               int i, refspec_nr = argc - 2;
+               int i;
                struct ref *local_refs = get_local_heads();
-               struct refspec *refspec = parse_push_refspec(refspec_nr,
-                                                            argv + 2);
+               struct refspec refspec = REFSPEC_INIT_PUSH;
+
+               refspec_appendn(&refspec, argv + 2, argc - 2);
 
-               for (i = 0; i < refspec_nr; i++) {
-                       struct refspec *rs = refspec + i;
+               for (i = 0; i < refspec.nr; i++) {
+                       const struct refspec_item *rs = &refspec.items[i];
 
                        if (rs->pattern || rs->matching)
                                continue;
@@ -1768,7 +1788,7 @@ static int push_check(int argc, const char **argv, const char *prefix)
                                    rs->src);
                        }
                }
-               free_refspec(refspec_nr, refspec);
+               refspec_clear(&refspec);
        }
        free(head);