Change rename_ref to use a single transaction to perform the ref rename. Signed-off-by: Ronnie Sahlberg <sahlberg@xxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html