git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: Patrick Steinhardt <ps@pks.im>
Cc: git@vger.kernel.org, Jeff King <peff@peff.net>,
	Bryan Turner <bturner@atlassian.com>,
	Waleed Khan <me@waleedkhan.name>,
	Han-Wen Nienhuys <hanwen@google.com>
Subject: Re: [PATCH v3 3/6] refs: allow skipping the reference-transaction hook
Date: Thu, 13 Jan 2022 14:34:41 +0100	[thread overview]
Message-ID: <220113.86zgnzu48q.gmgdl@evledraar.gmail.com> (raw)
In-Reply-To: <be826bae3b564fe003778ea10cb2e06fc753c21d.1642054003.git.ps@pks.im>


On Thu, Jan 13 2022, Patrick Steinhardt wrote:

> [[PGP Signed Part:Undecided]]
> The reference-transaction hook is executing whenever we prepare, commit
> or abort a reference transaction. While this is mostly intentional, in
> case of the files backend we're leaking the implementation detail that
> the store is in fact a composite store with one loose and one packed
> backend to the caller. So while we want to execute the hook for all
> logical updates, executing it for such implementation details is
> unexpected.
>
> Prepare for a fix by adding a new flag which allows to skip execution of
> the hook.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  refs.c | 3 +++
>  refs.h | 5 +++++
>  2 files changed, 8 insertions(+)
>
> diff --git a/refs.c b/refs.c
> index 7415864b62..526bf5ed97 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -2084,6 +2084,9 @@ static int run_transaction_hook(struct ref_transaction *transaction,
>  	const char *hook;
>  	int ret = 0, i;
>  
> +	if (transaction->flags & REF_TRANSACTION_SKIP_HOOK)
> +		return 0;
> +
>  	hook = find_hook("reference-transaction");
>  	if (!hook)
>  		return ret;
> diff --git a/refs.h b/refs.h
> index 31f7bf9642..d4056f9fe2 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -568,6 +568,11 @@ enum action_on_err {
>  	UPDATE_REFS_QUIET_ON_ERR
>  };
>  
> +/*
> + * Skip executing the reference-transaction hook.
> + */
> +#define REF_TRANSACTION_SKIP_HOOK (1 << 0)
> +
>  /*
>   * Begin a reference transaction.  The reference transaction must
>   * be freed by calling ref_transaction_free().

This isn't needed in refs.h, so let's put it in refs-internal.h where
e.g. "enum ref_transaction_state" now lives:
    
    diff --git a/refs.h b/refs.h
    index d4056f9fe26..31f7bf96424 100644
    --- a/refs.h
    +++ b/refs.h
    @@ -568,11 +568,6 @@ enum action_on_err {
            UPDATE_REFS_QUIET_ON_ERR
     };
     
    -/*
    - * Skip executing the reference-transaction hook.
    - */
    -#define REF_TRANSACTION_SKIP_HOOK (1 << 0)
    -
     /*
      * Begin a reference transaction.  The reference transaction must
      * be freed by calling ref_transaction_free().
    diff --git a/refs/refs-internal.h b/refs/refs-internal.h
    index a0af63f162f..87da39243f7 100644
    --- a/refs/refs-internal.h
    +++ b/refs/refs-internal.h
    @@ -201,6 +201,11 @@ enum ref_transaction_state {
            REF_TRANSACTION_CLOSED   = 2
     };
     
    +/*
    + * Skip executing the reference-transaction hook.
    + */
    +#define REF_TRANSACTION_SKIP_HOOK (1 << 0)
    +
     /*
      * Data structure for holding a reference transaction, which can
      * consist of checks and updates to multiple references, carried out

A bit more odd is that this series ends up with a
ref_transaction_begin() that doesn't correspond to its ref_store_*()
parent, i.e. the others pass the ref store for you, but now we omit the
flags too.

I see why you did that, to avoid tweaking every existing
ref_transaction_begin() caller.

But isn't something like the below a better approach? We can introduce a
refs-internal.h-only flag enum, and then just have a new
ref_store_transaction_begin_no_hook() called from these new
files-backend.c users.

The diff on top is a bit verbose, but the exposed API is cleaner
(presumably no "public" user should be allowed to skip the hook), and
the overall diff if this is squashed in is smaller.

diff --git a/refs.c b/refs.c
index 526bf5ed97a..ffaf34e9710 100644
--- a/refs.c
+++ b/refs.c
@@ -800,7 +800,7 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
 	struct ref_transaction *transaction;
 	struct strbuf err = STRBUF_INIT;
 
-	transaction = ref_store_transaction_begin(refs, 0, &err);
+	transaction = ref_store_transaction_begin(refs, &err);
 	if (!transaction ||
 	    ref_transaction_delete(transaction, refname, old_oid,
 				   flags, msg, &err) ||
@@ -1004,22 +1004,36 @@ int read_ref_at(struct ref_store *refs, const char *refname,
 	return 1;
 }
 
-struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
-						    unsigned int flags,
-						    struct strbuf *err)
+static struct ref_transaction *ref_store_transaction_begin_1(struct ref_store *refs,
+							     unsigned int no_hook,
+							     struct strbuf *err)
 {
 	struct ref_transaction *tr;
 	assert(err);
 
 	CALLOC_ARRAY(tr, 1);
 	tr->ref_store = refs;
-	tr->flags = flags;
+	if (no_hook)
+		tr->flags &= REF_TRANSACTION_SKIP_HOOK;
 	return tr;
 }
 
 struct ref_transaction *ref_transaction_begin(struct strbuf *err)
 {
-	return ref_store_transaction_begin(get_main_ref_store(the_repository), 0, err);
+	return ref_store_transaction_begin_1(get_main_ref_store(the_repository),
+					     0, err);
+}
+
+struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
+						    struct strbuf *err)
+{
+	return ref_store_transaction_begin_1(refs, 0, err);
+}
+
+struct ref_transaction *ref_store_transaction_begin_no_hook(struct ref_store *refs,
+							    struct strbuf *err)
+{
+	return ref_store_transaction_begin_1(refs, 1, err);
 }
 
 void ref_transaction_free(struct ref_transaction *transaction)
@@ -1158,7 +1172,7 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
 	struct strbuf err = STRBUF_INIT;
 	int ret = 0;
 
-	t = ref_store_transaction_begin(refs, 0, &err);
+	t = ref_store_transaction_begin(refs, &err);
 	if (!t ||
 	    ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
 				   &err) ||
diff --git a/refs.h b/refs.h
index 31f7bf96424..3663e0347ff 100644
--- a/refs.h
+++ b/refs.h
@@ -573,8 +573,9 @@ enum action_on_err {
  * be freed by calling ref_transaction_free().
  */
 struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
-						    unsigned int flags,
 						    struct strbuf *err);
