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,44 @@ 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 * refusal_msg ;
1260+ if (flags & REF_LOG_ONLY )
1261+ refusal_msg = _ ("refusing to update reflog for pseudoref '%s'" );
1262+ else
1263+ refusal_msg = _ ("refusing to update pseudoref '%s'" );
1264+ strbuf_addf (err , refusal_msg , refname );
1265+ return 0 ;
1266+ } else if ((new_oid && !is_null_oid (new_oid )) ?
1267+ check_refname_format (refname , REFNAME_ALLOW_ONELEVEL ) :
1268+ !refname_is_safe (refname )) {
1269+ const char * refusal_msg ;
1270+ if (flags & REF_LOG_ONLY )
1271+ refusal_msg = _ ("refusing to update reflog with bad name '%s'" );
1272+ else
1273+ refusal_msg = _ ("refusing to update ref with bad name '%s'" );
1274+ strbuf_addf (err , refusal_msg , refname );
1275+ return 0 ;
1276+ }
1277+
1278+ return 1 ;
1279+ }
1280+
12461281int ref_transaction_update (struct ref_transaction * transaction ,
12471282 const char * refname ,
12481283 const struct object_id * new_oid ,
@@ -1260,21 +1295,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
12601295 return -1 ;
12611296 }
12621297
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 );
1298+ if (!transaction_refname_valid (refname , new_oid , flags , err ))
12691299 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- }
12781300
12791301 if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS )
12801302 BUG ("illegal flags 0x%x passed to ref_transaction_update()" , flags );
@@ -1291,7 +1313,38 @@ int ref_transaction_update(struct ref_transaction *transaction,
12911313
12921314 ref_transaction_add_update (transaction , refname , flags ,
12931315 new_oid , old_oid , new_target ,
1294- old_target , msg );
1316+ old_target , NULL , msg );
1317+
1318+ return 0 ;
1319+ }
1320+
1321+ int ref_transaction_update_reflog (struct ref_transaction * transaction ,
1322+ const char * refname ,
1323+ const struct object_id * new_oid ,
1324+ const struct object_id * old_oid ,
1325+ const char * committer_info , unsigned int flags ,
1326+ const char * msg , unsigned int index ,
1327+ struct strbuf * err )
1328+ {
1329+ struct ref_update * update ;
1330+
1331+ assert (err );
1332+
1333+ flags |= REF_LOG_ONLY | REF_NO_DEREF ;
1334+
1335+ if (!transaction_refname_valid (refname , new_oid , flags , err ))
1336+ return -1 ;
1337+
1338+ update = ref_transaction_add_update (transaction , refname , flags ,
1339+ new_oid , old_oid , NULL , NULL ,
1340+ committer_info , msg );
1341+ /*
1342+ * While we do set the old_oid value, we unset the flag to skip
1343+ * old_oid verification which only makes sense for refs.
1344+ */
1345+ update -> flags &= ~REF_HAVE_OLD ;
1346+ update -> index = index ;
1347+
12951348 return 0 ;
12961349}
12971350
@@ -2711,6 +2764,7 @@ struct migration_data {
27112764 struct ref_store * old_refs ;
27122765 struct ref_transaction * transaction ;
27132766 struct strbuf * errbuf ;
2767+ struct strbuf sb ;
27142768};
27152769
27162770static int migrate_one_ref (const char * refname , const char * referent UNUSED , const struct object_id * oid ,
@@ -2743,6 +2797,52 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con
27432797 return ret ;
27442798}
27452799
2800+ struct reflog_migration_data {
2801+ unsigned int index ;
2802+ const char * refname ;
2803+ struct ref_store * old_refs ;
2804+ struct ref_transaction * transaction ;
2805+ struct strbuf * errbuf ;
2806+ struct strbuf * sb ;
2807+ };
2808+
2809+ static int migrate_one_reflog_entry (struct object_id * old_oid ,
2810+ struct object_id * new_oid ,
2811+ const char * committer ,
2812+ timestamp_t timestamp , int tz ,
2813+ const char * msg , void * cb_data )
2814+ {
2815+ struct reflog_migration_data * data = cb_data ;
2816+ const char * date ;
2817+ int ret ;
2818+
2819+ date = show_date (timestamp , tz , DATE_MODE (NORMAL ));
2820+ strbuf_reset (data -> sb );
2821+ /* committer contains name and email */
2822+ strbuf_addstr (data -> sb , fmt_ident ("" , committer , WANT_BLANK_IDENT , date , 0 ));
2823+
2824+ ret = ref_transaction_update_reflog (data -> transaction , data -> refname ,
2825+ new_oid , old_oid , data -> sb -> buf ,
2826+ REF_HAVE_NEW | REF_HAVE_OLD , msg ,
2827+ data -> index ++ , data -> errbuf );
2828+ return ret ;
2829+ }
2830+
2831+ static int migrate_one_reflog (const char * refname , void * cb_data )
2832+ {
2833+ struct migration_data * migration_data = cb_data ;
2834+ struct reflog_migration_data data = {
2835+ .refname = refname ,
2836+ .old_refs = migration_data -> old_refs ,
2837+ .transaction = migration_data -> transaction ,
2838+ .errbuf = migration_data -> errbuf ,
2839+ .sb = & migration_data -> sb ,
2840+ };
2841+
2842+ return refs_for_each_reflog_ent (migration_data -> old_refs , refname ,
2843+ migrate_one_reflog_entry , & data );
2844+ }
2845+
27462846static int move_files (const char * from_path , const char * to_path , struct strbuf * errbuf )
27472847{
27482848 struct strbuf from_buf = STRBUF_INIT , to_buf = STRBUF_INIT ;
@@ -2809,13 +2909,6 @@ static int move_files(const char *from_path, const char *to_path, struct strbuf
28092909 return ret ;
28102910}
28112911
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-
28192912static int has_worktrees (void )
28202913{
28212914 struct worktree * * worktrees = get_worktrees ();
@@ -2840,8 +2933,9 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28402933 struct ref_store * old_refs = NULL , * new_refs = NULL ;
28412934 struct ref_transaction * transaction = NULL ;
28422935 struct strbuf new_gitdir = STRBUF_INIT ;
2843- struct migration_data data ;
2844- size_t reflog_count = 0 ;
2936+ struct migration_data data = {
2937+ .sb = STRBUF_INIT ,
2938+ };
28452939 int did_migrate_refs = 0 ;
28462940 int ret ;
28472941
@@ -2853,21 +2947,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28532947
28542948 old_refs = get_main_ref_store (repo );
28552949
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-
28712950 /*
28722951 * Worktrees complicate the migration because every worktree has a
28732952 * separate ref storage. While it should be feasible to implement, this
@@ -2893,17 +2972,21 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28932972 * This operation is safe as we do not yet modify the main
28942973 * repository.
28952974 *
2896- * 3. If we're in dry-run mode then we are done and can hand over the
2975+ * 3. Enumerate all reflogs and write them into the new ref storage.
2976+ * This operation is safe as we do not yet modify the main
2977+ * repository.
2978+ *
2979+ * 4. If we're in dry-run mode then we are done and can hand over the
28972980 * directory to the caller for inspection. If not, we now start
28982981 * with the destructive part.
28992982 *
2900- * 4 . Delete the old ref storage from disk. As we have a copy of refs
2983+ * 5 . Delete the old ref storage from disk. As we have a copy of refs
29012984 * in the new ref storage it's okay(ish) if we now get interrupted
29022985 * as there is an equivalent copy of all refs available.
29032986 *
2904- * 5 . Move the new ref storage files into place.
2987+ * 6 . Move the new ref storage files into place.
29052988 *
2906- * 6 . Change the repository format to the new ref format.
2989+ * 7 . Change the repository format to the new ref format.
29072990 */
29082991 strbuf_addf (& new_gitdir , "%s/%s" , old_refs -> gitdir , "ref_migration.XXXXXX" );
29092992 if (!mkdtemp (new_gitdir .buf )) {
@@ -2945,6 +3028,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
29453028 if (ret < 0 )
29463029 goto done ;
29473030
3031+ ret = refs_for_each_reflog (old_refs , migrate_one_reflog , & data );
3032+ if (ret < 0 )
3033+ goto done ;
3034+
29483035 ret = ref_transaction_commit (transaction , errbuf );
29493036 if (ret < 0 )
29503037 goto done ;
@@ -3020,6 +3107,7 @@ int repo_migrate_ref_storage_format(struct repository *repo,
30203107 }
30213108 ref_transaction_free (transaction );
30223109 strbuf_release (& new_gitdir );
3110+ strbuf_release (& data .sb );
30233111 return ret ;
30243112}
30253113
0 commit comments