Merge pull request #491 from schu/refs-cleanup reference_rename() cleanup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
diff --git a/include/git2/reflog.h b/include/git2/reflog.h
index 9ad42b7..f1d0879 100644
--- a/include/git2/reflog.h
+++ b/include/git2/reflog.h
@@ -51,6 +51,23 @@ GIT_EXTERN(int) git_reflog_read(git_reflog **reflog, git_reference *ref);
GIT_EXTERN(int) git_reflog_write(git_reference *ref, const git_oid *oid_old, const git_signature *committer, const char *msg);
/**
+ * Rename the reflog for the given reference
+ *
+ * @param ref the reference
+ * @param new_name the new name of the reference
+ * @return GIT_SUCCESS or an error code
+ */
+GIT_EXTERN(int) git_reflog_rename(git_reference *ref, const char *new_name);
+
+/**
+ * Delete the reflog for the given reference
+ *
+ * @param ref the reference
+ * @return GIT_SUCCESS or an error code
+ */
+GIT_EXTERN(int) git_reflog_delete(git_reference *ref);
+
+/**
* Get the number of log entries in a reflog
*
* @param reflog the previously loaded reflog
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 82c5d88..32671aa 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -183,6 +183,11 @@ GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
* If the `force` flag is not enabled, and there's already
* a reference with the given name, the renaming will fail.
*
+ * IMPORTANT:
+ * The user needs to write a proper reflog entry if the
+ * reflog is enabled for the repository. We only rename
+ * the reflog if it exists.
+ *
* @param ref The reference to rename
* @param new_name The new name for the reference
* @param force Overwrite an existing reference
diff --git a/src/fileops.h b/src/fileops.h
index 56c4770..e1a59f6 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -90,11 +90,6 @@ extern int git_futils_rmdir_r(const char *path, int force);
extern int git_futils_mktmp(char *path_out, const char *filename);
/**
- * Atomically rename a file on the filesystem
- */
-extern int git_futils_mv_atomic(const char *from, const char *to);
-
-/**
* Move a file on the filesystem, create the
* destination path if it doesn't exist
*/
diff --git a/src/reflog.c b/src/reflog.c
index c136987..fbaaaea 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -255,6 +255,32 @@ int git_reflog_write(git_reference *ref, const git_oid *oid_old,
return reflog_write(log_path, old, new, committer, msg);
}
+int git_reflog_rename(git_reference *ref, const char *new_name)
+{
+ char old_path[GIT_PATH_MAX];
+ char new_path[GIT_PATH_MAX];
+
+ git_path_join_n(old_path, 3, ref->owner->path_repository,
+ GIT_REFLOG_DIR, ref->name);
+ git_path_join_n(new_path, 3, ref->owner->path_repository,
+ GIT_REFLOG_DIR, new_name);
+
+ return p_rename(old_path, new_path);
+}
+
+int git_reflog_delete(git_reference *ref)
+{
+ char path[GIT_PATH_MAX];
+
+ git_path_join_n(path, 3, ref->owner->path_repository,
+ GIT_REFLOG_DIR, ref->name);
+
+ if (git_futils_exists(path))
+ return GIT_SUCCESS;
+
+ return p_unlink(path);
+}
+
unsigned int git_reflog_entrycount(git_reflog *reflog)
{
assert(reflog);
diff --git a/src/refs.c b/src/refs.c
index 5a297a5..2374cc7 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -10,6 +10,7 @@
#include "repository.h"
#include "fileops.h"
#include "pack.h"
+#include "reflog.h"
#include <git2/tag.h>
#include <git2/object.h>
@@ -1319,28 +1320,6 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
}
/*
- * Crude hack: delete any logs till we support proper reflogs.
- * Otherwise git.git will possibly fail and leave a mess. git.git
- * writes reflogs by default in any repo with a working directory:
- *
- * "We only enable reflogs in repositories that have a working directory
- * associated with them, as shared/bare repositories do not have
- * an easy means to prune away old log entries, or may fail logging
- * entirely if the user's gecos information is not valid during a push.
- * This heuristic was suggested on the mailing list by Junio."
- *
- * Shawn O. Pearce - 0bee59186976b1d9e6b2dd77332480c9480131d5
- *
- * TODO
- *
- */
- git_path_join_n(aux_path, 3, ref->owner->path_repository, "logs", ref->name);
- if (git_futils_isfile(aux_path) == GIT_SUCCESS) {
- if ((error = p_unlink(aux_path)) < GIT_SUCCESS)
- goto rollback;
- }
-
- /*
* Finally we can create the new reference.
*/
if (ref->flags & GIT_REF_SYMBOLIC) {
@@ -1352,7 +1331,7 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
}
if (error < GIT_SUCCESS)
- goto cleanup;
+ goto rollback;
/*
* Check if we have to update HEAD.
@@ -1372,6 +1351,14 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
}
/*
+ * Rename the reflog file.
+ */
+ git_path_join_n(aux_path, 3, ref->owner->path_repository,
+ GIT_REFLOG_DIR, ref->name);
+ if (git_futils_exists(aux_path) == GIT_SUCCESS)
+ error = git_reflog_rename(ref, new_name);
+
+ /*
* Change the name of the reference given by the user.
*/
git__free(ref->name);
@@ -1398,6 +1385,9 @@ rollback:
error = git_reference_create_oid(
NULL, ref->owner, ref->name, &ref->target.oid, 0);
+ /* The reference is no longer packed */
+ ref->flags &= ~GIT_REF_PACKED;
+
return error == GIT_SUCCESS ?
git__rethrow(GIT_ERROR, "Failed to rename reference. Did rollback") :
git__rethrow(error, "Failed to rename reference. Failed to rollback");