diff options
author | Vicent Marti <vicent@github.com> | 2013-12-18 09:33:45 -0800 |
---|---|---|
committer | Vicent Marti <vicent@github.com> | 2013-12-18 09:33:45 -0800 |
commit | 4e1f517c61fef323b9cb3acedd19ce7859a8e546 (patch) | |
tree | 87823d6c36e00b3098069142ba9e630e2570f1b7 /src/refs.c | |
parent | a7ecd1a9e36df5d6843c1863542c02d777e9e8b5 (diff) | |
parent | f21051297cc698644ea0dc9c7122ec944dba2863 (diff) | |
download | libgit2-4e1f517c61fef323b9cb3acedd19ce7859a8e546.tar.gz |
Merge pull request #1920 from libgit2/cmn/ref-with-log
Reference operations with log
Diffstat (limited to 'src/refs.c')
-rw-r--r-- | src/refs.c | 213 |
1 files changed, 157 insertions, 56 deletions
diff --git a/src/refs.c b/src/refs.c index 4f3a557c6..83343f41b 100644 --- a/src/refs.c +++ b/src/refs.c @@ -21,6 +21,7 @@ #include <git2/refs.h> #include <git2/refdb.h> #include <git2/sys/refs.h> +#include <git2/signature.h> GIT__USE_STRMAP; @@ -328,13 +329,18 @@ static int reference__create( const char *name, const git_oid *oid, const char *symbolic, - int force) + int force, + const git_signature *signature, + const char *log_message) { char normalized[GIT_REFNAME_MAX]; git_refdb *refdb; git_reference *ref = NULL; int error = 0; + assert(repo && name); + assert(symbolic || signature); + if (ref_out) *ref_out = NULL; @@ -347,15 +353,34 @@ static int reference__create( return error; if (oid != NULL) { + git_odb *odb; + assert(symbolic == NULL); - ref = git_reference__alloc(normalized, oid, NULL); + + /* Sanity check the reference being created - target must exist. */ + if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) + return error; + + if (!git_odb_exists(odb, oid)) { + giterr_set(GITERR_REFERENCE, + "Target OID for the reference doesn't exist on the repository"); + return -1; + } + + ref = git_reference__alloc(name, oid, NULL); } else { - ref = git_reference__alloc_symbolic(normalized, symbolic); + char normalized_target[GIT_REFNAME_MAX]; + + if ((error = git_reference__normalize_name_lax( + normalized_target, sizeof(normalized_target), symbolic)) < 0) + return error; + + ref = git_reference__alloc_symbolic(name, normalized_target); } GITERR_CHECK_ALLOC(ref); - if ((error = git_refdb_write(refdb, ref, force)) < 0) { + if ((error = git_refdb_write(refdb, ref, force, signature, log_message)) < 0) { git_reference_free(ref); return error; } @@ -375,22 +400,37 @@ int git_reference_create( const git_oid *oid, int force) { - git_odb *odb; - int error = 0; + git_signature *who; + int error; - assert(repo && name && oid); + assert(oid); - /* Sanity check the reference being created - target must exist. */ - if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) + /* Should we return an error if there is no default? */ + if (((error = git_signature_default(&who, repo)) < 0) && + ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) { return error; - - if (!git_odb_exists(odb, oid)) { - giterr_set(GITERR_REFERENCE, - "Target OID for the reference doesn't exist on the repository"); - return -1; } - return reference__create(ref_out, repo, name, oid, NULL, force); + error = reference__create(ref_out, repo, name, oid, NULL, force, who, NULL); + + git_signature_free(who); + + return error; +} + +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( @@ -400,16 +440,17 @@ int git_reference_symbolic_create( const char *target, int force) { - char normalized[GIT_REFNAME_MAX]; - int error = 0; - - assert(repo && name && target); + assert(target); + return reference__create(ref_out, repo, name, NULL, target, force, NULL, NULL); +} - if ((error = git_reference__normalize_name_lax( - normalized, sizeof(normalized), target)) < 0) - return error; +static int ensure_is_an_updatable_direct_reference(git_reference *ref) +{ + if (ref->type == GIT_REF_OID) + return 0; - return reference__create(ref_out, repo, name, NULL, normalized, force); + giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference"); + return -1; } int git_reference_set_target( @@ -417,43 +458,68 @@ int git_reference_set_target( git_reference *ref, const git_oid *id) { + int error; + assert(out && ref && id); - if (ref->type != GIT_REF_OID) { - giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference"); - return -1; - } + if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) + return error; return git_reference_create(out, ref->db->repo, ref->name, id, 1); } +int git_reference_set_target_with_log( + git_reference **out, + git_reference *ref, + const git_oid *id, + const git_signature *signature, + const char *log_message) +{ + int error; + + assert(out && ref && id); + assert(signature && log_message); + + if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) + return error; + + return git_reference_create_with_log( + out, ref->db->repo, ref->name, id, 1, signature, log_message); +} + +static int ensure_is_an_updatable_symbolic_reference(git_reference *ref) +{ + if (ref->type == GIT_REF_SYMBOLIC) + return 0; + + giterr_set(GITERR_REFERENCE, "Cannot set symbolic target on a direct reference"); + return -1; +} + int git_reference_symbolic_set_target( git_reference **out, git_reference *ref, const char *target) { + int error; + assert(out && ref && target); - if (ref->type != GIT_REF_SYMBOLIC) { - giterr_set(GITERR_REFERENCE, - "Cannot set symbolic target on a direct reference"); - return -1; - } + 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); } -int git_reference_rename( - git_reference **out, - git_reference *ref, - const char *new_name, - int force) +static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force, + const git_signature *signature, const char *message) { unsigned int normalization_flags; char normalized[GIT_REFNAME_MAX]; bool should_head_be_updated = false; int error = 0; - int reference_has_log; + + assert(ref && new_name && signature); normalization_flags = ref->type == GIT_REF_SYMBOLIC ? GIT_REF_FORMAT_ALLOW_ONELEVEL : GIT_REF_FORMAT_NORMAL; @@ -462,13 +528,14 @@ int git_reference_rename( normalized, sizeof(normalized), new_name, normalization_flags)) < 0) return error; + /* Check if we have to update HEAD. */ if ((error = git_branch_is_head(ref)) < 0) return error; should_head_be_updated = (error > 0); - if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force)) < 0) + if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force, signature, message)) < 0) return error; /* Update HEAD it was pointing to the reference being renamed */ @@ -478,15 +545,41 @@ int git_reference_rename( return error; } - /* Rename the reflog file, if it exists. */ - reference_has_log = git_reference_has_log(ref); - if (reference_has_log < 0) - return reference_has_log; + return 0; +} + + +int git_reference_rename( + git_reference **out, + git_reference *ref, + const char *new_name, + int force) +{ + git_signature *who; + int error; - if (reference_has_log && (error = git_reflog_rename(git_reference_owner(ref), git_reference_name(ref), new_name)) < 0) + /* Should we return an error if there is no default? */ + if (((error = git_signature_default(&who, ref->db->repo)) < 0) && + ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) { return error; + } - return 0; + error = reference__rename(out, ref, new_name, force, who, NULL); + + git_signature_free(who); + + return error; +} + +int git_reference_rename_with_log( + git_reference **out, + git_reference *ref, + const char *new_name, + int force, + const git_signature *who, + const char * message) +{ + return reference__rename(out, ref, new_name, force, who, message); } int git_reference_resolve(git_reference **ref_out, const git_reference *ref) @@ -956,22 +1049,30 @@ int git_reference__update_terminal( return reference__update_terminal(repo, ref_name, oid, 0); } -int git_reference_has_log( - git_reference *ref) +int git_reference_has_log(git_repository *repo, const char *refname) { - git_buf path = GIT_BUF_INIT; - int result; + int error; + git_refdb *refdb; - assert(ref); + assert(repo && refname); - if (git_buf_join_n(&path, '/', 3, ref->db->repo->path_repository, - GIT_REFLOG_DIR, ref->name) < 0) - return -1; + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + return error; - result = git_path_isfile(git_buf_cstr(&path)); - git_buf_free(&path); + return git_refdb_has_log(refdb, refname); +} + +int git_reference_ensure_log(git_repository *repo, const char *refname) +{ + int error; + git_refdb *refdb; + + assert(repo && refname); + + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + return error; - return result; + return git_refdb_ensure_log(refdb, refname); } int git_reference__is_branch(const char *ref_name) |