From: Stefan Beller <sbeller@google.com>
To: ronniesahlberg@gmail.com, mhagger@alum.mit.edu,
jrnieder@gmail.com, gitster@pobox.com
Cc: git@vger.kernel.org, Ronnie Sahlberg <sahlberg@google.com>,
Stefan Beller <sbeller@google.com>
Subject: [PATCH 07/13] reflog.c: use a reflog transaction when writing during expire
Date: Thu, 4 Dec 2014 00:29:17 -0800 [thread overview]
Message-ID: <1417681763-32334-8-git-send-email-sbeller@google.com> (raw)
In-Reply-To: <1417681763-32334-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>
---
Notes:
Jonathan writes:
> This doesn't match the signature of each_reflog_ent_fn. Would putting
> err in the cb_data struct work?
That's what I do in this update.
builtin/reflog.c | 84 ++++++++++++++++++++++++--------------------------------
1 file changed, 36 insertions(+), 48 deletions(-)
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 2d85d26..e13427c 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -33,7 +33,8 @@ struct cmd_reflog_expire_cb {
};
struct expire_reflog_cb {
- FILE *newlog;
+ struct transaction *t;
+ const char *refname;
enum {
UE_NORMAL,
UE_ALWAYS,
@@ -43,6 +44,7 @@ struct expire_reflog_cb {
unsigned long mark_limit;
struct cmd_reflog_expire_cb *cmd;
unsigned char last_kept_sha1[20];
+ struct strbuf *err;
};
struct collected_reflog {
@@ -316,20 +318,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,
+ cb->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 +353,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;
+ struct strbuf err = STRBUF_INIT;
int status = 0;
memset(&cb, 0, sizeof(cb));
+ cb.refname = ref;
+ cb.err = &err;
- /*
- * 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_truncate_reflog(cb.t, cb.refname, &err)) {
+ status |= error("%s", err.buf);
+ goto cleanup;
}
-
cb.cmd = cmd;
if (!cmd->expire_unreachable || !strcmp(ref, "HEAD")) {
@@ -407,7 +404,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 +420,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
next prev parent reply other threads:[~2014-12-04 8:29 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-04 8:29 [PATCHv3 00/13] the refs-transactions-reflog series Stefan Beller
2014-12-04 8:29 ` [PATCH 01/13] refs.c: make ref_transaction_create a wrapper for ref_transaction_update Stefan Beller
2014-12-04 8:29 ` [PATCH 02/13] refs.c: make ref_transaction_delete " Stefan Beller
2014-12-04 8:29 ` [PATCH 03/13] refs.c: add a function to append a reflog entry to a fd Stefan Beller
2014-12-04 8:29 ` [PATCH 04/13] refs.c: rename the transaction functions Stefan Beller
2014-12-04 8:29 ` [PATCH 05/13] refs.c: rename transaction.updates to transaction.ref_updates Stefan Beller
2014-12-04 8:29 ` [PATCH 06/13] refs.c: add a transaction function to truncate or append a reflog entry Stefan Beller
2014-12-04 8:29 ` Stefan Beller [this message]
2014-12-04 8:29 ` [PATCH 08/13] refs.c: rename log_ref_setup to create_reflog Stefan Beller
2014-12-04 8:29 ` [PATCH 09/13] refs.c: remove unlock_ref/close_ref/commit_ref from the refs api Stefan Beller
2014-12-04 8:29 ` [PATCH 10/13] refs.c: remove lock_any_ref_for_update Stefan Beller
2014-12-04 8:29 ` [PATCH 11/13] refs.c: don't expose the internal struct ref_lock in the header file Stefan Beller
2014-12-04 8:29 ` [PATCH 12/13] refs.c: use a bit for ref_update have_old Stefan Beller
2014-12-04 16:10 ` Torsten Bögershausen
2014-12-04 17:00 ` Andreas Schwab
2014-12-04 8:29 ` [PATCH 13/13] refs.c: allow deleting refs with a broken sha1 Stefan Beller
2014-12-04 17:10 ` [PATCHv3 00/13] the refs-transactions-reflog series Michael Haggerty
2014-12-04 17:53 ` Jonathan Nieder
2014-12-04 18:14 ` Jonathan Nieder
2014-12-04 18:32 ` Stefan Beller
2014-12-04 21:13 ` Michael Haggerty
2014-12-04 18:37 ` Junio C Hamano
2014-12-04 18:41 ` Junio C Hamano
2014-12-04 18:49 ` Stefan Beller
2014-12-04 19:27 ` Jonathan Nieder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1417681763-32334-8-git-send-email-sbeller@google.com \
--to=sbeller@google.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jrnieder@gmail.com \
--cc=mhagger@alum.mit.edu \
--cc=ronniesahlberg@gmail.com \
--cc=sahlberg@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).