12345678910111213module cli1415import os16import src.fmt17181920pub fn hand_over(argv []string) {21 if argv.len < 2 {22 return23 }24 command := argv[1]25 if command in ['migrate', 'man', 'help', '--help', '-h', '--version', '-v', 'remote', 'update'] {26 return27 }28 if !inside_koh2_repo(os.getwd()) {29 return30 }31 32 33 if command in ['view', 'steal', 'doctor', 'build', 'strip'] {34 eprintln(' ${fmt.red(fmt.glyph_fail)} "koh ${command}" needs a Koh 3 repo, and this one is still Koh 2 — run "koh migrate" to convert it')35 exit(1)36 }37 target := koh2_binary()38 if target == '' {39 eprintln(' ${fmt.red(fmt.glyph_fail)} this folder holds a Koh 2 repo, and koh2 is not on PATH')40 eprintln(' install koh2, or run "koh migrate" to convert this repo')41 exit(1)42 }43 44 45 eprintln(' ${fmt.dim('this is a Koh 2 repo — handing the command to ${os.file_name(target)}')}')46 // execvp builds argv as [path, ...cmdargs], so the arguments go without47 // our own argv[0].48 os.execvp(target, argv[1..]) or {49 eprintln(' ${fmt.red(fmt.glyph_fail)} could not hand this command to ${target}: ${err.msg()}')50 exit(1)51 }52}5354// koh2_binary finds the Koh 2 binary. Before the cutover it is still called55// `koh`, so that name is a fallback — never this binary itself, which would56// hand the command straight back to us for ever.57fn koh2_binary() string {58 if found := os.find_abs_path_of_executable('koh2') {59 return found60 }61 if legacy := os.find_abs_path_of_executable('koh') {62 if os.real_path(legacy) != os.real_path(os.executable()) {63 return legacy64 }65 }66 return ''67}6869// inside_koh2_repo looks upward for a `.koh` that is a directory. A `.koh`70// file is Koh 3's.71fn inside_koh2_repo(start string) bool {72 mut dir := os.real_path(start)73 for {74 path := os.join_path(dir, '.koh')75 if os.is_dir(path) {76 return true77 }78 if os.is_file(path) {79 return false80 }81 parent := os.dir(dir)82 if parent == dir || parent == '' {83 return false84 }85 dir = parent86 }87 return false88}