Commit 477b3e047426d7ccddb6028416ff0fcc2541a0fd

Patrick Steinhardt 2017-07-10T12:25:43

submodule: refuse lookup in bare repositories While it is technically possible to look up submodules inside of a bare repository by reading the submodule configuration of a specific commit, we do not offer this functionality right now. As such, calling both `git_submodule_lookup` and `git_submodule_foreach` should error out early when these functions encounter a bare repository. While `git_submodule_lookup` already does return an error due to not being able to parse the configuration, `git_submodule_foreach` simply returns success and never invokes the callback function. Fix the issue by having both functions check whether the repository is bare and returning an error in that case.

diff --git a/src/submodule.c b/src/submodule.c
index 0b97a59..6c3e5f6 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -209,6 +209,11 @@ int git_submodule_lookup(
 
 	assert(repo && name);
 
+	if (repo->is_bare) {
+		giterr_set(GITERR_SUBMODULE, "cannot get submodules without a working tree");
+		return -1;
+	}
+
 	if (repo->submodule_cache != NULL) {
 		khiter_t pos = git_strmap_lookup_index(repo->submodule_cache, name);
 		if (git_strmap_valid_index(repo->submodule_cache, pos)) {
@@ -549,6 +554,11 @@ int git_submodule_foreach(
 	int error;
 	size_t i;
 
+	if (repo->is_bare) {
+		giterr_set(GITERR_SUBMODULE, "cannot get submodules without a working tree");
+		return -1;
+	}
+
 	if ((error = git_strmap_alloc(&submodules)) < 0)
 		return error;
 
diff --git a/tests/resources/submodules.git/HEAD b/tests/resources/submodules.git/HEAD
new file mode 100644
index 0000000..cb089cd
--- /dev/null
+++ b/tests/resources/submodules.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/submodules.git/config b/tests/resources/submodules.git/config
new file mode 100644
index 0000000..07d359d
--- /dev/null
+++ b/tests/resources/submodules.git/config
@@ -0,0 +1,4 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = true
diff --git a/tests/resources/submodules.git/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e b/tests/resources/submodules.git/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e
new file mode 100644
index 0000000..2c3c2cb
--- /dev/null
+++ b/tests/resources/submodules.git/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e
@@ -0,0 +1,2 @@
+x%=
+0F])0"I*|-t{?2ilV8$mvkk*FDA=(=|=6	DAv=A}&'O$=
\ No newline at end of file
diff --git a/tests/resources/submodules.git/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 b/tests/resources/submodules.git/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357
new file mode 100644
index 0000000..c85fb55
Binary files /dev/null and b/tests/resources/submodules.git/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 differ
diff --git a/tests/resources/submodules.git/objects/97/896810b3210244a62a82458b8e0819ecfc6850 b/tests/resources/submodules.git/objects/97/896810b3210244a62a82458b8e0819ecfc6850
new file mode 100644
index 0000000..1c8dbdf
--- /dev/null
+++ b/tests/resources/submodules.git/objects/97/896810b3210244a62a82458b8e0819ecfc6850
@@ -0,0 +1,3 @@
+x[
+0E*fʤS	K4ݿwׅ9p2MCFP@u..p!OYdiYU'̕8XbPn6
+ħԞ1[q}0qc[W#1fR:SZ+Y+{tdlvOmu_}5i`	K
\ No newline at end of file
diff --git a/tests/resources/submodules.git/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 b/tests/resources/submodules.git/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888
new file mode 100644
index 0000000..3d78bd6
Binary files /dev/null and b/tests/resources/submodules.git/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 differ
diff --git a/tests/resources/submodules.git/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 b/tests/resources/submodules.git/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818
new file mode 100644
index 0000000..6e0b49e
Binary files /dev/null and b/tests/resources/submodules.git/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 differ
diff --git a/tests/resources/submodules.git/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae b/tests/resources/submodules.git/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae
new file mode 100644
index 0000000..082a589
Binary files /dev/null and b/tests/resources/submodules.git/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae differ
diff --git a/tests/resources/submodules.git/objects/info/packs b/tests/resources/submodules.git/objects/info/packs
new file mode 100644
index 0000000..0785ef6
--- /dev/null
+++ b/tests/resources/submodules.git/objects/info/packs
@@ -0,0 +1,2 @@
+P pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack
+
diff --git a/tests/resources/submodules.git/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx b/tests/resources/submodules.git/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx
new file mode 100644
index 0000000..810fc31
Binary files /dev/null and b/tests/resources/submodules.git/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx differ
diff --git a/tests/resources/submodules.git/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack b/tests/resources/submodules.git/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack
new file mode 100644
index 0000000..c25c4a7
Binary files /dev/null and b/tests/resources/submodules.git/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack differ
diff --git a/tests/resources/submodules.git/refs/heads/master b/tests/resources/submodules.git/refs/heads/master
new file mode 100644
index 0000000..32b9358
--- /dev/null
+++ b/tests/resources/submodules.git/refs/heads/master
@@ -0,0 +1 @@
+97896810b3210244a62a82458b8e0819ecfc6850
diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c
index aa812fb..f84f07c 100644
--- a/tests/submodule/lookup.c
+++ b/tests/submodule/lookup.c
@@ -419,3 +419,29 @@ void test_submodule_lookup__cached(void)
 	git_submodule_free(sm);
 	git_submodule_free(sm2);
 }
+
+void test_submodule_lookup__lookup_in_bare_repository_fails(void)
+{
+	git_submodule *sm;
+
+	cl_git_sandbox_cleanup();
+	g_repo = cl_git_sandbox_init("submodules.git");
+
+	cl_git_fail(git_submodule_lookup(&sm, g_repo, "nonexisting"));
+}
+
+static int foreach_cb(git_submodule *sm, const char *name, void *payload)
+{
+	GIT_UNUSED(sm);
+	GIT_UNUSED(name);
+	GIT_UNUSED(payload);
+	return 0;
+}
+
+void test_submodule_lookup__foreach_in_bare_repository_fails(void)
+{
+	cl_git_sandbox_cleanup();
+	g_repo = cl_git_sandbox_init("submodules.git");
+
+	cl_git_fail(git_submodule_foreach(g_repo, foreach_cb, NULL));
+}