summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2020-01-17 08:32:37 +0100
committerGitHub <noreply@github.com>2020-01-17 08:32:37 +0100
commit47ac1187aaa53050c46056a4daf9a01916263da4 (patch)
tree4fc528463747aa24fcc09d21d005271995b46b37
parenta129941ac162e81f59d57737e2debcc9e456858d (diff)
parent852c83ee44d6d53137f12443c9f82f70bbabbadc (diff)
downloadlibgit2-47ac1187aaa53050c46056a4daf9a01916263da4.tar.gz
Merge pull request #5360 from josharian/fix-5357
refs: refuse to delete HEAD
-rw-r--r--src/refs.c5
-rw-r--r--tests/iterator/workdir.c3
-rw-r--r--tests/refs/delete.c11
-rw-r--r--tests/refs/list.c4
-rw-r--r--tests/refs/races.c14
-rw-r--r--tests/resources/testrepo/.gitted/refs/symref1
6 files changed, 28 insertions, 10 deletions
diff --git a/src/refs.c b/src/refs.c
index 29dd1bdeb..633d83abd 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -145,6 +145,11 @@ int git_reference_delete(git_reference *ref)
const git_oid *old_id = NULL;
const char *old_target = NULL;
+ if (!strcmp(ref->name, "HEAD")) {
+ git_error_set(GIT_ERROR_REFERENCE, "cannot delete HEAD");
+ return GIT_ERROR;
+ }
+
if (ref->type == GIT_REFERENCE_DIRECT)
old_id = &ref->target.oid;
else
diff --git a/tests/iterator/workdir.c b/tests/iterator/workdir.c
index 926cc6af0..72f8bf42c 100644
--- a/tests/iterator/workdir.c
+++ b/tests/iterator/workdir.c
@@ -620,6 +620,7 @@ void test_iterator_workdir__filesystem2(void)
"heads/subtrees",
"heads/test",
"heads/testrepo-worktree",
+ "symref",
"tags/e90810b",
"tags/foo/bar",
"tags/foo/foo/bar",
@@ -632,7 +633,7 @@ void test_iterator_workdir__filesystem2(void)
cl_git_pass(git_iterator_for_filesystem(
&i, "testrepo/.git/refs", NULL));
- expect_iterator_items(i, 16, expect_base, 16, expect_base);
+ expect_iterator_items(i, 17, expect_base, 17, expect_base);
git_iterator_free(i);
}
diff --git a/tests/refs/delete.c b/tests/refs/delete.c
index a33449641..3e99a7959 100644
--- a/tests/refs/delete.c
+++ b/tests/refs/delete.c
@@ -105,3 +105,14 @@ void test_refs_delete__remove(void)
cl_git_fail(git_reference_lookup(&ref, g_repo, packed_test_head_name));
}
+
+void test_refs_delete__head(void)
+{
+ git_reference *ref;
+
+ /* Check that it is not possible to delete HEAD */
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
+ cl_git_fail(git_reference_delete(ref));
+ git_reference_free(ref);
+}
diff --git a/tests/refs/list.c b/tests/refs/list.c
index 3e8c82c94..725d38161 100644
--- a/tests/refs/list.c
+++ b/tests/refs/list.c
@@ -36,7 +36,7 @@ void test_refs_list__all(void)
/* We have exactly 12 refs in total if we include the packed ones:
* there is a reference that exists both in the packfile and as
* loose, but we only list it once */
- cl_assert_equal_i((int)ref_list.count, 18);
+ cl_assert_equal_i((int)ref_list.count, 19);
git_strarray_free(&ref_list);
}
@@ -51,7 +51,7 @@ void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_exten
"144344043ba4d4a405da03de3844aa829ae8be0e\n");
cl_git_pass(git_reference_list(&ref_list, g_repo));
- cl_assert_equal_i((int)ref_list.count, 18);
+ cl_assert_equal_i((int)ref_list.count, 19);
git_strarray_free(&ref_list);
}
diff --git a/tests/refs/races.c b/tests/refs/races.c
index fbecf4a75..04a1bc17b 100644
--- a/tests/refs/races.c
+++ b/tests/refs/races.c
@@ -74,8 +74,8 @@ void test_refs_races__delete(void)
git_reference_free(ref);
/* We cannot delete a symbolic value that doesn't match */
- cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
- cl_git_pass(git_reference_symbolic_create_matching(&ref2, g_repo, "HEAD", other_refname, 1, NULL, refname));
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/symref"));
+ cl_git_pass(git_reference_symbolic_create_matching(&ref2, g_repo, "refs/symref", other_refname, 1, NULL, refname));
cl_git_fail_with(GIT_EMODIFIED, git_reference_delete(ref));
git_reference_free(ref);
@@ -131,19 +131,19 @@ void test_refs_races__switch_symbolic_to_oid(void)
git_oid_fromstr(&other_id, other_commit_id);
/* Removing a symbolic ref when it's currently direct should fail */
- cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
- cl_git_pass(git_reference_create(&ref2, g_repo, "HEAD", &id, 1, NULL));
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/symref"));
+ cl_git_pass(git_reference_create(&ref2, g_repo, "refs/symref", &id, 1, NULL));
cl_git_fail_with(GIT_EMODIFIED, git_reference_delete(ref));
git_reference_free(ref);
git_reference_free(ref2);
- cl_git_pass(git_reference_symbolic_create(&ref, g_repo, "HEAD", refname, 1, NULL));
+ cl_git_pass(git_reference_symbolic_create(&ref, g_repo, "refs/symref", refname, 1, NULL));
git_reference_free(ref);
/* Updating a symbolic ref when it's currently direct should fail */
- cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
- cl_git_pass(git_reference_create(&ref2, g_repo, "HEAD", &id, 1, NULL));
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/symref"));
+ cl_git_pass(git_reference_create(&ref2, g_repo, "refs/symref", &id, 1, NULL));
cl_git_fail_with(GIT_EMODIFIED, git_reference_symbolic_set_target(&ref3, ref, other_refname, NULL));
git_reference_free(ref);
diff --git a/tests/resources/testrepo/.gitted/refs/symref b/tests/resources/testrepo/.gitted/refs/symref
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests/resources/testrepo/.gitted/refs/symref
@@ -0,0 +1 @@
+ref: refs/heads/master