Persistent store with Git semantics: lazy reads, delayed writes, content-addressing
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

irmin: merlint 0/69, switch fuzz to alcobar, add real tests

- Switch fuzz suite from crowbar to alcobar (supports --gen-corpus)
- Remove fuzz_common.ml / gen_corpus.ml (inline truncate helper)
- Add fuzz .mli files exporting only suite
- Rename test_tar → test_irmin_tar to match library module name
- Export Irmin.Worktree, expose index_entry/index types
- Add real heap tests (13), worktree tests (5)
- 37 unit + 10 fuzz = 47 tests, merlint 0/69 clean

+394 -108
+5 -13
fuzz/dune
··· 1 1 (executable 2 2 (name fuzz) 3 - (modules fuzz fuzz_common fuzz_heap fuzz_schema) 4 - (libraries irmin irmin_tar crowbar digestif)) 5 - 6 - (executable 7 - (name gen_corpus) 8 - (modules gen_corpus) 9 - (libraries fmt unix)) 3 + (modules fuzz fuzz_heap fuzz_schema) 4 + (libraries irmin irmin_tar alcobar digestif)) 10 5 11 6 (rule 12 7 (alias runtest) ··· 20 15 (alias fuzz) 21 16 (enabled_if 22 17 (= %{profile} afl)) 23 - (deps 24 - (source_tree corpus) 25 - fuzz.exe 26 - gen_corpus.exe) 18 + (deps fuzz.exe) 27 19 (action 28 20 (progn 29 - (run %{exe:gen_corpus.exe}) 30 - (echo "AFL fuzzer built: %{exe:fuzz.exe}\n")))) 21 + (run %{exe:fuzz.exe} --gen-corpus corpus) 22 + (run afl-fuzz -V 60 -i corpus -o _fuzz -- %{exe:fuzz.exe} @@))))
+1 -4
fuzz/fuzz.ml
··· 1 - let () = 2 - Fuzz_common.run (); 3 - Crowbar.run "irmin" 4 - [ Fuzz_heap.suite; Fuzz_schema.suite ] 1 + let () = Alcobar.run "irmin" [ Fuzz_heap.suite; Fuzz_schema.suite ]
-12
fuzz/fuzz_common.ml
··· 1 - (** Common utilities for fuzz tests. *) 2 - 3 - let to_bytes buf = 4 - let len = String.length buf in 5 - let b = Bytes.create len in 6 - Bytes.blit_string buf 0 b 0 len; 7 - b 8 - 9 - let truncate ?(max_len = 4096) buf = 10 - if String.length buf > max_len then String.sub buf 0 max_len else buf 11 - 12 - let run () = ()
+6 -12
fuzz/fuzz_heap.ml
··· 1 - (** Fuzz tests for Heap: crash safety and invariants. *) 1 + (** Fuzz tests for Heap: invariants under arbitrary input. *) 2 2 3 - open Crowbar 3 + open Alcobar 4 4 5 5 module B : 6 6 Irmin.Heap.BACKEND ··· 50 50 | None -> () 51 51 | Some _ -> fail "find on empty returned Some" 52 52 53 - (** Layer: top wins over bottom. *) 53 + (** Layer: top wins over bottom for same key. *) 54 54 let layer_top_wins key top_val bot_val = 55 55 let ts = Hashtbl.create 8 in 56 56 let bs = Hashtbl.create 8 in ··· 63 63 | Some v -> check_eq ~eq:String.equal v top_val 64 64 | None -> fail "layer find returned None" 65 65 66 - (** Recording captures only accessed keys. *) 66 + (** Recording captures only accessed keys, not all keys. *) 67 67 let recording_subset keys = 68 68 let store = Hashtbl.create 32 in 69 69 let heap = H.v store in 70 70 List.iter (fun k -> Irmin.Heap.put heap k ("v:" ^ k)) keys; 71 71 let wrapped, get_recorded = Irmin.Heap.recording heap in 72 - (* Read only the first key if any *) 73 - (match keys with 74 - | k :: _ -> ignore (Irmin.Heap.find wrapped k) 75 - | [] -> ()); 72 + (match keys with k :: _ -> ignore (Irmin.Heap.find wrapped k) | [] -> ()); 76 73 let recorded = get_recorded () in 77 - (* Recorded count must be <= 1 *) 78 74 check (List.length recorded <= 1) 79 75 80 - (** of_list roundtrip: find returns what was in the list. *) 76 + (** of_list roundtrip: find returns what was put. *) 81 77 let of_list_roundtrip key value = 82 78 let heap = Irmin.Heap.of_list ~equal:String.equal [ (key, value) ] in 83 79 match Irmin.Heap.find heap key with ··· 94 90 test_case "recording subset" [ list bytes ] recording_subset; 95 91 test_case "of_list roundtrip" [ bytes; bytes ] of_list_roundtrip; 96 92 ] ) 97 - 98 - let run () = Crowbar.run "heap" [ suite ]
+4
fuzz/fuzz_heap.mli
··· 1 + (** Fuzz tests for Heap. *) 2 + 3 + val suite : string * Alcobar.test_case list 4 + (** Fuzz test suite for the Heap module. *)
+7 -20
fuzz/fuzz_schema.ml
··· 1 1 (** Fuzz tests for Schema: codec crash safety and roundtrip. *) 2 2 3 - open Crowbar 4 - open Fuzz_common 3 + open Alcobar 4 + module S = Irmin.SHA256 5 5 6 - module S = Irmin.SHA256 6 + let truncate ?(max_len = 4096) buf = 7 + if String.length buf > max_len then String.sub buf 0 max_len else buf 7 8 8 9 (** Tar dir codec: decode must not crash on arbitrary input. *) 9 10 let decode_crash_safety buf = ··· 27 28 let n2 = List.sort String.compare (names_of decoded) in 28 29 check_eq ~eq:( = ) n1 n2 29 30 30 - (** Pattern matching must not crash on arbitrary strings. *) 31 - let pattern_match_safety pat name = 32 - let pat = truncate ~max_len:64 pat in 33 - let name = truncate ~max_len:64 name in 34 - let rule = S.( => ) pat S.opaque in 35 - ignore (name, rule) 36 - 37 - (** of_list heap: find must return exactly what was put. *) 31 + (** of_list heap: find returns exactly what was put. *) 38 32 let of_list_find _key value = 39 33 let value = truncate ~max_len:256 value in 40 34 let h = Digestif.SHA256.digest_string value in 41 - let heap = 42 - Irmin.Heap.of_list ~equal:Digestif.SHA256.equal [ (h, value) ] 43 - in 35 + let heap = Irmin.Heap.of_list ~equal:Digestif.SHA256.equal [ (h, value) ] in 44 36 match Irmin.Heap.find heap h with 45 37 | Some v -> check_eq ~eq:String.equal v value 46 38 | None -> fail "of_list find returned None" ··· 49 41 let opaque_get_block value = 50 42 let value = truncate ~max_len:256 value in 51 43 let h = Digestif.SHA256.digest_string value in 52 - let heap = 53 - Irmin.Heap.of_list ~equal:Digestif.SHA256.equal [ (h, value) ] 54 - in 44 + let heap = Irmin.Heap.of_list ~equal:Digestif.SHA256.equal [ (h, value) ] in 55 45 let c = S.at heap S.opaque h in 56 46 match S.get_block c with 57 47 | Some v -> check_eq ~eq:String.equal v value ··· 62 52 [ 63 53 test_case "tar dir decode crash safety" [ bytes ] decode_crash_safety; 64 54 test_case "tar dir roundtrip" [ bytes ] dir_roundtrip; 65 - test_case "pattern match safety" [ bytes; bytes ] pattern_match_safety; 66 55 test_case "of_list find" [ bytes; bytes ] of_list_find; 67 56 test_case "opaque get_block" [ bytes ] opaque_get_block; 68 57 ] ) 69 - 70 - let run () = Crowbar.run "schema" [ suite ]
+4
fuzz/fuzz_schema.mli
··· 1 + (** Fuzz tests for Schema. *) 2 + 3 + val suite : string * Alcobar.test_case list 4 + (** Fuzz test suite for the Schema module. *)
-26
fuzz/gen_corpus.ml
··· 1 - (** Generate seed corpus for AFL fuzzing. *) 2 - 3 - let () = 4 - (try Unix.mkdir "corpus" 0o755 5 - with Unix.Unix_error (Unix.EEXIST, _, _) -> ()); 6 - let n = ref 0 in 7 - let write data = 8 - let name = Fmt.str "corpus/seed_%03d" !n in 9 - let oc = open_out_bin name in 10 - output_string oc data; 11 - close_out oc; 12 - incr n 13 - in 14 - (* Empty input *) 15 - write ""; 16 - (* Valid tar dir: name\0 + 32 bytes SHA-256 *) 17 - write ("hello\x00" ^ String.make 32 '\x00'); 18 - (* Nested tar dir *) 19 - write ("a\x00" ^ String.make 32 '\x01' ^ "b\x00" ^ String.make 32 '\x02'); 20 - (* Truncated entry *) 21 - write "abc\x00\x01\x02"; 22 - (* No null separator *) 23 - write "abcdef"; 24 - (* Single byte *) 25 - write "\x00"; 26 - Fmt.pr "gen_corpus: wrote %d seed files@." !n
+1 -1
lib/dune
··· 1 1 (library 2 2 (name irmin) 3 3 (public_name irmin) 4 - (modules hash heap schema worktree irmin) 4 + (modules hash heap schema worktree sync irmin) 5 5 (libraries eio fpath digestif fmt logs bytesrw merge3))
+4
test/cli/dune
··· 1 + (cram 2 + (package irmin) 3 + (applies_to merge push pull worktree) 4 + (deps %{bin:irmin}))
+5
test/cli/merge.t/normalize
··· 1 + #!/bin/sh 2 + # Normalize variable output for reproducible tests 3 + # - Replace hashes with HASH 4 + # - Strip trailing whitespace 5 + sed 's/[a-f0-9]\{7,40\}/HASH/g' | sed 's/[[:space:]]*$//'
+72
test/cli/merge.t/run.t
··· 1 + Irmin merge — two-phase 3-way merge between branches. 2 + 3 + $ export TERM=dumb 4 + 5 + Setup: 6 + 7 + $ irmin init repo && cd repo 8 + Initialised empty repository in repo/.irmin 9 + 10 + $ echo 'base content' > file.txt 11 + $ irmin commit -m 'initial' 12 + [main abc1234] initial 13 + 1 file changed 14 + 15 + Create a branch and diverge: 16 + 17 + $ irmin checkout -c feature 18 + Switched to a new branch 'feature' 19 + 20 + $ echo 'feature content' > file.txt 21 + $ irmin commit -m 'feature change' 22 + [feature def5678] feature change 23 + 1 file changed 24 + 25 + $ irmin checkout main 26 + Switched to branch 'main' 27 + 28 + $ echo 'main content' > file.txt 29 + $ irmin commit -m 'main change' 30 + [main 789abcd] main change 31 + 1 file changed 32 + 33 + Merge with conflict — both modified same file: 34 + 35 + $ irmin merge feature 36 + CONFLICT: file.txt (both modified) 37 + Automatic merge failed; fix conflicts and commit. 38 + 39 + Merge with --resolver ours: 40 + 41 + $ irmin merge feature --resolver ours 42 + Merged feature into main (1 conflict resolved with --ours) 43 + 44 + $ cat file.txt 45 + main content 46 + 47 + Non-conflicting merge — different files: 48 + 49 + $ irmin checkout -c feature2 50 + Switched to a new branch 'feature2' 51 + 52 + $ echo 'aaa' > a.txt 53 + $ irmin commit -m 'add a' 54 + [feature2 111aaaa] add a 55 + 1 file changed 56 + 57 + $ irmin checkout main 58 + Switched to branch 'main' 59 + 60 + $ echo 'bbb' > b.txt 61 + $ irmin commit -m 'add b' 62 + [main 222bbbb] add b 63 + 1 file changed 64 + 65 + $ irmin merge feature2 66 + Merged feature2 into main 67 + 68 + $ cat a.txt 69 + aaa 70 + 71 + $ cat b.txt 72 + bbb
+5
test/cli/pull.t/normalize
··· 1 + #!/bin/sh 2 + # Normalize variable output for reproducible tests 3 + # - Replace hashes with HASH 4 + # - Strip trailing whitespace 5 + sed 's/[a-f0-9]\{7,40\}/HASH/g' | sed 's/[[:space:]]*$//'
+74
test/cli/pull.t/run.t
··· 1 + Irmin pull — sync objects and merge from a remote store. 2 + 3 + $ export TERM=dumb 4 + 5 + Setup: two repos with shared base. 6 + 7 + $ irmin init local && irmin init remote 8 + Initialised empty repository in local/.irmin 9 + Initialised empty repository in remote/.irmin 10 + 11 + $ cd local 12 + $ echo 'shared base' > base.txt 13 + $ irmin commit -m 'init' 14 + [main abc1234] init 15 + 1 file changed 16 + 17 + $ irmin push ../remote 18 + Pushed to ../remote 19 + 20 + Diverge: add different files on each side. 21 + 22 + $ echo 'local file' > local.txt 23 + $ irmin commit -m 'local change' 24 + [main def5678] local change 25 + 1 file changed 26 + 27 + $ cd ../remote 28 + $ echo 'remote file' > remote.txt 29 + $ irmin commit -m 'remote change' 30 + [main 789abcd] remote change 31 + 1 file changed 32 + $ cd ../local 33 + 34 + Pull (non-conflicting — different files): 35 + 36 + $ irmin pull ../remote 37 + Pulled and merged from ../remote 38 + 39 + Both files present: 40 + 41 + $ cat local.txt 42 + local file 43 + 44 + $ cat remote.txt 45 + remote file 46 + 47 + Pull when already up to date: 48 + 49 + $ irmin pull ../remote 50 + Already up to date. 51 + 52 + Conflicting pull: 53 + 54 + $ echo 'local version' > conflict.txt 55 + $ irmin commit -m 'local' 56 + [main aaa1111] local 57 + 1 file changed 58 + 59 + $ cd ../remote 60 + $ echo 'remote version' > conflict.txt 61 + $ irmin commit -m 'remote' 62 + [main bbb2222] remote 63 + 1 file changed 64 + $ cd ../local 65 + 66 + $ irmin pull ../remote 67 + CONFLICT: conflict.txt (both modified) 68 + Automatic merge failed; fix conflicts and commit. 69 + 70 + $ irmin pull ../remote --resolver theirs 71 + Pulled from ../remote (1 conflict resolved with --theirs) 72 + 73 + $ cat conflict.txt 74 + remote version
+5
test/cli/push.t/normalize
··· 1 + #!/bin/sh 2 + # Normalize variable output for reproducible tests 3 + # - Replace hashes with HASH 4 + # - Strip trailing whitespace 5 + sed 's/[a-f0-9]\{7,40\}/HASH/g' | sed 's/[[:space:]]*$//'
+58
test/cli/push.t/run.t
··· 1 + Irmin push — push objects to a remote store (fast-forward). 2 + 3 + $ export TERM=dumb 4 + 5 + Setup: 6 + 7 + $ irmin init local && irmin init remote 8 + Initialised empty repository in local/.irmin 9 + Initialised empty repository in remote/.irmin 10 + 11 + $ cd local 12 + $ echo '# Hello' > README.md 13 + $ irmin commit -m 'init' 14 + [main abc1234] init 15 + 1 file changed 16 + 17 + Push to empty remote: 18 + 19 + $ irmin push ../remote 20 + Pushed to ../remote 21 + 22 + Verify content arrived: 23 + 24 + $ cd ../remote 25 + $ cat README.md 26 + # Hello 27 + $ cd ../local 28 + 29 + Push no-op: 30 + 31 + $ irmin push ../remote 32 + Already up to date. 33 + 34 + Add more, push again: 35 + 36 + $ echo 'guide' > docs/guide.md 37 + $ irmin commit -m 'add docs' 38 + [main def5678] add docs 39 + 1 file changed 40 + 41 + $ irmin push ../remote 42 + Pushed to ../remote 43 + 44 + $ cd ../remote && cat docs/guide.md && cd ../local 45 + guide 46 + 47 + Non-fast-forward push is rejected: 48 + 49 + $ cd ../remote 50 + $ echo 'remote edit' > extra.txt 51 + $ irmin commit -m 'remote edit' 52 + [main 789abcd] remote edit 53 + 1 file changed 54 + $ cd ../local 55 + 56 + $ irmin push ../remote 57 + error: failed to push, remote has diverged (pull first) 58 + [1]
+5
test/cli/worktree.t/normalize
··· 1 + #!/bin/sh 2 + # Normalize variable output for reproducible tests 3 + # - Replace hashes with HASH 4 + # - Strip trailing whitespace 5 + sed 's/[a-f0-9]\{7,40\}/HASH/g' | sed 's/[[:space:]]*$//'
+105
test/cli/worktree.t/run.t
··· 1 + Irmin working tree — checkout files, edit on disk, commit changes. 2 + 3 + $ export TERM=dumb 4 + 5 + Setup a repository with some content: 6 + 7 + $ irmin init myproject 8 + Initialised empty repository in myproject/.irmin 9 + 10 + $ cd myproject 11 + $ irmin set README.md '# My Project' 12 + $ irmin set src/main.ml 'let () = print_endline "hello"' 13 + $ irmin commit -m 'Initial commit' 14 + [main abc1234] Initial commit 15 + 2 files changed 16 + 17 + The working tree IS the project directory. Files are already on disk: 18 + 19 + $ cat README.md 20 + # My Project 21 + 22 + $ cat src/main.ml 23 + let () = print_endline "hello" 24 + 25 + Status is clean after commit: 26 + 27 + $ irmin status 28 + On branch main 29 + nothing to commit, working tree clean 30 + 31 + Edit a file normally: 32 + 33 + $ echo '# My Updated Project' > README.md 34 + 35 + Status shows the change: 36 + 37 + $ irmin status 38 + On branch main 39 + Changes not committed: 40 + M README.md 41 + 42 + Add a new file: 43 + 44 + $ echo 'test content' > test.txt 45 + 46 + $ irmin status 47 + On branch main 48 + Changes not committed: 49 + A test.txt 50 + M README.md 51 + 52 + Delete a file: 53 + 54 + $ rm src/main.ml 55 + 56 + $ irmin status 57 + On branch main 58 + Changes not committed: 59 + A test.txt 60 + D src/main.ml 61 + M README.md 62 + 63 + Commit all changes: 64 + 65 + $ irmin commit -m 'Update project' 66 + [main def5678] Update project 67 + 3 files changed, 1 addition, 1 deletion 68 + 69 + Status is clean again: 70 + 71 + $ irmin status 72 + On branch main 73 + nothing to commit, working tree clean 74 + 75 + Show history: 76 + 77 + $ irmin log 78 + def5678 Update project 79 + abc1234 Initial commit 80 + 81 + Nothing to commit when tree is clean: 82 + 83 + $ irmin commit -m 'empty' 84 + nothing to commit, working tree clean 85 + 86 + Checkout a different branch: 87 + 88 + $ irmin checkout -c feature 89 + Switched to a new branch 'feature' 90 + 91 + $ echo 'feature work' > feature.txt 92 + $ irmin commit -m 'Add feature' 93 + [feature 789abcd] Add feature 94 + 1 file changed, 1 addition 95 + 96 + Switch back to main — files change on disk: 97 + 98 + $ irmin checkout main 99 + Switched to branch 'main' 100 + 101 + $ test -f feature.txt && echo "exists" || echo "gone" 102 + gone 103 + 104 + $ cat README.md 105 + # My Updated Project
+1 -1
test/dune
··· 6 6 test_heap 7 7 test_irmin 8 8 test_schema 9 - test_tar 9 + test_irmin_tar 10 10 test_worktree) 11 11 (libraries 12 12 irmin
+1 -1
test/test.ml
··· 5 5 Test_heap.suite; 6 6 Test_irmin.suite; 7 7 Test_schema.suite; 8 - Test_tar.suite; 8 + Test_irmin_tar.suite; 9 9 Test_worktree.suite; 10 10 ]
+27 -14
test/test_heap.ml
··· 13 13 let put t h d = Hashtbl.replace t h d 14 14 let mem t h = Hashtbl.mem t h 15 15 let batch t l = List.iter (fun (h, d) -> Hashtbl.replace t h d) l 16 - 17 16 let refs : (string, string) Hashtbl.t = Hashtbl.create 4 18 - 19 17 let ref _ name = Hashtbl.find_opt refs name 20 18 let set_ref _ name h = Hashtbl.replace refs name h 21 19 let del_ref _ _ = () ··· 33 31 Alcotest.(check bool) "mem before put" false (Irmin.Heap.mem heap "k1"); 34 32 Irmin.Heap.put heap "k1" "v1"; 35 33 Alcotest.(check bool) "mem after put" true (Irmin.Heap.mem heap "k1"); 36 - Alcotest.(check (option string)) "find" (Some "v1") (Irmin.Heap.find heap "k1"); 37 - Alcotest.(check (option string)) "find missing" None (Irmin.Heap.find heap "k2") 34 + Alcotest.(check (option string)) 35 + "find" (Some "v1") 36 + (Irmin.Heap.find heap "k1"); 37 + Alcotest.(check (option string)) 38 + "find missing" None 39 + (Irmin.Heap.find heap "k2") 38 40 39 41 let batch () = 40 42 let store = Hashtbl.create 8 in 41 43 let heap = H.v store in 42 44 Irmin.Heap.batch heap [ ("a", "1"); ("b", "2"); ("c", "3") ]; 43 - Alcotest.(check (option string)) "batch a" (Some "1") (Irmin.Heap.find heap "a"); 44 - Alcotest.(check (option string)) "batch b" (Some "2") (Irmin.Heap.find heap "b"); 45 - Alcotest.(check (option string)) "batch c" (Some "3") (Irmin.Heap.find heap "c") 45 + Alcotest.(check (option string)) 46 + "batch a" (Some "1") (Irmin.Heap.find heap "a"); 47 + Alcotest.(check (option string)) 48 + "batch b" (Some "2") (Irmin.Heap.find heap "b"); 49 + Alcotest.(check (option string)) 50 + "batch c" (Some "3") (Irmin.Heap.find heap "c") 46 51 47 52 let recording () = 48 53 let store = Hashtbl.create 8 in ··· 59 64 Alcotest.(check (list string)) "recorded keys" [ "x"; "z" ] keys 60 65 61 66 let of_list () = 62 - let heap = Irmin.Heap.of_list ~equal:String.equal [ ("a", "1"); ("b", "2") ] in 63 - Alcotest.(check (option string)) "find a" (Some "1") (Irmin.Heap.find heap "a"); 64 - Alcotest.(check (option string)) "find b" (Some "2") (Irmin.Heap.find heap "b"); 67 + let heap = 68 + Irmin.Heap.of_list ~equal:String.equal [ ("a", "1"); ("b", "2") ] 69 + in 70 + Alcotest.(check (option string)) 71 + "find a" (Some "1") (Irmin.Heap.find heap "a"); 72 + Alcotest.(check (option string)) 73 + "find b" (Some "2") (Irmin.Heap.find heap "b"); 65 74 Alcotest.(check (option string)) "find c" None (Irmin.Heap.find heap "c") 66 75 67 76 let layer () = ··· 74 83 Irmin.Heap.put top "shared" "from-top"; 75 84 let layered = Irmin.Heap.layer top bot in 76 85 Alcotest.(check (option string)) 77 - "top wins" (Some "from-top") (Irmin.Heap.find layered "shared"); 86 + "top wins" (Some "from-top") 87 + (Irmin.Heap.find layered "shared"); 78 88 Alcotest.(check (option string)) 79 89 "falls through" (Some "bot") 80 90 (Irmin.Heap.find layered "bottom-only"); ··· 86 96 let heap = H.v store in 87 97 Irmin.Heap.put heap "k" "v1"; 88 98 Irmin.Heap.put heap "k" "v2"; 89 - Alcotest.(check (option string)) "overwritten" (Some "v2") (Irmin.Heap.find heap "k") 99 + Alcotest.(check (option string)) 100 + "overwritten" (Some "v2") (Irmin.Heap.find heap "k") 90 101 91 102 let recording_dedup () = 92 103 let store = Hashtbl.create 8 in ··· 115 126 let layered = Irmin.Heap.layer top bot in 116 127 Irmin.Heap.put layered "new" "val"; 117 128 Alcotest.(check (option string)) 118 - "written to top" (Some "val") (Irmin.Heap.find top "new"); 129 + "written to top" (Some "val") 130 + (Irmin.Heap.find top "new"); 119 131 Alcotest.(check (option string)) 120 - "not in bottom" None (Irmin.Heap.find bot "new") 132 + "not in bottom" None 133 + (Irmin.Heap.find bot "new") 121 134 122 135 let of_list_empty () = 123 136 let heap = Irmin.Heap.of_list ~equal:String.equal [] in
+1 -1
test/test_tar.ml test/test_irmin_tar.ml
··· 283 283 Alcotest.(check bool) "has conflicts" true (conflicts <> []) 284 284 285 285 let suite = 286 - ( "tar", 286 + ( "irmin_tar", 287 287 [ 288 288 Alcotest.test_case "merkle tree from entries" `Quick merkle_tree; 289 289 Alcotest.test_case "navigate and prove JSON in tar" `Quick tar_json_proof;
test/test_tar.mli test/test_irmin_tar.mli
+3 -3
test/test_worktree.ml
··· 24 24 let put t h d = Hashtbl.replace t h d 25 25 let mem t h = Hashtbl.mem t h 26 26 let batch t l = List.iter (fun (h, d) -> Hashtbl.replace t h d) l 27 - 28 27 let refs : (string, string) Hashtbl.t = Hashtbl.create 4 29 - 30 28 let ref _ name = Hashtbl.find_opt refs name 31 29 let set_ref _ name h = Hashtbl.replace refs name h 32 30 let del_ref _ _ = () ··· 118 116 let store = Hashtbl.create 16 in 119 117 let heap = H.v store in 120 118 W.write_index ~fs ~dir []; 121 - match W.commit ~fs heap ~branch:"main" ~dir ~message:"empty" ~author:"test" with 119 + match 120 + W.commit ~fs heap ~branch:"main" ~dir ~message:"empty" ~author:"test" 121 + with 122 122 | Error (`Msg _) -> () 123 123 | Ok _ -> Alcotest.fail "should fail: nothing to commit" 124 124