Persistent store with Git semantics: lazy reads, delayed writes, content-addressing
at inline-small-objects 91 lines 3.1 kB view raw
1(** Irmin CLI configuration. *) 2 3type backend = Git | Mst | Memory 4type t = { backend : backend; store_path : string; default_branch : string } 5 6let default = { backend = Git; store_path = "."; default_branch = "main" } 7 8let pp_backend ppf = function 9 | Git -> Fmt.string ppf "git" 10 | Mst -> Fmt.string ppf "mst" 11 | Memory -> Fmt.string ppf "memory" 12 13let backend_of_string = function 14 | "git" -> Some Git 15 | "mst" | "atproto" -> Some Mst 16 | "memory" | "mem" -> Some Memory 17 | _ -> None 18 19(** Parse config file. Format: key = value, one per line. *) 20let parse_config_file path = 21 if not (Sys.file_exists path) then None 22 else 23 let ic = open_in path in 24 let rec loop acc = 25 match input_line ic with 26 | line -> 27 let line = String.trim line in 28 if line = "" || line.[0] = '#' then loop acc 29 else begin 30 match String.index_opt line '=' with 31 | None -> loop acc 32 | Some i -> 33 let key = String.trim (String.sub line 0 i) in 34 let value = 35 String.trim 36 (String.sub line (i + 1) (String.length line - i - 1)) 37 in 38 loop ((key, value) :: acc) 39 end 40 | exception End_of_file -> 41 close_in ic; 42 Some acc 43 in 44 loop [] 45 46let config_of_pairs pairs = 47 List.fold_left 48 (fun cfg (key, value) -> 49 match key with 50 | "backend" -> ( 51 match backend_of_string value with 52 | Some b -> { cfg with backend = b } 53 | None -> cfg) 54 | "store" | "store_path" | "path" -> { cfg with store_path = value } 55 | "branch" | "default_branch" -> { cfg with default_branch = value } 56 | _ -> cfg) 57 default pairs 58 59(** Detect backend from directory structure. *) 60let detect_backend ~cwd = 61 let git_dir = Filename.concat cwd ".git" in 62 let irmin_dir = Filename.concat cwd ".irmin" in 63 if Sys.file_exists git_dir && Sys.is_directory git_dir then 64 Some { default with backend = Git; store_path = cwd } 65 else if Sys.file_exists irmin_dir && Sys.is_directory irmin_dir then 66 (* Check for config in .irmin/ *) 67 let config_path = Filename.concat irmin_dir "config" in 68 match parse_config_file config_path with 69 | Some pairs -> Some (config_of_pairs pairs) 70 | None -> Some { default with backend = Mst; store_path = irmin_dir } 71 else None 72 73(** Load configuration. Priority: explicit config > .irmin/config > auto-detect 74 > default *) 75let load ?config_file ~repo () = 76 (* First try explicit config file *) 77 match config_file with 78 | Some path -> ( 79 match parse_config_file path with 80 | Some pairs -> config_of_pairs pairs 81 | None -> default) 82 | None -> ( 83 (* Try .irmin/config in repo *) 84 let irmin_config = Filename.concat repo ".irmin/config" in 85 match parse_config_file irmin_config with 86 | Some pairs -> config_of_pairs pairs 87 | None -> ( 88 (* Auto-detect from directory structure *) 89 match detect_backend ~cwd:repo with 90 | Some cfg -> cfg 91 | None -> { default with store_path = repo }))