This continues the work of the previous patch as reflogs not
only grow, but also need a cut sometimes. This patch introduces
transaction_delete_reflog as part of the transaction API to
delete the reflog.

This function serves two purposes. It can be used to actually
delete the reflog as the name indicates. The other purpose is
truncation of the reflog and rewriting it.

Signed-off-by: Stefan Beller <sbel...@google.com>
---
 refs.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index d767418..57f4941 100644
--- a/refs.c
+++ b/refs.c
@@ -3649,6 +3649,56 @@ int transaction_update_ref(struct transaction 
*transaction,
 }
 
 /*
+ * Delete the reflog for the given refname.
+ *
+ */
+static int transaction_delete_reflog(struct transaction *transaction,
+                                      const char *refname,
+                                      struct strbuf *err)
+{
+       struct lock_file *lock;
+       struct string_list_item *item;
+
+       if (transaction->state != TRANSACTION_OPEN)
+               die("BUG: delete_reflog called for transaction that is not 
open");
+
+       item = string_list_insert(&transaction->reflog_updates, refname);
+
+       if (!item->util) {
+               char *path = git_path("logs/locks/%s", refname);
+               lock = xcalloc(1, sizeof(struct lock_file));
+               item->util = lock;
+               if (safe_create_leading_directories(path)) {
+                       strbuf_addf(err, "could not create leading directories 
of '%s': %s",
+                                   path, strerror(errno));
+                       goto failure;
+               }
+
+               if (hold_lock_file_for_update(lock, path, 0) < 0) {
+                       unable_to_lock_message(path, errno, err);
+                       goto failure;
+               }
+               /* The empty file indicates transaction_commit to
+                * delete the reflog */
+               return 0;
+       }
+
+       /* The transaction already writes to this reflog.  Clear it. */
+       lock = item->util;
+       if (lseek(lock->fd, 0, SEEK_SET) < 0 ||
+           ftruncate(lock->fd, 0)) {
+               strbuf_addf(err, "cannot truncate reflog '%s': %s",
+                           refname, strerror(errno));
+               goto failure;
+       }
+       return 0;
+
+failure:
+       transaction->state = TRANSACTION_CLOSED;
+       return -1;
+}
+
+/*
  * Append a reflog entry for refname.
  */
 static int transaction_update_reflog(struct transaction *transaction,
@@ -3885,7 +3935,17 @@ int transaction_commit(struct transaction *transaction,
        /* Commit all reflog updates*/
        for_each_string_list_item(item, &transaction->reflog_updates) {
                struct lock_file *lock = item->util;
-               commit_lock_file_to(lock, git_path("logs/%s", item->string));
+
+               /* If the lock file is empty we want to delete the reflog*/
+               off_t filepos = lseek(lock->fd, 0, SEEK_END);
+               if (filepos < 0) {
+                       ret = TRANSACTION_GENERIC_ERROR;
+                       goto cleanup;
+               }
+               if (filepos)
+                       commit_lock_file_to(lock, git_path("logs/%s", 
item->string));
+               else
+                       remove_path(git_path("logs/%s", item->string));
        }
 
        clear_loose_ref_cache(&ref_cache);
-- 
2.2.0

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