31
31
#include "date.h"
32
32
#include "commit.h"
33
33
#include "wildmatch.h"
34
+ #include "ident.h"
34
35
35
36
/*
36
37
* List of all available backends
@@ -1199,6 +1200,7 @@ void ref_transaction_free(struct ref_transaction *transaction)
1199
1200
1200
1201
for (i = 0 ; i < transaction -> nr ; i ++ ) {
1201
1202
free (transaction -> updates [i ]-> msg );
1203
+ free (transaction -> updates [i ]-> committer_info );
1202
1204
free ((char * )transaction -> updates [i ]-> new_target );
1203
1205
free ((char * )transaction -> updates [i ]-> old_target );
1204
1206
free (transaction -> updates [i ]);
@@ -1213,6 +1215,7 @@ struct ref_update *ref_transaction_add_update(
1213
1215
const struct object_id * new_oid ,
1214
1216
const struct object_id * old_oid ,
1215
1217
const char * new_target , const char * old_target ,
1218
+ const char * committer_info ,
1216
1219
const char * msg )
1217
1220
{
1218
1221
struct ref_update * update ;
@@ -1237,12 +1240,44 @@ struct ref_update *ref_transaction_add_update(
1237
1240
oidcpy (& update -> new_oid , new_oid );
1238
1241
if ((flags & REF_HAVE_OLD ) && old_oid )
1239
1242
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 );
1241
1245
update -> msg = normalize_reflog_message (msg );
1246
+ }
1242
1247
1243
1248
return update ;
1244
1249
}
1245
1250
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
+
1246
1281
int ref_transaction_update (struct ref_transaction * transaction ,
1247
1282
const char * refname ,
1248
1283
const struct object_id * new_oid ,
@@ -1260,21 +1295,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
1260
1295
return -1 ;
1261
1296
}
1262
1297
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 ))
1269
1299
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
- }
1278
1300
1279
1301
if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS )
1280
1302
BUG ("illegal flags 0x%x passed to ref_transaction_update()" , flags );
@@ -1291,7 +1313,38 @@ int ref_transaction_update(struct ref_transaction *transaction,
1291
1313
1292
1314
ref_transaction_add_update (transaction , refname , flags ,
1293
1315
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
+
1295
1348
return 0 ;
1296
1349
}
1297
1350
@@ -2711,6 +2764,7 @@ struct migration_data {
2711
2764
struct ref_store * old_refs ;
2712
2765
struct ref_transaction * transaction ;
2713
2766
struct strbuf * errbuf ;
2767
+ struct strbuf sb ;
2714
2768
};
2715
2769
2716
2770
static 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
2743
2797
return ret ;
2744
2798
}
2745
2799
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
+
2746
2846
static int move_files (const char * from_path , const char * to_path , struct strbuf * errbuf )
2747
2847
{
2748
2848
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
2809
2909
return ret ;
2810
2910
}
2811
2911
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
-
2819
2912
static int has_worktrees (void )
2820
2913
{
2821
2914
struct worktree * * worktrees = get_worktrees ();
@@ -2840,8 +2933,9 @@ int repo_migrate_ref_storage_format(struct repository *repo,
2840
2933
struct ref_store * old_refs = NULL , * new_refs = NULL ;
2841
2934
struct ref_transaction * transaction = NULL ;
2842
2935
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
+ };
2845
2939
int did_migrate_refs = 0 ;
2846
2940
int ret ;
2847
2941
@@ -2853,21 +2947,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
2853
2947
2854
2948
old_refs = get_main_ref_store (repo );
2855
2949
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
-
2871
2950
/*
2872
2951
* Worktrees complicate the migration because every worktree has a
2873
2952
* separate ref storage. While it should be feasible to implement, this
@@ -2893,17 +2972,21 @@ int repo_migrate_ref_storage_format(struct repository *repo,
2893
2972
* This operation is safe as we do not yet modify the main
2894
2973
* repository.
2895
2974
*
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
2897
2980
* directory to the caller for inspection. If not, we now start
2898
2981
* with the destructive part.
2899
2982
*
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
2901
2984
* in the new ref storage it's okay(ish) if we now get interrupted
2902
2985
* as there is an equivalent copy of all refs available.
2903
2986
*
2904
- * 5 . Move the new ref storage files into place.
2987
+ * 6 . Move the new ref storage files into place.
2905
2988
*
2906
- * 6 . Change the repository format to the new ref format.
2989
+ * 7 . Change the repository format to the new ref format.
2907
2990
*/
2908
2991
strbuf_addf (& new_gitdir , "%s/%s" , old_refs -> gitdir , "ref_migration.XXXXXX" );
2909
2992
if (!mkdtemp (new_gitdir .buf )) {
@@ -2945,6 +3028,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
2945
3028
if (ret < 0 )
2946
3029
goto done ;
2947
3030
3031
+ ret = refs_for_each_reflog (old_refs , migrate_one_reflog , & data );
3032
+ if (ret < 0 )
3033
+ goto done ;
3034
+
2948
3035
ret = ref_transaction_commit (transaction , errbuf );
2949
3036
if (ret < 0 )
2950
3037
goto done ;
@@ -3020,6 +3107,7 @@ int repo_migrate_ref_storage_format(struct repository *repo,
3020
3107
}
3021
3108
ref_transaction_free (transaction );
3022
3109
strbuf_release (& new_gitdir );
3110
+ strbuf_release (& data .sb );
3023
3111
return ret ;
3024
3112
}
3025
3113
0 commit comments