submodule: improve submodule_has_commits()

Teach 'submodule_has_commits()' to ensure that if a commit exists in a submodule, that it is also reachable from a ref. This is a preparatory step prior to merging the logic which checks for changed submodules when fetching or pushing. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed May 1, 2017 at 18:02 UTC 7c8d2b00f2516a0b30aaa3f59dceaf4fe83f8729
1 file changed +34
submodule.c
+34
@@ -644,10 +644,44 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
644 {
645 int has_commit = 1;
646
647 + /*
648 + * Perform a cheap, but incorrect check for the existance of 'commits'.
649 + * This is done by adding the submodule's object store to the in-core
650 + * object store, and then querying for each commit's existance. If we
651 + * do not have the commit object anywhere, there is no chance we have
652 + * it in the object store of the correct submodule and have it
653 + * reachable from a ref, so we can fail early without spawning rev-list
654 + * which is expensive.
655 + */
656 if (add_submodule_odb(path))
657 return 0;
658
659 oid_array_for_each_unique(commits, check_has_commit, &has_commit);
660 +
661 + if (has_commit) {
662 + /*
663 + * Even if the submodule is checked out and the commit is
664 + * present, make sure it exists in the submodule's object store
665 + * and that it is reachable from a ref.
666 + */
667 + struct child_process cp = CHILD_PROCESS_INIT;
668 + struct strbuf out = STRBUF_INIT;
669 +
670 + argv_array_pushl(&cp.args, "rev-list", "-n", "1", NULL);
671 + oid_array_for_each_unique(commits, append_oid_to_argv, &cp.args);
672 + argv_array_pushl(&cp.args, "--not", "--all", NULL);
673 +
674 + prepare_submodule_repo_env(&cp.env_array);
675 + cp.git_cmd = 1;
676 + cp.no_stdin = 1;
677 + cp.dir = path;
678 +
679 + if (capture_command(&cp, &out, GIT_MAX_HEXSZ + 1) || out.len)
680 + has_commit = 0;
681 +
682 + strbuf_release(&out);
683 + }
684 +
685 return has_commit;
686 }
687