git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] refs: remove virtual `delete_refs()` function
@ 2023-11-14  8:58 Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 1/4] t5510: ensure that the packed-refs file needs locking Patrick Steinhardt
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Patrick Steinhardt @ 2023-11-14  8:58 UTC (permalink / raw)
  To: git; +Cc: David Turner, Han-Wen Nienhuys

[-- Attachment #1: Type: text/plain, Size: 1612 bytes --]

Hi,

this patch series refactors the virtual `delete_refs()` function to
instead be implemented generically via a single reference transaction.

The main intent of this patch series is to reduce complexity that we
have in the reference backends so that it becomes easier to implement
new backends that have the same semantics as others. But at the same
time, benchmarks show that the new generic code is even faster than the
old backend-specific code. This is mostly because we avoid the overhead
of per-reference transactions when deleting many references, but also
because the transactional code in the files backend knows to avoid
rewriting the packed-refs file in case it contains none of the refs that
are to be deleted.

So in the end we have less duplicate code in the files backend, make it
easier to implement new backends, and have faster deletion of many refs
in the files backend.

Patrick

Patrick Steinhardt (4):
  t5510: ensure that the packed-refs file needs locking
  refs/files: use transactions to delete references
  refs: deduplicate code to delete references
  refs: remove `delete_refs` callback from backends

 refs.c                | 48 ++++++++++++++++++++++++++++++++++++++---
 refs/debug.c          | 15 -------------
 refs/files-backend.c  | 49 ------------------------------------------
 refs/packed-backend.c | 50 -------------------------------------------
 refs/refs-internal.h  |  3 ---
 t/t5510-fetch.sh      |  1 +
 6 files changed, 46 insertions(+), 120 deletions(-)


base-commit: e0939bec273052b1a8d69db4a3f7c87aaf83e220
-- 
2.42.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] t5510: ensure that the packed-refs file needs locking
  2023-11-14  8:58 [PATCH 0/4] refs: remove virtual `delete_refs()` function Patrick Steinhardt
@ 2023-11-14  8:58 ` Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 2/4] refs/files: use transactions to delete references Patrick Steinhardt
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Patrick Steinhardt @ 2023-11-14  8:58 UTC (permalink / raw)
  To: git; +Cc: David Turner, Han-Wen Nienhuys

[-- Attachment #1: Type: text/plain, Size: 1569 bytes --]

One of the tests in t5510 asserts that a `git fetch --prune` detects
failures to prune branches. This is done by locking the packed-refs
file, which would then later lead to a locking issue when Git tries to
rewrite the file to prune the branches from it.

Interestingly though, we do not pack the about-to-be-pruned branch into
the packed-refs file, so it never even contained that branch in the
first place. While this is good enough right now because the pruning
will always lock the file regardless of whether it contains the branch
or not, this is a mere implementation detail. In fact, we're about to
rewrite branch deletions to make use of the ref transaction interface,
which knows to skip rewrites of the packed-refs file in the case where
it does not contain the branches in the first place, and this will break
the test.

Prepare the test for that change by packing the refs before trying to
prune them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5510-fetch.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index dcadd56d3a..79592a3b0a 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -169,6 +169,7 @@ test_expect_success REFFILES 'fetch --prune fails to delete branches' '
 	git clone . prune-fail &&
 	cd prune-fail &&
 	git update-ref refs/remotes/origin/extrabranch main &&
+	git pack-refs --all &&
 	: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&
 	>.git/packed-refs.new &&
 
-- 
2.42.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] refs/files: use transactions to delete references
  2023-11-14  8:58 [PATCH 0/4] refs: remove virtual `delete_refs()` function Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 1/4] t5510: ensure that the packed-refs file needs locking Patrick Steinhardt
@ 2023-11-14  8:58 ` Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 3/4] refs: deduplicate code " Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 4/4] refs: remove `delete_refs` callback from backends Patrick Steinhardt
  3 siblings, 0 replies; 5+ messages in thread
