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 <sbeller@xxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html