3131#include "date.h"
3232#include "commit.h"
3333#include "wildmatch.h"
34+ #include "ident.h"
3435
3536/*
3637 * List of all available backends
@@ -1199,6 +1200,7 @@ void ref_transaction_free(struct ref_transaction *transaction)
11991200
12001201 for (i = 0 ; i < transaction -> nr ; i ++ ) {
12011202 free (transaction -> updates [i ]-> msg );
1203+ free (transaction -> updates [i ]-> committer_info );
12021204 free ((char * )transaction -> updates [i ]-> new_target );
12031205 free ((char * )transaction -> updates [i ]-> old_target );
12041206 free (transaction -> updates [i ]);
@@ -1213,6 +1215,7 @@ struct ref_update *ref_transaction_add_update(
12131215 const struct object_id * new_oid ,
12141216 const struct object_id * old_oid ,
12151217 const char * new_target , const char * old_target ,
1218+ const char * committer_info ,
12161219 const char * msg )
12171220{
12181221 struct ref_update * update ;
@@ -1237,12 +1240,36 @@ struct ref_update *ref_transaction_add_update(
12371240 oidcpy (& update -> new_oid , new_oid );
12381241 if ((flags & REF_HAVE_OLD ) && old_oid )
12391242 oidcpy (& update -> old_oid , old_oid );
1240- if (!(flags & REF_SKIP_CREATE_REFLOG ))
1243+ if (!(flags & REF_SKIP_CREATE_REFLOG )) {
1244+ update -> committer_info = xstrdup_or_null (committer_info );
12411245 update -> msg = normalize_reflog_message (msg );
1246+ }
12421247
12431248 return update ;
12441249}
12451250
1251+ static int transaction_refname_valid (const char * refname ,
1252+ const struct object_id * new_oid ,
1253+ unsigned int flags , struct strbuf * err )
1254+ {
1255+ if (flags & REF_SKIP_REFNAME_VERIFICATION )
1256+ return 1 ;
1257+
1258+ if (is_pseudo_ref (refname )) {
1259+ const char * what = flags & REF_LOG_ONLY ? "reflog for pseudoref" : "pseudoref" ;
1260+ strbuf_addf (err , _ ("refusing to update %s '%s'" ), what , refname );
1261+ return 0 ;
1262+ } else if ((new_oid && !is_null_oid (new_oid )) ?
1263+ check_refname_format (refname , REFNAME_ALLOW_ONELEVEL ) :
1264+ !refname_is_safe (refname )) {
1265+ const char * what = flags & REF_LOG_ONLY ? "reflog with bad name" : "ref with bad name" ;
1266+ strbuf_addf (err , _ ("refusing to update %s '%s'" ), what , refname );
1267+ return 0 ;
1268+ }
1269+
1270+ return 1 ;
1271+ }
1272+
12461273int ref_transaction_update (struct ref_transaction * transaction ,
12471274 const char * refname ,
12481275 const struct object_id * new_oid ,
@@ -1260,21 +1287,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
12601287 return -1 ;
12611288 }
12621289
1263- if (!(flags & REF_SKIP_REFNAME_VERIFICATION ) &&
1264- ((new_oid && !is_null_oid (new_oid )) ?
1265- check_refname_format (refname , REFNAME_ALLOW_ONELEVEL ) :
1266- !refname_is_safe (refname ))) {
1267- strbuf_addf (err , _ ("refusing to update ref with bad name '%s'" ),
1268- refname );
1290+ if (!transaction_refname_valid (refname , new_oid , flags , err ))
12691291 return -1 ;
1270- }
1271-
1272- if (!(flags & REF_SKIP_REFNAME_VERIFICATION ) &&
1273- is_pseudo_ref (refname )) {
1274- strbuf_addf (err , _ ("refusing to update pseudoref '%s'" ),
1275- refname );
1276- return -1 ;
1277- }
12781292
12791293 if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS )
12801294 BUG ("illegal flags 0x%x passed to ref_transaction_update()" , flags );
@@ -1291,7 +1305,38 @@ int ref_transaction_update(struct ref_transaction *transaction,
12911305
12921306 ref_transaction_add_update (transaction , refname , flags ,
12931307 new_oid , old_oid , new_target ,
1294- old_target , msg );
1308+ old_target , NULL , msg );
1309+
1310+ return 0 ;
1311+ }
1312+
1313+ int ref_transaction_update_reflog (struct ref_transaction * transaction ,
1314+ const char * refname ,
1315+ const struct object_id * new_oid ,
1316+ const struct object_id * old_oid ,
1317+ const char * committer_info , unsigned int flags ,
1318+ const char * msg , unsigned int index ,
1319+ struct strbuf * err )
1320+ {
1321+ struct ref_update * update ;
1322+
1323+ assert (err );
1324+
1325+ flags |= REF_LOG_ONLY | REF_NO_DEREF ;
1326+
1327+ if (!transaction_refname_valid (refname , new_oid , flags , err ))
1328+ return -1 ;
1329+
1330+ update = ref_transaction_add_update (transaction , refname , flags ,
1331+ new_oid , old_oid , NULL , NULL ,
1332+ committer_info , msg );
1333+ /*
1334+ * While we do set the old_oid value, we unset the flag to skip
1335+ * old_oid verification which only makes sense for refs.
1336+ */
1337+ update -> flags &= ~REF_HAVE_OLD ;
1338+ update -> index = index ;
1339+
12951340 return 0 ;
12961341}
12971342
@@ -2711,6 +2756,7 @@ struct migration_data {
27112756 struct ref_store * old_refs ;
27122757 struct ref_transaction * transaction ;
27132758 struct strbuf * errbuf ;
2759+ struct strbuf sb ;
27142760};
27152761
27162762static int migrate_one_ref (const char * refname , const char * referent UNUSED , const struct object_id * oid ,
@@ -2743,6 +2789,52 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con
27432789 return ret ;
27442790}
27452791
2792+ struct reflog_migration_data {
2793+ unsigned int index ;
2794+ const char * refname ;
2795+ struct ref_store * old_refs ;
2796+ struct ref_transaction * transaction ;
2797+ struct strbuf * errbuf ;
2798+ struct strbuf * sb ;
2799+ };
2800+
2801+ static int migrate_one_reflog_entry (struct object_id * old_oid ,
2802+ struct object_id * new_oid ,
2803+ const char * committer ,
2804+ timestamp_t timestamp , int tz ,
2805+ const char * msg , void * cb_data )
2806+ {
2807+ struct reflog_migration_data * data = cb_data ;
2808+ const char * date ;
2809+ int ret ;
2810+
2811+ date = show_date (timestamp , tz , DATE_MODE (NORMAL ));
2812+ strbuf_reset (data -> sb );
2813+ /* committer contains name and email */
2814+ strbuf_addstr (data -> sb , fmt_ident ("" , committer , WANT_BLANK_IDENT , date , 0 ));
2815+
2816+ ret = ref_transaction_update_reflog (data -> transaction , data -> refname ,
2817+ new_oid , old_oid , data -> sb -> buf ,
2818+ REF_HAVE_NEW | REF_HAVE_OLD , msg ,
2819+ data -> index ++ , data -> errbuf );
2820+ return ret ;
2821+ }
2822+
2823+ static int migrate_one_reflog (const char * refname , void * cb_data )
2824+ {
2825+ struct migration_data * migration_data = cb_data ;
2826+ struct reflog_migration_data data = {
2827+ .refname = refname ,
2828+ .old_refs = migration_data -> old_refs ,
2829+ .transaction = migration_data -> transaction ,
2830+ .errbuf = migration_data -> errbuf ,
2831+ .sb = & migration_data -> sb ,
2832+ };
2833+
2834+ return refs_for_each_reflog_ent (migration_data -> old_refs , refname ,
2835+ migrate_one_reflog_entry , & data );
2836+ }
2837+
27462838static int move_files (const char * from_path , const char * to_path , struct strbuf * errbuf )
27472839{
27482840 struct strbuf from_buf = STRBUF_INIT , to_buf = STRBUF_INIT ;
@@ -2809,13 +2901,6 @@ static int move_files(const char *from_path, const char *to_path, struct strbuf
28092901 return ret ;
28102902}
28112903
2812- static int count_reflogs (const char * reflog UNUSED , void * payload )
2813- {
2814- size_t * reflog_count = payload ;
2815- (* reflog_count )++ ;
2816- return 0 ;
2817- }
2818-
28192904static int has_worktrees (void )
28202905{
28212906 struct worktree * * worktrees = get_worktrees ();
@@ -2840,8 +2925,9 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28402925 struct ref_store * old_refs = NULL , * new_refs = NULL ;
28412926 struct ref_transaction * transaction = NULL ;
28422927 struct strbuf new_gitdir = STRBUF_INIT ;
2843- struct migration_data data ;
2844- size_t reflog_count = 0 ;
2928+ struct migration_data data = {
2929+ .sb = STRBUF_INIT ,
2930+ };
28452931 int did_migrate_refs = 0 ;
28462932 int ret ;
28472933
@@ -2853,21 +2939,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28532939
28542940 old_refs = get_main_ref_store (repo );
28552941
2856- /*
2857- * We do not have any interfaces that would allow us to write many
2858- * reflog entries. Once we have them we can remove this restriction.
2859- */
2860- if (refs_for_each_reflog (old_refs , count_reflogs , & reflog_count ) < 0 ) {
2861- strbuf_addstr (errbuf , "cannot count reflogs" );
2862- ret = -1 ;
2863- goto done ;
2864- }
2865- if (reflog_count ) {
2866- strbuf_addstr (errbuf , "migrating reflogs is not supported yet" );
2867- ret = -1 ;
2868- goto done ;
2869- }
2870-
28712942 /*
28722943 * Worktrees complicate the migration because every worktree has a
28732944 * separate ref storage. While it should be feasible to implement, this
@@ -2893,17 +2964,21 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28932964 * This operation is safe as we do not yet modify the main
28942965 * repository.
28952966 *
2896- * 3. If we're in dry-run mode then we are done and can hand over the
2967+ * 3. Enumerate all reflogs and write them into the new ref storage.
2968+ * This operation is safe as we do not yet modify the main
2969+ * repository.
2970+ *
2971+ * 4. If we're in dry-run mode then we are done and can hand over the
28972972 * directory to the caller for inspection. If not, we now start
28982973 * with the destructive part.
28992974 *
2900- * 4 . Delete the old ref storage from disk. As we have a copy of refs
2975+ * 5 . Delete the old ref storage from disk. As we have a copy of refs
29012976 * in the new ref storage it's okay(ish) if we now get interrupted
29022977 * as there is an equivalent copy of all refs available.
29032978 *
2904- * 5 . Move the new ref storage files into place.
2979+ * 6 . Move the new ref storage files into place.
29052980 *
2906- * 6 . Change the repository format to the new ref format.
2981+ * 7 . Change the repository format to the new ref format.
29072982 */
29082983 strbuf_addf (& new_gitdir , "%s/%s" , old_refs -> gitdir , "ref_migration.XXXXXX" );
29092984 if (!mkdtemp (new_gitdir .buf )) {
@@ -2945,6 +3020,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
29453020 if (ret < 0 )
29463021 goto done ;
29473022
3023+ ret = refs_for_each_reflog (old_refs , migrate_one_reflog , & data );
3024+ if (ret < 0 )
3025+ goto done ;
3026+
29483027 ret = ref_transaction_commit (transaction , errbuf );
29493028 if (ret < 0 )
29503029 goto done ;
@@ -3020,6 +3099,7 @@ int repo_migrate_ref_storage_format(struct repository *repo,
30203099 }
30213100 ref_transaction_free (transaction );
30223101 strbuf_release (& new_gitdir );
3102+ strbuf_release (& data .sb );
30233103 return ret ;
30243104}
30253105
0 commit comments