mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-11 06:25:59 +00:00
Brush up the refs API
Changed some more API details and updated documentation. Sketched API for addition/removal of entries. Signed-off-by: Vicent Marti <tanoku@gmail.com>
This commit is contained in:
parent
2de3b35cd4
commit
32054c24a2
@ -44,6 +44,9 @@ GIT_BEGIN_DECL
|
||||
* The reference will be created in the repository and written
|
||||
* to the disk.
|
||||
*
|
||||
* This reference is owned by the repository and shall not
|
||||
* be free'd by the user.
|
||||
*
|
||||
* @param ref_out Pointer to the newly created reference
|
||||
* @param repo Repository where that reference will live
|
||||
* @param name The name of the reference
|
||||
@ -58,6 +61,9 @@ GIT_EXTERN(int) git_reference_create_symbolic(git_reference **ref_out, git_repos
|
||||
* The reference will be created in the repository and written
|
||||
* to the disk.
|
||||
*
|
||||
* This reference is owned by the repository and shall not
|
||||
* be free'd by the user.
|
||||
*
|
||||
* @param ref_out Pointer to the newly created reference
|
||||
* @param repo Repository where that reference will live
|
||||
* @param name The name of the reference
|
||||
@ -119,22 +125,6 @@ GIT_EXTERN(const char *) git_reference_name(git_reference *ref);
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_resolve(git_reference **resolved_ref, git_reference *ref);
|
||||
|
||||
/**
|
||||
* Write a reference back to disk.
|
||||
*
|
||||
* The reference must have a valid name and a valid target
|
||||
* (either direct or symbolic).
|
||||
*
|
||||
* If the reference has been loaded from disk and no changes
|
||||
* have been made, no action will take place.
|
||||
*
|
||||
* The writing to disk is atomic.
|
||||
*
|
||||
* @param ref The reference
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_write(git_reference *ref);
|
||||
|
||||
/**
|
||||
* Get the repository where a reference resides
|
||||
*
|
||||
@ -144,14 +134,13 @@ GIT_EXTERN(int) git_reference_write(git_reference *ref);
|
||||
GIT_EXTERN(git_repository *) git_reference_owner(git_reference *ref);
|
||||
|
||||
/**
|
||||
* Set the target reference of a reference.
|
||||
* Set the symbolic target of a reference.
|
||||
*
|
||||
* This converts the reference into a symbolic
|
||||
* reference.
|
||||
* The reference must be a symbolic reference, otherwise
|
||||
* this method will fail.
|
||||
*
|
||||
* This marks the reference as modified; changes
|
||||
* won't take effect until it is manually written back
|
||||
* to disk.
|
||||
* The reference will be automatically updated in
|
||||
* memory and on disk.
|
||||
*
|
||||
* @param ref The reference
|
||||
* @param target The new target for the reference
|
||||
@ -162,12 +151,11 @@ GIT_EXTERN(int) git_reference_set_target(git_reference *ref, const char *target)
|
||||
/**
|
||||
* Set the OID target of a reference.
|
||||
*
|
||||
* This converts the reference into a direct
|
||||
* reference.
|
||||
* The reference must be a direct reference, otherwise
|
||||
* this method will fail.
|
||||
*
|
||||
* This marks the reference as modified; changes
|
||||
* won't take effect until it is manually written back
|
||||
* to disk.
|
||||
* The reference will be automatically updated in
|
||||
* memory and on disk.
|
||||
*
|
||||
* @param ref The reference
|
||||
* @param target The new target OID for the reference
|
||||
@ -175,6 +163,30 @@ GIT_EXTERN(int) git_reference_set_target(git_reference *ref, const char *target)
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
|
||||
|
||||
/**
|
||||
* Rename an existing reference
|
||||
*
|
||||
* This method works for both direct and symbolic references.
|
||||
* The new name will be checked for validity and may be
|
||||
* modified into a normalized form.
|
||||
*
|
||||
* The refernece will be immediately renamed in-memory
|
||||
* and on disk.
|
||||
*
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name);
|
||||
|
||||
/**
|
||||
* Delete an existing reference
|
||||
*
|
||||
* This method works for both direct and symbolic references.
|
||||
*
|
||||
* The reference will be immediately removed on disk and from
|
||||
* memory. The given reference pointer will no longer be valid.
|
||||
*
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_delete(git_reference *ref);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
90
src/refs.c
90
src/refs.c
@ -30,6 +30,8 @@
|
||||
|
||||
#define MAX_NESTING_LEVEL 5
|
||||
|
||||
static int reference_write(git_reference *ref);
|
||||
|
||||
static const int default_table_size = 32;
|
||||
|
||||
static uint32_t reftable_hash(const void *key, int hash_id)
|
||||
@ -43,17 +45,6 @@ static uint32_t reftable_hash(const void *key, int hash_id)
|
||||
return git__hash(key, strlen((const char *)key), hash_seeds[hash_id]);
|
||||
}
|
||||
|
||||
static int check_refname(const char *name)
|
||||
{
|
||||
/*
|
||||
* TODO: To be implemented
|
||||
* Check if the given name is a valid name
|
||||
* for a reference
|
||||
*/
|
||||
|
||||
return name ? GIT_SUCCESS : GIT_ERROR;
|
||||
}
|
||||
|
||||
static void reference_free(git_reference *reference)
|
||||
{
|
||||
if (reference == NULL)
|
||||
@ -68,7 +59,7 @@ static void reference_free(git_reference *reference)
|
||||
free(reference);
|
||||
}
|
||||
|
||||
static int reference__create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type) {
|
||||
static int reference_create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type) {
|
||||
char normalized[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
int error = GIT_SUCCESS;
|
||||
git_reference *reference = NULL;
|
||||
@ -111,7 +102,7 @@ int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo,
|
||||
int error = GIT_SUCCESS;
|
||||
git_reference *ref = NULL;
|
||||
|
||||
error = reference__create(&ref, repo, name, GIT_REF_SYMBOLIC);
|
||||
error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -120,14 +111,11 @@ int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo,
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
/* set the target; this will write the reference on disk */
|
||||
error = git_reference_set_target(ref, normalized);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_reference_write(ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*ref_out = ref;
|
||||
|
||||
return error;
|
||||
@ -142,18 +130,15 @@ int git_reference_create_oid(git_reference **ref_out, git_repository *repo, cons
|
||||
int error = GIT_SUCCESS;
|
||||
git_reference *ref = NULL;
|
||||
|
||||
error = reference__create(&ref, repo, name, GIT_REF_OID);
|
||||
error = reference_create(&ref, repo, name, GIT_REF_OID);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
/* set the oid; this will write the reference on disk */
|
||||
error = git_reference_set_oid(ref, id);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_reference_write(ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*ref_out = ref;
|
||||
|
||||
return error;
|
||||
@ -168,7 +153,6 @@ static int parse_sym_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
const unsigned int header_len = strlen(GIT_SYMREF);
|
||||
const char *refname_start;
|
||||
char *eol;
|
||||
int error;
|
||||
|
||||
refname_start = (const char *)file_content->data;
|
||||
|
||||
@ -182,9 +166,9 @@ static int parse_sym_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
|
||||
refname_start += header_len;
|
||||
|
||||
error = git_reference_set_target(ref, refname_start);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
ref->target.ref = git__strdup(refname_start);
|
||||
if (ref->target.ref == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
/* remove newline at the end of file */
|
||||
eol = strchr(ref->target.ref, '\n');
|
||||
@ -202,8 +186,6 @@ static int parse_oid_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
{
|
||||
char *buffer;
|
||||
git_oid id;
|
||||
int error;
|
||||
|
||||
buffer = (char *)file_content->data;
|
||||
|
||||
/* File format: 40 chars (OID) + newline */
|
||||
@ -213,9 +195,7 @@ static int parse_oid_ref(git_reference *ref, gitfo_buf *file_content)
|
||||
if (git_oid_mkstr(&id, buffer) < GIT_SUCCESS)
|
||||
return GIT_EREFCORRUPTED;
|
||||
|
||||
error = git_reference_set_oid(ref, &id);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
git_oid_cpy(&ref->target.oid, &id);
|
||||
|
||||
buffer = buffer + GIT_OID_HEXSZ;
|
||||
if (*buffer == '\r')
|
||||
@ -265,21 +245,19 @@ static int lookup_loose_ref(
|
||||
goto cleanup;
|
||||
|
||||
if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0) {
|
||||
error = reference__create(&ref, repo, name, GIT_REF_SYMBOLIC);
|
||||
error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = parse_sym_ref(ref, &ref_file);
|
||||
} else {
|
||||
error = reference__create(&ref, repo, name, GIT_REF_OID);
|
||||
error = reference_create(&ref, repo, name, GIT_REF_OID);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = parse_oid_ref(ref, &ref_file);
|
||||
}
|
||||
|
||||
ref->modified = 0;
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -397,16 +375,13 @@ static int parse_packed_line(
|
||||
if (refname[refname_len - 1] == '\r')
|
||||
refname[refname_len - 1] = 0;
|
||||
|
||||
error = reference__create(&ref, repo, refname, GIT_REF_OID);
|
||||
error = reference_create(&ref, repo, refname, GIT_REF_OID);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_reference_set_oid(ref, &id);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
git_oid_cpy(&ref->target.oid, &id);
|
||||
|
||||
ref->packed = 1;
|
||||
ref->modified = 0;
|
||||
|
||||
*ref_out = ref;
|
||||
*buffer_out = refname_end + 1;
|
||||
@ -496,9 +471,7 @@ int git_reference_set_oid(git_reference *ref, const git_oid *id)
|
||||
|
||||
git_oid_cpy(&ref->target.oid, id);
|
||||
|
||||
ref->modified = 1;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
return reference_write(ref);
|
||||
}
|
||||
|
||||
int git_reference_set_target(git_reference *ref, const char *target)
|
||||
@ -511,9 +484,7 @@ int git_reference_set_target(git_reference *ref, const char *target)
|
||||
if (ref->target.ref == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
ref->modified = 1;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
return reference_write(ref);
|
||||
}
|
||||
|
||||
const git_oid *git_reference_oid(git_reference *ref)
|
||||
@ -528,6 +499,8 @@ const git_oid *git_reference_oid(git_reference *ref)
|
||||
|
||||
const char *git_reference_target(git_reference *ref)
|
||||
{
|
||||
assert(ref);
|
||||
|
||||
if (ref->type != GIT_REF_SYMBOLIC)
|
||||
return NULL;
|
||||
|
||||
@ -576,19 +549,14 @@ int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
|
||||
return GIT_ETOONESTEDSYMREF;
|
||||
}
|
||||
|
||||
int git_reference_write(git_reference *ref)
|
||||
static int reference_write(git_reference *ref)
|
||||
{
|
||||
git_filebuf file;
|
||||
git_reference *looked_up_reference;
|
||||
char ref_path[GIT_PATH_MAX];
|
||||
int error, contents_size;
|
||||
char *ref_contents = NULL;
|
||||
|
||||
if (ref->type == GIT_REF_INVALID || ref->type == GIT_REF_ANY)
|
||||
return GIT_EINVALIDREFSTATE;
|
||||
|
||||
if (!ref->modified)
|
||||
return GIT_SUCCESS;
|
||||
assert(ref->type == GIT_REF_OID || ref->type == GIT_REF_SYMBOLIC);
|
||||
|
||||
git__joinpath(ref_path, ref->owner->path_repository, ref->name);
|
||||
|
||||
@ -619,27 +587,25 @@ int git_reference_write(git_reference *ref)
|
||||
strcat(ref_contents, ref->target.ref);
|
||||
}
|
||||
|
||||
/* TODO: win32 carriage return when writing references in Windows? */
|
||||
ref_contents[contents_size - 1] = '\n';
|
||||
|
||||
if ((error = git_filebuf_write(&file, ref_contents, contents_size)) < GIT_SUCCESS)
|
||||
goto error_cleanup;
|
||||
|
||||
error = git_filebuf_commit(&file);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto unlock;
|
||||
|
||||
looked_up_reference = git_hashtable_lookup(ref->owner->references.cache, ref->name);
|
||||
|
||||
if (looked_up_reference == NULL) {
|
||||
error = git_hashtable_insert(ref->owner->references.cache, ref->name, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
goto unlock;
|
||||
|
||||
goto cleanup;
|
||||
free(ref_contents);
|
||||
return GIT_SUCCESS;
|
||||
|
||||
unlock:
|
||||
git_filelock_unlock(&lock);
|
||||
|
||||
cleanup:
|
||||
git_filebuf_cleanup(&lock);
|
||||
free(ref_contents);
|
||||
return error;
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ struct git_reference {
|
||||
git_rtype type;
|
||||
char *name;
|
||||
|
||||
unsigned packed:1,
|
||||
modified:1;
|
||||
unsigned packed:1;
|
||||
|
||||
union {
|
||||
char *ref;
|
||||
|
Loading…
Reference in New Issue
Block a user