fetchurl: nixfmt-rfc-style

This commit is contained in:
Anderson Torres 2024-09-24 21:45:45 -03:00
parent a32c7a11dd
commit ce21e97a1f
4 changed files with 225 additions and 125 deletions

View File

@ -1,12 +1,15 @@
let mirrors = import ./mirrors.nix; in let
mirrors = import ./mirrors.nix;
in
{ system }: { system }:
{ url ? builtins.head urls {
, urls ? [] url ? builtins.head urls,
, sha256 ? "" urls ? [ ],
, hash ? "" sha256 ? "",
, name ? baseNameOf (toString url) hash ? "",
name ? baseNameOf (toString url),
}: }:
# assert exactly one hash is set # assert exactly one hash is set
@ -14,12 +17,18 @@ assert hash != "" || sha256 != "";
assert hash != "" -> sha256 == ""; assert hash != "" -> sha256 == "";
import <nix/fetchurl.nix> { import <nix/fetchurl.nix> {
inherit system hash sha256 name; inherit
system
hash
sha256
name
;
url = url =
# Handle mirror:// URIs. Since <nix/fetchurl.nix> currently # Handle mirror:// URIs. Since <nix/fetchurl.nix> currently
# supports only one URI, use the first listed mirror. # supports only one URI, use the first listed mirror.
let m = builtins.match "mirror://([a-z]+)/(.*)" url; in let
if m == null then url m = builtins.match "mirror://([a-z]+)/(.*)" url;
else builtins.head (mirrors.${builtins.elemAt m 0}) + (builtins.elemAt m 1); in
if m == null then url else builtins.head (mirrors.${builtins.elemAt m 0}) + (builtins.elemAt m 1);
} }

View File

@ -1,6 +1,12 @@
{ lib, buildPackages ? { inherit stdenvNoCC; }, stdenvNoCC {
, curl # Note that `curl' may be `null', in case of the native stdenvNoCC. lib,
, cacert ? null }: buildPackages ? {
inherit stdenvNoCC;
},
stdenvNoCC,
curl, # Note that `curl' may be `null', in case of the native stdenvNoCC.
cacert ? null,
}:
let let
@ -11,19 +17,23 @@ let
# fetchurl instantiations via environment variables. This makes the # fetchurl instantiations via environment variables. This makes the
# resulting store derivations (.drv files) much smaller, which in # resulting store derivations (.drv files) much smaller, which in
# turn makes nix-env/nix-instantiate faster. # turn makes nix-env/nix-instantiate faster.
mirrorsFile = mirrorsFile = buildPackages.stdenvNoCC.mkDerivation (
buildPackages.stdenvNoCC.mkDerivation ({ {
name = "mirrors-list"; name = "mirrors-list";
strictDeps = true; strictDeps = true;
builder = ./write-mirror-list.sh; builder = ./write-mirror-list.sh;
preferLocalBuild = true; preferLocalBuild = true;
} // mirrors); }
// mirrors
);
# Names of the master sites that are mirrored (i.e., "sourceforge", # Names of the master sites that are mirrored (i.e., "sourceforge",
# "gnu", etc.). # "gnu", etc.).
sites = builtins.attrNames mirrors; sites = builtins.attrNames mirrors;
impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ impureEnvVars =
lib.fetchers.proxyImpureEnvVars
++ [
# This variable allows the user to pass additional options to curl # This variable allows the user to pass additional options to curl
"NIX_CURL_FLAGS" "NIX_CURL_FLAGS"
@ -34,123 +44,169 @@ let
# This variable allows overriding the timeout for connecting to # This variable allows overriding the timeout for connecting to
# the hashed mirrors. # the hashed mirrors.
"NIX_CONNECT_TIMEOUT" "NIX_CONNECT_TIMEOUT"
] ++ (map (site: "NIX_MIRRORS_${site}") sites); ]
++ (map (site: "NIX_MIRRORS_${site}") sites);
in in
{ # URL to fetch. {
url ? "" # URL to fetch.
url ? "",
, # Alternatively, a list of URLs specifying alternative download # Alternatively, a list of URLs specifying alternative download
# locations. They are tried in order. # locations. They are tried in order.
urls ? [] urls ? [ ],
, # Additional curl options needed for the download to succeed. # Additional curl options needed for the download to succeed.
# Warning: Each space (no matter the escaping) will start a new argument. # Warning: Each space (no matter the escaping) will start a new argument.
# If you wish to pass arguments with spaces, use `curlOptsList` # If you wish to pass arguments with spaces, use `curlOptsList`
curlOpts ? "" curlOpts ? "",
, # Additional curl options needed for the download to succeed. # Additional curl options needed for the download to succeed.
curlOptsList ? [] curlOptsList ? [ ],
, # Name of the file. If empty, use the basename of `url' (or of the # Name of the file. If empty, use the basename of `url' (or of the
# first element of `urls'). # first element of `urls').
name ? "" name ? "",
# for versioned downloads optionally take pname + version. # for versioned downloads optionally take pname + version.
, pname ? "" pname ? "",
, version ? "" version ? "",
, # SRI hash. # SRI hash.
hash ? "" hash ? "",
, # Legacy ways of specifying the hash. # Legacy ways of specifying the hash.
outputHash ? "" outputHash ? "",
, outputHashAlgo ? "" outputHashAlgo ? "",
, sha1 ? "" sha1 ? "",
, sha256 ? "" sha256 ? "",
, sha512 ? "" sha512 ? "",
, recursiveHash ? false recursiveHash ? false,
, # Shell code to build a netrc file for BASIC auth # Shell code to build a netrc file for BASIC auth
netrcPhase ? null netrcPhase ? null,
, # Impure env vars (https://nixos.org/nix/manual/#sec-advanced-attributes) # Impure env vars (https://nixos.org/nix/manual/#sec-advanced-attributes)
# needed for netrcPhase # needed for netrcPhase
netrcImpureEnvVars ? [] netrcImpureEnvVars ? [ ],
, # Shell code executed after the file has been fetched # Shell code executed after the file has been fetched
# successfully. This can do things like check or transform the file. # successfully. This can do things like check or transform the file.
postFetch ? "" postFetch ? "",
, # Whether to download to a temporary path rather than $out. Useful # Whether to download to a temporary path rather than $out. Useful
# in conjunction with postFetch. The location of the temporary file # in conjunction with postFetch. The location of the temporary file
# is communicated to postFetch via $downloadedFile. # is communicated to postFetch via $downloadedFile.
downloadToTemp ? false downloadToTemp ? false,
, # If true, set executable bit on downloaded file # If true, set executable bit on downloaded file
executable ? false executable ? false,
, # If set, don't download the file, but write a list of all possible # If set, don't download the file, but write a list of all possible
# URLs (resulting from resolving mirror:// URLs) to $out. # URLs (resulting from resolving mirror:// URLs) to $out.
showURLs ? false showURLs ? false,
, # Meta information, if any. # Meta information, if any.
meta ? {} meta ? { },
# Passthru information, if any. # Passthru information, if any.
, passthru ? {} passthru ? { },
# Doing the download on a remote machine just duplicates network # Doing the download on a remote machine just duplicates network
# traffic, so don't do that by default # traffic, so don't do that by default
, preferLocalBuild ? true preferLocalBuild ? true,
# Additional packages needed as part of a fetch # Additional packages needed as part of a fetch
, nativeBuildInputs ? [ ] nativeBuildInputs ? [ ],
}: }:
let let
urls_ = urls_ =
if urls != [ ] && url == "" then if urls != [ ] && url == "" then
(if lib.isList urls then urls (if lib.isList urls then urls else throw "`urls` is not a list")
else throw "`urls` is not a list")
else if urls == [ ] && url != "" then else if urls == [ ] && url != "" then
(if lib.isString url then [url] (if lib.isString url then [ url ] else throw "`url` is not a string")
else throw "`url` is not a string") else
else throw "fetchurl requires either `url` or `urls` to be set"; throw "fetchurl requires either `url` or `urls` to be set";
hash_ = hash_ =
if with lib.lists; length (filter (s: s != "") [ hash outputHash sha1 sha256 sha512 ]) > 1 if
then throw "multiple hashes passed to fetchurl" else 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; } if hash != "" then
{
outputHashAlgo = null;
outputHash = hash;
}
else if outputHash != "" then else if outputHash != "" then
if outputHashAlgo != "" then { inherit outputHashAlgo outputHash; } if outputHashAlgo != "" then
else throw "fetchurl was passed outputHash without outputHashAlgo" { inherit outputHashAlgo outputHash; }
else if sha512 != "" then { outputHashAlgo = "sha512"; outputHash = sha512; } else
else if sha256 != "" then { outputHashAlgo = "sha256"; outputHash = sha256; } throw "fetchurl was passed outputHash without outputHashAlgo"
else if sha1 != "" then { outputHashAlgo = "sha1"; outputHash = sha1; } else if sha512 != "" then
else if cacert != null then { outputHashAlgo = "sha256"; outputHash = ""; } {
else throw "fetchurl requires a hash for fixed-output derivation: ${lib.concatStringsSep ", " urls_}"; 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 in
assert (lib.isList curlOpts) -> lib.warn '' assert
fetchurl for ${toString (builtins.head urls_)}: curlOpts is a list (${lib.generators.toPretty { multiline = false; } curlOpts}), which is not supported anymore. (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: - 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)}; 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: - 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; curlOptsList = [ ${lib.concatMapStringsSep " " lib.strings.escapeNixString curlOpts} ];'' true;
stdenvNoCC.mkDerivation (( stdenvNoCC.mkDerivation (
(
if (pname != "" && version != "") then if (pname != "" && version != "") then
{ inherit pname version; } { inherit pname version; }
else else
{ name = {
if showURLs then "urls" name =
else if name != "" then name if showURLs then
else baseNameOf (toString (builtins.head urls_)); "urls"
else if name != "" then
name
else
baseNameOf (toString (builtins.head urls_));
} }
) // { )
// {
builder = ./builder.sh; builder = ./builder.sh;
nativeBuildInputs = [ curl ] ++ nativeBuildInputs; nativeBuildInputs = [ curl ] ++ nativeBuildInputs;
@ -166,15 +222,31 @@ stdenvNoCC.mkDerivation ((
# Disable TLS verification only when we know the hash and no credentials are # Disable TLS verification only when we know the hash and no credentials are
# needed to access the resource # 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) SSL_CERT_FILE =
then "${cacert}/etc/ssl/certs/ca-bundle.crt" if
else "/no-cert-file.crt"; (
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"; outputHashMode = if (recursiveHash || executable) then "recursive" else "flat";
inherit curlOpts; inherit curlOpts;
curlOptsList = lib.escapeShellArgs curlOptsList; curlOptsList = lib.escapeShellArgs curlOptsList;
inherit showURLs mirrorsFile postFetch downloadToTemp executable; inherit
showURLs
mirrorsFile
postFetch
downloadToTemp
executable
;
impureEnvVars = impureEnvVars ++ netrcImpureEnvVars; impureEnvVars = impureEnvVars ++ netrcImpureEnvVars;
@ -182,11 +254,18 @@ stdenvNoCC.mkDerivation ((
inherit preferLocalBuild; inherit preferLocalBuild;
postHook = if netrcPhase == null then null else '' postHook =
if netrcPhase == null then
null
else
''
${netrcPhase} ${netrcPhase}
curlOpts="$curlOpts --netrc-file $PWD/netrc" curlOpts="$curlOpts --netrc-file $PWD/netrc"
''; '';
inherit meta; inherit meta;
passthru = { inherit url; } // passthru; passthru = {
}) inherit url;
} // passthru;
}
)

View File

@ -1,11 +1,23 @@
{ testers, fetchurl, jq, moreutils, ... }: { {
testers,
fetchurl,
jq,
moreutils,
...
}:
{
# Tests that we can send custom headers with spaces in them # Tests that we can send custom headers with spaces in them
header = header =
let headerValue = "Test '\" <- These are some quotes"; let
in testers.invalidateFetcherByDrvHash fetchurl { headerValue = "Test '\" <- These are some quotes";
in
testers.invalidateFetcherByDrvHash fetchurl {
url = "https://httpbin.org/headers"; url = "https://httpbin.org/headers";
sha256 = builtins.hashString "sha256" (headerValue + "\n"); sha256 = builtins.hashString "sha256" (headerValue + "\n");
curlOptsList = [ "-H" "Hello: ${headerValue}" ]; curlOptsList = [
"-H"
"Hello: ${headerValue}"
];
postFetch = '' postFetch = ''
${jq}/bin/jq -r '.headers.Hello' $out | ${moreutils}/bin/sponge $out ${jq}/bin/jq -r '.headers.Hello' $out | ${moreutils}/bin/sponge $out
''; '';