From f7e24d89a89f5848647b3c97d6ced3714f51f9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Wed, 27 Jul 2022 16:13:34 +0200 Subject: [PATCH 1/5] Generate opam files with Dune, bump to Dune 3.0 --- dockerfile-cmd.opam | 55 +++++++++++++++++++++------ dockerfile-opam.opam | 50 +++++++++++++++++++------ dockerfile.opam | 45 ++++++++++++++++++---- dune-project | 89 ++++++++++++++++++++++++++++++++++++++++++-- src-cmd/dune | 2 +- 5 files changed, 206 insertions(+), 35 deletions(-) diff --git a/dockerfile-cmd.opam b/dockerfile-cmd.opam index 1be93664..06719ce1 100644 --- a/dockerfile-cmd.opam +++ b/dockerfile-cmd.opam @@ -1,32 +1,63 @@ +# This file is generated by dune, edit dune-project instead opam-version: "2.0" -synopsis: "Dockerfile eDSL - generation support" +synopsis: "Dockerfile eDSL -- generation support" description: """ This library provides a typed OCaml interface to generating Dockerfiles programmatically without having to resort to lots of shell scripting and awk/sed-style assembly. This sublibrary has support functions for generating arrays of Dockerfiles -programmatically.""" -maintainer: "Anil Madhavapeddy " -authors: "Anil Madhavapeddy " +programmatically. +""" +maintainer: [ + "Anil Madhavapeddy " + "Antonin Décimo " + "David Allsopp " + "Kate " + "Thomas Leonard " + "Tim McGilchrist " +] +authors: [ + "Anil Madhavapeddy" + "Anton Kochkov" + "Antonin Décimo" + "David Allsopp" + "Ewan Mellor" + "Kate Deplaix" + "Louis Gesbert" + "Mark Elvers" + "Thomas Leonard" + "Tim McGilchrist" +] license: "ISC" tags: ["org:mirage" "org:ocamllabs"] homepage: "https://github.com/ocurrent/ocaml-dockerfile" -doc: "https://ocurrent.github.io/ocaml-dockerfile/doc" +doc: "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile-cmd/" bug-reports: "https://github.com/ocurrent/ocaml-dockerfile/issues" depends: [ - "ocaml" {>= "4.02.3"} - "dune" {>= "2.0.0"} - "dockerfile-opam" {= version} + "dune" {>= "3.0"} + "bos" "cmdliner" - "fmt" + "dockerfile-opam" {= version} + "fmt" {>= "0.8.7"} "logs" - "bos" - "result" "ppx_sexp_conv" {>= "v0.9.0"} + "result" + "sexplib" + "odoc" {with-doc} ] build: [ ["dune" "subst"] {dev} - ["dune" "build" "-p" name "-j" jobs] + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] ] dev-repo: "git+https://github.com/ocurrent/ocaml-dockerfile.git" diff --git a/dockerfile-opam.opam b/dockerfile-opam.opam index c4ef79bf..acdcc0ff 100644 --- a/dockerfile-opam.opam +++ b/dockerfile-opam.opam @@ -1,3 +1,4 @@ +# This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Dockerfile eDSL -- opam support" description: """ @@ -5,31 +6,56 @@ This library provides a typed OCaml interface to generating Dockerfiles programmatically without having to resort to lots of shell scripting and awk/sed-style assembly. -The opam subpackage provides opam and Linux-specific distribution -support for generating dockerfiles.""" -maintainer: "Anil Madhavapeddy " -authors: [ +The opam subpackage provides opam and Linux-specific distribution support +for generating dockerfiles. +""" +maintainer: [ "Anil Madhavapeddy " "Antonin Décimo " + "David Allsopp " + "Kate " + "Thomas Leonard " + "Tim McGilchrist " +] +authors: [ + "Anil Madhavapeddy" + "Anton Kochkov" + "Antonin Décimo" + "David Allsopp" + "Ewan Mellor" + "Kate Deplaix" + "Louis Gesbert" + "Mark Elvers" + "Thomas Leonard" + "Tim McGilchrist" ] license: "ISC" tags: ["org:mirage" "org:ocamllabs"] homepage: "https://github.com/ocurrent/ocaml-dockerfile" -doc: "https://ocurrent.github.io/ocaml-dockerfile/doc" +doc: "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile-opam/" bug-reports: "https://github.com/ocurrent/ocaml-dockerfile/issues" depends: [ - "ocaml" {>= "4.02.3"} - "dune" {>= "2.0.0"} - "dockerfile" {= version} - "ocaml-version" {>= "3.5.0"} - "cmdliner" + "dune" {>= "3.0"} "astring" + "dockerfile" {= version} + "fmt" {>= "0.8.7"} + "ocaml-version" {>= "3.2.0"} "ppx_sexp_conv" {>= "v0.9.0"} "sexplib" - "fmt" + "odoc" {with-doc} ] build: [ ["dune" "subst"] {dev} - ["dune" "build" "-p" name "-j" jobs] + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] ] dev-repo: "git+https://github.com/ocurrent/ocaml-dockerfile.git" diff --git a/dockerfile.opam b/dockerfile.opam index a3510112..abbff2c6 100644 --- a/dockerfile.opam +++ b/dockerfile.opam @@ -1,25 +1,56 @@ +# This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Dockerfile eDSL in OCaml" description: """ This library provides a typed OCaml interface to generating Dockerfiles programmatically without having to resort to lots of shell scripting and -awk/sed-style assembly.""" -maintainer: "Anil Madhavapeddy " -authors: "Anil Madhavapeddy " +awk/sed-style assembly. +""" +maintainer: [ + "Anil Madhavapeddy " + "Antonin Décimo " + "David Allsopp " + "Kate " + "Thomas Leonard " + "Tim McGilchrist " +] +authors: [ + "Anil Madhavapeddy" + "Anton Kochkov" + "Antonin Décimo" + "David Allsopp" + "Ewan Mellor" + "Kate Deplaix" + "Louis Gesbert" + "Mark Elvers" + "Thomas Leonard" + "Tim McGilchrist" +] license: "ISC" tags: ["org:mirage" "org:ocamllabs"] homepage: "https://github.com/ocurrent/ocaml-dockerfile" -doc: "https://ocurrent.github.io/ocaml-dockerfile/doc" +doc: "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile/" bug-reports: "https://github.com/ocurrent/ocaml-dockerfile/issues" depends: [ + "dune" {>= "3.0"} "ocaml" {>= "4.02.3"} - "dune" {>= "2.0.0"} + "fmt" {>= "0.8.7"} "ppx_sexp_conv" {>= "v0.9.0"} "sexplib" - "fmt" + "odoc" {with-doc} ] build: [ ["dune" "subst"] {dev} - ["dune" "build" "-p" name "-j" jobs] + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] ] dev-repo: "git+https://github.com/ocurrent/ocaml-dockerfile.git" diff --git a/dune-project b/dune-project index a1922af3..a232c750 100644 --- a/dune-project +++ b/dune-project @@ -1,5 +1,88 @@ -(lang dune 2.0) - +(lang dune 3.0) (name dockerfile) -(formatting disabled) +(formatting (enabled_for dune)) +(generate_opam_files true) + +(source (github ocurrent/ocaml-dockerfile)) +(license "ISC") + +(authors + "Anil Madhavapeddy" + "Anton Kochkov" + "Antonin Décimo" + "David Allsopp" + "Ewan Mellor" + "Kate Deplaix" + "Louis Gesbert" + "Mark Elvers" + "Thomas Leonard" + "Tim McGilchrist") + +(maintainers + "Anil Madhavapeddy " + "Antonin Décimo " + "David Allsopp " + "Kate " + "Thomas Leonard " + "Tim McGilchrist ") + +(package + (name dockerfile) + (synopsis "Dockerfile eDSL in OCaml") + (description +"\| This library provides a typed OCaml interface to generating Dockerfiles +"\| programmatically without having to resort to lots of shell scripting and +"\| awk/sed-style assembly. + ) + (depends + (ocaml (>= "4.02.3")) + (fmt (>= "0.8.7")) + (ppx_sexp_conv (>= "v0.9.0")) + sexplib) + (documentation "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile/") + (tags ("org:mirage" "org:ocamllabs"))) + +(package + (name dockerfile-cmd) + (synopsis "Dockerfile eDSL -- generation support") + (description +"\| This library provides a typed OCaml interface to generating Dockerfiles +"\| programmatically without having to resort to lots of shell scripting and +"\| awk/sed-style assembly. +"\| +"\| This sublibrary has support functions for generating arrays of Dockerfiles +"\| programmatically. + ) + (depends + bos + cmdliner + (dockerfile-opam (= :version)) + (fmt (>= "0.8.7")) + logs + (ppx_sexp_conv (>= "v0.9.0")) + result + sexplib) + (documentation "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile-cmd/") + (tags ("org:mirage" "org:ocamllabs"))) + +(package + (name dockerfile-opam) + (synopsis "Dockerfile eDSL -- opam support") + (description +"\| This library provides a typed OCaml interface to generating Dockerfiles +"\| programmatically without having to resort to lots of shell scripting and +"\| awk/sed-style assembly. +"\| +"\| The opam subpackage provides opam and Linux-specific distribution support +"\| for generating dockerfiles. + ) + (depends + astring + (dockerfile (= :version)) + (fmt (>= "0.8.7")) + (ocaml-version (>= "3.2.0")) + (ppx_sexp_conv (>= "v0.9.0")) + sexplib) + (documentation "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile-opam/") + (tags ("org:mirage" "org:ocamllabs"))) diff --git a/src-cmd/dune b/src-cmd/dune index bef43bb0..fddb13b0 100644 --- a/src-cmd/dune +++ b/src-cmd/dune @@ -2,7 +2,7 @@ (name dockerfile_cmd) (public_name dockerfile-cmd) (synopsis - "Utility functions to generate Dockerfiles and execute Docker commands") + "Utility functions to generate Dockerfiles and execute Docker commands") (wrapped false) (preprocess (per_module From 898e15dcc2e110a79b2a38450698ae6203d45eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Wed, 27 Jul 2022 16:55:59 +0200 Subject: [PATCH 2/5] Bump to OCaml 4.08, remove deps on result and rresult --- dockerfile-cmd.opam | 1 - dockerfile.opam | 2 +- dune-project | 3 +-- src-cmd/dockerfile_cmd.ml | 29 ++++++++++++++--------------- src-cmd/dockerfile_cmd.mli | 12 +++++------- src-cmd/dockerfile_gen.ml | 6 +++--- src-cmd/dockerfile_gen.mli | 8 ++++---- src-cmd/dune | 2 +- 8 files changed, 29 insertions(+), 34 deletions(-) diff --git a/dockerfile-cmd.opam b/dockerfile-cmd.opam index 06719ce1..482836ff 100644 --- a/dockerfile-cmd.opam +++ b/dockerfile-cmd.opam @@ -42,7 +42,6 @@ depends: [ "fmt" {>= "0.8.7"} "logs" "ppx_sexp_conv" {>= "v0.9.0"} - "result" "sexplib" "odoc" {with-doc} ] diff --git a/dockerfile.opam b/dockerfile.opam index abbff2c6..a3e54ce3 100644 --- a/dockerfile.opam +++ b/dockerfile.opam @@ -33,7 +33,7 @@ doc: "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile/" bug-reports: "https://github.com/ocurrent/ocaml-dockerfile/issues" depends: [ "dune" {>= "3.0"} - "ocaml" {>= "4.02.3"} + "ocaml" {>= "4.08"} "fmt" {>= "0.8.7"} "ppx_sexp_conv" {>= "v0.9.0"} "sexplib" diff --git a/dune-project b/dune-project index a232c750..9321654d 100644 --- a/dune-project +++ b/dune-project @@ -36,7 +36,7 @@ "\| awk/sed-style assembly. ) (depends - (ocaml (>= "4.02.3")) + (ocaml (>= "4.08")) (fmt (>= "0.8.7")) (ppx_sexp_conv (>= "v0.9.0")) sexplib) @@ -61,7 +61,6 @@ (fmt (>= "0.8.7")) logs (ppx_sexp_conv (>= "v0.9.0")) - result sexplib) (documentation "https://ocurrent.github.io/ocaml-dockerfile/doc/dockerfile-cmd/") (tags ("org:mirage" "org:ocamllabs"))) diff --git a/src-cmd/dockerfile_cmd.ml b/src-cmd/dockerfile_cmd.ml index 8c837a62..eccc511a 100644 --- a/src-cmd/dockerfile_cmd.ml +++ b/src-cmd/dockerfile_cmd.ml @@ -16,12 +16,12 @@ *) open Sexplib.Conv -open Rresult open Bos open Astring -open R.Infix module OC = OS.Cmd +let (>>=) = Result.bind + let rec iter fn l = match l with | hd::tl -> fn hd >>= fun () -> iter fn tl @@ -54,9 +54,9 @@ let run_log ?(ok_to_fail=true) ?env log_dir name cmd = let path = Fpath.(log_dir / (name ^ ".sxp")) in OS.File.write path (Sexplib.Sexp.to_string_hum (sexp_of_cmd_log cmd_log)) >>= fun () -> match status with - |`Signaled n -> if ok_to_fail then Ok () else R.error_msg (Fmt.str "Signal %d" n) + |`Signaled n -> if ok_to_fail then Ok () else Fmt.error_msg "Signal %d" n |`Exited 0 -> Ok () - |`Exited code -> if ok_to_fail then Ok () else R.error_msg (Fmt.str "Exit code %d" code) + |`Exited code -> if ok_to_fail then Ok () else Fmt.error_msg "Exit code %d" code (** Docker *) module Docker = struct @@ -64,10 +64,9 @@ module Docker = struct let info = Cmd.(bin % "info") let exists () = - OS.Cmd.run_out info |> OS.Cmd.out_string |> R.is_ok |> - function - | true -> Logs.info (fun l -> l "Docker is running"); true - | false -> Logs.err (fun l -> l "Docker not running"); false + match OS.Cmd.run_out info |> OS.Cmd.out_string with + | Ok _ -> Logs.info (fun l -> l "Docker is running"); true + | Error (`Msg msg) -> Logs.err (fun l -> l "Docker not running: %s" msg); false let build_cmd ?(squash=false) ?(pull=true) ?(cache=true) ?dockerfile ?tag path = let open Cmd in @@ -91,12 +90,12 @@ module Docker = struct | hd::tl when String.is_prefix ~affix:"Successfully tagged " hd -> find_id tl | hd::_ when String.is_prefix ~affix:"Successfully built " hd -> begin match String.cut ~sep:"Successfully built " hd with - | Some ("", id) -> R.ok id - | Some _ -> R.error_msg "Unexpected internal error in build_id" - | None -> R.error_msg "Malformed successfully built log" + | Some ("", id) -> Ok id + | Some _ -> Fmt.error_msg "Unexpected internal error in build_id" + | None -> Fmt.error_msg "Malformed successfully built log" end - | _hd::_tl -> R.error_msg "Unexpected lines at end of log" - | [] -> R.error_msg "Unable to find container id in log" in + | _hd::_tl -> Fmt.error_msg "Unexpected lines at end of log" + | [] -> Fmt.error_msg "Unable to find container id in log" in OS.File.read_lines log >>= fun lines -> List.rev lines |> fun lines -> find_id lines @@ -125,8 +124,8 @@ module Opam = struct OS.Env.current () >>= fun env -> String.Map.add "OPAMROOT" (Cmd.p root) env |> String.Map.add "OPAMYES" "1" |> - String.Map.add "OPAMJOBS" (string_of_int jobs) |> fun env -> - R.return env + String.Map.add "OPAMJOBS" (string_of_int jobs) |> + Result.ok end open Cmdliner diff --git a/src-cmd/dockerfile_cmd.mli b/src-cmd/dockerfile_cmd.mli index 1e6522fa..99224936 100644 --- a/src-cmd/dockerfile_cmd.mli +++ b/src-cmd/dockerfile_cmd.mli @@ -35,8 +35,8 @@ val run_log : ?ok_to_fail:bool -> ?env:Bos.OS.Env.t -> Fpath.t -> - string -> Bos.Cmd.t -> (unit, [> Rresult.R.msg ]) result -(** [runlog log_dir name cmd] will run [cmd] with label [name] + string -> Bos.Cmd.t -> (unit, [> `Msg of string ]) result +(** [runlog log_dir name cmd] will run [cmd] with label [name] and log the results in [/.sxp]. *) (** Docker command invocation *) @@ -57,7 +57,7 @@ module Docker : sig val push_cmd : string -> Bos.Cmd.t - val build_id : Fpath.t -> (string, [> Rresult.R.msg ]) result + val build_id : Fpath.t -> (string, [> `Msg of string ]) result val run_cmd : ?mounts:(string * string) list -> @@ -77,17 +77,15 @@ module Opam : sig val opam_env : root:Fpath.t -> - jobs:int -> (string Astring.String.map, [> Rresult.R.msg ]) result + jobs:int -> (string Astring.String.map, [> `Msg of string ]) result end (** {2 Utility functions} *) -val setup_logs : unit -> unit Cmdliner.Term.t +val setup_logs : unit -> unit Cmdliner.Term.t (** [setup_logs ()] initialises a {!Logs} environment. *) val iter : ('a -> (unit, 'b) result) -> 'a list -> (unit, 'b) result val map : ('a -> ('b, 'c) result) -> 'a list -> ('b list, 'c) result - - diff --git a/src-cmd/dockerfile_gen.ml b/src-cmd/dockerfile_gen.ml index 46a6091e..ccd4428a 100644 --- a/src-cmd/dockerfile_gen.ml +++ b/src-cmd/dockerfile_gen.ml @@ -17,10 +17,10 @@ open Dockerfile open Bos -open Rresult -open R.Infix module U = Dockerfile_cmd +let (>>=) = Result.bind + let write_dockerfile ~crunch file dfile = Logs.debug (fun l -> l "Writing Dockerfile to %a" Fpath.pp file); (if crunch then Dockerfile.crunch dfile else dfile) |> @@ -34,7 +34,7 @@ let generate_dockerfile ?(fname="Dockerfile") ?(crunch=true) output_dir d = let generate_dockerfiles_in_directories ?(crunch=true) output_dir = U.iter (fun (name, dockerfile) -> - let dir = Fpath.(output_dir / name) in + let dir = Fpath.(output_dir / name) in let file = Fpath.(dir / "Dockerfile") in Logs.info (fun l -> l "Generating %a" Fpath.pp file); OS.Dir.create ~path:true output_dir >>= fun _ -> diff --git a/src-cmd/dockerfile_gen.mli b/src-cmd/dockerfile_gen.mli index 4056b6ed..2ffdb356 100644 --- a/src-cmd/dockerfile_gen.mli +++ b/src-cmd/dockerfile_gen.mli @@ -15,7 +15,7 @@ * *) -val generate_dockerfile : ?fname:string -> ?crunch:bool -> Fpath.t -> Dockerfile.t -> (unit, [> Rresult.R.msg ]) Result.result +val generate_dockerfile : ?fname:string -> ?crunch:bool -> Fpath.t -> Dockerfile.t -> (unit, [> `Msg of string ]) result (** [generate_dockerfile output_dir docker] will output Dockerfile inside the [output_dir] subdirectory. @@ -24,7 +24,7 @@ val generate_dockerfile : ?fname:string -> ?crunch:bool -> Fpath.t -> Dockerfile more layers. *) val generate_dockerfiles : ?crunch:bool -> Fpath.t -> - (string * Dockerfile.t) list -> (unit, [> Rresult.R.msg ]) Result.result + (string * Dockerfile.t) list -> (unit, [> `Msg of string ]) result (** [generate_dockerfiles output_dir (name * docker)] will output a list of Dockerfiles inside the [output_dir/] subdirectory, with each Dockerfile named as [Dockerfile.]. @@ -34,7 +34,7 @@ val generate_dockerfiles : ?crunch:bool -> Fpath.t -> more layers. *) val generate_dockerfiles_in_directories : ?crunch:bool -> Fpath.t -> - (string * Dockerfile.t) list -> (unit, [> Rresult.R.msg ]) Result.result + (string * Dockerfile.t) list -> (unit, [> `Msg of string ]) result (** [generate_dockerfiles_in_directories output_dir (name * docker)] will output a list of Dockerfiles inside the [output_dir/name] subdirectory, with each directory containing the Dockerfile specified by [docker]. @@ -44,7 +44,7 @@ val generate_dockerfiles_in_directories : ?crunch:bool -> Fpath.t -> more layers. *) val generate_dockerfiles_in_git_branches : ?readme:string -> ?crunch:bool -> - Fpath.t -> (string * Dockerfile.t) list -> (unit, [> Rresult.R.msg ]) Result.result + Fpath.t -> (string * Dockerfile.t) list -> (unit, [> `Msg of string ]) result (** [generate_dockerfiles_in_git_branches output_dir (name * docker)] will output a set of git branches in the [output_dir] Git repository. Each branch will be named [name] and contain a single [docker] file. diff --git a/src-cmd/dune b/src-cmd/dune index fddb13b0..e395b951 100644 --- a/src-cmd/dune +++ b/src-cmd/dune @@ -8,4 +8,4 @@ (per_module ((pps ppx_sexp_conv) dockerfile_cmd))) - (libraries dockerfile cmdliner bos fmt.tty logs.cli fmt.cli logs.fmt result)) + (libraries dockerfile cmdliner bos fmt.tty logs.cli fmt.cli logs.fmt)) From 9fac581c7abf6c6a860aae9b6a6da1f598f6c09c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Fri, 23 Sep 2022 18:26:43 +0200 Subject: [PATCH 3/5] Apply ocamlformat.0.24.1 --- .ocamlformat | 3 + dune-project | 1 - src-cmd/dockerfile_cmd.ml | 140 +-- src-cmd/dockerfile_cmd.mli | 37 +- src-cmd/dockerfile_gen.ml | 75 +- src-cmd/dockerfile_gen.mli | 29 +- src-opam/dockerfile_distro.ml | 1513 ++++++++++++++++++------------- src-opam/dockerfile_distro.mli | 191 +++- src-opam/dockerfile_linux.ml | 247 ++--- src-opam/dockerfile_opam.ml | 538 ++++++----- src-opam/dockerfile_opam.mli | 23 +- src-opam/dockerfile_windows.ml | 299 ++++-- src-opam/dockerfile_windows.mli | 41 +- src/dockerfile.ml | 200 ++-- src/dockerfile.mli | 34 +- 15 files changed, 2015 insertions(+), 1356 deletions(-) create mode 100644 .ocamlformat diff --git a/.ocamlformat b/.ocamlformat new file mode 100644 index 00000000..82c2e515 --- /dev/null +++ b/.ocamlformat @@ -0,0 +1,3 @@ +profile = conventional +version = 0.24.1 +ocaml-version = 4.08 diff --git a/dune-project b/dune-project index 9321654d..a7107086 100644 --- a/dune-project +++ b/dune-project @@ -1,7 +1,6 @@ (lang dune 3.0) (name dockerfile) -(formatting (enabled_for dune)) (generate_opam_files true) (source (github ocurrent/ocaml-dockerfile)) diff --git a/src-cmd/dockerfile_cmd.ml b/src-cmd/dockerfile_cmd.ml index eccc511a..105d9401 100644 --- a/src-cmd/dockerfile_cmd.ml +++ b/src-cmd/dockerfile_cmd.ml @@ -20,43 +20,46 @@ open Bos open Astring module OC = OS.Cmd -let (>>=) = Result.bind +let ( >>= ) = Result.bind let rec iter fn l = - match l with - | hd::tl -> fn hd >>= fun () -> iter fn tl - | [] -> Ok () + match l with hd :: tl -> fn hd >>= fun () -> iter fn tl | [] -> Ok () let map fn l = - List.map fn l |> - List.fold_left (fun acc b -> - match acc, b with - | Ok acc, Ok v -> Ok (v :: acc) - | Ok _acc, Error v -> Error v - | Error _ as e, _ -> e - ) (Ok []) |> function + List.map fn l + |> List.fold_left + (fun acc b -> + match (acc, b) with + | Ok acc, Ok v -> Ok (v :: acc) + | Ok _acc, Error v -> Error v + | (Error _ as e), _ -> e) + (Ok []) + |> function | Ok v -> Ok (List.rev v) | e -> e type cmd_log = { - command: string; - stdout: string; - success: bool; - status: [ `Signaled of int | `Exited of int ] -} [@@deriving sexp] - -let run_log ?(ok_to_fail=true) ?env log_dir name cmd = + command : string; + stdout : string; + success : bool; + status : [ `Signaled of int | `Exited of int ]; +} +[@@deriving sexp] + +let run_log ?(ok_to_fail = true) ?env log_dir name cmd = let command = Cmd.to_string cmd in - OS.Cmd.(run_out ?env ~err:err_run_out) cmd |> - OS.Cmd.out_string >>= fun (stdout, (_,status)) -> + OS.Cmd.(run_out ?env ~err:err_run_out) cmd |> OS.Cmd.out_string + >>= fun (stdout, (_, status)) -> let success = status = `Exited 0 in let cmd_log = { command; stdout; success; status } in let path = Fpath.(log_dir / (name ^ ".sxp")) in - OS.File.write path (Sexplib.Sexp.to_string_hum (sexp_of_cmd_log cmd_log)) >>= fun () -> + OS.File.write path (Sexplib.Sexp.to_string_hum (sexp_of_cmd_log cmd_log)) + >>= fun () -> match status with - |`Signaled n -> if ok_to_fail then Ok () else Fmt.error_msg "Signal %d" n - |`Exited 0 -> Ok () - |`Exited code -> if ok_to_fail then Ok () else Fmt.error_msg "Exit code %d" code + | `Signaled n -> if ok_to_fail then Ok () else Fmt.error_msg "Signal %d" n + | `Exited 0 -> Ok () + | `Exited code -> + if ok_to_fail then Ok () else Fmt.error_msg "Exit code %d" code (** Docker *) module Docker = struct @@ -65,54 +68,68 @@ module Docker = struct let exists () = match OS.Cmd.run_out info |> OS.Cmd.out_string with - | Ok _ -> Logs.info (fun l -> l "Docker is running"); true - | Error (`Msg msg) -> Logs.err (fun l -> l "Docker not running: %s" msg); false - - let build_cmd ?(squash=false) ?(pull=true) ?(cache=true) ?dockerfile ?tag path = + | Ok _ -> + Logs.info (fun l -> l "Docker is running"); + true + | Error (`Msg msg) -> + Logs.err (fun l -> l "Docker not running: %s" msg); + false + + let build_cmd ?(squash = false) ?(pull = true) ?(cache = true) ?dockerfile + ?tag path = let open Cmd in let cache = if cache then empty else v "--no-cache" in let pull = if pull then v "--pull" else empty in let squash = if squash then v "--squash" else empty in - let dfile = match dockerfile with None -> empty | Some d -> v "-f" % p d in + let dfile = + match dockerfile with None -> empty | Some d -> v "-f" % p d + in let tag = match tag with None -> empty | Some t -> v "-t" % t in - bin % "build" %% tag %% cache %% pull %% squash %% dfile % p path + bin % "build" %% tag %% cache %% pull %% squash %% dfile % p path - let volume_cmd = - Cmd.(bin % "volume") - - let push_cmd tag = - Cmd.(bin % "push" % tag) + let volume_cmd = Cmd.(bin % "volume") + let push_cmd tag = Cmd.(bin % "push" % tag) (* Find the image id that we just built *) let build_id log = - let rec find_id = - function - | hd::tl when String.is_prefix ~affix:"Successfully tagged " hd -> find_id tl - | hd::_ when String.is_prefix ~affix:"Successfully built " hd -> begin - match String.cut ~sep:"Successfully built " hd with - | Some ("", id) -> Ok id - | Some _ -> Fmt.error_msg "Unexpected internal error in build_id" - | None -> Fmt.error_msg "Malformed successfully built log" - end - | _hd::_tl -> Fmt.error_msg "Unexpected lines at end of log" - | [] -> Fmt.error_msg "Unable to find container id in log" in + let rec find_id = function + | hd :: tl when String.is_prefix ~affix:"Successfully tagged " hd -> + find_id tl + | hd :: _ when String.is_prefix ~affix:"Successfully built " hd -> ( + match String.cut ~sep:"Successfully built " hd with + | Some ("", id) -> Ok id + | Some _ -> Fmt.error_msg "Unexpected internal error in build_id" + | None -> Fmt.error_msg "Malformed successfully built log") + | _hd :: _tl -> Fmt.error_msg "Unexpected lines at end of log" + | [] -> Fmt.error_msg "Unable to find container id in log" + in OS.File.read_lines log >>= fun lines -> - List.rev lines |> fun lines -> - find_id lines + List.rev lines |> fun lines -> find_id lines let manifest_push_cli ~platforms ~template ~target = let platforms = String.concat ~sep:"," platforms in - Cmd.(v "manifest-tool" % "push" % "from-args" % "--platforms" % platforms - % "--template" % template % "--target" % target) + Cmd.( + v "manifest-tool" % "push" % "from-args" % "--platforms" % platforms + % "--template" % template % "--target" % target) let manifest_push_file file = - Cmd.(v "manifest-tool" % "push" % "from-spec" % p file) + Cmd.(v "manifest-tool" % "push" % "from-spec" % p file) - let run_cmd ?(mounts=[]) ?(volumes=[]) ?(rm=true) img cmd = + let run_cmd ?(mounts = []) ?(volumes = []) ?(rm = true) img cmd = let rm = if rm then Cmd.(v "--rm") else Cmd.empty in - let mounts = List.map (fun (src,dst) -> ["--mount"; Printf.sprintf "source=%s,destination=%s" src dst]) mounts |> List.flatten |> Cmd.of_list in + let mounts = + List.map + (fun (src, dst) -> + [ "--mount"; Printf.sprintf "source=%s,destination=%s" src dst ]) + mounts + |> List.flatten |> Cmd.of_list + in let vols = - List.map (fun (src,dst) -> ["-v"; Printf.sprintf "%s:%s" src dst]) volumes |> List.flatten |> Cmd.of_list in + List.map + (fun (src, dst) -> [ "-v"; Printf.sprintf "%s:%s" src dst ]) + volumes + |> List.flatten |> Cmd.of_list + in Cmd.(bin % "run" %% rm %% mounts %% vols % img %% cmd) end @@ -122,19 +139,22 @@ module Opam = struct let opam_env ~root ~jobs = OS.Env.current () >>= fun env -> - String.Map.add "OPAMROOT" (Cmd.p root) env |> - String.Map.add "OPAMYES" "1" |> - String.Map.add "OPAMJOBS" (string_of_int jobs) |> - Result.ok + String.Map.add "OPAMROOT" (Cmd.p root) env + |> String.Map.add "OPAMYES" "1" + |> String.Map.add "OPAMJOBS" (string_of_int jobs) + |> Result.ok end open Cmdliner + let setup_logs () = let setup_log style_renderer level = Fmt_tty.setup_std_outputs ?style_renderer (); Logs.set_level level; - Logs.set_reporter (Logs_fmt.reporter ()) in + Logs.set_reporter (Logs_fmt.reporter ()) + in let global_option_section = "COMMON OPTIONS" in - Term.(const setup_log + Term.( + const setup_log $ Fmt_cli.style_renderer ~docs:global_option_section () $ Logs_cli.level ~docs:global_option_section ()) diff --git a/src-cmd/dockerfile_cmd.mli b/src-cmd/dockerfile_cmd.mli index 99224936..f12291fb 100644 --- a/src-cmd/dockerfile_cmd.mli +++ b/src-cmd/dockerfile_cmd.mli @@ -24,49 +24,53 @@ Feel free to contribute more functions if you need them. *) type cmd_log = { - command: string; - stdout: string; - success: bool; - status: [ `Signaled of int | `Exited of int ] -} [@@deriving sexp] + command : string; + stdout : string; + success : bool; + status : [ `Signaled of int | `Exited of int ]; +} +[@@deriving sexp] (** Results of a command invocation *) val run_log : ?ok_to_fail:bool -> ?env:Bos.OS.Env.t -> Fpath.t -> - string -> Bos.Cmd.t -> (unit, [> `Msg of string ]) result + string -> + Bos.Cmd.t -> + (unit, [> `Msg of string ]) result (** [runlog log_dir name cmd] will run [cmd] with label [name] and log the results in [/.sxp]. *) (** Docker command invocation *) module Docker : sig val bin : Bos.Cmd.t - val info : Bos.Cmd.t - val exists : unit -> bool val build_cmd : ?squash:bool -> ?pull:bool -> ?cache:bool -> - ?dockerfile:Fpath.t -> ?tag:string -> Fpath.t -> Bos.Cmd.t + ?dockerfile:Fpath.t -> + ?tag:string -> + Fpath.t -> + Bos.Cmd.t val volume_cmd : Bos.Cmd.t - val push_cmd : string -> Bos.Cmd.t - val build_id : Fpath.t -> (string, [> `Msg of string ]) result val run_cmd : ?mounts:(string * string) list -> ?volumes:(string * string) list -> - ?rm:bool -> string -> Bos.Cmd.t -> Bos.Cmd.t + ?rm:bool -> + string -> + Bos.Cmd.t -> + Bos.Cmd.t val manifest_push_cli : - platforms:string list -> - template:string -> target:string -> Bos.Cmd.t + platforms:string list -> template:string -> target:string -> Bos.Cmd.t val manifest_push_file : Fpath.t -> Bos.Cmd.t end @@ -77,8 +81,8 @@ module Opam : sig val opam_env : root:Fpath.t -> - jobs:int -> (string Astring.String.map, [> `Msg of string ]) result - + jobs:int -> + (string Astring.String.map, [> `Msg of string ]) result end (** {2 Utility functions} *) @@ -87,5 +91,4 @@ val setup_logs : unit -> unit Cmdliner.Term.t (** [setup_logs ()] initialises a {!Logs} environment. *) val iter : ('a -> (unit, 'b) result) -> 'a list -> (unit, 'b) result - val map : ('a -> ('b, 'c) result) -> 'a list -> ('b list, 'c) result diff --git a/src-cmd/dockerfile_gen.ml b/src-cmd/dockerfile_gen.ml index ccd4428a..a1487157 100644 --- a/src-cmd/dockerfile_gen.ml +++ b/src-cmd/dockerfile_gen.ml @@ -19,55 +19,56 @@ open Dockerfile open Bos module U = Dockerfile_cmd -let (>>=) = Result.bind +let ( >>= ) = Result.bind let write_dockerfile ~crunch file dfile = Logs.debug (fun l -> l "Writing Dockerfile to %a" Fpath.pp file); - (if crunch then Dockerfile.crunch dfile else dfile) |> - string_of_t |> OS.File.write file + (if crunch then Dockerfile.crunch dfile else dfile) + |> string_of_t |> OS.File.write file -let generate_dockerfile ?(fname="Dockerfile") ?(crunch=true) output_dir d = +let generate_dockerfile ?(fname = "Dockerfile") ?(crunch = true) output_dir d = let file = Fpath.(output_dir / fname) in Logs.info (fun l -> l "Generating: %a" Fpath.pp file); OS.Dir.create ~path:true output_dir >>= fun _ -> write_dockerfile ~crunch file d -let generate_dockerfiles_in_directories ?(crunch=true) output_dir = +let generate_dockerfiles_in_directories ?(crunch = true) output_dir = U.iter (fun (name, dockerfile) -> - let dir = Fpath.(output_dir / name) in - let file = Fpath.(dir / "Dockerfile") in - Logs.info (fun l -> l "Generating %a" Fpath.pp file); - OS.Dir.create ~path:true output_dir >>= fun _ -> - write_dockerfile ~crunch file dockerfile - ) + let dir = Fpath.(output_dir / name) in + let file = Fpath.(dir / "Dockerfile") in + Logs.info (fun l -> l "Generating %a" Fpath.pp file); + OS.Dir.create ~path:true output_dir >>= fun _ -> + write_dockerfile ~crunch file dockerfile) -let generate_dockerfiles ?(crunch=true) output_dir = +let generate_dockerfiles ?(crunch = true) output_dir = U.iter (fun (name, dockerfile) -> - let file = Fpath.(output_dir / ("Dockerfile." ^ name)) in - Logs.info (fun l -> l "Generating: %a" Fpath.pp file); - write_dockerfile ~crunch file dockerfile - ) + let file = Fpath.(output_dir / ("Dockerfile." ^ name)) in + Logs.info (fun l -> l "Generating: %a" Fpath.pp file); + write_dockerfile ~crunch file dockerfile) -let generate_dockerfiles_in_git_branches ?readme ?(crunch=true) output_dir d = +let generate_dockerfiles_in_git_branches ?readme ?(crunch = true) output_dir d = (* TODO move git to dockerfile_cmd *) let git = Cmd.(v "git" % "-C" % p output_dir) in - U.iter (fun (name, docker) -> - Logs.info (fun l -> l "Switching to branch %s in %a\n%!" name Fpath.pp output_dir); - OS.Cmd.run (match name with - | "master" -> Cmd.(git % "checkout" % "master") - | name -> Cmd.(git % "checkout" % "-q" % "-B" % name % "master") - ) >>= fun () -> - let file = Fpath.(output_dir / "Dockerfile") in - write_dockerfile ~crunch file docker >>= fun () -> - begin match readme with - | None -> Ok () - | Some r -> - OS.File.write Fpath.(output_dir / "README.md") r >>= fun () -> - Cmd.(git % "add" % "README.md") |> OS.Cmd.run - end >>= fun () -> - Cmd.(git % "add" % "Dockerfile") |> OS.Cmd.run >>= fun () -> - let msg = Fmt.str "update %s Dockerfile" name in - Cmd.(git % "commit" % "-q" % "-m" % msg % "-a") |> OS.Cmd.run_status >>= fun _ -> - Ok () - ) d >>= fun () -> - Cmd.(git % "checkout" % "-q" % "master") |> OS.Cmd.run + U.iter + (fun (name, docker) -> + Logs.info (fun l -> + l "Switching to branch %s in %a\n%!" name Fpath.pp output_dir); + OS.Cmd.run + (match name with + | "master" -> Cmd.(git % "checkout" % "master") + | name -> Cmd.(git % "checkout" % "-q" % "-B" % name % "master")) + >>= fun () -> + let file = Fpath.(output_dir / "Dockerfile") in + write_dockerfile ~crunch file docker >>= fun () -> + (match readme with + | None -> Ok () + | Some r -> + OS.File.write Fpath.(output_dir / "README.md") r >>= fun () -> + Cmd.(git % "add" % "README.md") |> OS.Cmd.run) + >>= fun () -> + Cmd.(git % "add" % "Dockerfile") |> OS.Cmd.run >>= fun () -> + let msg = Fmt.str "update %s Dockerfile" name in + Cmd.(git % "commit" % "-q" % "-m" % msg % "-a") |> OS.Cmd.run_status + >>= fun _ -> Ok ()) + d + >>= fun () -> Cmd.(git % "checkout" % "-q" % "master") |> OS.Cmd.run diff --git a/src-cmd/dockerfile_gen.mli b/src-cmd/dockerfile_gen.mli index 2ffdb356..1659b0ff 100644 --- a/src-cmd/dockerfile_gen.mli +++ b/src-cmd/dockerfile_gen.mli @@ -15,7 +15,12 @@ * *) -val generate_dockerfile : ?fname:string -> ?crunch:bool -> Fpath.t -> Dockerfile.t -> (unit, [> `Msg of string ]) result +val generate_dockerfile : + ?fname:string -> + ?crunch:bool -> + Fpath.t -> + Dockerfile.t -> + (unit, [> `Msg of string ]) result (** [generate_dockerfile output_dir docker] will output Dockerfile inside the [output_dir] subdirectory. @@ -23,8 +28,11 @@ val generate_dockerfile : ?fname:string -> ?crunch:bool -> Fpath.t -> Dockerfile optimisation to reduce the number of layers; disable it if you really want more layers. *) -val generate_dockerfiles : ?crunch:bool -> Fpath.t -> - (string * Dockerfile.t) list -> (unit, [> `Msg of string ]) result +val generate_dockerfiles : + ?crunch:bool -> + Fpath.t -> + (string * Dockerfile.t) list -> + (unit, [> `Msg of string ]) result (** [generate_dockerfiles output_dir (name * docker)] will output a list of Dockerfiles inside the [output_dir/] subdirectory, with each Dockerfile named as [Dockerfile.]. @@ -33,8 +41,11 @@ val generate_dockerfiles : ?crunch:bool -> Fpath.t -> optimisation to reduce the number of layers; disable it if you really want more layers. *) -val generate_dockerfiles_in_directories : ?crunch:bool -> Fpath.t -> - (string * Dockerfile.t) list -> (unit, [> `Msg of string ]) result +val generate_dockerfiles_in_directories : + ?crunch:bool -> + Fpath.t -> + (string * Dockerfile.t) list -> + (unit, [> `Msg of string ]) result (** [generate_dockerfiles_in_directories output_dir (name * docker)] will output a list of Dockerfiles inside the [output_dir/name] subdirectory, with each directory containing the Dockerfile specified by [docker]. @@ -43,8 +54,12 @@ val generate_dockerfiles_in_directories : ?crunch:bool -> Fpath.t -> optimisation to reduce the number of layers; disable it if you really want more layers. *) -val generate_dockerfiles_in_git_branches : ?readme:string -> ?crunch:bool -> - Fpath.t -> (string * Dockerfile.t) list -> (unit, [> `Msg of string ]) result +val generate_dockerfiles_in_git_branches : + ?readme:string -> + ?crunch:bool -> + Fpath.t -> + (string * Dockerfile.t) list -> + (unit, [> `Msg of string ]) result (** [generate_dockerfiles_in_git_branches output_dir (name * docker)] will output a set of git branches in the [output_dir] Git repository. Each branch will be named [name] and contain a single [docker] file. diff --git a/src-opam/dockerfile_distro.ml b/src-opam/dockerfile_distro.ml index 8b45754a..7bdae73e 100644 --- a/src-opam/dockerfile_distro.ml +++ b/src-opam/dockerfile_distro.ml @@ -15,21 +15,32 @@ * *) -(** Distro selection for various OPAM combinations *) open Astring -open Sexplib.Conv - -type win10_release = [ - | `V1507 | `V1511 | `V1607 | `V1703 | `V1709 | `V1803 | `V1809 - | `V1903 | `V1909 | `V2004 | `V20H2 | `V21H1 | `V21H2 -] [@@deriving sexp] +(** Distro selection for various OPAM combinations *) -type win10_ltsc = [ - `Ltsc2015 | `Ltsc2016 | `Ltsc2019 | `Ltsc2022 -] [@@deriving sexp] +open Sexplib.Conv -type win10_lcu = [ - | `LCU +type win10_release = + [ `V1507 + | `V1511 + | `V1607 + | `V1703 + | `V1709 + | `V1803 + | `V1809 + | `V1903 + | `V1909 + | `V2004 + | `V20H2 + | `V21H1 + | `V21H2 ] +[@@deriving sexp] + +type win10_ltsc = [ `Ltsc2015 | `Ltsc2016 | `Ltsc2019 | `Ltsc2022 ] +[@@deriving sexp] + +type win10_lcu = + [ `LCU | `LCU20220913 | `LCU20220809 | `LCU20220712 @@ -45,8 +56,8 @@ type win10_lcu = [ | `LCU20210914 | `LCU20210810 | `LCU20210713 - | `LCU20210608 -] [@@deriving sexp] + | `LCU20210608 ] +[@@deriving sexp] type win_all = [ win10_release | win10_ltsc ] [@@deriving sexp] @@ -54,178 +65,266 @@ let win10_current_lcu = `LCU20220913 type win10_revision = win10_release * win10_lcu option [@@deriving sexp] -let win10_lcus : ('a * int * win10_release list) list = [ - - `LCU20220913, 5017316, [`V21H2]; - `LCU20220913, 5017308, [`V21H1]; - `LCU20220913, 5017315, [`V1809]; - `LCU20220913, 5017305, [`V1607]; - `LCU20220913, 5017327, [`V1507]; - - `LCU20220809, 5016627, [`V21H2]; - `LCU20220809, 5016616, [`V20H2; `V21H1]; - `LCU20220809, 5016623, [`V1809]; - `LCU20220809, 5016622, [`V1607]; - `LCU20220809, 5016639, [`V1507]; - - `LCU20220712, 5015827, [`V21H2]; - `LCU20220712, 5015807, [`V20H2; `V21H1]; - `LCU20220712, 5015811, [`V1809]; - `LCU20220712, 5015808, [`V1607]; - `LCU20220712, 5015832, [`V1507]; - - `LCU20220614, 5014678, [`V21H2]; - `LCU20220614, 5014699, [`V20H2; `V21H1]; - `LCU20220614, 5014692, [`V1809]; - `LCU20220614, 5014702, [`V1607]; - `LCU20220614, 5014710, [`V1507]; - - `LCU20220510, 5013944, [`V21H2]; - `LCU20220510, 5013942, [`V20H2; `V21H1]; - `LCU20220510, 5013945, [`V1909]; - `LCU20220510, 5013941, [`V1809]; - `LCU20220510, 5013952, [`V1607]; - `LCU20220510, 5013963, [`V1507]; - - `LCU20220412, 5012604, [`V21H2]; - `LCU20220412, 5012599, [`V20H2; `V21H1]; - `LCU20220412, 5012591, [`V1909]; - `LCU20220412, 5012647, [`V1809]; - `LCU20220412, 5012596, [`V1607]; - `LCU20220412, 5012653, [`V1507]; - - `LCU20220308, 5011497, [`V21H2]; - `LCU20220308, 5011487, [`V20H2; `V21H1]; - `LCU20220308, 5011485, [`V1909]; - `LCU20220308, 5011503, [`V1809]; - `LCU20220308, 5011495, [`V1607]; - `LCU20220308, 5011491, [`V1507]; - - `LCU20220208, 5010354, [`V21H2]; - `LCU20220208, 5010342, [`V20H2; `V21H1]; - `LCU20220208, 5010345, [`V1909]; - `LCU20220208, 5010351, [`V1809]; - `LCU20220208, 5010359, [`V1607]; - `LCU20220208, 5010358, [`V1507]; - - `LCU20220111, 5009555, [`V21H2]; - `LCU20220111, 5009543, [`V20H2; `V21H1]; - `LCU20220111, 5009545, [`V1909]; - `LCU20220111, 5009557, [`V1809]; - `LCU20220111, 5009546, [`V1607]; - `LCU20220111, 5009585, [`V1507]; - - `LCU20211214, 5008223, [`V21H2]; - `LCU20211214, 5008212, [`V2004; `V20H2; `V21H1]; - `LCU20211214, 5008206, [`V1909]; - `LCU20211214, 5008218, [`V1809]; - `LCU20211214, 5008207, [`V1607]; - `LCU20211214, 5008230, [`V1507]; - - `LCU20211109, 5007205, [`V21H2]; - `LCU20211109, 5007186, [`V2004; `V20H2; `V21H1]; - `LCU20211109, 5007189, [`V1909]; - `LCU20211109, 5007206, [`V1809]; - `LCU20211109, 5007192, [`V1607]; - `LCU20211109, 5007207, [`V1507]; - - `LCU20211012, 5006699, [`V21H2]; - `LCU20211012, 5006670, [`V2004; `V20H2; `V21H1]; - `LCU20211012, 5006667, [`V1909]; - `LCU20211012, 5006672, [`V1809]; - `LCU20211012, 5006669, [`V1607]; - `LCU20211012, 5006675, [`V1507]; - `LCU20210914, 5005575, [`V21H2]; - `LCU20210914, 5005565, [`V2004; `V20H2; `V21H1]; - `LCU20210914, 5005566, [`V1909]; - `LCU20210914, 5005568, [`V1809]; - `LCU20210914, 5005573, [`V1607]; - `LCU20210914, 5005569, [`V1507]; - `LCU20210810, 5005039, [`V21H2]; - `LCU20210810, 5005033, [`V2004; `V20H2; `V21H1]; - `LCU20210810, 5005031, [`V1909]; - `LCU20210810, 5005030, [`V1809]; - `LCU20210810, 5005043, [`V1607]; - `LCU20210810, 5005040, [`V1507]; - `LCU20210713, 5004237, [`V2004; `V20H2; `V21H1]; - `LCU20210713, 5004245, [`V1909]; - `LCU20210713, 5004244, [`V1809]; - `LCU20210713, 5004238, [`V1607]; - `LCU20210713, 5004249, [`V1507]; - `LCU20210608, 5003637, [`V2004; `V20H2; `V21H1]; - `LCU20210608, 5003635, [`V1909]; - `LCU20210608, 5003646, [`V1809]; - `LCU20210608, 5003638, [`V1607]; - `LCU20210608, 5003687, [`V1507]; -] - -let win10_lcu_to_kb : ((win10_lcu * win10_release), int option) Hashtbl.t = +let win10_lcus : ('a * int * win10_release list) list = + [ + (`LCU20220913, 5017316, [ `V21H2 ]); + (`LCU20220913, 5017308, [ `V21H1 ]); + (`LCU20220913, 5017315, [ `V1809 ]); + (`LCU20220913, 5017305, [ `V1607 ]); + (`LCU20220913, 5017327, [ `V1507 ]); + (`LCU20220809, 5016627, [ `V21H2 ]); + (`LCU20220809, 5016616, [ `V20H2; `V21H1 ]); + (`LCU20220809, 5016623, [ `V1809 ]); + (`LCU20220809, 5016622, [ `V1607 ]); + (`LCU20220809, 5016639, [ `V1507 ]); + (`LCU20220712, 5015827, [ `V21H2 ]); + (`LCU20220712, 5015807, [ `V20H2; `V21H1 ]); + (`LCU20220712, 5015811, [ `V1809 ]); + (`LCU20220712, 5015808, [ `V1607 ]); + (`LCU20220712, 5015832, [ `V1507 ]); + (`LCU20220614, 5014678, [ `V21H2 ]); + (`LCU20220614, 5014699, [ `V20H2; `V21H1 ]); + (`LCU20220614, 5014692, [ `V1809 ]); + (`LCU20220614, 5014702, [ `V1607 ]); + (`LCU20220614, 5014710, [ `V1507 ]); + (`LCU20220510, 5013944, [ `V21H2 ]); + (`LCU20220510, 5013942, [ `V20H2; `V21H1 ]); + (`LCU20220510, 5013945, [ `V1909 ]); + (`LCU20220510, 5013941, [ `V1809 ]); + (`LCU20220510, 5013952, [ `V1607 ]); + (`LCU20220510, 5013963, [ `V1507 ]); + (`LCU20220412, 5012604, [ `V21H2 ]); + (`LCU20220412, 5012599, [ `V20H2; `V21H1 ]); + (`LCU20220412, 5012591, [ `V1909 ]); + (`LCU20220412, 5012647, [ `V1809 ]); + (`LCU20220412, 5012596, [ `V1607 ]); + (`LCU20220412, 5012653, [ `V1507 ]); + (`LCU20220308, 5011497, [ `V21H2 ]); + (`LCU20220308, 5011487, [ `V20H2; `V21H1 ]); + (`LCU20220308, 5011485, [ `V1909 ]); + (`LCU20220308, 5011503, [ `V1809 ]); + (`LCU20220308, 5011495, [ `V1607 ]); + (`LCU20220308, 5011491, [ `V1507 ]); + (`LCU20220208, 5010354, [ `V21H2 ]); + (`LCU20220208, 5010342, [ `V20H2; `V21H1 ]); + (`LCU20220208, 5010345, [ `V1909 ]); + (`LCU20220208, 5010351, [ `V1809 ]); + (`LCU20220208, 5010359, [ `V1607 ]); + (`LCU20220208, 5010358, [ `V1507 ]); + (`LCU20220111, 5009555, [ `V21H2 ]); + (`LCU20220111, 5009543, [ `V20H2; `V21H1 ]); + (`LCU20220111, 5009545, [ `V1909 ]); + (`LCU20220111, 5009557, [ `V1809 ]); + (`LCU20220111, 5009546, [ `V1607 ]); + (`LCU20220111, 5009585, [ `V1507 ]); + (`LCU20211214, 5008223, [ `V21H2 ]); + (`LCU20211214, 5008212, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20211214, 5008206, [ `V1909 ]); + (`LCU20211214, 5008218, [ `V1809 ]); + (`LCU20211214, 5008207, [ `V1607 ]); + (`LCU20211214, 5008230, [ `V1507 ]); + (`LCU20211109, 5007205, [ `V21H2 ]); + (`LCU20211109, 5007186, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20211109, 5007189, [ `V1909 ]); + (`LCU20211109, 5007206, [ `V1809 ]); + (`LCU20211109, 5007192, [ `V1607 ]); + (`LCU20211109, 5007207, [ `V1507 ]); + (`LCU20211012, 5006699, [ `V21H2 ]); + (`LCU20211012, 5006670, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20211012, 5006667, [ `V1909 ]); + (`LCU20211012, 5006672, [ `V1809 ]); + (`LCU20211012, 5006669, [ `V1607 ]); + (`LCU20211012, 5006675, [ `V1507 ]); + (`LCU20210914, 5005575, [ `V21H2 ]); + (`LCU20210914, 5005565, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20210914, 5005566, [ `V1909 ]); + (`LCU20210914, 5005568, [ `V1809 ]); + (`LCU20210914, 5005573, [ `V1607 ]); + (`LCU20210914, 5005569, [ `V1507 ]); + (`LCU20210810, 5005039, [ `V21H2 ]); + (`LCU20210810, 5005033, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20210810, 5005031, [ `V1909 ]); + (`LCU20210810, 5005030, [ `V1809 ]); + (`LCU20210810, 5005043, [ `V1607 ]); + (`LCU20210810, 5005040, [ `V1507 ]); + (`LCU20210713, 5004237, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20210713, 5004245, [ `V1909 ]); + (`LCU20210713, 5004244, [ `V1809 ]); + (`LCU20210713, 5004238, [ `V1607 ]); + (`LCU20210713, 5004249, [ `V1507 ]); + (`LCU20210608, 5003637, [ `V2004; `V20H2; `V21H1 ]); + (`LCU20210608, 5003635, [ `V1909 ]); + (`LCU20210608, 5003646, [ `V1809 ]); + (`LCU20210608, 5003638, [ `V1607 ]); + (`LCU20210608, 5003687, [ `V1507 ]); + ] + +let win10_lcu_to_kb : (win10_lcu * win10_release, int option) Hashtbl.t = let t = Hashtbl.create 63 in let f (lcu, kb, vs) = let g v = - if lcu = win10_current_lcu then - Hashtbl.add t (`LCU, v) (Some kb); + if lcu = win10_current_lcu then Hashtbl.add t (`LCU, v) (Some kb); Hashtbl.add t (lcu, v) (Some kb) in - List.iter g vs in - List.iter f win10_lcus; t + List.iter g vs + in + List.iter f win10_lcus; + t let win10_kb_to_lcu = let t = Hashtbl.create 63 in - let f (lcu, kb, vs) = List.iter (fun v -> Hashtbl.add t (kb, v) (Some lcu)) vs in - List.iter f win10_lcus; t + let f (lcu, kb, vs) = + List.iter (fun v -> Hashtbl.add t (kb, v) (Some lcu)) vs + in + List.iter f win10_lcus; + t let win10_lcu_kb_number v lcu = - try Hashtbl.find win10_lcu_to_kb (lcu, v) - with Not_found -> None + try Hashtbl.find win10_lcu_to_kb (lcu, v) with Not_found -> None -let win10_kb_number_to_lcu (v:win10_release) kb = +let win10_kb_number_to_lcu (v : win10_release) kb = match Hashtbl.find win10_kb_to_lcu (kb, v) with | lcu -> Some (v, lcu) | exception Not_found -> None -type distro = [ - | `Alpine of [ `V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15 ] +type distro = + [ `Alpine of + [ `V3_3 + | `V3_4 + | `V3_5 + | `V3_6 + | `V3_7 + | `V3_8 + | `V3_9 + | `V3_10 + | `V3_11 + | `V3_12 + | `V3_13 + | `V3_14 + | `V3_15 ] | `Archlinux of [ `Latest ] | `CentOS of [ `V6 | `V7 | `V8 ] | `Debian of [ `V11 | `V10 | `V9 | `V8 | `V7 | `Testing | `Unstable ] - | `Fedora of [ `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 | `V31 | `V32 | `V33 | `V34 | `V35 ] + | `Fedora of + [ `V21 + | `V22 + | `V23 + | `V24 + | `V25 + | `V26 + | `V27 + | `V28 + | `V29 + | `V30 + | `V31 + | `V32 + | `V33 + | `V34 + | `V35 ] | `OracleLinux of [ `V7 | `V8 ] | `OpenSUSE of [ `V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3 ] - | `Ubuntu of [ `V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 | `V17_10 | `V18_04 | `V18_10 | `V19_04 | `V19_10 | `V20_04 | `V20_10 | `V21_04 | `V21_10 | `V22_04 ] + | `Ubuntu of + [ `V12_04 + | `V14_04 + | `V15_04 + | `V15_10 + | `V16_04 + | `V16_10 + | `V17_04 + | `V17_10 + | `V18_04 + | `V18_10 + | `V19_04 + | `V19_10 + | `V20_04 + | `V20_10 + | `V21_04 + | `V21_10 + | `V22_04 ] | `Cygwin of win10_release - | `Windows of [`Mingw | `Msvc] * win10_release -] [@@deriving sexp] - -type t = [ - | `Alpine of [ `V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15 | `Latest ] + | `Windows of [ `Mingw | `Msvc ] * win10_release ] +[@@deriving sexp] + +type t = + [ `Alpine of + [ `V3_3 + | `V3_4 + | `V3_5 + | `V3_6 + | `V3_7 + | `V3_8 + | `V3_9 + | `V3_10 + | `V3_11 + | `V3_12 + | `V3_13 + | `V3_14 + | `V3_15 + | `Latest ] | `Archlinux of [ `Latest ] | `CentOS of [ `V6 | `V7 | `V8 | `Latest ] | `Debian of [ `V11 | `V10 | `V9 | `V8 | `V7 | `Stable | `Testing | `Unstable ] - | `Fedora of [ `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 | `V31 | `V32 | `V33 | `V34 | `V35 | `Latest ] + | `Fedora of + [ `V21 + | `V22 + | `V23 + | `V24 + | `V25 + | `V26 + | `V27 + | `V28 + | `V29 + | `V30 + | `V31 + | `V32 + | `V33 + | `V34 + | `V35 + | `Latest ] | `OracleLinux of [ `V7 | `V8 | `Latest ] - | `OpenSUSE of [ `V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3 | `Latest ] - | `Ubuntu of [ `V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 | `V17_10 | `V18_04 | `V18_10 | `V19_04 | `V19_10 | `V20_04 | `V20_10 | `V21_04 | `V21_10 | `V22_04 | `Latest | `LTS ] + | `OpenSUSE of + [ `V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3 | `Latest ] + | `Ubuntu of + [ `V12_04 + | `V14_04 + | `V15_04 + | `V15_10 + | `V16_04 + | `V16_10 + | `V17_04 + | `V17_10 + | `V18_04 + | `V18_10 + | `V19_04 + | `V19_10 + | `V20_04 + | `V20_10 + | `V21_04 + | `V21_10 + | `V22_04 + | `Latest + | `LTS ] | `Cygwin of win_all - | `Windows of [`Mingw | `Msvc] * win_all -] [@@deriving sexp] + | `Windows of [ `Mingw | `Msvc ] * win_all ] +[@@deriving sexp] type os_family = [ `Cygwin | `Linux | `Windows ] [@@deriving sexp] -let os_family_of_distro (t:t) : os_family = +let os_family_of_distro (t : t) : os_family = match t with | `Alpine _ | `Archlinux _ | `CentOS _ | `Debian _ | `Fedora _ - | `OracleLinux _ | `OpenSUSE _ | `Ubuntu _ -> `Linux + | `OracleLinux _ | `OpenSUSE _ | `Ubuntu _ -> + `Linux | `Cygwin _ -> `Cygwin | `Windows _ -> `Windows -let os_family_to_string (os:os_family) = +let os_family_to_string (os : os_family) = match os with | `Linux -> "linux" | `Windows -> "windows" | `Cygwin -> "cygwin" -let opam_repository (os:os_family) = +let opam_repository (os : os_family) = match os with | `Cygwin | `Linux -> "https://github.com/ocaml/opam-repository.git" | `Windows -> "https://github.com/fdopen/opam-repository-mingw.git#opam2" @@ -235,32 +334,115 @@ let personality os_family arch = | `Linux when Ocaml_version.arch_is_32bit arch -> Some "/usr/bin/linux32" | _ -> None -type status = [ - | `Deprecated +type status = + [ `Deprecated | `Active of [ `Tier1 | `Tier2 | `Tier3 ] | `Alias - | `Not_available -] [@@deriving sexp] - -let distros : t list = [ - `Alpine `V3_3; `Alpine `V3_4; `Alpine `V3_5; `Alpine `V3_6; `Alpine `V3_7; `Alpine `V3_8; `Alpine `V3_9; `Alpine `V3_10; `Alpine `V3_11; `Alpine `V3_12; `Alpine `V3_13; `Alpine `V3_14; `Alpine `V3_15; `Alpine `Latest; - `Archlinux `Latest; - `CentOS `V6; `CentOS `V7; `CentOS `V8; `CentOS `Latest; - `Debian `V11; `Debian `V10; `Debian `V9; `Debian `V8; `Debian `V7; - `Debian `Stable; `Debian `Testing; `Debian `Unstable; - `Fedora `V23; `Fedora `V24; `Fedora `V25; `Fedora `V26; `Fedora `V27; `Fedora `V28; `Fedora `V29; `Fedora `V30; `Fedora `V31; `Fedora `V32; `Fedora `V33; `Fedora `V34; `Fedora `V35; `Fedora `Latest; - `OracleLinux `V7; `OracleLinux `V8; `OracleLinux `Latest; - `OpenSUSE `V42_1; `OpenSUSE `V42_2; `OpenSUSE `V42_3; `OpenSUSE `V15_0; `OpenSUSE `V15_1; `OpenSUSE `V15_2; `OpenSUSE `V15_3; `OpenSUSE `Latest; - `Ubuntu `V12_04; `Ubuntu `V14_04; `Ubuntu `V15_04; `Ubuntu `V15_10; - `Ubuntu `V16_04; `Ubuntu `V16_10; `Ubuntu `V17_04; `Ubuntu `V17_10; `Ubuntu `V18_04; `Ubuntu `V18_10; `Ubuntu `V19_04; `Ubuntu `V19_10; `Ubuntu `V20_04; `Ubuntu `V20_10; `Ubuntu `V21_04; `Ubuntu `V21_10; `Ubuntu `V22_04; - `Ubuntu `Latest; `Ubuntu `LTS; -] + | `Not_available ] +[@@deriving sexp] + +let distros : t list = + [ + `Alpine `V3_3; + `Alpine `V3_4; + `Alpine `V3_5; + `Alpine `V3_6; + `Alpine `V3_7; + `Alpine `V3_8; + `Alpine `V3_9; + `Alpine `V3_10; + `Alpine `V3_11; + `Alpine `V3_12; + `Alpine `V3_13; + `Alpine `V3_14; + `Alpine `V3_15; + `Alpine `Latest; + `Archlinux `Latest; + `CentOS `V6; + `CentOS `V7; + `CentOS `V8; + `CentOS `Latest; + `Debian `V11; + `Debian `V10; + `Debian `V9; + `Debian `V8; + `Debian `V7; + `Debian `Stable; + `Debian `Testing; + `Debian `Unstable; + `Fedora `V23; + `Fedora `V24; + `Fedora `V25; + `Fedora `V26; + `Fedora `V27; + `Fedora `V28; + `Fedora `V29; + `Fedora `V30; + `Fedora `V31; + `Fedora `V32; + `Fedora `V33; + `Fedora `V34; + `Fedora `V35; + `Fedora `Latest; + `OracleLinux `V7; + `OracleLinux `V8; + `OracleLinux `Latest; + `OpenSUSE `V42_1; + `OpenSUSE `V42_2; + `OpenSUSE `V42_3; + `OpenSUSE `V15_0; + `OpenSUSE `V15_1; + `OpenSUSE `V15_2; + `OpenSUSE `V15_3; + `OpenSUSE `Latest; + `Ubuntu `V12_04; + `Ubuntu `V14_04; + `Ubuntu `V15_04; + `Ubuntu `V15_10; + `Ubuntu `V16_04; + `Ubuntu `V16_10; + `Ubuntu `V17_04; + `Ubuntu `V17_10; + `Ubuntu `V18_04; + `Ubuntu `V18_10; + `Ubuntu `V19_04; + `Ubuntu `V19_10; + `Ubuntu `V20_04; + `Ubuntu `V20_10; + `Ubuntu `V21_04; + `Ubuntu `V21_10; + `Ubuntu `V22_04; + `Ubuntu `Latest; + `Ubuntu `LTS; + ] + let distros = let win10_releases = - [ `V1507; `Ltsc2015; `V1511; `V1607; `Ltsc2016; `V1703; `V1709; `V1809; - `Ltsc2019; `V1903; `V1909; `V2004; `V20H2; `V21H1; `V21H2; `Ltsc2022 ] in - List.fold_left (fun distros version -> - `Cygwin version :: `Windows (`Mingw, version) :: `Windows (`Msvc, version) :: distros) + [ + `V1507; + `Ltsc2015; + `V1511; + `V1607; + `Ltsc2016; + `V1703; + `V1709; + `V1809; + `Ltsc2019; + `V1903; + `V1909; + `V2004; + `V20H2; + `V21H1; + `V21H2; + `Ltsc2022; + ] + in + List.fold_left + (fun distros version -> + `Cygwin version + :: `Windows (`Mingw, version) + :: `Windows (`Msvc, version) + :: distros) distros win10_releases type win10_release_status = [ `Deprecated | `Active ] @@ -274,16 +456,16 @@ let resolve_ltsc v = | #win10_release as v -> v (* https://en.wikipedia.org/wiki/Windows_10_version_history#Channels *) -let win10_release_status v : win10_release_status = match resolve_ltsc v with - | `V1507 -> `Deprecated | `Ltsc2015 -> `Active +let win10_release_status v : win10_release_status = + match resolve_ltsc v with + | `V1507 -> `Deprecated + | `Ltsc2015 -> `Active | `V1511 -> `Deprecated - | `V1607 -> `Deprecated | `Ltsc2016 -> `Active - | `V1703 - | `V1709 - | `V1803 - | `V1809 -> `Deprecated | `Ltsc2019 -> `Active - | `V1903 - | `V1909 -> `Deprecated + | `V1607 -> `Deprecated + | `Ltsc2016 -> `Active + | `V1703 | `V1709 | `V1803 | `V1809 -> `Deprecated + | `Ltsc2019 -> `Active + | `V1903 | `V1909 -> `Deprecated | `V2004 -> `Deprecated | `V20H2 -> `Deprecated | `V21H1 | `V21H2 | `Ltsc2022 -> `Active @@ -294,24 +476,20 @@ type win10_docker_base_image = [ `Windows | `ServerCore | `NanoServer ] (* https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/base-image-lifecycle *) let win10_docker_status (base : win10_docker_base_image) v : status = - match base, v with + match (base, v) with | _, `V21H2 -> `Active `Tier3 - | _, `V20H2 - | _, `V2004 - | _, `V1909 - | _, `V1903 -> `Deprecated - | `ServerCore, `V1809 - | `NanoServer, `V1809 - | `Windows, `V1809 -> `Active `Tier3 - | (`ServerCore | `NanoServer), `V1803 - | (`ServerCore | `NanoServer), `V1709 -> `Deprecated + | _, `V20H2 | _, `V2004 | _, `V1909 | _, `V1903 -> `Deprecated + | `ServerCore, `V1809 | `NanoServer, `V1809 | `Windows, `V1809 -> + `Active `Tier3 + | (`ServerCore | `NanoServer), `V1803 | (`ServerCore | `NanoServer), `V1709 -> + `Deprecated | `ServerCore, `V1607 -> `Active `Tier3 | `NanoServer, `V1607 -> `Deprecated | _ -> `Not_available let win10_latest_image = `V21H2 -let resolve_alias (d:t) : distro = +let resolve_alias (d : t) : distro = match d with | `Alpine `Latest -> `Alpine `V3_15 | `CentOS `Latest -> `CentOS `V7 @@ -323,50 +501,79 @@ let resolve_alias (d:t) : distro = | `Ubuntu `LTS -> `Ubuntu `V22_04 | `Cygwin (#win10_ltsc as v) -> `Cygwin (resolve_ltsc v) | `Windows (cc, (#win10_ltsc as v)) -> `Windows (cc, resolve_ltsc v) - | `Alpine (`V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15) - | `Archlinux `Latest - | `CentOS (`V6 | `V7 | `V8) - | `Debian (`V7 | `V8 | `V9 | `V10 | `V11 | `Testing | `Unstable) - | `Fedora (`V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 | `V31 | `V32 | `V33 | `V34 | `V35) - | `OracleLinux (`V7 | `V8) - | `OpenSUSE (`V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3) - | `Ubuntu (`V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 | `V17_10 | `V18_04 | `V18_10 | `V19_04 | `V19_10 | `V20_04 | `V20_10 | `V21_04 | `V21_10 | `V22_04) - | `Cygwin (`V1507 | `V1511 | `V1607 | `V1703 | `V1709 | `V1803 | `V1809 | `V1903 | `V1909 | `V2004 | `V20H2 | `V21H1 | `V21H2) - | `Windows (_, (`V1507 | `V1511 | `V1607 | `V1703 | `V1709 | `V1803 | `V1809 | `V1903 | `V1909 | `V2004 | `V20H2 | `V21H1 | `V21H2)) as d -> + | ( `Alpine + ( `V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 + | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15 ) + | `Archlinux `Latest + | `CentOS (`V6 | `V7 | `V8) + | `Debian (`V7 | `V8 | `V9 | `V10 | `V11 | `Testing | `Unstable) + | `Fedora + ( `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 + | `V31 | `V32 | `V33 | `V34 | `V35 ) + | `OracleLinux (`V7 | `V8) + | `OpenSUSE (`V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3) + | `Ubuntu + ( `V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 + | `V17_10 | `V18_04 | `V18_10 | `V19_04 | `V19_10 | `V20_04 | `V20_10 + | `V21_04 | `V21_10 | `V22_04 ) + | `Cygwin + ( `V1507 | `V1511 | `V1607 | `V1703 | `V1709 | `V1803 | `V1809 | `V1903 + | `V1909 | `V2004 | `V20H2 | `V21H1 | `V21H2 ) + | `Windows + ( _, + ( `V1507 | `V1511 | `V1607 | `V1703 | `V1709 | `V1803 | `V1809 + | `V1903 | `V1909 | `V2004 | `V20H2 | `V21H1 | `V21H2 ) ) ) as d -> d -let distro_status (d:t) : status = +let distro_status (d : t) : status = let resolved = resolve_alias d in - if (resolved : distro :> t) <> d then - `Alias + if (resolved : distro :> t) <> d then `Alias else match resolve_alias d with - | `Alpine (`V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 |`V3_13) -> `Deprecated + | `Alpine + ( `V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 + | `V3_11 | `V3_12 | `V3_13 ) -> + `Deprecated | `Alpine `V3_14 -> `Active `Tier2 | `Alpine `V3_15 -> `Active `Tier1 | `Archlinux `Latest -> `Active `Tier3 | `CentOS `V7 -> `Active `Tier3 - | `CentOS (`V6|`V8) -> `Deprecated - | `Debian (`V7|`V8|`V9) -> `Deprecated + | `CentOS (`V6 | `V8) -> `Deprecated + | `Debian (`V7 | `V8 | `V9) -> `Deprecated | `Debian `V10 -> `Active `Tier2 | `Debian `V11 -> `Active `Tier1 | `Debian `Testing -> `Active `Tier3 | `Debian `Unstable -> `Active `Tier3 - | `Fedora ( `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 | `V31 | `V32 | `V33) -> `Deprecated + | `Fedora + ( `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 + | `V31 | `V32 | `V33 ) -> + `Deprecated | `Fedora (`V34 | `V35) -> `Active `Tier2 - | `OracleLinux (`V7|`V8) -> `Active `Tier3 - | `OpenSUSE (`V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2) -> `Deprecated + | `OracleLinux (`V7 | `V8) -> `Active `Tier3 + | `OpenSUSE (`V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2) -> + `Deprecated | `OpenSUSE `V15_3 -> `Active `Tier2 - | `Ubuntu (`V18_04) -> `Active `Tier3 + | `Ubuntu `V18_04 -> `Active `Tier3 | `Ubuntu (`V20_04 | `V22_04) -> `Active `Tier2 - | `Ubuntu (`V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 | `V17_10 | `V18_10 | `V19_04 | `V19_10 | `V20_10 | `V21_04 | `V21_10) -> `Deprecated + | `Ubuntu + ( `V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 + | `V17_10 | `V18_10 | `V19_04 | `V19_10 | `V20_10 | `V21_04 | `V21_10 ) + -> + `Deprecated | `Cygwin v -> win10_docker_status `ServerCore v | `Windows (_, v) -> win10_docker_status `Windows v let latest_distros = - [ `Alpine `Latest; `Archlinux `Latest; `CentOS `Latest; - `Debian `Stable; `OracleLinux `Latest; `OpenSUSE `Latest; - `Fedora `Latest; `Ubuntu `Latest; `Ubuntu `LTS; + [ + `Alpine `Latest; + `Archlinux `Latest; + `CentOS `Latest; + `Debian `Stable; + `OracleLinux `Latest; + `OpenSUSE `Latest; + `Fedora `Latest; + `Ubuntu `Latest; + `Ubuntu `LTS; (* Prefer win10_latest_image to win10_latest_release as latest_distro is used by docker-base-images to fetch tag aliases. *) @@ -379,454 +586,504 @@ let master_distro = `Debian `Stable module OV = Ocaml_version -let distro_arches ov (d:t) = - match resolve_alias d, ov with +let distro_arches ov (d : t) = + match (resolve_alias d, ov) with | `Windows (`Msvc, _), ov when OV.major ov >= 5 -> [] - | (`CentOS (`V6|`V7)|`OracleLinux `V7), ov when OV.major ov >= 5 -> [] - | `Debian `V11, ov when OV.(compare Releases.v4_03_0 ov) = -1 -> [ `I386; `X86_64; `Aarch64; `Aarch32; `Ppc64le; `S390x ] - | `Debian `V11, ov when OV.(compare Releases.v4_02_0 ov) = -1 -> [ `I386; `X86_64; `Aarch64; `Aarch32] - | `Debian `V10, ov when OV.(compare Releases.v4_03_0 ov) = -1 -> [ `I386; `X86_64; `Aarch64; `Aarch32; `Ppc64le; `S390x ] - | `Debian `V10, ov when OV.(compare Releases.v4_02_0 ov) = -1 -> [ `I386; `X86_64; `Aarch64; `Aarch32] - | `Debian `V9, ov when OV.(compare Releases.v4_03_0 ov) = -1 -> [ `I386; `X86_64; `Aarch64; `Aarch32 ] - | `Alpine (`V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15), ov when OV.(compare Releases.v4_05_0 ov) = -1 -> [ `X86_64; `Aarch64 ] - | `Ubuntu `V18_04, ov when OV.(compare Releases.v4_05_0 ov) = -1 -> [ `X86_64; `Aarch64; `Ppc64le; `S390x ] - | `Ubuntu (`V20_04|`V20_10|`V21_04|`V21_10|`V22_04), ov when OV.(compare Releases.v4_05_0 ov) = -1 -> - let base = [ `X86_64; `Aarch64; `Ppc64le; `S390x ] in - if OV.(compare Releases.v4_11_0 ov) <= 0 then - `Riscv64 :: base - else - base - | `Fedora (`V33|`V34|`V35), ov when OV.(compare Releases.v4_08_0 ov) = -1 -> [ `X86_64; `Aarch64 ] + | (`CentOS (`V6 | `V7) | `OracleLinux `V7), ov when OV.major ov >= 5 -> [] + | `Debian `V11, ov when OV.(compare Releases.v4_03_0 ov) = -1 -> + [ `I386; `X86_64; `Aarch64; `Aarch32; `Ppc64le; `S390x ] + | `Debian `V11, ov when OV.(compare Releases.v4_02_0 ov) = -1 -> + [ `I386; `X86_64; `Aarch64; `Aarch32 ] + | `Debian `V10, ov when OV.(compare Releases.v4_03_0 ov) = -1 -> + [ `I386; `X86_64; `Aarch64; `Aarch32; `Ppc64le; `S390x ] + | `Debian `V10, ov when OV.(compare Releases.v4_02_0 ov) = -1 -> + [ `I386; `X86_64; `Aarch64; `Aarch32 ] + | `Debian `V9, ov when OV.(compare Releases.v4_03_0 ov) = -1 -> + [ `I386; `X86_64; `Aarch64; `Aarch32 ] + | ( `Alpine + ( `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 + | `V3_14 | `V3_15 ), + ov ) + when OV.(compare Releases.v4_05_0 ov) = -1 -> + [ `X86_64; `Aarch64 ] + | `Ubuntu `V18_04, ov when OV.(compare Releases.v4_05_0 ov) = -1 -> + [ `X86_64; `Aarch64; `Ppc64le; `S390x ] + | `Ubuntu (`V20_04 | `V20_10 | `V21_04 | `V21_10 | `V22_04), ov + when OV.(compare Releases.v4_05_0 ov) = -1 -> + let base = [ `X86_64; `Aarch64; `Ppc64le; `S390x ] in + if OV.(compare Releases.v4_11_0 ov) <= 0 then `Riscv64 :: base else base + | `Fedora (`V33 | `V34 | `V35), ov when OV.(compare Releases.v4_08_0 ov) = -1 + -> + [ `X86_64; `Aarch64 ] (* 2021-04-19: should be 4.03 but there's a linking failure until 4.06. *) | `Windows (`Msvc, _), ov when OV.(compare Releases.v4_06_0 ov) = 1 -> [] | _ -> [ `X86_64 ] +let distro_supported_on a ov (d : t) = List.mem a (distro_arches ov d) -let distro_supported_on a ov (d:t) = - List.mem a (distro_arches ov d) - -let distro_active_for arch (d:t) = - match arch, d with +let distro_active_for arch (d : t) = + match (arch, d) with | `X86_64, `Windows _ -> true | _ -> distro_supported_on arch OV.Releases.latest d let active_distros arch = - List.filter (fun d -> match distro_status d with `Active _ -> true | _ -> false ) distros |> - List.filter (distro_active_for arch) + List.filter + (fun d -> match distro_status d with `Active _ -> true | _ -> false) + distros + |> List.filter (distro_active_for arch) let active_tier1_distros arch = - List.filter (fun d -> match distro_status d with `Active `Tier1 -> true | _ -> false ) distros |> - List.filter (distro_active_for arch) + List.filter + (fun d -> match distro_status d with `Active `Tier1 -> true | _ -> false) + distros + |> List.filter (distro_active_for arch) let active_tier2_distros arch = - List.filter (fun d -> match distro_status d with `Active `Tier2 -> true | _ -> false ) distros |> - List.filter (distro_active_for arch) + List.filter + (fun d -> match distro_status d with `Active `Tier2 -> true | _ -> false) + distros + |> List.filter (distro_active_for arch) let active_tier3_distros arch = - List.filter (fun d -> match distro_status d with `Active `Tier3 -> true | _ -> false ) distros |> - List.filter (distro_active_for arch) + List.filter + (fun d -> match distro_status d with `Active `Tier3 -> true | _ -> false) + distros + |> List.filter (distro_active_for arch) (* The distro-supplied version of OCaml *) -let builtin_ocaml_of_distro (d:t) : string option = +let builtin_ocaml_of_distro (d : t) : string option = match resolve_alias d with - |`Debian `V7 -> Some "3.12.1" - |`Debian `V8 -> Some "4.01.0" - |`Debian `V9 -> Some "4.02.3" - |`Debian `V10 -> Some "4.05.0" - |`Debian `V11 -> Some "4.11.1" - |`Ubuntu `V12_04 -> Some "3.12.1" - |`Ubuntu `V14_04 -> Some "4.01.0" - |`Ubuntu `V15_04 -> Some "4.01.0" - |`Ubuntu `V15_10 -> Some "4.01.0" - |`Ubuntu `V16_04 -> Some "4.02.3" - |`Ubuntu `V16_10 -> Some "4.02.3" - |`Ubuntu `V17_04 -> Some "4.02.3" - |`Ubuntu `V17_10 -> Some "4.04.0" - |`Ubuntu `V18_04 -> Some "4.05.0" - |`Ubuntu `V18_10 -> Some "4.05.0" - |`Ubuntu `V19_04 -> Some "4.05.0" - |`Ubuntu `V19_10 -> Some "4.05.0" - |`Ubuntu `V20_04 -> Some "4.08.1" - |`Ubuntu `V20_10 -> Some "4.08.1" - |`Ubuntu `V21_04 -> Some "4.11.1" - |`Ubuntu `V21_10 -> Some "4.11.1" - |`Ubuntu `V22_04 -> failwith "4.11.1; not yet confirmed" - |`Alpine `V3_3 -> Some "4.02.3" - |`Alpine `V3_4 -> Some "4.02.3" - |`Alpine `V3_5 -> Some "4.04.0" - |`Alpine `V3_6 -> Some "4.04.1" - |`Alpine `V3_7 -> Some "4.04.2" - |`Alpine `V3_8 -> Some "4.06.1" - |`Alpine `V3_9 -> Some "4.06.1" - |`Alpine `V3_10 -> Some "4.07.0" - |`Alpine `V3_11 -> Some "4.08.1" - |`Alpine `V3_12 -> Some "4.08.1" - |`Alpine `V3_13 -> Some "4.08.1" - |`Alpine `V3_14 -> Some "4.12.0" - |`Alpine `V3_15 -> Some "4.13.1" - |`Archlinux `Latest -> Some "4.11.1" - |`Fedora `V21 -> Some "4.01.0" - |`Fedora `V22 -> Some "4.02.0" - |`Fedora `V23 -> Some "4.02.2" - |`Fedora `V24 -> Some "4.02.3" - |`Fedora `V25 -> Some "4.02.3" - |`Fedora `V26 -> Some "4.04.0" - |`Fedora `V27 -> Some "4.05.0" - |`Fedora `V28 -> Some "4.06.0" - |`Fedora `V29 -> Some "4.07.0" - |`Fedora `V30 -> Some "4.07.0" - |`Fedora `V31 -> Some "4.08.1" - |`Fedora `V32 -> Some "4.10.0" - |`Fedora `V33 -> Some "4.11.1" - |`Fedora `V34 -> Some "4.11.1" - |`Fedora `V35 -> Some "4.12.0" - |`CentOS `V6 -> Some "3.11.2" - |`CentOS `V7 -> Some "4.01.0" - |`CentOS `V8 -> Some "4.07.0" - |`OpenSUSE `V42_1 -> Some "4.02.3" - |`OpenSUSE `V42_2 -> Some "4.03.0" - |`OpenSUSE `V42_3 -> Some "4.03.0" - |`OpenSUSE `V15_0 -> Some "4.05.0" - |`OpenSUSE `V15_1 -> Some "4.05.0" - |`OpenSUSE `V15_2 -> Some "4.05.0" - |`OpenSUSE `V15_3 -> Some "4.05.0" - |`OracleLinux `V7 -> Some "4.01.0" - |`OracleLinux `V8 -> Some "4.07.0" - |`Cygwin _ -> None - |`Windows _ -> None - |`Debian (`Testing | `Unstable) -> assert false + | `Debian `V7 -> Some "3.12.1" + | `Debian `V8 -> Some "4.01.0" + | `Debian `V9 -> Some "4.02.3" + | `Debian `V10 -> Some "4.05.0" + | `Debian `V11 -> Some "4.11.1" + | `Ubuntu `V12_04 -> Some "3.12.1" + | `Ubuntu `V14_04 -> Some "4.01.0" + | `Ubuntu `V15_04 -> Some "4.01.0" + | `Ubuntu `V15_10 -> Some "4.01.0" + | `Ubuntu `V16_04 -> Some "4.02.3" + | `Ubuntu `V16_10 -> Some "4.02.3" + | `Ubuntu `V17_04 -> Some "4.02.3" + | `Ubuntu `V17_10 -> Some "4.04.0" + | `Ubuntu `V18_04 -> Some "4.05.0" + | `Ubuntu `V18_10 -> Some "4.05.0" + | `Ubuntu `V19_04 -> Some "4.05.0" + | `Ubuntu `V19_10 -> Some "4.05.0" + | `Ubuntu `V20_04 -> Some "4.08.1" + | `Ubuntu `V20_10 -> Some "4.08.1" + | `Ubuntu `V21_04 -> Some "4.11.1" + | `Ubuntu `V21_10 -> Some "4.11.1" + | `Ubuntu `V22_04 -> failwith "4.11.1; not yet confirmed" + | `Alpine `V3_3 -> Some "4.02.3" + | `Alpine `V3_4 -> Some "4.02.3" + | `Alpine `V3_5 -> Some "4.04.0" + | `Alpine `V3_6 -> Some "4.04.1" + | `Alpine `V3_7 -> Some "4.04.2" + | `Alpine `V3_8 -> Some "4.06.1" + | `Alpine `V3_9 -> Some "4.06.1" + | `Alpine `V3_10 -> Some "4.07.0" + | `Alpine `V3_11 -> Some "4.08.1" + | `Alpine `V3_12 -> Some "4.08.1" + | `Alpine `V3_13 -> Some "4.08.1" + | `Alpine `V3_14 -> Some "4.12.0" + | `Alpine `V3_15 -> Some "4.13.1" + | `Archlinux `Latest -> Some "4.11.1" + | `Fedora `V21 -> Some "4.01.0" + | `Fedora `V22 -> Some "4.02.0" + | `Fedora `V23 -> Some "4.02.2" + | `Fedora `V24 -> Some "4.02.3" + | `Fedora `V25 -> Some "4.02.3" + | `Fedora `V26 -> Some "4.04.0" + | `Fedora `V27 -> Some "4.05.0" + | `Fedora `V28 -> Some "4.06.0" + | `Fedora `V29 -> Some "4.07.0" + | `Fedora `V30 -> Some "4.07.0" + | `Fedora `V31 -> Some "4.08.1" + | `Fedora `V32 -> Some "4.10.0" + | `Fedora `V33 -> Some "4.11.1" + | `Fedora `V34 -> Some "4.11.1" + | `Fedora `V35 -> Some "4.12.0" + | `CentOS `V6 -> Some "3.11.2" + | `CentOS `V7 -> Some "4.01.0" + | `CentOS `V8 -> Some "4.07.0" + | `OpenSUSE `V42_1 -> Some "4.02.3" + | `OpenSUSE `V42_2 -> Some "4.03.0" + | `OpenSUSE `V42_3 -> Some "4.03.0" + | `OpenSUSE `V15_0 -> Some "4.05.0" + | `OpenSUSE `V15_1 -> Some "4.05.0" + | `OpenSUSE `V15_2 -> Some "4.05.0" + | `OpenSUSE `V15_3 -> Some "4.05.0" + | `OracleLinux `V7 -> Some "4.01.0" + | `OracleLinux `V8 -> Some "4.07.0" + | `Cygwin _ -> None + | `Windows _ -> None + | `Debian (`Testing | `Unstable) -> assert false let win10_release_to_string = function - | `V1507 -> "1507" | `Ltsc2015 -> "ltsc2015" | `V1511 -> "1511" - | `V1607 -> "1607" | `Ltsc2016 -> "ltsc2016" | `V1703 -> "1703" - | `V1709 -> "1709" | `V1803 -> "1803" | `V1809 -> "1809" - | `Ltsc2019 -> "ltsc2019" | `V1903 -> "1903" | `V1909 -> "1909" - | `V2004 -> "2004" | `V20H2 -> "20H2" | `V21H1 -> "21H1" - | `Ltsc2022 -> "ltsc2022" | `V21H2 -> "21H2" + | `V1507 -> "1507" + | `Ltsc2015 -> "ltsc2015" + | `V1511 -> "1511" + | `V1607 -> "1607" + | `Ltsc2016 -> "ltsc2016" + | `V1703 -> "1703" + | `V1709 -> "1709" + | `V1803 -> "1803" + | `V1809 -> "1809" + | `Ltsc2019 -> "ltsc2019" + | `V1903 -> "1903" + | `V1909 -> "1909" + | `V2004 -> "2004" + | `V20H2 -> "20H2" + | `V21H1 -> "21H1" + | `Ltsc2022 -> "ltsc2022" + | `V21H2 -> "21H2" let win10_release_of_string v : win_all option = - let v = match String.cut ~sep:"-KB" v with - | Some (v, kb) -> if String.for_all Char.Ascii.is_digit kb then v else "" - | None -> v + let v = + match String.cut ~sep:"-KB" v with + | Some (v, kb) -> if String.for_all Char.Ascii.is_digit kb then v else "" + | None -> v in match v with - | "1507" -> Some `V1507 | "ltsc2015" -> Some `Ltsc2015 | "1511" -> Some `V1511 - | "1607" -> Some `V1607 | "ltsc2016" -> Some `Ltsc2016 | "1703" -> Some `V1703 - | "1709" -> Some `V1709 | "1803" -> Some `V1803 | "1809" -> Some `V1809 - | "ltsc2019" -> Some `Ltsc2019 | "1903" -> Some `V1903 | "1909" -> Some `V1909 - | "2004" -> Some `V2004 | "20H2" -> Some `V20H2 | "21H1" -> Some `V21H1 + | "1507" -> Some `V1507 + | "ltsc2015" -> Some `Ltsc2015 + | "1511" -> Some `V1511 + | "1607" -> Some `V1607 + | "ltsc2016" -> Some `Ltsc2016 + | "1703" -> Some `V1703 + | "1709" -> Some `V1709 + | "1803" -> Some `V1803 + | "1809" -> Some `V1809 + | "ltsc2019" -> Some `Ltsc2019 + | "1903" -> Some `V1903 + | "1909" -> Some `V1909 + | "2004" -> Some `V2004 + | "20H2" -> Some `V20H2 + | "21H1" -> Some `V21H1 | "ltsc2022" -> Some `Ltsc2022 | _ -> None let rec win10_revision_to_string = function -| (v, None) -> win10_release_to_string v -| (v, Some `LCU) -> win10_revision_to_string (v, Some win10_current_lcu) -| (v, Some lcu) -> - match win10_lcu_kb_number (resolve_ltsc v) lcu with - | Some kb -> Printf.sprintf "%s-KB%d" (win10_release_to_string v) kb - | None -> Fmt.invalid_arg "No KB for this Win10 %s revision" (win10_release_to_string v) + | v, None -> win10_release_to_string v + | v, Some `LCU -> win10_revision_to_string (v, Some win10_current_lcu) + | v, Some lcu -> ( + match win10_lcu_kb_number (resolve_ltsc v) lcu with + | Some kb -> Printf.sprintf "%s-KB%d" (win10_release_to_string v) kb + | None -> + Fmt.invalid_arg "No KB for this Win10 %s revision" + (win10_release_to_string v)) let win10_revision_of_string v = let v, lcu = match String.cut ~sep:"-KB" v with | Some (v, lcu) when String.for_all Char.Ascii.is_digit lcu -> (v, Some (int_of_string lcu)) - | _ -> - (v, None) + | _ -> (v, None) in match win10_release_of_string v with | None -> None - | Some v -> + | Some v -> ( let v = resolve_ltsc v in match lcu with | None -> Some (v, None) - | Some lcu -> win10_kb_number_to_lcu v lcu + | Some lcu -> win10_kb_number_to_lcu v lcu) (* The Docker tag for this distro *) -let tag_of_distro (d:t) = match d with - |`Ubuntu `V12_04 -> "ubuntu-12.04" - |`Ubuntu `V14_04 -> "ubuntu-14.04" - |`Ubuntu `V15_04 -> "ubuntu-15.04" - |`Ubuntu `V15_10 -> "ubuntu-15.10" - |`Ubuntu `V16_04 -> "ubuntu-16.04" - |`Ubuntu `V16_10 -> "ubuntu-16.10" - |`Ubuntu `V17_04 -> "ubuntu-17.04" - |`Ubuntu `V17_10 -> "ubuntu-17.10" - |`Ubuntu `V18_04 -> "ubuntu-18.04" - |`Ubuntu `V18_10 -> "ubuntu-18.10" - |`Ubuntu `V19_04 -> "ubuntu-19.04" - |`Ubuntu `V19_10 -> "ubuntu-19.10" - |`Ubuntu `V20_04 -> "ubuntu-20.04" - |`Ubuntu `V20_10 -> "ubuntu-20.10" - |`Ubuntu `V21_04 -> "ubuntu-21.04" - |`Ubuntu `V21_10 -> "ubuntu-21.10" - |`Ubuntu `V22_04 -> "ubuntu-22.04" - |`Ubuntu `Latest -> "ubuntu" - |`Ubuntu `LTS -> "ubuntu-lts" - |`Debian `Stable -> "debian-stable" - |`Debian `Unstable -> "debian-unstable" - |`Debian `Testing -> "debian-testing" - |`Debian `V11 -> "debian-11" - |`Debian `V10 -> "debian-10" - |`Debian `V9 -> "debian-9" - |`Debian `V8 -> "debian-8" - |`Debian `V7 -> "debian-7" - |`CentOS `V6 -> "centos-6" - |`CentOS `V7 -> "centos-7" - |`CentOS `V8 -> "centos-8" - |`CentOS `Latest -> "centos" - |`Fedora `Latest -> "fedora" - |`Fedora `V21 -> "fedora-21" - |`Fedora `V22 -> "fedora-22" - |`Fedora `V23 -> "fedora-23" - |`Fedora `V24 -> "fedora-24" - |`Fedora `V25 -> "fedora-25" - |`Fedora `V26 -> "fedora-26" - |`Fedora `V27 -> "fedora-27" - |`Fedora `V28 -> "fedora-28" - |`Fedora `V29 -> "fedora-29" - |`Fedora `V30 -> "fedora-30" - |`Fedora `V31 -> "fedora-31" - |`Fedora `V32 -> "fedora-32" - |`Fedora `V33 -> "fedora-33" - |`Fedora `V34 -> "fedora-34" - |`Fedora `V35 -> "fedora-35" - |`OracleLinux `V7 -> "oraclelinux-7" - |`OracleLinux `V8 -> "oraclelinux-8" - |`OracleLinux `Latest -> "oraclelinux" - |`Alpine `V3_3 -> "alpine-3.3" - |`Alpine `V3_4 -> "alpine-3.4" - |`Alpine `V3_5 -> "alpine-3.5" - |`Alpine `V3_6 -> "alpine-3.6" - |`Alpine `V3_7 -> "alpine-3.7" - |`Alpine `V3_8 -> "alpine-3.8" - |`Alpine `V3_9 -> "alpine-3.9" - |`Alpine `V3_10 -> "alpine-3.10" - |`Alpine `V3_11 -> "alpine-3.11" - |`Alpine `V3_12 -> "alpine-3.12" - |`Alpine `V3_13 -> "alpine-3.13" - |`Alpine `V3_14 -> "alpine-3.14" - |`Alpine `V3_15 -> "alpine-3.15" - |`Alpine `Latest -> "alpine" - |`Archlinux `Latest -> "archlinux" - |`OpenSUSE `V42_1 -> "opensuse-42.1" - |`OpenSUSE `V42_2 -> "opensuse-42.2" - |`OpenSUSE `V42_3 -> "opensuse-42.3" - |`OpenSUSE `V15_0 -> "opensuse-15.0" - |`OpenSUSE `V15_1 -> "opensuse-15.1" - |`OpenSUSE `V15_2 -> "opensuse-15.2" - |`OpenSUSE `V15_3 -> "opensuse-15.3" - |`OpenSUSE `Latest -> "opensuse" - |`Cygwin v -> "cygwin-" ^ (win10_release_to_string v) - |`Windows (`Mingw, v) -> "windows-mingw-" ^ (win10_release_to_string v) - |`Windows (`Msvc, v) -> "windows-msvc-" ^ (win10_release_to_string v) +let tag_of_distro (d : t) = + match d with + | `Ubuntu `V12_04 -> "ubuntu-12.04" + | `Ubuntu `V14_04 -> "ubuntu-14.04" + | `Ubuntu `V15_04 -> "ubuntu-15.04" + | `Ubuntu `V15_10 -> "ubuntu-15.10" + | `Ubuntu `V16_04 -> "ubuntu-16.04" + | `Ubuntu `V16_10 -> "ubuntu-16.10" + | `Ubuntu `V17_04 -> "ubuntu-17.04" + | `Ubuntu `V17_10 -> "ubuntu-17.10" + | `Ubuntu `V18_04 -> "ubuntu-18.04" + | `Ubuntu `V18_10 -> "ubuntu-18.10" + | `Ubuntu `V19_04 -> "ubuntu-19.04" + | `Ubuntu `V19_10 -> "ubuntu-19.10" + | `Ubuntu `V20_04 -> "ubuntu-20.04" + | `Ubuntu `V20_10 -> "ubuntu-20.10" + | `Ubuntu `V21_04 -> "ubuntu-21.04" + | `Ubuntu `V21_10 -> "ubuntu-21.10" + | `Ubuntu `V22_04 -> "ubuntu-22.04" + | `Ubuntu `Latest -> "ubuntu" + | `Ubuntu `LTS -> "ubuntu-lts" + | `Debian `Stable -> "debian-stable" + | `Debian `Unstable -> "debian-unstable" + | `Debian `Testing -> "debian-testing" + | `Debian `V11 -> "debian-11" + | `Debian `V10 -> "debian-10" + | `Debian `V9 -> "debian-9" + | `Debian `V8 -> "debian-8" + | `Debian `V7 -> "debian-7" + | `CentOS `V6 -> "centos-6" + | `CentOS `V7 -> "centos-7" + | `CentOS `V8 -> "centos-8" + | `CentOS `Latest -> "centos" + | `Fedora `Latest -> "fedora" + | `Fedora `V21 -> "fedora-21" + | `Fedora `V22 -> "fedora-22" + | `Fedora `V23 -> "fedora-23" + | `Fedora `V24 -> "fedora-24" + | `Fedora `V25 -> "fedora-25" + | `Fedora `V26 -> "fedora-26" + | `Fedora `V27 -> "fedora-27" + | `Fedora `V28 -> "fedora-28" + | `Fedora `V29 -> "fedora-29" + | `Fedora `V30 -> "fedora-30" + | `Fedora `V31 -> "fedora-31" + | `Fedora `V32 -> "fedora-32" + | `Fedora `V33 -> "fedora-33" + | `Fedora `V34 -> "fedora-34" + | `Fedora `V35 -> "fedora-35" + | `OracleLinux `V7 -> "oraclelinux-7" + | `OracleLinux `V8 -> "oraclelinux-8" + | `OracleLinux `Latest -> "oraclelinux" + | `Alpine `V3_3 -> "alpine-3.3" + | `Alpine `V3_4 -> "alpine-3.4" + | `Alpine `V3_5 -> "alpine-3.5" + | `Alpine `V3_6 -> "alpine-3.6" + | `Alpine `V3_7 -> "alpine-3.7" + | `Alpine `V3_8 -> "alpine-3.8" + | `Alpine `V3_9 -> "alpine-3.9" + | `Alpine `V3_10 -> "alpine-3.10" + | `Alpine `V3_11 -> "alpine-3.11" + | `Alpine `V3_12 -> "alpine-3.12" + | `Alpine `V3_13 -> "alpine-3.13" + | `Alpine `V3_14 -> "alpine-3.14" + | `Alpine `V3_15 -> "alpine-3.15" + | `Alpine `Latest -> "alpine" + | `Archlinux `Latest -> "archlinux" + | `OpenSUSE `V42_1 -> "opensuse-42.1" + | `OpenSUSE `V42_2 -> "opensuse-42.2" + | `OpenSUSE `V42_3 -> "opensuse-42.3" + | `OpenSUSE `V15_0 -> "opensuse-15.0" + | `OpenSUSE `V15_1 -> "opensuse-15.1" + | `OpenSUSE `V15_2 -> "opensuse-15.2" + | `OpenSUSE `V15_3 -> "opensuse-15.3" + | `OpenSUSE `Latest -> "opensuse" + | `Cygwin v -> "cygwin-" ^ win10_release_to_string v + | `Windows (`Mingw, v) -> "windows-mingw-" ^ win10_release_to_string v + | `Windows (`Msvc, v) -> "windows-msvc-" ^ win10_release_to_string v let distro_of_tag x : t option = let win10_of_tag affix s f = let stop = String.length affix in - match win10_release_of_string (String.(sub ~start:0 ~stop s |> Sub.to_string)) with + match + win10_release_of_string String.(sub ~start:0 ~stop s |> Sub.to_string) + with | Some v -> Some (f v) | None -> None in match x with - |"ubuntu-12.04" -> Some (`Ubuntu `V12_04) - |"ubuntu-14.04" -> Some (`Ubuntu `V14_04) - |"ubuntu-15.04" -> Some (`Ubuntu `V15_04) - |"ubuntu-15.10" -> Some (`Ubuntu `V15_10) - |"ubuntu-16.04" -> Some (`Ubuntu `V16_04) - |"ubuntu-16.10" -> Some (`Ubuntu `V16_10) - |"ubuntu-17.04" -> Some (`Ubuntu `V17_04) - |"ubuntu-17.10" -> Some (`Ubuntu `V17_10) - |"ubuntu-18.04" -> Some (`Ubuntu `V18_04) - |"ubuntu-18.10" -> Some (`Ubuntu `V18_10) - |"ubuntu-19.04" -> Some (`Ubuntu `V19_04) - |"ubuntu-19.10" -> Some (`Ubuntu `V19_10) - |"ubuntu-20.04" -> Some (`Ubuntu `V20_04) - |"ubuntu-20.10" -> Some (`Ubuntu `V20_10) - |"ubuntu-21.04" -> Some (`Ubuntu `V21_04) - |"ubuntu-21.10" -> Some (`Ubuntu `V21_10) - |"ubuntu-22.04" -> Some (`Ubuntu `V22_04) - |"ubuntu" -> Some (`Ubuntu `Latest) - |"ubuntu-lts" -> Some (`Ubuntu `LTS) - |"debian-stable" -> Some (`Debian `Stable) - |"debian-unstable" -> Some (`Debian `Unstable) - |"debian-testing" -> Some (`Debian `Testing) - |"debian-11" -> Some (`Debian `V11) - |"debian-10" -> Some (`Debian `V10) - |"debian-9" -> Some (`Debian `V9) - |"debian-8" -> Some (`Debian `V8) - |"debian-7" -> Some (`Debian `V7) - |"centos-6" -> Some (`CentOS `V6) - |"centos-7" -> Some (`CentOS `V7) - |"centos-8" -> Some (`CentOS `V8) - |"fedora-21" -> Some (`Fedora `V21) - |"fedora-22" -> Some (`Fedora `V22) - |"fedora-23" -> Some (`Fedora `V23) - |"fedora-24" -> Some (`Fedora `V24) - |"fedora-25" -> Some (`Fedora `V25) - |"fedora-26" -> Some (`Fedora `V26) - |"fedora-27" -> Some (`Fedora `V27) - |"fedora-28" -> Some (`Fedora `V28) - |"fedora-29" -> Some (`Fedora `V29) - |"fedora-30" -> Some (`Fedora `V30) - |"fedora-31" -> Some (`Fedora `V31) - |"fedora-32" -> Some (`Fedora `V32) - |"fedora-33" -> Some (`Fedora `V33) - |"fedora-34" -> Some (`Fedora `V34) - |"fedora-35" -> Some (`Fedora `V35) - |"fedora" -> Some (`Fedora `Latest) - |"oraclelinux-7" -> Some (`OracleLinux `V7) - |"oraclelinux-8" -> Some (`OracleLinux `V8) - |"oraclelinux" -> Some (`OracleLinux `Latest) - |"alpine-3.3" -> Some (`Alpine `V3_3) - |"alpine-3.4" -> Some (`Alpine `V3_4) - |"alpine-3.5" -> Some (`Alpine `V3_5) - |"alpine-3.6" -> Some (`Alpine `V3_6) - |"alpine-3.7" -> Some (`Alpine `V3_7) - |"alpine-3.8" -> Some (`Alpine `V3_8) - |"alpine-3.9" -> Some (`Alpine `V3_9) - |"alpine-3.10" -> Some (`Alpine `V3_10) - |"alpine-3.11" -> Some (`Alpine `V3_11) - |"alpine-3.12" -> Some (`Alpine `V3_12) - |"alpine-3.13" -> Some (`Alpine `V3_13) - |"alpine-3.14" -> Some (`Alpine `V3_14) - |"alpine-3.15" -> Some (`Alpine `V3_15) - |"alpine" -> Some (`Alpine `Latest) - |"archlinux" -> Some (`Archlinux `Latest) - |"opensuse-42.1" -> Some (`OpenSUSE `V42_1) - |"opensuse-42.2" -> Some (`OpenSUSE `V42_2) - |"opensuse-42.3" -> Some (`OpenSUSE `V42_3) - |"opensuse-15.0" -> Some (`OpenSUSE `V15_0) - |"opensuse-15.1" -> Some (`OpenSUSE `V15_1) - |"opensuse-15.2" -> Some (`OpenSUSE `V15_2) - |"opensuse-15.3" -> Some (`OpenSUSE `V15_3) - |"opensuse" -> Some (`OpenSUSE `Latest) + | "ubuntu-12.04" -> Some (`Ubuntu `V12_04) + | "ubuntu-14.04" -> Some (`Ubuntu `V14_04) + | "ubuntu-15.04" -> Some (`Ubuntu `V15_04) + | "ubuntu-15.10" -> Some (`Ubuntu `V15_10) + | "ubuntu-16.04" -> Some (`Ubuntu `V16_04) + | "ubuntu-16.10" -> Some (`Ubuntu `V16_10) + | "ubuntu-17.04" -> Some (`Ubuntu `V17_04) + | "ubuntu-17.10" -> Some (`Ubuntu `V17_10) + | "ubuntu-18.04" -> Some (`Ubuntu `V18_04) + | "ubuntu-18.10" -> Some (`Ubuntu `V18_10) + | "ubuntu-19.04" -> Some (`Ubuntu `V19_04) + | "ubuntu-19.10" -> Some (`Ubuntu `V19_10) + | "ubuntu-20.04" -> Some (`Ubuntu `V20_04) + | "ubuntu-20.10" -> Some (`Ubuntu `V20_10) + | "ubuntu-21.04" -> Some (`Ubuntu `V21_04) + | "ubuntu-21.10" -> Some (`Ubuntu `V21_10) + | "ubuntu-22.04" -> Some (`Ubuntu `V22_04) + | "ubuntu" -> Some (`Ubuntu `Latest) + | "ubuntu-lts" -> Some (`Ubuntu `LTS) + | "debian-stable" -> Some (`Debian `Stable) + | "debian-unstable" -> Some (`Debian `Unstable) + | "debian-testing" -> Some (`Debian `Testing) + | "debian-11" -> Some (`Debian `V11) + | "debian-10" -> Some (`Debian `V10) + | "debian-9" -> Some (`Debian `V9) + | "debian-8" -> Some (`Debian `V8) + | "debian-7" -> Some (`Debian `V7) + | "centos-6" -> Some (`CentOS `V6) + | "centos-7" -> Some (`CentOS `V7) + | "centos-8" -> Some (`CentOS `V8) + | "fedora-21" -> Some (`Fedora `V21) + | "fedora-22" -> Some (`Fedora `V22) + | "fedora-23" -> Some (`Fedora `V23) + | "fedora-24" -> Some (`Fedora `V24) + | "fedora-25" -> Some (`Fedora `V25) + | "fedora-26" -> Some (`Fedora `V26) + | "fedora-27" -> Some (`Fedora `V27) + | "fedora-28" -> Some (`Fedora `V28) + | "fedora-29" -> Some (`Fedora `V29) + | "fedora-30" -> Some (`Fedora `V30) + | "fedora-31" -> Some (`Fedora `V31) + | "fedora-32" -> Some (`Fedora `V32) + | "fedora-33" -> Some (`Fedora `V33) + | "fedora-34" -> Some (`Fedora `V34) + | "fedora-35" -> Some (`Fedora `V35) + | "fedora" -> Some (`Fedora `Latest) + | "oraclelinux-7" -> Some (`OracleLinux `V7) + | "oraclelinux-8" -> Some (`OracleLinux `V8) + | "oraclelinux" -> Some (`OracleLinux `Latest) + | "alpine-3.3" -> Some (`Alpine `V3_3) + | "alpine-3.4" -> Some (`Alpine `V3_4) + | "alpine-3.5" -> Some (`Alpine `V3_5) + | "alpine-3.6" -> Some (`Alpine `V3_6) + | "alpine-3.7" -> Some (`Alpine `V3_7) + | "alpine-3.8" -> Some (`Alpine `V3_8) + | "alpine-3.9" -> Some (`Alpine `V3_9) + | "alpine-3.10" -> Some (`Alpine `V3_10) + | "alpine-3.11" -> Some (`Alpine `V3_11) + | "alpine-3.12" -> Some (`Alpine `V3_12) + | "alpine-3.13" -> Some (`Alpine `V3_13) + | "alpine-3.14" -> Some (`Alpine `V3_14) + | "alpine-3.15" -> Some (`Alpine `V3_15) + | "alpine" -> Some (`Alpine `Latest) + | "archlinux" -> Some (`Archlinux `Latest) + | "opensuse-42.1" -> Some (`OpenSUSE `V42_1) + | "opensuse-42.2" -> Some (`OpenSUSE `V42_2) + | "opensuse-42.3" -> Some (`OpenSUSE `V42_3) + | "opensuse-15.0" -> Some (`OpenSUSE `V15_0) + | "opensuse-15.1" -> Some (`OpenSUSE `V15_1) + | "opensuse-15.2" -> Some (`OpenSUSE `V15_2) + | "opensuse-15.3" -> Some (`OpenSUSE `V15_3) + | "opensuse" -> Some (`OpenSUSE `Latest) | s when String.is_prefix ~affix:"cygwin-" s -> - win10_of_tag "cygwin-" s (fun v -> `Cygwin v) + win10_of_tag "cygwin-" s (fun v -> `Cygwin v) | s when String.is_prefix ~affix:"windows-mingw-" s -> - win10_of_tag "windows-mingw-" s (fun v -> `Windows (`Mingw, v)) + win10_of_tag "windows-mingw-" s (fun v -> `Windows (`Mingw, v)) | s when String.is_prefix ~affix:"windows-msvc-" s -> - win10_of_tag "windows-msvc-" s (fun v -> `Windows (`Msvc, v)) - |_ -> None + win10_of_tag "windows-msvc-" s (fun v -> `Windows (`Msvc, v)) + | _ -> None -let human_readable_string_of_distro (d:t) = - if d = `Debian `Stable then - "Debian Stable" +let human_readable_string_of_distro (d : t) = + if d = `Debian `Stable then "Debian Stable" else match resolve_alias d with - |`Ubuntu `V12_04 -> "Ubuntu 12.04" - |`Ubuntu `V14_04 -> "Ubuntu 14.04" - |`Ubuntu `V15_04 -> "Ubuntu 15.04" - |`Ubuntu `V15_10 -> "Ubuntu 15.10" - |`Ubuntu `V16_04 -> "Ubuntu 16.04" - |`Ubuntu `V16_10 -> "Ubuntu 16.10" - |`Ubuntu `V17_04 -> "Ubuntu 17.04" - |`Ubuntu `V17_10 -> "Ubuntu 17.10" - |`Ubuntu `V18_04 -> "Ubuntu 18.04" - |`Ubuntu `V18_10 -> "Ubuntu 18.10" - |`Ubuntu `V19_04 -> "Ubuntu 19.04" - |`Ubuntu `V19_10 -> "Ubuntu 19.10" - |`Ubuntu `V20_04 -> "Ubuntu 20.04" - |`Ubuntu `V20_10 -> "Ubuntu 20.10" - |`Ubuntu `V21_04 -> "Ubuntu 21.04" - |`Ubuntu `V21_10 -> "Ubuntu 21.10" - |`Ubuntu `V22_04 -> "Ubuntu 22.04" - |`Debian `Unstable -> "Debian Unstable" - |`Debian `Testing -> "Debian Testing" - |`Debian `V11 -> "Debian 11 (Bullseye)" - |`Debian `V10 -> "Debian 10 (Buster)" - |`Debian `V9 -> "Debian 9 (Stretch)" - |`Debian `V8 -> "Debian 8 (Jessie)" - |`Debian `V7 -> "Debian 7 (Wheezy)" - |`CentOS `V6 -> "CentOS 6" - |`CentOS `V7 -> "CentOS 7" - |`CentOS `V8 -> "CentOS 8" - |`Fedora `V21 -> "Fedora 21" - |`Fedora `V22 -> "Fedora 22" - |`Fedora `V23 -> "Fedora 23" - |`Fedora `V24 -> "Fedora 24" - |`Fedora `V25 -> "Fedora 25" - |`Fedora `V26 -> "Fedora 26" - |`Fedora `V27 -> "Fedora 27" - |`Fedora `V28 -> "Fedora 28" - |`Fedora `V29 -> "Fedora 29" - |`Fedora `V30 -> "Fedora 30" - |`Fedora `V31 -> "Fedora 31" - |`Fedora `V32 -> "Fedora 32" - |`Fedora `V33 -> "Fedora 33" - |`Fedora `V34 -> "Fedora 34" - |`Fedora `V35 -> "Fedora 35" - |`OracleLinux `V7 -> "OracleLinux 7" - |`OracleLinux `V8 -> "OracleLinux 8" - |`Alpine `V3_3 -> "Alpine 3.3" - |`Alpine `V3_4 -> "Alpine 3.4" - |`Alpine `V3_5 -> "Alpine 3.5" - |`Alpine `V3_6 -> "Alpine 3.6" - |`Alpine `V3_7 -> "Alpine 3.7" - |`Alpine `V3_8 -> "Alpine 3.8" - |`Alpine `V3_9 -> "Alpine 3.9" - |`Alpine `V3_10 -> "Alpine 3.10" - |`Alpine `V3_11 -> "Alpine 3.11" - |`Alpine `V3_12 -> "Alpine 3.12" - |`Alpine `V3_13 -> "Alpine 3.13" - |`Alpine `V3_14 -> "Alpine 3.14" - |`Alpine `V3_15 -> "Alpine 3.15" - |`Archlinux `Latest -> "Archlinux" - |`OpenSUSE `V42_1 -> "OpenSUSE 42.1" - |`OpenSUSE `V42_2 -> "OpenSUSE 42.2" - |`OpenSUSE `V42_3 -> "OpenSUSE 42.3" - |`OpenSUSE `V15_0 -> "OpenSUSE 15.0 (Leap)" - |`OpenSUSE `V15_1 -> "OpenSUSE 15.1 (Leap)" - |`OpenSUSE `V15_2 -> "OpenSUSE 15.2 (Leap)" - |`OpenSUSE `V15_3 -> "OpenSUSE 15.3 (Leap)" - |`Cygwin v -> "Cygwin " ^ (win10_release_to_string v) - |`Windows (`Mingw, v) -> "Windows mingw " ^ (win10_release_to_string v) - |`Windows (`Msvc, v) -> "Windows mingw " ^ (win10_release_to_string v) - -let human_readable_short_string_of_distro (t:t) = + | `Ubuntu `V12_04 -> "Ubuntu 12.04" + | `Ubuntu `V14_04 -> "Ubuntu 14.04" + | `Ubuntu `V15_04 -> "Ubuntu 15.04" + | `Ubuntu `V15_10 -> "Ubuntu 15.10" + | `Ubuntu `V16_04 -> "Ubuntu 16.04" + | `Ubuntu `V16_10 -> "Ubuntu 16.10" + | `Ubuntu `V17_04 -> "Ubuntu 17.04" + | `Ubuntu `V17_10 -> "Ubuntu 17.10" + | `Ubuntu `V18_04 -> "Ubuntu 18.04" + | `Ubuntu `V18_10 -> "Ubuntu 18.10" + | `Ubuntu `V19_04 -> "Ubuntu 19.04" + | `Ubuntu `V19_10 -> "Ubuntu 19.10" + | `Ubuntu `V20_04 -> "Ubuntu 20.04" + | `Ubuntu `V20_10 -> "Ubuntu 20.10" + | `Ubuntu `V21_04 -> "Ubuntu 21.04" + | `Ubuntu `V21_10 -> "Ubuntu 21.10" + | `Ubuntu `V22_04 -> "Ubuntu 22.04" + | `Debian `Unstable -> "Debian Unstable" + | `Debian `Testing -> "Debian Testing" + | `Debian `V11 -> "Debian 11 (Bullseye)" + | `Debian `V10 -> "Debian 10 (Buster)" + | `Debian `V9 -> "Debian 9 (Stretch)" + | `Debian `V8 -> "Debian 8 (Jessie)" + | `Debian `V7 -> "Debian 7 (Wheezy)" + | `CentOS `V6 -> "CentOS 6" + | `CentOS `V7 -> "CentOS 7" + | `CentOS `V8 -> "CentOS 8" + | `Fedora `V21 -> "Fedora 21" + | `Fedora `V22 -> "Fedora 22" + | `Fedora `V23 -> "Fedora 23" + | `Fedora `V24 -> "Fedora 24" + | `Fedora `V25 -> "Fedora 25" + | `Fedora `V26 -> "Fedora 26" + | `Fedora `V27 -> "Fedora 27" + | `Fedora `V28 -> "Fedora 28" + | `Fedora `V29 -> "Fedora 29" + | `Fedora `V30 -> "Fedora 30" + | `Fedora `V31 -> "Fedora 31" + | `Fedora `V32 -> "Fedora 32" + | `Fedora `V33 -> "Fedora 33" + | `Fedora `V34 -> "Fedora 34" + | `Fedora `V35 -> "Fedora 35" + | `OracleLinux `V7 -> "OracleLinux 7" + | `OracleLinux `V8 -> "OracleLinux 8" + | `Alpine `V3_3 -> "Alpine 3.3" + | `Alpine `V3_4 -> "Alpine 3.4" + | `Alpine `V3_5 -> "Alpine 3.5" + | `Alpine `V3_6 -> "Alpine 3.6" + | `Alpine `V3_7 -> "Alpine 3.7" + | `Alpine `V3_8 -> "Alpine 3.8" + | `Alpine `V3_9 -> "Alpine 3.9" + | `Alpine `V3_10 -> "Alpine 3.10" + | `Alpine `V3_11 -> "Alpine 3.11" + | `Alpine `V3_12 -> "Alpine 3.12" + | `Alpine `V3_13 -> "Alpine 3.13" + | `Alpine `V3_14 -> "Alpine 3.14" + | `Alpine `V3_15 -> "Alpine 3.15" + | `Archlinux `Latest -> "Archlinux" + | `OpenSUSE `V42_1 -> "OpenSUSE 42.1" + | `OpenSUSE `V42_2 -> "OpenSUSE 42.2" + | `OpenSUSE `V42_3 -> "OpenSUSE 42.3" + | `OpenSUSE `V15_0 -> "OpenSUSE 15.0 (Leap)" + | `OpenSUSE `V15_1 -> "OpenSUSE 15.1 (Leap)" + | `OpenSUSE `V15_2 -> "OpenSUSE 15.2 (Leap)" + | `OpenSUSE `V15_3 -> "OpenSUSE 15.3 (Leap)" + | `Cygwin v -> "Cygwin " ^ win10_release_to_string v + | `Windows (`Mingw, v) -> "Windows mingw " ^ win10_release_to_string v + | `Windows (`Msvc, v) -> "Windows mingw " ^ win10_release_to_string v + +let human_readable_short_string_of_distro (t : t) = match t with - |`Ubuntu _ -> "Ubuntu" - |`Debian _ -> "Debian" - |`CentOS _ -> "CentOS" - |`Fedora _ -> "Fedora" - |`OracleLinux _ -> "OracleLinux" - |`Alpine _ -> "Alpine" - |`Archlinux _ -> "Archlinux" - |`OpenSUSE _ -> "OpenSUSE" - |`Cygwin _ -> "Cygwin" - |`Windows (`Mingw, _) -> "Windows mingw" - |`Windows (`Msvc, _) -> "Windows mvsc" - -let is_same_distro (d1:t) (d2:t) = - match d1, d2 with - | `Ubuntu _, `Ubuntu _ | `Debian _, `Debian _ | `CentOS _, `CentOS _ - | `Fedora _, `Fedora _ | `OracleLinux _, `OracleLinux _ - | `Alpine _, `Alpine _ | `Archlinux _, `Archlinux _ - | `OpenSUSE _, `OpenSUSE _ | `Cygwin _, `Cygwin _ -> true + | `Ubuntu _ -> "Ubuntu" + | `Debian _ -> "Debian" + | `CentOS _ -> "CentOS" + | `Fedora _ -> "Fedora" + | `OracleLinux _ -> "OracleLinux" + | `Alpine _ -> "Alpine" + | `Archlinux _ -> "Archlinux" + | `OpenSUSE _ -> "OpenSUSE" + | `Cygwin _ -> "Cygwin" + | `Windows (`Mingw, _) -> "Windows mingw" + | `Windows (`Msvc, _) -> "Windows mvsc" + +let is_same_distro (d1 : t) (d2 : t) = + match (d1, d2) with + | `Ubuntu _, `Ubuntu _ + | `Debian _, `Debian _ + | `CentOS _, `CentOS _ + | `Fedora _, `Fedora _ + | `OracleLinux _, `OracleLinux _ + | `Alpine _, `Alpine _ + | `Archlinux _, `Archlinux _ + | `OpenSUSE _, `OpenSUSE _ + | `Cygwin _, `Cygwin _ -> + true | `Windows (p1, _), `Windows (p2, _) when p1 = p2 -> true | _ -> false (* The alias tag for the latest stable version of this distro *) -let latest_tag_of_distro (t:t) = +let latest_tag_of_distro (t : t) = let latest = List.find (is_same_distro t) latest_distros in tag_of_distro latest -type package_manager = [ `Apt | `Yum | `Apk | `Zypper | `Pacman | `Cygwin | `Windows ] [@@deriving sexp] +type package_manager = + [ `Apt | `Yum | `Apk | `Zypper | `Pacman | `Cygwin | `Windows ] +[@@deriving sexp] -let package_manager (t:t) = +let package_manager (t : t) = match t with - |`Ubuntu _ -> `Apt - |`Debian _ -> `Apt - |`CentOS _ -> `Yum - |`Fedora _ -> `Yum - |`OracleLinux _ -> `Yum - |`Alpine _ -> `Apk - |`Archlinux _ -> `Pacman - |`OpenSUSE _ -> `Zypper - |`Cygwin _ -> `Cygwin - |`Windows _ -> `Windows - -let rec bubblewrap_version (t:t) = + | `Ubuntu _ -> `Apt + | `Debian _ -> `Apt + | `CentOS _ -> `Yum + | `Fedora _ -> `Yum + | `OracleLinux _ -> `Yum + | `Alpine _ -> `Apk + | `Archlinux _ -> `Pacman + | `OpenSUSE _ -> `Zypper + | `Cygwin _ -> `Cygwin + | `Windows _ -> `Windows + +let rec bubblewrap_version (t : t) = match resolve_alias t with | `Ubuntu `V12_04 -> None | `Ubuntu `V14_04 -> None @@ -850,7 +1107,7 @@ let rec bubblewrap_version (t:t) = | `Debian `V9 -> Some (0, 3, 1) | `Debian `V10 -> Some (0, 3, 1) | `Debian `V11 -> Some (0, 4, 1) - | `Debian `Testing -> Some (0, 5, 0) + | `Debian `Testing -> Some (0, 5, 0) | `Debian `Unstable -> Some (0, 5, 0) | `CentOS `V6 -> None | `CentOS `V7 -> None @@ -870,7 +1127,7 @@ let rec bubblewrap_version (t:t) = | `Fedora `V33 -> Some (0, 4, 1) | `Fedora `V34 -> Some (0, 4, 1) | `Fedora `V35 -> Some (0, 5, 0) - | `OracleLinux (`V7|`V8 as v) -> bubblewrap_version (`CentOS v) + | `OracleLinux ((`V7 | `V8) as v) -> bubblewrap_version (`CentOS v) | `Alpine `V3_3 -> None (* Not actually checked *) | `Alpine `V3_4 -> None (* Not actually checked *) | `Alpine `V3_5 -> None (* Not actually checked *) @@ -895,17 +1152,19 @@ let rec bubblewrap_version (t:t) = | `Cygwin _ -> None | `Windows _ -> None -let win10_base_tag ?win10_revision (base:win10_docker_base_image) v = - let base, v = match base, resolve_ltsc v with - | `NanoServer, _ -> "mcr.microsoft.com/windows/nanoserver", v - | `ServerCore, _ -> "mcr.microsoft.com/windows/servercore", v - | `Windows, `V21H2 -> "mcr.microsoft.com/windows/server", `Ltsc2022 - | `Windows, _ -> "mcr.microsoft.com/windows", v in - base, win10_revision_to_string (v, win10_revision) +let win10_base_tag ?win10_revision (base : win10_docker_base_image) v = + let base, v = + match (base, resolve_ltsc v) with + | `NanoServer, _ -> ("mcr.microsoft.com/windows/nanoserver", v) + | `ServerCore, _ -> ("mcr.microsoft.com/windows/servercore", v) + | `Windows, `V21H2 -> ("mcr.microsoft.com/windows/server", `Ltsc2022) + | `Windows, _ -> ("mcr.microsoft.com/windows", v) + in + (base, win10_revision_to_string (v, win10_revision)) -let base_distro_tag ?win10_revision ?(arch=`X86_64) d = +let base_distro_tag ?win10_revision ?(arch = `X86_64) d = match resolve_alias d with - | `Alpine v -> begin + | `Alpine v -> ( let tag = match v with | `V3_3 -> "3.3" @@ -922,13 +1181,9 @@ let base_distro_tag ?win10_revision ?(arch=`X86_64) d = | `V3_14 -> "3.14" | `V3_15 -> "3.15" in - match arch with - | `I386 -> "i386/alpine", tag - | _ -> "alpine", tag - end - | `Archlinux `Latest -> - "archlinux", "latest" - | `Debian v -> begin + match arch with `I386 -> ("i386/alpine", tag) | _ -> ("alpine", tag)) + | `Archlinux `Latest -> ("archlinux", "latest") + | `Debian v -> ( let tag = match v with | `V7 -> "7" @@ -940,10 +1195,9 @@ let base_distro_tag ?win10_revision ?(arch=`X86_64) d = | `Unstable -> "unstable" in match arch with - | `I386 -> "i386/debian", tag - | `Aarch32 -> "arm32v7/debian", tag - | _ -> "debian", tag - end + | `I386 -> ("i386/debian", tag) + | `Aarch32 -> ("arm32v7/debian", tag) + | _ -> ("debian", tag)) | `Ubuntu v -> let tag = match v with @@ -965,10 +1219,10 @@ let base_distro_tag ?win10_revision ?(arch=`X86_64) d = | `V21_10 -> "impish" | `V22_04 -> "jammy" in - "ubuntu", tag + ("ubuntu", tag) | `CentOS v -> let tag = match v with `V6 -> "6" | `V7 -> "7" | `V8 -> "8" in - "centos", tag + ("centos", tag) | `Fedora v -> let tag = match v with @@ -988,13 +1242,10 @@ let base_distro_tag ?win10_revision ?(arch=`X86_64) d = | `V34 -> "34" | `V35 -> "35" in - "fedora", tag + ("fedora", tag) | `OracleLinux v -> - let tag = - match v with - | `V7 -> "7" - | `V8 -> "8" in - "oraclelinux", tag + let tag = match v with `V7 -> "7" | `V8 -> "8" in + ("oraclelinux", tag) | `OpenSUSE v -> let tag = match v with @@ -1006,9 +1257,15 @@ let base_distro_tag ?win10_revision ?(arch=`X86_64) d = | `V15_2 -> "15.2" | `V15_3 -> "15.3" in - "opensuse/leap", tag - | `Cygwin v -> win10_base_tag ?win10_revision `ServerCore (v : win10_release :> [> win10_release]) - | `Windows (_, v) -> win10_base_tag ?win10_revision `Windows (v : win10_release :> [> win10_release]) + ("opensuse/leap", tag) + | `Cygwin v -> + win10_base_tag ?win10_revision `ServerCore + (v : win10_release :> [> win10_release ]) + | `Windows (_, v) -> + win10_base_tag ?win10_revision `Windows + (v : win10_release :> [> win10_release ]) let compare a b = - String.compare (human_readable_string_of_distro a) (human_readable_string_of_distro b) + String.compare + (human_readable_string_of_distro a) + (human_readable_string_of_distro b) diff --git a/src-opam/dockerfile_distro.mli b/src-opam/dockerfile_distro.mli index 3bf10398..f55fb129 100644 --- a/src-opam/dockerfile_distro.mli +++ b/src-opam/dockerfile_distro.mli @@ -22,24 +22,33 @@ (** {2 Known distributions and OCaml variants} *) -type win10_release = [ - | `V1507 | `V1511 | `V1607 - | `V1703 | `V1709 | `V1803 | `V1809 | `V1903 | `V1909 - | `V2004 | `V20H2 | `V21H1 | `V21H2 -] [@@deriving sexp] +type win10_release = + [ `V1507 + | `V1511 + | `V1607 + | `V1703 + | `V1709 + | `V1803 + | `V1809 + | `V1903 + | `V1909 + | `V2004 + | `V20H2 + | `V21H1 + | `V21H2 ] +[@@deriving sexp] (** All Windows 10 release versions. *) -type win10_ltsc = [ - `Ltsc2015 | `Ltsc2016 | `Ltsc2019 | `Ltsc2022 -] [@@deriving sexp] +type win10_ltsc = [ `Ltsc2015 | `Ltsc2016 | `Ltsc2019 | `Ltsc2022 ] +[@@deriving sexp] (** All Windows Long-Term Service Branch releases. LTSC versions are aliased to the semi-annual release they're based on. *) type win_all = [ win10_release | win10_ltsc ] [@@deriving sexp] (** All Windows 10/11 release versions and LTSC names *) -type win10_lcu = [ - | `LCU +type win10_lcu = + [ `LCU | `LCU20220913 | `LCU20220809 | `LCU20220712 @@ -55,8 +64,8 @@ type win10_lcu = [ | `LCU20210914 | `LCU20210810 | `LCU20210713 - | `LCU20210608 -] [@@deriving sexp] + | `LCU20210608 ] +[@@deriving sexp] (** Windows 10 Latest Cumulative Update. Out-of-band LCUs are not included as they aren't released with Docker images. [`LCU] always refers to the most recent LCU. *) @@ -68,32 +77,127 @@ val win10_current_lcu : win10_lcu type win10_revision = win10_release * win10_lcu option [@@deriving sexp] (** A Windows 10 version optionally with an LCU. *) -type distro = [ - | `Alpine of [ `V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15 ] +type distro = + [ `Alpine of + [ `V3_3 + | `V3_4 + | `V3_5 + | `V3_6 + | `V3_7 + | `V3_8 + | `V3_9 + | `V3_10 + | `V3_11 + | `V3_12 + | `V3_13 + | `V3_14 + | `V3_15 ] | `Archlinux of [ `Latest ] | `CentOS of [ `V6 | `V7 | `V8 ] | `Debian of [ `V11 | `V10 | `V9 | `V8 | `V7 | `Testing | `Unstable ] - | `Fedora of [ `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 | `V31 | `V32 | `V33 | `V34 | `V35 ] + | `Fedora of + [ `V21 + | `V22 + | `V23 + | `V24 + | `V25 + | `V26 + | `V27 + | `V28 + | `V29 + | `V30 + | `V31 + | `V32 + | `V33 + | `V34 + | `V35 ] | `OracleLinux of [ `V7 | `V8 ] | `OpenSUSE of [ `V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3 ] - | `Ubuntu of [ `V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 | `V17_10 | `V18_04 | `V18_10 | `V19_04 | `V19_10 | `V20_04 | `V20_10 | `V21_04 | `V21_10 | `V22_04 ] + | `Ubuntu of + [ `V12_04 + | `V14_04 + | `V15_04 + | `V15_10 + | `V16_04 + | `V16_10 + | `V17_04 + | `V17_10 + | `V18_04 + | `V18_10 + | `V19_04 + | `V19_10 + | `V20_04 + | `V20_10 + | `V21_04 + | `V21_10 + | `V22_04 ] | `Cygwin of win10_release - | `Windows of [`Mingw | `Msvc] * win10_release -] [@@deriving sexp] + | `Windows of [ `Mingw | `Msvc ] * win10_release ] +[@@deriving sexp] (** Supported Docker container distributions distributions *) -type t = [ - | `Alpine of [ `V3_3 | `V3_4 | `V3_5 | `V3_6 | `V3_7 | `V3_8 | `V3_9 | `V3_10 | `V3_11 | `V3_12 | `V3_13 | `V3_14 | `V3_15 | `Latest ] +type t = + [ `Alpine of + [ `V3_3 + | `V3_4 + | `V3_5 + | `V3_6 + | `V3_7 + | `V3_8 + | `V3_9 + | `V3_10 + | `V3_11 + | `V3_12 + | `V3_13 + | `V3_14 + | `V3_15 + | `Latest ] | `Archlinux of [ `Latest ] | `CentOS of [ `V6 | `V7 | `V8 | `Latest ] | `Debian of [ `V11 | `V10 | `V9 | `V8 | `V7 | `Stable | `Testing | `Unstable ] - | `Fedora of [ `V21 | `V22 | `V23 | `V24 | `V25 | `V26 | `V27 | `V28 | `V29 | `V30 | `V31 | `V32 | `V33 | `V34 | `V35 | `Latest ] + | `Fedora of + [ `V21 + | `V22 + | `V23 + | `V24 + | `V25 + | `V26 + | `V27 + | `V28 + | `V29 + | `V30 + | `V31 + | `V32 + | `V33 + | `V34 + | `V35 + | `Latest ] | `OracleLinux of [ `V7 | `V8 | `Latest ] - | `OpenSUSE of [ `V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3 | `Latest ] - | `Ubuntu of [ `V12_04 | `V14_04 | `V15_04 | `V15_10 | `V16_04 | `V16_10 | `V17_04 | `V17_10 | `V18_04 | `V18_10 | `V19_04 | `V19_10 | `V20_04 | `V20_10 | `V21_04 | `V21_10 | `V22_04 | `Latest | `LTS ] + | `OpenSUSE of + [ `V42_1 | `V42_2 | `V42_3 | `V15_0 | `V15_1 | `V15_2 | `V15_3 | `Latest ] + | `Ubuntu of + [ `V12_04 + | `V14_04 + | `V15_04 + | `V15_10 + | `V16_04 + | `V16_10 + | `V17_04 + | `V17_10 + | `V18_04 + | `V18_10 + | `V19_04 + | `V19_10 + | `V20_04 + | `V20_10 + | `V21_04 + | `V21_10 + | `V22_04 + | `Latest + | `LTS ] | `Cygwin of win_all - | `Windows of [`Mingw | `Msvc] * win_all -] [@@deriving sexp] + | `Windows of [ `Mingw | `Msvc ] * win_all ] +[@@deriving sexp] (** Supported Docker container distributions *) type os_family = [ `Cygwin | `Linux | `Windows ] [@@deriving sexp] @@ -156,15 +260,15 @@ val human_readable_short_string_of_distro : t -> string (** [human_readable_short_string_of_distro t] returns a human readable short version of the distribution tag, excluding version information. *) -type package_manager = [ - | `Apk (** Alpine Apk *) +type package_manager = + [ `Apk (** Alpine Apk *) | `Apt (** Debian Apt *) | `Yum (** Fedora Yum *) - | `Zypper (** OpenSUSE Zypper *) - | `Pacman (** Archlinux Pacman *) - | `Cygwin (** Cygwin package manager *) - | `Windows (** Native Windows, WinGet, Cygwin *) -] [@@deriving sexp] + | `Zypper (** OpenSUSE Zypper *) + | `Pacman (** Archlinux Pacman *) + | `Cygwin (** Cygwin package manager *) + | `Windows (** Native Windows, WinGet, Cygwin *) ] +[@@deriving sexp] (** The package manager used by a distro. *) val package_manager : t -> package_manager @@ -192,15 +296,18 @@ val latest_tag_of_distro : t -> string regularly rewritten to point to any new releases of the distribution. *) -type win10_docker_base_image = [ - | `NanoServer (** Windows Nano Server *) - | `ServerCore (** Windows Server Core *) - | `Windows (** Windows Server "with Desktop Experience" *) -] +type win10_docker_base_image = + [ `NanoServer (** Windows Nano Server *) + | `ServerCore (** Windows Server Core *) + | `Windows (** Windows Server "with Desktop Experience" *) ] (** Windows containers base images. @see *) -val win10_base_tag : ?win10_revision:win10_lcu -> win10_docker_base_image -> win_all -> string * string +val win10_base_tag : + ?win10_revision:win10_lcu -> + win10_docker_base_image -> + win_all -> + string * string (** [win10_base_tag base_image release] will return a tuple of Windows container base image and tag for which the base image of a Windows base image can be found (e.g. @@ -208,7 +315,8 @@ val win10_base_tag : ?win10_revision:win10_lcu -> win10_docker_base_image -> win [mcr.microsoft.com/windows/servercore:ltsc2022] on the Microsoft Container Registry). *) -val base_distro_tag : ?win10_revision:win10_lcu -> ?arch:Ocaml_version.arch -> t -> string * string +val base_distro_tag : + ?win10_revision:win10_lcu -> ?arch:Ocaml_version.arch -> t -> string * string (** [base_distro_tag ?arch t] will return a tuple of a Docker Hub user/repository and tag for which the base image of a distribution can be found (e.g. [opensuse/leap],[15.0] which maps to [opensuse/leap:15.0] @@ -225,7 +333,6 @@ val win10_release_of_string : string -> win_all option string to its internal representation. Ignores any KB number. *) val win10_revision_to_string : win10_revision -> string - val win10_revision_of_string : string -> win10_revision option (** {2 CPU architectures} *) @@ -246,8 +353,8 @@ type win10_release_status = [ `Deprecated | `Active ] val win10_release_status : win_all -> win10_release_status (* [win10_release_status v channel] returns the Microsoft support - status of the specified Windows 10 release. - @see *) + status of the specified Windows 10 release. + @see *) val active_distros : Ocaml_version.arch -> t list (** [active_distros arch] returns the list of currently supported diff --git a/src-opam/dockerfile_linux.ml b/src-opam/dockerfile_linux.ml index 73ee3cde..1dd9e116 100644 --- a/src-opam/dockerfile_linux.ml +++ b/src-opam/dockerfile_linux.ml @@ -22,9 +22,9 @@ let run_sh fmt = ksprintf (run "sh -c %S") fmt let run_as_user user fmt = ksprintf (run "sudo -u %s sh -c %S" user) fmt module Git = struct - let init ?(name="Docker") ?(email="docker@example.com") () = - run "git config --global user.email %S" email @@ - run "git config --global user.name %S" name + let init ?(name = "Docker") ?(email = "docker@example.com") () = + run "git config --global user.email %S" email + @@ run "git config --global user.name %S" name end let sudo_nopasswd = "ALL=(ALL:ALL) NOPASSWD:ALL" @@ -33,72 +33,85 @@ let sudo_nopasswd = "ALL=(ALL:ALL) NOPASSWD:ALL" module RPM = struct let update = run "yum update -y" let install fmt = ksprintf (run "yum install -y %s && yum clean all") fmt - let groupinstall fmt = ksprintf (run "yum groupinstall -y %s && yum clean all") fmt - let add_user ?uid ?gid ?(sudo=false) username = + let groupinstall fmt = + ksprintf (run "yum groupinstall -y %s && yum clean all") fmt + + let add_user ?uid ?gid ?(sudo = false) username = let uid = match uid with Some u -> sprintf "-u %d " u | None -> "" in let gid = match gid with Some g -> sprintf "-g %d " g | None -> "" in - let home = "/home/"^username in + let home = "/home/" ^ username in (match sudo with | false -> empty | true -> - let sudofile = "/etc/sudoers.d/"^username in - copy_heredoc ~src:[heredoc ~strip:true "\t%s %s" username sudo_nopasswd] ~dst:sudofile () @@ - run "chmod 440 %s" sudofile @@ - run "chown root:root %s" sudofile @@ - run "sed -i.bak 's/^Defaults.*requiretty//g' /etc/sudoers") @@ - run "useradd -d %s %s%s-m -s /bin/bash %s" home uid gid username @@ - run "passwd -l %s" username @@ - run "chown -R %s:%s %s" username username home @@ - user "%s" username @@ - env ["HOME", home] @@ - workdir "%s" home @@ - run "mkdir .ssh" @@ - run "chmod 700 .ssh" + let sudofile = "/etc/sudoers.d/" ^ username in + copy_heredoc + ~src:[ heredoc ~strip:true "\t%s %s" username sudo_nopasswd ] + ~dst:sudofile () + @@ run "chmod 440 %s" sudofile + @@ run "chown root:root %s" sudofile + @@ run "sed -i.bak 's/^Defaults.*requiretty//g' /etc/sudoers") + @@ run "useradd -d %s %s%s-m -s /bin/bash %s" home uid gid username + @@ run "passwd -l %s" username + @@ run "chown -R %s:%s %s" username username home + @@ user "%s" username + @@ env [ ("HOME", home) ] + @@ workdir "%s" home @@ run "mkdir .ssh" @@ run "chmod 700 .ssh" let dev_packages ?extra () = - groupinstall "\"Development Tools\"" @@ - install "sudo passwd bzip2 patch rsync nano gcc-c++ git tar curl xz libX11-devel which m4 diffutils findutils%s" - (match extra with None -> "" | Some x -> " " ^ x) + groupinstall "\"Development Tools\"" + @@ install + "sudo passwd bzip2 patch rsync nano gcc-c++ git tar curl xz \ + libX11-devel which m4 diffutils findutils%s" + (match extra with None -> "" | Some x -> " " ^ x) - let install_system_ocaml = - install "ocaml ocaml-camlp4-devel ocaml-ocamldoc" + let install_system_ocaml = install "ocaml ocaml-camlp4-devel ocaml-ocamldoc" end (** Debian rules *) module Apt = struct - let update = run "apt-get -y update" @@ run "DEBIAN_FRONTEND=noninteractive apt-get -y upgrade" - let install fmt = ksprintf (fun s -> update @@ run "DEBIAN_FRONTEND=noninteractive apt-get -y install %s" s) fmt + let update = + run "apt-get -y update" + @@ run "DEBIAN_FRONTEND=noninteractive apt-get -y upgrade" - let dev_packages ?extra () = - update @@ - copy_heredoc ~src:[heredoc ~strip:true "\tAcquire::Retries \"5\";"] ~dst:"/etc/apt/apt.conf.d/mirror-retry" () @@ - install "build-essential curl git rsync sudo unzip nano libcap-dev libx11-dev%s" - (match extra with None -> "" | Some x -> " " ^ x) + let install fmt = + ksprintf + (fun s -> + update @@ run "DEBIAN_FRONTEND=noninteractive apt-get -y install %s" s) + fmt - let add_user ?uid ?gid ?(sudo=false) username = + let dev_packages ?extra () = + update + @@ copy_heredoc + ~src:[ heredoc ~strip:true "\tAcquire::Retries \"5\";" ] + ~dst:"/etc/apt/apt.conf.d/mirror-retry" () + @@ install + "build-essential curl git rsync sudo unzip nano libcap-dev \ + libx11-dev%s" + (match extra with None -> "" | Some x -> " " ^ x) + + let add_user ?uid ?gid ?(sudo = false) username = let uid = match uid with Some u -> sprintf "--uid %d " u | None -> "" in let gid = match gid with Some g -> sprintf "--gid %d " g | None -> "" in - let home = "/home/"^username in + let home = "/home/" ^ username in (match sudo with | false -> empty | true -> - let sudofile = "/etc/sudoers.d/"^username in - copy_heredoc ~src:[heredoc ~strip:true "\t%s %s" username sudo_nopasswd] ~dst:sudofile () @@ - run "chmod 440 %s" sudofile @@ - run "chown root:root %s" sudofile) @@ - run "adduser %s%s--disabled-password --gecos '' %s" uid gid username @@ - run "passwd -l %s" username @@ - run "chown -R %s:%s %s" username username home @@ - user "%s" username @@ - env ["HOME", home] @@ - workdir "%s" home @@ - run "mkdir .ssh" @@ - run "chmod 700 .ssh" + let sudofile = "/etc/sudoers.d/" ^ username in + copy_heredoc + ~src:[ heredoc ~strip:true "\t%s %s" username sudo_nopasswd ] + ~dst:sudofile () + @@ run "chmod 440 %s" sudofile + @@ run "chown root:root %s" sudofile) + @@ run "adduser %s%s--disabled-password --gecos '' %s" uid gid username + @@ run "passwd -l %s" username + @@ run "chown -R %s:%s %s" username username home + @@ user "%s" username + @@ env [ ("HOME", home) ] + @@ workdir "%s" home @@ run "mkdir .ssh" @@ run "chmod 700 .ssh" let install_system_ocaml = install "ocaml ocaml-native-compilers camlp4-extra rsync" - end (** Alpine rules *) @@ -107,33 +120,34 @@ module Apk = struct let install fmt = ksprintf (fun s -> update @@ run "apk add %s" s) fmt let dev_packages ?extra () = - install "build-base patch tar ca-certificates git rsync curl sudo bash libx11-dev nano coreutils xz libexecinfo-dev ncurses-dev%s" + install + "build-base patch tar ca-certificates git rsync curl sudo bash \ + libx11-dev nano coreutils xz libexecinfo-dev ncurses-dev%s" (match extra with None -> "" | Some x -> " " ^ x) - let add_user ?uid ?gid ?(sudo=false) username = - let home = "/home/"^username in + let add_user ?uid ?gid ?(sudo = false) username = + let home = "/home/" ^ username in (match gid with - | None -> empty - | Some gid -> run "addgroup -S -g %d %s" gid username) @@ - run "adduser -S %s%s%s" - (match uid with None -> "" | Some d -> sprintf "-u %d " d) - (match gid with None -> "" | Some _ -> sprintf "-G %s " username) - username @@ - (match sudo with - | false -> empty - | true -> - let sudofile = "/etc/sudoers.d/"^username in - copy_heredoc ~src:[heredoc ~strip:true "\t%s %s" username sudo_nopasswd] ~dst:sudofile () @@ - run "chmod 440 %s" sudofile @@ - run "chown root:root %s" sudofile @@ - run "sed -i.bak 's/^Defaults.*requiretty//g' /etc/sudoers") @@ - user "%s" username @@ - workdir "%s" home @@ - run "mkdir .ssh" @@ - run "chmod 700 .ssh" - - let install_system_ocaml = - run "apk add ocaml camlp4" + | None -> empty + | Some gid -> run "addgroup -S -g %d %s" gid username) + @@ run "adduser -S %s%s%s" + (match uid with None -> "" | Some d -> sprintf "-u %d " d) + (match gid with None -> "" | Some _ -> sprintf "-G %s " username) + username + @@ (match sudo with + | false -> empty + | true -> + let sudofile = "/etc/sudoers.d/" ^ username in + copy_heredoc + ~src:[ heredoc ~strip:true "\t%s %s" username sudo_nopasswd ] + ~dst:sudofile () + @@ run "chmod 440 %s" sudofile + @@ run "chown root:root %s" sudofile + @@ run "sed -i.bak 's/^Defaults.*requiretty//g' /etc/sudoers") + @@ user "%s" username @@ workdir "%s" home @@ run "mkdir .ssh" + @@ run "chmod 700 .ssh" + + let install_system_ocaml = run "apk add ocaml camlp4" let add_repository ?tag url = run "<<-EOF cat >> /etc/apk/repositories\n\t%s\nEOF" @@ -142,41 +156,49 @@ module Apk = struct let add_repositories repos = let repos = String.concat "" - (List.map (function None, url -> url | Some tag, url -> sprintf "\n\t@%s %s" tag url) repos) in + (List.map + (function + | None, url -> url | Some tag, url -> sprintf "\n\t@%s %s" tag url) + repos) + in run "<<-EOF cat >> /etc/apk/repositories%s\nEOF" repos - end (* Zypper (opensuse) rules *) module Zypper = struct let update = run "zypper update -y" - let install fmt = ksprintf (fun s -> update @@ run "zypper install --force-resolution -y %s" s) fmt - let dev_packages ?extra () = - install "-t pattern devel_C_C++" @@ - install "sudo git unzip curl gcc-c++ libcap-devel xz libX11-devel bzip2 which rsync" @@ - (maybe (install "%s") extra) + let install fmt = + ksprintf + (fun s -> update @@ run "zypper install --force-resolution -y %s" s) + fmt - let add_user ?uid ?gid ?(sudo=false) username = - let home = "/home/"^username in + let dev_packages ?extra () = + install "-t pattern devel_C_C++" + @@ install + "sudo git unzip curl gcc-c++ libcap-devel xz libX11-devel bzip2 which \ + rsync" + @@ maybe (install "%s") extra + + let add_user ?uid ?gid ?(sudo = false) username = + let home = "/home/" ^ username in run "useradd %s%s -d %s -m --user-group %s" (match uid with None -> "" | Some d -> sprintf "-u %d " d) (match gid with None -> "" | Some g -> sprintf "-g %d " g) - home username @@ - (match sudo with - | false -> empty - | true -> - let sudofile = "/etc/sudoers.d/"^username in - copy_heredoc ~src:[heredoc ~strip:true "\t%s %s" username sudo_nopasswd] ~dst:sudofile () @@ - run "chmod 440 %s" sudofile @@ - run "chown root:root %s" sudofile) @@ - user "%s" username @@ - workdir "%s" home @@ - run "mkdir .ssh" @@ - run "chmod 700 .ssh" - - let install_system_ocaml = - install "ocaml camlp4 ocaml-ocamldoc" + home username + @@ (match sudo with + | false -> empty + | true -> + let sudofile = "/etc/sudoers.d/" ^ username in + copy_heredoc + ~src:[ heredoc ~strip:true "\t%s %s" username sudo_nopasswd ] + ~dst:sudofile () + @@ run "chmod 440 %s" sudofile + @@ run "chown root:root %s" sudofile) + @@ user "%s" username @@ workdir "%s" home @@ run "mkdir .ssh" + @@ run "chmod 700 .ssh" + + let install_system_ocaml = install "ocaml camlp4 ocaml-ocamldoc" end (** Pacman rules *) @@ -185,27 +207,28 @@ module Pacman = struct let install fmt = ksprintf (fun s -> run "pacman -Syu --noconfirm %s" s) fmt let dev_packages ?extra () = - install "make gcc patch tar ca-certificates git rsync curl sudo bash libx11 nano coreutils xz ncurses diffutils unzip%s" + install + "make gcc patch tar ca-certificates git rsync curl sudo bash libx11 nano \ + coreutils xz ncurses diffutils unzip%s" (match extra with None -> "" | Some x -> " " ^ x) - let add_user ?uid ?gid ?(sudo=false) username = - let home = "/home/"^username in + let add_user ?uid ?gid ?(sudo = false) username = + let home = "/home/" ^ username in run "useradd %s%s -d %s -m --user-group %s" (match uid with None -> "" | Some d -> sprintf "-u %d " d) (match gid with None -> "" | Some g -> sprintf "-g %d " g) - home username @@ - (match sudo with - | false -> empty - | true -> - let sudofile = "/etc/sudoers.d/"^username in - copy_heredoc ~src:[heredoc ~strip:true "\t%s %s" username sudo_nopasswd] ~dst:sudofile () @@ - run "chmod 440 %s" sudofile @@ - run "chown root:root %s" sudofile) @@ - user "%s" username @@ - workdir "%s" home @@ - run "mkdir .ssh" @@ - run "chmod 700 .ssh" - - let install_system_ocaml = - run "pacman add ocaml ocaml-compiler-libs" + home username + @@ (match sudo with + | false -> empty + | true -> + let sudofile = "/etc/sudoers.d/" ^ username in + copy_heredoc + ~src:[ heredoc ~strip:true "\t%s %s" username sudo_nopasswd ] + ~dst:sudofile () + @@ run "chmod 440 %s" sudofile + @@ run "chown root:root %s" sudofile) + @@ user "%s" username @@ workdir "%s" home @@ run "mkdir .ssh" + @@ run "chmod 700 .ssh" + + let install_system_ocaml = run "pacman add ocaml ocaml-compiler-libs" end diff --git a/src-opam/dockerfile_opam.ml b/src-opam/dockerfile_opam.ml index 5c4cf86a..588aa9a2 100644 --- a/src-opam/dockerfile_opam.ml +++ b/src-opam/dockerfile_opam.ml @@ -36,108 +36,131 @@ let maybe_link_opam add_default_link prefix branch = else empty (* Build opam in a separate worktree from an already cloned opam *) -let install_opam_from_source ?(add_default_link=true) ?(prefix= "/usr/local") ?(enable_0install_solver=false) ~branch ~hash () = +let install_opam_from_source ?(add_default_link = true) ?(prefix = "/usr/local") + ?(enable_0install_solver = false) ~branch ~hash () = run - "cd /tmp/opam-sources && cp -P -R -p . ../opam-build-%s && \ - cd ../opam-build-%s && git checkout %s && \ - ln -s ../opam/src_ext/archives src_ext/archives && \ - env PATH=\"/tmp/opam/bootstrap/ocaml/bin:$PATH\" ./configure --enable-cold-check%s && \ - env PATH=\"/tmp/opam/bootstrap/ocaml/bin:$PATH\" make lib-ext all && \ - mkdir -p %s/bin && cp /tmp/opam-build-%s/opam %s/bin/opam-%s && chmod a+x %s/bin/opam-%s && \ - rm -rf /tmp/opam-build-%s" - branch branch hash (if enable_0install_solver then " --with-0install-solver" else "") - prefix branch prefix branch prefix branch branch @@ - maybe_link_opam add_default_link prefix branch + "cd /tmp/opam-sources && cp -P -R -p . ../opam-build-%s && cd \ + ../opam-build-%s && git checkout %s && ln -s ../opam/src_ext/archives \ + src_ext/archives && env PATH=\"/tmp/opam/bootstrap/ocaml/bin:$PATH\" \ + ./configure --enable-cold-check%s && env \ + PATH=\"/tmp/opam/bootstrap/ocaml/bin:$PATH\" make lib-ext all && mkdir -p \ + %s/bin && cp /tmp/opam-build-%s/opam %s/bin/opam-%s && chmod a+x \ + %s/bin/opam-%s && rm -rf /tmp/opam-build-%s" + branch branch hash + (if enable_0install_solver then " --with-0install-solver" else "") + prefix branch prefix branch prefix branch branch + @@ maybe_link_opam add_default_link prefix branch let bubblewrap_minimum = (0, 4, 1) -let maybe_build_bubblewrap_from_source ?(prefix="/usr/local") distro = +let maybe_build_bubblewrap_from_source ?(prefix = "/usr/local") distro = let major, minor, revision = bubblewrap_minimum in match D.bubblewrap_version distro with | Some release when release >= bubblewrap_minimum -> empty | _ -> - let rel = Printf.sprintf "%d.%d.%d" major minor revision in - let file = Printf.sprintf "bubblewrap-%s.tar.xz" rel in - let url = Printf.sprintf "https://github.com/projectatomic/bubblewrap/releases/download/v%s/bubblewrap-%s.tar.xz" rel rel in - run "curl -fOL %s" url @@ - run "tar xf %s" file @@ - run "cd bubblewrap-%s && ./configure --prefix=%s && make && sudo make install" rel prefix @@ - run "rm -rf %s bubblewrap-%s" file rel + let rel = Printf.sprintf "%d.%d.%d" major minor revision in + let file = Printf.sprintf "bubblewrap-%s.tar.xz" rel in + let url = + Printf.sprintf + "https://github.com/projectatomic/bubblewrap/releases/download/v%s/bubblewrap-%s.tar.xz" + rel rel + in + run "curl -fOL %s" url @@ run "tar xf %s" file + @@ run + "cd bubblewrap-%s && ./configure --prefix=%s && make && sudo make \ + install" + rel prefix + @@ run "rm -rf %s bubblewrap-%s" file rel let bubblewrap_and_dev_packages distro = - let dev_packages = match D.package_manager distro with - | `Apk -> Linux.Apk.dev_packages - | `Apt -> Linux.Apt.dev_packages - | `Yum -> Linux.RPM.dev_packages - | `Zypper -> Linux.Zypper.dev_packages - | `Pacman -> Linux.Pacman.dev_packages - | `Cygwin | `Windows -> assert false + let dev_packages = + match D.package_manager distro with + | `Apk -> Linux.Apk.dev_packages + | `Apt -> Linux.Apt.dev_packages + | `Yum -> Linux.RPM.dev_packages + | `Zypper -> Linux.Zypper.dev_packages + | `Pacman -> Linux.Pacman.dev_packages + | `Cygwin | `Windows -> assert false in match D.bubblewrap_version distro with | Some version when version >= bubblewrap_minimum -> - dev_packages ~extra:"bubblewrap" () + dev_packages ~extra:"bubblewrap" () | _ -> - copy ~from:"0" ~src:["/usr/local/bin/bwrap"] ~dst:"/usr/bin/bwrap" () - @@ dev_packages () + copy ~from:"0" ~src:[ "/usr/local/bin/bwrap" ] ~dst:"/usr/bin/bwrap" () + @@ dev_packages () let install_bubblewrap_wrappers = let strip = true in - let opamrc_sandbox = heredoc ~strip -{| wrap-build-commands: ["%%{hooks}%%/sandbox.sh" "build"] + let opamrc_sandbox = + heredoc ~strip + {| wrap-build-commands: ["%%{hooks}%%/sandbox.sh" "build"] wrap-install-commands: ["%%{hooks}%%/sandbox.sh" "install"] - wrap-remove-commands: ["%%{hooks}%%/sandbox.sh" "remove"]|} in - let opamrc_nosandbox = heredoc ~strip -{| wrap-build-commands: [] + wrap-remove-commands: ["%%{hooks}%%/sandbox.sh" "remove"]|} + in + let opamrc_nosandbox = + heredoc ~strip + {| wrap-build-commands: [] wrap-install-commands: [] wrap-remove-commands: [] - required-tools: []|} in - let sandbox_enable = heredoc ~strip -{| #!/bin/sh + required-tools: []|} + in + let sandbox_enable = + heredoc ~strip + {| #!/bin/sh cp ~/.opamrc-sandbox ~/.opamrc - echo --- opam sandboxing enabled|} in - let sandbox_disable = heredoc ~strip -{| #!/bin/sh + echo --- opam sandboxing enabled|} + in + let sandbox_disable = + heredoc ~strip + {| #!/bin/sh cp ~/.opamrc-nosandbox ~/.opamrc - echo --- opam sandboxing disabled|} in + echo --- opam sandboxing disabled|} + in (* Disable bubblewrap *) - copy_heredoc ~chown:"opam" ~src:[opamrc_nosandbox] ~dst:"/home/opam/.opamrc-nosandbox" () @@ - copy_heredoc ~chown:"opam" ~src:[sandbox_disable] ~dst:"/home/opam/opam-sandbox-disable" () @@ - run "chmod a+x /home/opam/opam-sandbox-disable" @@ - run "sudo mv /home/opam/opam-sandbox-disable /usr/bin/opam-sandbox-disable" @@ + copy_heredoc ~chown:"opam" ~src:[ opamrc_nosandbox ] + ~dst:"/home/opam/.opamrc-nosandbox" () + @@ copy_heredoc ~chown:"opam" ~src:[ sandbox_disable ] + ~dst:"/home/opam/opam-sandbox-disable" () + @@ run "chmod a+x /home/opam/opam-sandbox-disable" + @@ run "sudo mv /home/opam/opam-sandbox-disable /usr/bin/opam-sandbox-disable" (* Enable bubblewrap *) - copy_heredoc ~chown:"opam" ~src:[opamrc_sandbox] ~dst:"/home/opam/.opamrc-sandbox" () @@ - copy_heredoc ~chown:"opam" ~src:[sandbox_enable] ~dst:"/home/opam/opam-sandbox-enable" () @@ - run "chmod a+x /home/opam/opam-sandbox-enable" @@ - run "sudo mv /home/opam/opam-sandbox-enable /usr/bin/opam-sandbox-enable" + @@ copy_heredoc ~chown:"opam" ~src:[ opamrc_sandbox ] + ~dst:"/home/opam/.opamrc-sandbox" () + @@ copy_heredoc ~chown:"opam" ~src:[ sandbox_enable ] + ~dst:"/home/opam/opam-sandbox-enable" () + @@ run "chmod a+x /home/opam/opam-sandbox-enable" + @@ run "sudo mv /home/opam/opam-sandbox-enable /usr/bin/opam-sandbox-enable" let header ?win10_revision ?arch ?maintainer ?img ?tag d = let platform = match arch with | Some `I386 -> Some "386" | Some `Aarch32 -> Some "arm" - | _ -> None in + | _ -> None + in let shell = match personality ?arch d with - | Some pers -> shell [pers; "/bin/bash"; "-c"] - | None -> empty in + | Some pers -> shell [ pers; "/bin/bash"; "-c" ] + | None -> empty + in let maintainer = match maintainer with | Some t -> Dockerfile.maintainer "%s" t - | None -> empty in + | None -> empty + in let parser_directives = match D.os_family_of_distro d with | `Windows | `Cygwin -> parser_directive (`Escape '`') - | _ -> parser_directive (`Syntax "docker/dockerfile:1") in + | _ -> parser_directive (`Syntax "docker/dockerfile:1") + in let img, tag = let dimg, dtag = D.base_distro_tag ?win10_revision ?arch d in let value default = function None -> default | Some str -> str in - value dimg img, value dtag tag + (value dimg img, value dtag tag) in - parser_directives @@ - comment "Autogenerated by OCaml-Dockerfile scripts" @@ - from ?platform ~tag img - @@ maintainer - @@ shell + parser_directives + @@ comment "Autogenerated by OCaml-Dockerfile scripts" + @@ from ?platform ~tag img @@ maintainer @@ shell type opam_hashes = { opam_2_0_hash : string; @@ -154,82 +177,92 @@ type opam_branch = { } let create_opam_branches opam_hashes = - let { - opam_2_0_hash; - opam_2_1_hash; - opam_master_hash; - } = opam_hashes in - opam_master_hash, - [ - { - branch = "2.0"; - hash = opam_2_0_hash; - enable_0install_solver = false; - public_name = "opam-2.0"; - aliases = ["opam"]; (* Default *) - }; - { - branch = "2.1"; - hash = opam_2_1_hash; - enable_0install_solver = true; - public_name = "opam-2.1"; - aliases = []; - }; - { - branch = "master"; - hash = opam_master_hash; - enable_0install_solver = true; - public_name = "opam-dev"; - aliases = ["opam-2.2"]; (* TODO: Remove/update when opam 2.2 is branched *) - }; - ] + let { opam_2_0_hash; opam_2_1_hash; opam_master_hash } = opam_hashes in + ( opam_master_hash, + [ + { + branch = "2.0"; + hash = opam_2_0_hash; + enable_0install_solver = false; + public_name = "opam-2.0"; + aliases = [ "opam" ]; + (* Default *) + }; + { + branch = "2.1"; + hash = opam_2_1_hash; + enable_0install_solver = true; + public_name = "opam-2.1"; + aliases = []; + }; + { + branch = "master"; + hash = opam_master_hash; + enable_0install_solver = true; + public_name = "opam-dev"; + aliases = [ "opam-2.2" ]; + (* TODO: Remove/update when opam 2.2 is branched *) + }; + ] ) let install_opams ?prefix opam_master_hash opam_branches = - run "git clone https://github.com/ocaml/opam /tmp/opam && \ - cd /tmp/opam && cp -P -R -p . ../opam-sources && \ - git checkout %s && \ - env MAKE='make -j' shell/bootstrap-ocaml.sh && \ - make -C src_ext cache-archives" opam_master_hash @@ - List.fold_left (fun acc {branch; hash; enable_0install_solver; _} -> - let add_default_link = Some false in - let enable_0install_solver = Some enable_0install_solver in - acc @@ install_opam_from_source ?add_default_link ?prefix ?enable_0install_solver ~branch ~hash () - ) empty opam_branches + run + "git clone https://github.com/ocaml/opam /tmp/opam && cd /tmp/opam && cp \ + -P -R -p . ../opam-sources && git checkout %s && env MAKE='make -j' \ + shell/bootstrap-ocaml.sh && make -C src_ext cache-archives" + opam_master_hash + @@ List.fold_left + (fun acc { branch; hash; enable_0install_solver; _ } -> + let add_default_link = Some false in + let enable_0install_solver = Some enable_0install_solver in + acc + @@ install_opam_from_source ?add_default_link ?prefix + ?enable_0install_solver ~branch ~hash ()) + empty opam_branches let copy_opams ~src ~dst opam_branches = - List.fold_left (fun acc {branch; public_name; aliases; _} -> - acc @@ - copy ~from:"0" ~src:[src^"/opam-"^branch] ~dst:(dst^"/"^public_name) () @@@ - List.map (fun alias -> run "ln %s/%s %s/%s" dst public_name dst alias) aliases - ) empty opam_branches + List.fold_left + (fun acc { branch; public_name; aliases; _ } -> + acc + @@ copy ~from:"0" + ~src:[ src ^ "/opam-" ^ branch ] + ~dst:(dst ^ "/" ^ public_name) + () + @@@ List.map + (fun alias -> run "ln %s/%s %s/%s" dst public_name dst alias) + aliases) + empty opam_branches (* Apk based Dockerfile *) -let apk_opam2 ?(labels=[]) ?arch ~opam_hashes distro () = +let apk_opam2 ?(labels = []) ?arch ~opam_hashes distro () = let opam_master_hash, opam_branches = create_opam_branches opam_hashes in let img, tag = D.base_distro_tag ?arch distro in - header ?arch distro @@ label (("distro_style", "apk") :: labels) + header ?arch distro + @@ label (("distro_style", "apk") :: labels) @@ Linux.Apk.install "build-base bzip2 git tar curl ca-certificates openssl" @@ Linux.Git.init () @@ maybe_build_bubblewrap_from_source distro @@ install_opams opam_master_hash opam_branches @@ run "strip /usr/local/bin/opam*" @@ from ~tag img - @@ Linux.Apk.add_repositories [ - Some "edge", "https://dl-cdn.alpinelinux.org/alpine/edge/main"; - Some "edgecommunity", "https://dl-cdn.alpinelinux.org/alpine/edge/community"; - Some "testing", "https://dl-cdn.alpinelinux.org/alpine/edge/testing"; + @@ Linux.Apk.add_repositories + [ + (Some "edge", "https://dl-cdn.alpinelinux.org/alpine/edge/main"); + ( Some "edgecommunity", + "https://dl-cdn.alpinelinux.org/alpine/edge/community" ); + (Some "testing", "https://dl-cdn.alpinelinux.org/alpine/edge/testing"); ] @@ bubblewrap_and_dev_packages distro @@ copy_opams ~src:"/usr/local/bin" ~dst:"/usr/bin" opam_branches @@ Linux.Apk.add_user ~uid:1000 ~gid:1000 ~sudo:true "opam" @@ install_bubblewrap_wrappers @@ Linux.Git.init () - (* Debian based Dockerfile *) -let apt_opam2 ?(labels=[]) ?arch distro ~opam_hashes () = +let apt_opam2 ?(labels = []) ?arch distro ~opam_hashes () = let opam_master_hash, opam_branches = create_opam_branches opam_hashes in let img, tag = D.base_distro_tag ?arch distro in - header ?arch distro @@ label (("distro_style", "apt") :: labels) + header ?arch distro + @@ label (("distro_style", "apt") :: labels) @@ Linux.Apt.install "build-essential curl git libcap-dev sudo" @@ Linux.Git.init () @@ maybe_build_bubblewrap_from_source distro @@ -238,11 +271,12 @@ let apt_opam2 ?(labels=[]) ?arch distro ~opam_hashes () = @@ run "ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime" @@ bubblewrap_and_dev_packages distro @@ copy_opams ~src:"/usr/local/bin" ~dst:"/usr/bin" opam_branches - @@ run "echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections" + @@ run + "echo 'debconf debconf/frontend select Noninteractive' | \ + debconf-set-selections" @@ Linux.Apt.add_user ~uid:1000 ~sudo:true "opam" @@ install_bubblewrap_wrappers @@ Linux.Git.init () - (* RPM based Dockerfile. [yum_workaround] activates the overlay/yum workaround needed @@ -250,40 +284,43 @@ let apt_opam2 ?(labels=[]) ?arch distro ~opam_hashes () = [enable_powertools] enables the PowerTools repository on CentOS 8 and above. This is needed to get most of *-devel packages frequently used by opam packages. *) -let yum_opam2 ?(labels= []) ?arch ~yum_workaround ~enable_powertools ~opam_hashes distro () = +let yum_opam2 ?(labels = []) ?arch ~yum_workaround ~enable_powertools + ~opam_hashes distro () = let opam_master_hash, opam_branches = create_opam_branches opam_hashes in let img, tag = D.base_distro_tag ?arch distro in let workaround = if yum_workaround then - run "touch /var/lib/rpm/*" - @@ Linux.RPM.install "yum-plugin-ovl" + run "touch /var/lib/rpm/*" @@ Linux.RPM.install "yum-plugin-ovl" else empty in - header ?arch distro @@ label (("distro_style", "rpm") :: labels) + header ?arch distro + @@ label (("distro_style", "rpm") :: labels) @@ run "yum --version || dnf install -y yum" - @@ workaround - @@ Linux.RPM.update + @@ workaround @@ Linux.RPM.update @@ Linux.RPM.dev_packages ~extra:"which tar curl xz libcap-devel openssl" () @@ Linux.Git.init () @@ maybe_build_bubblewrap_from_source distro @@ install_opams ~prefix:"/usr" opam_master_hash opam_branches @@ from ~tag img @@ run "yum --version || dnf install -y yum" - @@ workaround - @@ Linux.RPM.update + @@ workaround @@ Linux.RPM.update @@ bubblewrap_and_dev_packages distro @@ copy_opams ~src:"/usr/bin" ~dst:"/usr/bin" opam_branches - @@ (if enable_powertools then run "yum config-manager --set-enabled powertools" @@ Linux.RPM.update else empty) + @@ (if enable_powertools then + run "yum config-manager --set-enabled powertools" @@ Linux.RPM.update + else empty) @@ run - "sed -i.bak '/LC_TIME LC_ALL LANGUAGE/aDefaults env_keep += \"OPAMYES OPAMJOBS OPAMVERBOSE\"' /etc/sudoers" + "sed -i.bak '/LC_TIME LC_ALL LANGUAGE/aDefaults env_keep += \ + \"OPAMYES OPAMJOBS OPAMVERBOSE\"' /etc/sudoers" @@ Linux.RPM.add_user ~uid:1000 ~sudo:true "opam" @@ install_bubblewrap_wrappers @@ Linux.Git.init () (* Zypper based Dockerfile *) -let zypper_opam2 ?(labels=[]) ?arch ~opam_hashes distro () = +let zypper_opam2 ?(labels = []) ?arch ~opam_hashes distro () = let opam_master_hash, opam_branches = create_opam_branches opam_hashes in let img, tag = D.base_distro_tag ?arch distro in - header ?arch distro @@ label (("distro_style", "zypper") :: labels) + header ?arch distro + @@ label (("distro_style", "zypper") :: labels) @@ Linux.Zypper.dev_packages () @@ Linux.Git.init () @@ maybe_build_bubblewrap_from_source distro @@ -295,10 +332,11 @@ let zypper_opam2 ?(labels=[]) ?arch ~opam_hashes distro () = @@ install_bubblewrap_wrappers @@ Linux.Git.init () (* Pacman based Dockerfile *) -let pacman_opam2 ?(labels=[]) ?arch ~opam_hashes distro () = +let pacman_opam2 ?(labels = []) ?arch ~opam_hashes distro () = let opam_master_hash, opam_branches = create_opam_branches opam_hashes in let img, tag = D.base_distro_tag ?arch distro in - header ?arch distro @@ label (("distro_style", "pacman") :: labels) + header ?arch distro + @@ label (("distro_style", "pacman") :: labels) @@ Linux.Pacman.dev_packages () @@ Linux.Git.init () @@ maybe_build_bubblewrap_from_source distro @@ -311,11 +349,15 @@ let pacman_opam2 ?(labels=[]) ?arch ~opam_hashes distro () = @@ install_bubblewrap_wrappers @@ Linux.Git.init () (* Cygwin based Dockerfile *) -let cygwin_opam2 ?win10_revision ?(labels=[]) ?arch ~opam_hashes distro () = +let cygwin_opam2 ?win10_revision ?(labels = []) ?arch ~opam_hashes distro () = let opam_master_hash, opam_branches = create_opam_branches opam_hashes in let img, tag = D.base_distro_tag ?arch distro in - let cyg = Windows.Cygwin.{ default with args = "--allow-test-packages" :: default.args } in - header ?win10_revision ?arch distro @@ label (("distro_style", "cygwin") :: labels) + let cyg = + Windows.Cygwin. + { default with args = "--allow-test-packages" :: default.args } + in + header ?win10_revision ?arch distro + @@ label (("distro_style", "cygwin") :: labels) @@ user "ContainerAdministrator" @@ Windows.Cygwin.(setup ~cyg ~extra:(cygwin_packages ()) ()) @@ Windows.Cygwin.Git.init () @@ -330,166 +372,224 @@ let cygwin_opam2 ?win10_revision ?(labels=[]) ?arch ~opam_hashes distro () = add an option to enable 0install-solver, and pass ~hash_opam_2_0 ~hash_opam_2_1 like the cygwin one *) (* Native Windows, WinGet, Cygwin based Dockerfiles *) -let windows_opam2 ?win10_revision ?winget ?(labels=[]) ?arch distro () = +let windows_opam2 ?win10_revision ?winget ?(labels = []) ?arch distro () = let version = match distro with `Windows (_, v) -> v | _ -> assert false in (match winget with - | None when Windows.Winget.is_supported version -> Windows.Winget.install_from_release ?win10_revision ~version () + | None when Windows.Winget.is_supported version -> + Windows.Winget.install_from_release ?win10_revision ~version () | _ -> empty) - @@ header ?win10_revision ?arch distro @@ label (("distro_style", "windows") :: labels) + @@ header ?win10_revision ?arch distro + @@ label (("distro_style", "windows") :: labels) @@ user "ContainerAdministrator" - @@ begin - let extra, t = match distro with - | `Windows (`Mingw, _) -> - Windows.Cygwin.mingw_packages (), empty + @@ (let extra, t = + match distro with + | `Windows (`Mingw, _) -> (Windows.Cygwin.mingw_packages (), empty) | `Windows (`Msvc, _) -> - Windows.Cygwin.msvc_packages (), - Windows.install_visual_studio_build_tools [ - "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"; - "Microsoft.VisualStudio.Component.Windows10SDK.18362"] + ( Windows.Cygwin.msvc_packages (), + Windows.install_visual_studio_build_tools + [ + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"; + "Microsoft.VisualStudio.Component.Windows10SDK.18362"; + ] ) | _ -> invalid_arg "Invalid distribution" in let extra, t' = Windows.Cygwin.ocaml_for_windows_packages ~extra () in - Windows.install_vc_redist () @@ t + Windows.install_vc_redist () + @@ t @@ Windows.sanitize_reg_path () - @@ Windows.Cygwin.setup ~extra () @@ t' - end - @@ begin if Windows.Winget.is_supported version then + @@ Windows.Cygwin.setup ~extra () + @@ t') + @@ (if Windows.Winget.is_supported version then Windows.Winget.setup ?from:winget () @@ Windows.Winget.dev_packages ~version () - else empty end - @@ Windows.Cygwin.Git.init () - @@ Windows.cleanup () - -let gen_opam2_distro ?win10_revision ?winget ?(clone_opam_repo=true) ?arch ?labels ~opam_hashes d = - let fn = match D.package_manager d with - | `Apk -> apk_opam2 ?labels ?arch ~opam_hashes d () - | `Apt -> apt_opam2 ?labels ?arch ~opam_hashes d () - | `Yum -> - let yum_workaround = match d with `CentOS `V7 -> true | _ -> false in - let enable_powertools = match d with `CentOS (`V6 | `V7) -> false | `CentOS _ -> true | _ -> false in - yum_opam2 ?labels ?arch ~yum_workaround ~enable_powertools ~opam_hashes d () - | `Zypper -> zypper_opam2 ?labels ?arch ~opam_hashes d () - | `Pacman -> pacman_opam2 ?labels ?arch ~opam_hashes d () - | `Cygwin -> cygwin_opam2 ?win10_revision ?labels ?arch ~opam_hashes d () - | `Windows -> windows_opam2 ?win10_revision ?winget ?labels ?arch d () + else empty) + @@ Windows.Cygwin.Git.init () @@ Windows.cleanup () + +let gen_opam2_distro ?win10_revision ?winget ?(clone_opam_repo = true) ?arch + ?labels ~opam_hashes d = + let fn = + match D.package_manager d with + | `Apk -> apk_opam2 ?labels ?arch ~opam_hashes d () + | `Apt -> apt_opam2 ?labels ?arch ~opam_hashes d () + | `Yum -> + let yum_workaround = match d with `CentOS `V7 -> true | _ -> false in + let enable_powertools = + match d with + | `CentOS (`V6 | `V7) -> false + | `CentOS _ -> true + | _ -> false + in + yum_opam2 ?labels ?arch ~yum_workaround ~enable_powertools ~opam_hashes + d () + | `Zypper -> zypper_opam2 ?labels ?arch ~opam_hashes d () + | `Pacman -> pacman_opam2 ?labels ?arch ~opam_hashes d () + | `Cygwin -> cygwin_opam2 ?win10_revision ?labels ?arch ~opam_hashes d () + | `Windows -> windows_opam2 ?win10_revision ?winget ?labels ?arch d () + in + let clone = + if clone_opam_repo then + let url = Dockerfile_distro.(os_family_of_distro d |> opam_repository) in + run "git clone %S /home/opam/opam-repository" url + else empty + in + let pers = + match personality ?arch d with + | None -> empty + | Some pers -> entrypoint_exec [ pers ] in - let clone = if clone_opam_repo then - let url = Dockerfile_distro.(os_family_of_distro d |> opam_repository) in - run "git clone %S /home/opam/opam-repository" url - else empty in - let pers = match personality ?arch d with - | None -> empty | Some pers -> entrypoint_exec [pers] in (D.tag_of_distro d, fn @@ clone @@ pers) let create_switch ~arch distro t = - let create_switch switch pkg = run "opam switch create %s %s" (OV.to_string switch) pkg in + let create_switch switch pkg = + run "opam switch create %s %s" (OV.to_string switch) pkg + in let switch = OV.with_patch t None in match distro with | `Windows (port, _) -> - let (pn, pv) = Dockerfile_windows.ocaml_for_windows_package_exn ~port ~arch ~switch in - create_switch switch (pv ^ pn) - | _ -> - create_switch switch (Ocaml_version.Opam.V2.name switch) + let pn, pv = + Dockerfile_windows.ocaml_for_windows_package_exn ~port ~arch ~switch + in + create_switch switch (pv ^ pn) + | _ -> create_switch switch (Ocaml_version.Opam.V2.name switch) let all_ocaml_compilers hub_id arch distro = let distro_tag = D.tag_of_distro distro in let os_family = Dockerfile_distro.os_family_of_distro distro in let compilers = - OV.Releases.recent |> - List.filter (fun ov -> D.distro_supported_on arch ov distro) |> fun ovs -> + OV.Releases.recent + |> List.filter (fun ov -> D.distro_supported_on arch ov distro) + |> fun ovs -> let add_beta_remote = if List.exists OV.Releases.is_dev ovs then - run "opam repo add beta git+https://github.com/ocaml/ocaml-beta-repository --set-default" - else empty in + run + "opam repo add beta \ + git+https://github.com/ocaml/ocaml-beta-repository --set-default" + else empty + in add_beta_remote @@@ List.map (create_switch ~arch distro) ovs in let d = - let pers = match personality ~arch distro with - | None -> [] | Some pers -> [pers] in - let sandbox = match os_family with + let pers = + match personality ~arch distro with None -> [] | Some pers -> [ pers ] + in + let sandbox = + match os_family with | `Linux -> run "opam-sandbox-disable" | `Windows | `Cygwin -> empty in header ~arch ~tag:(Printf.sprintf "%s-opam" distro_tag) ~img:hub_id distro - @@ workdir "/home/opam/opam-repository" @@ run "git pull origin master" + @@ workdir "/home/opam/opam-repository" + @@ run "git pull origin master" @@ sandbox @@ run "opam init -k git -a /home/opam/opam-repository --bare%s" (if os_family = `Windows then " --disable-sandboxing" else "") @@ compilers - @@ run "opam switch %s" (OV.(to_string (with_patch OV.Releases.latest None))) - @@ entrypoint_exec (pers @ ["opam"; "config"; "exec"; "--"]) + @@ run "opam switch %s" OV.(to_string (with_patch OV.Releases.latest None)) + @@ entrypoint_exec (pers @ [ "opam"; "config"; "exec"; "--" ]) @@ run "opam install -y depext%s" (if os_family = `Windows then " depext-cygwinports" else "") - @@ env ["OPAMYES","1"] - @@ match os_family with - | `Linux | `Cygwin -> cmd "bash" - | `Windows -> cmd_exec ["cmd.exe"] + @@ env [ ("OPAMYES", "1") ] + @@ + match os_family with + | `Linux | `Cygwin -> cmd "bash" + | `Windows -> cmd_exec [ "cmd.exe" ] in (distro_tag, d) let tag_of_ocaml_version ov = - Ocaml_version.with_patch ov None |> - Ocaml_version.to_string |> - String.map (function '+' -> '-' | x -> x) + Ocaml_version.with_patch ov None + |> Ocaml_version.to_string + |> String.map (function '+' -> '-' | x -> x) let separate_ocaml_compilers hub_id arch distro = let distro_tag = D.tag_of_distro distro in let os_family = Dockerfile_distro.os_family_of_distro distro in - OV.Releases.recent_with_dev |> List.filter (fun ov -> D.distro_supported_on arch ov distro) + OV.Releases.recent_with_dev + |> List.filter (fun ov -> D.distro_supported_on arch ov distro) |> List.map (fun ov -> let add_remote = if OV.Releases.is_dev ov then - run "opam repo add beta git+https://github.com/ocaml/ocaml-beta-repository --set-default" - else empty in - let default_switch_name = OV.(with_patch (with_variant ov None) None |> to_string) in + run + "opam repo add beta \ + git+https://github.com/ocaml/ocaml-beta-repository \ + --set-default" + else empty + in + let default_switch_name = + OV.(with_patch (with_variant ov None) None |> to_string) + in let variants = - empty @@@ List.map (create_switch ~arch distro) (OV.Opam.V2.switches arch ov) + empty + @@@ List.map + (create_switch ~arch distro) + (OV.Opam.V2.switches arch ov) in let d = - let pers = match personality ~arch distro with - | None -> [] | Some pers -> [pers] in - let sandbox = match os_family with + let pers = + match personality ~arch distro with + | None -> [] + | Some pers -> [ pers ] + in + let sandbox = + match os_family with | `Linux -> run "opam-sandbox-disable" - | `Windows | `Cygwin -> empty in - header ~arch ~tag:(Printf.sprintf "%s-opam" distro_tag) ~img:hub_id distro + | `Windows | `Cygwin -> empty + in + header ~arch + ~tag:(Printf.sprintf "%s-opam" distro_tag) + ~img:hub_id distro @@ workdir "/home/opam/opam-repository" @@ sandbox @@ run "opam init -k git -a /home/opam/opam-repository --bare%s" (if os_family = `Windows then "--disable-sandboxing" else "") - @@ add_remote - @@ variants + @@ add_remote @@ variants @@ run "opam switch %s" default_switch_name @@ run "opam install -y depext%s" (if os_family = `Windows then "depext-cygwinports" else "") - @@ env ["OPAMYES","1"] - @@ entrypoint_exec (pers @ ["opam"; "config"; "exec"; "--"]) - @@ match os_family with - | `Linux | `Cygwin -> cmd "bash" - | `Windows -> cmd_exec ["cmd.exe"] + @@ env [ ("OPAMYES", "1") ] + @@ entrypoint_exec (pers @ [ "opam"; "config"; "exec"; "--" ]) + @@ + match os_family with + | `Linux | `Cygwin -> cmd "bash" + | `Windows -> cmd_exec [ "cmd.exe" ] in - (Printf.sprintf "%s-ocaml-%s" distro_tag (tag_of_ocaml_version ov), d) ) - + (Printf.sprintf "%s-ocaml-%s" distro_tag (tag_of_ocaml_version ov), d)) let deprecated = header (`Alpine `Latest) - @@ run "echo 'This container is now deprecated and no longer supported. Please see https://github.com/ocaml/infrastructure/wiki/Containers for the latest supported tags. Try to use the longer term supported aliases instead of specific distribution versions if you want to avoid seeing this message in the future.' && exit 1" + @@ run + "echo 'This container is now deprecated and no longer supported. Please \ + see https://github.com/ocaml/infrastructure/wiki/Containers for the \ + latest supported tags. Try to use the longer term supported aliases \ + instead of specific distribution versions if you want to avoid seeing \ + this message in the future.' && exit 1" let multiarch_manifest ~target ~platforms = let ms = List.map (fun (image, arch) -> Printf.sprintf - " -\n image: %s\n platform:\n architecture: %s\n os: linux" - image arch) + " -\n\ + \ image: %s\n\ + \ platform:\n\ + \ architecture: %s\n\ + \ os: linux" image arch) platforms |> String.concat "\n" in Printf.sprintf "image: %s\nmanifests:\n%s" target ms (* Clone and build opam from source (legacy function) *) -let install_opam_from_source ?(add_default_link=true) ?(prefix= "/usr/local") ?(enable_0install_solver=false) ~branch ~hash () = - run "git clone https://github.com/ocaml/opam /tmp/opam && cd /tmp/opam && git checkout %s" hash @@ - Linux.run_sh - "cd /tmp/opam && make%s cold && mkdir -p %s/bin && cp /tmp/opam/opam %s/bin/opam-%s && chmod a+x %s/bin/opam-%s && rm -rf /tmp/opam" - (if enable_0install_solver then " CONFIGURE_ARGS=--with-0install-solver" else "") prefix prefix branch prefix branch @@ - maybe_link_opam add_default_link prefix branch +let install_opam_from_source ?(add_default_link = true) ?(prefix = "/usr/local") + ?(enable_0install_solver = false) ~branch ~hash () = + run + "git clone https://github.com/ocaml/opam /tmp/opam && cd /tmp/opam && git \ + checkout %s" + hash + @@ Linux.run_sh + "cd /tmp/opam && make%s cold && mkdir -p %s/bin && cp /tmp/opam/opam \ + %s/bin/opam-%s && chmod a+x %s/bin/opam-%s && rm -rf /tmp/opam" + (if enable_0install_solver then " CONFIGURE_ARGS=--with-0install-solver" + else "") + prefix prefix branch prefix branch + @@ maybe_link_opam add_default_link prefix branch diff --git a/src-opam/dockerfile_opam.mli b/src-opam/dockerfile_opam.mli index 50903d49..de3b75fe 100644 --- a/src-opam/dockerfile_opam.mli +++ b/src-opam/dockerfile_opam.mli @@ -26,8 +26,14 @@ val run_as_opam : ('a, unit, string, Dockerfile.t) format4 -> 'a (** [run_as_opam fmt] runs the command specified by the [fmt] format string as the [opam] user. *) -val install_opam_from_source : ?add_default_link:bool -> - ?prefix:string -> ?enable_0install_solver:bool -> branch:string -> hash:string -> unit -> Dockerfile.t +val install_opam_from_source : + ?add_default_link:bool -> + ?prefix:string -> + ?enable_0install_solver:bool -> + branch:string -> + hash:string -> + unit -> + Dockerfile.t (** Commands to install OPAM via a source code checkout from GitHub. The [branch] can be a git tag or branch (e.g. [2.0] for opam 2.0.x or [2.1] for the opam 2.1.x). @@ -52,8 +58,8 @@ val gen_opam2_distro : ?arch:Ocaml_version.arch -> ?labels:(string * string) list -> opam_hashes:opam_hashes -> - Dockerfile_distro.t - -> string * Dockerfile.t + Dockerfile_distro.t -> + string * Dockerfile.t (** [gen_opam2_distro ~opam_hashes d] will generate a Dockerfile for Linux distribution [d] with opam 2.0, opam 2.1, opam 2.2 and opam master, per hash given in parameter. @@ -74,8 +80,10 @@ val all_ocaml_compilers : distribution [distro] on architecture [arch]. *) val separate_ocaml_compilers : - string -> Ocaml_version.arch -> Dockerfile_distro.t - -> (string * Dockerfile.t) list + string -> + Ocaml_version.arch -> + Dockerfile_distro.t -> + (string * Dockerfile.t) list (** [separate_ocaml_compilers hub_id arch distro] will install a list of Dockerfiles that build individual OCaml compiler versions and their variants (e.g. flambda) in separate containers. *) @@ -85,6 +93,7 @@ val deprecated : Dockerfile.t is used to replace unsupported containers on the Hub rather than leaving an unmaintained distribution lying around with possible security holes. *) -val multiarch_manifest : target:string -> platforms:(string * string) list -> string +val multiarch_manifest : + target:string -> platforms:(string * string) list -> string (** [multiarch_manifest ~target ~platforms] will generate a manifest-tool compliant yaml file to build a [target] on the given multiarch [platforms]. *) diff --git a/src-opam/dockerfile_windows.ml b/src-opam/dockerfile_windows.ml index 1a9ea074..ff76ad2d 100644 --- a/src-opam/dockerfile_windows.ml +++ b/src-opam/dockerfile_windows.ml @@ -19,159 +19,258 @@ open Dockerfile open Printf let run_cmd fmt = ksprintf (run "cmd /S /C %s") fmt -let run_powershell ?(escape=Fun.id) fmt = ksprintf (fun s -> run {|powershell -Command "%s"|} (escape s)) fmt + +let run_powershell ?(escape = Fun.id) fmt = + ksprintf (fun s -> run {|powershell -Command "%s"|} (escape s)) fmt + let run_vc ~arch fmt = - let arch = match arch with - | `I386 -> "x86" | `X86_64 -> "amd64" - | `Aarch64 | `Aarch32 | `Ppc64le | `S390x | `Riscv64 -> invalid_arg "Unsupported architecture" + let arch = + match arch with + | `I386 -> "x86" + | `X86_64 -> "amd64" + | `Aarch64 | `Aarch32 | `Ppc64le | `S390x | `Riscv64 -> + invalid_arg "Unsupported architecture" in - ksprintf (run {|cd C:\BuildTools\VC\Auxiliary\Build && vcvarsall.bat %s && %s|} arch) fmt -let run_ocaml_env args fmt = ksprintf (run {|ocaml-env exec %s -- %s|} (String.concat " " args)) fmt + ksprintf + (run {|cd C:\BuildTools\VC\Auxiliary\Build && vcvarsall.bat %s && %s|} arch) + fmt -let install_vc_redist ?(vs_version="16") () = - add ~src:["https://aka.ms/vs/" ^ vs_version ^ "/release/vc_redist.x64.exe"] ~dst:{|C:\TEMP\|} () - @@ run {|C:\TEMP\vc_redist.x64.exe /install /passive /norestart /log C:\TEMP\vc_redist.log|} +let run_ocaml_env args fmt = + ksprintf (run {|ocaml-env exec %s -- %s|} (String.concat " " args)) fmt -let install_visual_studio_build_tools ?(vs_version="16") components = +let install_vc_redist ?(vs_version = "16") () = + add + ~src:[ "https://aka.ms/vs/" ^ vs_version ^ "/release/vc_redist.x64.exe" ] + ~dst:{|C:\TEMP\|} () + @@ run + {|C:\TEMP\vc_redist.x64.exe /install /passive /norestart /log C:\TEMP\vc_redist.log|} + +let install_visual_studio_build_tools ?(vs_version = "16") components = let install = - let fmt = format_of_string - {|C:\TEMP\Install.cmd C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ` + let fmt = + format_of_string + {|C:\TEMP\Install.cmd C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ` --installPath C:\BuildTools --channelUri C:\TEMP\VisualStudio.chman ` - --installChannelUri C:\TEMP\VisualStudio.chman%s|} in - run fmt (List.fold_left (fun acc component -> - acc ^ " `\n --add " ^ component) "" components) + --installChannelUri C:\TEMP\VisualStudio.chman%s|} + in + run fmt + (List.fold_left + (fun acc component -> acc ^ " `\n --add " ^ component) + "" components) in (* https://docs.microsoft.com/en-us/visualstudio/install/advanced-build-tools-container?view=vs-2019#install-script *) - add ~src:["https://raw.githubusercontent.com/avsm/ocaml-dockerfile/master/src-opam/Install.cmd"] + add + ~src: + [ + "https://raw.githubusercontent.com/avsm/ocaml-dockerfile/master/src-opam/Install.cmd"; + ] ~dst:{|C:\TEMP\|} () - @@ add ~src:["https://aka.ms/vscollect.exe"] ~dst:{|C:\TEMP\collect.exe|} () - @@ add ~src:["https://aka.ms/vs/" ^ vs_version ^ "/release/channel"] ~dst:{|C:\TEMP\VisualStudio.chman|} () - @@ add ~src:["https://aka.ms/vs/" ^ vs_version ^ "/release/vs_buildtools.exe"] ~dst:{|C:\TEMP\vs_buildtools.exe|} () + @@ add ~src:[ "https://aka.ms/vscollect.exe" ] ~dst:{|C:\TEMP\collect.exe|} () + @@ add + ~src:[ "https://aka.ms/vs/" ^ vs_version ^ "/release/channel" ] + ~dst:{|C:\TEMP\VisualStudio.chman|} () + @@ add + ~src:[ "https://aka.ms/vs/" ^ vs_version ^ "/release/vs_buildtools.exe" ] + ~dst:{|C:\TEMP\vs_buildtools.exe|} () @@ install let sanitize_reg_path () = - run {|for /f "tokens=1,2,*" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path ^| findstr /r "\\$"') do ` + run + {|for /f "tokens=1,2,*" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path ^| findstr /r "\\$"') do ` for /f "delims=" %%l in ('cmd /v:on /c "set v=%%c&& echo !v:~0,-1!"') do ` reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path /t REG_EXPAND_SZ /f /d "%%l"|} let prepend_path paths = let paths = String.concat ";" paths in - run {|for /f "tokens=1,2,*" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path ^| findstr /r "^[^H]"') do ` - reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path /t REG_EXPAND_SZ /f /d "%s;%%c"|} paths + run + {|for /f "tokens=1,2,*" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path ^| findstr /r "^[^H]"') do ` + reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path /t REG_EXPAND_SZ /f /d "%s;%%c"|} + paths let ocaml_for_windows_package_exn ~switch ~port ~arch = let variant = let bitness = if Ocaml_version.arch_is_32bit arch then "32" else "64" in match arch with | `X86_64 | `I386 -> - (match port with `Mingw -> "mingw" | `Msvc -> "msvc") ^ bitness + (match port with `Mingw -> "mingw" | `Msvc -> "msvc") ^ bitness | _ -> invalid_arg "Unsupported architecture" in let _, pkgver = Ocaml_version.Opam.V2.package switch in ("ocaml-variants", pkgver ^ "+" ^ variant) -let cleanup () = - run_powershell {|Remove-Item 'C:\TEMP' -Recurse|} +let cleanup () = run_powershell {|Remove-Item 'C:\TEMP' -Recurse|} module Cygwin = struct - type cyg = { - root : string; - site : string; - args : string list; - } + type cyg = { root : string; site : string; args : string list } let cygsetup = {|C:\cygwin-setup-x86_64.exe|} let cygcache = {|C:\TEMP\cache|} - let default = { + let default = + { root = {|C:\cygwin64|}; site = "https://mirrors.kernel.org/sourceware/cygwin/"; - args = ["--quiet-mode"; "--no-shortcuts"; "--no-startmenu"; "--no-desktop"; - "--only-site"; "--local-package-dir"; cygcache]; + args = + [ + "--quiet-mode"; + "--no-shortcuts"; + "--no-startmenu"; + "--no-desktop"; + "--only-site"; + "--local-package-dir"; + cygcache; + ]; } - let run_sh ?(cyg=default) fmt = ksprintf (run {|%s\bin\bash.exe --login -c "%s"|} cyg.root) fmt - let run_sh_ocaml_env ?(cyg=default) args fmt = ksprintf (run_sh ~cyg "ocaml-env exec %s -- %s" (String.concat " " args)) fmt + let run_sh ?(cyg = default) fmt = + ksprintf (run {|%s\bin\bash.exe --login -c "%s"|} cyg.root) fmt + + let run_sh_ocaml_env ?(cyg = default) args fmt = + ksprintf + (run_sh ~cyg "ocaml-env exec %s -- %s" (String.concat " " args)) + fmt let install_cygsympathy_from_source cyg = - run {|mkdir %s\lib\cygsympathy && mkdir %s\etc\postinstall|} cyg.root cyg.root - @@ add ~src:["https://raw.githubusercontent.com/metastack/cygsympathy/master/cygsympathy.cmd"] - ~dst:(cyg.root ^ {|\lib\cygsympathy\|}) () - @@ add ~src:["https://raw.githubusercontent.com/metastack/cygsympathy/master/cygsympathy.sh"] - ~dst:(cyg.root ^ {|\lib\cygsympathy\cygsympathy|}) () + run {|mkdir %s\lib\cygsympathy && mkdir %s\etc\postinstall|} cyg.root + cyg.root + @@ add + ~src: + [ + "https://raw.githubusercontent.com/metastack/cygsympathy/master/cygsympathy.cmd"; + ] + ~dst:(cyg.root ^ {|\lib\cygsympathy\|}) + () + @@ add + ~src: + [ + "https://raw.githubusercontent.com/metastack/cygsympathy/master/cygsympathy.sh"; + ] + ~dst:(cyg.root ^ {|\lib\cygsympathy\cygsympathy|}) + () (* Beware: CygSymPathy must be executed last, or it may miss files installed by other post-install scripts. Use a name that is greater than every other script in the lexicographic order. *) - @@ run {|mklink %s\etc\postinstall\zp_zcygsympathy.sh %s\lib\cygsympathy\cygsympathy|} cyg.root cyg.root + @@ run + {|mklink %s\etc\postinstall\zp_zcygsympathy.sh %s\lib\cygsympathy\cygsympathy|} + cyg.root cyg.root - let install_msvs_tools_from_source ?(version="0.4.1") cyg = - add ~src:["https://github.com/metastack/msvs-tools/archive/" ^ version ^ ".tar.gz"] - ~dst:({|C:\TEMP\msvs-tools.tar.gz|}) () - @@ run_sh ~cyg {|cd /tmp && tar -xf /cygdrive/c/TEMP/msvs-tools.tar.gz && cp msvs-tools-%s/msvs-detect msvs-tools-%s/msvs-promote-path /bin|} version version + let install_msvs_tools_from_source ?(version = "0.4.1") cyg = + add + ~src: + [ + "https://github.com/metastack/msvs-tools/archive/" ^ version + ^ ".tar.gz"; + ] + ~dst:{|C:\TEMP\msvs-tools.tar.gz|} () + @@ run_sh ~cyg + {|cd /tmp && tar -xf /cygdrive/c/TEMP/msvs-tools.tar.gz && cp msvs-tools-%s/msvs-detect msvs-tools-%s/msvs-promote-path /bin|} + version version - let cygwin ?(cyg=default) fmt = - ksprintf (run {|%s %s --root %s --site %s --symlink-type=wsl %s|} cygsetup (String.concat " " cyg.args) cyg.root cyg.site) fmt + let cygwin ?(cyg = default) fmt = + ksprintf + (run {|%s %s --root %s --site %s --symlink-type=wsl %s|} cygsetup + (String.concat " " cyg.args) + cyg.root cyg.site) + fmt - let install ?(cyg=default) fmt = - ksprintf (cygwin ~cyg "--packages %s") fmt + let install ?(cyg = default) fmt = ksprintf (cygwin ~cyg "--packages %s") fmt - let setup ?(cyg=default) ?(winsymlinks_native=true) ?(extra=[]) () = - (if winsymlinks_native then env [("CYGWIN", "winsymlinks:native")] else empty) - @@ add ~src:["https://www.cygwin.com/setup-x86_64.exe"] ~dst:{|C:\cygwin-setup-x86_64.exe|} () + let setup ?(cyg = default) ?(winsymlinks_native = true) ?(extra = []) () = + (if winsymlinks_native then env [ ("CYGWIN", "winsymlinks:native") ] + else empty) + @@ add + ~src:[ "https://www.cygwin.com/setup-x86_64.exe" ] + ~dst:{|C:\cygwin-setup-x86_64.exe|} () @@ install_cygsympathy_from_source cyg - @@ cygwin ~cyg "--packages %s" (extra |> List.sort_uniq String.compare |> String.concat ",") + @@ cygwin ~cyg "--packages %s" + (extra |> List.sort_uniq String.compare |> String.concat ",") @@ install_msvs_tools_from_source cyg - @@ prepend_path (List.map ((^) cyg.root) [{|\bin|}]) - @@ run {|awk -i inplace "/(^#)|(^$)/{print;next}{$4=""noacl,""$4; print}" %s\etc\fstab|} cyg.root + @@ prepend_path (List.map (( ^ ) cyg.root) [ {|\bin|} ]) + @@ run + {|awk -i inplace "/(^#)|(^$)/{print;next}{$4=""noacl,""$4; print}" %s\etc\fstab|} + cyg.root @@ workdir {|%s\home\opam|} cyg.root - let update ?(cyg=default) () = - run {|%s %s --root %s --site %s --upgrade-also|} cygsetup (String.concat " " cyg.args) cyg.root cyg.site + let update ?(cyg = default) () = + run {|%s %s --root %s --site %s --upgrade-also|} cygsetup + (String.concat " " cyg.args) + cyg.root cyg.site - let cygwin_packages ?(extra=[]) ?(flexdll_version="0.39-1") () = + let cygwin_packages ?(extra = []) ?(flexdll_version = "0.39-1") () = (* 2021-03-19: flexdll 0.39 is required, but is in Cygwin testing *) "make" :: "diffutils" :: "ocaml" :: "gcc-core" :: "git" :: "patch" :: "m4" - :: "cygport" :: ("flexdll="^flexdll_version) :: extra + :: "cygport" + :: ("flexdll=" ^ flexdll_version) + :: extra + + let mingw_packages ?(extra = []) () = + "make" :: "diffutils" :: "mingw64-x86_64-gcc-core" :: extra - let mingw_packages ?(extra=[]) () = "make" :: "diffutils" :: "mingw64-x86_64-gcc-core" :: extra - let msvc_packages ?(extra=[]) () = "make" :: "diffutils" :: extra + let msvc_packages ?(extra = []) () = "make" :: "diffutils" :: extra - let ocaml_for_windows_packages ?cyg ?(extra=[]) ?(version="0.0.0.2") () = - let packages = "make" :: "diffutils" :: "mingw64-x86_64-gcc-g++" :: "vim" :: "git" - :: "curl" :: "rsync" :: "unzip" :: "patch" :: "m4" :: extra in + let ocaml_for_windows_packages ?cyg ?(extra = []) ?(version = "0.0.0.2") () = + let packages = + "make" :: "diffutils" :: "mingw64-x86_64-gcc-g++" :: "vim" :: "git" + :: "curl" :: "rsync" :: "unzip" :: "patch" :: "m4" :: extra + in let t = - add ~src:["https://github.com/fdopen/opam-repository-mingw/releases/download/" ^ version ^ "/opam64.tar.xz"] + add + ~src: + [ + "https://github.com/fdopen/opam-repository-mingw/releases/download/" + ^ version ^ "/opam64.tar.xz"; + ] ~dst:{|C:\TEMP\|} () - @@ run_sh ?cyg {|cd /tmp && tar -xf /cygdrive/c/TEMP/opam64.tar.xz && ./opam64/install.sh --prefix=/usr && rm -rf opam64 opam64.tar.xz|} in - packages, t + @@ run_sh ?cyg + {|cd /tmp && tar -xf /cygdrive/c/TEMP/opam64.tar.xz && ./opam64/install.sh --prefix=/usr && rm -rf opam64 opam64.tar.xz|} + in + (packages, t) module Git = struct - let init ?(cyg=default) ?(name="Docker") ?(email="docker@example.com") () = - env ["HOME", cyg.root ^ {|\home\opam|}] - @@ run_sh ~cyg "git config --global user.email '%s' && \ - git config --global user.name '%s' && \ - git config --system core.longpaths true && \ - git config --global --add safe.directory /home/opam/opam-repository" email name + let init ?(cyg = default) ?(name = "Docker") ?(email = "docker@example.com") + () = + env [ ("HOME", cyg.root ^ {|\home\opam|}) ] + @@ run_sh ~cyg + "git config --global user.email '%s' && git config --global \ + user.name '%s' && git config --system core.longpaths true && git \ + config --global --add safe.directory /home/opam/opam-repository" + email name end end module Winget = struct let is_supported version = - not (List.mem version [`V1507; `Ltsc2015; `V1511; `V1607; `Ltsc2016; `V1703; `V1709; `V1803]) + not + (List.mem version + [ + `V1507; `Ltsc2015; `V1511; `V1607; `Ltsc2016; `V1703; `V1709; `V1803; + ]) let winget = "winget-builder" - let header ?win10_revision ?(version=(Dockerfile_distro.win10_latest_image : Dockerfile_distro.win10_release :> Dockerfile_distro.win_all)) () = - let img, tag = Dockerfile_distro.win10_base_tag ?win10_revision `Windows version in + let header ?win10_revision + ?(version = + (Dockerfile_distro.win10_latest_image + : Dockerfile_distro.win10_release + :> Dockerfile_distro.win_all)) () = + let img, tag = + Dockerfile_distro.win10_base_tag ?win10_revision `Windows version + in parser_directive (`Escape '`') @@ from ~alias:winget ~tag img @@ user "ContainerAdministrator" let footer path = run {|mkdir "C:\Program Files\winget-cli"|} - @@ run {|move "C:\TEMP\winget-cli\%s\winget.exe" "C:\Program Files\winget-cli\"|} path - @@ run {|move "C:\TEMP\winget-cli\%s\WindowsPackageManager.dll" "C:\Program Files\winget-cli\"|} path - @@ run {|move "C:\TEMP\winget-cli\%s\resources.pri" "C:\Program Files\winget-cli\"|} path + @@ run + {|move "C:\TEMP\winget-cli\%s\winget.exe" "C:\Program Files\winget-cli\"|} + path + @@ run + {|move "C:\TEMP\winget-cli\%s\WindowsPackageManager.dll" "C:\Program Files\winget-cli\"|} + path + @@ run + {|move "C:\TEMP\winget-cli\%s\resources.pri" "C:\Program Files\winget-cli\"|} + path |> crunch let install_from_release ?win10_revision ?version ?winget_version () = @@ -184,32 +283,46 @@ module Winget = struct in let dst = {|C:\TEMP\|} ^ file ^ "zip" in header ?win10_revision ?version () - @@ add ~src:[src] ~dst () - @@ run_powershell {|Expand-Archive -LiteralPath %s -DestinationPath C:\TEMP\winget-cli -Force|} dst + @@ add ~src:[ src ] ~dst () + @@ run_powershell + {|Expand-Archive -LiteralPath %s -DestinationPath C:\TEMP\winget-cli -Force|} + dst @@ run {|ren C:\TEMP\winget-cli\AppInstaller_x64.msix AppInstaller_x64.zip|} - @@ run_powershell {|Expand-Archive -LiteralPath C:\TEMP\winget-cli\AppInstaller_x64.zip -DestinationPath C:\TEMP\winget-cli\ -Force|} + @@ run_powershell + {|Expand-Archive -LiteralPath C:\TEMP\winget-cli\AppInstaller_x64.zip -DestinationPath C:\TEMP\winget-cli\ -Force|} @@ footer "" - let setup ?(from=winget) () = + let setup ?(from = winget) () = let escape s = String.(concat {|""""|} (split_on_char '"' s)) in - copy ~from ~src:[{|C:\Program Files\winget-cli|}] ~dst:{|C:\Program Files\winget-cli|} () - @@ prepend_path [{|C:\Program Files\winget-cli|}] - @@ run_powershell ~escape {|$path=(Join-Path $env:LOCALAPPDATA 'Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState'); New-Item $path -ItemType Directory -Force; '{ "$schema": "https://aka.ms/winget-settings.schema.json", "telemetry": { "disable": "true" } }' | Out-File -encoding ASCII (Join-Path $path 'settings.json')|} + copy ~from + ~src:[ {|C:\Program Files\winget-cli|} ] + ~dst:{|C:\Program Files\winget-cli|} () + @@ prepend_path [ {|C:\Program Files\winget-cli|} ] + @@ run_powershell ~escape + {|$path=(Join-Path $env:LOCALAPPDATA 'Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState'); New-Item $path -ItemType Directory -Force; '{ "$schema": "https://aka.ms/winget-settings.schema.json", "telemetry": { "disable": "true" } }' | Out-File -encoding ASCII (Join-Path $path 'settings.json')|} let install pkgs = - List.fold_left (fun acc pkg -> acc @@ run "winget install --exact --accept-source-agreements --accept-package-agreements %s" pkg) empty pkgs + List.fold_left + (fun acc pkg -> + acc + @@ run + "winget install --exact --accept-source-agreements \ + --accept-package-agreements %s" + pkg) + empty pkgs let dev_packages ?version ?extra () = match version with (* 2021-04-01: Installing git fails with exit-code 2316632065. *) | Some `V1809 -> maybe install extra - | _ -> install ["Git.Git"] @@ maybe install extra + | _ -> install [ "Git.Git" ] @@ maybe install extra module Git = struct - let init ?(name="Docker") ?(email="docker@example.com") () = - run "git config --global user.email %S && \ - git config --global user.name %S && \ - git config --system core.longpaths true && \ - git config --global --add safe.directory C:/cygwin64/home/opam/opam-repository" email name + let init ?(name = "Docker") ?(email = "docker@example.com") () = + run + "git config --global user.email %S && git config --global user.name %S \ + && git config --system core.longpaths true && git config --global \ + --add safe.directory C:/cygwin64/home/opam/opam-repository" + email name end end diff --git a/src-opam/dockerfile_windows.mli b/src-opam/dockerfile_windows.mli index 5b849f92..88e55433 100644 --- a/src-opam/dockerfile_windows.mli +++ b/src-opam/dockerfile_windows.mli @@ -22,8 +22,8 @@ open Dockerfile val run_cmd : ('a, unit, string, t) format4 -> 'a (** [run_cmd fmt] will execute [cmd /S /C fmt]. *) -val run_powershell : ?escape:(string -> string) -> - ('a, unit, string, t) format4 -> 'a +val run_powershell : + ?escape:(string -> string) -> ('a, unit, string, t) format4 -> 'a (** [run_powershell fmt] will execute [powershell -Command "fmt"]. @param escape (defaults to {!Fun.id}) allows to escape [fmt] @@ -53,8 +53,10 @@ val install_visual_studio_build_tools : ?vs_version:string -> string list -> t @see *) val ocaml_for_windows_package_exn : - switch:Ocaml_version.t -> port:[`Mingw | `Msvc] -> arch:Ocaml_version.arch -> - (string * string) + switch:Ocaml_version.t -> + port:[ `Mingw | `Msvc ] -> + arch:Ocaml_version.arch -> + string * string (** [ocaml_for_windows_variant ~port ~arch] returns the [(package_name, package_version)] of the OCaml compiler package in OCaml for Windows, if applicable. *) @@ -65,16 +67,18 @@ val cleanup : unit -> t (** Rules for Cygwin-based installation *) module Cygwin : sig type cyg = { - root : string; (** Root installation directory *) - site : string; (** Download site URL *) - args : string list; (** List of arguments to give to Cygwin's + root : string; (** Root installation directory *) + site : string; (** Download site URL *) + args : string list; + (** List of arguments to give to Cygwin's setup, except [--root] and [--site]. *) - } + } val default : cyg (** The default Cygwin root, mirror, and arguments. *) - val setup : ?cyg:cyg -> ?winsymlinks_native:bool -> ?extra:string list -> unit -> t + val setup : + ?cyg:cyg -> ?winsymlinks_native:bool -> ?extra:string list -> unit -> t (** Setup Cygwin with CygSymPathy and msvs-tools, and [extra] Cygwin packages. Sets the [CYGWIN=winsymlinks:native] environment variable by default. @@ -88,8 +92,8 @@ module Cygwin : sig val update : ?cyg:cyg -> unit -> t (** Update Cygwin packages. *) - val cygwin_packages : ?extra:string list -> ?flexdll_version:string -> unit - -> string list + val cygwin_packages : + ?extra:string list -> ?flexdll_version:string -> unit -> string list (** [cygwin_packages ?extra ()] will install the base development tools for the OCaml Cygwin port. Extra packages may also be optionally supplied via [extra]. *) @@ -104,8 +108,8 @@ module Cygwin : sig tools for the OCaml MSVC port. Extra packages may also be optionally supplied via [extra]. *) - val ocaml_for_windows_packages : ?cyg:cyg -> ?extra:string list -> ?version:string -> unit - -> string list * t + val ocaml_for_windows_packages : + ?cyg:cyg -> ?extra:string list -> ?version:string -> unit -> string list * t (** [ocaml_for_windows_packages ?extra ()] returns the list of Cygwin packages dependencies, and the installation instructions. Extra packages may also be optionally supplied via [extra]. @@ -115,7 +119,8 @@ module Cygwin : sig (** [run_sh ?cyg fmt] will execute in the Cygwin root [\bin\bash.exe --login -c "fmt"]. *) - val run_sh_ocaml_env : ?cyg:cyg -> string list -> ('a, unit, string, t) format4 -> 'a + val run_sh_ocaml_env : + ?cyg:cyg -> string list -> ('a, unit, string, t) format4 -> 'a (** [run_cmd_ocaml_env args fmt] will execute [fmt] in the evironment loaded by [ocaml-env cygwin exec] with [args]. *) @@ -136,7 +141,10 @@ module Winget : sig val install_from_release : ?win10_revision:Dockerfile_distro.win10_lcu -> - ?version:Dockerfile_distro.win_all -> ?winget_version:string -> unit -> t + ?version:Dockerfile_distro.win_all -> + ?winget_version:string -> + unit -> + t (** Install winget from a released build (first in a separate Docker image). The optional [winget_version] specifies a Git tag. *) @@ -148,8 +156,7 @@ module Winget : sig (** [install packages] will install the supplied winget package list. *) val dev_packages : - ?version:Dockerfile_distro.win_all -> - ?extra:string list -> unit -> t + ?version:Dockerfile_distro.win_all -> ?extra:string list -> unit -> t (** [dev_packages ?version ?extra ()] will install the base development tools. Extra packages may also be optionally supplied via [extra]. Using [?version] may change the set of installed packages. *) diff --git a/src/dockerfile.ml b/src/dockerfile.ml index 85d67520..ad068712 100644 --- a/src/dockerfile.ml +++ b/src/dockerfile.ml @@ -18,32 +18,38 @@ open Sexplib.Conv type shell_or_exec = - [`Shell of string | `Shells of string list | `Exec of string list] - [@@deriving sexp] + [ `Shell of string | `Shells of string list | `Exec of string list ] +[@@deriving sexp] type sources_to_dest = - [`From of string option] * [`Src of string list] * [`Dst of string] * [`Chown of string option] * [`Link of bool option] - [@@deriving sexp] + [ `From of string option ] + * [ `Src of string list ] + * [ `Dst of string ] + * [ `Chown of string option ] + * [ `Link of bool option ] +[@@deriving sexp] type from = { image : string; - tag: string option; - alias: string option; - platform: string option } [@@deriving sexp] + tag : string option; + alias : string option; + platform : string option; +} +[@@deriving sexp] -type parser_directive = - [ `Syntax of string | `Escape of char ] - [@@deriving sexp] +type parser_directive = [ `Syntax of string | `Escape of char ] +[@@deriving sexp] type heredoc = { - here_document: string; - word: string; - delimiter: string; - strip: bool } [@@deriving sexp] + here_document : string; + word : string; + delimiter : string; + strip : bool; +} +[@@deriving sexp] -type heredocs_to_dest = - [`Chown of string option] * heredoc list * string - [@@deriving sexp] +type heredocs_to_dest = [ `Chown of string option ] * heredoc list * string +[@@deriving sexp] type line = [ `ParserDirective of parser_directive @@ -64,16 +70,13 @@ type line = | `Workdir of string | `Onbuild of line | `Label of (string * string) list ] - [@@deriving sexp] +[@@deriving sexp] type t = line list [@@deriving sexp] let ( @@ ) = ( @ ) - let ( @@@ ) = List.fold_left (fun a b -> a @@ b) - let empty = [] - let maybe f = function None -> empty | Some v -> f v open Printf @@ -84,11 +87,11 @@ let crunch l = let pack l = let rec aux acc = function | [] -> acc - | (`Run `Shell a) :: (`Run `Shell b) :: tl -> - aux (`Run (`Shells [a; b]) :: acc) tl - | (`Run `Shells a) :: (`Run `Shell b) :: tl -> - aux (`Run (`Shells (a @ [b])) :: acc) tl - | (`Run `Shells a) :: (`Run `Shells b) :: tl -> + | `Run (`Shell a) :: `Run (`Shell b) :: tl -> + aux (`Run (`Shells [ a; b ]) :: acc) tl + | `Run (`Shells a) :: `Run (`Shell b) :: tl -> + aux (`Run (`Shells (a @ [ b ])) :: acc) tl + | `Run (`Shells a) :: `Run (`Shells b) :: tl -> aux (`Run (`Shells (a @ b)) :: acc) tl | hd :: tl -> aux (hd :: acc) tl in @@ -100,86 +103,83 @@ let crunch l = in fixp pack l - let quote s = sprintf "%S" s - let cmd c r = c ^ " " ^ r let json_array_of_list sl = sprintf "[ %s ]" (String.concat ", " (List.map quote sl)) - -let string_of_shell_or_exec ~escape (t: shell_or_exec) = +let string_of_shell_or_exec ~escape (t : shell_or_exec) = match t with | `Shell s -> s | `Shells [] -> "" - | `Shells [s] -> s - | `Shells l -> String.concat (" && "^(String.make 1 escape)^"\n ") l + | `Shells [ s ] -> s + | `Shells l -> String.concat (" && " ^ String.make 1 escape ^ "\n ") l | `Exec sl -> json_array_of_list sl - let string_of_env_list ~escape el = let quote v = let len = String.length v in let buf = Buffer.create len in let j = ref 0 in for i = 0 to len - 1 do - if v.[i] = '"' || v.[i] = escape then begin + if v.[i] = '"' || v.[i] = escape then ( if i - !j > 0 then Buffer.add_substring buf v !j (i - !j); Buffer.add_char buf escape; - j := i - end + j := i) done; Buffer.add_substring buf v !j (len - !j); Buffer.contents buf in - String.concat " " (List.map (fun (k, v) -> sprintf {|%s="%s"|} k (quote v)) el) - + String.concat " " + (List.map (fun (k, v) -> sprintf {|%s="%s"|} k (quote v)) el) let optional name = function | None -> [] - | Some value -> [sprintf "%s=%s" name value] + | Some value -> [ sprintf "%s=%s" name value ] let optional_flag name = function - | Some true -> [name] + | Some true -> [ name ] | Some false | None -> [] -let string_of_sources_to_dest (t: sources_to_dest) = +let string_of_sources_to_dest (t : sources_to_dest) = let `From frm, `Src sl, `Dst d, `Chown chown, `Link link = t in - String.concat " " ( - optional_flag "--link" link - @ optional "--chown" chown - @ optional "--from" frm - @ [json_array_of_list (sl @ [d])]) + String.concat " " + (optional_flag "--link" link + @ optional "--chown" chown @ optional "--from" frm + @ [ json_array_of_list (sl @ [ d ]) ]) let string_of_label_list ls = List.map (fun (k, v) -> sprintf "%s=%S" k v) ls |> String.concat " " -let string_of_copy_heredoc (t: heredocs_to_dest) = +let string_of_copy_heredoc (t : heredocs_to_dest) = let `Chown chown, heredocs, dst = t in let header, docs = - List.fold_left (fun (header, docs) t -> - (sprintf "<<%s%s" (if t.strip then "-" else "") t.word) :: header, - sprintf "%s\n%s\n%s" docs t.here_document t.delimiter) - ([], "") heredocs in - String.concat " " ( - optional "--chown" chown - @ (List.rev header) - @ [dst]) + List.fold_left + (fun (header, docs) t -> + ( sprintf "<<%s%s" (if t.strip then "-" else "") t.word :: header, + sprintf "%s\n%s\n%s" docs t.here_document t.delimiter )) + ([], "") heredocs + in + String.concat " " (optional "--chown" chown @ List.rev header @ [ dst ]) ^ docs -let rec string_of_line ~escape (t: line) = +let rec string_of_line ~escape (t : line) = match t with - | `ParserDirective (`Escape c) -> - cmd "#" ("escape="^(String.make 1 c)) - | `ParserDirective (`Syntax str) -> cmd "#" ("syntax="^str) + | `ParserDirective (`Escape c) -> cmd "#" ("escape=" ^ String.make 1 c) + | `ParserDirective (`Syntax str) -> cmd "#" ("syntax=" ^ str) | `Comment c -> cmd "#" c - | `From {image; tag; alias; platform} -> - cmd "FROM" (String.concat "" [ - (match platform with None -> "" | Some p -> "--platform="^p^" "); - image; - (match tag with None -> "" | Some t -> ":"^t); - (match alias with None -> "" | Some a -> " as " ^ a)]) + | `From { image; tag; alias; platform } -> + cmd "FROM" + (String.concat "" + [ + (match platform with + | None -> "" + | Some p -> "--platform=" ^ p ^ " "); + image; + (match tag with None -> "" | Some t -> ":" ^ t); + (match alias with None -> "" | Some a -> " as " ^ a); + ]) | `Maintainer m -> cmd "MAINTAINER" m | `Run c -> cmd "RUN" (string_of_shell_or_exec ~escape c) | `Cmd c -> cmd "CMD" (string_of_shell_or_exec ~escape c) @@ -196,57 +196,41 @@ let rec string_of_line ~escape (t: line) = | `Onbuild t -> cmd "ONBUILD" (string_of_line ~escape t) | `Label ls -> cmd "LABEL" (string_of_label_list ls) - (* Function interface *) -let parser_directive pd : t = [`ParserDirective pd] - -let heredoc ?(strip=false) ?(word="EOF") ?(delimiter=word) fmt = - ksprintf (fun here_document -> { here_document; strip; word; delimiter; }) fmt - -let from ?alias ?tag ?platform image = - [`From { image; tag; alias; platform }] - -let comment fmt = ksprintf (fun c -> [`Comment c]) fmt - -let maintainer fmt = ksprintf (fun m -> [`Maintainer m]) fmt +let parser_directive pd : t = [ `ParserDirective pd ] -let run fmt = ksprintf (fun b -> [`Run (`Shell b)]) fmt +let heredoc ?(strip = false) ?(word = "EOF") ?(delimiter = word) fmt = + ksprintf (fun here_document -> { here_document; strip; word; delimiter }) fmt -let run_exec cmds : t = [`Run (`Exec cmds)] +let from ?alias ?tag ?platform image = [ `From { image; tag; alias; platform } ] +let comment fmt = ksprintf (fun c -> [ `Comment c ]) fmt +let maintainer fmt = ksprintf (fun m -> [ `Maintainer m ]) fmt +let run fmt = ksprintf (fun b -> [ `Run (`Shell b) ]) fmt +let run_exec cmds : t = [ `Run (`Exec cmds) ] +let cmd fmt = ksprintf (fun b -> [ `Cmd (`Shell b) ]) fmt +let cmd_exec cmds : t = [ `Cmd (`Exec cmds) ] +let expose_port p : t = [ `Expose [ p ] ] +let expose_ports p : t = [ `Expose p ] +let env e : t = [ `Env e ] -let cmd fmt = ksprintf (fun b -> [`Cmd (`Shell b)]) fmt +let add ?link ?chown ?from ~src ~dst () : t = + [ `Add (`From from, `Src src, `Dst dst, `Chown chown, `Link link) ] -let cmd_exec cmds : t = [`Cmd (`Exec cmds)] +let copy ?link ?chown ?from ~src ~dst () : t = + [ `Copy (`From from, `Src src, `Dst dst, `Chown chown, `Link link) ] -let expose_port p : t = [`Expose [p]] - -let expose_ports p : t = [`Expose p] - -let env e : t = [`Env e] - -let add ?link ?chown ?from ~src ~dst () : t = [`Add (`From from, `Src src, `Dst dst, `Chown chown, `Link link)] - -let copy ?link ?chown ?from ~src ~dst () : t = [`Copy (`From from, `Src src, `Dst dst, `Chown chown, `Link link)] - -let copy_heredoc ?chown ~src ~dst () : t = [`Copy_heredoc (`Chown chown, src, dst)] - -let user fmt = ksprintf (fun u -> [`User u]) fmt +let copy_heredoc ?chown ~src ~dst () : t = + [ `Copy_heredoc (`Chown chown, src, dst) ] +let user fmt = ksprintf (fun u -> [ `User u ]) fmt let onbuild t = List.map (fun l -> `Onbuild l) t - -let volume fmt = ksprintf (fun v -> [`Volume [v]]) fmt - -let volumes v : t = [`Volume v] - -let label ls = [`Label ls] - -let entrypoint fmt = ksprintf (fun e -> [`Entrypoint (`Shell e)]) fmt - -let entrypoint_exec e : t = [`Entrypoint (`Exec e)] - -let shell s : t = [`Shell s] - -let workdir fmt = ksprintf (fun wd -> [`Workdir wd]) fmt +let volume fmt = ksprintf (fun v -> [ `Volume [ v ] ]) fmt +let volumes v : t = [ `Volume v ] +let label ls = [ `Label ls ] +let entrypoint fmt = ksprintf (fun e -> [ `Entrypoint (`Shell e) ]) fmt +let entrypoint_exec e : t = [ `Entrypoint (`Exec e) ] +let shell s : t = [ `Shell s ] +let workdir fmt = ksprintf (fun wd -> [ `Workdir wd ]) fmt let string_of_t tl = let rec find_escape = function diff --git a/src/dockerfile.mli b/src/dockerfile.mli index 90ae6f3f..f8b8fe23 100644 --- a/src/dockerfile.mli +++ b/src/dockerfile.mli @@ -21,8 +21,8 @@ (** {2 Core combinators and serializers} *) -(** [t] is a list of Dockerfile lines *) type t +(** [t] is a list of Dockerfile lines *) val sexp_of_t : t -> Sexplib.Sexp.t (** [sexp_of_t t] converts a Dockerfile into a s-expression representation. *) @@ -52,9 +52,8 @@ val maybe : ('a -> t) -> 'a option -> t (** {2 Dockerfile commands} *) -type parser_directive = - [ `Syntax of string | `Escape of char ] - [@@deriving sexp] +type parser_directive = [ `Syntax of string | `Escape of char ] +[@@deriving sexp] val parser_directive : parser_directive -> t (** A parser directive. If used, needs to be the first line of the @@ -67,7 +66,12 @@ val comment : ('a, unit, string, t) format4 -> 'a type heredoc (** Build here-document values with {!val:heredoc}. *) -val heredoc : ?strip:bool -> ?word:string -> ?delimiter:string -> ('a, unit, string, heredoc) format4 -> 'a +val heredoc : + ?strip:bool -> + ?word:string -> + ?delimiter:string -> + ('a, unit, string, heredoc) format4 -> + 'a (** [heredoc ~word here_document] creates a {!type:heredoc} value with [here_document] as content and [word] () as opening delimiter. If [word] is quoted, then [delimiter] (unquoted [word]) needs to be @@ -156,7 +160,14 @@ val env : (string * string) list -> t instructions. This is functionally equivalent to prefixing a shell command with [=]. *) -val add : ?link:bool -> ?chown:string -> ?from:string -> src:string list -> dst:string -> unit -> t +val add : + ?link:bool -> + ?chown:string -> + ?from:string -> + src:string list -> + dst:string -> + unit -> + t (** [add ?link ?chown ?from ~src ~dst ()] copies new files, directories or remote file URLs from [src] and adds them to the filesystem of the container at the [dst] path. @@ -191,7 +202,14 @@ val add : ?link:bool -> ?chown:string -> ?from:string -> src:string list -> dst: the first {!from} stage, or a named stage (supplied via [?alias] to the {!from} command). *) -val copy : ?link:bool -> ?chown:string -> ?from:string -> src:string list -> dst:string -> unit -> t +val copy : + ?link:bool -> + ?chown:string -> + ?from:string -> + src:string list -> + dst:string -> + unit -> + t (** [copy ?link ?chown ?from ~src ~dst ()] copies new files or directories from [src] and adds them to the filesystem of the container at the path [dst]. See {!add} for more detailed @@ -210,7 +228,7 @@ val copy : ?link:bool -> ?chown:string -> ?from:string -> src:string list -> dst the first {!from} stage, or a named stage (supplied via [?alias] to the {!from} command). *) -val copy_heredoc : ?chown:string -> src:(heredoc list) -> dst:string -> unit -> t +val copy_heredoc : ?chown:string -> src:heredoc list -> dst:string -> unit -> t (** [copy_heredoc src dst] creates the file [dst] using the content of the here-documents [src]. Requires BuildKit 1.4 {{!val:parser_directive}syntax}. From b9e0665a350f252f11e0a37a70074de5fcd058ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Wed, 27 Jul 2022 17:48:15 +0200 Subject: [PATCH 4/5] Wrap libraries - `Dockerfile_gen` from the `dockerfile-cmd` package becomes `Dockerfile_cmd.Gen`; - `Dockerfile_distro`, `Dockerfile_linux`, `Dockerfile_windows` from the `dockerfile_opam` package respectively become `Dockerfile_opam.Distro`, `Dockerfile_opam.Linux`, `Dockerfile_opam.Windows`. --- CHANGES.md | 8 +++++++- src-cmd/dockerfile_cmd.ml | 2 ++ src-cmd/dockerfile_cmd.mli | 4 ++++ src-cmd/dune | 1 - src-cmd/{dockerfile_gen.ml => gen.ml} | 10 ++++++---- src-cmd/{dockerfile_gen.mli => gen.mli} | 2 ++ src-opam/{dockerfile_distro.ml => distro.ml} | 0 src-opam/{dockerfile_distro.mli => distro.mli} | 0 src-opam/dockerfile_opam.ml | 17 ++++++++--------- src-opam/dockerfile_opam.mli | 15 ++++++++------- src-opam/dune | 1 - src-opam/{dockerfile_linux.ml => linux.ml} | 0 src-opam/{dockerfile_linux.mli => linux.mli} | 0 src-opam/{dockerfile_windows.ml => windows.ml} | 9 +++------ .../{dockerfile_windows.mli => windows.mli} | 9 ++++----- 15 files changed, 44 insertions(+), 34 deletions(-) rename src-cmd/{dockerfile_gen.ml => gen.ml} (94%) rename src-cmd/{dockerfile_gen.mli => gen.mli} (98%) rename src-opam/{dockerfile_distro.ml => distro.ml} (100%) rename src-opam/{dockerfile_distro.mli => distro.mli} (100%) rename src-opam/{dockerfile_linux.ml => linux.ml} (100%) rename src-opam/{dockerfile_linux.mli => linux.mli} (100%) rename src-opam/{dockerfile_windows.ml => windows.ml} (98%) rename src-opam/{dockerfile_windows.mli => windows.mli} (96%) diff --git a/CHANGES.md b/CHANGES.md index ccc4702c..0c82adc6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,15 @@ unreleased ---------- +- Bump to OCaml 4.08 and remove dependencies on result and rresult (@MisterDA #106) +- Wrap libraries: + + `Dockerfile_gen` from the `dockerfile-cmd` package becomes `Dockerfile_cmd.Gen`; + + `Dockerfile_distro`, `Dockerfile_linux`, `Dockerfile_windows` from the + `dockerfile_opam` package respectively become `Dockerfile_opam.Distro`, + `Dockerfile_opam.Linux`, `Dockerfile_opam.Windows`. (@MisterDA #106) +- Generate opam images using BuildKit 1.4 syntax for Dockerfiles. (@MisterDA #105) - Support BuildKit 1.4 syntax of here-documents in `COPY` instructions. (@MisterDA #99) - Support BuildKit 1.4 `--link` flag in `ADD` and `COPY` instructions. (@MisterDA #99) -- Generate opam images using BuildKit 1.4 syntax for Dockerfiles. (@MisterDA #105) v8.0.0 2022-07-27 Sydney ------------------------ diff --git a/src-cmd/dockerfile_cmd.ml b/src-cmd/dockerfile_cmd.ml index 105d9401..3c2de5f1 100644 --- a/src-cmd/dockerfile_cmd.ml +++ b/src-cmd/dockerfile_cmd.ml @@ -38,6 +38,8 @@ let map fn l = | Ok v -> Ok (List.rev v) | e -> e +module Gen = Gen + type cmd_log = { command : string; stdout : string; diff --git a/src-cmd/dockerfile_cmd.mli b/src-cmd/dockerfile_cmd.mli index f12291fb..cb1dcbfd 100644 --- a/src-cmd/dockerfile_cmd.mli +++ b/src-cmd/dockerfile_cmd.mli @@ -92,3 +92,7 @@ val setup_logs : unit -> unit Cmdliner.Term.t val iter : ('a -> (unit, 'b) result) -> 'a list -> (unit, 'b) result val map : ('a -> ('b, 'c) result) -> 'a list -> ('b list, 'c) result + +(** {2 Generate Dockerfiles} *) + +module Gen = Gen diff --git a/src-cmd/dune b/src-cmd/dune index e395b951..4da5a395 100644 --- a/src-cmd/dune +++ b/src-cmd/dune @@ -3,7 +3,6 @@ (public_name dockerfile-cmd) (synopsis "Utility functions to generate Dockerfiles and execute Docker commands") - (wrapped false) (preprocess (per_module ((pps ppx_sexp_conv) diff --git a/src-cmd/dockerfile_gen.ml b/src-cmd/gen.ml similarity index 94% rename from src-cmd/dockerfile_gen.ml rename to src-cmd/gen.ml index a1487157..20895192 100644 --- a/src-cmd/dockerfile_gen.ml +++ b/src-cmd/gen.ml @@ -17,10 +17,12 @@ open Dockerfile open Bos -module U = Dockerfile_cmd let ( >>= ) = Result.bind +let rec iter fn l = + match l with hd :: tl -> fn hd >>= fun () -> iter fn tl | [] -> Ok () + let write_dockerfile ~crunch file dfile = Logs.debug (fun l -> l "Writing Dockerfile to %a" Fpath.pp file); (if crunch then Dockerfile.crunch dfile else dfile) @@ -33,7 +35,7 @@ let generate_dockerfile ?(fname = "Dockerfile") ?(crunch = true) output_dir d = write_dockerfile ~crunch file d let generate_dockerfiles_in_directories ?(crunch = true) output_dir = - U.iter (fun (name, dockerfile) -> + iter (fun (name, dockerfile) -> let dir = Fpath.(output_dir / name) in let file = Fpath.(dir / "Dockerfile") in Logs.info (fun l -> l "Generating %a" Fpath.pp file); @@ -41,7 +43,7 @@ let generate_dockerfiles_in_directories ?(crunch = true) output_dir = write_dockerfile ~crunch file dockerfile) let generate_dockerfiles ?(crunch = true) output_dir = - U.iter (fun (name, dockerfile) -> + iter (fun (name, dockerfile) -> let file = Fpath.(output_dir / ("Dockerfile." ^ name)) in Logs.info (fun l -> l "Generating: %a" Fpath.pp file); write_dockerfile ~crunch file dockerfile) @@ -49,7 +51,7 @@ let generate_dockerfiles ?(crunch = true) output_dir = let generate_dockerfiles_in_git_branches ?readme ?(crunch = true) output_dir d = (* TODO move git to dockerfile_cmd *) let git = Cmd.(v "git" % "-C" % p output_dir) in - U.iter + iter (fun (name, docker) -> Logs.info (fun l -> l "Switching to branch %s in %a\n%!" name Fpath.pp output_dir); diff --git a/src-cmd/dockerfile_gen.mli b/src-cmd/gen.mli similarity index 98% rename from src-cmd/dockerfile_gen.mli rename to src-cmd/gen.mli index 1659b0ff..bb41aeb4 100644 --- a/src-cmd/dockerfile_gen.mli +++ b/src-cmd/gen.mli @@ -15,6 +15,8 @@ * *) +(** Utility functions to generate Dockerfiles. *) + val generate_dockerfile : ?fname:string -> ?crunch:bool -> diff --git a/src-opam/dockerfile_distro.ml b/src-opam/distro.ml similarity index 100% rename from src-opam/dockerfile_distro.ml rename to src-opam/distro.ml diff --git a/src-opam/dockerfile_distro.mli b/src-opam/distro.mli similarity index 100% rename from src-opam/dockerfile_distro.mli rename to src-opam/distro.mli diff --git a/src-opam/dockerfile_opam.ml b/src-opam/dockerfile_opam.ml index 588aa9a2..a3068ebe 100644 --- a/src-opam/dockerfile_opam.ml +++ b/src-opam/dockerfile_opam.ml @@ -18,9 +18,10 @@ (** OPAM-specific Dockerfile rules *) open Dockerfile -module Linux = Dockerfile_linux -module Windows = Dockerfile_windows -module D = Dockerfile_distro +module Distro = Distro +module Linux = Linux +module Windows = Windows +module D = Distro module OV = Ocaml_version let personality ?arch distro = @@ -428,7 +429,7 @@ let gen_opam2_distro ?win10_revision ?winget ?(clone_opam_repo = true) ?arch in let clone = if clone_opam_repo then - let url = Dockerfile_distro.(os_family_of_distro d |> opam_repository) in + let url = Distro.(os_family_of_distro d |> opam_repository) in run "git clone %S /home/opam/opam-repository" url else empty in @@ -446,15 +447,13 @@ let create_switch ~arch distro t = let switch = OV.with_patch t None in match distro with | `Windows (port, _) -> - let pn, pv = - Dockerfile_windows.ocaml_for_windows_package_exn ~port ~arch ~switch - in + let pn, pv = Windows.ocaml_for_windows_package_exn ~port ~arch ~switch in create_switch switch (pv ^ pn) | _ -> create_switch switch (Ocaml_version.Opam.V2.name switch) let all_ocaml_compilers hub_id arch distro = let distro_tag = D.tag_of_distro distro in - let os_family = Dockerfile_distro.os_family_of_distro distro in + let os_family = Distro.os_family_of_distro distro in let compilers = OV.Releases.recent |> List.filter (fun ov -> D.distro_supported_on arch ov distro) @@ -503,7 +502,7 @@ let tag_of_ocaml_version ov = let separate_ocaml_compilers hub_id arch distro = let distro_tag = D.tag_of_distro distro in - let os_family = Dockerfile_distro.os_family_of_distro distro in + let os_family = Distro.os_family_of_distro distro in OV.Releases.recent_with_dev |> List.filter (fun ov -> D.distro_supported_on arch ov distro) |> List.map (fun ov -> diff --git a/src-opam/dockerfile_opam.mli b/src-opam/dockerfile_opam.mli index de3b75fe..e71bc68f 100644 --- a/src-opam/dockerfile_opam.mli +++ b/src-opam/dockerfile_opam.mli @@ -22,6 +22,10 @@ there change, so please contact [anil@recoil.org] if you depend on these functions for your own infrastructure. *) +module Distro = Distro +module Linux = Linux +module Windows = Windows + val run_as_opam : ('a, unit, string, Dockerfile.t) format4 -> 'a (** [run_as_opam fmt] runs the command specified by the [fmt] format string as the [opam] user. *) @@ -52,13 +56,13 @@ type opam_hashes = { } val gen_opam2_distro : - ?win10_revision:Dockerfile_distro.win10_lcu -> + ?win10_revision:Distro.win10_lcu -> ?winget:string -> ?clone_opam_repo:bool -> ?arch:Ocaml_version.arch -> ?labels:(string * string) list -> opam_hashes:opam_hashes -> - Dockerfile_distro.t -> + Distro.t -> string * Dockerfile.t (** [gen_opam2_distro ~opam_hashes d] will generate a Dockerfile for Linux distribution [d] with opam 2.0, opam 2.1, opam 2.2 and opam master, @@ -74,16 +78,13 @@ val gen_opam2_distro : winget will be pulled from the [winget] external image. *) val all_ocaml_compilers : - string -> Ocaml_version.arch -> Dockerfile_distro.t -> string * Dockerfile.t + string -> Ocaml_version.arch -> Distro.t -> string * Dockerfile.t (** [all_ocaml_compilers hub_id arch distro] will generate an opam2 container that has all the recent OCaml compilers installed into a distribution [distro] on architecture [arch]. *) val separate_ocaml_compilers : - string -> - Ocaml_version.arch -> - Dockerfile_distro.t -> - (string * Dockerfile.t) list + string -> Ocaml_version.arch -> Distro.t -> (string * Dockerfile.t) list (** [separate_ocaml_compilers hub_id arch distro] will install a list of Dockerfiles that build individual OCaml compiler versions and their variants (e.g. flambda) in separate containers. *) diff --git a/src-opam/dune b/src-opam/dune index ee09e09f..8fe9763f 100644 --- a/src-opam/dune +++ b/src-opam/dune @@ -2,7 +2,6 @@ (name dockerfile_opam) (public_name dockerfile-opam) (synopsis "Dockerfile functions to generate opam2 base containers") - (wrapped false) (libraries ocaml-version dockerfile fmt sexplib astring) (preprocess (per_module diff --git a/src-opam/dockerfile_linux.ml b/src-opam/linux.ml similarity index 100% rename from src-opam/dockerfile_linux.ml rename to src-opam/linux.ml diff --git a/src-opam/dockerfile_linux.mli b/src-opam/linux.mli similarity index 100% rename from src-opam/dockerfile_linux.mli rename to src-opam/linux.mli diff --git a/src-opam/dockerfile_windows.ml b/src-opam/windows.ml similarity index 98% rename from src-opam/dockerfile_windows.ml rename to src-opam/windows.ml index ff76ad2d..0f123d54 100644 --- a/src-opam/dockerfile_windows.ml +++ b/src-opam/windows.ml @@ -250,12 +250,9 @@ module Winget = struct let header ?win10_revision ?(version = - (Dockerfile_distro.win10_latest_image - : Dockerfile_distro.win10_release - :> Dockerfile_distro.win_all)) () = - let img, tag = - Dockerfile_distro.win10_base_tag ?win10_revision `Windows version - in + (Distro.win10_latest_image : Distro.win10_release :> Distro.win_all)) () + = + let img, tag = Distro.win10_base_tag ?win10_revision `Windows version in parser_directive (`Escape '`') @@ from ~alias:winget ~tag img @@ user "ContainerAdministrator" diff --git a/src-opam/dockerfile_windows.mli b/src-opam/windows.mli similarity index 96% rename from src-opam/dockerfile_windows.mli rename to src-opam/windows.mli index 88e55433..2ce01c8f 100644 --- a/src-opam/dockerfile_windows.mli +++ b/src-opam/windows.mli @@ -134,14 +134,14 @@ end (** Rules for winget installation. @see / *) module Winget : sig - val is_supported : Dockerfile_distro.win_all -> bool + val is_supported : Distro.win_all -> bool (** Winget 1.0.11692 discontinued support for versions older than Windows 10 1809. Older versions of Winget have bugs, don't use them. *) val install_from_release : - ?win10_revision:Dockerfile_distro.win10_lcu -> - ?version:Dockerfile_distro.win_all -> + ?win10_revision:Distro.win10_lcu -> + ?version:Distro.win_all -> ?winget_version:string -> unit -> t @@ -155,8 +155,7 @@ module Winget : sig val install : string list -> t (** [install packages] will install the supplied winget package list. *) - val dev_packages : - ?version:Dockerfile_distro.win_all -> ?extra:string list -> unit -> t + val dev_packages : ?version:Distro.win_all -> ?extra:string list -> unit -> t (** [dev_packages ?version ?extra ()] will install the base development tools. Extra packages may also be optionally supplied via [extra]. Using [?version] may change the set of installed packages. *) From d3f57652f0e63ce0f16941cd69e156bf53889198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Tue, 20 Sep 2022 12:07:04 +0200 Subject: [PATCH 5/5] Refactor Windows Git setup --- src-opam/windows.ml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src-opam/windows.ml b/src-opam/windows.ml index 0f123d54..c6781844 100644 --- a/src-opam/windows.ml +++ b/src-opam/windows.ml @@ -100,6 +100,15 @@ let ocaml_for_windows_package_exn ~switch ~port ~arch = let cleanup () = run_powershell {|Remove-Item 'C:\TEMP' -Recurse|} +let git_init ~name ~email ~opam_repository = + String.concat " && " + [ + sprintf "git config --global user.email '%s'" email; + sprintf "git config --global user.name '%s'" name; + "git config --system core.longpaths true"; + sprintf "git config --global --add safe.directory %s" opam_repository; + ] + module Cygwin = struct type cyg = { root : string; site : string; args : string list } @@ -230,11 +239,8 @@ module Cygwin = struct let init ?(cyg = default) ?(name = "Docker") ?(email = "docker@example.com") () = env [ ("HOME", cyg.root ^ {|\home\opam|}) ] - @@ run_sh ~cyg - "git config --global user.email '%s' && git config --global \ - user.name '%s' && git config --system core.longpaths true && git \ - config --global --add safe.directory /home/opam/opam-repository" - email name + @@ run_sh ~cyg "%s" + (git_init ~email ~name ~opam_repository:"/home/opam/opam-repository") end end @@ -316,10 +322,8 @@ module Winget = struct module Git = struct let init ?(name = "Docker") ?(email = "docker@example.com") () = - run - "git config --global user.email %S && git config --global user.name %S \ - && git config --system core.longpaths true && git config --global \ - --add safe.directory C:/cygwin64/home/opam/opam-repository" - email name + run "%s" + (git_init ~email ~name + ~opam_repository:"C:/cygwin64/home/opam/opam-repository") end end