module cli import os import src.history import src.snapshot import src.storage // The history view's `l` key goes through restore_now, which a CLI test cannot // reach without a terminal, so it is checked here directly. fn test_restore_now_refuses_to_overwrite_unsaved_work() { dir := os.join_path(os.temp_dir(), 'koh3_cli_restore_now_${os.getpid()}') os.rmdir_all(dir) or {} os.mkdir_all(dir)! defer { os.rmdir_all(dir) or {} } store := storage.create(dir)! defer { store.close() } path := os.join_path(dir, 'a.txt') os.write_file(path, 'one\n')! first := history.save_worktree(store, dir, snapshot.load(dir), history.SaveInput{ message: 'one' })! os.write_file(path, 'two\n')! history.save_worktree(store, dir, snapshot.load(dir), history.SaveInput{ message: 'two' })! os.write_file(path, 'unsaved\n')! if _ := restore_now(store, first, 'load') { assert false, 'restore_now overwrote unsaved work' } else { assert err.msg() == unsaved_changes } assert os.read_file(path)! == 'unsaved\n' } fn test_a_peek_is_old_only_after_more_than_a_day() { now := i64(1_000_000) assert !peek_is_old(now, now) assert !peek_is_old(now - peek_age, now) assert peek_is_old(now - peek_age - 1, now) } // The restore's save is recorded before its files are written. A kill between // the two must still leave the mark, so the mark goes down first. fn test_a_restore_is_marked_before_its_save_is_recorded() { dir := os.join_path(os.temp_dir(), 'koh3_cli_mark_first_${os.getpid()}') os.rmdir_all(dir) or {} os.mkdir_all(dir)! defer { os.rmdir_all(dir) or {} } store := storage.create(dir)! defer { store.close() } os.write_file(os.join_path(dir, 'a.txt'), 'one\n')! first := history.save_worktree(store, dir, snapshot.load(dir), history.SaveInput{ message: 'one' })! os.write_file(os.join_path(dir, 'a.txt'), 'two\n')! history.save_worktree(store, dir, snapshot.load(dir), history.SaveInput{ message: 'two' })! // Any save recorded while the mark is missing aborts the restore. store.db.exec("CREATE TEMP TRIGGER mark_first BEFORE INSERT ON saves WHEN NOT EXISTS (SELECT 1 FROM state WHERE key = 'restoring') BEGIN SELECT RAISE(ABORT, 'save recorded before the mark'); END")! apply_restore(store, first, 'load', plan_restore(store, first)!, false)! assert snapshot.restore_pending(store) } // A revert finishing an earlier restore must not lift that restore's mark when // it fails to record anything itself. fn test_a_failed_restore_keeps_an_earlier_mark() { dir := os.join_path(os.temp_dir(), 'koh3_cli_keep_mark_${os.getpid()}') os.rmdir_all(dir) or {} os.mkdir_all(dir)! defer { os.rmdir_all(dir) or {} } store := storage.create(dir)! defer { store.close() } os.write_file(os.join_path(dir, 'a.txt'), 'one\n')! first := history.save_worktree(store, dir, snapshot.load(dir), history.SaveInput{ message: 'one' })! snapshot.mark_restore(store)! // An object the store does not have makes recording the save fail. broken := RestorePlan{ files: [snapshot.FileEntry{ path: 'a.txt' hash: 'not-an-object' }] } if _ := apply_restore(store, first, 'revert', broken, false) { assert false, 'recording a save with a missing object should fail' } assert snapshot.restore_pending(store) }