From: Junio C Hamano Date: Fri, 22 May 2015 19:41:53 +0000 (-0700) Subject: Merge branch 'mh/ref-directory-file' X-Git-Tag: v2.5.0-rc0~89 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=faa4b2ecbb6ea5fdc8d685343c4985dfb97f4dbf;p=thirdparty%2Fgit.git Merge branch 'mh/ref-directory-file' The ref API did not handle cases where 'refs/heads/xyzzy/frotz' is removed at the same time as 'refs/heads/xyzzy' is added (or vice versa) very well. * mh/ref-directory-file: reflog_expire(): integrate lock_ref_sha1_basic() errors into ours ref_transaction_commit(): delete extra "the" from error message ref_transaction_commit(): provide better error messages rename_ref(): integrate lock_ref_sha1_basic() errors into ours lock_ref_sha1_basic(): improve diagnostics for ref D/F conflicts lock_ref_sha1_basic(): report errors via a "struct strbuf *err" verify_refname_available(): report errors via a "struct strbuf *err" verify_refname_available(): rename function refs: check for D/F conflicts among refs created in a transaction ref_transaction_commit(): use a string_list for detecting duplicates is_refname_available(): use dirname in first loop struct nonmatching_ref_data: store a refname instead of a ref_entry report_refname_conflict(): inline function entry_matches(): inline function is_refname_available(): convert local variable "dirname" to strbuf is_refname_available(): avoid shadowing "dir" variable is_refname_available(): revamp the comments t1404: new tests of ref D/F conflicts within transactions --- faa4b2ecbb6ea5fdc8d685343c4985dfb97f4dbf diff --cc refs.c index 825a1f6847,97043fd2ef..f704ee285c --- a/refs.c +++ b/refs.c @@@ -2294,10 -2331,12 +2354,12 @@@ int dwim_log(const char *str, int len, */ static struct ref_lock *lock_ref_sha1_basic(const char *refname, const unsigned char *old_sha1, + const struct string_list *extras, const struct string_list *skip, - unsigned int flags, int *type_p) + unsigned int flags, int *type_p, + struct strbuf *err) { - char *ref_file; + const char *ref_file; const char *orig_refname = refname; struct ref_lock *lock; int last_errno = 0; @@@ -2306,7 -2345,10 +2368,9 @@@ int resolve_flags = 0; int attempts_remaining = 3; + assert(err); + lock = xcalloc(1, sizeof(struct ref_lock)); - lock->lock_fd = -1; if (mustexist) resolve_flags |= RESOLVE_REF_READING; @@@ -3812,19 -3833,30 +3889,24 @@@ int ref_transaction_commit(struct ref_t update->refname, ((update->flags & REF_HAVE_OLD) ? update->old_sha1 : NULL), - NULL, + &affected_refnames, NULL, - flags, + update->flags, - &update->type); + &update->type, + err); if (!update->lock) { + char *reason; + ret = (errno == ENOTDIR) ? TRANSACTION_NAME_CONFLICT : TRANSACTION_GENERIC_ERROR; - strbuf_addf(err, "Cannot lock the ref '%s'.", - update->refname); + reason = strbuf_detach(err, NULL); + strbuf_addf(err, "Cannot lock ref '%s': %s", + update->refname, reason); + free(reason); goto cleanup; } - } - - /* Perform updates first so live commits remain referenced */ - for (i = 0; i < n; i++) { - struct ref_update *update = updates[i]; - int flags = update->flags; - - if ((flags & REF_HAVE_NEW) && !is_null_sha1(update->new_sha1)) { + if ((update->flags & REF_HAVE_NEW) && + !(update->flags & REF_DELETING)) { int overwriting_symref = ((update->type & REF_ISSYMREF) && (update->flags & REF_NODEREF));