about summary refs log tree commit diff
path: root/pkgs/build-support/fetchurl/default.nix
blob: e4a70743334b5429ee14cd13c4548d8b8c1c1f8a (plain) (blame)
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
{
  lib,
  buildPackages ? {
    inherit stdenvNoCC;
  },
  stdenvNoCC,
  curl, # Note that `curl' may be `null', in case of the native stdenvNoCC.
  cacert ? null,
}:

let

  mirrors = import ./mirrors.nix;

  # Write the list of mirrors to a file that we can reuse between
  # fetchurl instantiations, instead of passing the mirrors to
  # fetchurl instantiations via environment variables.  This makes the
  # resulting store derivations (.drv files) much smaller, which in
  # turn makes nix-env/nix-instantiate faster.
  mirrorsFile = buildPackages.stdenvNoCC.mkDerivation (
    {
      name = "mirrors-list";
      strictDeps = true;
      builder = ./write-mirror-list.sh;
      preferLocalBuild = true;
    }
    // mirrors
  );

  # Names of the master sites that are mirrored (i.e., "sourceforge",
  # "gnu", etc.).
  sites = builtins.attrNames mirrors;

  impureEnvVars =
    lib.fetchers.proxyImpureEnvVars
    ++ [
      # This variable allows the user to pass additional options to curl
      "NIX_CURL_FLAGS"

      # This variable allows the user to override hashedMirrors from the
      # command-line.
      "NIX_HASHED_MIRRORS"

      # This variable allows overriding the timeout for connecting to
      # the hashed mirrors.
      "NIX_CONNECT_TIMEOUT"
    ]
    ++ (map (site: "NIX_MIRRORS_${site}") sites);

in

{
  # URL to fetch.
  url ? "",

  # Alternatively, a list of URLs specifying alternative download
  # locations.  They are tried in order.
  urls ? [ ],

  # Additional curl options needed for the download to succeed.
  # Warning: Each space (no matter the escaping) will start a new argument.
  # If you wish to pass arguments with spaces, use `curlOptsList`
  curlOpts ? "",

  # Additional curl options needed for the download to succeed.
  curlOptsList ? [ ],

  # Name of the file.  If empty, use the basename of `url' (or of the
  # first element of `urls').
  name ? "",

  # for versioned downloads optionally take pname + version.
  pname ? "",
  version ? "",

  # SRI hash.
  hash ? "",

  # Legacy ways of specifying the hash.
  outputHash ? "",
  outputHashAlgo ? "",
  sha1 ? "",
  sha256 ? "",
  sha512 ? "",

  recursiveHash ? false,

  # Shell code to build a netrc file for BASIC auth
  netrcPhase ? null,

  # Impure env vars (https://nixos.org/nix/manual/#sec-advanced-attributes)
  # needed for netrcPhase
  netrcImpureEnvVars ? [ ],

  # Shell code executed after the file has been fetched
  # successfully. This can do things like check or transform the file.
  postFetch ? "",

  # Whether to download to a temporary path rather than $out. Useful
  # in conjunction with postFetch. The location of the temporary file
  # is communicated to postFetch via $downloadedFile.
  downloadToTemp ? false,

  # If true, set executable bit on downloaded file
  executable ? false,

  # If set, don't download the file, but write a list of all possible
  # URLs (resulting from resolving mirror:// URLs) to $out.
  showURLs ? false,

  # Meta information, if any.
  meta ? { },

  # Passthru information, if any.
  passthru ? { },
  # Doing the download on a remote machine just duplicates network
  # traffic, so don't do that by default
  preferLocalBuild ? true,

  # Additional packages needed as part of a fetch
  nativeBuildInputs ? [ ],
}:

let
  urls_ =
    if urls != [ ] && url == "" then
      (if lib.isList urls then urls else throw "`urls` is not a list")
    else if urls == [ ] && url != "" then
      (if lib.isString url then [ url ] else throw "`url` is not a string")
    else
      throw "fetchurl requires either `url` or `urls` to be set";

  hash_ =
    if
      with lib.lists;
      length (
        filter (s: s != "") [
          hash
          outputHash
          sha1
          sha256
          sha512
        ]
      ) > 1
    then
      throw "multiple hashes passed to fetchurl"
    else

    if hash != "" then
      {
        outputHashAlgo = null;
        outputHash = hash;
      }
    else if outputHash != "" then
      if outputHashAlgo != "" then
        { inherit outputHashAlgo outputHash; }
      else
        throw "fetchurl was passed outputHash without outputHashAlgo"
    else if sha512 != "" then
      {
        outputHashAlgo = "sha512";
        outputHash = sha512;
      }
    else if sha256 != "" then
      {
        outputHashAlgo = "sha256";
        outputHash = sha256;
      }
    else if sha1 != "" then
      {
        outputHashAlgo = "sha1";
        outputHash = sha1;
      }
    else if cacert != null then
      {
        outputHashAlgo = "sha256";
        outputHash = "";
      }
    else
      throw "fetchurl requires a hash for fixed-output derivation: ${lib.concatStringsSep ", " urls_}";
in

assert
  (lib.isList curlOpts)
  -> lib.warn ''
    fetchurl for ${toString (builtins.head urls_)}: curlOpts is a list (${
      lib.generators.toPretty { multiline = false; } curlOpts
    }), which is not supported anymore.
    - If you wish to get the same effect as before, for elements with spaces (even if escaped) to expand to multiple curl arguments, use a string argument instead:
      curlOpts = ${lib.strings.escapeNixString (toString curlOpts)};
    - If you wish for each list element to be passed as a separate curl argument, allowing arguments to contain spaces, use curlOptsList instead:
      curlOptsList = [ ${lib.concatMapStringsSep " " lib.strings.escapeNixString curlOpts} ];'' true;

stdenvNoCC.mkDerivation (
  (
    if (pname != "" && version != "") then
      { inherit pname version; }
    else
      {
        name =
          if showURLs then
            "urls"
          else if name != "" then
            name
          else
            baseNameOf (toString (builtins.head urls_));
      }
  )
  // {
    builder = ./builder.sh;

    nativeBuildInputs = [ curl ] ++ nativeBuildInputs;

    urls = urls_;

    # If set, prefer the content-addressable mirrors
    # (http://tarballs.nixos.org) over the original URLs.
    preferHashedMirrors = true;

    # New-style output content requirements.
    inherit (hash_) outputHashAlgo outputHash;

    # Disable TLS verification only when we know the hash and no credentials are
    # needed to access the resource
    SSL_CERT_FILE =
      if
        (
          hash_.outputHash == ""
          || hash_.outputHash == lib.fakeSha256
          || hash_.outputHash == lib.fakeSha512
          || hash_.outputHash == lib.fakeHash
          || netrcPhase != null
        )
      then
        "${cacert}/etc/ssl/certs/ca-bundle.crt"
      else
        "/no-cert-file.crt";

    outputHashMode = if (recursiveHash || executable) then "recursive" else "flat";

    inherit curlOpts;
    curlOptsList = lib.escapeShellArgs curlOptsList;
    inherit
      showURLs
      mirrorsFile
      postFetch
      downloadToTemp
      executable
      ;

    impureEnvVars = impureEnvVars ++ netrcImpureEnvVars;

    nixpkgsVersion = lib.trivial.release;

    inherit preferLocalBuild;

    postHook =
      if netrcPhase == null then
        null
      else
        ''
          ${netrcPhase}
          curlOpts="$curlOpts --netrc-file $PWD/netrc"
        '';

    inherit meta;
    passthru = {
      inherit url;
    } // passthru;
  }
)