solver — Dependency resolution#
Everything about solving package constraints. The only library that needs the 0install solver and git libraries.
External dependencies#
exec(process execution for git commands inLocal_repo)layer(solution JSON persistence)opam-0install(the SAT-based dependency solver)opam-format(opam file parsing, formula evaluation)git-unix(git repository introspection for incremental solving)
Modules#
Context — solver context#
Reads packages from a Git_packages.t index (built from a git
opam-repository). All opam repos are in git, so there's no need
for a separate filesystem-backed context.
Supports prefer_oldest (for reproducible solves), doc/post dependency
filtering, user constraints, pinned packages, and tracking which
packages were examined (for incremental reuse).
Git_utils — git repository access#
val get_git_repo_store_and_hash : string -> Git.Store.t * Git.Hash.t
val resolve_commit_in_store : Git.Store.t -> string option -> Git.Hash.t
Git_packages — package index from git#
type t (** Lazy package index keyed by name *)
val of_commit : Git.Store.t -> Git.Hash.t -> t
val get_versions : t -> OpamPackage.Name.t -> OpamPackage.t list
val get_package : t -> OpamPackage.t -> OpamFile.OPAM.t option
val diff_packages : store:Git.Store.t -> Git.Hash.t -> Git.Hash.t -> OpamPackage.Name.t list
(** Compute which package names changed between two commits. *)
Local_repo — local package discovery#
For --local-repo support: discover .opam files in a directory,
compute cache hashes (from git state or file contents), validate repos.
val discover_packages : string -> string list
val repo_hash : string -> string
val find_for_packages : local_repos:string list -> string list -> (string * string list) option
val validate : string list -> (unit, string) result
Solve — the solver entry point#
val solve :
config:Config.t -> OpamPackage.t ->
(OpamPackage.Set.t OpamPackage.Map.t * OpamPackage.Name.Set.t,
string * OpamPackage.Name.Set.t) result
(** [solve config target] returns [Ok (solution, examined)] or
[Error (message, examined)]. The [examined] set enables incremental
solver reuse. *)
Graph — dependency graph operations#
val topological_sort :
OpamPackage.Set.t OpamPackage.Map.t -> OpamPackage.t list
(** Kahn's algorithm. Returns packages in build order. *)
val pkg_deps :
OpamPackage.Set.t OpamPackage.Map.t -> OpamPackage.t list ->
OpamPackage.Set.t OpamPackage.Map.t
(** Transitive dependency closure for each package. *)
val extract_dag :
OpamPackage.Set.t OpamPackage.Map.t -> OpamPackage.t ->
OpamPackage.Set.t OpamPackage.Map.t
(** Extract sub-DAG rooted at a given package. *)
val extract_ocaml_version :
OpamPackage.Set.t OpamPackage.Map.t -> OpamPackage.t option
(** Find ocaml-base-compiler or ocaml-variants in solution. *)
Opam_env — opam variable environment#
val std_env :
?ocaml_native:bool -> ?opam_version:string ->
arch:string -> os:string -> os_distribution:string ->
os_family:string -> os_version:string ->
?ocaml_version:OpamPackage.t -> unit ->
string -> OpamVariable.variable_contents option
Opamh — opam switch state helpers#
val dump_state : Fpath.t -> Fpath.t -> unit
(** [dump_state packages_dir state_file] writes switch-state from
packages directory. Used when assembling container overlays. *)
Dot_solution — graphviz output#
val to_string : OpamPackage.Set.t OpamPackage.Map.t -> string
val save : Fpath.t -> OpamPackage.Set.t OpamPackage.Map.t -> unit
Source in day10#
| day10 file | What moves here |
|---|---|
dir_context.ml |
Dir_context module |
git_context.ml |
Git_context module (if it exists) |
git_utils.ml |
Git_utils module |
git_packages.ml |
Git_packages module |
local_repo.ml |
Local_repo module |
opamh.ml |
Opamh module |
dot_solution.ml |
Dot_solution module |
main.ml |
solve, topological_sort, pkg_deps, extract_dag, extract_ocaml_version, opam_env/std_env |
util.ml |
std_env, solution_* (JSON persistence moves to layer) |
Testing#
Unit tests (needs opam-format, opam-0install)#
Graph.topological_sort— small DAG (A→B→C, A→C): verify order is [C, B, A]. Test single-node graph. Test cycle detection if applicable.Graph.pkg_deps— verify transitive closure: if A→B→C, thenpkg_deps Aincludes B and C.Graph.extract_dag— extract sub-DAG for a leaf vs a root, verify correct nodes.Graph.extract_ocaml_version— solution withocaml-base-compiler.5.1.0returns it. Solution without returnsNone.Opam_env.std_env— verify known variables (os,arch,os-distribution) return expected values. Verifyocaml-nativeflag works.Dot_solution—to_stringon a small solution produces valid DOT syntax.
Integration tests (needs opam repos on disk)#
Dir_context— create a minimal opam repo (2-3 packages with deps), create context, verifycandidatesreturns expected versions. Testprefer_oldestflips version order. Testfilter_depsrespects doc/post flags.Solve.solve— solve for a package in a minimal repo, verify the solution contains expected packages in correct dependency order.Local_repo— create a temp dir with.opamfiles, verifydiscover_packagesfinds them. Verifyrepo_hashis deterministic.
Git-related tests (needs git)#
Git_packages— init a temp git repo with opam-repo structure, commit, verifyof_commitindexes it correctly. Testdiff_packagesbetween two commits.
Failure mode tests#
Solve.solve— unsatisfiable: solve for a package with conflicting constraints (e.g. requires two incompatible versions of the same dep). VerifyError (message, examined)with a useful diagnostic, not a solver exception.Dir_context— corrupt opam file: place a malformed opam file in the repo. Verifycandidatesskips it (returns it as unavailable) rather than crashing the entire solve.Dir_context— empty repository: create context with an emptypackages/dir. Verifycandidatesreturns[]for any name.Git_utils— bad ref:resolve_commit_in_storewith a nonexistent commit SHA → meaningfulError, not an uncaught git library exception.Git_packages— missing package in commit:get_packagefor a package not in the commit →None.Local_repo— no opam files:discover_packageson a dir with no.opamfiles → returns[].Local_repo— not a git repo:repo_hashon a non-git directory → falls back to file content hashing (orError).