mirror of
https://github.com/nix-community/dream2nix.git
synced 2024-09-11 14:35:30 +03:00
chore: manage all-cabal-json via flake input
This commit is contained in:
parent
0cf5483645
commit
48f490a2ed
298
flake-compat.nix
Normal file
298
flake-compat.nix
Normal file
@ -0,0 +1,298 @@
|
||||
# Compatibility function to allow flakes to be used by
|
||||
# non-flake-enabled Nix versions. Given a source tree containing a
|
||||
# 'flake.nix' and 'flake.lock' file, it fetches the flake inputs and
|
||||
# calls the flake's 'outputs' function. It then returns an attrset
|
||||
# containing 'defaultNix' (to be used in 'default.nix'), 'shellNix'
|
||||
# (to be used in 'shell.nix').
|
||||
{
|
||||
src,
|
||||
system ? builtins.currentSystem or "unknown-system",
|
||||
}: let
|
||||
lockFilePath = src + "/flake.lock";
|
||||
|
||||
lockFile = builtins.fromJSON (builtins.readFile lockFilePath);
|
||||
|
||||
fetchTree = info:
|
||||
if info.type == "github"
|
||||
then {
|
||||
outPath =
|
||||
fetchTarball
|
||||
(
|
||||
{url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}";}
|
||||
// (
|
||||
if info ? narHash
|
||||
then {sha256 = info.narHash;}
|
||||
else {}
|
||||
)
|
||||
);
|
||||
rev = info.rev;
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
lastModified = info.lastModified;
|
||||
lastModifiedDate = formatSecondsSinceEpoch info.lastModified;
|
||||
narHash = info.narHash;
|
||||
}
|
||||
else if info.type == "git"
|
||||
then
|
||||
{
|
||||
outPath =
|
||||
builtins.fetchGit
|
||||
(
|
||||
{url = info.url;}
|
||||
// (
|
||||
if info ? rev
|
||||
then {inherit (info) rev;}
|
||||
else {}
|
||||
)
|
||||
// (
|
||||
if info ? ref
|
||||
then {inherit (info) ref;}
|
||||
else {}
|
||||
)
|
||||
// (
|
||||
if info ? submodules
|
||||
then {inherit (info) submodules;}
|
||||
else {}
|
||||
)
|
||||
);
|
||||
lastModified = info.lastModified;
|
||||
lastModifiedDate = formatSecondsSinceEpoch info.lastModified;
|
||||
narHash = info.narHash;
|
||||
}
|
||||
// (
|
||||
if info ? rev
|
||||
then {
|
||||
rev = info.rev;
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
}
|
||||
else {
|
||||
}
|
||||
)
|
||||
else if info.type == "path"
|
||||
then {
|
||||
outPath = builtins.path {path = info.path;};
|
||||
narHash = info.narHash;
|
||||
}
|
||||
else if info.type == "tarball"
|
||||
then {
|
||||
outPath =
|
||||
fetchTarball
|
||||
(
|
||||
{inherit (info) url;}
|
||||
// (
|
||||
if info ? narHash
|
||||
then {sha256 = info.narHash;}
|
||||
else {}
|
||||
)
|
||||
);
|
||||
}
|
||||
else if info.type == "gitlab"
|
||||
then {
|
||||
inherit (info) rev narHash lastModified;
|
||||
outPath =
|
||||
fetchTarball
|
||||
(
|
||||
{url = "https://${info.host or "gitlab.com"}/api/v4/projects/${info.owner}%2F${info.repo}/repository/archive.tar.gz?sha=${info.rev}";}
|
||||
// (
|
||||
if info ? narHash
|
||||
then {sha256 = info.narHash;}
|
||||
else {}
|
||||
)
|
||||
);
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
}
|
||||
else
|
||||
# FIXME: add Mercurial, tarball inputs.
|
||||
throw "flake input has unsupported input type '${info.type}'";
|
||||
|
||||
callFlake4 = flakeSrc: locks: let
|
||||
flake = import (flakeSrc + "/flake.nix");
|
||||
|
||||
inputs = builtins.mapAttrs (n: v:
|
||||
if v.flake or true
|
||||
then callFlake4 (fetchTree (v.locked // v.info)) v.inputs
|
||||
else fetchTree (v.locked // v.info))
|
||||
locks;
|
||||
|
||||
outputs = flakeSrc // (flake.outputs (inputs // {self = outputs;}));
|
||||
in
|
||||
assert flake.edition == 201909; outputs;
|
||||
|
||||
callLocklessFlake = flakeSrc: let
|
||||
flake = import (flakeSrc + "/flake.nix");
|
||||
outputs = flakeSrc // (flake.outputs {self = outputs;});
|
||||
in
|
||||
outputs;
|
||||
|
||||
rootSrc = let
|
||||
# Try to clean the source tree by using fetchGit, if this source
|
||||
# tree is a valid git repository.
|
||||
tryFetchGit = src:
|
||||
if isGit && !isShallow
|
||||
then let
|
||||
res = builtins.fetchGit src;
|
||||
in
|
||||
if res.rev == "0000000000000000000000000000000000000000"
|
||||
then removeAttrs res ["rev" "shortRev"]
|
||||
else res
|
||||
else {outPath = src;};
|
||||
# NB git worktrees have a file for .git, so we don't check the type of .git
|
||||
isGit = builtins.pathExists (src + "/.git");
|
||||
isShallow = builtins.pathExists (src + "/.git/shallow");
|
||||
in
|
||||
{
|
||||
lastModified = 0;
|
||||
lastModifiedDate = formatSecondsSinceEpoch 0;
|
||||
}
|
||||
// (
|
||||
if src ? outPath
|
||||
then src
|
||||
else tryFetchGit src
|
||||
);
|
||||
|
||||
# Format number of seconds in the Unix epoch as %Y%m%d%H%M%S.
|
||||
formatSecondsSinceEpoch = t: let
|
||||
rem = x: y: x - x / y * y;
|
||||
days = t / 86400;
|
||||
secondsInDay = rem t 86400;
|
||||
hours = secondsInDay / 3600;
|
||||
minutes = (rem secondsInDay 3600) / 60;
|
||||
seconds = rem t 60;
|
||||
|
||||
# Courtesy of https://stackoverflow.com/a/32158604.
|
||||
z = days + 719468;
|
||||
era =
|
||||
(
|
||||
if z >= 0
|
||||
then z
|
||||
else z - 146096
|
||||
)
|
||||
/ 146097;
|
||||
doe = z - era * 146097;
|
||||
yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
y = yoe + era * 400;
|
||||
doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
mp = (5 * doy + 2) / 153;
|
||||
d = doy - (153 * mp + 2) / 5 + 1;
|
||||
m =
|
||||
mp
|
||||
+ (
|
||||
if mp < 10
|
||||
then 3
|
||||
else -9
|
||||
);
|
||||
y' =
|
||||
y
|
||||
+ (
|
||||
if m <= 2
|
||||
then 1
|
||||
else 0
|
||||
);
|
||||
|
||||
pad = s:
|
||||
if builtins.stringLength s < 2
|
||||
then "0" + s
|
||||
else s;
|
||||
in "${toString y'}${pad (toString m)}${pad (toString d)}${pad (toString hours)}${pad (toString minutes)}${pad (toString seconds)}";
|
||||
|
||||
allNodes =
|
||||
builtins.mapAttrs
|
||||
(
|
||||
key: node: let
|
||||
sourceInfo =
|
||||
if key == lockFile.root
|
||||
then rootSrc
|
||||
else fetchTree (node.info or {} // removeAttrs node.locked ["dir"]);
|
||||
|
||||
subdir =
|
||||
if key == lockFile.root
|
||||
then ""
|
||||
else node.locked.dir or "";
|
||||
|
||||
flake = import (sourceInfo
|
||||
+ (
|
||||
if subdir != ""
|
||||
then "/"
|
||||
else ""
|
||||
)
|
||||
+ subdir
|
||||
+ "/flake.nix");
|
||||
|
||||
inputs =
|
||||
builtins.mapAttrs
|
||||
(inputName: inputSpec: allNodes.${resolveInput inputSpec})
|
||||
(node.inputs or {});
|
||||
|
||||
# Resolve a input spec into a node name. An input spec is
|
||||
# either a node name, or a 'follows' path from the root
|
||||
# node.
|
||||
resolveInput = inputSpec:
|
||||
if builtins.isList inputSpec
|
||||
then getInputByPath lockFile.root inputSpec
|
||||
else inputSpec;
|
||||
|
||||
# Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the
|
||||
# root node, returning the final node.
|
||||
getInputByPath = nodeName: path:
|
||||
if path == []
|
||||
then nodeName
|
||||
else
|
||||
getInputByPath
|
||||
# Since this could be a 'follows' input, call resolveInput.
|
||||
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
||||
(builtins.tail path);
|
||||
|
||||
outputs = flake.outputs (inputs // {self = result;});
|
||||
|
||||
result =
|
||||
outputs
|
||||
// sourceInfo
|
||||
// {
|
||||
inherit inputs;
|
||||
inherit outputs;
|
||||
inherit sourceInfo;
|
||||
};
|
||||
in
|
||||
if node.flake or true
|
||||
then assert builtins.isFunction flake.outputs; result
|
||||
else sourceInfo
|
||||
)
|
||||
lockFile.nodes;
|
||||
|
||||
result =
|
||||
if !(builtins.pathExists lockFilePath)
|
||||
then callLocklessFlake rootSrc
|
||||
else if lockFile.version == 4
|
||||
then callFlake4 rootSrc (lockFile.inputs)
|
||||
else if lockFile.version >= 5 && lockFile.version <= 7
|
||||
then allNodes.${lockFile.root}
|
||||
else throw "lock file '${lockFilePath}' has unsupported version ${toString lockFile.version}";
|
||||
in rec {
|
||||
# expose flake inputs
|
||||
inherit (result) inputs;
|
||||
|
||||
defaultNix =
|
||||
result
|
||||
// (
|
||||
if result ? defaultPackage.${system}
|
||||
then {default = result.defaultPackage.${system};}
|
||||
else {}
|
||||
)
|
||||
// (
|
||||
if result ? packages.${system}.default
|
||||
then {default = result.packages.${system}.default;}
|
||||
else {}
|
||||
);
|
||||
|
||||
shellNix =
|
||||
defaultNix
|
||||
// (
|
||||
if result ? devShell.${system}
|
||||
then {default = result.devShell.${system};}
|
||||
else {}
|
||||
)
|
||||
// (
|
||||
if result ? devShells.${system}.default
|
||||
then {default = result.devShells.${system}.default;}
|
||||
else {}
|
||||
);
|
||||
}
|
18
flake.lock
18
flake.lock
@ -22,6 +22,23 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"all-cabal-json": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1665552503,
|
||||
"narHash": "sha256-r14RmRSwzv5c+bWKUDaze6pXM7nOsiz1H8nvFHJvufc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "all-cabal-json",
|
||||
"rev": "d7c0434eebffb305071404edcf9d5cd99703878e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "hackage",
|
||||
"repo": "all-cabal-json",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@ -196,6 +213,7 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"alejandra": "alejandra",
|
||||
"all-cabal-json": "all-cabal-json",
|
||||
"crane": "crane",
|
||||
"devshell": "devshell",
|
||||
"flake-utils-pre-commit": "flake-utils-pre-commit",
|
||||
|
12
flake.nix
12
flake.nix
@ -15,7 +15,6 @@
|
||||
|
||||
pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
|
||||
pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
|
||||
# upstream flake-utils dep not supporting `aarch64-darwin` yet
|
||||
flake-utils-pre-commit.url = "github:numtide/flake-utils";
|
||||
pre-commit-hooks.inputs.flake-utils.follows = "flake-utils-pre-commit";
|
||||
|
||||
@ -48,6 +47,12 @@
|
||||
url = "github:ipetkov/crane";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
# required for haskell translators
|
||||
all-cabal-json = {
|
||||
url = "github:nix-community/all-cabal-json/hackage";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {
|
||||
@ -60,6 +65,7 @@
|
||||
poetry2nix,
|
||||
pre-commit-hooks,
|
||||
crane,
|
||||
all-cabal-json,
|
||||
...
|
||||
} @ inp: let
|
||||
b = builtins;
|
||||
@ -150,7 +156,7 @@
|
||||
dream2nixFor = forAllSystems (system: pkgs:
|
||||
import ./src rec {
|
||||
externalDir = externalDirFor."${system}";
|
||||
inherit externalPaths externalSources lib pkgs;
|
||||
inherit all-cabal-json externalPaths externalSources lib pkgs;
|
||||
config = {
|
||||
inherit overridesDirs;
|
||||
};
|
||||
@ -168,7 +174,7 @@
|
||||
# Produces flake-like output schema.
|
||||
d2n-lib =
|
||||
(import ./src/lib.nix {
|
||||
inherit externalPaths externalSources overridesDirs lib;
|
||||
inherit all-cabal-json externalPaths externalSources overridesDirs lib;
|
||||
nixpkgsSrc = "${nixpkgs}";
|
||||
})
|
||||
# system specific dream2nix library
|
||||
|
@ -6,6 +6,13 @@
|
||||
pkgs ? import <nixpkgs> {},
|
||||
lib ? pkgs.lib,
|
||||
nix ? pkgs.nix,
|
||||
all-cabal-json ?
|
||||
(import ../flake-compat.nix {
|
||||
src = ../.;
|
||||
inherit (pkgs) system;
|
||||
})
|
||||
.inputs
|
||||
.all-cabal-json,
|
||||
# default to empty dream2nix config
|
||||
config ?
|
||||
# if called via CLI, load config via env
|
||||
@ -52,6 +59,7 @@ in let
|
||||
|
||||
framework = import ./modules/framework.nix {
|
||||
inherit
|
||||
all-cabal-json
|
||||
apps
|
||||
lib
|
||||
dlib
|
||||
@ -74,6 +82,7 @@ in let
|
||||
callPackageDreamArgs =
|
||||
pkgs
|
||||
// {
|
||||
inherit all-cabal-json;
|
||||
inherit apps;
|
||||
inherit callPackageDream;
|
||||
inherit config;
|
||||
|
@ -7,12 +7,13 @@
|
||||
overridesDirs,
|
||||
externalSources,
|
||||
externalPaths,
|
||||
all-cabal-json,
|
||||
} @ args: let
|
||||
l = lib // builtins;
|
||||
|
||||
initDream2nix = config: pkgs:
|
||||
import ./default.nix
|
||||
{inherit config pkgs externalPaths externalSources;};
|
||||
{inherit all-cabal-json config pkgs externalPaths externalSources;};
|
||||
|
||||
loadConfig = config'': let
|
||||
config' = (import ./utils/config.nix).loadConfig config'';
|
||||
@ -93,6 +94,7 @@
|
||||
inherit lib dlib externalSources;
|
||||
dream2nixConfig = config;
|
||||
dream2nixConfigFile = l.toFile "dream2nix-config.json" (l.toJSON config);
|
||||
all-cabal-json = throw "all-cabal-json is not available before nixpkgs is imported";
|
||||
apps = throw "apps is not available before nixpkgs is imported";
|
||||
pkgs = throw "pkgs is not available before nixpkgs is imported";
|
||||
utils = throw "utils is not available before nixpkgs is imported";
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
all-cabal-json,
|
||||
apps,
|
||||
dlib,
|
||||
externals,
|
||||
@ -25,6 +26,9 @@ in {
|
||||
./translators
|
||||
];
|
||||
options = {
|
||||
all-cabal-json = lib.mkOption {
|
||||
type = t.raw;
|
||||
};
|
||||
apps = lib.mkOption {
|
||||
type = t.raw;
|
||||
};
|
||||
|
@ -4,6 +4,7 @@
|
||||
pkgs,
|
||||
utils,
|
||||
name,
|
||||
all-cabal-json,
|
||||
...
|
||||
}: let
|
||||
l = lib // builtins;
|
||||
@ -77,11 +78,7 @@ in {
|
||||
translate = let
|
||||
stackLockUtils = import ./utils.nix {inherit dlib lib pkgs;};
|
||||
all-cabal-hashes = let
|
||||
all-cabal-hashes' = pkgs.runCommandLocal "all-cabal-hashes" {} ''
|
||||
mkdir $out
|
||||
cd $out
|
||||
tar --strip-components 1 -xf ${pkgs.all-cabal-hashes}
|
||||
'';
|
||||
all-cabal-hashes' = all-cabal-json;
|
||||
names = dlib.listDirs all-cabal-hashes';
|
||||
getVersions = name: dlib.listDirs "${all-cabal-hashes'}/${name}";
|
||||
in
|
||||
@ -91,7 +88,7 @@ in {
|
||||
(getVersions name)
|
||||
(
|
||||
version:
|
||||
(l.fromJSON (l.readFile "${all-cabal-hashes'}/${name}/${version}/${name}.json"))
|
||||
(l.fromJSON (l.readFile "${all-cabal-hashes'}/${name}/${version}/${name}.hashes.json"))
|
||||
.package-hashes
|
||||
));
|
||||
in
|
||||
@ -156,7 +153,7 @@ in {
|
||||
(rawObj: dlib.nameVersionPair rawObj.name rawObj.version)
|
||||
serializedRawObjects;
|
||||
|
||||
haskellUtils = import ../utils.nix {inherit lib pkgs;};
|
||||
haskellUtils = import ../utils.nix {inherit all-cabal-json lib pkgs;};
|
||||
|
||||
cabalData =
|
||||
haskellUtils.batchFindJsonFromCabalCandidates
|
||||
|
@ -10,12 +10,6 @@
|
||||
sha256 = "1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7";
|
||||
});
|
||||
in rec {
|
||||
all-cabal-hashes = pkgs.runCommandLocal "all-cabal-hashes" {} ''
|
||||
mkdir $out
|
||||
cd $out
|
||||
tar --strip-components 1 -xf ${pkgs.all-cabal-hashes}
|
||||
'';
|
||||
|
||||
# The cabal2json program
|
||||
cabal2json = let
|
||||
haskellLib = pkgs.haskell.lib.compose;
|
||||
|
@ -1,21 +1,10 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
all-cabal-json,
|
||||
}: let
|
||||
l = lib // builtins;
|
||||
|
||||
all-cabal-json = let
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://github.com/nix-community/all-cabal-json/tarball/bdb5c96a57926392fbfd567867fada983f480195";
|
||||
sha256 = "sha256-C6/4T4yJ8uT0qmRezY5YT+dl0v6/FTpMEahuBMnPhiU=";
|
||||
};
|
||||
in
|
||||
pkgs.runCommandLocal "all-cabal-json" {} ''
|
||||
mkdir $out
|
||||
cd $out
|
||||
tar --strip-components 1 -xf ${src}
|
||||
'';
|
||||
|
||||
findJsonFromCabalCandidate = name: version: let
|
||||
jsonCabalFile = "${all-cabal-json}/${name}/${version}/${name}.json";
|
||||
in
|
||||
|
Loading…
Reference in New Issue
Block a user