+struct ref_transaction *ref_store_transaction_begin_no_hook(struct ref_store *refs,
+							    struct strbuf *err);
 struct ref_transaction *ref_transaction_begin(struct strbuf *err);
 
 /*
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 9a20cb8fa89..f85c8f3a692 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1121,8 +1121,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
 	if (check_refname_format(r->name, 0))
 		return;
 
-	transaction = ref_store_transaction_begin(&refs->base,
-						  REF_TRANSACTION_SKIP_HOOK, &err);
+	transaction = ref_store_transaction_begin_no_hook(&refs->base, &err);
 	if (!transaction)
 		goto cleanup;
 	ref_transaction_add_update(
@@ -1193,8 +1192,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
 	struct strbuf err = STRBUF_INIT;
 	struct ref_transaction *transaction;
 
-	transaction = ref_store_transaction_begin(refs->packed_ref_store,
-						  REF_TRANSACTION_SKIP_HOOK, &err);
+	transaction = ref_store_transaction_begin_no_hook(refs->packed_ref_store, &err);
 	if (!transaction)
 		return -1;
 
@@ -1261,8 +1259,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg,
 	if (packed_refs_lock(refs->packed_ref_store, 0, &err))
 		goto error;
 
-	transaction = ref_store_transaction_begin(refs->packed_ref_store,
-						  REF_TRANSACTION_SKIP_HOOK, &err);
+	transaction = ref_store_transaction_begin_no_hook(refs->packed_ref_store, &err);
 	if (!transaction)
 		goto error;
 
@@ -2775,9 +2772,8 @@ static int files_transaction_prepare(struct ref_store *ref_store,
 			 * packed-refs if it exists there.
 			 */
 			if (!packed_transaction) {
-				packed_transaction = ref_store_transaction_begin(
-						refs->packed_ref_store,
-						REF_TRANSACTION_SKIP_HOOK, err);
+				packed_transaction = ref_store_transaction_begin_no_hook(
+						refs->packed_ref_store, err);
 				if (!packed_transaction) {
 					ret = TRANSACTION_GENERIC_ERROR;
 					goto cleanup;
@@ -3048,8 +3044,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
 				 &affected_refnames))
 		BUG("initial ref transaction called with existing refs");
 
