Skip to content

Commit 3c96aa9

Browse files
stefanbellergitster
authored andcommitted
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>
1 parent 607bd83 commit 3c96aa9

File tree

2 files changed

+35
-8
lines changed

2 files changed

+35
-8
lines changed

submodule.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -767,19 +767,36 @@ static int append_oid_to_argv(const struct object_id *oid, void *data)
767767
return 0;
768768
}
769769

770+
struct has_commit_data {
771+
int result;
772+
const char *path;
773+
};
774+
770775
static int check_has_commit(const struct object_id *oid, void *data)
771776
{
772-
int *has_commit = data;
777+
struct has_commit_data *cb = data;
773778

774-
if (!lookup_commit_reference(oid))
775-
*has_commit = 0;
779+
enum object_type type = sha1_object_info(oid->hash, NULL);
776780

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+
}
778795
}
779796

780797
static int submodule_has_commits(const char *path, struct oid_array *commits)
781798
{
782-
int has_commit = 1;
799+
struct has_commit_data has_commit = { 1, path };
783800

784801
/*
785802
* 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)
795812

796813
oid_array_for_each_unique(commits, check_has_commit, &has_commit);
797814

798-
if (has_commit) {
815+
if (has_commit.result) {
799816
/*
800817
* Even if the submodule is checked out and the commit is
801818
* 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)
814831
cp.dir = path;
815832

816833
if (capture_command(&cp, &out, GIT_MAX_HEXSZ + 1) || out.len)
817-
has_commit = 0;
834+
has_commit.result = 0;
818835

819836
strbuf_release(&out);
820837
}
821838

822-
return has_commit;
839+
return has_commit.result;
823840
}
824841

825842
static int submodule_needs_pushing(const char *path, struct oid_array *commits)

t/t5531-deep-submodule-push.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,16 @@ test_expect_success 'push succeeds if submodule commit disabling recursion from
298298
)
299299
'
300300

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+
301311
test_expect_success 'push fails if recurse submodules option passed as yes' '
302312
(
303313
cd work/gar/bage &&

0 commit comments

Comments
 (0)