My aggregated monorepo of OCaml code, automaintained
0
fork

Configure Feed

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

feat(day10): add --local-repo for local opam pins in containers

Adds --local-repo PATH CLI option (repeatable) that bind-mounts local
directories into build containers and pins opam packages from the local
path instead of from a git URL. Supports both jtw and odoc tool layers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+143 -60
+1
day10/bin/config.ml
··· 19 19 doc_tools_branch : string; 20 20 jtw_tools_repo : string; 21 21 jtw_tools_branch : string; 22 + local_repos : string list; 22 23 html_output : string option; (* Shared HTML output directory for all docs *) 23 24 jtw_output : string option; (* Output directory for jtw artifacts *) 24 25 tag : string option;
+60 -28
day10/bin/doc_tools.ml
··· 11 11 12 12 All tools are pinned to odoc 3.1 from the configured repo/branch. *) 13 13 14 + let driver_packages = [ "odoc"; "odoc-parser"; "odoc-md"; "sherlodoc"; "odoc-driver" ] 15 + let odoc_packages = [ "odoc"; "odoc-parser" ] 16 + 17 + (** Return the local repo path to bind-mount for doc tools, if any. *) 18 + let local_repo_mount ~(config : Config.t) = 19 + match Local_repo.find_for_packages ~local_repos:config.local_repos driver_packages with 20 + | Some (path, _) -> Some (path, "/home/opam/local/odoc") 21 + | None -> None 22 + 14 23 (** Compute hash for the shared driver layer. 15 24 Only depends on repo/branch since it's always built with a fixed OCaml version. *) 16 25 let driver_layer_hash ~(config : Config.t) = 17 - let components = [ "driver"; config.doc_tools_repo; config.doc_tools_branch ] in 26 + let source_component = match Local_repo.find_for_packages ~local_repos:config.local_repos driver_packages with 27 + | Some (path, _) -> Local_repo.repo_hash path 28 + | None -> config.doc_tools_repo ^ "|" ^ config.doc_tools_branch 29 + in 30 + let components = [ "driver"; source_component ] in 18 31 String.concat "|" components |> Digest.string |> Digest.to_hex 19 32 20 33 (** Directory name for the driver layer *) ··· 31 44 let driver_build_script ~(config : Config.t) = 32 45 let repo = config.doc_tools_repo in 33 46 let branch = config.doc_tools_branch in 34 - (* Use a recent OCaml 5.x for building the driver tools *) 47 + let pin_cmds = match Local_repo.find_for_packages ~local_repos:config.local_repos driver_packages with 48 + | Some (_, matched) -> 49 + let local_mount = "/home/opam/local/odoc" in 50 + let from_local = List.map (fun pkg -> 51 + Printf.sprintf "opam pin add -yn %s %s" pkg local_mount 52 + ) matched in 53 + let from_git = List.filter_map (fun pkg -> 54 + if List.mem pkg matched then None 55 + else Some (Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch) 56 + ) driver_packages in 57 + from_local @ from_git 58 + | None -> 59 + List.map (fun pkg -> 60 + Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch 61 + ) driver_packages 62 + in 35 63 String.concat " && " 36 - [ 37 - "opam install -y ocaml-base-compiler.5.2.1"; 38 - (* Pin all packages from the odoc repo *) 39 - Printf.sprintf "opam pin add -yn odoc %s#%s" repo branch; 40 - Printf.sprintf "opam pin add -yn odoc-parser %s#%s" repo branch; 41 - Printf.sprintf "opam pin add -yn odoc-md %s#%s" repo branch; 42 - Printf.sprintf "opam pin add -yn sherlodoc %s#%s" repo branch; 43 - Printf.sprintf "opam pin add -yn odoc-driver %s#%s" repo branch; 44 - (* Install the driver tools *) 45 - "opam install -y odoc-driver odoc-md sherlodoc"; 46 - (* Generate sherlodoc.js for client-side search *) 47 - "eval $(opam env) && sherlodoc js > /home/opam/sherlodoc.js"; 48 - (* Verify the tools are installed *) 49 - "which odoc_driver_voodoo && which sherlodoc"; 50 - ] 64 + ([ "opam install -y ocaml-base-compiler.5.2.1" ] 65 + @ pin_cmds 66 + @ [ "opam install -y odoc-driver odoc-md sherlodoc"; 67 + "eval $(opam env) && sherlodoc js > /home/opam/sherlodoc.js"; 68 + "which odoc_driver_voodoo && which sherlodoc" ]) 51 69 52 70 (** Check if driver layer exists *) 53 71 let driver_exists ~(config : Config.t) : bool = ··· 72 90 Depends on OCaml version and repo/branch for odoc 3.1. *) 73 91 let odoc_layer_hash ~(config : Config.t) ~(ocaml_version : OpamPackage.t) = 74 92 let version = OpamPackage.Version.to_string (OpamPackage.version ocaml_version) in 75 - let components = [ "odoc"; version; config.doc_tools_repo; config.doc_tools_branch ] in 93 + let source_component = match Local_repo.find_for_packages ~local_repos:config.local_repos odoc_packages with 94 + | Some (path, _) -> Local_repo.repo_hash path 95 + | None -> config.doc_tools_repo ^ "|" ^ config.doc_tools_branch 96 + in 97 + let components = [ "odoc"; version; source_component ] in 76 98 String.concat "|" components |> Digest.string |> Digest.to_hex 77 99 78 100 (** Directory name for the odoc layer *) ··· 90 112 let repo = config.doc_tools_repo in 91 113 let branch = config.doc_tools_branch in 92 114 let version = OpamPackage.Version.to_string (OpamPackage.version ocaml_version) in 115 + let pin_cmds = match Local_repo.find_for_packages ~local_repos:config.local_repos odoc_packages with 116 + | Some (_, matched) -> 117 + let local_mount = "/home/opam/local/odoc" in 118 + let from_local = List.map (fun pkg -> 119 + Printf.sprintf "opam pin add -yn %s %s" pkg local_mount 120 + ) matched in 121 + let from_git = List.filter_map (fun pkg -> 122 + if List.mem pkg matched then None 123 + else Some (Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch) 124 + ) odoc_packages in 125 + from_local @ from_git 126 + | None -> 127 + List.map (fun pkg -> 128 + Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch 129 + ) odoc_packages 130 + in 93 131 String.concat " && " 94 - [ 95 - Printf.sprintf "opam install -y ocaml-base-compiler.%s" version; 96 - (* Pin odoc and odoc-parser from the repo *) 97 - Printf.sprintf "opam pin add -yn odoc %s#%s" repo branch; 98 - Printf.sprintf "opam pin add -yn odoc-parser %s#%s" repo branch; 99 - (* Install odoc *) 100 - "opam install -y odoc"; 101 - (* Verify odoc is installed and show version *) 102 - "eval $(opam env) && which odoc && odoc --version"; 103 - ] 132 + ([ Printf.sprintf "opam install -y ocaml-base-compiler.%s" version ] 133 + @ pin_cmds 134 + @ [ "opam install -y odoc"; 135 + "eval $(opam env) && which odoc && odoc --version" ]) 104 136 105 137 (** Check if odoc layer exists for this OCaml version *) 106 138 let odoc_exists ~(config : Config.t) ~(ocaml_version : OpamPackage.t) : bool =
+35 -19
day10/bin/jtw_tools.ml
··· 5 5 6 6 Cached as [jtw-tools-<hash>/] per OCaml version + repo + branch. *) 7 7 8 + let jtw_packages = [ "js_top_worker"; "js_top_worker-rpc"; "js_top_worker-bin"; 9 + "js_top_worker-web"; "js_top_worker_rpc_def" ] 10 + 8 11 (** Compute hash for the jtw-tools layer. 9 12 Depends on OCaml version, repo, and branch. *) 10 13 let layer_hash ~(config : Config.t) ~(ocaml_version : OpamPackage.t) = 11 14 let version = OpamPackage.Version.to_string (OpamPackage.version ocaml_version) in 12 - let components = [ "jtw-tools"; version; config.jtw_tools_repo; config.jtw_tools_branch ] in 15 + let source_component = match Local_repo.find_for_packages ~local_repos:config.local_repos jtw_packages with 16 + | Some (path, _) -> Local_repo.repo_hash path 17 + | None -> config.jtw_tools_repo ^ "|" ^ config.jtw_tools_branch 18 + in 19 + let components = [ "jtw-tools"; version; source_component ] in 13 20 String.concat "|" components |> Digest.string |> Digest.to_hex 14 21 15 22 (** Directory name for the jtw-tools layer *) ··· 27 34 and extracts stdlib cmis. *) 28 35 let build_script ~(config : Config.t) ~(ocaml_version : OpamPackage.t) = 29 36 let version = OpamPackage.Version.to_string (OpamPackage.version ocaml_version) in 30 - let repo = config.jtw_tools_repo in 31 - let branch = config.jtw_tools_branch in 37 + let pin_cmds = match Local_repo.find_for_packages ~local_repos:config.local_repos jtw_packages with 38 + | Some (_, matched) -> 39 + let local_mount = "/home/opam/local/js_top_worker" in 40 + let from_local = List.map (fun pkg -> 41 + Printf.sprintf "opam pin add -yn %s %s" pkg local_mount 42 + ) matched in 43 + let from_git = List.filter_map (fun pkg -> 44 + if List.mem pkg matched then None 45 + else Some (Printf.sprintf "opam pin add -yn %s git+%s#%s" pkg config.jtw_tools_repo config.jtw_tools_branch) 46 + ) jtw_packages in 47 + from_local @ from_git 48 + | None -> 49 + List.map (fun pkg -> 50 + Printf.sprintf "opam pin add -yn %s git+%s#%s" pkg config.jtw_tools_repo config.jtw_tools_branch 51 + ) jtw_packages 52 + in 32 53 String.concat " && " 33 - [ 34 - Printf.sprintf "opam install -y ocaml-base-compiler.%s" version; 35 - (* Pin all js_top_worker packages from the repo. 36 - Use git+ prefix so opam treats it as a git repo, not an archive. *) 37 - Printf.sprintf "opam pin add -yn js_top_worker git+%s#%s" repo branch; 38 - Printf.sprintf "opam pin add -yn js_top_worker-rpc git+%s#%s" repo branch; 39 - Printf.sprintf "opam pin add -yn js_top_worker-bin git+%s#%s" repo branch; 40 - Printf.sprintf "opam pin add -yn js_top_worker-web git+%s#%s" repo branch; 41 - Printf.sprintf "opam pin add -yn js_top_worker_rpc_def git+%s#%s" repo branch; 42 - (* Install js_of_ocaml, jtw CLI, and web worker library *) 43 - "opam install -y js_of_ocaml js_top_worker-bin js_top_worker-web"; 44 - (* Verify tools are installed *) 45 - "eval $(opam env) && which js_of_ocaml && which jtw"; 46 - (* Build worker.js + stdlib cmis/dynamic_cmis.json in one step *) 47 - "eval $(opam env) && jtw opam -o /home/opam/jtw-tools-output stdlib"; 48 - ] 54 + ([ Printf.sprintf "opam install -y ocaml-base-compiler.%s" version ] 55 + @ pin_cmds 56 + @ [ "opam install -y js_of_ocaml js_top_worker-bin js_top_worker-web"; 57 + "eval $(opam env) && which js_of_ocaml && which jtw"; 58 + "eval $(opam env) && jtw opam -o /home/opam/jtw-tools-output stdlib" ]) 49 59 50 60 (** Check if jtw-tools layer exists for this OCaml version *) 51 61 let exists ~(config : Config.t) ~(ocaml_version : OpamPackage.t) : bool = ··· 64 74 let has_worker_js ~(config : Config.t) ~(ocaml_version : OpamPackage.t) : bool = 65 75 let worker_path = Path.(layer_path ~config ~ocaml_version / "fs" / "home" / "opam" / "jtw-tools-output" / "worker.js") in 66 76 Sys.file_exists worker_path 77 + 78 + (** Return the local repo path to bind-mount for jtw, if any. *) 79 + let local_repo_mount ~(config : Config.t) = 80 + match Local_repo.find_for_packages ~local_repos:config.local_repos jtw_packages with 81 + | Some (path, _) -> Some (path, "/home/opam/local/js_top_worker") 82 + | None -> None
+26 -6
day10/bin/linux.ml
··· 271 271 This is built directly on the base layer without any compiler layers. 272 272 Takes a build_script parameter to support both driver and odoc layers. 273 273 Returns the exit status of the build. *) 274 - let build_doc_tools_layer ~t ~temp_dir ~build_script build_log = 274 + let build_doc_tools_layer ~t ~temp_dir ~build_script ?(extra_mounts=[]) build_log = 275 275 let config = t.config in 276 276 let os_key = Config.os_key ~config in 277 277 let upperdir = Path.(temp_dir / "fs") in ··· 299 299 options = [ "rbind"; "rprivate" ]; 300 300 }; 301 301 { ty = "bind"; src = etc_hosts; dst = "/etc/hosts"; options = [ "ro"; "rbind"; "rprivate" ] }; 302 - ] 302 + ] @ extra_mounts 303 303 in 304 304 let config_runc = 305 305 make ~root:rootfsdir ~cwd:"/home/opam" ~argv ~hostname ~uid:t.uid ··· 352 352 let opam_repo = Path.(temp_dir / "opam-repository") in 353 353 Unix.symlink opam_repo_src opam_repo; 354 354 let build_script = Doc_tools.driver_build_script ~config in 355 - let r = build_doc_tools_layer ~t ~temp_dir ~build_script build_log in 355 + let extra_mounts = match Doc_tools.local_repo_mount ~config with 356 + | Some (src, dst) -> 357 + [ { Mount.ty = "bind"; src; dst; options = [ "ro"; "rbind"; "rprivate" ] } ] 358 + | None -> [] 359 + in 360 + let r = build_doc_tools_layer ~t ~temp_dir ~build_script ~extra_mounts build_log in 356 361 let () = Os.safe_rename_dir ~marker_file:layer_json temp_dir target_dir in 357 362 let dummy_pkg = OpamPackage.of_string "doc-driver.0" in 358 363 Util.save_layer_info layer_json dummy_pkg [] [] r ··· 380 385 let opam_repo = Path.(temp_dir / "opam-repository") in 381 386 Unix.symlink opam_repo_src opam_repo; 382 387 let build_script = Doc_tools.odoc_build_script ~config ~ocaml_version in 383 - let r = build_doc_tools_layer ~t ~temp_dir ~build_script build_log in 388 + let extra_mounts = match Doc_tools.local_repo_mount ~config with 389 + | Some (src, dst) -> 390 + [ { Mount.ty = "bind"; src; dst; options = [ "ro"; "rbind"; "rprivate" ] } ] 391 + | None -> [] 392 + in 393 + let r = build_doc_tools_layer ~t ~temp_dir ~build_script ~extra_mounts build_log in 384 394 let () = Os.safe_rename_dir ~marker_file:layer_json temp_dir target_dir in 385 395 let dummy_pkg = OpamPackage.of_string "doc-odoc.0" in 386 396 Util.save_layer_info layer_json dummy_pkg [] [] r ··· 639 649 let opam_repo = Path.(temp_dir / "opam-repository") in 640 650 Unix.symlink opam_repo_src opam_repo; 641 651 let build_script = Jtw_tools.build_script ~config ~ocaml_version in 642 - let r = build_doc_tools_layer ~t ~temp_dir ~build_script build_log in 652 + let extra_mounts = match Jtw_tools.local_repo_mount ~config with 653 + | Some (src, dst) -> 654 + [ { Mount.ty = "bind"; src; dst; options = [ "ro"; "rbind"; "rprivate" ] } ] 655 + | None -> [] 656 + in 657 + let r = build_doc_tools_layer ~t ~temp_dir ~build_script ~extra_mounts build_log in 643 658 let () = Os.safe_rename_dir ~marker_file:layer_json temp_dir target_dir in 644 659 let dummy_pkg = OpamPackage.of_string "jtw-tools.0" in 645 660 Util.save_layer_info layer_json dummy_pkg [] [] r ··· 697 712 [ "mount"; "-t"; "overlay"; "overlay"; rootfsdir; "-o"; String.concat "," [ ld; ud; wd ] ] in 698 713 if mount_result <> 0 then 1 699 714 else begin 715 + let local_mounts = match Jtw_tools.local_repo_mount ~config with 716 + | Some (src, dst) -> 717 + [ { Mount.ty = "bind"; src; dst; options = [ "ro"; "rbind"; "rprivate" ] } ] 718 + | None -> [] 719 + in 700 720 let mounts = [ 701 721 { Mount.ty = "bind"; src = jtw_output_host; dst = "/home/opam/jtw-output"; options = [ "rw"; "rbind"; "rprivate" ] }; 702 722 { ty = "bind"; src = etc_hosts; dst = "/etc/hosts"; options = [ "ro"; "rbind"; "rprivate" ] }; 703 - ] in 723 + ] @ local_mounts in 704 724 let jtw_env = List.map (fun (k, v) -> 705 725 if k = "PATH" then (k, "/home/opam/.opam/default/bin:" ^ v) else (k, v) 706 726 ) env in
+21 -7
day10/bin/main.ml
··· 857 857 output config results 858 858 859 859 let run_health_check_multi (config : Config.t) package_arg = 860 + let () = match Local_repo.validate config.local_repos with 861 + | Ok () -> () 862 + | Error msg -> failwith msg 863 + in 860 864 match package_arg.[0] = '@' with 861 865 | false -> 862 866 (* Single package: use paths as-is (files, not directories) *) ··· 1054 1058 | None -> () 1055 1059 1056 1060 let run_batch (config : Config.t) package_arg = 1061 + let () = match Local_repo.validate config.local_repos with 1062 + | Ok () -> () 1063 + | Error msg -> failwith msg 1064 + in 1057 1065 let packages = 1058 1066 if String.length package_arg > 0 && package_arg.[0] = '@' then 1059 1067 let filename = String.sub package_arg 1 (String.length package_arg - 1) in ··· 1440 1448 let doc = "Git branch for js_top_worker tools (default: main)" in 1441 1449 Arg.(value & opt string "main" & info [ "jtw-tools-branch" ] ~docv:"BRANCH" ~doc) 1442 1450 1451 + let local_repo_term = 1452 + let doc = "Use local directory for opam pins instead of git (repeatable). \ 1453 + Scans for *.opam files and pins matching packages from the local path." in 1454 + Arg.(value & opt_all string [] & info [ "local-repo" ] ~docv:"PATH" ~doc) 1455 + 1443 1456 let html_output_term = 1444 1457 let doc = "Shared HTML output directory for all documentation (enables doc generation for all packages)" in 1445 1458 Arg.(value & opt (some string) None & info [ "html-output" ] ~docv:"DIR" ~doc) ··· 1542 1555 doc_tools_branch; 1543 1556 jtw_tools_repo = ""; 1544 1557 jtw_tools_branch = ""; 1558 + local_repos = []; 1545 1559 html_output; 1546 1560 jtw_output = None; 1547 1561 tag = None; ··· 1563 1577 in 1564 1578 let health_check_term = 1565 1579 Term.( 1566 - const (fun dir ocaml_version opam_repositories package_arg md json dot with_test with_doc with_jtw doc_tools_repo doc_tools_branch jtw_tools_repo jtw_tools_branch html_output jtw_output log dry_run tag arch os os_distribution os_family os_version fork prune_layers blessed_map_file -> 1580 + const (fun dir ocaml_version opam_repositories package_arg md json dot with_test with_doc with_jtw doc_tools_repo doc_tools_branch jtw_tools_repo jtw_tools_branch local_repos html_output jtw_output log dry_run tag arch os os_distribution os_family os_version fork prune_layers blessed_map_file -> 1567 1581 let ocaml_version = Option.map OpamPackage.of_string ocaml_version in 1568 1582 let blessed_map = Option.map Blessing.load_blessed_map blessed_map_file in 1569 - run_health_check_multi { dir; ocaml_version; opam_repositories; package = ""; arch; os; os_distribution; os_family; os_version; directory = None; md; json; dot; with_test; with_doc; with_jtw; doc_tools_repo; doc_tools_branch; jtw_tools_repo; jtw_tools_branch; html_output; jtw_output; tag; log; dry_run; fork; prune_layers; blessed_map } package_arg) 1570 - $ cache_dir_term $ ocaml_version_term $ opam_repository_term $ package_arg $ md_term $ json_term $ dot_term $ with_test_term $ with_doc_term $ with_jtw_term $ doc_tools_repo_term $ doc_tools_branch_term $ jtw_tools_repo_term $ jtw_tools_branch_term $ html_output_term $ jtw_output_term $ log_term $ dry_run_term $ tag_term $ arch_term $ os_term $ os_distribution_term $ os_family_term $ os_version_term $ fork_term $ prune_layers_term $ blessed_map_term) 1583 + run_health_check_multi { dir; ocaml_version; opam_repositories; package = ""; arch; os; os_distribution; os_family; os_version; directory = None; md; json; dot; with_test; with_doc; with_jtw; doc_tools_repo; doc_tools_branch; jtw_tools_repo; jtw_tools_branch; local_repos; html_output; jtw_output; tag; log; dry_run; fork; prune_layers; blessed_map } package_arg) 1584 + $ cache_dir_term $ ocaml_version_term $ opam_repository_term $ package_arg $ md_term $ json_term $ dot_term $ with_test_term $ with_doc_term $ with_jtw_term $ doc_tools_repo_term $ doc_tools_branch_term $ jtw_tools_repo_term $ jtw_tools_branch_term $ local_repo_term $ html_output_term $ jtw_output_term $ log_term $ dry_run_term $ tag_term $ arch_term $ os_term $ os_distribution_term $ os_family_term $ os_version_term $ fork_term $ prune_layers_term $ blessed_map_term) 1571 1585 in 1572 1586 let health_check_info = Cmd.info "health-check" ~doc:"Run health check on a package or list of packages" in 1573 1587 Cmd.v health_check_info health_check_term ··· 1578 1592 const (fun ocaml_version opam_repositories all_versions json arch os os_distribution os_family os_version -> 1579 1593 let ocaml_version = Option.map OpamPackage.of_string ocaml_version in 1580 1594 run_list 1581 - { dir = ""; ocaml_version; opam_repositories; package = ""; arch; os; os_distribution; os_family; os_version; directory = None; md = None; json; dot = None; with_test = false; with_doc = false; with_jtw = false; doc_tools_repo = ""; doc_tools_branch = ""; jtw_tools_repo = ""; jtw_tools_branch = ""; html_output = None; jtw_output = None; tag = None; log = false; dry_run = false; fork = None; prune_layers = false; blessed_map = None } 1595 + { dir = ""; ocaml_version; opam_repositories; package = ""; arch; os; os_distribution; os_family; os_version; directory = None; md = None; json; dot = None; with_test = false; with_doc = false; with_jtw = false; doc_tools_repo = ""; doc_tools_branch = ""; jtw_tools_repo = ""; jtw_tools_branch = ""; local_repos = []; html_output = None; jtw_output = None; tag = None; log = false; dry_run = false; fork = None; prune_layers = false; blessed_map = None } 1582 1596 all_versions) 1583 1597 $ ocaml_version_term $ opam_repository_term $ all_versions_term $ json_term $ arch_term $ os_term $ os_distribution_term $ os_family_term $ os_version_term) 1584 1598 in ··· 1672 1686 in 1673 1687 let batch_term = 1674 1688 Term.( 1675 - const (fun dir ocaml_version opam_repositories package_arg md json dot with_test with_doc with_jtw doc_tools_repo doc_tools_branch jtw_tools_repo jtw_tools_branch html_output jtw_output log dry_run tag arch os os_distribution os_family os_version fork prune_layers -> 1689 + const (fun dir ocaml_version opam_repositories package_arg md json dot with_test with_doc with_jtw doc_tools_repo doc_tools_branch jtw_tools_repo jtw_tools_branch local_repos html_output jtw_output log dry_run tag arch os os_distribution os_family os_version fork prune_layers -> 1676 1690 let ocaml_version = Option.map OpamPackage.of_string ocaml_version in 1677 - run_batch { dir; ocaml_version; opam_repositories; package = ""; arch; os; os_distribution; os_family; os_version; directory = None; md; json; dot; with_test; with_doc; with_jtw; doc_tools_repo; doc_tools_branch; jtw_tools_repo; jtw_tools_branch; html_output; jtw_output; tag; log; dry_run; fork; prune_layers; blessed_map = None } package_arg) 1678 - $ cache_dir_term $ ocaml_version_term $ opam_repository_term $ package_arg $ md_term $ json_term $ dot_term $ with_test_term $ with_doc_term $ with_jtw_term $ doc_tools_repo_term $ doc_tools_branch_term $ jtw_tools_repo_term $ jtw_tools_branch_term $ html_output_term $ jtw_output_term $ log_term $ dry_run_term $ tag_term $ arch_term $ os_term $ os_distribution_term $ os_family_term $ os_version_term $ fork_term $ prune_layers_term) 1691 + run_batch { dir; ocaml_version; opam_repositories; package = ""; arch; os; os_distribution; os_family; os_version; directory = None; md; json; dot; with_test; with_doc; with_jtw; doc_tools_repo; doc_tools_branch; jtw_tools_repo; jtw_tools_branch; local_repos; html_output; jtw_output; tag; log; dry_run; fork; prune_layers; blessed_map = None } package_arg) 1692 + $ cache_dir_term $ ocaml_version_term $ opam_repository_term $ package_arg $ md_term $ json_term $ dot_term $ with_test_term $ with_doc_term $ with_jtw_term $ doc_tools_repo_term $ doc_tools_branch_term $ jtw_tools_repo_term $ jtw_tools_branch_term $ local_repo_term $ html_output_term $ jtw_output_term $ log_term $ dry_run_term $ tag_term $ arch_term $ os_term $ os_distribution_term $ os_family_term $ os_version_term $ fork_term $ prune_layers_term) 1679 1693 in 1680 1694 let batch_info = Cmd.info "batch" ~doc:"Solve all targets, compute blessings, then build with pre-computed blessing maps" in 1681 1695 Cmd.v batch_info batch_term