-	packed_transaction = ref_store_transaction_begin(refs->packed_ref_store,
-							 REF_TRANSACTION_SKIP_HOOK, err);
+	packed_transaction = ref_store_transaction_begin_no_hook(refs->packed_ref_store, err);
 	if (!packed_transaction) {
 		ret = TRANSACTION_GENERIC_ERROR;
 		goto cleanup;
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index cfebcd0b46e..e97d67f9321 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1535,7 +1535,7 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
 	 * updates into a single transaction.
 	 */
 
-	transaction = ref_store_transaction_begin(ref_store, 0, &err);
+	transaction = ref_store_transaction_begin(ref_store, &err);
 	if (!transaction)
 		return -1;
 
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 87da39243f7..8ff9e0e6e3a 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -204,7 +204,9 @@ enum ref_transaction_state {
 /*
  * Skip executing the reference-transaction hook.
  */
-#define REF_TRANSACTION_SKIP_HOOK (1 << 0)
+enum ref_transaction_flags {
+	REF_TRANSACTION_SKIP_HOOK = 1 << 0,
+};
 
 /*
  * Data structure for holding a reference transaction, which can
@@ -218,7 +220,7 @@ struct ref_transaction {
 	size_t nr;
 	enum ref_transaction_state state;
 	void *backend_data;
-	unsigned int flags;
+	enum ref_transaction_flags flags;
 };
 
 /*
diff --git a/sequencer.c b/sequencer.c
index 61edd39d7a4..6abd72160cc 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -3588,7 +3588,7 @@ static int do_label(struct repository *r, const char *name, int len)
 	strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
 	strbuf_addf(&msg, "rebase (label) '%.*s'", len, name);
 
-	transaction = ref_store_transaction_begin(refs, 0, &err);
+	transaction = ref_store_transaction_begin(refs, &err);
 	if (!transaction) {
 		error("%s", err.buf);
 		ret = -1;

  reply	other threads:[~2022-01-13 13:58 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-07 10:55 [PATCH 0/6] refs: excessive hook execution with packed refs Patrick Steinhardt
2021-12-07 10:55 ` [PATCH 1/6] refs: open-code deletion of " Patrick Steinhardt
2021-12-07 10:56 ` [PATCH 2/6] refs: allow passing flags when beginning transactions Patrick Steinhardt
2021-12-07 10:56 ` [PATCH 3/6] refs: allow skipping the reference-transaction hook Patrick Steinhardt
2021-12-07 10:56 ` [PATCH 4/6] refs: demonstrate excessive execution of " Patrick Steinhardt
2021-12-07 10:56 ` [PATCH 5/6] refs: do not execute reference-transaction hook on packing refs Patrick Steinhardt
2021-12-07 10:56 ` [PATCH 6/6] refs: skip hooks when deleting uncovered packed refs Patrick Steinhardt
2022-01-07 11:55 ` [PATCH v2 0/6] refs: excessive hook execution with " Patrick Steinhardt
2022-01-07 11:55   ` [PATCH v2 1/6] refs: open-code deletion of " Patrick Steinhardt
2022-01-08  0:57     ` Junio C Hamano
2022-01-08  1:51     ` Junio C Hamano
2022-01-13  0:24     ` Junio C Hamano
2022-01-07 11:55   ` [PATCH v2 2/6] refs: allow passing flags when beginning transactions Patrick Steinhardt
2022-01-08  1:51     ` Junio C Hamano
2022-01-07 11:55   ` [PATCH v2 3/6] refs: allow skipping the reference-transaction hook Patrick Steinhardt
2022-01-07 11:55   ` [PATCH v2 4/6] refs: demonstrate excessive execution of " Patrick Steinhardt
2022-01-08  1:31     ` Junio C Hamano
2022-01-10 12:54       ` Patrick Steinhardt
2022-01-08  5:43     ` Eric Sunshine
2022-01-07 11:55   ` [PATCH v2 5/6] refs: do not execute reference-transaction hook on packing refs Patrick Steinhardt
2022-01-07 11:55   ` [PATCH v2 6/6] refs: skip hooks when deleting uncovered packed refs Patrick Steinhardt
2022-01-08  2:01     ` Junio C Hamano
2022-01-10 13:18       ` Patrick Steinhardt
2022-01-10 18:00         ` Junio C Hamano
2022-01-07 22:17   ` [PATCH v2 0/6] refs: excessive hook execution with " Junio C Hamano
2022-01-13 18:24     ` Han-Wen Nienhuys
2022-01-17  7:18       ` Patrick Steinhardt
2022-01-17 11:37         ` Han-Wen Nienhuys
2022-01-24  7:13           ` Patrick Steinhardt
2022-01-13  6:11   ` [PATCH v3 " Patrick Steinhardt
2022-01-13  6:11     ` [PATCH v3 1/6] refs: extract packed_refs_delete_refs() to allow control of transaction Patrick Steinhardt
2022-01-13 12:43       ` Ævar Arnfjörð Bjarmason
2022-01-17  7:36         ` Patrick Steinhardt
2022-01-13  6:11     ` [PATCH v3 2/6] refs: allow passing flags when beginning transactions Patrick Steinhardt
2022-01-13  6:11     ` [PATCH v3 3/6] refs: allow skipping the reference-transaction hook Patrick Steinhardt
2022-01-13 13:34       ` Ævar Arnfjörð Bjarmason [this message]
2022-01-17  8:03         ` Patrick Steinhardt
2022-01-13  6:11     ` [PATCH v3 4/6] refs: demonstrate excessive execution of " Patrick Steinhardt
2022-01-13  6:11     ` [PATCH v3 5/6] refs: do not execute reference-transaction hook on packing refs Patrick Steinhardt
2022-01-13 13:00       ` Ævar Arnfjörð Bjarmason
2022-01-17  7:44         ` Patrick Steinhardt
2022-01-13  6:11     ` [PATCH v3 6/6] refs: skip hooks when deleting uncovered packed refs Patrick Steinhardt
2022-01-13 13:04       ` Ævar Arnfjörð Bjarmason
2022-01-17  7:56         ` Patrick Steinhardt
2022-01-17  8:12   ` [PATCH v4 0/6] refs: excessive hook execution with " Patrick Steinhardt
2022-01-17  8:12     ` [PATCH v4 1/6] refs: extract packed_refs_delete_refs() to allow control of transaction Patrick Steinhardt
2022-01-17  8:12     ` [PATCH v4 2/6] refs: allow passing flags when beginning transactions Patrick Steinhardt
2022-01-17  8:12     ` [PATCH v4 3/6] refs: allow skipping the reference-transaction hook Patrick Steinhardt
2022-01-17  8:12     ` [PATCH v4 4/6] refs: demonstrate excessive execution of " Patrick Steinhardt
2022-01-17  8:12     ` [PATCH v4 5/6] refs: do not execute reference-transaction hook on packing refs Patrick Steinhardt
2022-01-17  8:12     ` [PATCH v4 6/6] refs: skip hooks when deleting uncovered packed refs Patrick Steinhardt

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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=220113.86zgnzu48q.gmgdl@evledraar.gmail.com \
    --to=avarab@gmail.com \
    --cc=bturner@atlassian.com \
    --cc=git@vger.kernel.org \
    --cc=hanwen@google.com \
    --cc=me@waleedkhan.name \
    --cc=peff@peff.net \
    --cc=ps@pks.im \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).