batch check whether submodule needs pushing into one call
[gitweb.git] / submodule.c
index d07390bc5835c425d43ede5cce59b91ab090051d..85287a1d16b7e5346fcd760bf2afd1deb75e6ee2 100644 (file)
@@ -529,27 +529,49 @@ static int append_sha1_to_argv(const unsigned char sha1[20], void *data)
        return 0;
 }
 
-static int submodule_needs_pushing(const char *path, const unsigned char sha1[20])
+static int check_has_commit(const unsigned char sha1[20], void *data)
 {
-       if (add_submodule_odb(path) || !lookup_commit_reference(sha1))
+       int *has_commit = data;
+
+       if (!lookup_commit_reference(sha1))
+               *has_commit = 0;
+
+       return 0;
+}
+
+static int submodule_has_commits(const char *path, struct sha1_array *commits)
+{
+       int has_commit = 1;
+
+       if (add_submodule_odb(path))
+               return 0;
+
+       sha1_array_for_each_unique(commits, check_has_commit, &has_commit);
+       return has_commit;
+}
+
+static int submodule_needs_pushing(const char *path, struct sha1_array *commits)
+{
+       if (!submodule_has_commits(path, commits))
                return 0;
 
        if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
                struct child_process cp = CHILD_PROCESS_INIT;
-               const char *argv[] = {"rev-list", NULL, "--not", "--remotes", "-n", "1" , NULL};
                struct strbuf buf = STRBUF_INIT;
                int needs_pushing = 0;
 
-               argv[1] = sha1_to_hex(sha1);
-               cp.argv = argv;
+               argv_array_push(&cp.args, "rev-list");
+               sha1_array_for_each_unique(commits, append_sha1_to_argv, &cp.args);
+               argv_array_pushl(&cp.args, "--not", "--remotes", "-n", "1" , NULL);
+
                prepare_submodule_repo_env(&cp.env_array);
                cp.git_cmd = 1;
                cp.no_stdin = 1;
                cp.out = -1;
                cp.dir = path;
                if (start_command(&cp))
-                       die("Could not run 'git rev-list %s --not --remotes -n 1' command in submodule %s",
-                               sha1_to_hex(sha1), path);
+                       die("Could not run 'git rev-list <commits> --not --remotes -n 1' command in submodule %s",
+                                       path);
                if (strbuf_read(&buf, cp.out, 41))
                        needs_pushing = 1;
                finish_command(&cp);
@@ -604,22 +626,6 @@ static void find_unpushed_submodule_commits(struct commit *commit,
        diff_tree_combined_merge(commit, 1, &rev);
 }
 
-struct collect_submodule_from_sha1s_data {
-       char *submodule_path;
-       struct string_list *needs_pushing;
-};
-
-static int collect_submodules_from_sha1s(const unsigned char sha1[20],
-               void *data)
-{
-       struct collect_submodule_from_sha1s_data *me = data;
-
-       if (submodule_needs_pushing(me->submodule_path, sha1))
-               string_list_insert(me->needs_pushing, me->submodule_path);
-
-       return 0;
-}
-
 static void free_submodules_sha1s(struct string_list *submodules)
 {
        struct string_list_item *item;
@@ -656,12 +662,10 @@ int find_unpushed_submodules(struct sha1_array *commits,
        argv_array_clear(&argv);
 
        for_each_string_list_item(submodule, &submodules) {
-               struct collect_submodule_from_sha1s_data data;
-               data.submodule_path = submodule->string;
-               data.needs_pushing = needs_pushing;
-               sha1_array_for_each_unique((struct sha1_array *) submodule->util,
-                               collect_submodules_from_sha1s,
-                               &data);
+               struct sha1_array *commits = (struct sha1_array *) submodule->util;
+
+               if (submodule_needs_pushing(submodule->string, commits))
+                       string_list_insert(needs_pushing, submodule->string);
        }
        free_submodules_sha1s(&submodules);