opam2nix prototype

This commit is contained in:
Alexander Bantyev 2020-03-25 21:14:18 +03:00
parent e9a26f7db7
commit 2796c9510e
Signed by: balsoft
GPG Key ID: E081FF12ADCB4AD5
7 changed files with 663 additions and 0 deletions

3
default.nix Normal file
View File

@ -0,0 +1,3 @@
{ sources ? import ./nix/sources.nix }:
let ocaml-overlay = import ./nix/ocaml-overlay.nix { inherit sources; };
in import sources.nixpkgs { overlays = [ ocaml-overlay ]; }

7
nix/dune-package.nix Normal file
View File

@ -0,0 +1,7 @@
{ buildDunePackage, $DEPENDS }:
buildDunePackage {
pname = "$name";
version = "$version";
buildInputs = [ $DEPENDS_SPACES ];
src = $source;
}

57
nix/lib.nix Normal file
View File

@ -0,0 +1,57 @@
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" ];
};
opam2nix = { src, opamFile ? findOpamFile src, ... }@args:
pkgs.runCommandNoCC (args.pname or opamFile + ".nix") args
"cat ${src}/${opamFile} | ${opam-parser} > $out";
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) "";
opamPkgs = builtins.mapAttrs (n: _:
let
v = latestVersion (versions n);
file = opam2nix {
src = "${repo}/packages/${n}/${n}.${v}";
opamFile = "opam";
pname = n;
version = v;
};
in self.callPackage file { }) pkgNames;
in opamPkgs;
callOPAMPackage' = callPackage: src: newAttrs: overrides:
(callPackage (opam2nix (newAttrs // { inherit src; }))
overrides).overrideAttrs ({ buildInputs, src ? src, ... }:
{
inherit src;
buildInputs = buildInputs ++ newAttrs.extraBuildInputs or [ ];
propagatedBuildInputs = buildInputs
++ newAttrs.extraBuildInputs or [ ];
} // newAttrs);
}

169
nix/ocaml-overlay.nix Normal file
View File

@ -0,0 +1,169 @@
{ sources ? import ./sources.nix, version ? "git" }:
self: super:
let lib = import ./lib.nix self;
in {
ocamlPackages = super.ocaml-ng.ocamlPackages_4_09.overrideScope'
(builtins.foldl' self.lib.composeExtensions (_: _: { }) [
(oself: osuper:
(lib.traverseOPAMRepo (builtins.fetchTarball
"https://github.com/ocaml/opam-repository/archive/master.tar.gz") oself osuper)
// osuper)
(lib.traverseOPAMRepo ../../tezos-opam-repository)
(oself: osuper:
with oself; {
ocamlfind = findlib;
lwt = lwt4;
bigstring-unix = null;
})
]);
}
# (oself: osuper:
# let
# callTezosPackage = name: args:
# oself.callOPAMPackage "${sources.tezos}/src/lib_${
# builtins.replaceStrings [ "-" ] [ "_" ] name
# }" ({
# pname = "tezos-${name}";
# version = sources.tezos.rev;
# });
# tezos = builtins.listToAttrs (map (name: {
# name = "tezos-${name}";
# value = callTezosPackage name { } { };
# }) [
# "base"
# "event-logging"
# "micheline"
# "clic"
# "rpc"
# "error-monad"
# "stdlib"
# "crypto"
# ]);
# in tezos // {
# lwt = oself.lwt4;
# bigstring = oself.callOPAMPackage sources.bigstring {
# opamFile = "bigstring.opam";
# buildPhase = "dune build -p bigstring";
# } { bigstring-unix = null; };
# hidapi = oself.callOPAMPackage sources.hidapi {
# version = "1.1.1";
# extraBuildInputs = [ self.pkg-config ];
# } { conf-hidapi = self.hidapi; };
# crowbar = oself.callOPAMPackage sources.crowbar {
# pname = "crowbar";
# version = "0.1";
# } { };
# afl-persistent = oself.callOPAMPackage sources.ocaml-afl-persistent {
# pname = "afl-persistent";
# version = "1.1";
# } { };
# blake2 = oself.callOPAMPackage sources.blake2 {
# pname = "blake2";
# version = "0.2";
# } { };
# hacl = oself.callOPAMPackage sources.hacl {
# pname = "hacl";
# version = "0.1";
# } { };
# xmldiff = oself.callPackage
# ({ stdenv, autoreconfHook, ocaml, findlib, xmlm }:
# stdenv.mkDerivation {
# pname = "xmldiff";
# version = "0.5.0";
# src = sources.xmldiff;
# preInstall =
# "mkdir -p $out/lib/ocaml/${oself.ocaml.version}/site-lib";
# nativeBuildInputs = [ autoreconfHook ocaml findlib ];
# buildInputs = [ xmlm findlib ];
# }) { };
# json-data-encoding = oself.callOPAMPackage sources.json-data-encoding {
# opamFile = "json-data-encoding.opam";
# pname = "json-data-encoding";
# version = "0.8";
# extraBuildInputs = [ oself.crowbar ];
# } { };
# json-data-encoding-bson =
# oself.callOPAMPackage sources.json-data-encoding {
# opamFile = "json-data-encoding-bson.opam";
# pname = "json-data-encoding-bson";
# version = "0.8";
# } { };
# data-encoding = oself.callOPAMPackage sources.data-encoding {
# pname = "data-encoding";
# version = "0.0.0";
# } { };
# secp256k1-internal = oself.callOPAMPackage sources.secp256k1-internal {
# pname = "secp256k1-internal";
# version = "0.1.0";
# } { conf-gmp = self.gmp; };
# uecc = oself.callOPAMPackage sources.uecc {
# pname = "uecc";
# version = "0.1";
# } { };
# resto = oself.callOPAMPackage sources.resto {
# opamFile = "resto.opam";
# pname = "resto";
# version = "0.4";
# } { };
# resto-directory = oself.callOPAMPackage sources.resto {
# opamFile = "resto-directory.opam";
# pname = "resto-directory";
# version = "0.4";
# } { resto-json = null; };
# lwt-canceler = oself.callOPAMPackage sources.lwt-canceler {
# pname = "lwt-canceler";
# version = "0.2";
# } { };
# simple-utils =
# oself.callOPAMPackage ../vendors/ligo-utils/simple-utils {
# pname = "simple-utils";
# version = "0.1";
# } { };
# michelson-parser = oself.callOPAMPackage
# ../vendors/ligo-utils/tezos-utils/michelson-parser {
# pname = "michelson-parser";
# version = "0.0.0";
# } { ocamlfind = oself.findlib; };
# tezos-tooling = oself.callOPAMPackage "${sources.tezos}/src/tooling" {
# pname = "tezos-tooling";
# version = sources.tezos.rev;
# } { };
# tezos-protocol-environment = oself.callOPAMPackage
# "${sources.tezos}/src/lib_protocol_environment" {
# pname = "tezos-protocol-environment";
# opamFile = "tezos-protocol-environment.opam";
# version = sources.tezos.rev;
# } { };
# tezos-memory-proto-alpha =
# oself.callOPAMPackage ../vendors/ligo-utils/memory-proto-alpha {
# pname = "tezos-memory-proto-alpha";
# version = "0.0.0";
# } { };
# tezos-stdlib-unix =
# oself.callOPAMPackage "${sources.tezos}/src/lib_stdlib_unix" {
# pname = "tezos-stdlib-unix";
# version = sources.tezos.rev;
# extraBuildInputs = [ oself.fmt ];
# } { conf-libev = self.libev; };
# tezos-protocol-alpha = null;
# tezos-protocol-006-PsCARTHA = null;
# tezos-protocol-environment-sigs = null;
# tezos-data-encoding = null;
# tezos-utils = oself.callOPAMPackage ../vendors/ligo-utils/tezos-utils {
# pname = "tezos-utils";
# version = "0.1";
# } { };
# proto-alpha-utils =
# oself.callOPAMPackage ../vendors/ligo-utils/proto-alpha-utils {
# pname = "proto-alpha-utils";
# version = "0.1";
# } { };
# terminal_size = oself.callOPAMPackage sources.terminal_size {
# pname = "terminal_size";
# version = "0.1.4";
# } { };
# ligo = oself.callOPAMPackage ../. { version = "0.1"; } {
# ocamlfind = oself.findlib;
# };
# });
# }

135
nix/opam-parser.hs Normal file
View File

@ -0,0 +1,135 @@
{-# LANGUAGE FlexibleContexts, LambdaCase, RecordWildCards #-}
import Text.Parsec
import Data.Functor.Identity (Identity ())
import System.Environment (getEnv)
import Data.Maybe (fromJust, isNothing, maybeToList)
import Control.Monad (void)
import Data.List (intersperse, nub, isPrefixOf)
import qualified Control.Applicative as A (optional)
type Package = String
data OPAM
= OPAM
{ name :: Maybe String
, version :: Maybe String
, depends :: Maybe [String]
, build :: Maybe [[String]]
, source :: Maybe (String)
} deriving Show
opam2nix :: OPAM -> String
opam2nix OPAM {..} =
let depends' = nub ([ "findlib", "ocaml", "opaline", "dune" ]
++ (map (\case 'b':'a':'s':'e':_ -> "base"; s -> s)
$ mconcat $ maybeToList depends))
in
"{ stdenv, fetchzip, " <> (mconcat $ intersperse ", " depends') <> " }:\n"
<>"stdenv.mkDerivation rec {\n"
<>foldMap (\name -> " pname = \""<>name<>"\";\n") name
<>foldMap (\version -> " version = \""<>version<>"\";\n") version
<>foldMap (\url -> " src = builtins.fetchTarball { url = \""<>url<>"\"; };\n") source
<>" buildInputs = [ "<>(mconcat $ intersperse " " depends')<>" ];\n"
<>" propagatedBuildInputs = buildInputs;\n"
<>foldMap (\build -> " buildPhase = ''runHook preBuild\n"<>(mconcat $ intersperse " " $ mconcat $ intersperse ["\n"] $ build)<>"\nrunHook postBuild\n'';\n") build
<>(if "dune" `elem` depends' then " installPhase = ''\nrunHook preInstall\nopaline -prefix $out -libdir $OCAMLFIND_DESTDIR\nrunHook postInstall\n'';\n" else "")
<>"}\n"
getSha512 :: [String] -> String
getSha512 cs = (tail.tail.tail.tail.tail.tail.tail) $ head $ filter (isPrefixOf "sha512=") cs
evaluateField :: OPAM -> Field -> OPAM
evaluateField o@(OPAM {..}) = \case
Name s -> o { name = if isNothing name then Just s else name }
Version s -> o { version = if isNothing version then Just s else version }
Depends s -> o { depends = if isNothing depends then Just s else depends }
Build e -> o { build = if isNothing build then Just (fmap (evaluateExp $ fromJust $ name) <$> e) else build }
URL url -> o { source = if isNothing source then Just url else source }
Other _ -> o
evaluateFields :: OPAM -> [Field] -> OPAM
evaluateFields = foldl evaluateField
data Field
= Name String
| Version String
| Depends [Package]
| Build [[Exp]]
| URL String
| Other String
deriving Show
data Exp = Raw String | NameVar | JobsVar deriving Show
evaluateExp :: String -> Exp -> String
evaluateExp name = \case
Raw s -> s
NameVar -> name
JobsVar -> "1"
opamFile :: ParsecT String u Identity [Field]
opamFile = many field <* eof
field :: ParsecT String u Identity Field
field = Name <$> fieldParser "name" stringParser
<|> Version <$> fieldParser "version" stringParser
<|> Depends <$> fieldParser "depends" (listParser packageParser)
<|> Build <$> fieldParser "build" (pure <$> try commandParser <|> listParser commandParser)
<|> sectionParser "url" (URL <$> (fieldParser "src" stringParser <* many (noneOf "}")))
<|> Other <$> ((many (noneOf "\n")) <* char '\n')
fieldParser :: String -> ParsecT String u Identity t -> ParsecT String u Identity t
fieldParser name valueParser = try $ between (string (name<>":") >> (many $ oneOf " \n")) (many $ oneOf " \n") valueParser <* commentParser
sectionParser :: String -> ParsecT String u Identity t -> ParsecT String u Identity t
sectionParser name valueParser = try $ between (string name >> many (oneOf " ") >> string "{" >> many (oneOf " \n")) (many (oneOf " \n") >> char '}' >> char '\n') valueParser
stringParser :: ParsecT String u Identity String
stringParser = between (char '"') (char '"') (many $ noneOf "\"")
expParser :: ParsecT String u Identity Exp
expParser = try (string "name" >> return NameVar)
<|> try (string "jobs" >> return JobsVar)
<|> Raw <$> stringParser
commandParser :: ParsecT String u Identity [Exp]
commandParser = do
command <- listParser expParser
optional $ try $ between (many (char ' ') >> char '{') (char '}') (many $ noneOf "}")
return command
commentParser :: ParsecT String u Identity ()
commentParser = optional $ do
void $ string "#"
many $ noneOf "\n"
packageParser :: ParsecT String u Identity Package
packageParser = do
name <- stringParser
optional $ try $ between (many (char ' ') >> string "{") (char '}') (many $ noneOf "}")
return name
listParser :: ParsecT String u Identity t -> ParsecT String u Identity [t]
listParser valueParser =
between (char '[') (char ']') $ between startPadding endPadding
valueParser `sepBy` sep
where
startPadding = sep
endPadding = optional $ oneOf " \n"
sep = (whiteSpace >> commentParser) <|> whiteSpace
whiteSpace = (optional $ many $ oneOf " \n")
main :: IO ()
main = do
initialOPAM <- OPAM
<$> A.optional (getEnv "pname")
<*> A.optional (getEnv "version")
<*> pure Nothing
<*> pure Nothing
<*> pure Nothing
getContents >>= \s -> case parse opamFile "(unknown)" s of
Left e -> putStrLn $ show e
Right fs -> putStrLn $ opam2nix $ evaluateFields initialOPAM fs
-- Right fs -> print fs

158
nix/sources.json Normal file
View File

@ -0,0 +1,158 @@
{
"bigstring": {
"branch": "master",
"description": "Overlay over bigarrays of chars",
"homepage": "http://c-cube.github.io/ocaml-bigstring/",
"owner": "c-cube",
"repo": "ocaml-bigstring",
"rev": "38f766741634bfeba3f24ca72d4e902289d1a75d",
"sha256": "1vxc8jaxxn2djiwa8p12my5a2q1w3j3cdcdsafx0mlw3sz601siy",
"type": "tarball",
"url": "https://github.com/c-cube/ocaml-bigstring/archive/38f766741634bfeba3f24ca72d4e902289d1a75d.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"blake2": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/ocaml-blake2",
"rev": "d9599805097ee70ab271ffebcf959683efad9aaa",
"type": "git"
},
"crowbar": {
"branch": "master",
"description": "Property fuzzing for OCaml",
"homepage": null,
"owner": "stedolan",
"repo": "crowbar",
"rev": "9bbb8013c41c632e15db639cdba8a0d180c9755f",
"sha256": "01d7qp1xg0vrm7xi7chzx7kfrbfh504hwmpz7s44rkwhrdp9dk9x",
"type": "tarball",
"url": "https://github.com/stedolan/crowbar/archive/9bbb8013c41c632e15db639cdba8a0d180c9755f.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"data-encoding": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/data-encoding",
"rev": "c38bfaf8d320e05050a55b7634503f5dd80d9668",
"type": "git"
},
"genspio": {
"branch": "master",
"description": "Generate Shell Phrases In OCaml",
"homepage": "https://smondet.gitlab.io/genspio-doc/",
"owner": "hammerlab",
"repo": "genspio",
"rev": "f270fb296cebcf25e2ea89a7929a274c03ae9e6e",
"sha256": "09kr2b78f2184fajavbi7zigy0zlhz0bys4679rg0h6p828rdfhq",
"type": "tarball",
"url": "https://github.com/hammerlab/genspio/archive/f270fb296cebcf25e2ea89a7929a274c03ae9e6e.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"hacl": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/ocaml-hacl",
"rev": "d2e39bb0c53188369723d97c48f1c50184544624",
"type": "git"
},
"hidapi": {
"branch": "master",
"description": "Bindings to http://www.signal11.us/oss/hidapi/",
"homepage": null,
"owner": "vbmithr",
"repo": "ocaml-hidapi",
"rev": "5ea3529099955b290199621b5e7b4cb74ffabf95",
"sha256": "1qhc8iby3i54zflbi3yrnhpg62pwdl6g2sfnykgashjy7ghh495y",
"type": "tarball",
"url": "https://github.com/vbmithr/ocaml-hidapi/archive/5ea3529099955b290199621b5e7b4cb74ffabf95.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"json-data-encoding": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/json-data-encoding",
"rev": "0112ce9e2b07ad7a77ac383e9a22261045dd0018",
"type": "git"
},
"ligo-utils": {
"ref": "master",
"repo": "https://gitlab.com/ligolang/ligo-utils",
"rev": "533c801c103627484af042bf1f976eeffcf592e3",
"type": "git"
},
"lwt-canceler": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/lwt-canceler",
"rev": "02e6e7cc23bf6ab9479bc370b1511a727ce02c61",
"type": "git"
},
"nixpkgs": {
"branch": "ocaml-cross-fixes",
"description": "Pinned Nixpkgs tree (master follows nixos-unstable-small, only tags have stable history)",
"homepage": "",
"owner": "serokell",
"repo": "nixpkgs",
"rev": "80a7615300badde924f2ca30caa988484c6c11cc",
"sha256": "09i6f2qpsbgr2m8b5a1ac13fvhvg25560xvscl83bj9bb28sc3xc",
"type": "tarball",
"url": "https://github.com/serokell/nixpkgs/archive/80a7615300badde924f2ca30caa988484c6c11cc.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"ocaml-afl-persistent": {
"branch": "master",
"description": "persistent-mode afl-fuzz for ocaml",
"homepage": null,
"owner": "stedolan",
"repo": "ocaml-afl-persistent",
"rev": "a37c4f581ba417d7e09a6efb34fdd8a90a7e9ede",
"sha256": "1krp9vbyi79hh9nhylx47frsb08wb9vla85kykx5cma5y6rnxprh",
"type": "tarball",
"url": "https://github.com/stedolan/ocaml-afl-persistent/archive/a37c4f581ba417d7e09a6efb34fdd8a90a7e9ede.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"resto": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/resto",
"rev": "099145d1997ed8b38c98d9b6197c734d5afa9ea1",
"type": "git"
},
"secp256k1-internal": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/ocaml-secp256k1-internal",
"rev": "c54b3e4ac9015ea503132223a5aeb6ac0d752e1b",
"type": "git"
},
"terminal_size": {
"branch": "master",
"description": "Get the size of the attached terminal in OCaml",
"homepage": null,
"owner": "cryptosense",
"repo": "terminal_size",
"rev": "07464b9ead32fa3201fea36a8d21252d20151caa",
"sha256": "1yjr2aamy20iw8nw13nzj6h8y5g8aby80kshl53hdnd316vddp0f",
"type": "tarball",
"url": "https://github.com/cryptosense/terminal_size/archive/07464b9ead32fa3201fea36a8d21252d20151caa.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"tezos": {
"ref": "master",
"repo": "https://gitlab.com/tezos/tezos",
"rev": "be706b7060cc9805d66fce1a032a586d09ee8718",
"type": "git"
},
"uecc": {
"ref": "master",
"repo": "https://gitlab.com/nomadic-labs/ocaml-uecc",
"rev": "44e0c343b02702eec7e8011244a7bf61e21a8bf3",
"type": "git"
},
"xmldiff": {
"branch": "master",
"description": "Diffs on XML trees",
"homepage": "http://zoggy.github.io/xmldiff",
"owner": "zoggy",
"repo": "xmldiff",
"rev": "5873df80c1ba8c79287dc42e5008fac14cefffed",
"sha256": "0b92j9j2xdd2gyi9bgp39w0w1lkp0vc2rxq6wx6xdfvvklpprgb4",
"type": "tarball",
"url": "https://github.com/zoggy/xmldiff/archive/5873df80c1ba8c79287dc42e5008fac14cefffed.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

134
nix/sources.nix Normal file
View File

@ -0,0 +1,134 @@
# This file has been generated by Niv.
let
#
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: spec:
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; }
else
pkgs.fetchurl { inherit (spec) url sha256; };
fetch_tarball = pkgs: spec:
if spec.builtin or true then
builtins_fetchTarball { inherit (spec) url sha256; }
else
pkgs.fetchzip { inherit (spec) url sha256; };
fetch_git = spec:
builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
fetch_builtin-tarball = spec:
builtins.trace
''
WARNING:
The niv type "builtin-tarball" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=tarball -a builtin=true
''
builtins_fetchTarball { inherit (spec) url sha256; };
fetch_builtin-url = spec:
builtins.trace
''
WARNING:
The niv type "builtin-url" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=file -a builtin=true
''
(builtins_fetchurl { inherit (spec) url sha256; });
#
# Various helpers
#
# The set of packages used when specs are fetched using non-builtins.
mkPkgs = sources:
let
sourcesNixpkgs =
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {};
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
in
if builtins.hasAttr "nixpkgs" sources
then sourcesNixpkgs
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
import <nixpkgs> {}
else
abort
''
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
add a package called "nixpkgs" to your sources.json.
'';
# The actual fetching function.
fetch = pkgs: name: spec:
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs spec
else if spec.type == "tarball" then fetch_tarball pkgs spec
else if spec.type == "git" then fetch_git spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec
else if spec.type == "builtin-url" then fetch_builtin-url spec
else
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (
f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
);
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball { inherit url; }
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchurl;
in
if lessThan nixVersion "1.12" then
fetchurl { inherit url; }
else
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs (
name: spec:
if builtins.hasAttr "outPath" spec
then abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = fetch config.pkgs name spec; }
) config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? ./sources.json
, sources ? builtins.fromJSON (builtins.readFile sourcesFile)
, pkgs ? mkPkgs sources
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
};
in
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }