cmd_status.v

2.7 KB · raw

1//! `koh status` — what the working tree has that head does not.23module cli45import json6import src.fmt7import src.history8import src.snapshot9import src.storage1011pub fn cmd_status(raw []string) int {12	args := parse('status', raw, Options{13		flags: ['json']14	}) or { return usage_error(err.msg()) }15	store := open_store() or { return refuse(args.json(), err.msg()) }16	defer {17		store.close()18	}19	head := history.head(store) or {20		return refuse(args.json(), 'this repo has no saves yet — run "koh save \\"first save\\""')21	}22	changes := compare_with_head(store, head) or { return refuse(args.json(), err.msg()) }2324	if args.json() {25		emit_json(json.encode(StatusJson{26			head_id:        head.id27			head_msg:       head.message28			dirty:          changes.dirty29			modified:       changes.modified30			added:          changes.added31			deleted:        changes.removed32			ignore_changed: changes.ignore_changed33		}))34		return 035	}36	if !changes.dirty {37		ok('no changes')38		if changes.ignore_changed {39			note('${snapshot.ignore_file} changed since [${head.id}]')40		}41		return 042	}43	for path in changes.added {44		println('  ${fmt.green('+')} ${path}')45	}46	for path in changes.modified {47		println('  ${fmt.amber('~')} ${path}')48	}49	for path in changes.removed {50		println('  ${fmt.red('-')} ${path}')51	}52	note('${changes.added.len} added  ·  ${changes.modified.len} modified  ·  ${changes.removed.len} removed')53	if changes.ignore_changed {54		warn('${snapshot.ignore_file} changed since [${head.id}] — the next save records the new rules')55	}56	return 057}5859pub struct Changes {60pub:61	dirty          bool62	added          []string63	modified       []string64	removed        []string65	ignore_changed bool66}6768struct StatusJson {69	head_id        string70	head_msg       string71	dirty          bool72	modified       []string73	added          []string74	deleted        []string75	ignore_changed bool76}7778pub fn compare_with_head(store &storage.Store, head history.Save) !Changes {79	before := snapshot.index_files(history.files_of(store, head.id)!)80	after := snapshot.index_files(snapshot.walk(store, store.root, snapshot.load(store.root))!)81	mut added := []string{}82	mut modified := []string{}83	mut removed := []string{}84	for path in after.keys() {85		if path !in before {86			added << path87		} else if before[path].hash != after[path].hash88			|| before[path].executable != after[path].executable {89			modified << path90		}91	}92	for path in before.keys() {93		if path !in after {94			removed << path95		}96	}97	added.sort()98	modified.sort()99	removed.sort()100	ignore_changed := snapshot.ignore_file in added || snapshot.ignore_file in modified101	return Changes{102		dirty:          added.len + modified.len + removed.len > 0103		added:          added104		modified:       modified105		removed:        removed106		ignore_changed: ignore_changed107	}108}