Commit
+88 -17 +/-2 browse
1 | diff --git a/lib/manifest.ml b/lib/manifest.ml |
2 | index 284dd69..7fa4592 100644 |
3 | --- a/lib/manifest.ml |
4 | +++ b/lib/manifest.ml |
5 | @@ -1,5 +1,13 @@ |
6 | open Core |
7 | |
8 | + module Util = struct |
9 | + let dirname path = |
10 | + (* nothing is relative, all things are absolute! *) |
11 | + match path |> Filename.is_relative with |
12 | + | true -> Filename.concat "/" (Filename.dirname path) |
13 | + | false -> path |> Filename.dirname |
14 | + end |
15 | + |
16 | module Item = struct |
17 | type t = { |
18 | parent : string option; |
19 | @@ -117,11 +125,13 @@ let list ~path manifest = |
20 | manifest.items |
21 | |> List.filter ~f:(fun item -> |
22 | let item_path = item |> to_path ~manifest in |
23 | - String.equal path (Filename.dirname item_path)) |
24 | + Filename.equal path (Filename.dirname item_path)) |
25 | |
26 | - let insert ~path ~slug ~title ~description ~tags manifest = |
27 | - match path with |
28 | - | "" | "/" -> |
29 | + let insert ~path ~slug ~description ~tags manifest = |
30 | + let title = path |> Filename.basename in |
31 | + let dirname = path |> Util.dirname in |
32 | + match dirname with |
33 | + | "/" -> |
34 | let item = Item.make ~parent:None ~slug ~title ~description ~tags in |
35 | if manifest |> exists ~path:(item |> to_path ~manifest) then |
36 | failwith "duplicate item" |
37 | @@ -160,6 +170,29 @@ let remove ~path manifest = |
38 | { items } |
39 | | None -> failwith "not found" |
40 | |
41 | + let update ?(new_path = None) ~path ~description ~tags manifest = |
42 | + let result = |
43 | + manifest.items |
44 | + |> List.findi ~f:(fun _ item -> |
45 | + let file_path = item |> to_path ~manifest in |
46 | + Filename.equal file_path path) |
47 | + in |
48 | + match result with |
49 | + | Some (index, item) -> ( |
50 | + match new_path with |
51 | + | Some new_path -> |
52 | + let manifest = manifest |> remove ~path in |
53 | + manifest |> insert ~path:new_path ~slug:item.slug ~description ~tags |
54 | + | None -> |
55 | + let item = { item with description; tags } in |
56 | + let items = |
57 | + manifest.items |
58 | + |> List.foldi ~init:[] ~f:(fun i accm other -> |
59 | + if Int.equal i index then item :: accm else other :: accm) |
60 | + in |
61 | + { items }) |
62 | + | None -> failwith "not found" |
63 | + |
64 | let slugs manifest = manifest.items |> List.map ~f:(fun item -> item.slug) |
65 | |
66 | let tags manifest = |
67 | diff --git a/test/manifest_test.ml b/test/manifest_test.ml |
68 | index 1c69b8a..d60d0ff 100644 |
69 | --- a/test/manifest_test.ml |
70 | +++ b/test/manifest_test.ml |
71 | @@ -4,14 +4,14 @@ open Note_lib |
72 | let test_recurse () = |
73 | let manifest = |
74 | Manifest.empty |
75 | - |> Manifest.insert ~path:"/" ~slug:"note-00000000-0" ~title:"a" |
76 | - ~description:"" ~tags:[] |
77 | - |> Manifest.insert ~path:"/a" ~slug:"note-00000000-1" ~title:"b" |
78 | - ~description:"" ~tags:[] |
79 | - |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-2" ~title:"c" |
80 | - ~description:"" ~tags:[] |
81 | - |> Manifest.insert ~path:"/a/b/c" ~slug:"note-00000000-3" ~title:"d" |
82 | - ~description:"" ~tags:[] |
83 | + |> Manifest.insert ~path:"/a" ~slug:"note-00000000-0" ~description:"" |
84 | + ~tags:[] |
85 | + |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-1" ~description:"" |
86 | + ~tags:[] |
87 | + |> Manifest.insert ~path:"/a/b/c" ~slug:"note-00000000-2" ~description:"" |
88 | + ~tags:[] |
89 | + |> Manifest.insert ~path:"/a/b/c/d" ~slug:"note-00000000-3" ~description:"" |
90 | + ~tags:[] |
91 | in |
92 | Alcotest.(check int) "n_results" 4 (List.length manifest.items) |
93 | |
94 | @@ -20,14 +20,14 @@ let test_manifest () = |
95 | Manifest.empty |> Manifest.save ~path:temp_db; |
96 | let manifest = |
97 | Manifest.load_or_init temp_db |
98 | - |> Manifest.insert ~path:"/" ~slug:"note-00000000-0.md" ~title:"fuu" |
99 | - ~description:"" ~tags:[] |
100 | + |> Manifest.insert ~path:"/fuu" ~slug:"note-00000000-0.md" ~description:"" |
101 | + ~tags:[] |
102 | in |
103 | let result = manifest |> Manifest.find ~path:"/fuu" in |
104 | Alcotest.(check bool) "manifest loaded" (result |> Option.is_some) true; |
105 | let manifest = |
106 | manifest |
107 | - |> Manifest.insert ~path:"/fuu" ~slug:"note-00000000-1.md" ~title:"bar" |
108 | + |> Manifest.insert ~path:"/fuu/bar" ~slug:"note-00000000-1.md" |
109 | ~description:"" ~tags:[] |
110 | in |
111 | let result = manifest |> Manifest.find ~path:"/fuu/bar" in |
112 | @@ -37,14 +37,14 @@ let test_manifest () = |
113 | Alcotest.(check string) "result path" "/fuu/bar" result_path; |
114 | let manifest = |
115 | manifest |
116 | - |> Manifest.insert ~path:"/fuu" ~slug:"note-00000000-2.md" ~title:"baz" |
117 | + |> Manifest.insert ~path:"/fuu/baz" ~slug:"note-00000000-2.md" |
118 | ~description:"" ~tags:[] |
119 | in |
120 | let results = manifest |> Manifest.list ~path:"/fuu" in |
121 | Alcotest.(check int) "n_results" 2 (List.length results); |
122 | let manifest = |
123 | manifest |
124 | - |> Manifest.insert ~path:"/fuu/bar" ~slug:"note-00000000-3.md" ~title:"qux" |
125 | + |> Manifest.insert ~path:"/fuu/bar/qux" ~slug:"note-00000000-3.md" |
126 | ~description:"" ~tags:[] |
127 | in |
128 | let results = manifest |> Manifest.list ~path:"/fuu/bar" in |
129 | @@ -55,9 +55,47 @@ let test_manifest () = |
130 | print_endline (Manifest.to_string manifest); |
131 | Alcotest.(check int) "remove" 3 (List.length manifest.items) |
132 | |
133 | + let test_update () = |
134 | + let manifest = |
135 | + Manifest.empty |
136 | + |> Manifest.insert ~path:"/a" ~slug:"note-00000000-0" ~description:"" |
137 | + ~tags:[] |
138 | + |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-1" ~description:"" |
139 | + ~tags:[] |
140 | + in |
141 | + Alcotest.(check int) "two entries" 2 (List.length manifest.items); |
142 | + let manifest = |
143 | + manifest |> Manifest.update ~path:"/a/b" ~description:"" ~tags:[ "a"; "b" ] |
144 | + in |
145 | + let result = Option.value_exn (manifest |> Manifest.find ~path:"/a/b") in |
146 | + Alcotest.(check string) "updated" "a" (List.nth_exn result.tags 0); |
147 | + Alcotest.(check string) "updated" "b" (List.nth_exn result.tags 1); |
148 | + |
149 | + Alcotest.(check int) "two entries" 2 (List.length manifest.items) |
150 | + |
151 | + let test_move () = |
152 | + let manifest = |
153 | + Manifest.empty |
154 | + |> Manifest.insert ~path:"/a" ~slug:"note-00000000-0" ~description:"" |
155 | + ~tags:[] |
156 | + |> Manifest.insert ~path:"/a/b" ~slug:"note-00000000-1" ~description:"" |
157 | + ~tags:[] |
158 | + in |
159 | + let manifest = |
160 | + manifest |
161 | + |> Manifest.update ~new_path:(Some "/b") ~path:"/a/b" ~description:"" |
162 | + ~tags:[] |
163 | + in |
164 | + Alcotest.(check bool) |
165 | + "moved" true |
166 | + (manifest |> Manifest.find ~path:"/b" |> Option.is_some) ; |
167 | + Alcotest.(check int) "two entries" 2 (List.length manifest.items) |
168 | + |
169 | let () = |
170 | Alcotest.run "Config" |
171 | [ |
172 | ("recurse", [ Alcotest.test_case "test recurse" `Quick test_recurse ]); |
173 | ("load", [ Alcotest.test_case "test manifest" `Quick test_manifest ]); |
174 | + ("update", [ Alcotest.test_case "test update" `Quick test_update ]); |
175 | + ("move", [ Alcotest.test_case "test move" `Quick test_move ]); |
176 | ] |