Change rename_ref to use a single transaction to perform the ref rename.

Signed-off-by: Ronnie Sahlberg <sahlb...@google.com>
---
 refs.c | 73 ++++++++++++++++++------------------------------------------------
 1 file changed, 20 insertions(+), 53 deletions(-)

diff --git a/refs.c b/refs.c
index c940509..336df40 100644
--- a/refs.c
+++ b/refs.c
@@ -2602,9 +2602,10 @@ static int rename_tmp_log(const char *newrefname)
 
 int rename_ref(const char *oldrefname, const char *newrefname, const char 
*logmsg)
 {
-       unsigned char sha1[20], orig_sha1[20];
-       int flag = 0, logmoved = 0;
-       struct ref_lock *lock;
+       unsigned char sha1[20];
+       int flag = 0;
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
        struct stat loginfo;
        int log = !lstat(git_path("logs/%s", oldrefname), &loginfo);
        const char *symref = NULL;
@@ -2615,7 +2616,7 @@ int rename_ref(const char *oldrefname, const char 
*newrefname, const char *logms
        if (log && S_ISLNK(loginfo.st_mode))
                return error("reflog for %s is a symlink", oldrefname);
 
-       symref = resolve_ref_unsafe(oldrefname, orig_sha1, 1, &flag);
+       symref = resolve_ref_unsafe(oldrefname, sha1, 1, &flag);
        if (flag & REF_ISSYMREF)
                return error("refname %s is a symbolic ref, renaming it is not 
supported",
                        oldrefname);
@@ -2637,62 +2638,28 @@ int rename_ref(const char *oldrefname, const char 
*newrefname, const char *logms
        if (pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE))
                return error("unable to pack refs");
 
-       if (delete_ref(oldrefname, orig_sha1, REF_NODEREF)) {
-               error("unable to delete old %s", oldrefname);
-               goto rollback;
-       }
-
-       if (!read_ref_full(newrefname, sha1, 1, NULL) &&
-           delete_ref(newrefname, sha1, REF_NODEREF)) {
-               if (errno==EISDIR) {
-                       if (remove_empty_directories(git_path("%s", 
newrefname))) {
-                               error("Directory not empty: %s", newrefname);
-                               goto rollback;
-                       }
-               } else {
-                       error("unable to delete existing %s", newrefname);
-                       goto rollback;
-               }
+       transaction = ref_transaction_begin();
+       if (!transaction ||
+           ref_transaction_delete(transaction, oldrefname, sha1,
+                                  REF_NODEREF | REF_ISPACKONLY,
+                                  1, NULL) ||
+           ref_transaction_update(transaction, newrefname, sha1,
+                                  NULL, 0, 0, logmsg) ||
+           ref_transaction_commit(transaction, &err)) {
+               ref_transaction_rollback(transaction);
+               error("rename_ref failed: %s", err.buf);
+               strbuf_release(&err);
+               goto rollbacklog;
        }
+       ref_transaction_free(transaction);
 
        if (log && rename_tmp_log(newrefname))
-               goto rollback;
-
-       logmoved = log;
-
-       lock = lock_ref_sha1_basic(newrefname, NULL, 0, NULL, NULL, 0);
-       if (!lock) {
-               error("unable to lock %s for update", newrefname);
-               goto rollback;
-       }
-       lock->force_write = 1;
-       hashcpy(lock->old_sha1, orig_sha1);
-       if (write_ref_sha1(lock, orig_sha1, logmsg)) {
-               error("unable to write current sha1 into %s", newrefname);
-               goto rollback;
-       }
-
-       return 0;
-
- rollback:
-       lock = lock_ref_sha1_basic(oldrefname, NULL, 0, NULL, NULL, 0);
-       if (!lock) {
-               error("unable to lock %s for rollback", oldrefname);
                goto rollbacklog;
-       }
 
-       lock->force_write = 1;
-       flag = log_all_ref_updates;
-       log_all_ref_updates = 0;
-       if (write_ref_sha1(lock, orig_sha1, NULL))
-               error("unable to write current sha1 into %s", oldrefname);
-       log_all_ref_updates = flag;
+       return 0;
 
  rollbacklog:
-       if (logmoved && rename(git_path("logs/%s", newrefname), 
git_path("logs/%s", oldrefname)))
-               error("unable to restore logfile %s from %s: %s",
-                       oldrefname, newrefname, strerror(errno));
-       if (!logmoved && log &&
+       if (log &&
            rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", oldrefname)))
                error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
                        oldrefname, strerror(errno));
-- 
2.0.0.rc3.477.g0f8edf7

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to