cmd_status.v

2.7 KB · raw

1//! `koh status` — what the working tree has that head does not.23module cli45import json6import src.history7import src.snapshot8import src.storage910pub fn cmd_status(raw []string) int {11	args := parse('status', raw, Options{12		flags: ['json']13	}) or { return usage_error(err.msg()) }14	store := open_store() or { return refuse(args.json(), err.msg()) }15	defer {16		store.close()17	}18	head := history.head(store) or {19		return refuse(args.json(), 'this repo has no saves yet — run "koh save \\"first save\\""')20	}21	changes := compare_with_head(store, head) or { return refuse(args.json(), err.msg()) }2223	if args.json() {24		emit_json(json.encode(StatusJson{25			head_id:        head.id26			head_msg:       head.message27			dirty:          changes.dirty28			modified:       changes.modified29			added:          changes.added30			deleted:        changes.removed31			ignore_changed: changes.ignore_changed32		}))33		return 034	}35	if !changes.dirty {36		ok('no changes')37		if changes.ignore_changed {38			note('${snapshot.ignore_file} changed since [${head.id}]')39		}40		return 041	}42	for path in changes.added {43		println('  ${green('+')} ${path}')44	}45	for path in changes.modified {46		println('  ${amber('~')} ${path}')47	}48	for path in changes.removed {49		println('  ${red('-')} ${path}')50	}51	note('${changes.added.len} added  ·  ${changes.modified.len} modified  ·  ${changes.removed.len} removed')52	if changes.ignore_changed {53		warn('${snapshot.ignore_file} changed since [${head.id}] — the next save records the new rules')54	}55	return 056}5758pub struct Changes {59pub:60	dirty          bool61	added          []string62	modified       []string63	removed        []string64	ignore_changed bool65}6667struct StatusJson {68	head_id        string69	head_msg       string70	dirty          bool71	modified       []string72	added          []string73	deleted        []string74	ignore_changed bool75}7677pub fn compare_with_head(store &storage.Store, head history.Save) !Changes {78	before := snapshot.index_files(history.files_of(store, head.id)!)79	after := snapshot.index_files(snapshot.walk(store, store.root, snapshot.load(store.root))!)80	mut added := []string{}81	mut modified := []string{}82	mut removed := []string{}83	for path in after.keys() {84		if path !in before {85			added << path86		} else if before[path].hash != after[path].hash {87			modified << path88		}89	}90	for path in before.keys() {91		if path !in after {92			removed << path93		}94	}95	added.sort()96	modified.sort()97	removed.sort()98	ignore_changed := snapshot.ignore_file in added || snapshot.ignore_file in modified99	return Changes{100		dirty:          added.len + modified.len + removed.len > 0101		added:          added102		modified:       modified103		removed:        removed104		ignore_changed: ignore_changed105	}106}