push, fetch: error out for submodule entries not pointing to commits
The check_has_commit helper uses resolves a submodule entry to a commit, when validating its existence. As a side effect this means tolerates a submodule entry pointing to a tag, which is not a valid submodule entry that git commands would know how to cope with. Tighten the check to require an actual commit, not a tag pointing to a commit. Also improve the error handling when a submodule entry points to non-commit (e.g., a blob) to error out instead of warning and pretending the pointed to object doesn't exist. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stefan Beller committed
Sep 12, 2017 at 10:30 UTC
3c96aa97232367a24eef8b3b387f5ddae5b0c10f
2 files changed
+35
-8
submodule.c
+25
-8
@@ -767,19 +767,36 @@ static int append_oid_to_argv(const struct object_id *oid, void *data)
767
return 0;
768
}
769
770
+struct has_commit_data {
771
+ int result;
772
+ const char *path;
773
+};
774
+
775
static int check_has_commit(const struct object_id *oid, void *data)
776
{
772
- int *has_commit = data;
777
+ struct has_commit_data *cb = data;
778
774
- if (!lookup_commit_reference(oid))
775
- *has_commit = 0;
779
+ enum object_type type = sha1_object_info(oid->hash, NULL);
780
777
- return 0;
781
+ switch (type) {
782
+ case OBJ_COMMIT:
783
+ return 0;
784
+ case OBJ_BAD:
785
+ /*
786
+ * Object is missing or invalid. If invalid, an error message
787
+ * has already been printed.
788
+ */
789
+ cb->result = 0;
790
+ return 0;
791
+ default:
792
+ die(_("submodule entry '%s' (%s) is a %s, not a commit"),
793
+ cb->path, oid_to_hex(oid), typename(type));
794
+ }
795
}
796
797
static int submodule_has_commits(const char *path, struct oid_array *commits)
798
{
782
- int has_commit = 1;
799
+ struct has_commit_data has_commit = { 1, path };
800
801
/*
802
* Perform a cheap, but incorrect check for the existence of 'commits'.
@@ -795,7 +812,7 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
812
813
oid_array_for_each_unique(commits, check_has_commit, &has_commit);
814
798
- if (has_commit) {
815
+ if (has_commit.result) {
816
/*
817
* Even if the submodule is checked out and the commit is
818
* present, make sure it exists in the submodule's object store
@@ -814,12 +831,12 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
831
cp.dir = path;
832
833
if (capture_command(&cp, &out, GIT_MAX_HEXSZ + 1) || out.len)
817
- has_commit = 0;
834
+ has_commit.result = 0;
835
836
strbuf_release(&out);
837
}
838
822
- return has_commit;
839
+ return has_commit.result;
840
}
841
842
static int submodule_needs_pushing(const char *path, struct oid_array *commits)
t/t5531-deep-submodule-push.sh
+10
@@ -298,6 +298,16 @@ test_expect_success 'push succeeds if submodule commit disabling recursion from
298
)
299
'
300
301
+test_expect_success 'submodule entry pointing at a tag is error' '
302
+ git -C work/gar/bage tag -a test1 -m "tag" &&
303
+ tag=$(git -C work/gar/bage rev-parse test1^{tag}) &&
304
+ git -C work update-index --cacheinfo 160000 "$tag" gar/bage &&
305
+ git -C work commit -m "bad commit" &&
306
+ test_when_finished "git -C work reset --hard HEAD^" &&
307
+ test_must_fail git -C work push --recurse-submodules=on-demand ../pub.git master 2>err &&
308
+ test_i18ngrep "is a tag, not a commit" err
309
+'
310
+
311
test_expect_success 'push fails if recurse submodules option passed as yes' '
312
(
313
cd work/gar/bage &&