git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 4/4] reflog.c: use a reflog transaction when writing during expire

From
Stefan Beller <sbeller@google.com>
Date
Nov 27, 2014, 05:34 UTC
Message-ID
<1417066485-24921-5-git-send-email-sbeller@google.com>
In-Reply-To
<1417066485-24921-1-git-send-email-sbeller@google.com>
From: Ronnie Sahlberg <sahlberg@google.com>
Use a transaction for all updates during expire_reflog.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
 builtin/reflog.c | 85 ++++++++++++++++++++++++--------------------------------
 1 file changed, 37 insertions(+), 48 deletions(-)
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 2d85d26..6bb7454 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 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 = git_pathdup("logs/%s.lock", ref);
-		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,20 @@ 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_ref(cb.t, cb.refname,
+					   cb.last_kept_sha1, sha1,
+					   0, 1, NULL, &err)) {
+			status |= error("%s", err.buf);
+			goto cleanup;
 		}
+		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;
 }
 
-- 
2.2.0.rc3
Previous: Stefan Beller
Message 31 of 31 in “ref-transactions-reflog”
  1. 00/14 ref-transactions-reflogStefan Beller, Nov 18, 2014
  2. 01/14 refs.c: make ref_transaction_create a wrapper for ref_transaction_updateStefan Beller, Nov 18, 2014
  3. 02/14 refs.c: make ref_transaction_delete a wrapper for ref_transaction_updateStefan Beller, Nov 18, 2014
  4. 03/14 refs.c: rename the transaction functionsStefan Beller, Nov 18, 2014
  5. 04/14 refs.c: add a function to append a reflog entry to a fdStefan Beller, Nov 18, 2014
  6. 05/14 refs.c: add a new update_type field to ref_updateStefan Beller, Nov 18, 2014
  7. 06/14 refs.c: add a transaction function to append a reflog entryStefan Beller, Nov 18, 2014
  8. 07/14 refs.c: add a flag to allow reflog updates to truncate the logStefan Beller, Nov 18, 2014
  9. 08/14 refs.c: only write reflog update if msg is non-NULLStefan Beller, Nov 18, 2014
  10. 09/14 refs.c: allow multiple reflog updates during a single transactionStefan Beller, Nov 18, 2014
  11. 10/14 reflog.c: use a reflog transaction when writing during expireStefan Beller, Nov 18, 2014
  12. 11/14 refs.c: rename log_ref_setup to create_reflogStefan Beller, Nov 18, 2014
  13. 12/14 refs.c: Remove unlock_ref/close_ref/commit_ref from the refs apiStefan Beller, Nov 18, 2014
  14. 13/14 refs.c: remove lock_any_ref_for_updateStefan Beller, Nov 18, 2014
  15. 14/14 refs.c: allow deleting refs with a broken sha1Stefan Beller, Nov 18, 2014
  16. Michael HaggertyNov 18, 2014
  17. Ronnie SahlbergNov 18, 2014
  18. Michael HaggertyNov 18, 2014
  19. Junio C HamanoNov 18, 2014
  20. Michael HaggertyNov 18, 2014
  21. Junio C HamanoNov 18, 2014
  22. Stefan BellerNov 19, 2014
  23. Jonathan NiederNov 20, 2014
  24. Junio C HamanoNov 20, 2014
  25. Michael HaggertyNov 20, 2014
  26. Jonathan NiederNov 20, 2014
  27. 0/4 Using transactions for the reflogStefan Beller, Nov 27, 2014
  28. 1/4 refs.c: rename the transaction functionsStefan Beller, Nov 27, 2014
  29. 2/4 refs.c: add a new update_type field to ref_updateStefan Beller, Nov 27, 2014
  30. 3/4 refs.c: add a transaction function to append a reflog entryStefan Beller, Nov 27, 2014
  31. 4/4 reflog.c: use a reflog transaction when writing during expireStefan Beller, Nov 27, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.