batch check whether submodule needs pushing into one call

We run a command for each sha1 change in a submodule. This is unnecessary since we can simply batch all sha1's we want to check into one command. Lets do it so we can speedup the check when many submodule changes are in need of checking. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Heiko Voigt committed Nov 16, 2016 at 16:11 UTC 5b6607d23f8a262e1c0ede954f0477664934eed8
1 file changed +33 -29
submodule.c
+33 -29
@@ -529,27 +529,49 @@ static int append_sha1_to_argv(const unsigned char sha1[20], void *data)
529 return 0;
530 }
531
532 -static int submodule_needs_pushing(const char *path, const unsigned char sha1[20])
532 +static int check_has_commit(const unsigned char sha1[20], void *data)
533 {
534 - if (add_submodule_odb(path) || !lookup_commit_reference(sha1))
534 + int *has_commit = data;
535 +
536 + if (!lookup_commit_reference(sha1))
537 + *has_commit = 0;
538 +
539 + return 0;
540 +}
541 +
542 +static int submodule_has_commits(const char *path, struct sha1_array *commits)
543 +{
544 + int has_commit = 1;
545 +
546 + if (add_submodule_odb(path))
547 + return 0;
548 +
549 + sha1_array_for_each_unique(commits, check_has_commit, &has_commit);
550 + return has_commit;
551 +}
552 +
553 +static int submodule_needs_pushing(const char *path, struct sha1_array *commits)
554 +{
555 + if (!submodule_has_commits(path, commits))
556 return 0;
557
558 if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
559 struct child_process cp = CHILD_PROCESS_INIT;
539 - const char *argv[] = {"rev-list", NULL, "--not", "--remotes", "-n", "1" , NULL};
560 struct strbuf buf = STRBUF_INIT;
561 int needs_pushing = 0;
562
543 - argv[1] = sha1_to_hex(sha1);
544 - cp.argv = argv;
563 + argv_array_push(&cp.args, "rev-list");
564 + sha1_array_for_each_unique(commits, append_sha1_to_argv, &cp.args);
565 + argv_array_pushl(&cp.args, "--not", "--remotes", "-n", "1" , NULL);
566 +
567 prepare_submodule_repo_env(&cp.env_array);
568 cp.git_cmd = 1;
569 cp.no_stdin = 1;
570 cp.out = -1;
571 cp.dir = path;
572 if (start_command(&cp))
551 - die("Could not run 'git rev-list %s --not --remotes -n 1' command in submodule %s",
552 - sha1_to_hex(sha1), path);
573 + die("Could not run 'git rev-list <commits> --not --remotes -n 1' command in submodule %s",
574 + path);
575 if (strbuf_read(&buf, cp.out, 41))
576 needs_pushing = 1;
577 finish_command(&cp);
@@ -604,22 +626,6 @@ static void find_unpushed_submodule_commits(struct commit *commit,
626 diff_tree_combined_merge(commit, 1, &rev);
627 }
628
607 -struct collect_submodule_from_sha1s_data {
608 - char *submodule_path;
609 - struct string_list *needs_pushing;
610 -};
611 -
612 -static int collect_submodules_from_sha1s(const unsigned char sha1[20],
613 - void *data)
614 -{
615 - struct collect_submodule_from_sha1s_data *me = data;
616 -
617 - if (submodule_needs_pushing(me->submodule_path, sha1))
618 - string_list_insert(me->needs_pushing, me->submodule_path);
619 -
620 - return 0;
621 -}
622 -
629 static void free_submodules_sha1s(struct string_list *submodules)
630 {
631 struct string_list_item *item;
@@ -656,12 +662,10 @@ int find_unpushed_submodules(struct sha1_array *commits,
662 argv_array_clear(&argv);
663
664 for_each_string_list_item(submodule, &submodules) {
659 - struct collect_submodule_from_sha1s_data data;
660 - data.submodule_path = submodule->string;
661 - data.needs_pushing = needs_pushing;
662 - sha1_array_for_each_unique((struct sha1_array *) submodule->util,
663 - collect_submodules_from_sha1s,
664 - &data);
665 + struct sha1_array *commits = (struct sha1_array *) submodule->util;
666 +
667 + if (submodule_needs_pushing(submodule->string, commits))
668 + string_list_insert(needs_pushing, submodule->string);
669 }
670 free_submodules_sha1s(&submodules);
671