123module cli45import json26import os7import src.fmt8import src.machine9import src.migrate10import src.snapshot11import time1213pub fn cmd_migrate(raw []string) int {14 args := parse('migrate', raw, Options{15 values: ['lane']16 flags: ['json', 'yes']17 }) or { return usage_error(err.msg()) }18 mut lane := args.value('lane')19 if lane == '' {20 lane = migrate.default_lane21 }22 if lane !in ['dev', 'main'] {23 return usage_error('--lane takes dev or main, not "${lane}"')24 }25 plan := migrate.prepare(os.getwd(), lane) or { return refuse(args.json(), err.msg()) }26 if !args.json() {27 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()}')28 note('this will:')29 note(' · copy the history into one .koh file and check every save')30 if plan.renames_build {31 note(' · rename kepr.build to koh.build, as its own save')32 }33 note(' · keep the Koh 2 data as ${migrate.archive_dir}/ — move it back to undo')34 }35 approved := confirm(args.flag('yes')) or { return refuse(args.json(), err.msg()) }36 if !approved {37 return refuse(args.json(), 'not migrating, then — nothing changed')38 }39 report := migrate.run(plan, fn (stage string, done int, total int) {40 working('${stage} ${done} / ${total} saves')41 }) or { return refuse(args.json(), err.msg()) }42 if args.json() {43 emit_json(json2.encode(MigrateJson{44 repo: report.root45 lane: report.lane46 saves: report.saves47 checkpoints: report.checkpoints48 flags: report.flags49 objects: report.objects50 head: report.head51 ignore_moved: report.ignore_carried52 build_file: report.build_renamed53 unsafe_paths: report.unsafe_paths54 }))55 return 056 }57 ok('migrated ${fmt.plural(report.saves, 'save')} from Koh 2 (lane ${report.lane})')58 note('${fmt.plural(report.checkpoints, 'checkpoint')} · ${fmt.plural(report.flags, 'flag')} · ${fmt.plural(report.objects, 'object')}')59 warn_unsafe_paths(report.unsafe_paths)60 note('the Koh 2 data is untouched in ${migrate.archive_dir}/ — move it back to go back')61 if report.ignore_carried {62 note('carried the ignore rules to ${snapshot.ignore_file}')63 }64 if report.build_renamed {65 note('renamed kepr.build to koh.build, and saved that')66 }67 if report.log_md_was_tracked {68 warn('LOG.md was tracked by Koh 2; koh writes it itself now, so it is no longer snapshotted')69 }70 note('run "koh status" to see what the migration left, then "koh save"')71 if machine.has_remote() {72 note('this machine has a remote — run "koh offer" to publish the migrated history')73 }74 return 075}7677struct MigrateJson {78 repo string79 lane string80 saves int81 checkpoints int82 flags int83 objects int84 head string85 ignore_moved bool86 build_file bool87 unsafe_paths []string88}