diff options
Diffstat (limited to 'src/refs.c')
| -rw-r--r-- | src/refs.c | 153 |
1 files changed, 85 insertions, 68 deletions
diff --git a/src/refs.c b/src/refs.c index e3157529b..415918600 100644 --- a/src/refs.c +++ b/src/refs.c @@ -416,12 +416,22 @@ static int reference__create( return 0; } +int configured_ident(git_signature **out, const git_repository *repo) +{ + if (repo->ident_name && repo->ident_email) + return git_signature_now(out, repo->ident_name, repo->ident_email); + + /* if not configured let us fall-through to the next method */ + return -1; +} + int git_reference__log_signature(git_signature **out, git_repository *repo) { int error; git_signature *who; - if(((error = git_signature_default(&who, repo)) < 0) && + if(((error = configured_ident(&who, repo)) < 0) && + ((error = git_signature_default(&who, repo)) < 0) && ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) return error; @@ -436,7 +446,6 @@ int git_reference_create_matching( const git_oid *id, int force, const git_oid *old_id, - const git_signature *signature, const char *log_message) { @@ -445,15 +454,11 @@ int git_reference_create_matching( assert(id); - if (!signature) { - if ((error = git_reference__log_signature(&who, repo)) < 0) - return error; - else - signature = who; - } + if ((error = git_reference__log_signature(&who, repo)) < 0) + return error; error = reference__create( - ref_out, repo, name, id, NULL, force, signature, log_message, old_id, NULL); + ref_out, repo, name, id, NULL, force, who, log_message, old_id, NULL); git_signature_free(who); return error; @@ -465,10 +470,9 @@ int git_reference_create( const char *name, const git_oid *id, int force, - const git_signature *signature, const char *log_message) { - return git_reference_create_matching(ref_out, repo, name, id, force, NULL, signature, log_message); + return git_reference_create_matching(ref_out, repo, name, id, force, NULL, log_message); } int git_reference_symbolic_create_matching( @@ -478,7 +482,6 @@ int git_reference_symbolic_create_matching( const char *target, int force, const char *old_target, - const git_signature *signature, const char *log_message) { int error; @@ -486,15 +489,11 @@ int git_reference_symbolic_create_matching( assert(target); - if (!signature) { - if ((error = git_reference__log_signature(&who, repo)) < 0) - return error; - else - signature = who; - } + if ((error = git_reference__log_signature(&who, repo)) < 0) + return error; error = reference__create( - ref_out, repo, name, NULL, target, force, signature, log_message, NULL, old_target); + ref_out, repo, name, NULL, target, force, who, log_message, NULL, old_target); git_signature_free(who); return error; @@ -506,10 +505,9 @@ int git_reference_symbolic_create( 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, NULL, signature, log_message); + return git_reference_symbolic_create_matching(ref_out, repo, name, target, force, NULL, log_message); } static int ensure_is_an_updatable_direct_reference(git_reference *ref) @@ -525,7 +523,6 @@ int git_reference_set_target( git_reference **out, git_reference *ref, const git_oid *id, - const git_signature *signature, const char *log_message) { int error; @@ -538,7 +535,7 @@ int git_reference_set_target( if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) return error; - return git_reference_create_matching(out, repo, ref->name, id, 1, &ref->target.oid, signature, log_message); + return git_reference_create_matching(out, repo, ref->name, id, 1, &ref->target.oid, log_message); } static int ensure_is_an_updatable_symbolic_reference(git_reference *ref) @@ -554,7 +551,6 @@ int git_reference_symbolic_set_target( git_reference **out, git_reference *ref, const char *target, - const git_signature *signature, const char *log_message) { int error; @@ -565,7 +561,7 @@ int git_reference_symbolic_set_target( return error; return git_reference_symbolic_create_matching( - out, ref->db->repo, ref->name, target, 1, ref->target.symbolic, signature, log_message); + out, ref->db->repo, ref->name, target, 1, ref->target.symbolic, log_message); } static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force, @@ -593,7 +589,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char /* Update HEAD it was pointing to the reference being renamed */ if (should_head_be_updated && - (error = git_repository_set_head(ref->db->repo, normalized, signature, message)) < 0) { + (error = git_repository_set_head(ref->db->repo, normalized, message)) < 0) { giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference"); return error; } @@ -607,23 +603,16 @@ int git_reference_rename( git_reference *ref, const char *new_name, int force, - const git_signature *signature, const char *log_message) { - git_signature *who = (git_signature*)signature; + git_signature *who; int error; - /* Should we return an error if there is no default? */ - if (!who && - ((error = git_signature_default(&who, ref->db->repo)) < 0) && - ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) { + if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0) return error; - } error = reference__rename(out, ref, new_name, force, who, log_message); - - if (!signature) - git_signature_free(who); + git_signature_free(who); return error; } @@ -1038,13 +1027,11 @@ int git_reference_cmp( return git_oid__cmp(&ref1->target.oid, &ref2->target.oid); } -static int reference__update_terminal( - git_repository *repo, - const char *ref_name, - const git_oid *oid, - int nesting, - const git_signature *signature, - const char *log_message) +/** + * Get the end of a chain of references. If the final one is not + * found, we return the reference just before that. + */ +static int get_terminal(git_reference **out, git_repository *repo, const char *ref_name, int nesting) { git_reference *ref; int error = 0; @@ -1054,27 +1041,23 @@ static int reference__update_terminal( return GIT_ENOTFOUND; } - error = git_reference_lookup(&ref, repo, ref_name); - - /* If we haven't found the reference at all, create a new reference. */ - if (error == GIT_ENOTFOUND) { - giterr_clear(); - return git_reference_create(NULL, repo, ref_name, oid, 0, signature, log_message); - } - - if (error < 0) + /* set to NULL to let the caller know that they're at the end of the chain */ + if ((error = git_reference_lookup(&ref, repo, ref_name)) < 0) { + *out = NULL; return error; + } - /* If the ref is a symbolic reference, follow its target. */ - if (git_reference_type(ref) == GIT_REF_SYMBOLIC) { - error = reference__update_terminal(repo, git_reference_symbolic_target(ref), oid, - nesting+1, signature, log_message); - git_reference_free(ref); + if (git_reference_type(ref) == GIT_REF_OID) { + *out = ref; + error = 0; } else { - /* If we're not moving the target, don't recreate the ref */ - if (0 != git_oid_cmp(git_reference_target(ref), oid)) - error = git_reference_create(NULL, repo, ref_name, oid, 1, signature, log_message); - git_reference_free(ref); + error = get_terminal(out, repo, git_reference_symbolic_target(ref), nesting + 1); + if (error == GIT_ENOTFOUND) { + if (!*out) /* set by the error case in lookup above */ + *out = ref; + } else { + git_reference_free(ref); + } } return error; @@ -1089,10 +1072,38 @@ int git_reference__update_terminal( git_repository *repo, const char *ref_name, const git_oid *oid, - const git_signature *signature, + const git_signature *sig, const char *log_message) { - return reference__update_terminal(repo, ref_name, oid, 0, signature, log_message); + git_reference *ref = NULL; + git_signature *who = NULL; + const git_signature *to_use; + int error = 0; + + if (!sig && (error = git_reference__log_signature(&who, repo)) < 0) + return error; + + to_use = sig ? sig : who; + error = get_terminal(&ref, repo, ref_name, 0); + + /* found a dangling symref */ + if (error == GIT_ENOTFOUND && ref) { + assert(git_reference_type(ref) == GIT_REF_SYMBOLIC); + giterr_clear(); + error = reference__create(&ref, repo, ref->target.symbolic, oid, NULL, 0, to_use, + log_message, NULL, NULL); + } else if (error == GIT_ENOTFOUND) { + giterr_clear(); + error = reference__create(&ref, repo, ref_name, oid, NULL, 0, to_use, + log_message, NULL, NULL); + } else if (error == 0) { + assert(git_reference_type(ref) == GIT_REF_OID); + error = reference__create(&ref, repo, ref->name, oid, NULL, 1, to_use, + log_message, &ref->target.oid, NULL); + } + + git_signature_free(who); + return error; } int git_reference__update_for_commit( @@ -1100,12 +1111,12 @@ int git_reference__update_for_commit( git_reference *ref, const char *ref_name, const git_oid *id, - const git_signature *committer, const char *operation) { git_reference *ref_new = NULL; git_commit *commit = NULL; git_buf reflog_msg = GIT_BUF_INIT; + const git_signature *who; int error; if ((error = git_commit_lookup(&commit, repo, id)) < 0 || @@ -1115,12 +1126,18 @@ int git_reference__update_for_commit( git_commit_summary(commit))) < 0) goto done; - if (ref) - error = git_reference_set_target( - &ref_new, ref, id, committer, git_buf_cstr(&reflog_msg)); + who = git_commit_committer(commit); + + if (ref) { + if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0) + return error; + + error = reference__create(&ref_new, repo, ref->name, id, NULL, 1, who, + git_buf_cstr(&reflog_msg), &ref->target.oid, NULL); + } else error = git_reference__update_terminal( - repo, ref_name, id, committer, git_buf_cstr(&reflog_msg)); + repo, ref_name, id, who, git_buf_cstr(&reflog_msg)); done: git_reference_free(ref_new); |
