mirror of
https://git.proxmox.com/git/libgit2
synced 2025-12-29 20:17:17 +00:00
refs: bring conditional symbolic updates to the frontend
Bring the race detection goodness to symbolic references as well.
This commit is contained in:
parent
911236619b
commit
878fb66f57
@ -67,6 +67,46 @@ GIT_EXTERN(int) git_reference_name_to_id(
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, const char *shorthand);
|
||||
|
||||
/**
|
||||
* Conditionally create a new symbolic reference.
|
||||
*
|
||||
* A symbolic reference is a reference name that refers to another
|
||||
* reference name. If the other name moves, the symbolic name will move,
|
||||
* too. As a simple example, the "HEAD" reference might refer to
|
||||
* "refs/heads/master" while on the "master" branch of a repository.
|
||||
*
|
||||
* The symbolic reference will be created in the repository and written to
|
||||
* the disk. The generated reference object must be freed by the user.
|
||||
*
|
||||
* Valid reference names must follow one of two patterns:
|
||||
*
|
||||
* 1. Top-level names must contain only capital letters and underscores,
|
||||
* and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD").
|
||||
* 2. Names prefixed with "refs/" can be almost anything. You must avoid
|
||||
* the characters '~', '^', ':', '\\', '?', '[', and '*', and the
|
||||
* sequences ".." and "@{" which have special meaning to revparse.
|
||||
*
|
||||
* This function will return an error if a reference already exists with the
|
||||
* given name unless `force` is true, in which case it will be overwritten.
|
||||
*
|
||||
* The signature and message for the reflog will be ignored if the
|
||||
* reference does not belong in the standard set (HEAD, branches and
|
||||
* remote-tracking branches) and it does not have a reflog.
|
||||
*
|
||||
* It will also return an error if the reference's value at the time
|
||||
* of updating does not match the one passed.
|
||||
*
|
||||
* @param out Pointer to the newly created reference
|
||||
* @param repo Repository where that reference will live
|
||||
* @param name The name of the reference
|
||||
* @param target The target of the reference
|
||||
* @param force Overwrite existing references
|
||||
* @param signature The identity that will used to populate the reflog entry
|
||||
* @param log_message The one line long message to be appended to the reflog
|
||||
* @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC, GIT_EMODIFIED or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_symbolic_create_matching(git_reference **out, git_repository *repo, const char *name, const char *target, int force, const git_signature *signature, const char *log_message, const char *old_value);
|
||||
|
||||
/**
|
||||
* Create a new symbolic reference.
|
||||
*
|
||||
|
||||
23
src/refs.c
23
src/refs.c
@ -450,14 +450,15 @@ int git_reference_create(
|
||||
return git_reference_create_matching(ref_out, repo, name, id, force, signature, log_message, NULL);
|
||||
}
|
||||
|
||||
int git_reference_symbolic_create(
|
||||
int git_reference_symbolic_create_matching(
|
||||
git_reference **ref_out,
|
||||
git_repository *repo,
|
||||
const char *name,
|
||||
const char *target,
|
||||
int force,
|
||||
const git_signature *signature,
|
||||
const char *log_message)
|
||||
const char *log_message,
|
||||
const char *old_target)
|
||||
{
|
||||
int error;
|
||||
git_signature *who = NULL;
|
||||
@ -472,12 +473,24 @@ int git_reference_symbolic_create(
|
||||
}
|
||||
|
||||
error = reference__create(
|
||||
ref_out, repo, name, NULL, target, force, signature, log_message, NULL, NULL);
|
||||
ref_out, repo, name, NULL, target, force, signature, log_message, NULL, old_target);
|
||||
|
||||
git_signature_free(who);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_reference_symbolic_create(
|
||||
git_reference **ref_out,
|
||||
git_repository *repo,
|
||||
const char *name,
|
||||
const char *target,
|
||||
int force,
|
||||
const git_signature *signature,
|
||||
const char *log_message)
|
||||
{
|
||||
return git_reference_symbolic_create_matching(ref_out, repo, name, target, force, signature, log_message, NULL);
|
||||
}
|
||||
|
||||
static int ensure_is_an_updatable_direct_reference(git_reference *ref)
|
||||
{
|
||||
if (ref->type == GIT_REF_OID)
|
||||
@ -530,8 +543,8 @@ int git_reference_symbolic_set_target(
|
||||
if ((error = ensure_is_an_updatable_symbolic_reference(ref)) < 0)
|
||||
return error;
|
||||
|
||||
return git_reference_symbolic_create(
|
||||
out, ref->db->repo, ref->name, target, 1, signature, log_message);
|
||||
return git_reference_symbolic_create_matching(
|
||||
out, ref->db->repo, ref->name, target, 1, signature, log_message, ref->target.symbolic);
|
||||
}
|
||||
|
||||
static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
static const char *commit_id = "099fabac3a9ea935598528c27f866e34089c2eff";
|
||||
static const char *refname = "refs/heads/master";
|
||||
static const char *other_refname = "refs/heads/foo";
|
||||
static const char *other_commit_id = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
|
||||
|
||||
static git_repository *g_repo;
|
||||
@ -23,7 +24,6 @@ void test_refs_races__cleanup(void)
|
||||
|
||||
void test_refs_races__create_matching(void)
|
||||
{
|
||||
int error;
|
||||
git_reference *ref, *ref2, *ref3;
|
||||
git_oid id, other_id;
|
||||
|
||||
@ -40,3 +40,22 @@ void test_refs_races__create_matching(void)
|
||||
git_reference_free(ref2);
|
||||
git_reference_free(ref3);
|
||||
}
|
||||
|
||||
void test_refs_races__symbolic_create_matching(void)
|
||||
{
|
||||
git_reference *ref, *ref2, *ref3;
|
||||
git_oid id, other_id;
|
||||
|
||||
git_oid_fromstr(&id, commit_id);
|
||||
git_oid_fromstr(&other_id, other_commit_id);
|
||||
|
||||
cl_git_fail_with(GIT_EMODIFIED, git_reference_symbolic_create_matching(&ref, g_repo, "HEAD", other_refname, 1, NULL, NULL, other_refname));
|
||||
|
||||
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_symbolic_set_target(&ref3, ref, other_refname, NULL, NULL));
|
||||
|
||||
git_reference_free(ref);
|
||||
git_reference_free(ref2);
|
||||
git_reference_free(ref3);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user