-
Notifications
You must be signed in to change notification settings - Fork 14
/
overlay.nix
146 lines (137 loc) · 4.96 KB
/
overlay.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
{ lib }:
# This file contains a set of function that are being applyed to a package
# if they are declared in the `overlay` section of `package.json` file.
# See <link to the docs> for more details.
#
# The `self` and `super` are references
# to the resulting set of packages for a whole closure, coming from
# generated Nix expressions, like ./yarn.lock.nix.
let
getLocalPath = package-json: value:
# A naive check if the src is a path.
assert (lib.hasPrefix "." value) || (lib.hasPrefix "/" value);
builtins.path {
# See: https://nixos.org/manual/nix/stable/#builtin-path
name = builtins.replaceStrings [ "." "@" "+" ] [ "-" "-" "-" ] (builtins.baseNameOf value);
path =
if lib.hasPrefix "." value
# relative to the given `package.json` file
then (builtins.dirOf package-json) + "/${value}"
# an absolute path, nothing to do.
else value;
filter = p: t: ! (t == "directory" && lib.hasSuffix "node_modules" p);
};
in
{
# This is the entry point function that iterates over all the declarations in
# the `overlay` section in the `package.json` file and invoke functions declared
# in this attr set.
#
# Functions' naming convention:
# The "overlays.babel-jest.addDependencies" declaration corresponds to the
# `fn.addDependencies` function declared below that is being invoked with
# an attr set of arguments:
# - pkg
# - value (the value from the `package.json#overlays.babel-jest.addDependencies`)
# - self
# - super
# - package-json (the Nix's path type)
# - parsed (parsed `package.json` content)
#
# Add a function with prefix `fn.` so it will be automatically invoked. The function
# must return overriden package derivation. Be careful with `override` and `overrideAttrs`
# because the `override` called after `overrideAttrs` can cause issues.
#
__functor = this: package-json: self: super:
let
parsed = lib.importJSON package-json;
_ovrl = lib.attrByPath [ "js2nix" "overlay" ] { } parsed;
localPkgsOverlay =
let
# Get and merge the dependencies sections as an attrset
deps = builtins.foldl' (acc: curr: if lib.hasAttr curr parsed then acc // parsed.${curr} else acc) { } [
"dependencies"
"devDependencies"
];
# Filter out to have only the local ones, by prefix of "." or "/".
localDeps = builtins.filter
(e: let p = builtins.elemAt e 1; in (lib.hasPrefix "." p) || (lib.hasPrefix "/" p))
(lib.mapAttrsToList (name: value: [ name value ]) deps);
in
builtins.foldl'
(acc: curr:
let
name = builtins.elemAt curr 0;
value = builtins.elemAt curr 1;
pkg = super.${super.__meta__.aliases.${name}};
in
acc // {
${super.__meta__.aliases.${name}} = this.fn.src {
inherit pkg value self super package-json parsed;
};
}
)
{ }
localDeps;
overlay = builtins.foldl'
(acc: curr:
let
target = acc.${super.__meta__.aliases.${curr}} or super.${super.__meta__.aliases.${curr}};
declaration = _ovrl.${curr};
in
acc // {
${super.__meta__.aliases.${curr}} = builtins.foldl'
(prev: fn: this.fn.${fn} {
pkg = prev;
value = declaration.${fn};
inherit self super package-json parsed;
})
target
(builtins.attrNames declaration);
})
localPkgsOverlay
(builtins.attrNames _ovrl);
in
overlay;
# Add modules.
#
fn.addDependencies = { pkg, value, self, super, ... }:
assert builtins.typeOf value == "list";
let
modules = builtins.map
(name:
assert builtins.typeOf name == "string";
self.${super.__meta__.aliases.${name}})
value;
in
pkg.override (x: {
modules = (x.modules or [ ]) ++ modules;
});
fn.doCheck = { pkg, value, ... }:
# Accept only boolean as an input.
assert builtins.typeOf value == "bool";
pkg.override { doCheck = value; };
# Override the src field.
#
fn.src = { pkg, value, package-json, ... }:
# Accept only string or set as an input.
assert builtins.typeOf value == "string" || builtins.typeOf value == "set";
pkg.override (x: {
src =
if builtins.typeOf value == "string"
then getLocalPath package-json value
else x.src.override value;
});
fn.patches = { pkg, value, package-json, ... }:
# Accept only list of string as an input.
assert builtins.typeOf value == "list";
pkg.override (x: {
patches = builtins.map (getLocalPath package-json) value;
});
fn.lifeCycleScripts = { pkg, value, ... }:
# Accept only list of string as an input.
assert builtins.typeOf value == "list";
pkg.override (x: {
lifeCycleScripts = value;
});
}