//! The cut-over hand-off. //! //! While repos with an unmigrated Koh 2 `.koh/` directory still exist on this //! machine, `koh` is Koh 3 but those repos belong to Koh 2. Rather than let a //! command fail confusingly, Koh 3 hands it to `koh2` unchanged — same //! arguments, same terminal. Agents always type `koh`, and every repo gets the //! Koh that owns it. //! //! `migrate` is the exception: it is how such a repo stops being a Koh 2 repo. module cli import os import src.fmt // hand_over reports whether this invocation belongs to Koh 2, and if so runs // it. It never returns when the hand-off happens. pub fn hand_over(argv []string) { if argv.len < 2 { return } command := argv[1] if command in ['migrate', 'man', 'help', '--help', '-h', '--version', '-v'] { return } if !inside_koh2_repo(os.getwd()) { return } target := koh2_binary() if target == '' { eprintln(' ${fmt.red(fmt.glyph_fail)} this folder holds a Koh 2 repo, and koh2 is not on PATH') eprintln(' install koh2, or run "koh migrate" to convert this repo') exit(1) } // execvp builds argv as [path, ...cmdargs], so the arguments go without // our own argv[0]. os.execvp(target, argv[1..]) or { eprintln(' ${fmt.red(fmt.glyph_fail)} could not hand this command to ${target}: ${err.msg()}') exit(1) } } // koh2_binary finds the Koh 2 binary. Before the cutover it is still called // `koh`, so that name is a fallback — never this binary itself, which would // hand the command straight back to us for ever. fn koh2_binary() string { if found := os.find_abs_path_of_executable('koh2') { return found } if legacy := os.find_abs_path_of_executable('koh') { if os.real_path(legacy) != os.real_path(os.executable()) { return legacy } } return '' } // inside_koh2_repo looks upward for a `.koh` that is a directory. A `.koh` // file is Koh 3's. fn inside_koh2_repo(start string) bool { mut dir := os.real_path(start) for { path := os.join_path(dir, '.koh') if os.is_dir(path) { return true } if os.is_file(path) { return false } parent := os.dir(dir) if parent == dir || parent == '' { return false } dir = parent } return false }