diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-05-02 11:24:43 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-05-02 15:40:35 +0300 |
commit | d07ed513fd4723ed9c1af1cd749ccc478e38aab9 (patch) | |
tree | cd6c6f110d1c17e71ed26080e78047de01816a2b | |
parent | e134a10baea70bbf661a7ba4d9d3857809f87564 (diff) |
Makefile: Install bundled Git v2.36.0.gl1
Install bundled Git v2.36.0.gl1 alongside v2.35.1.gl1. Note that we
carry forward a set of patches from the old version which hasn't made
it into the final release yet.
Changelog: added
7 files changed, 686 insertions, 0 deletions
@@ -302,13 +302,17 @@ install: build .PHONY: build-bundled-git ## Build bundled Git binaries. build-bundled-git: build-bundled-git-v2.35.1.gl1 +build-bundled-git: build-bundled-git-v2.36.0.gl1 build-bundled-git-v2.35.1.gl1: $(patsubst %,${BUILD_DIR}/bin/gitaly-%-v2.35.1.gl1,${GIT_EXECUTABLES}) +build-bundled-git-v2.36.0.gl1: $(patsubst %,${BUILD_DIR}/bin/gitaly-%-v2.36.0.gl1,${GIT_EXECUTABLES}) .PHONY: install-bundled-git ## Install bundled Git binaries. The target directory can be modified by ## setting PREFIX and DESTDIR. install-bundled-git: install-bundled-git-v2.35.1.gl1 +install-bundled-git: install-bundled-git-v2.36.0.gl1 install-bundled-git-v2.35.1.gl1: $(patsubst %,${INSTALL_DEST_DIR}/gitaly-%-v2.35.1.gl1,${GIT_EXECUTABLES}) +install-bundled-git-v2.36.0.gl1: $(patsubst %,${INSTALL_DEST_DIR}/gitaly-%-v2.36.0.gl1,${GIT_EXECUTABLES}) ifdef WITH_BUNDLED_GIT build: build-bundled-git @@ -575,6 +579,12 @@ ${BUILD_DIR}/bin/gitaly-%-v2.35.1.gl1: override GIT_EXTRA_VERSION = gl1 ${BUILD_DIR}/bin/gitaly-%-v2.35.1.gl1: ${DEPENDENCY_DIR}/git-v2.35.1.gl1/% | ${BUILD_DIR}/bin ${Q}install $< $@ +${BUILD_DIR}/bin/gitaly-%-v2.36.0.gl1: override GIT_PATCHES := $(sort $(wildcard ${SOURCE_DIR}/_support/git-patches/v2.36.0.gl1/*)) +${BUILD_DIR}/bin/gitaly-%-v2.36.0.gl1: override GIT_VERSION = v2.36.0 +${BUILD_DIR}/bin/gitaly-%-v2.36.0.gl1: override GIT_EXTRA_VERSION = gl1 +${BUILD_DIR}/bin/gitaly-%-v2.36.0.gl1: ${DEPENDENCY_DIR}/git-v2.36.0.gl1/% | ${BUILD_DIR}/bin + ${Q}install $< $@ + ${INSTALL_DEST_DIR}/gitaly-%: ${BUILD_DIR}/bin/gitaly-% ${Q}mkdir -p ${@D} ${Q}install $< $@ diff --git a/_support/git-patches/v2.36.0.gl1/0001-refs-extract-packed_refs_delete_refs-to-allow-contro.patch b/_support/git-patches/v2.36.0.gl1/0001-refs-extract-packed_refs_delete_refs-to-allow-contro.patch new file mode 100644 index 000000000..47dd3e41c --- /dev/null +++ b/_support/git-patches/v2.36.0.gl1/0001-refs-extract-packed_refs_delete_refs-to-allow-contro.patch @@ -0,0 +1,156 @@ +From c74f385fb46855ac0db222b6845ddb95e6a36264 Mon Sep 17 00:00:00 2001 +Message-Id: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Mon, 17 Jan 2022 09:12:31 +0100 +Subject: [PATCH 21/34] refs: extract packed_refs_delete_refs() to allow + control of transaction + +When deleting loose refs, then we also have to delete the refs in the +packed backend. This is done by calling `refs_delete_refs()`, which +then uses the packed-backend's logic to delete refs. This doesn't allow +us to exercise any control over the reference transaction which is being +created in the packed backend, which is required in a subsequent commit. + +Extract a new function `packed_refs_delete_refs()`, which hosts most of +the logic to delete refs except for creating the transaction itself. +Like this, we can easily create the transaction in the files backend +and thus exert more control over it. + +Signed-off-by: Patrick Steinhardt <ps@pks.im> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +(cherry picked from commit 69840cc0f7b4f3352903bd2b8f3de7077916c26b) +--- + refs/files-backend.c | 13 ++++++++++--- + refs/packed-backend.c | 26 ++++++++++++++++++++------ + refs/packed-backend.h | 7 +++++++ + 3 files changed, 37 insertions(+), 9 deletions(-) + +diff --git a/refs/files-backend.c b/refs/files-backend.c +index 43a3b882d7..18baea4c6a 100644 +--- a/refs/files-backend.c ++++ b/refs/files-backend.c +@@ -1244,6 +1244,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg, + { + struct files_ref_store *refs = + files_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); ++ struct ref_transaction *transaction = NULL; + struct strbuf err = STRBUF_INIT; + int i, result = 0; + +@@ -1253,10 +1254,14 @@ 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; + +- if (refs_delete_refs(refs->packed_ref_store, msg, refnames, flags)) { +- packed_refs_unlock(refs->packed_ref_store); ++ transaction = ref_store_transaction_begin(refs->packed_ref_store, &err); ++ if (!transaction) ++ goto error; ++ ++ result = packed_refs_delete_refs(refs->packed_ref_store, ++ transaction, msg, refnames, flags); ++ if (result) + goto error; +- } + + packed_refs_unlock(refs->packed_ref_store); + +@@ -1267,6 +1272,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg, + result |= error(_("could not remove reference %s"), refname); + } + ++ ref_transaction_free(transaction); + strbuf_release(&err); + return result; + +@@ -1283,6 +1289,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg, + else + error(_("could not delete references: %s"), err.buf); + ++ ref_transaction_free(transaction); + strbuf_release(&err); + return -1; + } +diff --git a/refs/packed-backend.c b/refs/packed-backend.c +index d91a2018f6..960b43ff76 100644 +--- a/refs/packed-backend.c ++++ b/refs/packed-backend.c +@@ -1521,15 +1521,10 @@ static int packed_initial_transaction_commit(struct ref_store *ref_store, + static int packed_delete_refs(struct ref_store *ref_store, const char *msg, + struct string_list *refnames, unsigned int flags) + { +- struct packed_ref_store *refs = +- packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); + struct strbuf err = STRBUF_INIT; + struct ref_transaction *transaction; +- struct string_list_item *item; + int ret; + +- (void)refs; /* We need the check above, but don't use the variable */ +- + if (!refnames->nr) + return 0; + +@@ -1543,6 +1538,26 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg, + if (!transaction) + return -1; + ++ ret = packed_refs_delete_refs(ref_store, transaction, ++ msg, refnames, flags); ++ ++ ref_transaction_free(transaction); ++ return ret; ++} ++ ++int packed_refs_delete_refs(struct ref_store *ref_store, ++ struct ref_transaction *transaction, ++ const char *msg, ++ struct string_list *refnames, ++ unsigned int flags) ++{ ++ struct strbuf err = STRBUF_INIT; ++ struct string_list_item *item; ++ int ret; ++ ++ /* Assert that the ref store refers to a packed backend. */ ++ packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); ++ + for_each_string_list_item(item, refnames) { + if (ref_transaction_delete(transaction, item->string, NULL, + flags, msg, &err)) { +@@ -1562,7 +1577,6 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg, + error(_("could not delete references: %s"), err.buf); + } + +- ref_transaction_free(transaction); + strbuf_release(&err); + return ret; + } +diff --git a/refs/packed-backend.h b/refs/packed-backend.h +index 9dd8a344c3..52e0490753 100644 +--- a/refs/packed-backend.h ++++ b/refs/packed-backend.h +@@ -3,6 +3,7 @@ + + struct repository; + struct ref_transaction; ++struct string_list; + + /* + * Support for storing references in a `packed-refs` file. +@@ -27,6 +28,12 @@ int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err) + void packed_refs_unlock(struct ref_store *ref_store); + int packed_refs_is_locked(struct ref_store *ref_store); + ++int packed_refs_delete_refs(struct ref_store *ref_store, ++ struct ref_transaction *transaction, ++ const char *msg, ++ struct string_list *refnames, ++ unsigned int flags); ++ + /* + * Return true if `transaction` really needs to be carried out against + * the specified packed_ref_store, or false if it can be skipped +-- +2.35.1 + diff --git a/_support/git-patches/v2.36.0.gl1/0002-refs-allow-passing-flags-when-beginning-transactions.patch b/_support/git-patches/v2.36.0.gl1/0002-refs-allow-passing-flags-when-beginning-transactions.patch new file mode 100644 index 000000000..8038daca2 --- /dev/null +++ b/_support/git-patches/v2.36.0.gl1/0002-refs-allow-passing-flags-when-beginning-transactions.patch @@ -0,0 +1,183 @@ +From 60d0682e02db5c197c09bc4cd5a643dc2269cca2 Mon Sep 17 00:00:00 2001 +Message-Id: <60d0682e02db5c197c09bc4cd5a643dc2269cca2.1646206541.git.ps@pks.im> +In-Reply-To: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +References: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Mon, 17 Jan 2022 09:12:35 +0100 +Subject: [PATCH 22/34] refs: allow passing flags when beginning transactions + +We do not currently have any flags when creating reference transactions, +but we'll add one to disable execution of the reference transaction hook +in some cases. + +Allow passing flags to `ref_store_transaction_begin()` to prepare for +this change. + +Signed-off-by: Patrick Steinhardt <ps@pks.im> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +(cherry picked from commit fbe73f61cbc29f6c4a85478cf792c37dbe5aa26c) +--- + refs.c | 8 +++++--- + refs.h | 3 ++- + refs/files-backend.c | 10 +++++----- + refs/packed-backend.c | 2 +- + refs/refs-internal.h | 1 + + sequencer.c | 2 +- + 6 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/refs.c b/refs.c +index addb26293b..f498d232e5 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, &err); ++ transaction = ref_store_transaction_begin(refs, 0, &err); + if (!transaction || + ref_transaction_delete(transaction, refname, old_oid, + flags, msg, &err) || +@@ -1005,6 +1005,7 @@ int read_ref_at(struct ref_store *refs, const char *refname, + } + + struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, ++ unsigned int flags, + struct strbuf *err) + { + struct ref_transaction *tr; +@@ -1012,12 +1013,13 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, + + CALLOC_ARRAY(tr, 1); + tr->ref_store = refs; ++ tr->flags = flags; + return tr; + } + + struct ref_transaction *ref_transaction_begin(struct strbuf *err) + { +- return ref_store_transaction_begin(get_main_ref_store(the_repository), err); ++ return ref_store_transaction_begin(get_main_ref_store(the_repository), 0, err); + } + + void ref_transaction_free(struct ref_transaction *transaction) +@@ -1156,7 +1158,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, &err); ++ t = ref_store_transaction_begin(refs, 0, &err); + if (!t || + ref_transaction_update(t, refname, new_oid, old_oid, flags, msg, + &err) || +diff --git a/refs.h b/refs.h +index 8f91a7f9ff..3a141d7066 100644 +--- a/refs.h ++++ b/refs.h +@@ -231,7 +231,7 @@ char *repo_default_branch_name(struct repository *r, int quiet); + * struct strbuf err = STRBUF_INIT; + * int ret = 0; + * +- * transaction = ref_store_transaction_begin(refs, &err); ++ * transaction = ref_store_transaction_begin(refs, 0, &err); + * if (!transaction || + * ref_transaction_update(...) || + * ref_transaction_create(...) || +@@ -573,6 +573,7 @@ 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_transaction_begin(struct strbuf *err); + +diff --git a/refs/files-backend.c b/refs/files-backend.c +index 18baea4c6a..758d12a0fa 100644 +--- a/refs/files-backend.c ++++ b/refs/files-backend.c +@@ -1116,7 +1116,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, &err); ++ transaction = ref_store_transaction_begin(&refs->base, 0, &err); + if (!transaction) + goto cleanup; + ref_transaction_add_update( +@@ -1187,7 +1187,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, &err); ++ transaction = ref_store_transaction_begin(refs->packed_ref_store, 0, &err); + if (!transaction) + return -1; + +@@ -1254,7 +1254,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, &err); ++ transaction = ref_store_transaction_begin(refs->packed_ref_store, 0, &err); + if (!transaction) + goto error; + +@@ -2769,7 +2769,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, + */ + if (!packed_transaction) { + packed_transaction = ref_store_transaction_begin( +- refs->packed_ref_store, err); ++ refs->packed_ref_store, 0, err); + if (!packed_transaction) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; +@@ -3040,7 +3040,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, err); ++ packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, 0, err); + if (!packed_transaction) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; +diff --git a/refs/packed-backend.c b/refs/packed-backend.c +index 960b43ff76..27dd8c3922 100644 +--- a/refs/packed-backend.c ++++ b/refs/packed-backend.c +@@ -1534,7 +1534,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, &err); ++ transaction = ref_store_transaction_begin(ref_store, 0, &err); + if (!transaction) + return -1; + +diff --git a/refs/refs-internal.h b/refs/refs-internal.h +index 7ff6fba4f0..6e15db3ca4 100644 +--- a/refs/refs-internal.h ++++ b/refs/refs-internal.h +@@ -213,6 +213,7 @@ struct ref_transaction { + size_t nr; + enum ref_transaction_state state; + void *backend_data; ++ unsigned int flags; + }; + + /* +diff --git a/sequencer.c b/sequencer.c +index 5213d16e97..5a2b609557 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, &err); ++ transaction = ref_store_transaction_begin(refs, 0, &err); + if (!transaction) { + error("%s", err.buf); + ret = -1; +-- +2.35.1 + diff --git a/_support/git-patches/v2.36.0.gl1/0003-refs-allow-skipping-the-reference-transaction-hook.patch b/_support/git-patches/v2.36.0.gl1/0003-refs-allow-skipping-the-reference-transaction-hook.patch new file mode 100644 index 000000000..cd194f8aa --- /dev/null +++ b/_support/git-patches/v2.36.0.gl1/0003-refs-allow-skipping-the-reference-transaction-hook.patch @@ -0,0 +1,60 @@ +From 4eccd16b45516df5ab02288d0c50c16e03cc44e4 Mon Sep 17 00:00:00 2001 +Message-Id: <4eccd16b45516df5ab02288d0c50c16e03cc44e4.1646206541.git.ps@pks.im> +In-Reply-To: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +References: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Mon, 17 Jan 2022 09:12:39 +0100 +Subject: [PATCH 23/34] refs: allow skipping the reference-transaction hook + +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> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +(cherry picked from commit 958fbc74e3d0fcc88b2065190e23db556a963644) +--- + refs.c | 3 +++ + refs.h | 5 +++++ + 2 files changed, 8 insertions(+) + +diff --git a/refs.c b/refs.c +index f498d232e5..435b90b1ec 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 3a141d7066..a015354fd6 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(). +-- +2.35.1 + diff --git a/_support/git-patches/v2.36.0.gl1/0004-refs-demonstrate-excessive-execution-of-the-referenc.patch b/_support/git-patches/v2.36.0.gl1/0004-refs-demonstrate-excessive-execution-of-the-referenc.patch new file mode 100644 index 000000000..aa6d96a3e --- /dev/null +++ b/_support/git-patches/v2.36.0.gl1/0004-refs-demonstrate-excessive-execution-of-the-referenc.patch @@ -0,0 +1,97 @@ +From 079f96ed16bb70f99fbe810b1646b1709bb82871 Mon Sep 17 00:00:00 2001 +Message-Id: <079f96ed16bb70f99fbe810b1646b1709bb82871.1646206541.git.ps@pks.im> +In-Reply-To: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +References: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Mon, 17 Jan 2022 09:12:44 +0100 +Subject: [PATCH 24/34] refs: demonstrate excessive execution of the + reference-transaction hook + +Add tests which demonstate that we're executing the +reference-transaction hook too often in some cases, which thus leaks +implementation details about the reference store's implementation +itself. Behaviour will be fixed in follow-up commits. + +Signed-off-by: Patrick Steinhardt <ps@pks.im> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +(cherry picked from commit 2ce825436268d6409bee8ebb5f5500b7ff172b1e) +--- + t/t1416-ref-transaction-hooks.sh | 64 ++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh +index 6c941027a8..0567fbdf0b 100755 +--- a/t/t1416-ref-transaction-hooks.sh ++++ b/t/t1416-ref-transaction-hooks.sh +@@ -136,4 +136,68 @@ test_expect_success 'interleaving hook calls succeed' ' + test_cmp expect target-repo.git/actual + ' + ++test_expect_success 'hook does not get called on packing refs' ' ++ # Pack references first such that we are in a known state. ++ git pack-refs --all && ++ ++ write_script .git/hooks/reference-transaction <<-\EOF && ++ echo "$@" >>actual ++ cat >>actual ++ EOF ++ rm -f actual && ++ ++ git update-ref refs/heads/unpacked-ref $POST_OID && ++ git pack-refs --all && ++ ++ # We only expect a single hook invocation, which is the call to ++ # git-update-ref(1). But currently, packing refs will also trigger the ++ # hook. ++ cat >expect <<-EOF && ++ prepared ++ $ZERO_OID $POST_OID refs/heads/unpacked-ref ++ committed ++ $ZERO_OID $POST_OID refs/heads/unpacked-ref ++ prepared ++ $ZERO_OID $POST_OID refs/heads/unpacked-ref ++ committed ++ $ZERO_OID $POST_OID refs/heads/unpacked-ref ++ prepared ++ $POST_OID $ZERO_OID refs/heads/unpacked-ref ++ committed ++ $POST_OID $ZERO_OID refs/heads/unpacked-ref ++ EOF ++ ++ test_cmp expect actual ++' ++ ++test_expect_success 'deleting packed ref calls hook once' ' ++ # Create a reference and pack it. ++ git update-ref refs/heads/to-be-deleted $POST_OID && ++ git pack-refs --all && ++ ++ write_script .git/hooks/reference-transaction <<-\EOF && ++ echo "$@" >>actual ++ cat >>actual ++ EOF ++ rm -f actual && ++ ++ git update-ref -d refs/heads/to-be-deleted $POST_OID && ++ ++ # We only expect a single hook invocation, which is the logical ++ # deletion. But currently, we see two interleaving transactions, once ++ # for deleting the loose refs and once for deleting the packed ref. ++ cat >expect <<-EOF && ++ prepared ++ $ZERO_OID $ZERO_OID refs/heads/to-be-deleted ++ prepared ++ $POST_OID $ZERO_OID refs/heads/to-be-deleted ++ committed ++ $ZERO_OID $ZERO_OID refs/heads/to-be-deleted ++ committed ++ $POST_OID $ZERO_OID refs/heads/to-be-deleted ++ EOF ++ ++ test_cmp expect actual ++' ++ + test_done +-- +2.35.1 + diff --git a/_support/git-patches/v2.36.0.gl1/0005-refs-do-not-execute-reference-transaction-hook-on-pa.patch b/_support/git-patches/v2.36.0.gl1/0005-refs-do-not-execute-reference-transaction-hook-on-pa.patch new file mode 100644 index 000000000..f2e7c06ed --- /dev/null +++ b/_support/git-patches/v2.36.0.gl1/0005-refs-do-not-execute-reference-transaction-hook-on-pa.patch @@ -0,0 +1,81 @@ +From ef35ab926309bf406d3871679c576c718708a93b Mon Sep 17 00:00:00 2001 +Message-Id: <ef35ab926309bf406d3871679c576c718708a93b.1646206541.git.ps@pks.im> +In-Reply-To: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +References: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Mon, 17 Jan 2022 09:12:48 +0100 +Subject: [PATCH 25/34] refs: do not execute reference-transaction hook on + packing refs + +The reference-transaction hook is supposed to track logical changes to +references, but it currently also gets executed when packing refs in a +repository. This is unexpected and ultimately not all that useful: +packing refs is not supposed to result in any user-visible change to the +refs' state, and it ultimately is an implementation detail of how refs +stores work. + +Fix this excessive execution of the hook when packing refs. + +Reported-by: Waleed Khan <me@waleedkhan.name> +Signed-off-by: Patrick Steinhardt <ps@pks.im> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +(cherry picked from commit ffad9941383465553bf26d88050f3243726f30df) +--- + refs/files-backend.c | 6 ++++-- + t/t1416-ref-transaction-hooks.sh | 11 +---------- + 2 files changed, 5 insertions(+), 12 deletions(-) + +diff --git a/refs/files-backend.c b/refs/files-backend.c +index 758d12a0fa..19f43e8d29 100644 +--- a/refs/files-backend.c ++++ b/refs/files-backend.c +@@ -1116,7 +1116,8 @@ 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, 0, &err); ++ transaction = ref_store_transaction_begin(&refs->base, ++ REF_TRANSACTION_SKIP_HOOK, &err); + if (!transaction) + goto cleanup; + ref_transaction_add_update( +@@ -1187,7 +1188,8 @@ 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, 0, &err); ++ transaction = ref_store_transaction_begin(refs->packed_ref_store, ++ REF_TRANSACTION_SKIP_HOOK, &err); + if (!transaction) + return -1; + +diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh +index 0567fbdf0b..f9d3d5213f 100755 +--- a/t/t1416-ref-transaction-hooks.sh ++++ b/t/t1416-ref-transaction-hooks.sh +@@ -150,21 +150,12 @@ test_expect_success 'hook does not get called on packing refs' ' + git pack-refs --all && + + # We only expect a single hook invocation, which is the call to +- # git-update-ref(1). But currently, packing refs will also trigger the +- # hook. ++ # git-update-ref(1). + cat >expect <<-EOF && + prepared + $ZERO_OID $POST_OID refs/heads/unpacked-ref + committed + $ZERO_OID $POST_OID refs/heads/unpacked-ref +- prepared +- $ZERO_OID $POST_OID refs/heads/unpacked-ref +- committed +- $ZERO_OID $POST_OID refs/heads/unpacked-ref +- prepared +- $POST_OID $ZERO_OID refs/heads/unpacked-ref +- committed +- $POST_OID $ZERO_OID refs/heads/unpacked-ref + EOF + + test_cmp expect actual +-- +2.35.1 + diff --git a/_support/git-patches/v2.36.0.gl1/0006-refs-skip-hooks-when-deleting-uncovered-packed-refs.patch b/_support/git-patches/v2.36.0.gl1/0006-refs-skip-hooks-when-deleting-uncovered-packed-refs.patch new file mode 100644 index 000000000..3b21bf489 --- /dev/null +++ b/_support/git-patches/v2.36.0.gl1/0006-refs-skip-hooks-when-deleting-uncovered-packed-refs.patch @@ -0,0 +1,99 @@ +From d56f2a0e1eed4d0a39b99638117e0c8259e5078d Mon Sep 17 00:00:00 2001 +Message-Id: <d56f2a0e1eed4d0a39b99638117e0c8259e5078d.1646206542.git.ps@pks.im> +In-Reply-To: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +References: <c74f385fb46855ac0db222b6845ddb95e6a36264.1646206541.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Mon, 17 Jan 2022 09:12:53 +0100 +Subject: [PATCH 26/34] refs: skip hooks when deleting uncovered packed refs + +When deleting refs from the loose-files refs backend, then we need to be +careful to also delete the same ref from the packed refs backend, if it +exists. If we don't, then deleting the loose ref would "uncover" the +packed ref. We thus always have to queue up deletions of refs for both +the loose and the packed refs backend. This is done in two separate +transactions, where the end result is that the reference-transaction +hook is executed twice for the deleted refs. + +This behaviour is quite misleading: it's exposing implementation details +of how the files backend works to the user, in contrast to the logical +updates that we'd really want to expose via the hook. Worse yet, whether +the hook gets executed once or twice depends on how well-packed the +repository is: if the ref only exists as a loose ref, then we execute it +once, otherwise if it is also packed then we execute it twice. + +Fix this behaviour and don't execute the reference-transaction hook at +all when refs in the packed-refs backend if it's driven by the files +backend. This works as expected even in case the refs to be deleted only +exist in the packed-refs backend because the loose-backend always queues +refs in its own transaction even if they don't exist such that they can +be locked for concurrent creation. And it also does the right thing in +case neither of the backends has the ref because that would cause the +transaction to fail completely. + +Signed-off-by: Patrick Steinhardt <ps@pks.im> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +(cherry picked from commit 2ed1b64ebdeefc7f9473ae159fb45ff0c6cf121a) +--- + refs/files-backend.c | 9 ++++++--- + t/t1416-ref-transaction-hooks.sh | 7 +------ + 2 files changed, 7 insertions(+), 9 deletions(-) + +diff --git a/refs/files-backend.c b/refs/files-backend.c +index 19f43e8d29..c931dd479c 100644 +--- a/refs/files-backend.c ++++ b/refs/files-backend.c +@@ -1256,7 +1256,8 @@ 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, 0, &err); ++ transaction = ref_store_transaction_begin(refs->packed_ref_store, ++ REF_TRANSACTION_SKIP_HOOK, &err); + if (!transaction) + goto error; + +@@ -2771,7 +2772,8 @@ static int files_transaction_prepare(struct ref_store *ref_store, + */ + if (!packed_transaction) { + packed_transaction = ref_store_transaction_begin( +- refs->packed_ref_store, 0, err); ++ refs->packed_ref_store, ++ REF_TRANSACTION_SKIP_HOOK, err); + if (!packed_transaction) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; +@@ -3042,7 +3044,8 @@ 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, 0, err); ++ packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, ++ REF_TRANSACTION_SKIP_HOOK, err); + if (!packed_transaction) { + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; +diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh +index f9d3d5213f..4e1e84a91f 100755 +--- a/t/t1416-ref-transaction-hooks.sh ++++ b/t/t1416-ref-transaction-hooks.sh +@@ -175,16 +175,11 @@ test_expect_success 'deleting packed ref calls hook once' ' + git update-ref -d refs/heads/to-be-deleted $POST_OID && + + # We only expect a single hook invocation, which is the logical +- # deletion. But currently, we see two interleaving transactions, once +- # for deleting the loose refs and once for deleting the packed ref. ++ # deletion. + cat >expect <<-EOF && +- prepared +- $ZERO_OID $ZERO_OID refs/heads/to-be-deleted + prepared + $POST_OID $ZERO_OID refs/heads/to-be-deleted + committed +- $ZERO_OID $ZERO_OID refs/heads/to-be-deleted +- committed + $POST_OID $ZERO_OID refs/heads/to-be-deleted + EOF + +-- +2.35.1 + |