summaryrefslogtreecommitdiff
path: root/src/refs.c
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-01-07 12:23:05 +0000
committerCarlos Martín Nieto <cmn@dwim.me>2015-03-03 14:40:50 +0100
commit659cf2029f322ea876d663d85783b48945227e8f (patch)
tree435e9185c38d96656e21db83fc736b5294499b10 /src/refs.c
parent99b68a2aecfaa24f252f265d61b230b8e2576dd2 (diff)
downloadlibgit2-659cf2029f322ea876d663d85783b48945227e8f.tar.gz
Remove the signature from ref-modifying functions
The signature for the reflog is not something which changes dynamically. Almost all uses will be NULL, since we want for the repository's default identity to be used, making it noise. In order to allow for changing the identity, we instead provide git_repository_set_ident() and git_repository_ident() which allow a user to override the choice of signature.
Diffstat (limited to 'src/refs.c')
-rw-r--r--src/refs.c153
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);