Hi Junio, Michael reviewed the rest of rs/ref-transaction-1 (thanks!) and some more small tweaks resulted --- in particular, there was a missing call to ref_transaction_free. Interdiff below. This is meant to replace rs/ref-transaction-1 in 'pu' and should be ready for 'next'. These patches are also available from the git repository at git://repo.or.cz/git/jrn.git tags/rs/ref-transaction-1 "Use ref transactions", early part Ronnie explains: This patch series expands on the transaction API. It converts ref updates, inside refs.c as well as external, to use the transaction API for updates. This makes most ref updates atomic when there are failures locking or writing to a ref. This series teaches the tag, replace, commit, cherry-pick, fast-import, checkout -b, branch, receive-pack, and http-fetch commands and all update_ref and delete_ref callers to use the ref transaction API instead of lock_ref_sha1. The main user-visible change should be some cosmetic changes to error messages. The series also combines multiple ref updates into a single transaction in 'git http-fetch -w' and when writing tags in fast-import but otherwise doesn't change the granularity of transactions. Jonathan Nieder (2): update-ref --stdin: narrow scope of err strbuf update-ref --stdin: pass transaction around explicitly Ronnie Sahlberg (20): refs.c: change ref_transaction_create to do error checking and return status refs.c: update ref_transaction_delete to check for error and return status refs.c: make ref_transaction_begin take an err argument refs.c: add transaction.status and track OPEN/CLOSED tag.c: use ref transactions when doing updates replace.c: use the ref transaction functions for updates commit.c: use ref transactions for updates sequencer.c: use ref transactions for all ref updates fast-import.c: change update_branch to use ref transactions branch.c: use ref transaction for all ref updates refs.c: change update_ref to use a transaction receive-pack.c: use a reference transaction for updating the refs fast-import.c: use a ref transaction when dumping tags walker.c: use ref transaction for ref updates refs.c: make lock_ref_sha1 static refs.c: remove the update_ref_lock function refs.c: remove the update_ref_write function refs.c: remove lock_ref_sha1 refs.c: make prune_ref use a transaction to delete the ref refs.c: make delete_ref use a transaction branch.c | 31 ++++--- builtin/commit.c | 25 +++-- builtin/receive-pack.c | 25 +++-- builtin/replace.c | 14 +-- builtin/tag.c | 16 ++-- builtin/update-ref.c | 52 +++++++---- fast-import.c | 54 +++++++---- refs.c | 245 ++++++++++++++++++++++++++++--------------------- refs.h | 77 ++++++++++++---- sequencer.c | 26 ++++-- walker.c | 70 ++++++++------ 11 files changed, 393 insertions(+), 242 deletions(-) --- Changes since v21: builtin/update-ref.c | 38 +++++++++++++++++++++++++------------- refs.c | 1 + 2 files changed, 26 insertions(+), 13 deletions(-) diff --git c/builtin/update-ref.c w/builtin/update-ref.c index 96a53b9..54a48c0 100644 --- c/builtin/update-ref.c +++ w/builtin/update-ref.c @@ -12,11 +12,8 @@ static const char * const git_update_ref_usage[] = { NULL }; -static struct ref_transaction *transaction; - static char line_termination = '\n'; static int update_flags; -static struct strbuf err = STRBUF_INIT; /* * Parse one whitespace- or NUL-terminated, possibly C-quoted argument @@ -177,8 +174,10 @@ static int parse_next_sha1(struct strbuf *input, const char **next, * depending on how line_termination is set. */ -static const char *parse_cmd_update(struct strbuf *input, const char *next) +static const char *parse_cmd_update(struct ref_transaction *transaction, + struct strbuf *input, const char *next) { + struct strbuf err = STRBUF_INIT; char *refname; unsigned char new_sha1[20]; unsigned char old_sha1[20]; @@ -204,12 +203,15 @@ static const char *parse_cmd_update(struct strbuf *input, const char *next) update_flags = 0; free(refname); + strbuf_release(&err); return next; } -static const char *parse_cmd_create(struct strbuf *input, const char *next) +static const char *parse_cmd_create(struct ref_transaction *transaction, + struct strbuf *input, const char *next) { + struct strbuf err = STRBUF_INIT; char *refname; unsigned char new_sha1[20]; @@ -232,12 +234,15 @@ static const char *parse_cmd_create(struct strbuf *input, const char *next) update_flags = 0; free(refname); + strbuf_release(&err); return next; } -static const char *parse_cmd_delete(struct strbuf *input, const char *next) +static const char *parse_cmd_delete(struct ref_transaction *transaction, + struct strbuf *input, const char *next) { + struct strbuf err = STRBUF_INIT; char *refname; unsigned char old_sha1[20]; int have_old; @@ -264,12 +269,15 @@ static const char *parse_cmd_delete(struct strbuf *input, const char *next) update_flags = 0; free(refname); + strbuf_release(&err); return next; } -static const char *parse_cmd_verify(struct strbuf *input, const char *next) +static const char *parse_cmd_verify(struct ref_transaction *transaction, + struct strbuf *input, const char *next) { + struct strbuf err = STRBUF_INIT; char *refname; unsigned char new_sha1[20]; unsigned char old_sha1[20]; @@ -297,6 +305,7 @@ static const char *parse_cmd_verify(struct strbuf *input, const char *next) update_flags = 0; free(refname); + strbuf_release(&err); return next; } @@ -310,7 +319,7 @@ static const char *parse_cmd_option(struct strbuf *input, const char *next) return next + 8; } -static void update_refs_stdin(void) +static void update_refs_stdin(struct ref_transaction *transaction) { struct strbuf input = STRBUF_INIT; const char *next; @@ -325,13 +334,13 @@ static void update_refs_stdin(void) else if (isspace(*next)) die("whitespace before command: %s", next); else if (starts_with(next, "update ")) - next = parse_cmd_update(&input, next + 7); + next = parse_cmd_update(transaction, &input, next + 7); else if (starts_with(next, "create ")) - next = parse_cmd_create(&input, next + 7); + next = parse_cmd_create(transaction, &input, next + 7); else if (starts_with(next, "delete ")) - next = parse_cmd_delete(&input, next + 7); + next = parse_cmd_delete(transaction, &input, next + 7); else if (starts_with(next, "verify ")) - next = parse_cmd_verify(&input, next + 7); + next = parse_cmd_verify(transaction, &input, next + 7); else if (starts_with(next, "option ")) next = parse_cmd_option(&input, next + 7); else @@ -365,6 +374,9 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) die("Refusing to perform update with empty message."); if (read_stdin) { + struct strbuf err = STRBUF_INIT; + struct ref_transaction *transaction; + transaction = ref_transaction_begin(&err); if (!transaction) die("%s", err.buf); @@ -372,7 +384,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) usage_with_options(git_update_ref_usage, options); if (end_null) line_termination = '\0'; - update_refs_stdin(); + update_refs_stdin(transaction); if (ref_transaction_commit(transaction, msg, &err)) die("%s", err.buf); ref_transaction_free(transaction); diff --git c/refs.c w/refs.c index 7996be9..7235574 100644 --- c/refs.c +++ w/refs.c @@ -3511,6 +3511,7 @@ int update_ref(const char *action, const char *refname, return 1; } strbuf_release(&err); + ref_transaction_free(t); return 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