Skip to content

Commit 88675c1

Browse files
committed
Add Nix setup
1 parent 2e8388a commit 88675c1

File tree

4 files changed

+253
-2
lines changed

4 files changed

+253
-2
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
.cabal-sandbox
33
cabal.sandbox.config
44
dist
5+
dist-newstyle
56

67
# ctags
78
tags
89

9-
# local vim configs
10-
.lvimrc
10+
# Nix build artifacts
11+
result*

default.nix

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
let
2+
sources = import nix/sources.nix;
3+
availableBuildTools = [ "cabal" "stack" ];
4+
in
5+
6+
{ pkgs ? import sources.nixpkgs {}
7+
, haskellPackages ? pkgs.haskellPackages
8+
9+
# nix-shell options
10+
, inNixShell ? false # Automatically set to `true` when used by nix-shell
11+
, buildTools ? [ "cabal" ] # See “availableBuildTools”
12+
, withHoogle ? true
13+
, withHLS ? true
14+
}:
15+
16+
assert builtins.all (x: builtins.elem x availableBuildTools) buildTools;
17+
18+
let
19+
inherit (pkgs) lib;
20+
cleanSource = pkgs.nix-gitignore.gitignoreRecursiveSource [ ./.gitignore ];
21+
22+
hsPkgs = haskellPackages.extend (self: super: {
23+
qm-interpolated-string =
24+
self.callCabal2nix "qm-interpolated-string" (cleanSource ./.) {};
25+
});
26+
27+
shell = hsPkgs.shellFor {
28+
name = "qm-interpolated-string-shell";
29+
packages = p: [ p.qm-interpolated-string ];
30+
inherit withHoogle;
31+
32+
buildInputs =
33+
lib.optional (builtins.elem "cabal" buildTools) hsPkgs.cabal-install
34+
++ lib.optional (builtins.elem "stack" buildTools) hsPkgs.stack
35+
++ lib.optional withHLS hsPkgs.haskell-language-server;
36+
};
37+
in
38+
39+
(if inNixShell then shell else {}) // {
40+
inherit shell;
41+
inherit (hsPkgs) qm-interpolated-string;
42+
}

nix/sources.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"nixpkgs": {
3+
"branch": "release-22.05",
4+
"description": "Nix Packages collection",
5+
"homepage": "",
6+
"owner": "NixOS",
7+
"repo": "nixpkgs",
8+
"rev": "4e329926df7ee5fa49929a83d31ee7d541f8b45c",
9+
"sha256": "0v6s0pbjnsqxha4ri0cgadaaiapln9z314myczmh3kqz8sd1i5sl",
10+
"type": "tarball",
11+
"url": "https://github.com/NixOS/nixpkgs/archive/4e329926df7ee5fa49929a83d31ee7d541f8b45c.tar.gz",
12+
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13+
}
14+
}

