mirror of
https://git.proxmox.com/git/libgit2
synced 2025-12-30 05:47:51 +00:00
refs: check the ref's old value when deleting
Recognize when the reference has changed since we loaded it.
This commit is contained in:
parent
7ee8c7e677
commit
f44fd59ed7
@ -398,8 +398,11 @@ GIT_EXTERN(int) git_reference_rename(
|
||||
* will be immediately removed on disk but the memory will not be freed.
|
||||
* Callers must call `git_reference_free`.
|
||||
*
|
||||
* This function will return an error if the reference has changed
|
||||
* from the time it was looked up.
|
||||
*
|
||||
* @param ref The reference to remove
|
||||
* @return 0 or an error code
|
||||
* @return 0, GIT_EMODIFIED or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_delete(git_reference *ref);
|
||||
|
||||
|
||||
10
src/refs.c
10
src/refs.c
@ -116,7 +116,15 @@ void git_reference_free(git_reference *reference)
|
||||
|
||||
int git_reference_delete(git_reference *ref)
|
||||
{
|
||||
return git_refdb_delete(ref->db, ref->name, NULL, NULL);
|
||||
const git_oid *old_id = NULL;
|
||||
const char *old_target = NULL;
|
||||
|
||||
if (ref->type == GIT_REF_OID)
|
||||
old_id = &ref->target.oid;
|
||||
else
|
||||
old_target = ref->target.symbolic;
|
||||
|
||||
return git_refdb_delete(ref->db, ref->name, old_id, old_target);
|
||||
}
|
||||
|
||||
int git_reference_lookup(git_reference **ref_out,
|
||||
|
||||
@ -59,3 +59,36 @@ void test_refs_races__symbolic_create_matching(void)
|
||||
git_reference_free(ref2);
|
||||
git_reference_free(ref3);
|
||||
}
|
||||
|
||||
void test_refs_races__delete(void)
|
||||
{
|
||||
git_reference *ref, *ref2;
|
||||
git_oid id, other_id;
|
||||
|
||||
git_oid_fromstr(&id, commit_id);
|
||||
git_oid_fromstr(&other_id, other_commit_id);
|
||||
|
||||
/* We can delete a value that matches */
|
||||
cl_git_pass(git_reference_lookup(&ref, g_repo, refname));
|
||||
cl_git_pass(git_reference_delete(ref));
|
||||
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, NULL, refname));
|
||||
cl_git_fail_with(GIT_EMODIFIED, git_reference_delete(ref));
|
||||
|
||||
git_reference_free(ref);
|
||||
git_reference_free(ref2);
|
||||
|
||||
cl_git_pass(git_reference_create(&ref, g_repo, refname, &id, 1, NULL, NULL));
|
||||
git_reference_free(ref);
|
||||
|
||||
/* We cannot delete an oid value that doesn't match */
|
||||
cl_git_pass(git_reference_lookup(&ref, g_repo, refname));
|
||||
cl_git_pass(git_reference_create_matching(&ref2, g_repo, refname, &other_id, 1, NULL, NULL, &id));
|
||||
cl_git_fail_with(GIT_EMODIFIED, git_reference_delete(ref));
|
||||
|
||||
git_reference_free(ref);
|
||||
git_reference_free(ref2);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user