Git fork

Merge branch 'ps/ref-deletion-updates'

Simplify API implementation to delete references by eliminating
duplication.

* ps/ref-deletion-updates:
refs: remove `delete_refs` callback from backends
refs: deduplicate code to delete references
refs/files: use transactions to delete references
t5510: ensure that the packed-refs file needs locking

+46 -120
+45 -3
refs.c
··· 2599 2599 int refs_delete_refs(struct ref_store *refs, const char *logmsg, 2600 2600 struct string_list *refnames, unsigned int flags) 2601 2601 { 2602 + struct ref_transaction *transaction; 2603 + struct strbuf err = STRBUF_INIT; 2604 + struct string_list_item *item; 2605 + int ret = 0, failures = 0; 2602 2606 char *msg; 2603 - int retval; 2607 + 2608 + if (!refnames->nr) 2609 + return 0; 2604 2610 2605 2611 msg = normalize_reflog_message(logmsg); 2606 - retval = refs->be->delete_refs(refs, msg, refnames, flags); 2612 + 2613 + /* 2614 + * Since we don't check the references' old_oids, the 2615 + * individual updates can't fail, so we can pack all of the 2616 + * updates into a single transaction. 2617 + */ 2618 + transaction = ref_store_transaction_begin(refs, &err); 2619 + if (!transaction) { 2620 + ret = error("%s", err.buf); 2621 + goto out; 2622 + } 2623 + 2624 + for_each_string_list_item(item, refnames) { 2625 + ret = ref_transaction_delete(transaction, item->string, 2626 + NULL, flags, msg, &err); 2627 + if (ret) { 2628 + warning(_("could not delete reference %s: %s"), 2629 + item->string, err.buf); 2630 + strbuf_reset(&err); 2631 + failures = 1; 2632 + } 2633 + } 2634 + 2635 + ret = ref_transaction_commit(transaction, &err); 2636 + if (ret) { 2637 + if (refnames->nr == 1) 2638 + error(_("could not delete reference %s: %s"), 2639 + refnames->items[0].string, err.buf); 2640 + else 2641 + error(_("could not delete references: %s"), err.buf); 2642 + } 2643 + 2644 + out: 2645 + if (!ret && failures) 2646 + ret = -1; 2647 + ref_transaction_free(transaction); 2648 + strbuf_release(&err); 2607 2649 free(msg); 2608 - return retval; 2650 + return ret; 2609 2651 } 2610 2652 2611 2653 int delete_refs(const char *msg, struct string_list *refnames,
-15
refs/debug.c
··· 143 143 return res; 144 144 } 145 145 146 - static int debug_delete_refs(struct ref_store *ref_store, const char *msg, 147 - struct string_list *refnames, unsigned int flags) 148 - { 149 - struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store; 150 - int res = 151 - drefs->refs->be->delete_refs(drefs->refs, msg, refnames, flags); 152 - int i; 153 - trace_printf_key(&trace_refs, "delete_refs {\n"); 154 - for (i = 0; i < refnames->nr; i++) 155 - trace_printf_key(&trace_refs, "%s\n", refnames->items[i].string); 156 - trace_printf_key(&trace_refs, "}: %d\n", res); 157 - return res; 158 - } 159 - 160 146 static int debug_rename_ref(struct ref_store *ref_store, const char *oldref, 161 147 const char *newref, const char *logmsg) 162 148 { ··· 458 444 459 445 .pack_refs = debug_pack_refs, 460 446 .create_symref = debug_create_symref, 461 - .delete_refs = debug_delete_refs, 462 447 .rename_ref = debug_rename_ref, 463 448 .copy_ref = debug_copy_ref, 464 449
-49
refs/files-backend.c
··· 1265 1265 return 0; 1266 1266 } 1267 1267 1268 - static int files_delete_refs(struct ref_store *ref_store, const char *msg, 1269 - struct string_list *refnames, unsigned int flags) 1270 - { 1271 - struct files_ref_store *refs = 1272 - files_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); 1273 - struct strbuf err = STRBUF_INIT; 1274 - int i, result = 0; 1275 - 1276 - if (!refnames->nr) 1277 - return 0; 1278 - 1279 - if (packed_refs_lock(refs->packed_ref_store, 0, &err)) 1280 - goto error; 1281 - 1282 - if (refs_delete_refs(refs->packed_ref_store, msg, refnames, flags)) { 1283 - packed_refs_unlock(refs->packed_ref_store); 1284 - goto error; 1285 - } 1286 - 1287 - packed_refs_unlock(refs->packed_ref_store); 1288 - 1289 - for (i = 0; i < refnames->nr; i++) { 1290 - const char *refname = refnames->items[i].string; 1291 - 1292 - if (refs_delete_ref(&refs->base, msg, refname, NULL, flags)) 1293 - result |= error(_("could not remove reference %s"), refname); 1294 - } 1295 - 1296 - strbuf_release(&err); 1297 - return result; 1298 - 1299 - error: 1300 - /* 1301 - * If we failed to rewrite the packed-refs file, then it is 1302 - * unsafe to try to remove loose refs, because doing so might 1303 - * expose an obsolete packed value for a reference that might 1304 - * even point at an object that has been garbage collected. 1305 - */ 1306 - if (refnames->nr == 1) 1307 - error(_("could not delete reference %s: %s"), 1308 - refnames->items[0].string, err.buf); 1309 - else 1310 - error(_("could not delete references: %s"), err.buf); 1311 - 1312 - strbuf_release(&err); 1313 - return -1; 1314 - } 1315 - 1316 1268 /* 1317 1269 * People using contrib's git-new-workdir have .git/logs/refs -> 1318 1270 * /some/other/path/.git/logs/refs, and that may live on another device. ··· 3300 3252 3301 3253 .pack_refs = files_pack_refs, 3302 3254 .create_symref = files_create_symref, 3303 - .delete_refs = files_delete_refs, 3304 3255 .rename_ref = files_rename_ref, 3305 3256 .copy_ref = files_copy_ref, 3306 3257
-50
refs/packed-backend.c
··· 1688 1688 return ref_transaction_commit(transaction, err); 1689 1689 } 1690 1690 1691 - static int packed_delete_refs(struct ref_store *ref_store, const char *msg, 1692 - struct string_list *refnames, unsigned int flags) 1693 - { 1694 - struct packed_ref_store *refs = 1695 - packed_downcast(ref_store, REF_STORE_WRITE, "delete_refs"); 1696 - struct strbuf err = STRBUF_INIT; 1697 - struct ref_transaction *transaction; 1698 - struct string_list_item *item; 1699 - int ret; 1700 - 1701 - (void)refs; /* We need the check above, but don't use the variable */ 1702 - 1703 - if (!refnames->nr) 1704 - return 0; 1705 - 1706 - /* 1707 - * Since we don't check the references' old_oids, the 1708 - * individual updates can't fail, so we can pack all of the 1709 - * updates into a single transaction. 1710 - */ 1711 - 1712 - transaction = ref_store_transaction_begin(ref_store, &err); 1713 - if (!transaction) 1714 - return -1; 1715 - 1716 - for_each_string_list_item(item, refnames) { 1717 - if (ref_transaction_delete(transaction, item->string, NULL, 1718 - flags, msg, &err)) { 1719 - warning(_("could not delete reference %s: %s"), 1720 - item->string, err.buf); 1721 - strbuf_reset(&err); 1722 - } 1723 - } 1724 - 1725 - ret = ref_transaction_commit(transaction, &err); 1726 - 1727 - if (ret) { 1728 - if (refnames->nr == 1) 1729 - error(_("could not delete reference %s: %s"), 1730 - refnames->items[0].string, err.buf); 1731 - else 1732 - error(_("could not delete references: %s"), err.buf); 1733 - } 1734 - 1735 - ref_transaction_free(transaction); 1736 - strbuf_release(&err); 1737 - return ret; 1738 - } 1739 - 1740 1691 static int packed_pack_refs(struct ref_store *ref_store UNUSED, 1741 1692 struct pack_refs_opts *pack_opts UNUSED) 1742 1693 { ··· 1765 1716 1766 1717 .pack_refs = packed_pack_refs, 1767 1718 .create_symref = NULL, 1768 - .delete_refs = packed_delete_refs, 1769 1719 .rename_ref = NULL, 1770 1720 .copy_ref = NULL, 1771 1721
-3
refs/refs-internal.h
··· 553 553 const char *ref_target, 554 554 const char *refs_heads_master, 555 555 const char *logmsg); 556 - typedef int delete_refs_fn(struct ref_store *ref_store, const char *msg, 557 - struct string_list *refnames, unsigned int flags); 558 556 typedef int rename_ref_fn(struct ref_store *ref_store, 559 557 const char *oldref, const char *newref, 560 558 const char *logmsg); ··· 677 675 678 676 pack_refs_fn *pack_refs; 679 677 create_symref_fn *create_symref; 680 - delete_refs_fn *delete_refs; 681 678 rename_ref_fn *rename_ref; 682 679 copy_ref_fn *copy_ref; 683 680
+1
t/t5510-fetch.sh
··· 169 169 git clone . prune-fail && 170 170 cd prune-fail && 171 171 git update-ref refs/remotes/origin/extrabranch main && 172 + git pack-refs --all && 172 173 : this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds && 173 174 >.git/packed-refs.new && 174 175