Skip to content

Instantly share code, notes, and snippets.

@samoht
Last active December 21, 2015 18:19
Show Gist options
  • Save samoht/6346885 to your computer and use it in GitHub Desktop.
Save samoht/6346885 to your computer and use it in GitHub Desktop.
Check that all the package correctly depend on ocamlfind
(* Run that file at the root of your repository:
ocamlbuild -pkg opam chek_ocamlfind.native --
This will rewrite all the OPAM files to add the missing ocamlfind dependency if needed.
*)
open OpamTypes
module N = OpamPackage.Name
let repo = OpamRepository.local (OpamFilename.cwd())
let packages = OpamRepository.packages_with_prefixes repo
let ocamlfind = N.of_string "ocamlfind"
let use_ocamlfind (commands: command list) =
let aux (args, _)= match args with
| (CString "ocamlfind",_) :: _ -> true
| [] -> true
| _ -> false in
List.exists aux commands
let depends_graph = Hashtbl.create 1024
let needs_graph = Hashtbl.create 1024
let get_depends name =
try Hashtbl.find depends_graph name
with Not_found -> N.Set.empty
let add_depends name deps =
let deps = N.Set.union deps (get_depends name) in
Hashtbl.replace depends_graph name deps
let depends_on_ocamlfind name =
N.Set.mem ocamlfind (get_depends name)
(* Fill the graph seeds, and gather dependency information *)
let () =
OpamPackage.Map.iter (fun nv prefix ->
let name = OpamPackage.name nv in
let file = OpamPath.Repository.opam repo prefix nv in
let opam = OpamFile.OPAM.read file in
let atoms = OpamFormula.atoms (OpamFile.OPAM.depends opam) in
let needs = List.exists (fun (name,_) -> name=ocamlfind) atoms in
Hashtbl.add needs_graph name needs;
List.iter (fun (n, _) ->
add_depends name (N.Set.singleton n)
) atoms
) packages
(* Transitive closure of the dependencies *)
(* XXX: very inefficient *)
let () =
let changes = ref true in
let names = Hashtbl.fold (fun h _ t -> h :: t) depends_graph [] in
while !changes do
changes := false;
List.iter (fun name ->
let preds0 = get_depends name in
let preds1 = N.Set.fold (fun n acc ->
N.Set.union acc (get_depends n)
) preds0 preds0 in
if N.Set.compare preds0 preds1 <> 0 then changes := true;
add_depends name preds1
) names
done
let () =
OpamPackage.Map.iter (fun nv prefix ->
let name = OpamPackage.name nv in
let file = OpamPath.Repository.opam repo prefix nv in
let opam = OpamFile.OPAM.read file in
let remove = OpamFile.OPAM.remove opam in
if use_ocamlfind remove && not (depends_on_ocamlfind name) then
let depends = And ( Atom (ocamlfind, Empty), OpamFile.OPAM.depends opam) in
let opam = OpamFile.OPAM.with_depends opam depends in
OpamGlobals.msg "Fixing %s\n" (OpamPackage.to_string nv);
OpamFile.OPAM.write file opam
) packages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment