diff mbox series

[v4,04/12] refs: allow to skip creation of reflog entries

Message ID d0539b7456e29fad5c2d1af76657207a199a5d9a.1717402363.git.ps@pks.im (mailing list archive)
State Superseded
Commit 1c8a2a59c6309c4597d0ea3758d5e0983a3e73fd
Headers show
Series refs: ref storage migrations | expand

Commit Message

Patrick Steinhardt June 3, 2024, 9:30 a.m. UTC
The ref backends do not have any way to disable the creation of reflog
entries. This will be required for upcoming ref format migration logic
so that we do not create any entries that didn't exist in the original
ref database.

Provide a new `REF_SKIP_CREATE_REFLOG` flag that allows the caller to
disable reflog entry creation.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs.c                    | 6 ++++++
 refs.h                    | 8 +++++++-
 refs/files-backend.c      | 4 ++++
 refs/reftable-backend.c   | 3 ++-
 t/helper/test-ref-store.c | 1 +
 5 files changed, 20 insertions(+), 2 deletions(-)

Comments

Karthik Nayak June 4, 2024, 11:04 a.m. UTC | #1
Patrick Steinhardt <ps@pks.im> writes:

[snip]

> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index 73380d7e99..bd0d63bcba 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -1750,6 +1750,9 @@ static int files_log_ref_write(struct files_ref_store *refs,
>  {
>  	int logfd, result;
>
> +	if (flags & REF_SKIP_CREATE_REFLOG)
> +		return 0;
> +
>  	if (log_all_ref_updates == LOG_REFS_UNSET)
>  		log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
>
> @@ -2251,6 +2254,7 @@ static int split_head_update(struct ref_update *update,
>  	struct ref_update *new_update;
>
>  	if ((update->flags & REF_LOG_ONLY) ||
> +	    (update->flags & REF_SKIP_CREATE_REFLOG) ||
>  	    (update->flags & REF_IS_PRUNING) ||
>  	    (update->flags & REF_UPDATE_VIA_HEAD))
>  		return 0;

So updates to refs which are pointed by HEAD usually trigger a reflog
entry for HEAD itself. Here we skip that since REF_SKIP_CREATE_REFLOG is
set. Nice, this is an edge case that could have been easy to miss.

> diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
> index f6edfdf5b3..bffed9257f 100644
> --- a/refs/reftable-backend.c
> +++ b/refs/reftable-backend.c
> @@ -1103,7 +1103,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
>
>  			if (ret)
>  				goto done;
> -		} else if (u->flags & REF_HAVE_NEW &&
> +		} else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&
> +			   (u->flags & REF_HAVE_NEW) &&
>  			   (u->flags & REF_FORCE_CREATE_REFLOG ||
>  			    should_write_log(&arg->refs->base, u->refname))) {
>  			struct reftable_log_record *log;
> diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
> index c9efd74c2b..ad24300170 100644
> --- a/t/helper/test-ref-store.c
> +++ b/t/helper/test-ref-store.c
> @@ -126,6 +126,7 @@ static struct flag_definition transaction_flags[] = {
>  	FLAG_DEF(REF_FORCE_CREATE_REFLOG),
>  	FLAG_DEF(REF_SKIP_OID_VERIFICATION),
>  	FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION),
> +	FLAG_DEF(REF_SKIP_CREATE_REFLOG),
>  	{ NULL, 0 }
>  };
>
> --
> 2.45.1.410.g58bac47f8e.dirty
diff mbox series

Patch

diff --git a/refs.c b/refs.c
index 7c3f4df457..66e9585767 100644
--- a/refs.c
+++ b/refs.c
@@ -1194,6 +1194,12 @@  int ref_transaction_update(struct ref_transaction *transaction,
 {
 	assert(err);
 
+	if ((flags & REF_FORCE_CREATE_REFLOG) &&
+	    (flags & REF_SKIP_CREATE_REFLOG)) {
+		strbuf_addstr(err, _("refusing to force and skip creation of reflog"));
+		return -1;
+	}
+
 	if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
 	    ((new_oid && !is_null_oid(new_oid)) ?
 		     check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
diff --git a/refs.h b/refs.h
index a7afa9bede..50a2b3ab09 100644
--- a/refs.h
+++ b/refs.h
@@ -659,13 +659,19 @@  struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
  */
 #define REF_SKIP_REFNAME_VERIFICATION (1 << 11)
 
+/*
+ * Skip creation of a reflog entry, even if it would have otherwise been
+ * created.
+ */
+#define REF_SKIP_CREATE_REFLOG (1 << 12)
+
 /*
  * Bitmask of all of the flags that are allowed to be passed in to
  * ref_transaction_update() and friends:
  */
 #define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS                                  \
 	(REF_NO_DEREF | REF_FORCE_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION | \
-	 REF_SKIP_REFNAME_VERIFICATION)
+	 REF_SKIP_REFNAME_VERIFICATION | REF_SKIP_CREATE_REFLOG)
 
 /*
  * Add a reference update to transaction. `new_oid` is the value that
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 73380d7e99..bd0d63bcba 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1750,6 +1750,9 @@  static int files_log_ref_write(struct files_ref_store *refs,
 {
 	int logfd, result;
 
+	if (flags & REF_SKIP_CREATE_REFLOG)
+		return 0;
+
 	if (log_all_ref_updates == LOG_REFS_UNSET)
 		log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
 
@@ -2251,6 +2254,7 @@  static int split_head_update(struct ref_update *update,
 	struct ref_update *new_update;
 
 	if ((update->flags & REF_LOG_ONLY) ||
+	    (update->flags & REF_SKIP_CREATE_REFLOG) ||
 	    (update->flags & REF_IS_PRUNING) ||
 	    (update->flags & REF_UPDATE_VIA_HEAD))
 		return 0;
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index f6edfdf5b3..bffed9257f 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1103,7 +1103,8 @@  static int write_transaction_table(struct reftable_writer *writer, void *cb_data
 
 			if (ret)
 				goto done;
-		} else if (u->flags & REF_HAVE_NEW &&
+		} else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&
+			   (u->flags & REF_HAVE_NEW) &&
 			   (u->flags & REF_FORCE_CREATE_REFLOG ||
 			    should_write_log(&arg->refs->base, u->refname))) {
 			struct reftable_log_record *log;
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index c9efd74c2b..ad24300170 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -126,6 +126,7 @@  static struct flag_definition transaction_flags[] = {
 	FLAG_DEF(REF_FORCE_CREATE_REFLOG),
 	FLAG_DEF(REF_SKIP_OID_VERIFICATION),
 	FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION),
+	FLAG_DEF(REF_SKIP_CREATE_REFLOG),
 	{ NULL, 0 }
 };