From: Patrick Steinhardt @ 2023-11-14  8:58 UTC (permalink / raw)
  To: git; +Cc: David Turner, Han-Wen Nienhuys

[-- Attachment #1: Type: text/plain, Size: 7477 bytes --]

In the `files_delete_refs()` callback function of the files backend we
implement deletion of references. This is done in two steps:

    1. We lock the packed-refs file and delete all references from it in
       a single transaction.

    2. We delete all loose references via separate calls to
       `refs_delete_ref()`.

These steps essentially duplicate the logic around locking and deletion
order that we already have in the transactional interfaces, where we do
know to lock and evict references from the packed-refs file. Despite the
fact that we duplicate the logic, it's also less efficient than if we
used a single generic transaction:

    - The transactional interface knows to skip locking of the packed
      refs in case they don't contain any of the refs which are about to
      be deleted.

    - We end up creating N+1 separate reference transactions, one for
      the packed-refs file and N for the individual loose references.

Refactor the code to instead delete references via a single transaction.
As we don't assert the expected old object ID this is equivalent to the
previous behaviour, and we already do the same in the packed-refs
backend.

Despite the fact that the result is simpler to reason about, this change
also results in improved performance. The following benchmarks have been
executed in linux.git:

```
$ hyperfine -n '{rev}, packed={packed} refcount={refcount}' \
    -L packed true,false -L refcount 1,1000 -L rev master,pks-ref-store-generic-delete-refs \
    --setup 'git -C /home/pks/Development/git switch --detach {rev} && make -C /home/pks/Development/git -j17' \
    --prepare 'printf "create refs/heads/new-branch-%d HEAD\n" $(seq {refcount}) | git -C /home/pks/Reproduction/linux.git update-ref --stdin && if test {packed} = true; then git pack-refs --all; fi' \
    --warmup=10 \
    '/home/pks/Development/git/bin-wrappers/git -C /home/pks/Reproduction/linux.git branch -d new-branch-{1..{refcount}}'

Benchmark 1: master packed=true refcount=1
  Time (mean ± σ):       7.8 ms ±   1.6 ms    [User: 3.4 ms, System: 4.4 ms]
  Range (min … max):     5.5 ms …  11.0 ms    120 runs

Benchmark 2: master packed=false refcount=1
  Time (mean ± σ):       7.0 ms ±   1.1 ms    [User: 3.2 ms, System: 3.8 ms]
  Range (min … max):     5.7 ms …   9.8 ms    180 runs

Benchmark 3: master packed=true refcount=1000
  Time (mean ± σ):     283.8 ms ±   5.2 ms    [User: 45.7 ms, System: 231.5 ms]
  Range (min … max):   276.7 ms … 291.6 ms    10 runs

Benchmark 4: master packed=false refcount=1000
  Time (mean ± σ):     284.4 ms ±   5.3 ms    [User: 44.2 ms, System: 233.6 ms]
  Range (min … max):   277.1 ms … 293.3 ms    10 runs

Benchmark 5: generic-delete-refs packed=true refcount=1
  Time (mean ± σ):       6.2 ms ±   1.8 ms    [User: 2.3 ms, System: 3.9 ms]
  Range (min … max):     4.1 ms …  12.2 ms    142 runs

Benchmark 6: generic-delete-refs packed=false refcount=1
  Time (mean ± σ):       7.1 ms ±   1.4 ms    [User: 2.8 ms, System: 4.3 ms]
  Range (min … max):     4.2 ms …  10.8 ms    157 runs

Benchmark 7: generic-delete-refs packed=true refcount=1000
  Time (mean ± σ):     198.9 ms ±   1.7 ms    [User: 29.5 ms, System: 165.7 ms]
  Range (min … max):   196.1 ms … 201.4 ms    10 runs

Benchmark 8: generic-delete-refs packed=false refcount=1000
  Time (mean ± σ):     199.7 ms ±   7.8 ms    [User: 32.2 ms, System: 163.2 ms]
  Range (min … max):   193.8 ms … 220.7 ms    10 runs

Summary
  generic-delete-refs packed=true refcount=1 ran
    1.14 ± 0.37 times faster than master packed=false refcount=1
    1.15 ± 0.40 times faster than generic-delete-refs packed=false refcount=1
    1.26 ± 0.44 times faster than master packed=true refcount=1
   32.24 ± 9.17 times faster than generic-delete-refs packed=true refcount=1000
   32.36 ± 9.29 times faster than generic-delete-refs packed=false refcount=1000
   46.00 ± 13.10 times faster than master packed=true refcount=1000
   46.10 ± 13.13 times faster than master packed=false refcount=1000
```

Especially in the case where we have many references we can see a clear
performance speedup of nearly 30%.

This is in contrast to the stated objecive in a27dcf89b68 (refs: make
delete_refs() virtual, 2016-09-04), where the virtual `delete_refs()`
function was introduced with the intent to speed things up rather than
making things slower. So it seems like we have outlived the need for a
virtual function.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs/files-backend.c | 66 +++++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 32 deletions(-)

diff --git a/refs/files-backend.c b/refs/files-backend.c
index db5c0c7a72..778d3a96ba 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1268,49 +1268,51 @@ static int files_pack_refs(struct ref_store *ref_store,
 static int files_delete_refs(struct ref_store *ref_store, const char *msg,
 			     struct string_list *refnames, unsigned int flags)
 {
-	struct files_ref_store *refs =
-		files_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
+	struct ref_transaction *transaction;
 	struct strbuf err = STRBUF_INIT;
-	int i, result = 0;
+	struct string_list_item *item;
+	int ret = 0, failures = 0;
 
 	if (!refnames->nr)
 		return 0;
 
-	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);
-		goto error;
+	/*
+	 * Since we don't check the references' old_oids, the
+	 * individual updates can't fail, so we can pack all of the
+	 * updates into a single transaction.
+	 */
+	transaction = ref_store_transaction_begin(ref_store, &err);
+	if (!transaction) {
+		ret = error("%s", err.buf);
+		goto out;
 	}
 
-	packed_refs_unlock(refs->packed_ref_store);
-
-	for (i = 0; i < refnames->nr; i++) {
-		const char *refname = refnames->items[i].string;
-
-		if (refs_delete_ref(&refs->base, msg, refname, NULL, flags))
-			result |= error(_("could not remove reference %s"), refname);
+	for_each_string_list_item(item, refnames) {
+		ret = ref_transaction_delete(transaction, item->string,
+					     NULL, flags, msg, &err);
+		if (ret) {
+			warning(_("could not delete reference %s: %s"),
+				item->string, err.buf);
+			strbuf_reset(&err);
+			failures = 1;
+		}
 	}
 
-	strbuf_release(&err);
-	return result;
-
-error:
-	/*
-	 * If we failed to rewrite the packed-refs file, then it is
-	 * unsafe to try to remove loose refs, because doing so might
-	 * expose an obsolete packed value for a reference that might
-	 * even point at an object that has been garbage collected.
-	 */
-	if (refnames->nr == 1)
-		error(_("could not delete reference %s: %s"),
-		      refnames->items[0].string, err.buf);
-	else
-		error(_("could not delete references: %s"), err.buf);
+	ret = ref_transaction_commit(transaction, &err);
+	if (ret) {
+		if (refnames->nr == 1)
+			error(_("could not delete reference %s: %s"),
+			      refnames->items[0].string, err.buf);
+		else
+			error(_("could not delete references: %s"), err.buf);
+	}
 
+out:
+	if (!ret && failures)
+		ret = -1;
+	ref_transaction_free(transaction);
 	strbuf_release(&err);
-	return -1;
+	return ret;
 }
 
 /*
-- 
2.42.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] refs: deduplicate code to delete references
  2023-11-14  8:58 [PATCH 0/4] refs: remove virtual `delete_refs()` function Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 1/4] t5510: ensure that the packed-refs file needs locking Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 2/4] refs/files: use transactions to delete references Patrick Steinhardt
@ 2023-11-14  8:58 ` Patrick Steinhardt
  2023-11-14  8:58 ` [PATCH 4/4] refs: remove `delete_refs` callback from backends Patrick Steinhardt
  3 siblings, 0 replies; 5+ messages in thread
From: Patrick Steinhardt @ 2023-11-14  8:58 UTC (permalink / raw)
  To: git; +Cc: David Turner, Han-Wen Nienhuys

[-- Attachment #1: Type: text/plain, Size: 5709 bytes --]

Both the files and the packed-refs reference backends now use the same
generic transactions-based code to delete references. Let's pull these
implementations up into `refs_delete_refs()` to deduplicate the code.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs.c                | 48 ++++++++++++++++++++++++++++++++++++++++---
 refs/files-backend.c  | 46 +----------------------------------------
 refs/packed-backend.c | 45 +---------------------------------------
 3 files changed, 47 insertions(+), 92 deletions(-)

diff --git a/refs.c b/refs.c
index fcae5dddc6..16bfa21df7 100644
--- a/refs.c
+++ b/refs.c
@@ -2599,13 +2599,55 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction,
 int refs_delete_refs(struct ref_store *refs, const char *logmsg,
 		     struct string_list *refnames, unsigned int flags)
 {
+	struct ref_transaction *transaction;
+	struct strbuf err = STRBUF_INIT;
+	struct string_list_item *item;
+	int ret = 0, failures = 0;
 	char *msg;
-	int retval;
+
+	if (!refnames->nr)
+		return 0;
 
 	msg = normalize_reflog_message(logmsg);
-	retval = refs->be->delete_refs(refs, msg, refnames, flags);
+
+	/*
+	 * Since we don't check the references' old_oids, the
+	 * individual updates can't fail, so we can pack all of the
+	 * updates into a single transaction.
+	 */
+	transaction = ref_store_transaction_begin(refs, &err);
+	if (!transaction) {
+		ret = error("%s", err.buf);
+		goto out;
+	}
+
+	for_each_string_list_item(item, refnames) {
+		ret = ref_transaction_delete(transaction, item->string,
+					     NULL, flags, msg, &err);
+		if (ret) {
+			warning(_("could not delete reference %s: %s"),
+				item->string, err.buf);
+			strbuf_reset(&err);
+			failures = 1;
+		}
+	}
+
+	ret = ref_transaction_commit(transaction, &err);
+	if (ret) {
+		if (refnames->nr == 1)
+			error(_("could not delete reference %s: %s"),
+			      refnames->items[0].string, err.buf);
+		else
+			error(_("could not delete references: %s"), err.buf);
+	}
+
+out:
+	if (!ret && failures)
+		ret = -1;
+	ref_transaction_free(transaction);
+	strbuf_release(&err);
 	free(msg);
-	return retval;
+	return ret;
 }
 
 int delete_refs(const char *msg, struct string_list *refnames,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 778d3a96ba..8d28810e67 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1268,51 +1268,7 @@ static int files_pack_refs(struct ref_store *ref_store,
 static int files_delete_refs(struct ref_store *ref_store, const char *msg,
 			     struct string_list *refnames, unsigned int flags)
 {
-	struct ref_transaction *transaction;
-	struct strbuf err = STRBUF_INIT;
-	struct string_list_item *item;
-	int ret = 0, failures = 0;
-
-	if (!refnames->nr)
-		return 0;
-
-	/*
-	 * Since we don't check the references' old_oids, the
-	 * individual updates can't fail, so we can pack all of the
-	 * updates into a single transaction.
-	 */
-	transaction = ref_store_transaction_begin(ref_store, &err);
-	if (!transaction) {
-		ret = error("%s", err.buf);
-		goto out;
-	}
-
-	for_each_string_list_item(item, refnames) {
-		ret = ref_transaction_delete(transaction, item->string,
-					     NULL, flags, msg, &err);
-		if (ret) {
-			warning(_("could not delete reference %s: %s"),
-				item->string, err.buf);
-			strbuf_reset(&err);
-			failures = 1;
-		}
-	}
-
-	ret = ref_transaction_commit(transaction, &err);
-	if (ret) {
-		if (refnames->nr == 1)
-			error(_("could not delete reference %s: %s"),
-			      refnames->items[0].string, err.buf);
-		else
-			error(_("could not delete references: %s"), err.buf);
-	}
-
-out:
-	if (!ret && failures)
-		ret = -1;
-	ref_transaction_free(transaction);
-	strbuf_release(&err);
-	return ret;
+	return refs_delete_refs(ref_store, msg, refnames, flags);
 }
 
 /*
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 59c78d7941..1589577005 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1691,50 +1691,7 @@ static int packed_initial_transaction_commit(struct ref_store *ref_store UNUSED,
 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;
-
-	/*
-	 * Since we don't check the references' old_oids, the
-	 * individual updates can't fail, so we can pack all of the
-	 * updates into a single transaction.
-	 */
-
-	transaction = ref_store_transaction_begin(ref_store, &err);
-	if (!transaction)
-		return -1;
-
-	for_each_string_list_item(item, refnames) {
-		if (ref_transaction_delete(transaction, item->string, NULL,
-					   flags, msg, &err)) {
-			warning(_("could not delete reference %s: %s"),
-				item->string, err.buf);
-			strbuf_reset(&err);
-		}
-	}
-
-	ret = ref_transaction_commit(transaction, &err);
-
-	if (ret) {
-		if (refnames->nr == 1)
-			error(_("could not delete reference %s: %s"),
-			      refnames->items[0].string, err.buf);
-		else
-			error(_("could not delete references: %s"), err.buf);
-	}
-
-	ref_transaction_free(transaction);
-	strbuf_release(&err);
-	return ret;
+	return refs_delete_refs(ref_store, msg, refnames, flags);
 }
 
 static int packed_pack_refs(struct ref_store *ref_store UNUSED,
-- 
2.42.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] refs: remove `delete_refs` callback from backends
  2023-11-14  8:58 [PATCH 0/4] refs: remove virtual `delete_refs()` function Patrick Steinhardt
                   ` (2 preceding siblings ...)
  2023-11-14  8:58 ` [PATCH 3/4] refs: deduplicate code " Patrick Steinhardt
@ 2023-11-14  8:58 ` Patrick Steinhardt
  3 siblings, 0 replies; 5+ messages in thread
From: Patrick Steinhardt @ 2023-11-14  8:58 UTC (permalink / raw)
  To: git; +Cc: David Turner, Han-Wen Nienhuys

[-- Attachment #1: Type: text/plain, Size: 4122 bytes --]

Now that `refs_delete_refs` is implemented in a generic way via the ref
transaction interfaces there are no callers left that invoke the
`delete_refs` callback anymore. Remove it from all of our backends.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 refs/debug.c          | 15 ---------------
 refs/files-backend.c  |  7 -------
 refs/packed-backend.c |  7 -------
 refs/refs-internal.h  |  3 ---
 4 files changed, 32 deletions(-)

diff --git a/refs/debug.c b/refs/debug.c
index b7ffc4ce67..83b7a0ba65 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -143,20 +143,6 @@ static int debug_create_symref(struct ref_store *ref_store,
 	return res;
 }
 
-static int debug_delete_refs(struct ref_store *ref_store, const char *msg,
-			     struct string_list *refnames, unsigned int flags)
-{
-	struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
-	int res =
-		drefs->refs->be->delete_refs(drefs->refs, msg, refnames, flags);
-	int i;
-	trace_printf_key(&trace_refs, "delete_refs {\n");
-	for (i = 0; i < refnames->nr; i++)
-		trace_printf_key(&trace_refs, "%s\n", refnames->items[i].string);
-	trace_printf_key(&trace_refs, "}: %d\n", res);
-	return res;
-}
-
 static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
 			    const char *newref, const char *logmsg)
 {
@@ -458,7 +444,6 @@ struct ref_storage_be refs_be_debug = {
 
 	.pack_refs = debug_pack_refs,
 	.create_symref = debug_create_symref,
-	.delete_refs = debug_delete_refs,
 	.rename_ref = debug_rename_ref,
 	.copy_ref = debug_copy_ref,
 
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 8d28810e67..ad8b1d143f 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1265,12 +1265,6 @@ static int files_pack_refs(struct ref_store *ref_store,
 	return 0;
 }
 
-static int files_delete_refs(struct ref_store *ref_store, const char *msg,
-			     struct string_list *refnames, unsigned int flags)
-{
-	return refs_delete_refs(ref_store, msg, refnames, flags);
-}
-
 /*
  * People using contrib's git-new-workdir have .git/logs/refs ->
  * /some/other/path/.git/logs/refs, and that may live on another device.
@@ -3258,7 +3252,6 @@ struct ref_storage_be refs_be_files = {
 
 	.pack_refs = files_pack_refs,
 	.create_symref = files_create_symref,
-	.delete_refs = files_delete_refs,
 	.rename_ref = files_rename_ref,
 	.copy_ref = files_copy_ref,
 
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 1589577005..b9fa097a29 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1688,12 +1688,6 @@ static int packed_initial_transaction_commit(struct ref_store *ref_store UNUSED,
 	return ref_transaction_commit(transaction, err);
 }
 
-static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
-			     struct string_list *refnames, unsigned int flags)
-{
-	return refs_delete_refs(ref_store, msg, refnames, flags);
-}
-
 static int packed_pack_refs(struct ref_store *ref_store UNUSED,
 			    struct pack_refs_opts *pack_opts UNUSED)
 {
@@ -1722,7 +1716,6 @@ struct ref_storage_be refs_be_packed = {
 
 	.pack_refs = packed_pack_refs,
 	.create_symref = NULL,
-	.delete_refs = packed_delete_refs,
 	.rename_ref = NULL,
 	.copy_ref = NULL,
 
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 9db8aec4da..4af83bf9a5 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -553,8 +553,6 @@ typedef int create_symref_fn(struct ref_store *ref_store,
 			     const char *ref_target,
 			     const char *refs_heads_master,
 			     const char *logmsg);
-typedef int delete_refs_fn(struct ref_store *ref_store, const char *msg,
-			   struct string_list *refnames, unsigned int flags);
 typedef int rename_ref_fn(struct ref_store *ref_store,
 			  const char *oldref, const char *newref,
 			  const char *logmsg);
@@ -677,7 +675,6 @@ struct ref_storage_be {
 
 	pack_refs_fn *pack_refs;
 	create_symref_fn *create_symref;
-	delete_refs_fn *delete_refs;
 	rename_ref_fn *rename_ref;
 	copy_ref_fn *copy_ref;
 
-- 
2.42.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-11-14  8:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-14  8:58 [PATCH 0/4] refs: remove virtual `delete_refs()` function Patrick Steinhardt
2023-11-14  8:58 ` [PATCH 1/4] t5510: ensure that the packed-refs file needs locking Patrick Steinhardt
2023-11-14  8:58 ` [PATCH 2/4] refs/files: use transactions to delete references Patrick Steinhardt
2023-11-14  8:58 ` [PATCH 3/4] refs: deduplicate code " Patrick Steinhardt
2023-11-14  8:58 ` [PATCH 4/4] refs: remove `delete_refs` callback from backends Patrick Steinhardt

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).