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

[PATCH 6/8] refs.c: use a reflog transaction when writing during expire

From
Stefan Beller <sbeller@google.com>
Date
Dec 6, 2014, 02:46 UTC
Message-ID
<1417833995-25687-7-git-send-email-sbeller@google.com>
In-Reply-To
<1417833995-25687-1-git-send-email-sbeller@google.com>
From: Ronnie Sahlberg <sahlberg@google.com>
Use a transaction for all updates during expire_reflog.

[sb: This was once a patch series on its own. I cherry-picked these patches on top of Michaels series to cleanup the refs api. So any anomalies and bugs may be introduced by me.]

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
---
Notes:
    Maybe we can leave out the first patch of the series
    as this one deletes the changes made in the first patch of the series.
    
    Originally authored by Ronnie for the reflogs.c file,
    cherrypicked over to the refs.c file by Stefan
 refs.c | 85 +++++++++++++++++++++++++++---------------------------------------
 1 file changed, 35 insertions(+), 50 deletions(-)
diff --git a/refs.c b/refs.c
index 57f4941..295ea09 100644
--- a/refs.c
+++ b/refs.c
@@ -4100,8 +4100,10 @@ struct expire_reflog_cb {
 	unsigned int flags;
 	reflog_expiry_select_fn *select_fn;
 	void *policy_cb;
-	FILE *newlog;
+	struct transaction *t;
+	const char *refname;
 	unsigned char last_kept_sha1[20];
+	struct strbuf *err;
 };
 
 static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
@@ -4116,15 +4118,18 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
 
 	if ((*cb->select_fn)(osha1, nsha1, email, timestamp, tz,
 			     message, policy_cb)) {
-		if (!cb->newlog)
+		if (!cb->t)
 			printf("would prune %s", message);
 		else if (cb->flags & EXPIRE_REFLOGS_VERBOSE)
 			printf("prune %s", message);
 	} else {
-		if (cb->newlog) {
-			fprintf(cb->newlog, "%s %s %s %lu %+05d\t%s",
-				sha1_to_hex(osha1), sha1_to_hex(nsha1),
-				email, timestamp, tz, message);
+		if (cb->t) {
+			if (transaction_update_reflog(cb->t, cb->refname,
+						      nsha1, osha1,
+						      email, timestamp,
+						      tz, message,
+						      cb->err))
+				return -1;
 			hashcpy(cb->last_kept_sha1, nsha1);
 		}
 		if (cb->flags & EXPIRE_REFLOGS_VERBOSE)
@@ -4133,8 +4138,6 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
 	return 0;
 }
 
-static struct lock_file reflog_lock;
-
 extern int reflog_expire(const char *refname, const unsigned char *sha1,
 			 unsigned int flags,
 			 reflog_expiry_prepare_fn prepare_fn,
@@ -4143,66 +4146,48 @@ extern int reflog_expire(const char *refname, const unsigned char *sha1,
 			 void *policy_cb_data)
 {
 	struct expire_reflog_cb cb;
-	struct ref_lock *lock;
-	char *log_file;
 	int status = 0;
+	struct strbuf err = STRBUF_INIT;
 
 	memset(&cb, 0, sizeof(cb));
 	cb.flags = flags;
 	cb.policy_cb = policy_cb_data;
 	cb.select_fn = select_fn;
+	cb.err = &err;
+	cb.refname = refname;
 
 	/*
-	 * we take the lock for the ref itself to prevent it from
-	 * getting updated.
+	 * todo: we need to take the lock for the ref itself to
+	 * prevent it from getting updated.
 	 */
-	lock = lock_ref_sha1_basic(refname, sha1, NULL, 0, NULL);
-	if (!lock)
-		return error("cannot lock ref '%s'", refname);
-	if (!reflog_exists(refname)) {
-		unlock_ref(lock);
-		return 0;
+	cb.t = transaction_begin(&err);
+	if (!cb.t) {
+		status |= error("%s", err.buf);
+		goto cleanup;
 	}
-
-	log_file = git_pathdup("logs/%s", refname);
-	if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
-		if (hold_lock_file_for_update(&reflog_lock, log_file, 0) < 0)
-			goto failure;
-		cb.newlog = fdopen_lock_file(&reflog_lock, "w");
-		if (!cb.newlog)
-			goto failure;
+	if (transaction_delete_reflog(cb.t, cb.refname, &err)) {
+		status |= error("%s", err.buf);
+		goto cleanup;
 	}
 
 	(*prepare_fn)(refname, sha1, cb.policy_cb);
 	for_each_reflog_ent(refname, expire_reflog_ent, &cb);
 	(*cleanup_fn)(cb.policy_cb);
 
+
 	if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) {
-		if (close_lock_file(&reflog_lock)) {
-			status |= error("Couldn't write %s: %s", log_file,
-					strerror(errno));
-		} else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
-			(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);
-			rollback_lock_file(&reflog_lock);
-		} else if (commit_lock_file(&reflog_lock)) {
-			status |= error("cannot rename %s.lock to %s",
-					log_file, log_file);
-		} else if ((flags & EXPIRE_REFLOGS_UPDATE_REF) && commit_ref(lock)) {
-			status |= error("Couldn't set %s", lock->ref_name);
+		if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
+		    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(log_file);
-	unlock_ref(lock);
+cleanup:
+	transaction_free(cb.t);
+	strbuf_release(&err);
 	return status;
-
- failure:
-	rollback_lock_file(&reflog_lock);
-	free(log_file);
-	unlock_ref(lock);
-	return -1;
 }
-- 
2.2.0
Previous: Stefan BellerNext: Stefan Beller
Message 10 of 18 in “Making reflog modifications part of the transactions API”
  1. 0/8 Making reflog modifications part of the transactions APIStefan Beller, Dec 6, 2014
  2. 1/8 refs.c: let fprintf handle the formattingStefan Beller, Dec 6, 2014
  3. 2/8 refs.c: rename the transaction functionsStefan Beller, Dec 6, 2014
  4. Junio C HamanoDec 11, 2014
  5. Stefan BellerDec 11, 2014
  6. 3/8 refs.c: rename transaction.updates to transaction.ref_updatesStefan Beller, Dec 6, 2014
  7. 4/8 refs.c: add transaction function to append to the reflogStefan Beller, Dec 6, 2014
  8. Junio C HamanoDec 11, 2014
  9. 5/8 refs.c: add transaction function to delete the reflogStefan Beller, Dec 6, 2014
  10. 6/8 refs.c: use a reflog transaction when writing during expireStefan Beller, Dec 6, 2014
  11. 7/8 refs.c: rename log_ref_setup to create_reflogStefan Beller, Dec 6, 2014
  12. 8/8 refs.c: allow deleting refs with a broken sha1Stefan Beller, Dec 6, 2014
  13. Stefan BellerDec 8, 2014
  14. Jonathan NiederDec 8, 2014
  15. Michael HaggertyDec 12, 2014
  16. Stefan BellerDec 12, 2014
  17. ronnie sahlbergDec 12, 2014
  18. Michael HaggertyDec 14, 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.