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>

Patrick Steinhardt committed Jan 17, 2022 at 09:12 UTC 69840cc0f7b4f3352903bd2b8f3de7077916c26b
3 files changed +37 -9
refs/files-backend.c
+10 -3
@@ -1249,6 +1249,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg,
1249 {
1250 struct files_ref_store *refs =
1251 files_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
1252 + struct ref_transaction *transaction = NULL;
1253 struct strbuf err = STRBUF_INIT;
1254 int i, result = 0;
1255
@@ -1258,10 +1259,14 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg,
1259 if (packed_refs_lock(refs->packed_ref_store, 0, &err))
1260 goto error;
1261
1261 - if (refs_delete_refs(refs->packed_ref_store, msg, refnames, flags)) {
1262 - packed_refs_unlock(refs->packed_ref_store);
1262 + transaction = ref_store_transaction_begin(refs->packed_ref_store, &err);
1263 + if (!transaction)
1264 + goto error;
1265 +
1266 + result = packed_refs_delete_refs(refs->packed_ref_store,
1267 + transaction, msg, refnames, flags);
1268 + if (result)
1269 goto error;
1264 - }
1270
1271 packed_refs_unlock(refs->packed_ref_store);
1272
@@ -1272,6 +1277,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg,
1277 result |= error(_("could not remove reference %s"), refname);
1278 }
1279
1280 + ref_transaction_free(transaction);
1281 strbuf_release(&err);
1282 return result;
1283
@@ -1288,6 +1294,7 @@ error:
1294 else
1295 error(_("could not delete references: %s"), err.buf);
1296
1297 + ref_transaction_free(transaction);
1298 strbuf_release(&err);
1299 return -1;
1300 }
refs/packed-backend.c
+20 -6
@@ -1522,15 +1522,10 @@ static int packed_initial_transaction_commit(struct ref_store *ref_store,
1522 static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
1523 struct string_list *refnames, unsigned int flags)
1524 {
1525 - struct packed_ref_store *refs =
1526 - packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
1525 struct strbuf err = STRBUF_INIT;
1526 struct ref_transaction *transaction;
1529 - struct string_list_item *item;
1527 int ret;
1528
1532 - (void)refs; /* We need the check above, but don't use the variable */
1533 -
1529 if (!refnames->nr)
1530 return 0;
1531
@@ -1544,6 +1539,26 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
1539 if (!transaction)
1540 return -1;
1541
1542 + ret = packed_refs_delete_refs(ref_store, transaction,
1543 + msg, refnames, flags);
1544 +
1545 + ref_transaction_free(transaction);
1546 + return ret;
1547 +}
1548 +
1549 +int packed_refs_delete_refs(struct ref_store *ref_store,
1550 + struct ref_transaction *transaction,
1551 + const char *msg,
1552 + struct string_list *refnames,
1553 + unsigned int flags)
1554 +{
1555 + struct strbuf err = STRBUF_INIT;
1556 + struct string_list_item *item;
1557 + int ret;
1558 +
1559 + /* Assert that the ref store refers to a packed backend. */
1560 + packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs");
1561 +
1562 for_each_string_list_item(item, refnames) {
1563 if (ref_transaction_delete(transaction, item->string, NULL,
1564 flags, msg, &err)) {
@@ -1563,7 +1578,6 @@ static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
1578 error(_("could not delete references: %s"), err.buf);
1579 }
1580
1566 - ref_transaction_free(transaction);
1581 strbuf_release(&err);
1582 return ret;
1583 }
refs/packed-backend.h
+7
@@ -3,6 +3,7 @@
3
4 struct repository;
5 struct ref_transaction;
6 +struct string_list;
7
8 /*
9 * 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)
28 void packed_refs_unlock(struct ref_store *ref_store);
29 int packed_refs_is_locked(struct ref_store *ref_store);
30
31 +int packed_refs_delete_refs(struct ref_store *ref_store,
32 + struct ref_transaction *transaction,
33 + const char *msg,
34 + struct string_list *refnames,
35 + unsigned int flags);
36 +
37 /*
38 * Return true if `transaction` really needs to be carried out against
39 * the specified packed_ref_store, or false if it can be skipped