git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Michael Haggerty <mhagger@alum.mit.edu>
Cc: git@vger.kernel.org, Ronnie Sahlberg <sahlberg@google.com>,
	Junio C Hamano <gitster@pobox.com>
Subject: [PATCH 11/25] refs.c: ref_transaction_commit: distinguish name conflicts from other errors
Date: Tue, 14 Oct 2014 17:50:46 -0700	[thread overview]
Message-ID: <20141015005045.GO32245@google.com> (raw)
In-Reply-To: <20141015004522.GD32245@google.com>

From: Ronnie Sahlberg <sahlberg@google.com>
Date: Fri, 16 May 2014 14:14:38 -0700

In _commit, ENOTDIR can happen in the call to lock_ref_sha1_basic, either
when we lstat the new refname or if the name checking function reports that
the same type of conflict happened.  In both cases, it means that we can not
create the new ref due to a name conflict.

Start defining specific return codes for _commit.  TRANSACTION_NAME_CONFLICT
refers to a failure to create a ref due to a name conflict with another ref.
TRANSACTION_GENERIC_ERROR is for all other errors.

When "git fetch" is creating refs, name conflicts differ from other errors in
that they are likely to be resolved by running "git remote prune <remote>".
"git fetch" currently inspects errno to decide whether to give that advice.
Once it switches to the transaction API, it can check for
TRANSACTION_NAME_CONFLICT instead.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 refs.c | 26 ++++++++++++++++----------
 refs.h |  9 +++++++--
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/refs.c b/refs.c
index a007cf3..9d9bbeb 100644
--- a/refs.c
+++ b/refs.c
@@ -3637,9 +3637,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
 
 	/* Copy, sort, and reject duplicate refs */
 	qsort(updates, n, sizeof(*updates), ref_update_compare);
-	ret = ref_update_reject_duplicates(updates, n, err);
-	if (ret)
+	if (ref_update_reject_duplicates(updates, n, err)) {
+		ret = TRANSACTION_GENERIC_ERROR;
 		goto cleanup;
+	}
 
 	/* Acquire all locks while verifying old values */
 	for (i = 0; i < n; i++) {
@@ -3653,10 +3654,12 @@ int ref_transaction_commit(struct ref_transaction *transaction,
 						   update->flags,
 						   &update->type);
 		if (!update->lock) {
+			ret = (errno == ENOTDIR)
+				? TRANSACTION_NAME_CONFLICT
+				: TRANSACTION_GENERIC_ERROR;
 			if (err)
 				strbuf_addf(err, "Cannot lock the ref '%s'.",
 					    update->refname);
-			ret = 1;
 			goto cleanup;
 		}
 	}
@@ -3666,15 +3669,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
 		struct ref_update *update = updates[i];
 
 		if (!is_null_sha1(update->new_sha1)) {
-			ret = write_ref_sha1(update->lock, update->new_sha1,
-					     update->msg);
-			update->lock = NULL; /* freed by write_ref_sha1 */
-			if (ret) {
+			if (write_ref_sha1(update->lock, update->new_sha1,
+					   update->msg)) {
+				update->lock = NULL; /* freed by write_ref_sha1 */
 				if (err)
 					strbuf_addf(err, "Cannot update the ref '%s'.",
 						    update->refname);
+				ret = TRANSACTION_GENERIC_ERROR;
 				goto cleanup;
 			}
+			update->lock = NULL; /* freed by write_ref_sha1 */
 		}
 	}
 
@@ -3683,14 +3687,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
 		struct ref_update *update = updates[i];
 
 		if (update->lock) {
-			ret |= delete_ref_loose(update->lock, update->type,
-						err);
+			if (delete_ref_loose(update->lock, update->type, err))
+				ret = TRANSACTION_GENERIC_ERROR;
+
 			if (!(update->flags & REF_ISPRUNING))
 				delnames[delnum++] = update->lock->ref_name;
 		}
 	}
 
-	ret |= repack_without_refs(delnames, delnum, err);
+	if (repack_without_refs(delnames, delnum, err))
+		ret = TRANSACTION_GENERIC_ERROR;
 	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 1a55cab..50b115a 100644
--- a/refs.h
+++ b/refs.h
@@ -326,9 +326,14 @@ 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.
+ * atomically as possible.
+ *
+ * Returns 0 for success, or one of the below error codes for errors.
  */
