diff mbox series

[v6,4/6] transaction: add TRANSACTION_CREATE_EXISTS error

Message ID 20241010133022.1733542-4-bence@ferdinandy.com (mailing list archive)
State New
Headers show
Series [v6,1/6] refs_update_symref: atomically record overwritten ref | expand

Commit Message

Bence Ferdinandy Oct. 10, 2024, 1:29 p.m. UTC
Currently there is only one special error for transaction, for when
there is a naming conflict, all other errors are dumped under a generic
error. Add a new special error case for when the caller requests the
reference to be updated only when it does not yet exist and the
reference actually does exist.

Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
---

Notes:
    v4: new patch
    v5: no change
    v6: no change

 refs.h                  |  4 +++-
 refs/files-backend.c    | 28 ++++++++++++++++++++--------
 refs/reftable-backend.c |  6 ++++--
 3 files changed, 27 insertions(+), 11 deletions(-)

Comments

karthik nayak Oct. 10, 2024, 9:12 p.m. UTC | #1
Bence Ferdinandy <bence@ferdinandy.com> writes:

> transaction: add TRANSACTION_CREATE_EXISTS error

Nit: but it would be nice to have s/transaction/refs here and similarly
in other patches. Phrasing 'Documentation/SubmittingPatches':

  It is also conventional in most cases to prefix the first line with
  "area: " where the area is a filename or identifier for the general
  area of the code being modified, e.g.

    * doc: clarify distinction between sign-off and pgp-signing
    * githooks.txt: improve the intro section

So in this sense, it would be the refs area, no?

