summaryrefslogtreecommitdiff
path: root/src/refs.c
diff options
context:
space:
mode:
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);