//! `koh migrate` — one-time conversion from Koh 2. module cli import json2 import os import src.fmt import src.machine import src.migrate import src.snapshot import time pub fn cmd_migrate(raw []string) int { args := parse('migrate', raw, Options{ values: ['lane'] flags: ['json', 'yes'] }) or { return usage_error(err.msg()) } mut lane := args.value('lane') if lane == '' { lane = migrate.default_lane } if lane !in ['dev', 'main'] { return usage_error('--lane takes dev or main, not "${lane}"') } plan := migrate.prepare(os.getwd(), lane) or { return refuse(args.json(), err.msg()) } if !args.json() { note('Koh 2 repo · lane ${plan.lane} · ${fmt.plural(plan.saves, 'save')} (${fmt.plural(plan.checkpoints, 'checkpoint')}) · ${fmt.plural(plan.objects, 'object')} · last save ${time.unix(plan.last_saved).ymmdd()}') note('this will:') note(' · copy the history into one .koh file and check every save') if plan.renames_build { note(' · rename kepr.build to koh.build, as its own save') } note(' · keep the Koh 2 data as ${migrate.archive_dir}/ — move it back to undo') } approved := confirm(args.flag('yes')) or { return refuse(args.json(), err.msg()) } if !approved { return refuse(args.json(), 'not migrating, then — nothing changed') } report := migrate.run(plan, fn (stage string, done int, total int) { working('${stage} ${done} / ${total} saves') }) or { return refuse(args.json(), err.msg()) } if args.json() { emit_json(json2.encode(MigrateJson{ repo: report.root lane: report.lane saves: report.saves checkpoints: report.checkpoints flags: report.flags objects: report.objects head: report.head ignore_moved: report.ignore_carried build_file: report.build_renamed unsafe_paths: report.unsafe_paths })) return 0 } ok('migrated ${fmt.plural(report.saves, 'save')} from Koh 2 (lane ${report.lane})') note('${fmt.plural(report.checkpoints, 'checkpoint')} · ${fmt.plural(report.flags, 'flag')} · ${fmt.plural(report.objects, 'object')}') warn_unsafe_paths(report.unsafe_paths) note('the Koh 2 data is untouched in ${migrate.archive_dir}/ — move it back to go back') if report.ignore_carried { note('carried the ignore rules to ${snapshot.ignore_file}') } if report.build_renamed { note('renamed kepr.build to koh.build, and saved that') } if report.log_md_was_tracked { warn('LOG.md was tracked by Koh 2; koh writes it itself now, so it is no longer snapshotted') } note('run "koh status" to see what the migration left, then "koh save"') if machine.has_remote() { note('this machine has a remote — run "koh offer" to publish the migrated history') } return 0 } struct MigrateJson { repo string lane string saves int checkpoints int flags int objects int head string ignore_moved bool build_file bool unsafe_paths []string }