@@ -640,17 +640,13 @@ static struct ref *get_ref_map(struct remote *remote,
640640 return ref_map ;
641641}
642642
643- #define STORE_REF_ERROR_OTHER 1
644- #define STORE_REF_ERROR_DF_CONFLICT 2
645-
646643static int s_update_ref (const char * action ,
647644 struct ref * ref ,
648645 struct ref_transaction * transaction ,
649646 int check_old )
650647{
651648 char * msg ;
652649 char * rla = getenv ("GIT_REFLOG_ACTION" );
653- struct ref_transaction * our_transaction = NULL ;
654650 struct strbuf err = STRBUF_INIT ;
655651 int ret ;
656652
@@ -660,43 +656,10 @@ static int s_update_ref(const char *action,
660656 rla = default_rla .buf ;
661657 msg = xstrfmt ("%s: %s" , rla , action );
662658
663- /*
664- * If no transaction was passed to us, we manage the transaction
665- * ourselves. Otherwise, we trust the caller to handle the transaction
666- * lifecycle.
667- */
668- if (!transaction ) {
669- transaction = our_transaction = ref_store_transaction_begin (get_main_ref_store (the_repository ),
670- 0 , & err );
671- if (!transaction ) {
672- ret = STORE_REF_ERROR_OTHER ;
673- goto out ;
674- }
675- }
676-
677659 ret = ref_transaction_update (transaction , ref -> name , & ref -> new_oid ,
678660 check_old ? & ref -> old_oid : NULL ,
679661 NULL , NULL , 0 , msg , & err );
680- if (ret ) {
681- ret = STORE_REF_ERROR_OTHER ;
682- goto out ;
683- }
684662
685- if (our_transaction ) {
686- switch (ref_transaction_commit (our_transaction , & err )) {
687- case 0 :
688- break ;
689- case REF_TRANSACTION_ERROR_NAME_CONFLICT :
690- ret = STORE_REF_ERROR_DF_CONFLICT ;
691- goto out ;
692- default :
693- ret = STORE_REF_ERROR_OTHER ;
694- goto out ;
695- }
696- }
697-
698- out :
699- ref_transaction_free (our_transaction );
700663 if (ret )
701664 error ("%s" , err .buf );
702665 strbuf_release (& err );
@@ -1139,7 +1102,6 @@ N_("it took %.2f seconds to check forced updates; you can use\n"
11391102 "to avoid this check\n" );
11401103
11411104static int store_updated_refs (struct display_state * display_state ,
1142- const char * remote_name ,
11431105 int connectivity_checked ,
11441106 struct ref_transaction * transaction , struct ref * ref_map ,
11451107 struct fetch_head * fetch_head ,
@@ -1277,11 +1239,6 @@ static int store_updated_refs(struct display_state *display_state,
12771239 }
12781240 }
12791241
1280- if (rc & STORE_REF_ERROR_DF_CONFLICT )
1281- error (_ ("some local refs could not be updated; try running\n"
1282- " 'git remote prune %s' to remove any old, conflicting "
1283- "branches" ), remote_name );
1284-
12851242 if (advice_enabled (ADVICE_FETCH_SHOW_FORCED_UPDATES )) {
12861243 if (!config -> show_forced_updates ) {
12871244 warning (_ (warn_show_forced_updates ));
@@ -1365,9 +1322,8 @@ static int fetch_and_consume_refs(struct display_state *display_state,
13651322 }
13661323
13671324 trace2_region_enter ("fetch" , "consume_refs" , the_repository );
1368- ret = store_updated_refs (display_state , transport -> remote -> name ,
1369- connectivity_checked , transaction , ref_map ,
1370- fetch_head , config );
1325+ ret = store_updated_refs (display_state , connectivity_checked ,
1326+ transaction , ref_map , fetch_head , config );
13711327 trace2_region_leave ("fetch" , "consume_refs" , the_repository );
13721328
13731329out :
@@ -1687,6 +1643,32 @@ static int set_head(const struct ref *remote_refs, struct remote *remote)
16871643 return result ;
16881644}
16891645
1646+ struct ref_rejection_data {
1647+ int * retcode ;
1648+ int conflict_msg_shown ;
1649+ const char * remote_name ;
1650+ };
1651+
1652+ static void ref_transaction_rejection_handler (const char * refname UNUSED ,
1653+ const struct object_id * old_oid UNUSED ,
1654+ const struct object_id * new_oid UNUSED ,
1655+ const char * old_target UNUSED ,
1656+ const char * new_target UNUSED ,
1657+ enum ref_transaction_error err ,
1658+ void * cb_data )
1659+ {
1660+ struct ref_rejection_data * data = (struct ref_rejection_data * )cb_data ;
1661+
1662+ if (err == REF_TRANSACTION_ERROR_NAME_CONFLICT && !data -> conflict_msg_shown ) {
1663+ error (_ ("some local refs could not be updated; try running\n"
1664+ " 'git remote prune %s' to remove any old, conflicting "
1665+ "branches" ), data -> remote_name );
1666+ data -> conflict_msg_shown = 1 ;
1667+ }
1668+
1669+ * data -> retcode = 1 ;
1670+ }
1671+
16901672static int do_fetch (struct transport * transport ,
16911673 struct refspec * rs ,
16921674 const struct fetch_config * config )
@@ -1807,6 +1789,20 @@ static int do_fetch(struct transport *transport,
18071789 retcode = 1 ;
18081790 }
18091791
1792+ /*
1793+ * If not atomic, we can still use batched updates, which would be much
1794+ * more performent. We don't initiate the transaction before pruning,
1795+ * since pruning must be an independent step, to avoid F/D conflicts.
1796+ */
1797+ if (!transaction ) {
1798+ transaction = ref_store_transaction_begin (get_main_ref_store (the_repository ),
1799+ REF_TRANSACTION_ALLOW_FAILURE , & err );
1800+ if (!transaction ) {
1801+ retcode = -1 ;
1802+ goto cleanup ;
1803+ }
1804+ }
1805+
18101806 if (fetch_and_consume_refs (& display_state , transport , transaction , ref_map ,
18111807 & fetch_head , config )) {
18121808 retcode = 1 ;
@@ -1838,16 +1834,31 @@ static int do_fetch(struct transport *transport,
18381834 free_refs (tags_ref_map );
18391835 }
18401836
1841- if (transaction ) {
1842- if (retcode )
1843- goto cleanup ;
1837+ if (retcode )
1838+ goto cleanup ;
1839+
1840+ retcode = ref_transaction_commit (transaction , & err );
1841+ if (retcode ) {
1842+ /*
1843+ * Explicitly handle transaction cleanup to avoid
1844+ * aborting an already closed transaction.
1845+ */
1846+ ref_transaction_free (transaction );
1847+ transaction = NULL ;
1848+ goto cleanup ;
1849+ }
18441850
1845- retcode = ref_transaction_commit (transaction , & err );
1851+ if (!atomic_fetch ) {
1852+ struct ref_rejection_data data = {
1853+ .retcode = & retcode ,
1854+ .conflict_msg_shown = 0 ,
1855+ .remote_name = transport -> remote -> name ,
1856+ };
1857+
1858+ ref_transaction_for_each_rejected_update (transaction ,
1859+ ref_transaction_rejection_handler ,
1860+ & data );
18461861 if (retcode ) {
1847- /*
1848- * Explicitly handle transaction cleanup to avoid
1849- * aborting an already closed transaction.
1850- */
18511862 ref_transaction_free (transaction );
18521863 transaction = NULL ;
18531864 goto cleanup ;
0 commit comments