1 | open Logarion
|
---|
2 | module A = Archive.Make (Logarion.File_store)
|
---|
3 |
|
---|
4 | let convert_modified source dest fn title text =
|
---|
5 | if (try Unix.((stat dest).st_mtime < (stat source).st_mtime) with _-> true)
|
---|
6 | then (File_store.file dest (fn title text); true) else false
|
---|
7 |
|
---|
8 | let word_fname dir text = dir ^ "/" ^ Text.alias text
|
---|
9 | let id_fname dir text = dir ^ "/" ^ Text.short_id text
|
---|
10 |
|
---|
11 | let writer types dir name (text,store_item) = (* todo: single_parser -> [files] *)
|
---|
12 | (* convert_modified store_item idfilename (fun _title -> Text.to_string) text.title text;*)
|
---|
13 | let h = if "htm" = types || "all" = types then
|
---|
14 | convert_modified store_item (id_fname dir text ^ ".htm") Html.page name text
|
---|
15 | else false in
|
---|
16 | let g = if "gmi" = types || "all" = types then
|
---|
17 | convert_modified store_item (id_fname dir text ^ ".gmi") Gemini.page name text
|
---|
18 | else false in
|
---|
19 | h || g
|
---|
20 |
|
---|
21 | let index_writer types noindex dir archive topic_roots topic_map texts =
|
---|
22 | let name = archive.A.name in
|
---|
23 | let file path = File_store.file (dir ^ path) in
|
---|
24 | file "/index.pck" (Header_pack.pack archive texts);
|
---|
25 | if not noindex && ("htm" = types || "all" = types) then (
|
---|
26 | let index_name = try Store.KV.find "HTML-index" archive.File_store.kv
|
---|
27 | with Not_found -> "index.html" in
|
---|
28 | if index_name <> "" then
|
---|
29 | file ("/"^index_name) (Html.topic_main_index name topic_roots texts);
|
---|
30 | file "/index.date.htm" (Html.date_index name texts);
|
---|
31 | List.iter
|
---|
32 | (fun topic -> file ("/index." ^ topic ^ ".htm")
|
---|
33 | (Html.topic_sub_index name topic_map topic texts))
|
---|
34 | topic_roots;
|
---|
35 | let base_url = try Store.KV.find "HTTP-URL" archive.File_store.kv
|
---|
36 | with Not_found -> prerr_endline "Missing `HTTP-URL:` in config"; "" in
|
---|
37 | file "/feed.atom" (Atom.feed archive.A.name archive.A.id base_url "text/html" texts)
|
---|
38 | );
|
---|
39 | if not noindex && ("gmi" = types || "all" = types) then (
|
---|
40 | let index_name = try Store.KV.find "Gemini-index" archive.File_store.kv
|
---|
41 | with Not_found -> "index.gmi" in
|
---|
42 | if index_name <> "" then
|
---|
43 | file ("/"^index_name) (Gemini.topic_main_index name topic_roots texts);
|
---|
44 | file "/index.date.gmi" (Gemini.date_index name texts);
|
---|
45 | List.iter
|
---|
46 | (fun topic -> file ("/index." ^ topic ^ ".gmi")
|
---|
47 | (Gemini.topic_sub_index name topic_map topic texts))
|
---|
48 | topic_roots;
|
---|
49 | let base_url = try Store.KV.find "GEMINI-URL" archive.File_store.kv
|
---|
50 | with Not_found -> prerr_endline "Missing `GEMINI-URL:` in config"; "" in
|
---|
51 | file "/gmi.atom" (Atom.feed archive.A.name archive.A.id base_url "text/gemini" texts)
|
---|
52 | )
|
---|
53 |
|
---|
54 | let txt_writer types dir name ((text, _store_item) as r) =
|
---|
55 | match Text.str "Content-Type" text with
|
---|
56 | | "" | "text/plain" -> writer types dir name r
|
---|
57 | | x -> prerr_endline ("Can't convert Content-Type: "^x^" file: " ^text.Text.title); false
|
---|
58 |
|
---|
59 | let convert_all types noindex dir archive =
|
---|
60 | let name = archive.A.name in
|
---|
61 | let fn (ts,ls,acc) ((elt,_) as r) =
|
---|
62 | (Topic_set.to_map ts (Text.set "topics" elt)),
|
---|
63 | elt::ls, if txt_writer types dir name r then acc+1 else acc in
|
---|
64 | let empty = Topic_set.Map.empty in
|
---|
65 | let topic_map, texts, count = A.(fold ~order:newest fn (empty,[],0) archive) in
|
---|
66 | let topic_roots = Topic_set.roots topic_map in
|
---|
67 | index_writer types noindex dir archive topic_roots topic_map texts;
|
---|
68 | print_endline @@ "Converted: " ^ string_of_int (count)
|
---|
69 | ^ "\nIndexed: " ^ string_of_int (List.length texts);
|
---|
70 | Ok ()
|
---|
71 |
|
---|
72 | let convert_dir types noindex cmd_dir =
|
---|
73 | let (>>=) = Result.bind in
|
---|
74 | let with_dir dir =
|
---|
75 | Result.map_error (function `Msg m -> m)
|
---|
76 | Logarion.File_store.Directory.(directory dir |> print ~descr:"export" dir) in
|
---|
77 | (A.of_path "."
|
---|
78 | >>= fun archive -> (match cmd_dir with "" -> Error "unspecified export dir" | x -> Ok x)
|
---|
79 | >>= fun dir -> with_dir dir
|
---|
80 | >>= fun _ -> convert_all types noindex dir { archive with store = dir })
|
---|
81 | |> function Ok () -> () | Error x -> prerr_endline x
|
---|
82 |
|
---|
83 | open Cmdliner
|
---|
84 |
|
---|
85 | let term =
|
---|
86 | let directory = Arg.(value & pos 0 string "" & info [] ~docv:"target directory" ~doc:"Directory to convert into") in
|
---|
87 | let types = Arg.(value & opt string "all" & info ["t"; "type"] ~docv:"TYPES" ~doc:"Convert to type") in
|
---|
88 | let noindex = Arg.(value & flag & info ["noindex"] ~doc:"don't write an index when converting") in
|
---|
89 | Term.(const convert_dir $ types $ noindex $ directory),
|
---|
90 | Term.info "convert" ~doc:"convert archive" ~man:[ `S "DESCRIPTION"; `P "Convert Logarion archive" ]
|
---|