123module 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}