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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ronnie Sahlberg <sahlberg@xxxxxxxxxx>

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@xxxxxxxxxx>
Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx>
---

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

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




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]