[PATCH 11/15] reflog.c: use a reflog transaction when writing during expire
commit 5ac378cd8fad09a836d17fec379780854838bde5 upstream. Use a transaction for all updates during expire_reflog. Change-Id: Ieb81b2660cefeeecf0bcb3cdbc1ef3cbb86e7eb8 Signed-off-by: Ronnie Sahlberg sahlb...@google.com Signed-off-by: Jonathan Nieder jrnie...@gmail.com --- builtin/reflog.c | 85 refs.c | 4 +-- refs.h | 2 +- 3 files changed, 40 insertions(+), 51 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
[PATCH 11/15] reflog.c: use a reflog transaction when writing during expire
Use a transaction for all updates during expire_reflog. Signed-off-by: Ronnie Sahlberg sahlb...@google.com --- builtin/reflog.c | 84 refs.c | 4 +-- refs.h | 2 +- 3 files changed, 39 insertions(+), 51 deletions(-) diff --git a/builtin/reflog.c b/builtin/reflog.c index e8a8fb1..f11fee3 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 ref_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,19 @@ 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); - 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 { -