Changeset 3 in code for trunk/cli/convert.ml
- Timestamp:
- Apr 15, 2022, 1:17:01 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/cli/convert.ml
r2 r3 1 1 open Logarion 2 module A = Archive.Make (Logarion.File_store)3 2 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 3 let is_older source dest = try 4 Unix.((stat dest).st_mtime < (stat source).st_mtime) with _-> true 7 5 8 let word_fname dir text = dir ^ "/" ^ Text.alias text 9 let id_fname dir text = dir ^ "/" ^ Text.short_id text 6 let convert cs r (text, files) = match Text.str "Content-Type" text with 7 | "" | "text/plain" -> 8 let source = List.hd files in 9 let dest = Filename.concat r.Conversion.dir (Text.short_id text) in 10 List.fold_left 11 (fun a f -> 12 let dest = dest ^ f.Conversion.ext in 13 if is_older source dest then (File_store.file dest (f.Conversion.page r text); true) else false 14 || a) 15 false cs 16 | x -> Printf.eprintf "Can't convert Content-Type: %s file: %s" x text.Text.title; false 10 17 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" = typesthen14 convert_modified store_item (id_fname dir text ^ ".htm") Html.page name text15 else false in16 let g = if "gmi" = types || "all" = types then17 convert_modified store_item (id_fname dir text ^ ".gmi") Gemini.page name text18 else falsein19 h || g18 let converters types kv = 19 let t = [] in 20 let t = if ("htm" = types || "all" = types) then 21 (let htm = Html.init kv in 22 Conversion.{ ext = Html.ext; page = Html.page htm; indices = Html.indices htm })::t 23 else t in 24 let t = if ("gmi" = types || "all" = types) then 25 Conversion.{ ext = Gemini.ext; page = Gemini.page; indices = Gemini.indices}::t else t in 26 t 20 27 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 ) 28 let convert_all converters noindex dir id kv = 29 let empty = Topic_set.Map.empty in 30 let repo = Conversion.{ id; dir; kv; topic_roots = []; topics = empty; texts = [] } in 31 let fn (ts,ls,acc) ((elt,_) as r) = 32 (Topic_set.to_map ts (Text.set "topics" elt)), elt::ls, 33 if convert converters repo r then acc+1 else acc in 34 let topics, texts, count = File_store.(fold ~dir ~order:newest fn (empty,[],0)) in 35 let topic_roots = try List.rev @@ String_set.list_of_csv (Store.KV.find "Topics" kv) 36 with Not_found -> Topic_set.roots topics in 37 let repo = Conversion.{ repo with topic_roots; topics; texts } in 38 if not noindex then List.iter (fun c -> c.Conversion.indices repo) converters; 39 Printf.printf "Converted: %d Indexed: %d\n" count (List.length texts) 53 40 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 41 let convert_dir types noindex dir = 42 match dir with "" -> prerr_endline "unspecified dir" 43 | dir -> 44 let fname = Filename.concat dir "index.pck" in 45 match Header_pack.of_string @@ File_store.to_string fname with 46 | Error s -> prerr_endline s 47 | Ok { info; _ } -> 48 let kv = let f = Filename.concat dir ".convert.conf" in (* TODO: better place to store convert conf? *) 49 if Sys.file_exists f then File_store.of_kv_file f else Store.KV.empty in 50 let kv = if Store.KV.mem "Title" kv then kv 51 else Store.KV.add "Title" info.Header_pack.title kv in 52 let kv = Store.KV.add "Locations" (String.concat ";\n" info.Header_pack.locations) kv in 53 let cs = converters types kv in 54 convert_all cs noindex dir info.Header_pack.id kv 82 55 83 56 open Cmdliner 84 85 57 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 58 let directory = Arg.(value & pos 0 string "" & info [] ~docv:"target directory" 59 ~doc:"Directory to convert") in 60 let types = Arg.(value & opt string "all" & info ["t"; "type"] ~docv:"TYPES" 61 ~doc:"Convert to type") in 62 let noindex = Arg.(value & flag & info ["noindex"] 63 ~doc:"don't create indices in target format") in 89 64 Term.(const convert_dir $ types $ noindex $ directory), 90 Term.info "convert" ~doc:"convert archive" ~man:[ `S "DESCRIPTION"; `P "Convert Logarion archive" ] 65 Term.info "convert" ~doc:"convert txts" 66 ~man:[ `S "DESCRIPTION"; `P "Convert texts within a directory to another format. 67 Directory must contain an index.pck. Run `txt index` first." ]
Note:
See TracChangeset
for help on using the changeset viewer.