mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-26 13:31:18 +00:00
refs: Introduce git_reference_create_with_log()
This commit is contained in:
parent
92f95a170c
commit
bba25f39a2
@ -130,6 +130,49 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force);
|
GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new direct reference and update the reflog with a given
|
||||||
|
* message.
|
||||||
|
*
|
||||||
|
* A direct reference (also called an object id reference) refers directly
|
||||||
|
* to a specific object id (a.k.a. OID or SHA) in the repository. The id
|
||||||
|
* permanently refers to the object (although the reference itself can be
|
||||||
|
* moved). For example, in libgit2 the direct ref "refs/tags/v0.17.0"
|
||||||
|
* refers to OID 5b9fac39d8a76b9139667c26a63e6b3f204b3977.
|
||||||
|
*
|
||||||
|
* The direct 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.
|
||||||
|
*
|
||||||
|
* @param out Pointer to the newly created reference
|
||||||
|
* @param repo Repository where that reference will live
|
||||||
|
* @param name The name of the reference
|
||||||
|
* @param id The object id pointed to by 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 that has to be appended
|
||||||
|
* to the reflog
|
||||||
|
* @return 0 on success, EEXISTS, EINVALIDSPEC or an error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_reference_create_with_log(
|
||||||
|
git_reference **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *name,
|
||||||
|
const git_oid *id,
|
||||||
|
int force,
|
||||||
|
const git_signature *signature,
|
||||||
|
const char *log_message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the OID pointed to by a direct reference.
|
* Get the OID pointed to by a direct reference.
|
||||||
*
|
*
|
||||||
|
58
src/refs.c
58
src/refs.c
@ -322,13 +322,44 @@ const char *git_reference_symbolic_target(const git_reference *ref)
|
|||||||
return ref->target.symbolic;
|
return ref->target.symbolic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int feed_reflog(
|
||||||
|
const git_reference *ref,
|
||||||
|
const git_signature *signature,
|
||||||
|
const char *log_message)
|
||||||
|
{
|
||||||
|
|
||||||
|
git_reflog *reflog = NULL;
|
||||||
|
git_oid peeled_ref_oid;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((error = git_reflog_read(&reflog, ref)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((error = git_reference_name_to_id(&peeled_ref_oid,
|
||||||
|
git_reference_owner(ref), git_reference_name(ref))) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((error = git_reflog_append(reflog, &peeled_ref_oid,
|
||||||
|
signature, log_message)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
error = git_reflog_write(reflog);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
git_reflog_free(reflog);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int reference__create(
|
static int reference__create(
|
||||||
git_reference **ref_out,
|
git_reference **ref_out,
|
||||||
git_repository *repo,
|
git_repository *repo,
|
||||||
const char *name,
|
const char *name,
|
||||||
const git_oid *oid,
|
const git_oid *oid,
|
||||||
const char *symbolic,
|
const char *symbolic,
|
||||||
int force)
|
int force,
|
||||||
|
const git_signature *signature,
|
||||||
|
const char *log_message)
|
||||||
{
|
{
|
||||||
char normalized[GIT_REFNAME_MAX];
|
char normalized[GIT_REFNAME_MAX];
|
||||||
git_refdb *refdb;
|
git_refdb *refdb;
|
||||||
@ -336,6 +367,7 @@ static int reference__create(
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
assert(repo && name);
|
assert(repo && name);
|
||||||
|
assert(!((signature == NULL) ^ (log_message == NULL)));
|
||||||
|
|
||||||
if (ref_out)
|
if (ref_out)
|
||||||
*ref_out = NULL;
|
*ref_out = NULL;
|
||||||
@ -381,6 +413,11 @@ static int reference__create(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (log_message && (error = feed_reflog(ref, signature, log_message)) < 0) {
|
||||||
|
git_reference_free(ref);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
if (ref_out == NULL)
|
if (ref_out == NULL)
|
||||||
git_reference_free(ref);
|
git_reference_free(ref);
|
||||||
else
|
else
|
||||||
@ -398,7 +435,22 @@ int git_reference_create(
|
|||||||
{
|
{
|
||||||
assert(oid);
|
assert(oid);
|
||||||
|
|
||||||
return reference__create(ref_out, repo, name, oid, NULL, force);
|
return reference__create(ref_out, repo, name, oid, NULL, force, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_reference_create_with_log(
|
||||||
|
git_reference **ref_out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *name,
|
||||||
|
const git_oid *oid,
|
||||||
|
int force,
|
||||||
|
const git_signature *signature,
|
||||||
|
const char *log_message)
|
||||||
|
{
|
||||||
|
assert(oid && signature && log_message);
|
||||||
|
|
||||||
|
return reference__create(
|
||||||
|
ref_out, repo, name, oid, NULL, force, signature, log_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_reference_symbolic_create(
|
int git_reference_symbolic_create(
|
||||||
@ -410,7 +462,7 @@ int git_reference_symbolic_create(
|
|||||||
{
|
{
|
||||||
assert(target);
|
assert(target);
|
||||||
|
|
||||||
return reference__create(ref_out, repo, name, NULL, target, force);
|
return reference__create(ref_out, repo, name, NULL, target, force, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_reference_set_target(
|
int git_reference_set_target(
|
||||||
|
52
tests/refs/createwithlog.c
Normal file
52
tests/refs/createwithlog.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
|
||||||
|
#include "repository.h"
|
||||||
|
#include "git2/reflog.h"
|
||||||
|
#include "reflog.h"
|
||||||
|
#include "ref_helpers.h"
|
||||||
|
|
||||||
|
static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750";
|
||||||
|
static const char *current_head_target = "refs/heads/master";
|
||||||
|
|
||||||
|
static git_repository *g_repo;
|
||||||
|
|
||||||
|
void test_refs_createwithlog__initialize(void)
|
||||||
|
{
|
||||||
|
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_refs_createwithlog__cleanup(void)
|
||||||
|
{
|
||||||
|
cl_git_sandbox_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_refs_createwithlog__creating_a_direct_reference_adds_a_reflog_entry(void)
|
||||||
|
{
|
||||||
|
git_reference *reference;
|
||||||
|
git_oid id;
|
||||||
|
git_signature *signature;
|
||||||
|
git_reflog *reflog;
|
||||||
|
const git_reflog_entry *entry;
|
||||||
|
|
||||||
|
const char *name = "refs/heads/new-head";
|
||||||
|
const char *message = "You've been logged, mate!";
|
||||||
|
|
||||||
|
git_oid_fromstr(&id, current_master_tip);
|
||||||
|
|
||||||
|
cl_git_pass(git_signature_now(&signature, "foo", "foo@bar"));
|
||||||
|
|
||||||
|
cl_git_pass(
|
||||||
|
git_reference_create_with_log(&reference, g_repo, name, &id, 0, signature, message));
|
||||||
|
|
||||||
|
cl_git_pass(git_reflog_read(&reflog, reference));
|
||||||
|
cl_assert_equal_sz(1, git_reflog_entrycount(reflog));
|
||||||
|
|
||||||
|
entry = git_reflog_entry_byindex(reflog, 0);
|
||||||
|
cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0);
|
||||||
|
cl_assert(git_oid_cmp(&id, &entry->oid_cur) == 0);
|
||||||
|
cl_assert_equal_s(message, entry->msg);
|
||||||
|
|
||||||
|
git_reflog_free(reflog);
|
||||||
|
git_reference_free(reference);
|
||||||
|
git_signature_free(signature);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user