summaryrefslogtreecommitdiff
path: root/src/refs.c
diff options
context:
space:
mode:
authorVicent Marti <vicent@github.com>2013-12-18 09:33:45 -0800
committerVicent Marti <vicent@github.com>2013-12-18 09:33:45 -0800
commit4e1f517c61fef323b9cb3acedd19ce7859a8e546 (patch)
tree87823d6c36e00b3098069142ba9e630e2570f1b7 /src/refs.c
parenta7ecd1a9e36df5d6843c1863542c02d777e9e8b5 (diff)
parentf21051297cc698644ea0dc9c7122ec944dba2863 (diff)
downloadlibgit2-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.c213
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)