handover.v

2.4 KB · raw

1//! The cut-over hand-off.2//!3//! While repos with an unmigrated Koh 2 `.koh/` directory still exist on this4//! machine, `koh` is Koh 3 but those repos belong to Koh 2. Rather than let a5//! command fail confusingly, Koh 3 hands it to `koh2` unchanged — same6//! arguments, same terminal. Agents always type `koh`, and every repo gets the7//! Koh that owns it.8//!9//! `migrate` is the exception: it is how such a repo stops being a Koh 2 repo.1011module cli1213import os14import src.fmt1516// hand_over reports whether this invocation belongs to Koh 2, and if so runs17// it. It never returns when the hand-off happens.18pub fn hand_over(argv []string) {19	if argv.len < 2 {20		return21	}22	command := argv[1]23	if command in ['migrate', 'man', 'help', '--help', '-h', '--version', '-v'] {24		return25	}26	if !inside_koh2_repo(os.getwd()) {27		return28	}29	target := koh2_binary()30	if target == '' {31		eprintln('  ${fmt.red(fmt.glyph_fail)} this folder holds a Koh 2 repo, and koh2 is not on PATH')32		eprintln('  install koh2, or run "koh migrate" to convert this repo')33		exit(1)34	}35	// The one notice line the document asks for, on stderr so the output koh236	// prints (JSON included) reaches the caller unchanged.37	eprintln('  ${fmt.dim('this is a Koh 2 repo — handing the command to ${os.file_name(target)}')}')38	// execvp builds argv as [path, ...cmdargs], so the arguments go without39	// our own argv[0].40	os.execvp(target, argv[1..]) or {41		eprintln('  ${fmt.red(fmt.glyph_fail)} could not hand this command to ${target}: ${err.msg()}')42		exit(1)43	}44}4546// koh2_binary finds the Koh 2 binary. Before the cutover it is still called47// `koh`, so that name is a fallback — never this binary itself, which would48// hand the command straight back to us for ever.49fn koh2_binary() string {50	if found := os.find_abs_path_of_executable('koh2') {51		return found52	}53	if legacy := os.find_abs_path_of_executable('koh') {54		if os.real_path(legacy) != os.real_path(os.executable()) {55			return legacy56		}57	}58	return ''59}6061// inside_koh2_repo looks upward for a `.koh` that is a directory. A `.koh`62// file is Koh 3's.63fn inside_koh2_repo(start string) bool {64	mut dir := os.real_path(start)65	for {66		path := os.join_path(dir, '.koh')67		if os.is_dir(path) {68			return true69		}70		if os.is_file(path) {71			return false72		}73		parent := os.dir(dir)74		if parent == dir || parent == '' {75			return false76		}77		dir = parent78	}79	return false80}