Merge branch 'mh/ref-directory-file'
authorJunio C Hamano <gitster@pobox.com>
Fri, 22 May 2015 19:41:53 +0000 (12:41 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 22 May 2015 19:41:53 +0000 (12:41 -0700)
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

1  2 
refs.c
t/t1400-update-ref.sh
diff --cc refs.c
index 825a1f6847ccefb3aba29e489c05c96382fff907,97043fd2ef88fd50dadf05d673bb80018d3caf06..f704ee285cdff46e94d9bd47de5f39a7cc6927ee
--- 1/refs.c
--- 2/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;
        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));
  
Simple merge