@@ -1041,11 +1041,17 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
10411041 strbuf_release (& err );
10421042}
10431043
1044- static void prune_refs (struct files_ref_store * refs , struct ref_to_prune * r )
1044+ /*
1045+ * Prune the loose versions of the references in the linked list
1046+ * `*refs_to_prune`, freeing the entries in the list as we go.
1047+ */
1048+ static void prune_refs (struct files_ref_store * refs , struct ref_to_prune * * refs_to_prune )
10451049{
1046- while (r ) {
1050+ while (* refs_to_prune ) {
1051+ struct ref_to_prune * r = * refs_to_prune ;
1052+ * refs_to_prune = r -> next ;
10471053 prune_ref (refs , r );
1048- r = r -> next ;
1054+ free ( r ) ;
10491055 }
10501056}
10511057
@@ -1084,6 +1090,11 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
10841090 int ok ;
10851091 struct ref_to_prune * refs_to_prune = NULL ;
10861092 struct strbuf err = STRBUF_INIT ;
1093+ struct ref_transaction * transaction ;
1094+
1095+ transaction = ref_store_transaction_begin (refs -> packed_ref_store , & err );
1096+ if (!transaction )
1097+ return -1 ;
10871098
10881099 packed_refs_lock (refs -> packed_ref_store , LOCK_DIE_ON_ERROR , & err );
10891100
@@ -1099,12 +1110,14 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
10991110 continue ;
11001111
11011112 /*
1102- * Create an entry in the packed-refs cache equivalent
1103- * to the one from the loose ref cache, except that
1104- * we don't copy the peeled status, because we want it
1105- * to be re-peeled.
1113+ * Add a reference creation for this reference to the
1114+ * packed-refs transaction:
11061115 */
1107- add_packed_ref (refs -> packed_ref_store , iter -> refname , iter -> oid );
1116+ if (ref_transaction_update (transaction , iter -> refname ,
1117+ iter -> oid -> hash , NULL ,
1118+ REF_NODEREF , NULL , & err ))
1119+ die ("failure preparing to create packed reference %s: %s" ,
1120+ iter -> refname , err .buf );
11081121
11091122 /* Schedule the loose reference for pruning if requested. */
11101123 if ((flags & PACK_REFS_PRUNE )) {
@@ -1118,11 +1131,14 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
11181131 if (ok != ITER_DONE )
11191132 die ("error while iterating over references" );
11201133
1121- if (commit_packed_refs (refs -> packed_ref_store , & err ))
1122- die ("unable to overwrite old ref-pack file: %s" , err .buf );
1134+ if (ref_transaction_commit (transaction , & err ))
1135+ die ("unable to write new packed-refs: %s" , err .buf );
1136+
1137+ ref_transaction_free (transaction );
1138+
11231139 packed_refs_unlock (refs -> packed_ref_store );
11241140
1125- prune_refs (refs , refs_to_prune );
1141+ prune_refs (refs , & refs_to_prune );
11261142 strbuf_release (& err );
11271143 return 0 ;
11281144}
@@ -1141,7 +1157,7 @@ static int files_delete_refs(struct ref_store *ref_store, const char *msg,
11411157 if (packed_refs_lock (refs -> packed_ref_store , 0 , & err ))
11421158 goto error ;
11431159
1144- if (repack_without_refs (refs -> packed_ref_store , refnames , & err )) {
1160+ if (refs_delete_refs (refs -> packed_ref_store , msg , refnames , flags )) {
11451161 packed_refs_unlock (refs -> packed_ref_store );
11461162 goto error ;
11471163 }
@@ -2431,13 +2447,22 @@ static int lock_ref_for_update(struct files_ref_store *refs,
24312447 return ret ;
24322448}
24332449
2450+ struct files_transaction_backend_data {
2451+ struct ref_transaction * packed_transaction ;
2452+ int packed_refs_locked ;
2453+ };
2454+
24342455/*
24352456 * Unlock any references in `transaction` that are still locked, and
24362457 * mark the transaction closed.
24372458 */
2438- static void files_transaction_cleanup (struct ref_transaction * transaction )
2459+ static void files_transaction_cleanup (struct files_ref_store * refs ,
2460+ struct ref_transaction * transaction )
24392461{
24402462 size_t i ;
2463+ struct files_transaction_backend_data * backend_data =
2464+ transaction -> backend_data ;
2465+ struct strbuf err = STRBUF_INIT ;
24412466
24422467 for (i = 0 ; i < transaction -> nr ; i ++ ) {
24432468 struct ref_update * update = transaction -> updates [i ];
@@ -2449,6 +2474,17 @@ static void files_transaction_cleanup(struct ref_transaction *transaction)
24492474 }
24502475 }
24512476
2477+ if (backend_data -> packed_transaction &&
2478+ ref_transaction_abort (backend_data -> packed_transaction , & err )) {
2479+ error ("error aborting transaction: %s" , err .buf );
2480+ strbuf_release (& err );
2481+ }
2482+
2483+ if (backend_data -> packed_refs_locked )
2484+ packed_refs_unlock (refs -> packed_ref_store );
2485+
2486+ free (backend_data );
2487+
24522488 transaction -> state = REF_TRANSACTION_CLOSED ;
24532489}
24542490
@@ -2465,12 +2501,17 @@ static int files_transaction_prepare(struct ref_store *ref_store,
24652501 char * head_ref = NULL ;
24662502 int head_type ;
24672503 struct object_id head_oid ;
2504+ struct files_transaction_backend_data * backend_data ;
2505+ struct ref_transaction * packed_transaction = NULL ;
24682506
24692507 assert (err );
24702508
24712509 if (!transaction -> nr )
24722510 goto cleanup ;
24732511
2512+ backend_data = xcalloc (1 , sizeof (* backend_data ));
2513+ transaction -> backend_data = backend_data ;
2514+
24742515 /*
24752516 * Fail if a refname appears more than once in the
24762517 * transaction. (If we end up splitting up any updates using
@@ -2537,14 +2578,49 @@ static int files_transaction_prepare(struct ref_store *ref_store,
25372578 head_ref , & affected_refnames , err );
25382579 if (ret )
25392580 break ;
2581+
2582+ if (update -> flags & REF_DELETING &&
2583+ !(update -> flags & REF_LOG_ONLY ) &&
2584+ !(update -> flags & REF_ISPRUNING )) {
2585+ /*
2586+ * This reference has to be deleted from
2587+ * packed-refs if it exists there.
2588+ */
2589+ if (!packed_transaction ) {
2590+ packed_transaction = ref_store_transaction_begin (
2591+ refs -> packed_ref_store , err );
2592+ if (!packed_transaction ) {
2593+ ret = TRANSACTION_GENERIC_ERROR ;
2594+ goto cleanup ;
2595+ }
2596+
2597+ backend_data -> packed_transaction =
2598+ packed_transaction ;
2599+ }
2600+
2601+ ref_transaction_add_update (
2602+ packed_transaction , update -> refname ,
2603+ update -> flags & ~REF_HAVE_OLD ,
2604+ update -> new_oid .hash , update -> old_oid .hash ,
2605+ NULL );
2606+ }
2607+ }
2608+
2609+ if (packed_transaction ) {
2610+ if (packed_refs_lock (refs -> packed_ref_store , 0 , err )) {
2611+ ret = TRANSACTION_GENERIC_ERROR ;
2612+ goto cleanup ;
2613+ }
2614+ backend_data -> packed_refs_locked = 1 ;
2615+ ret = ref_transaction_prepare (packed_transaction , err );
25402616 }
25412617
25422618cleanup :
25432619 free (head_ref );
25442620 string_list_clear (& affected_refnames , 0 );
25452621
25462622 if (ret )
2547- files_transaction_cleanup (transaction );
2623+ files_transaction_cleanup (refs , transaction );
25482624 else
25492625 transaction -> state = REF_TRANSACTION_PREPARED ;
25502626
@@ -2559,9 +2635,10 @@ static int files_transaction_finish(struct ref_store *ref_store,
25592635 files_downcast (ref_store , 0 , "ref_transaction_finish" );
25602636 size_t i ;
25612637 int ret = 0 ;
2562- struct string_list refs_to_delete = STRING_LIST_INIT_NODUP ;
2563- struct string_list_item * ref_to_delete ;
25642638 struct strbuf sb = STRBUF_INIT ;
2639+ struct files_transaction_backend_data * backend_data ;
2640+ struct ref_transaction * packed_transaction ;
2641+
25652642
25662643 assert (err );
25672644
@@ -2570,6 +2647,9 @@ static int files_transaction_finish(struct ref_store *ref_store,
25702647 return 0 ;
25712648 }
25722649
2650+ backend_data = transaction -> backend_data ;
2651+ packed_transaction = backend_data -> packed_transaction ;
2652+
25732653 /* Perform updates first so live commits remain referenced */
25742654 for (i = 0 ; i < transaction -> nr ; i ++ ) {
25752655 struct ref_update * update = transaction -> updates [i ];
@@ -2605,7 +2685,44 @@ static int files_transaction_finish(struct ref_store *ref_store,
26052685 }
26062686 }
26072687 }
2608- /* Perform deletes now that updates are safely completed */
2688+
2689+ /*
2690+ * Now that updates are safely completed, we can perform
2691+ * deletes. First delete the reflogs of any references that
2692+ * will be deleted, since (in the unexpected event of an
2693+ * error) leaving a reference without a reflog is less bad
2694+ * than leaving a reflog without a reference (the latter is a
2695+ * mildly invalid repository state):
2696+ */
2697+ for (i = 0 ; i < transaction -> nr ; i ++ ) {
2698+ struct ref_update * update = transaction -> updates [i ];
2699+ if (update -> flags & REF_DELETING &&
2700+ !(update -> flags & REF_LOG_ONLY ) &&
2701+ !(update -> flags & REF_ISPRUNING )) {
2702+ strbuf_reset (& sb );
2703+ files_reflog_path (refs , & sb , update -> refname );
2704+ if (!unlink_or_warn (sb .buf ))
2705+ try_remove_empty_parents (refs , update -> refname ,
2706+ REMOVE_EMPTY_PARENTS_REFLOG );
2707+ }
2708+ }
2709+
2710+ /*
2711+ * Perform deletes now that updates are safely completed.
2712+ *
2713+ * First delete any packed versions of the references, while
2714+ * retaining the packed-refs lock:
2715+ */
2716+ if (packed_transaction ) {
2717+ ret = ref_transaction_commit (packed_transaction , err );
2718+ ref_transaction_free (packed_transaction );
2719+ packed_transaction = NULL ;
2720+ backend_data -> packed_transaction = NULL ;
2721+ if (ret )
2722+ goto cleanup ;
2723+ }
2724+
2725+ /* Now delete the loose versions of the references: */
26092726 for (i = 0 ; i < transaction -> nr ; i ++ ) {
26102727 struct ref_update * update = transaction -> updates [i ];
26112728 struct ref_lock * lock = update -> backend_data ;
@@ -2623,39 +2740,13 @@ static int files_transaction_finish(struct ref_store *ref_store,
26232740 }
26242741 update -> flags |= REF_DELETED_LOOSE ;
26252742 }
2626-
2627- if (!(update -> flags & REF_ISPRUNING ))
2628- string_list_append (& refs_to_delete ,
2629- lock -> ref_name );
26302743 }
26312744 }
26322745
2633- if (packed_refs_lock (refs -> packed_ref_store , 0 , err )) {
2634- ret = TRANSACTION_GENERIC_ERROR ;
2635- goto cleanup ;
2636- }
2637-
2638- if (repack_without_refs (refs -> packed_ref_store , & refs_to_delete , err )) {
2639- ret = TRANSACTION_GENERIC_ERROR ;
2640- packed_refs_unlock (refs -> packed_ref_store );
2641- goto cleanup ;
2642- }
2643-
2644- packed_refs_unlock (refs -> packed_ref_store );
2645-
2646- /* Delete the reflogs of any references that were deleted: */
2647- for_each_string_list_item (ref_to_delete , & refs_to_delete ) {
2648- strbuf_reset (& sb );
2649- files_reflog_path (refs , & sb , ref_to_delete -> string );
2650- if (!unlink_or_warn (sb .buf ))
2651- try_remove_empty_parents (refs , ref_to_delete -> string ,
2652- REMOVE_EMPTY_PARENTS_REFLOG );
2653- }
2654-
26552746 clear_loose_ref_cache (refs );
26562747
26572748cleanup :
2658- files_transaction_cleanup (transaction );
2749+ files_transaction_cleanup (refs , transaction );
26592750
26602751 for (i = 0 ; i < transaction -> nr ; i ++ ) {
26612752 struct ref_update * update = transaction -> updates [i ];
@@ -2673,15 +2764,17 @@ static int files_transaction_finish(struct ref_store *ref_store,
26732764 }
26742765
26752766 strbuf_release (& sb );
2676- string_list_clear (& refs_to_delete , 0 );
26772767 return ret ;
26782768}
26792769
26802770static int files_transaction_abort (struct ref_store * ref_store ,
26812771 struct ref_transaction * transaction ,
26822772 struct strbuf * err )
26832773{
2684- files_transaction_cleanup (transaction );
2774+ struct files_ref_store * refs =
2775+ files_downcast (ref_store , 0 , "ref_transaction_abort" );
2776+
2777+ files_transaction_cleanup (refs , transaction );
26852778 return 0 ;
26862779}
26872780
@@ -2703,6 +2796,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
27032796 size_t i ;
27042797 int ret = 0 ;
27052798 struct string_list affected_refnames = STRING_LIST_INIT_NODUP ;
2799+ struct ref_transaction * packed_transaction = NULL ;
27062800
27072801 assert (err );
27082802
@@ -2735,6 +2829,12 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
27352829 & affected_refnames ))
27362830 die ("BUG: initial ref transaction called with existing refs" );
27372831
2832+ packed_transaction = ref_store_transaction_begin (refs -> packed_ref_store , err );
2833+ if (!packed_transaction ) {
2834+ ret = TRANSACTION_GENERIC_ERROR ;
2835+ goto cleanup ;
2836+ }
2837+
27382838 for (i = 0 ; i < transaction -> nr ; i ++ ) {
27392839 struct ref_update * update = transaction -> updates [i ];
27402840
@@ -2747,28 +2847,30 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
27472847 ret = TRANSACTION_NAME_CONFLICT ;
27482848 goto cleanup ;
27492849 }
2850+
2851+ /*
2852+ * Add a reference creation for this reference to the
2853+ * packed-refs transaction:
2854+ */
2855+ ref_transaction_add_update (packed_transaction , update -> refname ,
2856+ update -> flags & ~REF_HAVE_OLD ,
2857+ update -> new_oid .hash , update -> old_oid .hash ,
2858+ NULL );
27502859 }
27512860
27522861 if (packed_refs_lock (refs -> packed_ref_store , 0 , err )) {
27532862 ret = TRANSACTION_GENERIC_ERROR ;
27542863 goto cleanup ;
27552864 }
27562865
2757- for (i = 0 ; i < transaction -> nr ; i ++ ) {
2758- struct ref_update * update = transaction -> updates [i ];
2759-
2760- if ((update -> flags & REF_HAVE_NEW ) &&
2761- !is_null_oid (& update -> new_oid ))
2762- add_packed_ref (refs -> packed_ref_store , update -> refname ,
2763- & update -> new_oid );
2764- }
2765-
2766- if (commit_packed_refs (refs -> packed_ref_store , err )) {
2866+ if (initial_ref_transaction_commit (packed_transaction , err )) {
27672867 ret = TRANSACTION_GENERIC_ERROR ;
27682868 goto cleanup ;
27692869 }
27702870
27712871cleanup :
2872+ if (packed_transaction )
2873+ ref_transaction_free (packed_transaction );
27722874 packed_refs_unlock (refs -> packed_ref_store );
27732875 transaction -> state = REF_TRANSACTION_CLOSED ;
27742876 string_list_clear (& affected_refnames , 0 );
0 commit comments