history_test.v

3.5 KB · raw

1module history23import os4import src.snapshot5import src.storage67fn temp_repo(name string) !(storage.Store, string) {8	dir := os.join_path(os.temp_dir(), 'koh3_hist_${os.getpid()}_${name}')9	os.rmdir_all(dir) or {}10	os.mkdir_all(dir, os.MkdirParams{})!11	store := storage.create(dir)!12	return store, dir13}1415fn write_file(root string, rel string, text string) ! {16	full := os.join_path(root, rel)17	os.mkdir_all(os.dir(full), os.MkdirParams{})!18	os.write_file(full, text)!19}2021fn test_walk_then_commit() {22	mut store, dir := temp_repo('commit')!23	defer {24		store.close()25		os.rmdir_all(dir) or {}26	}27	write_file(dir, 'a.txt', 'hello\n')!28	write_file(dir, 'sub/b.txt', 'world\n')!29	entries := snapshot.walk(store, dir, snapshot.Ignore{})!30	assert entries.len == 23132	save := commit_worktree(store, dir, snapshot.Ignore{}, SaveInput{33		message: 'first save'34	})!35	assert save.id.len == 1236	assert save.parent == ''37	assert head_id(store) == save.id3839	files := files_of(store, save.id)!40	assert files.len == 241	assert files[0].path == 'a.txt'42	assert files[1].path == 'sub/b.txt'4344	// Nothing changed, so a plain save refuses and a checkpoint records.45	if _ := commit_worktree(store, dir, snapshot.Ignore{}, SaveInput{ message: 'again' }) {46		assert false, 'a save with no changes should refuse'47	} else {48		assert err.msg() == nothing_changed49	}50	second := commit_worktree(store, dir, snapshot.Ignore{}, SaveInput{51		message:       'checked anyway'52		is_checkpoint: true53	})!54	assert second.parent == save.id55	assert second.is_checkpoint56}5758fn test_going_back_is_recorded_not_rewound() {59	mut store, dir := temp_repo('back')!60	defer {61		store.close()62		os.rmdir_all(dir) or {}63	}64	write_file(dir, 'a.txt', 'one\n')!65	first := commit_worktree(store, dir, snapshot.Ignore{}, SaveInput{ message: 'one' })!66	write_file(dir, 'a.txt', 'two\n')!67	second := commit_worktree(store, dir, snapshot.Ignore{}, SaveInput{ message: 'two' })!6869	// effective position follows restores, so undo keeps stepping back.70	assert effective(store)!.id == second.id71	first_files := files_of(store, first.id)!72	restore := commit_files(store, '', first_files, SaveInput{73		message:  'undo: ${first.id}'74		restores: first.id75	})!76	assert restore.parent == second.id77	assert restore.restores == first.id78	assert effective(store)!.id == first.id79	// Walking back from the first save has nowhere to go; undo says so rather80	// than looping.81	if _ := step_back(store, effective(store)!.id, 1) {82		assert false, 'there is nothing before the first save'83	} else {84		assert err.msg().contains('nothing before')85	}8687	// The tree at head is the restored one.88	assert same_files(store, head_id(store), first_files)!89}9091fn same_files(store &storage.Store, id string, expected []snapshot.FileEntry) !bool {92	actual := files_of(store, id)!93	if actual.len != expected.len {94		return false95	}96	for i in 0 .. actual.len {97		if actual[i].path != expected[i].path || actual[i].hash != expected[i].hash {98			return false99		}100	}101	return true102}103104fn test_resolve_accepts_a_unique_prefix() {105	mut store, dir := temp_repo('resolve')!106	defer {107		store.close()108		os.rmdir_all(dir) or {}109	}110	write_file(dir, 'a.txt', 'one\n')!111	first := commit_worktree(store, dir, snapshot.Ignore{}, SaveInput{ message: 'one' })!112	assert resolve(store, first.id[..6])!.id == first.id113	if _ := resolve(store, 'abc') {114		assert false, 'a prefix shorter than six characters should be refused'115	} else {116		assert err.msg().contains('at least 6')117	}118	if _ := resolve(store, 'zzzzzz') {119		assert false, 'an unknown prefix should be refused'120	} else {121		assert err.msg().contains('no save starts with')122	}123}