+/* Naming conflict (for example, the ref names A and A/B conflict). */
+#define TRANSACTION_NAME_CONFLICT -1
+/* All other errors. */
+#define TRANSACTION_GENERIC_ERROR -2
 int ref_transaction_commit(struct ref_transaction *transaction,
 			   struct strbuf *err);
 
-- 
2.1.0.rc2.206.gedb03e5

  parent reply	other threads:[~2014-10-15  0:50 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-15  0:45 [PATCH v23 0/25] rs/ref-transaction ("Use ref transactions", part 3) Jonathan Nieder
2014-10-15  0:46 ` [PATCH 01/25] mv test: recreate mod/ directory instead of relying on stale copy Jonathan Nieder
2014-10-15  0:46 ` [PATCH 02/25] wrapper.c: remove/unlink_or_warn: simplify, treat ENOENT as success Jonathan Nieder
2014-10-15  0:47 ` [PATCH 03/25] refs.c: lock_ref_sha1_basic is used for all refs Jonathan Nieder
2014-10-15  0:47 ` [PATCH 04/25] wrapper.c: add a new function unlink_or_msg Jonathan Nieder
2014-10-15  0:47 ` [PATCH 05/25] refs.c: add an err argument to delete_ref_loose Jonathan Nieder
2014-10-15  0:48 ` [PATCH 06/25] refs.c: pass the ref log message to _create/delete/update instead of _commit Jonathan Nieder
2014-10-15  0:48 ` [PATCH 07/25] rename_ref: don't ask read_ref_full where the ref came from Jonathan Nieder
2014-10-15  0:49 ` [PATCH 08/25] refs.c: refuse to lock badly named refs in lock_ref_sha1_basic Jonathan Nieder
2014-10-15  0:49 ` [PATCH 09/25] refs.c: call lock_ref_sha1_basic directly from commit Jonathan Nieder
2014-10-15  0:50 ` [PATCH 10/25] refs.c: pass a list of names to skip to is_refname_available Jonathan Nieder
2014-10-15  0:50 ` Jonathan Nieder [this message]
2014-10-15  0:51 ` [PATCH 12/25] fetch.c: change s_update_ref to use a ref transaction Jonathan Nieder
2014-10-15  0:51 ` [PATCH 13/25] refs.c: make write_ref_sha1 static Jonathan Nieder
2014-10-15  0:51 ` [PATCH 14/25] refs.c: change resolve_ref_unsafe reading argument to be a flags field Jonathan Nieder
2014-10-15  0:52 ` [PATCH 15/25] reflog test: test interaction with detached HEAD Jonathan Nieder
2014-10-15  0:52 ` [PATCH 16/25] branch -d: avoid repeated symref resolution Jonathan Nieder
2014-10-15  0:52 ` [PATCH 17/25] branch -d: simplify by using RESOLVE_REF_READING Jonathan Nieder
2014-10-15  0:53 ` [PATCH 18/25] packed-ref cache: forbid dot-components in refnames Jonathan Nieder
2014-10-15  0:53 ` [PATCH 19/25] test: put tests for handling of bad ref names in one place Jonathan Nieder
2014-10-15  0:54 ` [PATCH 20/25] refs.c: allow listing and deleting badly named refs Jonathan Nieder
2014-10-15  0:54 ` [PATCH 21/25] for-each-ref: skip and warn about broken ref names Jonathan Nieder
2014-10-15  0:54 ` [PATCH 22/25] remote rm/prune: print a message when writing packed-refs fails Jonathan Nieder
2014-10-15  0:55 ` [PATCH 23/25] refs.c: do not permit err == NULL Jonathan Nieder
2014-10-15  0:55 ` [PATCH 24/25] lockfile: remove unable_to_lock_error Jonathan Nieder
2014-10-15  0:55 ` [PATCH 25/25] ref_transaction_commit: bail out on failure to remove a ref Jonathan Nieder
2014-10-15 21:36 ` [PATCH v23 0/25] rs/ref-transaction ("Use ref transactions", part 3) Junio C Hamano
2014-10-16 23:27 ` Michael Haggerty

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141015005045.GO32245@google.com \
    --to=jrnieder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=mhagger@alum.mit.edu \
    --cc=sahlberg@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).