> Currently there is only one special error for transaction, for when
> there is a naming conflict, all other errors are dumped under a generic
> error. Add a new special error case for when the caller requests the
> reference to be updated only when it does not yet exist and the
> reference actually does exist.
>
> Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
> ---
>
> Notes:
>     v4: new patch
>     v5: no change
>     v6: no change
>
>  refs.h                  |  4 +++-
>  refs/files-backend.c    | 28 ++++++++++++++++++++--------
>  refs/reftable-backend.c |  6 ++++--
>  3 files changed, 27 insertions(+), 11 deletions(-)
>
> diff --git a/refs.h b/refs.h
> index f38616db84..166affbc89 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -759,8 +759,10 @@ int ref_transaction_verify(struct ref_transaction *transaction,
>
>  /* Naming conflict (for example, the ref names A and A/B conflict). */
>  #define TRANSACTION_NAME_CONFLICT -1
> +/* When only creation was requested, but the ref already exists. */
> +#define TRANSACTION_CREATE_EXISTS -2
>  /* All other errors. */
> -#define TRANSACTION_GENERIC_ERROR -2
> +#define TRANSACTION_GENERIC_ERROR -3
>
>  /*
>   * Perform the preparatory stages of committing `transaction`. Acquire
> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index 8415f2d020..272ad81315 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -2502,14 +2502,18 @@ static int split_symref_update(struct ref_update *update,
>  static int check_old_oid(struct ref_update *update, struct object_id *oid,
>  			 struct strbuf *err)
>  {
> +	int ret = TRANSACTION_GENERIC_ERROR;
> +
>  	if (!(update->flags & REF_HAVE_OLD) ||
>  		   oideq(oid, &update->old_oid))
>  		return 0;
>
> -	if (is_null_oid(&update->old_oid))
> +	if (is_null_oid(&update->old_oid)) {
>  		strbuf_addf(err, "cannot lock ref '%s': "
>  			    "reference already exists",
>  			    ref_update_original_update_refname(update));
> +		ret = TRANSACTION_CREATE_EXISTS;
> +	}
>  	else if (is_null_oid(oid))
>  		strbuf_addf(err, "cannot lock ref '%s': "
>  			    "reference is missing but expected %s",
> @@ -2522,7 +2526,7 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid,
>  			    oid_to_hex(oid),
>  			    oid_to_hex(&update->old_oid));
>
> -	return -1;
> +	return ret;
>  }
>
>  /*
> @@ -2603,9 +2607,13 @@ static int lock_ref_for_update(struct files_ref_store *refs,
>  					ret = TRANSACTION_GENERIC_ERROR;
>  					goto out;
>  				}
> -			} else if  (check_old_oid(update, &lock->old_oid, err)) {
> -				ret = TRANSACTION_GENERIC_ERROR;
> -				goto out;
> +			} else {
> +				int checkret;
> +				checkret = check_old_oid(update, &lock->old_oid, err);
> +				if  (checkret) {
> +					ret = checkret;
> +					goto out;
> +				}

Can't we simply do:

  ret = check_old_oid(update, &lock->old_oid, err);
  if (ret) {
     goto out
  }

if ret is '0', it shouldn't matter no?

[snip]
Junio C Hamano Oct. 11, 2024, 4:34 p.m. UTC | #2
karthik nayak <karthik.188@gmail.com> writes:

>> +			} else {
>> +				int checkret;
>> +				checkret = check_old_oid(update, &lock->old_oid, err);
>> +				if  (checkret) {
>> +					ret = checkret;
>> +					goto out;
>> +				}
>
> Can't we simply do:
>
>   ret = check_old_oid(update, &lock->old_oid, err);
>   if (ret) {
>      goto out
>   }
>
> if ret is '0', it shouldn't matter no?

That's nice.  Yes, as long as "ret" has no useful information when
we enter this "else" block, reusing it like you did is just fine.

This is one of these moments I tell myself "oh, why didn't *I* think
of that" ;-).

Thanks.
diff mbox series

Patch

diff --git a/refs.h b/refs.h
index f38616db84..166affbc89 100644
--- a/refs.h
+++ b/refs.h
@@ -759,8 +759,10 @@  int ref_transaction_verify(struct ref_transaction *transaction,
 
 /* Naming conflict (for example, the ref names A and A/B conflict). */
 #define TRANSACTION_NAME_CONFLICT -1
+/* When only creation was requested, but the ref already exists. */
+#define TRANSACTION_CREATE_EXISTS -2
 /* All other errors. */
-#define TRANSACTION_GENERIC_ERROR -2
+#define TRANSACTION_GENERIC_ERROR -3
 
 /*
  * Perform the preparatory stages of committing `transaction`. Acquire
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 8415f2d020..272ad81315 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2502,14 +2502,18 @@  static int split_symref_update(struct ref_update *update,
 static int check_old_oid(struct ref_update *update, struct object_id *oid,
 			 struct strbuf *err)
 {
+	int ret = TRANSACTION_GENERIC_ERROR;
+
 	if (!(update->flags & REF_HAVE_OLD) ||
 		   oideq(oid, &update->old_oid))
 		return 0;
 
-	if (is_null_oid(&update->old_oid))
+	if (is_null_oid(&update->old_oid)) {
 		strbuf_addf(err, "cannot lock ref '%s': "
 			    "reference already exists",
 			    ref_update_original_update_refname(update));
+		ret = TRANSACTION_CREATE_EXISTS;
+	}
 	else if (is_null_oid(oid))
 		strbuf_addf(err, "cannot lock ref '%s': "
 			    "reference is missing but expected %s",
@@ -2522,7 +2526,7 @@  static int check_old_oid(struct ref_update *update, struct object_id *oid,
 			    oid_to_hex(oid),
 			    oid_to_hex(&update->old_oid));
 
-	return -1;
+	return ret;
 }
 
 /*
@@ -2603,9 +2607,13 @@  static int lock_ref_for_update(struct files_ref_store *refs,
 					ret = TRANSACTION_GENERIC_ERROR;
 					goto out;
 				}
-			} else if  (check_old_oid(update, &lock->old_oid, err)) {
-				ret = TRANSACTION_GENERIC_ERROR;
-				goto out;
+			} else {
+				int checkret;
+				checkret = check_old_oid(update, &lock->old_oid, err);
+				if  (checkret) {
+					ret = checkret;
+					goto out;
+				}
 			}
 		} else {
 			/*
@@ -2636,9 +2644,13 @@  static int lock_ref_for_update(struct files_ref_store *refs,
 				    update->old_target);
 			ret = TRANSACTION_GENERIC_ERROR;
 			goto out;
-		} else if  (check_old_oid(update, &lock->old_oid, err)) {
-			ret = TRANSACTION_GENERIC_ERROR;
-			goto out;
+		} else {
+			int checkret;
+			checkret = check_old_oid(update, &lock->old_oid, err);
+			if  (checkret) {
+				ret = checkret;
+				goto out;
+			}
 		}
 
 		/*
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 32330b6bc6..c6b25ebac4 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1206,10 +1206,13 @@  static int reftable_be_transaction_prepare(struct ref_store *ref_store,
 				goto done;
 			}
 		} else if ((u->flags & REF_HAVE_OLD) && !oideq(&current_oid, &u->old_oid)) {
-			if (is_null_oid(&u->old_oid))
+			ret = TRANSACTION_NAME_CONFLICT;
+			if (is_null_oid(&u->old_oid)) {
 				strbuf_addf(err, _("cannot lock ref '%s': "
 						   "reference already exists"),
 					    ref_update_original_update_refname(u));
+				ret = TRANSACTION_CREATE_EXISTS;
+			}
 			else if (is_null_oid(&current_oid))
 				strbuf_addf(err, _("cannot lock ref '%s': "
 						   "reference is missing but expected %s"),
@@ -1221,7 +1224,6 @@  static int reftable_be_transaction_prepare(struct ref_store *ref_store,
 					    ref_update_original_update_refname(u),
 					    oid_to_hex(&current_oid),
 					    oid_to_hex(&u->old_oid));
-			ret = -1;
 			goto done;
 		}