-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfetchers.nix
189 lines (159 loc) · 5.7 KB
/
fetchers.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# snippets that can be shared by multiple fetchers (pkgs/build-support)
{ lib }:
let
commonH = hashTypes: rec {
hashNames = [ "hash" ] ++ hashTypes;
hashSet = lib.genAttrs hashNames (lib.const {});
};
fakeH = {
hash = lib.fakeHash;
sha256 = lib.fakeSha256;
sha512 = lib.fakeSha512;
};
in rec {
proxyImpureEnvVars = [
# We borrow these environment variables from the caller to allow
# easy proxy configuration. This is impure, but a fixed-output
# derivation like fetchurl is allowed to do so since its result is
# by definition pure.
"http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy"
"HTTP_PROXY" "HTTPS_PROXY" "FTP_PROXY" "ALL_PROXY" "NO_PROXY"
# https proxies typically need to inject custom root CAs too
"NIX_SSL_CERT_FILE"
];
/**
Converts an attrset containing one of `hash`, `sha256` or `sha512`,
into one containing `outputHash{,Algo}` as accepted by `mkDerivation`.
An appropriate “fake hash” is substituted when the hash value is `""`,
as is the [convention for fetchers](#sec-pkgs-fetchers-updating-source-hashes-fakehash-method).
All other attributes in the set remain as-is.
# Example
```nix
normalizeHash { } { hash = ""; foo = "bar"; }
=>
{
outputHash = lib.fakeHash;
outputHashAlgo = null;
foo = "bar";
}
```
```nix
normalizeHash { } { sha256 = lib.fakeSha256; }
=>
{
outputHash = lib.fakeSha256;
outputHashAlgo = "sha256";
}
```
```nix
normalizeHash { } { sha512 = lib.fakeSha512; }
=>
{
outputHash = lib.fakeSha512;
outputHashAlgo = "sha512";
}
```
# Type
```
normalizeHash :: { hashTypes :: List String, required :: Bool } -> AttrSet -> AttrSet
```
# Arguments
hashTypes
: the set of attribute names accepted as hash inputs, in addition to `hash`
required
: whether to throw if no hash was present in the input; otherwise returns the original input, unmodified
*/
normalizeHash = {
hashTypes ? [ "sha256" ],
required ? true,
}:
let
inherit (lib) concatMapStringsSep head tail throwIf;
inherit (lib.attrsets) attrsToList intersectAttrs removeAttrs optionalAttrs;
inherit (commonH hashTypes) hashNames hashSet;
in
args:
if args ? "outputHash" then
args
else
let
# The argument hash, as a {name, value} pair
h =
# All hashes passed in arguments (possibly 0 or >1) as a list of {name, value} pairs
let hashesAsNVPairs = attrsToList (intersectAttrs hashSet args); in
if hashesAsNVPairs == [] then
throwIf required "fetcher called without `hash`" null
else if tail hashesAsNVPairs != [] then
throw "fetcher called with mutually-incompatible arguments: ${concatMapStringsSep ", " (a: a.name) hashesAsNVPairs}"
else
head hashesAsNVPairs
;
in
removeAttrs args hashNames // (optionalAttrs (h != null) {
outputHashAlgo = if h.name == "hash" then null else h.name;
outputHash =
if h.value == "" then
fakeH.${h.name} or (throw "no “fake hash” defined for ${h.name}")
else
h.value;
})
;
/**
Wraps a function which accepts `outputHash{,Algo}` into one which accepts `hash` or `sha{256,512}`
# Example
```nix
withNormalizedHash { hashTypes = [ "sha256" "sha512" ]; } (
{ outputHash, outputHashAlgo, ... }:
...
)
```
is a function which accepts one of `hash`, `sha256`, or `sha512` (or the original's `outputHash` and `outputHashAlgo`).
Its `functionArgs` metadata only lists `hash` as a parameter, optional iff. `outputHash` was an optional parameter of
the original function. `sha256`, `sha512`, `outputHash`, or `outputHashAlgo` are not mentioned in the `functionArgs`
metadata.
# Type
```
withNormalizedHash :: { hashTypes :: List String } -> (AttrSet -> T) -> (AttrSet -> T)
```
# Arguments
hashTypes
: the set of attribute names accepted as hash inputs, in addition to `hash`
: they must correspond to a valid value for `outputHashAlgo`, currently one of: `md5`, `sha1`, `sha256`, or `sha512`.
f
: the function to be wrapped
::: {.note}
In nixpkgs, `mkDerivation` rejects MD5 `outputHash`es, and SHA-1 is being deprecated.
As such, there is no reason to add `md5` to `hashTypes`, and
`sha1` should only ever be included for backwards compatibility.
:::
# Output
`withNormalizedHash { inherit hashTypes; } f` is functionally equivalent to
```nix
args: f (normalizeHash {
inherit hashTypes;
required = !(lib.functionArgs f).outputHash;
} args)
```
However, `withNormalizedHash` preserves `functionArgs` metadata insofar as possible,
and is implemented somewhat more efficiently.
*/
withNormalizedHash = {
hashTypes ? [ "sha256" ]
}: fetcher:
let
inherit (lib.attrsets) genAttrs intersectAttrs removeAttrs;
inherit (lib.trivial) const functionArgs setFunctionArgs;
inherit (commonH hashTypes) hashSet;
fArgs = functionArgs fetcher;
normalize = normalizeHash {
inherit hashTypes;
required = !fArgs.outputHash;
};
in
# The o.g. fetcher must *only* accept outputHash and outputHashAlgo
assert fArgs ? outputHash && fArgs ? outputHashAlgo;
assert intersectAttrs fArgs hashSet == {};
setFunctionArgs
(args: fetcher (normalize args))
(removeAttrs fArgs [ "outputHash" "outputHashAlgo" ] // { hash = fArgs.outputHash; });
}