nix/sources.nix

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# This file has been generated by Niv.
2+
3+
let
4+
5+
#
6+
# The fetchers. fetch_<type> fetches specs of type <type>.
7+
#
8+
9+
fetch_file = pkgs: name: spec:
10+
let
11+
name' = sanitizeName name + "-src";
12+
in
13+
if spec.builtin or true then
14+
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
15+
else
16+
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
17+
18+
fetch_tarball = pkgs: name: spec:
19+
let
20+
name' = sanitizeName name + "-src";
21+
in
22+
if spec.builtin or true then
23+
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
24+
else
25+
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
26+
27+
fetch_git = name: spec:
28+
let
29+
ref =
30+
if spec ? ref then spec.ref else
31+
if spec ? branch then "refs/heads/${spec.branch}" else
32+
if spec ? tag then "refs/tags/${spec.tag}" else
33+
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
34+
submodules = if spec ? submodules then spec.submodules else false;
35+
submoduleArg =
36+
let
37+
nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0;
38+
emptyArgWithWarning =
39+
if submodules == true
40+
then
41+
builtins.trace
42+
(
43+
"The niv input \"${name}\" uses submodules "
44+
+ "but your nix's (${builtins.nixVersion}) builtins.fetchGit "
45+
+ "does not support them"
46+
)
47+
{}
48+
else {};
49+
in
50+
if nixSupportsSubmodules
51+
then { inherit submodules; }
52+
else emptyArgWithWarning;
53+
in
54+
builtins.fetchGit
55+
({ url = spec.repo; inherit (spec) rev; inherit ref; } // submoduleArg);
56+
57+
fetch_local = spec: spec.path;
58+
59+
fetch_builtin-tarball = name: throw
60+
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
61+
$ niv modify ${name} -a type=tarball -a builtin=true'';
62+
63+
fetch_builtin-url = name: throw
64+
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
65+
$ niv modify ${name} -a type=file -a builtin=true'';
66+
67+
#
68+
# Various helpers
69+
#
70+
71+
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
72+
sanitizeName = name:
73+
(
74+
concatMapStrings (s: if builtins.isList s then "-" else s)
75+
(
76+
builtins.split "[^[:alnum:]+._?=-]+"
77+
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
78+
)
79+
);
80+
81+
# The set of packages used when specs are fetched using non-builtins.
82+
mkPkgs = sources: system:
83+
let
84+
sourcesNixpkgs =
85+
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
86+
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
87+
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
88+
in
89+
if builtins.hasAttr "nixpkgs" sources
90+
then sourcesNixpkgs
91+
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
92+
import <nixpkgs> {}
93+
else
94+
abort
95+
''
96+
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
97+
add a package called "nixpkgs" to your sources.json.
98+
'';
99+
100+
# The actual fetching function.
101+
fetch = pkgs: name: spec:
102+
103+
if ! builtins.hasAttr "type" spec then
104+
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
105+
else if spec.type == "file" then fetch_file pkgs name spec
106+
else if spec.type == "tarball" then fetch_tarball pkgs name spec
107+
else if spec.type == "git" then fetch_git name spec
108+
else if spec.type == "local" then fetch_local spec
109+
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
110+
else if spec.type == "builtin-url" then fetch_builtin-url name
111+
else
112+
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
113+
114+
# If the environment variable NIV_OVERRIDE_${name} is set, then use
115+
# the path directly as opposed to the fetched source.
116+
replace = name: drv:
117+
let
118+
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
119+
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
120+
in
121+
if ersatz == "" then drv else
122+
# this turns the string into an actual Nix path (for both absolute and
123+
# relative paths)
124+
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
125+
126+
# Ports of functions for older nix versions
127+
128+
# a Nix version of mapAttrs if the built-in doesn't exist
129+
mapAttrs = builtins.mapAttrs or (
130+
f: set: with builtins;
131+
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
132+
);
133+
134+
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
135+
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
136+
137+
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
138+
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
139+
140+
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
141+
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
142+
concatMapStrings = f: list: concatStrings (map f list);
143+
concatStrings = builtins.concatStringsSep "";
144+
145+
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
146+
optionalAttrs = cond: as: if cond then as else {};
147+
148+
# fetchTarball version that is compatible between all the versions of Nix
149+
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
150+
let
151+
inherit (builtins) lessThan nixVersion fetchTarball;
152+
in
153+
if lessThan nixVersion "1.12" then
154+
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
155+
else
156+
fetchTarball attrs;
157+
158+
# fetchurl version that is compatible between all the versions of Nix
159+
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
160+
let
161+
inherit (builtins) lessThan nixVersion fetchurl;
162+
in
163+
if lessThan nixVersion "1.12" then
164+
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
165+
else
166+
fetchurl attrs;
167+
168+
# Create the final "sources" from the config
169+
mkSources = config:
170+
mapAttrs (
171+
name: spec:
172+
if builtins.hasAttr "outPath" spec
173+
then abort
174+
"The values in sources.json should not have an 'outPath' attribute"
175+
else
176+
spec // { outPath = replace name (fetch config.pkgs name spec); }
177+
) config.sources;
178+
179+
# The "config" used by the fetchers
180+
mkConfig =
181+
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
182+
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
183+
, system ? builtins.currentSystem
184+
, pkgs ? mkPkgs sources system
185+
}: rec {
186+
# The sources, i.e. the attribute set of spec name to spec
187+
inherit sources;
188+
189+
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
190+
inherit pkgs;
191+
};
192+
193+
in
194+
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

0 commit comments

Comments
 (0)