edencommon: skip flaky test everywhere (#372055)
[NixPkgs.git] / lib / fetchers.nix
blobdc6d8f137cb38bd7edc6237effab2be213aa0e68
1 # snippets that can be shared by multiple fetchers (pkgs/build-support)
2 { lib }:
3 let
4   commonH = hashTypes: rec {
5     hashNames = [ "hash" ] ++ hashTypes;
6     hashSet = lib.genAttrs hashNames (lib.const { });
7   };
9   fakeH = {
10     hash = lib.fakeHash;
11     sha256 = lib.fakeSha256;
12     sha512 = lib.fakeSha512;
13   };
15 rec {
17   proxyImpureEnvVars = [
18     # We borrow these environment variables from the caller to allow
19     # easy proxy configuration.  This is impure, but a fixed-output
20     # derivation like fetchurl is allowed to do so since its result is
21     # by definition pure.
22     "http_proxy"
23     "https_proxy"
24     "ftp_proxy"
25     "all_proxy"
26     "no_proxy"
27     "HTTP_PROXY"
28     "HTTPS_PROXY"
29     "FTP_PROXY"
30     "ALL_PROXY"
31     "NO_PROXY"
33     # https proxies typically need to inject custom root CAs too
34     "NIX_SSL_CERT_FILE"
35   ];
37   /**
38     Converts an attrset containing one of `hash`, `sha256` or `sha512`,
39     into one containing `outputHash{,Algo}` as accepted by `mkDerivation`.
41     An appropriate “fake hash” is substituted when the hash value is `""`,
42     as is the [convention for fetchers](#sec-pkgs-fetchers-updating-source-hashes-fakehash-method).
44     All other attributes in the set remain as-is.
46     # Example
48     ```nix
49     normalizeHash { } { hash = ""; foo = "bar"; }
50     =>
51     {
52       outputHash = lib.fakeHash;
53       outputHashAlgo = null;
54       foo = "bar";
55     }
56     ```
58     ```nix
59     normalizeHash { } { sha256 = lib.fakeSha256; }
60     =>
61     {
62       outputHash = lib.fakeSha256;
63       outputHashAlgo = "sha256";
64     }
65     ```
67     ```nix
68     normalizeHash { } { sha512 = lib.fakeSha512; }
69     =>
70     {
71       outputHash = lib.fakeSha512;
72       outputHashAlgo = "sha512";
73     }
74     ```
76     # Type
77     ```
78     normalizeHash :: { hashTypes :: List String, required :: Bool } -> AttrSet -> AttrSet
79     ```
81     # Arguments
83     hashTypes
84     : the set of attribute names accepted as hash inputs, in addition to `hash`
86     required
87     : whether to throw if no hash was present in the input; otherwise returns the original input, unmodified
88   */
89   normalizeHash =
90     {
91       hashTypes ? [ "sha256" ],
92       required ? true,
93     }:
94     let
95       inherit (lib)
96         concatMapStringsSep
97         head
98         tail
99         throwIf
100         ;
101       inherit (lib.attrsets)
102         attrsToList
103         intersectAttrs
104         removeAttrs
105         optionalAttrs
106         ;
108       inherit (commonH hashTypes) hashNames hashSet;
109     in
110     args:
111     if args ? "outputHash" then
112       args
113     else
114       let
115         # The argument hash, as a {name, value} pair
116         h =
117           # All hashes passed in arguments (possibly 0 or >1) as a list of {name, value} pairs
118           let
119             hashesAsNVPairs = attrsToList (intersectAttrs hashSet args);
120           in
121           if hashesAsNVPairs == [ ] then
122             throwIf required "fetcher called without `hash`" null
123           else if tail hashesAsNVPairs != [ ] then
124             throw "fetcher called with mutually-incompatible arguments: ${
125               concatMapStringsSep ", " (a: a.name) hashesAsNVPairs
126             }"
127           else
128             head hashesAsNVPairs;
129       in
130       removeAttrs args hashNames
131       // (optionalAttrs (h != null) {
132         outputHashAlgo = if h.name == "hash" then null else h.name;
133         outputHash =
134           if h.value == "" then
135             fakeH.${h.name} or (throw "no “fake hash” defined for ${h.name}")
136           else
137             h.value;
138       });
140   /**
141     Wraps a function which accepts `outputHash{,Algo}` into one which accepts `hash` or `sha{256,512}`
143     # Example
144     ```nix
145     withNormalizedHash { hashTypes = [ "sha256" "sha512" ]; } (
146       { outputHash, outputHashAlgo, ... }:
147       ...
148     )
149     ```
150     is a function which accepts one of `hash`, `sha256`, or `sha512` (or the original's `outputHash` and `outputHashAlgo`).
152     Its `functionArgs` metadata only lists `hash` as a parameter, optional iff. `outputHash` was an optional parameter of
153     the original function.  `sha256`, `sha512`, `outputHash`, or `outputHashAlgo` are not mentioned in the `functionArgs`
154     metadata.
156     # Type
157     ```
158     withNormalizedHash :: { hashTypes :: List String } -> (AttrSet -> T) -> (AttrSet -> T)
159     ```
161     # Arguments
163     hashTypes
164     : the set of attribute names accepted as hash inputs, in addition to `hash`
165     : they must correspond to a valid value for `outputHashAlgo`, currently one of: `md5`, `sha1`, `sha256`, or `sha512`.
167     f
168     : the function to be wrapped
170     ::: {.note}
171     In nixpkgs, `mkDerivation` rejects MD5 `outputHash`es, and SHA-1 is being deprecated.
173     As such, there is no reason to add `md5` to `hashTypes`, and
174     `sha1` should only ever be included for backwards compatibility.
175     :::
177     # Output
179     `withNormalizedHash { inherit hashTypes; } f` is functionally equivalent to
180     ```nix
181     args: f (normalizeHash {
182       inherit hashTypes;
183       required = !(lib.functionArgs f).outputHash;
184     } args)
185     ```
187     However, `withNormalizedHash` preserves `functionArgs` metadata insofar as possible,
188     and is implemented somewhat more efficiently.
189   */
190   withNormalizedHash =
191     {
192       hashTypes ? [ "sha256" ],
193     }:
194     fetcher:
195     let
196       inherit (lib.attrsets) genAttrs intersectAttrs removeAttrs;
197       inherit (lib.trivial) const functionArgs setFunctionArgs;
199       inherit (commonH hashTypes) hashSet;
200       fArgs = functionArgs fetcher;
202       normalize = normalizeHash {
203         inherit hashTypes;
204         required = !fArgs.outputHash;
205       };
206     in
207     # The o.g. fetcher must *only* accept outputHash and outputHashAlgo
208     assert fArgs ? outputHash && fArgs ? outputHashAlgo;
209     assert intersectAttrs fArgs hashSet == { };
211     setFunctionArgs (args: fetcher (normalize args)) (
212       removeAttrs fArgs [
213         "outputHash"
214         "outputHashAlgo"
215       ]
216       // {
217         hash = fArgs.outputHash;
218       }
219     );