diff options
author | Brandon Williams <bmwill@google.com> | 2017-05-01 18:02:38 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-05-02 10:45:04 +0900 |
commit | 7c8d2b00f2516a0b30aaa3f59dceaf4fe83f8729 (patch) | |
tree | 85dabcd646b4b88bde3d1d15b6c4b750097ce41a /submodule.c | |
parent | a6bb78c3b19697133a01122c13993986b66ef28b (diff) | |
download | git-7c8d2b00f2516a0b30aaa3f59dceaf4fe83f8729.tar.gz |
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>
Diffstat (limited to 'submodule.c')
-rw-r--r-- | submodule.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/submodule.c b/submodule.c index 3bcf44521b..057695e645 100644 --- a/submodule.c +++ b/submodule.c @@ -644,10 +644,44 @@ static int submodule_has_commits(const char *path, struct oid_array *commits) { int has_commit = 1; + /* + * Perform a cheap, but incorrect check for the existance of 'commits'. + * This is done by adding the submodule's object store to the in-core + * object store, and then querying for each commit's existance. If we + * do not have the commit object anywhere, there is no chance we have + * it in the object store of the correct submodule and have it + * reachable from a ref, so we can fail early without spawning rev-list + * which is expensive. + */ if (add_submodule_odb(path)) return 0; oid_array_for_each_unique(commits, check_has_commit, &has_commit); + + if (has_commit) { + /* + * Even if the submodule is checked out and the commit is + * present, make sure it exists in the submodule's object store + * and that it is reachable from a ref. + */ + struct child_process cp = CHILD_PROCESS_INIT; + struct strbuf out = STRBUF_INIT; + + argv_array_pushl(&cp.args, "rev-list", "-n", "1", NULL); + oid_array_for_each_unique(commits, append_oid_to_argv, &cp.args); + argv_array_pushl(&cp.args, "--not", "--all", NULL); + + prepare_submodule_repo_env(&cp.env_array); + cp.git_cmd = 1; + cp.no_stdin = 1; + cp.dir = path; + + if (capture_command(&cp, &out, GIT_MAX_HEXSZ + 1) || out.len) + has_commit = 0; + + strbuf_release(&out); + } + return has_commit; } |