Jonathan Nieder <jrnieder@xxxxxxxxx> writes: > Ronnie Sahlberg wrote: > >> This patch series is based on next and expands on the transaction API. > > Thanks. Will pick up in v8 where I left off with v6. > > Applies with just one minor conflict on top of a merge of > mh/ref-transaction, rs/ref-update-check-errors-early, and > rs/reflog-exists. Here's an interdiff against version 6 for those > following along. The interdiffs look mostly sensible. Thanks. >> Version 8: >> - Updates after review by JN >> - Improve commit messages >> - Add a patch that adds an err argument to repack_without_refs >> - Add a patch that adds an err argument to delete_loose_ref >> - Better document that a _update/_delete/_create failure means the whole >> transaction has failed and needs rollback. >> >> Version 7: >> - Updated commit messages per JNs review comments. >> - Changed REF_ISPRUNING and REF_ISPACKONLY to be private flags and not >> exposed through refs.h > > diff --git a/builtin/commit.c b/builtin/commit.c > index 0f4e1fc..07ccc97 100644 > --- a/builtin/commit.c > +++ b/builtin/commit.c > @@ -1684,7 +1684,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) > 0, !!current_head, sb.buf) || > ref_transaction_commit(transaction, &err)) { > rollback_index_files(); > - die(_("HEAD: cannot update ref: %s"), err.buf); > + die("%s", err.buf); > } > ref_transaction_free(transaction); > > diff --git a/builtin/replace.c b/builtin/replace.c > index 47c360c..952b589 100644 > --- a/builtin/replace.c > +++ b/builtin/replace.c > @@ -163,7 +163,7 @@ static int replace_object(const char *object_ref, const char *replace_ref, > ref_transaction_update(transaction, ref, repl, prev, > 0, !is_null_sha1(prev), NULL) || > ref_transaction_commit(transaction, &err)) > - die(_("%s: failed to replace ref: %s"), ref, err.buf); > + die("%s: failed to replace ref: %s", ref, err.buf); > > ref_transaction_free(transaction); > return 0; > diff --git a/builtin/update-ref.c b/builtin/update-ref.c > index c5aff92..bd7e96f 100644 > --- a/builtin/update-ref.c > +++ b/builtin/update-ref.c > @@ -228,7 +228,7 @@ static const char *parse_cmd_create(struct strbuf *input, const char *next) > > if (ref_transaction_create(transaction, refname, new_sha1, > update_flags, msg)) > - die("failed transaction create for %s", refname); > + die("cannot create ref '%s'", refname); > > update_flags = 0; > free(refname); > diff --git a/refs.c b/refs.c > index 302a2b3..ed93b75 100644 > --- a/refs.c > +++ b/refs.c > @@ -29,6 +29,15 @@ static inline int bad_ref_char(int ch) > return 0; > } > > +/** Used as a flag to ref_transaction_delete when a loose ref is beeing > + * pruned. > + */ > +#define REF_ISPRUNING 0x0100 > +/** Deletion of a ref that only exists as a packed ref in which case we do not > + * need to lock the loose ref during the transaction. > + */ > +#define REF_ISPACKONLY 0x0200 > + > /* > * Try to read one refname component from the front of refname. Return > * the length of the component found, or -1 if the component is not > @@ -2447,12 +2456,12 @@ static int curate_packed_ref_fn(struct ref_entry *entry, void *cb_data) > return 0; > } > > -static int repack_without_refs(const char **refnames, int n) > +static int repack_without_refs(const char **refnames, int n, struct strbuf *err) > { > struct ref_dir *packed; > struct string_list refs_to_delete = STRING_LIST_INIT_DUP; > struct string_list_item *ref_to_delete; > - int i, removed = 0; > + int i, ret, removed = 0; > > /* Look for a packed ref */ > for (i = 0; i < n; i++) > @@ -2465,6 +2474,9 @@ static int repack_without_refs(const char **refnames, int n) > > if (lock_packed_refs(0)) { > unable_to_lock_error(git_path("packed-refs"), errno); > + if (err) > + strbuf_addf(err, "cannot delete '%s' from packed refs", > + refnames[i]); > return error("cannot delete '%s' from packed refs", refnames[i]); > } > packed = get_packed_refs(&ref_cache); > @@ -2490,20 +2502,28 @@ static int repack_without_refs(const char **refnames, int n) > } > > /* Write what remains */ > - return commit_packed_refs(); > + ret = commit_packed_refs(); > + if (ret && err) > + strbuf_addf(err, "unable to overwrite old ref-pack file"); > + return ret; > } > > -static int delete_ref_loose(struct ref_lock *lock, int flag) > +static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err) > { > if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) { > /* loose */ > - int err, i = strlen(lock->lk->filename) - 5; /* .lock */ > + int res, i = strlen(lock->lk->filename) - 5; /* .lock */ > > lock->lk->filename[i] = 0; > - err = unlink_or_warn(lock->lk->filename); > + res = unlink_or_warn(lock->lk->filename); > lock->lk->filename[i] = '.'; > - if (err && errno != ENOENT) > + if (res && errno != ENOENT) { > + if (err) > + strbuf_addf(err, > + "failed to delete loose ref '%s'", > + lock->lk->filename); > return 1; > + } > } > return 0; > } > @@ -3483,7 +3503,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, > delnames, delnum); > if (!update->lock) { > if (err) > - strbuf_addf(err ,"Cannot lock the ref '%s'.", > + strbuf_addf(err, "Cannot lock the ref '%s'.", > update->refname); > ret = 1; > goto cleanup; > @@ -3516,13 +3536,14 @@ int ref_transaction_commit(struct ref_transaction *transaction, > continue; > > if (update->lock) { > - ret |= delete_ref_loose(update->lock, update->type); > + ret |= delete_ref_loose(update->lock, update->type, > + err); > if (!(update->flags & REF_ISPRUNING)) > delnames[delnum++] = update->lock->ref_name; > } > } > > - ret |= repack_without_refs(delnames, delnum); > + ret |= repack_without_refs(delnames, delnum, err); > for (i = 0; i < delnum; i++) > unlink_or_warn(git_path("logs/%s", delnames[i])); > clear_loose_ref_cache(&ref_cache); > diff --git a/refs.h b/refs.h > index 03b4a7e..0e6d416 100644 > --- a/refs.h > +++ b/refs.h > @@ -134,10 +134,6 @@ extern int peel_ref(const char *refname, unsigned char *sha1); > > /** Locks any ref (for 'HEAD' type refs). */ > #define REF_NODEREF 0x01 > -/** Deleting a loose ref during prune */ > -#define REF_ISPRUNING 0x02 > -/** Deletion of a ref that only exists as a packed ref */ > -#define REF_ISPACKONLY 0x04 > extern struct ref_lock *lock_any_ref_for_update(const char *refname, > const unsigned char *old_sha1, > int flags, int *type_p); > @@ -240,6 +236,9 @@ void ref_transaction_rollback(struct ref_transaction *transaction); > * be deleted. If have_old is true, then old_sha1 holds the value > * that the reference should have had before the update, or zeros if > * it must not have existed beforehand. > + * Function returns 0 on success and non-zero on failure. A failure to update > + * means that the transaction as a whole has failed and will need to be > + * rolled back. > */ > int ref_transaction_update(struct ref_transaction *transaction, > const char *refname, > @@ -252,6 +251,9 @@ int ref_transaction_update(struct ref_transaction *transaction, > * that the reference should have after the update; it must not be the > * null SHA-1. It is verified that the reference does not exist > * already. > + * Function returns 0 on success and non-zero on failure. A failure to create > + * means that the transaction as a whole has failed and will need to be > + * rolled back. > */ > int ref_transaction_create(struct ref_transaction *transaction, > const char *refname, > @@ -262,6 +264,9 @@ int ref_transaction_create(struct ref_transaction *transaction, > * Add a reference deletion to transaction. If have_old is true, then > * old_sha1 holds the value that the reference should have had before > * the update (which must not be the null SHA-1). > + * Function returns 0 on success and non-zero on failure. A failure to delete > + * means that the transaction as a whole has failed and will need to be > + * rolled back. > */ > int ref_transaction_delete(struct ref_transaction *transaction, > const char *refname, > @@ -272,7 +277,7 @@ int ref_transaction_delete(struct ref_transaction *transaction, > * Commit all of the changes that have been queued in transaction, as > * atomically as possible. Return a nonzero value if there is a > * problem. If err is non-NULL we will add an error string to it to explain > - * why the transaction failed. > + * why the transaction failed. The string does not end in newline. > */ > int ref_transaction_commit(struct ref_transaction *transaction, > struct strbuf *err); -- 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