Use a transaction for all updates during expire_reflog.

Signed-off-by: Ronnie Sahlberg <sahlb...@google.com>
---
 builtin/reflog.c | 85 ++++++++++++++++++++++++--------------------------------
 refs.c           |  4 +--
 refs.h           |  2 +-
 3 files changed, 39 insertions(+), 52 deletions(-)

diff --git a/builtin/reflog.c b/builtin/reflog.c
index d45344a..c3db3fb 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -32,8 +32,11 @@ struct cmd_reflog_expire_cb {
        int recno;
 };
 
+static struct strbuf err = STRBUF_INIT;
+
 struct expire_reflog_cb {
-       FILE *newlog;
+       struct ref_transaction *t;
+       const char *refname;
        enum {
                UE_NORMAL,
                UE_ALWAYS,
@@ -316,20 +319,18 @@ static int expire_reflog_ent(unsigned char *osha1, 
unsigned char *nsha1,
        if (cb->cmd->recno && --(cb->cmd->recno) == 0)
                goto prune;
 
-       if (cb->newlog) {
-               char sign = (tz < 0) ? '-' : '+';
-               int zone = (tz < 0) ? (-tz) : tz;
-               fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s",
-                       sha1_to_hex(osha1), sha1_to_hex(nsha1),
-                       email, timestamp, sign, zone,
-                       message);
+       if (cb->t) {
+               if (transaction_update_reflog(cb->t, cb->refname, nsha1, osha1,
+                                             email, timestamp, tz, message, 0,
+                                             &err))
+                       return -1;
                hashcpy(cb->last_kept_sha1, nsha1);
        }
        if (cb->cmd->verbose)
                printf("keep %s", message);
        return 0;
  prune:
-       if (!cb->newlog)
+       if (!cb->t)
                printf("would prune %s", message);
        else if (cb->cmd->verbose)
                printf("prune %s", message);
@@ -353,29 +354,26 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
 {
        struct cmd_reflog_expire_cb *cmd = cb_data;
        struct expire_reflog_cb cb;
-       struct ref_lock *lock;
-       char *log_file, *newlog_path = NULL;
        struct commit *tip_commit;
        struct commit_list *tips;
        int status = 0;
 
        memset(&cb, 0, sizeof(cb));
+       cb.refname = ref;
 
-       /*
-        * we take the lock for the ref itself to prevent it from
-        * getting updated.
-        */
-       lock = lock_any_ref_for_update(ref, sha1, 0, NULL);
-       if (!lock)
-               return error("cannot lock ref '%s'", ref);
-       log_file = git_pathdup("logs/%s", ref);
        if (!reflog_exists(ref))
                goto finish;
-       if (!cmd->dry_run) {
-               newlog_path = mkpathdup("%s.lock", log_file);
-               cb.newlog = fopen(newlog_path, "w");
+       cb.t = transaction_begin(&err);
+       if (!cb.t) {
+               status |= error("%s", err.buf);
+               goto cleanup;
+       }
+       if (transaction_update_reflog(cb.t, cb.refname, null_sha1, null_sha1,
+                                     NULL, 0, 0, NULL, REFLOG_TRUNCATE,
+                                     &err)) {
+               status |= error("%s", err.buf);
+               goto cleanup;
        }
-
        cb.cmd = cmd;
 
        if (!cmd->expire_unreachable || !strcmp(ref, "HEAD")) {
@@ -407,7 +405,10 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
                mark_reachable(&cb);
        }
 
-       for_each_reflog_ent(ref, expire_reflog_ent, &cb);
+       if (for_each_reflog_ent(ref, expire_reflog_ent, &cb)) {
+               status |= error("%s", err.buf);
+               goto cleanup;
+       }
 
        if (cb.unreachable_expire_kind != UE_ALWAYS) {
                if (cb.unreachable_expire_kind == UE_HEAD) {
@@ -420,32 +421,18 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
                }
        }
  finish:
-       if (cb.newlog) {
-               if (fclose(cb.newlog)) {
-                       status |= error("%s: %s", strerror(errno),
-                                       newlog_path);
-                       unlink(newlog_path);
-               } else if (cmd->updateref &&
-                       (write_in_full(lock->lock_fd,
-                               sha1_to_hex(cb.last_kept_sha1), 40) != 40 ||
-                        write_str_in_full(lock->lock_fd, "\n") != 1 ||
-                        close_ref(lock) < 0)) {
-                       status |= error("Couldn't write %s",
-                                       lock->lk->filename.buf);
-                       unlink(newlog_path);
-               } else if (rename(newlog_path, log_file)) {
-                       status |= error("cannot rename %s to %s",
-                                       newlog_path, log_file);
-                       unlink(newlog_path);
-               } else if (cmd->updateref && commit_ref(lock)) {
-                       status |= error("Couldn't set %s", lock->ref_name);
-               } else {
-                       adjust_shared_perm(log_file);
-               }
+       if (!cmd->dry_run) {
+               if (cmd->updateref &&
+                   transaction_update_sha1(cb.t, cb.refname,
+                                           cb.last_kept_sha1, sha1,
+                                           0, 1, NULL, &err)) {
+                       status |= error("%s", err.buf);
+               } else if (transaction_commit(cb.t, &err))
+                       status |= error("%s", err.buf);
        }
-       free(newlog_path);
-       free(log_file);
-       unlock_ref(lock);
+ cleanup:
+       transaction_free(cb.t);
+       strbuf_release(&err);
        return status;
 }
 
diff --git a/refs.c b/refs.c
index 3b90457..4069da1 100644
--- a/refs.c
+++ b/refs.c
@@ -3514,7 +3514,7 @@ int transaction_update_reflog(struct ref_transaction 
*transaction,
                              const char *refname,
                              const unsigned char *new_sha1,
                              const unsigned char *old_sha1,
-                             const unsigned char *email,
+                             const char *email,
                              unsigned long timestamp, int tz,
                              const char *msg, int flags,
                              struct strbuf *err)
@@ -3790,7 +3790,7 @@ int transaction_commit(struct ref_transaction 
*transaction,
 
        /*
         * Update all reflog files
-        * We have already done all ref updates and deletes.
+        * We have already committed all ref updates and deletes.
         * There is not much we can do here if there are any reflog
         * update errors other than complain.
         */
diff --git a/refs.h b/refs.h
index b0e339b..e321721 100644
--- a/refs.h
+++ b/refs.h
@@ -342,7 +342,7 @@ int transaction_update_reflog(struct ref_transaction 
*transaction,
                              const char *refname,
                              const unsigned char *new_sha1,
                              const unsigned char *old_sha1,
-                             const unsigned char *email,
+                             const char *email,
                              unsigned long timestamp, int tz,
                              const char *msg, int flags,
                              struct strbuf *err);
-- 
2.0.0.770.gd892650.dirty

--
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