at master 5.9 kB view raw
1# snippets that can be shared by multiple fetchers (pkgs/build-support) 2{ lib }: 3let 4 commonH = hashTypes: rec { 5 hashNames = [ "hash" ] ++ hashTypes; 6 hashSet = lib.genAttrs hashNames (lib.const { }); 7 }; 8 9 fakeH = { 10 hash = lib.fakeHash; 11 sha256 = lib.fakeSha256; 12 sha512 = lib.fakeSha512; 13 }; 14in 15rec { 16 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" 32 33 # https proxies typically need to inject custom root CAs too 34 "NIX_SSL_CERT_FILE" 35 ]; 36 37 /** 38 Converts an attrset containing one of `hash`, `sha256` or `sha512`, 39 into one containing `outputHash{,Algo}` as accepted by `mkDerivation`. 40 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). 43 44 All other attributes in the set remain as-is. 45 46 # Example 47 48 ```nix 49 normalizeHash { } { hash = ""; foo = "bar"; } 50 => 51 { 52 outputHash = lib.fakeHash; 53 outputHashAlgo = null; 54 foo = "bar"; 55 } 56 ``` 57 58 ```nix 59 normalizeHash { } { sha256 = lib.fakeSha256; } 60 => 61 { 62 outputHash = lib.fakeSha256; 63 outputHashAlgo = "sha256"; 64 } 65 ``` 66 67 ```nix 68 normalizeHash { } { sha512 = lib.fakeSha512; } 69 => 70 { 71 outputHash = lib.fakeSha512; 72 outputHashAlgo = "sha512"; 73 } 74 ``` 75 76 # Type 77 ``` 78 normalizeHash :: { hashTypes :: List String, required :: Bool } -> AttrSet -> AttrSet 79 ``` 80 81 # Arguments 82 83 hashTypes 84 : the set of attribute names accepted as hash inputs, in addition to `hash` 85 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 ; 107 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 }); 139 140 /** 141 Wraps a function which accepts `outputHash{,Algo}` into one which accepts `hash` or `sha{256,512}` 142 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`). 151 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. 155 156 # Type 157 ``` 158 withNormalizedHash :: { hashTypes :: List String } -> (AttrSet -> T) -> (AttrSet -> T) 159 ``` 160 161 # Arguments 162 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`. 166 167 f 168 : the function to be wrapped 169 170 ::: {.note} 171 In nixpkgs, `mkDerivation` rejects MD5 `outputHash`es, and SHA-1 is being deprecated. 172 173 As such, there is no reason to add `md5` to `hashTypes`, and 174 `sha1` should only ever be included for backwards compatibility. 175 ::: 176 177 # Output 178 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 ``` 186 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) intersectAttrs removeAttrs; 197 inherit (lib.trivial) functionArgs setFunctionArgs; 198 199 inherit (commonH hashTypes) hashSet; 200 fArgs = functionArgs fetcher; 201 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 == { }; 210 211 setFunctionArgs (args: fetcher (normalize args)) ( 212 removeAttrs fArgs [ 213 "outputHash" 214 "outputHashAlgo" 215 ] 216 // { 217 hash = fArgs.outputHash; 218 } 219 ); 220}