2020-03-25 22:14:18 +04:00
|
|
|
pkgs:
|
|
|
|
let
|
|
|
|
findOpamFile = src:
|
|
|
|
let
|
|
|
|
opamFiles = (builtins.filter (x: !isNull (builtins.match ".*.opam" x))
|
|
|
|
(builtins.attrNames (builtins.readDir src)));
|
|
|
|
in if builtins.length opamFiles == 1 then
|
|
|
|
builtins.head opamFiles
|
|
|
|
else
|
|
|
|
builtins.throw "Unable to determine a single opam file in ${src} (${
|
|
|
|
toString opamFiles
|
|
|
|
}), unable to proceed" "";
|
|
|
|
in rec {
|
|
|
|
opam-parser = pkgs.stdenv.mkDerivation {
|
|
|
|
name = "opam-parser";
|
|
|
|
src = ./opam-parser.hs;
|
|
|
|
unpackPhase = "true";
|
|
|
|
buildInputs = [ pkgs.ghc ];
|
|
|
|
buildPhase = "ghc -o $out $src";
|
|
|
|
phases = [ "buildPhase" ];
|
|
|
|
};
|
|
|
|
|
2020-03-26 14:38:56 +04:00
|
|
|
# Generate a nix file from an opam file
|
2020-03-25 22:14:18 +04:00
|
|
|
opam2nix = { src, opamFile ? findOpamFile src, ... }@args:
|
|
|
|
pkgs.runCommandNoCC (args.pname or opamFile + ".nix") args
|
2020-03-26 03:48:32 +04:00
|
|
|
"cat ${src}/${opamFile} | ${pkgs.glibc.bin}/bin/iconv -c -f utf-8 -t ascii | ${opam-parser} > $out";
|
2020-03-25 22:14:18 +04:00
|
|
|
|
2020-03-26 14:38:56 +04:00
|
|
|
# Traverse OPAM repository, producing an extension to
|
|
|
|
# ocamlPackages than includes all the packages in the repo.
|
2020-03-25 22:14:18 +04:00
|
|
|
traverseOPAMRepo = repo: self: super:
|
|
|
|
let
|
|
|
|
pkgNames = builtins.readDir "${repo}/packages";
|
|
|
|
parseVersion = n: builtins.head (builtins.match "[^.]*.(.*)" n);
|
|
|
|
versions = pkg:
|
|
|
|
map parseVersion
|
|
|
|
(builtins.attrNames (builtins.readDir "${repo}/packages/${pkg}"));
|
|
|
|
latestVersion = builtins.foldl'
|
|
|
|
(x: acc: if builtins.compareVersions x acc == 1 then x else acc) "";
|
2020-03-26 03:48:32 +04:00
|
|
|
opamPkgs = builtins.mapAttrs (name: _:
|
2020-03-25 22:14:18 +04:00
|
|
|
let
|
2020-03-26 03:48:32 +04:00
|
|
|
file = version:
|
|
|
|
opam2nix {
|
|
|
|
src = "${repo}/packages/${name}/${name}.${version}";
|
|
|
|
opamFile = "opam";
|
|
|
|
pname = name;
|
|
|
|
inherit version;
|
|
|
|
};
|
|
|
|
package = version: self.callPackage (file version) { };
|
|
|
|
latest = package (latestVersion (versions name));
|
|
|
|
others = map package (versions name);
|
|
|
|
in latest // {
|
|
|
|
versions = builtins.listToAttrs (map (p: {
|
|
|
|
name = p.version;
|
|
|
|
value = p;
|
|
|
|
}) others);
|
|
|
|
}) pkgNames;
|
2020-03-25 22:14:18 +04:00
|
|
|
in opamPkgs;
|
|
|
|
|
2020-03-26 14:38:56 +04:00
|
|
|
# Same as traverseOPAMRepo, but packages in super take precedence over packages from the new repo.
|
2020-03-26 03:48:32 +04:00
|
|
|
traverseOPAMRepo' = repo: self: super:
|
|
|
|
let traversed = traverseOPAMRepo repo self super;
|
|
|
|
in traversed // builtins.mapAttrs (name: v:
|
|
|
|
v // {
|
|
|
|
versions = (traversed.${name} or { versions = { }; }).versions;
|
|
|
|
}) super;
|
|
|
|
|
2020-03-26 14:38:56 +04:00
|
|
|
# Extension that adds callOPAMPackage to the package set
|
2020-03-26 03:48:32 +04:00
|
|
|
callOPAMPackage = self: super: {
|
|
|
|
callOPAMPackage = src: newAttrs: overrides:
|
|
|
|
(self.callPackage (opam2nix (newAttrs // { inherit src; }))
|
|
|
|
overrides).overrideAttrs ({ buildInputs, ... }@args:
|
|
|
|
{
|
|
|
|
inherit src;
|
|
|
|
buildInputs = buildInputs ++ newAttrs.extraBuildInputs or [ ];
|
|
|
|
propagatedBuildInputs = buildInputs
|
|
|
|
++ newAttrs.extraBuildInputs or [ ];
|
|
|
|
} // newAttrs);
|
|
|
|
};
|
2020-03-25 22:14:18 +04:00
|
|
|
}
|