30
#include "date.h"
31
#include "commit.h"
32
#include "wildmatch.h"
33
+#include "ident.h"
34
35
/*
36
* List of all available backends
2674
struct ref_store *old_refs;
2675
struct ref_transaction *transaction;
2676
struct strbuf *errbuf;
2677
+ struct strbuf sb;
2678
};
2679
2680
static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
2707
return ret;
2708
}
2709
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
+
2756
static int move_files(const char *from_path, const char *to_path, struct strbuf *errbuf)
2757
{
2758
struct strbuf from_buf = STRBUF_INIT, to_buf = STRBUF_INIT;
2819
return ret;
2820
}
2821
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
-
2822
static int has_worktrees(void)
2823
{
2824
struct worktree **worktrees = get_worktrees();
2843
struct ref_store *old_refs = NULL, *new_refs = NULL;
2844
struct ref_transaction *transaction = NULL;
2845
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
+ };
2849
int did_migrate_refs = 0;
2850
int ret;
2851
2857
2858
old_refs = get_main_ref_store(repo);
2859
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
-
2860
/*
2861
* Worktrees complicate the migration because every worktree has a
2862
* separate ref storage. While it should be feasible to implement, this
2882
* This operation is safe as we do not yet modify the main
2883
* repository.
2884
*
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
2890
* directory to the caller for inspection. If not, we now start
2891
* with the destructive part.
2892
*
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
2894
* in the new ref storage it's okay(ish) if we now get interrupted
2895
* as there is an equivalent copy of all refs available.
2896
*
2866
- * 5. Move the new ref storage files into place.
2897
+ * 6. Move the new ref storage files into place.
2898
*
2868
- * 6. Change the repository format to the new ref format.
2899
+ * 7. Change the repository format to the new ref format.
2900
*/
2901
strbuf_addf(&new_gitdir, "%s/%s", old_refs->gitdir, "ref_migration.XXXXXX");
2902
if (!mkdtemp(new_gitdir.buf)) {
2938
if (ret < 0)
2939
goto done;
2940
2941
+ ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);
2942
+ if (ret < 0)
2943
+ goto done;
2944
+
2945
ret = ref_transaction_commit(transaction, errbuf);
2946
if (ret < 0)
2947
goto done;
3017
}
3018
ref_transaction_free(transaction);
3019
strbuf_release(&new_gitdir);
3020
+ strbuf_release(&data.sb);
3021
return ret;
3022
}
3023