A fork of mtelver's day10 project

It can solve

Mark Elvers b263c019

+211
+2
.gitignore
··· 1 + _build 2 + *.swp
+3
.ocamlformat
··· 1 + margin=160 2 + break-cases=all 3 + type-decl=sparse
+4
bin/dune
··· 1 + (executable 2 + (public_name day10) 3 + (name main) 4 + (libraries opam-0install))
+111
bin/git_context.ml
··· 1 + module Store = Git_unix.Store 2 + module Search = Git.Search.Make (Digestif.SHA1) (Store) 3 + open Lwt.Infix 4 + 5 + type rejection = 6 + | UserConstraint of OpamFormula.atom 7 + | Unavailable 8 + 9 + type t = { 10 + env : string -> OpamVariable.variable_contents option; 11 + packages : OpamFile.OPAM.t OpamPackage.Version.Map.t OpamPackage.Name.Map.t; 12 + pins : (OpamPackage.Version.t * OpamFile.OPAM.t) OpamPackage.Name.Map.t; 13 + constraints : OpamFormula.version_constraint OpamTypes.name_map; 14 + (* User-provided constraints *) 15 + test : OpamPackage.Name.Set.t; 16 + } 17 + 18 + let user_restrictions t name = OpamPackage.Name.Map.find_opt name t.constraints 19 + let dev = OpamPackage.Version.of_string "dev" 20 + 21 + let env t pkg v = 22 + if List.mem v OpamPackageVar.predefined_depends_variables then None 23 + else 24 + match OpamVariable.Full.to_string v with 25 + | "version" -> Some (OpamTypes.S (OpamPackage.version_to_string pkg)) 26 + | x -> t.env x 27 + 28 + let filter_deps t pkg f = 29 + let dev = OpamPackage.Version.compare (OpamPackage.version pkg) dev = 0 in 30 + let test = OpamPackage.Name.Set.mem (OpamPackage.name pkg) t.test in 31 + f |> OpamFilter.partial_filter_formula (env t pkg) |> OpamFilter.filter_deps ~build:true ~post:true ~test ~doc:false ~dev ~dev_setup:false ~default:false 32 + 33 + let candidates t name = 34 + match OpamPackage.Name.Map.find_opt name t.pins with 35 + | Some (version, opam) -> [ (version, Ok opam) ] 36 + | None -> ( 37 + match OpamPackage.Name.Map.find_opt name t.packages with 38 + | None -> 39 + OpamConsole.log "opam-0install" "Package %S not found!" (OpamPackage.Name.to_string name); 40 + [] 41 + | Some versions -> 42 + let user_constraints = user_restrictions t name in 43 + OpamPackage.Version.Map.bindings versions 44 + |> List.rev_map (fun (v, opam) -> 45 + match user_constraints with 46 + | Some test when not (OpamFormula.check_version_formula (OpamFormula.Atom test) v) -> (v, Error (UserConstraint (name, Some test))) 47 + | _ -> ( 48 + let pkg = OpamPackage.create name v in 49 + let available = OpamFile.OPAM.available opam in 50 + match OpamFilter.eval ~default:(B false) (env t pkg) available with 51 + | B true -> (v, Ok opam) 52 + | B false -> (v, Error Unavailable) 53 + | _ -> 54 + OpamConsole.error "Available expression not a boolean: %s" (OpamFilter.to_string available); 55 + (v, Error Unavailable)))) 56 + 57 + let pp_rejection f = function 58 + | UserConstraint x -> Fmt.pf f "Rejected by user-specified constraint %s" (OpamFormula.string_of_atom x) 59 + | Unavailable -> Fmt.string f "Availability condition not satisfied" 60 + 61 + let read_dir store hash = 62 + Store.read store hash >|= function 63 + | Error e -> Fmt.failwith "Failed to read tree: %a" Store.pp_error e 64 + | Ok (Git.Value.Tree tree) -> Some tree 65 + | Ok _ -> None 66 + 67 + let read_package store pkg hash = 68 + Search.find store hash (`Path [ "opam" ]) >>= function 69 + | None -> Fmt.failwith "opam file not found for %s" (OpamPackage.to_string pkg) 70 + | Some hash -> ( 71 + Store.read store hash >|= function 72 + | Ok (Git.Value.Blob blob) -> OpamFile.OPAM.read_from_string (Store.Value.Blob.to_string blob) 73 + | _ -> Fmt.failwith "Bad Git object type for %s!" (OpamPackage.to_string pkg)) 74 + 75 + (* Get a map of the versions inside [entry] (an entry under "packages") *) 76 + let read_versions store (entry : Store.Value.Tree.entry) = 77 + read_dir store entry.node >>= function 78 + | None -> Lwt.return_none 79 + | Some tree -> 80 + Store.Value.Tree.to_list tree 81 + |> Lwt_list.fold_left_s 82 + (fun acc (entry : Store.Value.Tree.entry) -> 83 + match OpamPackage.of_string_opt entry.name with 84 + | Some pkg -> read_package store pkg entry.node >|= fun opam -> OpamPackage.Version.Map.add pkg.version opam acc 85 + | None -> 86 + OpamConsole.log "opam-0install" "Invalid package name %S" entry.name; 87 + Lwt.return acc) 88 + OpamPackage.Version.Map.empty 89 + >|= fun versions -> Some versions 90 + 91 + let read_packages store commit = 92 + Search.find store commit (`Commit (`Path [ "packages" ])) >>= function 93 + | None -> Fmt.failwith "Failed to find packages directory!" 94 + | Some tree_hash -> ( 95 + read_dir store tree_hash >>= function 96 + | None -> Fmt.failwith "'packages' is not a directory!" 97 + | Some tree -> 98 + Store.Value.Tree.to_list tree 99 + |> Lwt_list.fold_left_s 100 + (fun acc (entry : Store.Value.Tree.entry) -> 101 + match OpamPackage.Name.of_string entry.name with 102 + | exception ex -> 103 + OpamConsole.log "opam-0install" "Invalid package name %S: %s" entry.name (Printexc.to_string ex); 104 + Lwt.return acc 105 + | name -> ( 106 + read_versions store entry >|= function 107 + | None -> acc 108 + | Some versions -> OpamPackage.Name.Map.add name versions acc)) 109 + OpamPackage.Name.Map.empty) 110 + 111 + let create ?(test = OpamPackage.Name.Set.empty) ?(pins = OpamPackage.Name.Map.empty) ~constraints ~env ~packages () = { env; packages; pins; constraints; test }
+13
bin/git_context.mli
··· 1 + include Opam_0install.S.CONTEXT 2 + 3 + val read_packages : Git_unix.Store.t -> Git_unix.Store.Hash.t -> OpamFile.OPAM.t OpamPackage.Version.Map.t OpamPackage.Name.Map.t Lwt.t 4 + (** [read_packages store commit] is an index of the opam files in [store] at [commit]. *) 5 + 6 + val create : 7 + ?test:OpamPackage.Name.Set.t -> 8 + ?pins:(OpamPackage.Version.t * OpamFile.OPAM.t) OpamPackage.Name.Map.t -> 9 + constraints:OpamFormula.version_constraint OpamPackage.Name.Map.t -> 10 + env:(string -> OpamVariable.variable_contents option) -> 11 + packages:OpamFile.OPAM.t OpamPackage.Version.Map.t OpamPackage.Name.Map.t -> 12 + unit -> 13 + t
+21
bin/main.ml
··· 1 + module Solver = Opam_0install.Solver.Make (Opam_0install.Switch_context) 2 + 3 + let constraints = OpamPackage.Name.Map.of_list [ (OpamPackage.Name.of_string "ocaml", (`Eq, OpamPackage.Version.of_string "5.3.0")) ] 4 + let pp_pkg = Fmt.of_to_string OpamPackage.to_string 5 + 6 + let _ = 7 + let root = OpamStateConfig.opamroot () in 8 + OpamFormatConfig.init (); 9 + ignore (OpamStateConfig.load_defaults root); 10 + OpamCoreConfig.init (); 11 + OpamStateConfig.init (); 12 + OpamGlobalState.with_ `Lock_none @@ fun gt -> 13 + OpamSwitchState.with_ `Lock_none gt @@ fun st -> 14 + let context = Opam_0install.Switch_context.create ~constraints st in 15 + let r = Solver.solve context [ OpamPackage.Name.of_string "obuilder" ] in 16 + match r with 17 + | Ok sels -> Fmt.pr "%a@." Fmt.(list ~sep:(any " ") pp_pkg) (Solver.packages_of_result sels) 18 + | Error problem -> 19 + OpamConsole.error "No solution"; 20 + print_endline (Solver.diagnostics problem); 21 + ()
+31
day10.opam
··· 1 + # This file is generated by dune, edit dune-project instead 2 + opam-version: "2.0" 3 + synopsis: "A short synopsis" 4 + description: "A longer description" 5 + maintainer: ["Maintainer Name <maintainer@example.com>"] 6 + authors: ["Author Name <author@example.com>"] 7 + license: "LICENSE" 8 + tags: ["add topics" "to describe" "your" "project"] 9 + homepage: "https://github.com/username/reponame" 10 + doc: "https://url/to/documentation" 11 + bug-reports: "https://github.com/username/reponame/issues" 12 + depends: [ 13 + "dune" {>= "3.17"} 14 + "ocaml" 15 + "odoc" {with-doc} 16 + ] 17 + build: [ 18 + ["dune" "subst"] {dev} 19 + [ 20 + "dune" 21 + "build" 22 + "-p" 23 + name 24 + "-j" 25 + jobs 26 + "@install" 27 + "@runtest" {with-test} 28 + "@doc" {with-doc} 29 + ] 30 + ] 31 + dev-repo: "git+https://github.com/username/reponame.git"
+26
dune-project
··· 1 + (lang dune 3.17) 2 + 3 + (name day10) 4 + 5 + (generate_opam_files true) 6 + 7 + (source 8 + (github username/reponame)) 9 + 10 + (authors "Author Name <author@example.com>") 11 + 12 + (maintainers "Maintainer Name <maintainer@example.com>") 13 + 14 + (license LICENSE) 15 + 16 + (documentation https://url/to/documentation) 17 + 18 + (package 19 + (name day10) 20 + (synopsis "A short synopsis") 21 + (description "A longer description") 22 + (depends ocaml) 23 + (tags 24 + ("add topics" "to describe" your project))) 25 + 26 + ; See the complete stanza docs at https://dune.readthedocs.io/en/stable/reference/dune-project/index.html