3030#include "date.h"
3131#include "commit.h"
3232#include "wildmatch.h"
33+ #include "ident.h"
3334
3435/*
3536 * List of all available backends
@@ -2673,6 +2674,7 @@ struct migration_data {
26732674 struct ref_store * old_refs ;
26742675 struct ref_transaction * transaction ;
26752676 struct strbuf * errbuf ;
2677+ struct strbuf sb ;
26762678};
26772679
26782680static int migrate_one_ref (const char * refname , const char * referent UNUSED , const struct object_id * oid ,
@@ -2705,6 +2707,52 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con
27052707 return ret ;
27062708}
27072709
2710+ struct reflog_migration_data {
2711+ unsigned int index ;
2712+ const char * refname ;
2713+ struct ref_store * old_refs ;
2714+ struct ref_transaction * transaction ;
2715+ struct strbuf * errbuf ;
2716+ struct strbuf * sb ;
2717+ };
2718+
2719+ static int migrate_one_reflog_entry (struct object_id * old_oid ,
2720+ struct object_id * new_oid ,
2721+ const char * committer ,
2722+ timestamp_t timestamp , int tz ,
2723+ const char * msg , void * cb_data )
2724+ {
2725+ struct reflog_migration_data * data = cb_data ;
2726+ const char * date ;
2727+ int ret ;
2728+
2729+ date = show_date (timestamp , tz , DATE_MODE (NORMAL ));
2730+ strbuf_reset (data -> sb );
2731+ /* committer contains name and email */
2732+ strbuf_addstr (data -> sb , fmt_ident ("" , committer , WANT_BLANK_IDENT , date , 0 ));
2733+
2734+ ret = ref_transaction_update_reflog (data -> transaction , data -> refname ,
2735+ new_oid , old_oid , data -> sb -> buf ,
2736+ REF_HAVE_NEW | REF_HAVE_OLD , msg ,
2737+ data -> index ++ , data -> errbuf );
2738+ return ret ;
2739+ }
2740+
2741+ static int migrate_one_reflog (const char * refname , void * cb_data )
2742+ {
2743+ struct migration_data * migration_data = cb_data ;
2744+ struct reflog_migration_data data = {
2745+ .refname = refname ,
2746+ .old_refs = migration_data -> old_refs ,
2747+ .transaction = migration_data -> transaction ,
2748+ .errbuf = migration_data -> errbuf ,
2749+ .sb = & migration_data -> sb ,
2750+ };
2751+
2752+ return refs_for_each_reflog_ent (migration_data -> old_refs , refname ,
2753+ migrate_one_reflog_entry , & data );
2754+ }
2755+
27082756static int move_files (const char * from_path , const char * to_path , struct strbuf * errbuf )
27092757{
27102758 struct strbuf from_buf = STRBUF_INIT , to_buf = STRBUF_INIT ;
@@ -2771,13 +2819,6 @@ static int move_files(const char *from_path, const char *to_path, struct strbuf
27712819 return ret ;
27722820}
27732821
2774- static int count_reflogs (const char * reflog UNUSED , void * payload )
2775- {
2776- size_t * reflog_count = payload ;
2777- (* reflog_count )++ ;
2778- return 0 ;
2779- }
2780-
27812822static int has_worktrees (void )
27822823{
27832824 struct worktree * * worktrees = get_worktrees ();
@@ -2802,8 +2843,9 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28022843 struct ref_store * old_refs = NULL , * new_refs = NULL ;
28032844 struct ref_transaction * transaction = NULL ;
28042845 struct strbuf new_gitdir = STRBUF_INIT ;
2805- struct migration_data data ;
2806- size_t reflog_count = 0 ;
2846+ struct migration_data data = {
2847+ .sb = STRBUF_INIT ,
2848+ };
28072849 int did_migrate_refs = 0 ;
28082850 int ret ;
28092851
@@ -2815,21 +2857,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28152857
28162858 old_refs = get_main_ref_store (repo );
28172859
2818- /*
2819- * We do not have any interfaces that would allow us to write many
2820- * reflog entries. Once we have them we can remove this restriction.
2821- */
2822- if (refs_for_each_reflog (old_refs , count_reflogs , & reflog_count ) < 0 ) {
2823- strbuf_addstr (errbuf , "cannot count reflogs" );
2824- ret = -1 ;
2825- goto done ;
2826- }
2827- if (reflog_count ) {
2828- strbuf_addstr (errbuf , "migrating reflogs is not supported yet" );
2829- ret = -1 ;
2830- goto done ;
2831- }
2832-
28332860 /*
28342861 * Worktrees complicate the migration because every worktree has a
28352862 * separate ref storage. While it should be feasible to implement, this
@@ -2855,17 +2882,21 @@ int repo_migrate_ref_storage_format(struct repository *repo,
28552882 * This operation is safe as we do not yet modify the main
28562883 * repository.
28572884 *
2858- * 3. If we're in dry-run mode then we are done and can hand over the
2885+ * 3. Enumerate all reflogs and write them into the new ref storage.
2886+ * This operation is safe as we do not yet modify the main
2887+ * repository.
2888+ *
2889+ * 4. If we're in dry-run mode then we are done and can hand over the
28592890 * directory to the caller for inspection. If not, we now start
28602891 * with the destructive part.
28612892 *
2862- * 4 . Delete the old ref storage from disk. As we have a copy of refs
2893+ * 5 . Delete the old ref storage from disk. As we have a copy of refs
28632894 * in the new ref storage it's okay(ish) if we now get interrupted
28642895 * as there is an equivalent copy of all refs available.
28652896 *
2866- * 5 . Move the new ref storage files into place.
2897+ * 6 . Move the new ref storage files into place.
28672898 *
2868- * 6 . Change the repository format to the new ref format.
2899+ * 7 . Change the repository format to the new ref format.
28692900 */
28702901 strbuf_addf (& new_gitdir , "%s/%s" , old_refs -> gitdir , "ref_migration.XXXXXX" );
28712902 if (!mkdtemp (new_gitdir .buf )) {
@@ -2907,6 +2938,10 @@ int repo_migrate_ref_storage_format(struct repository *repo,
29072938 if (ret < 0 )
29082939 goto done ;
29092940
2941+ ret = refs_for_each_reflog (old_refs , migrate_one_reflog , & data );
2942+ if (ret < 0 )
2943+ goto done ;
2944+
29102945 ret = ref_transaction_commit (transaction , errbuf );
29112946 if (ret < 0 )
29122947 goto done ;
@@ -2982,6 +3017,7 @@ int repo_migrate_ref_storage_format(struct repository *repo,
29823017 }
29833018 ref_transaction_free (transaction );
29843019 strbuf_release (& new_gitdir );
3020+ strbuf_release (& data .sb );
29853021 return ret ;
29863022}
29873023
0 commit comments