diff --git a/doc/release-notes/rl-2511.section.md b/doc/release-notes/rl-2511.section.md index f739ba9cd1f5..02b08039812b 100644 --- a/doc/release-notes/rl-2511.section.md +++ b/doc/release-notes/rl-2511.section.md @@ -21,7 +21,7 @@ -- Create the first release note entry in this section! +- Added `rewriteURL` attribute to the nixpkgs `config`, to allow for rewriting the URLs downloaded by `fetchurl`. ## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib} diff --git a/pkgs/build-support/fetchurl/boot.nix b/pkgs/build-support/fetchurl/boot.nix index 4aa76094a843..a950b9983329 100644 --- a/pkgs/build-support/fetchurl/boot.nix +++ b/pkgs/build-support/fetchurl/boot.nix @@ -2,7 +2,10 @@ let mirrors = import ./mirrors.nix; in -{ system }: +{ + rewriteURL, + system, +}: { url ? builtins.head urls, @@ -28,7 +31,15 @@ import { # Handle mirror:// URIs. Since currently # supports only one URI, use the first listed mirror. let - m = builtins.match "mirror://([a-z]+)/(.*)" url; + url_ = + let + u = rewriteURL url; + in + if builtins.isString u then + u + else + throw "rewriteURL deleted the only URL passed to fetchurlBoot (was ${url})"; + m = builtins.match "mirror://([a-z]+)/(.*)" url_; in - if m == null then url else builtins.head (mirrors.${builtins.elemAt m 0}) + (builtins.elemAt m 1); + if m == null then url_ else builtins.head (mirrors.${builtins.elemAt m 0}) + (builtins.elemAt m 1); } diff --git a/pkgs/build-support/fetchurl/default.nix b/pkgs/build-support/fetchurl/default.nix index c0e53ba637a7..f948b9ee88aa 100644 --- a/pkgs/build-support/fetchurl/default.nix +++ b/pkgs/build-support/fetchurl/default.nix @@ -6,6 +6,7 @@ stdenvNoCC, curl, # Note that `curl' may be `null', in case of the native stdenvNoCC. cacert ? null, + rewriteURL, }: let @@ -122,7 +123,7 @@ in }@args: let - urls_ = + preRewriteUrls = if urls != [ ] && url == "" then ( if lib.isList urls then urls else throw "`urls` is not a list: ${lib.generators.toPretty { } urls}" @@ -137,6 +138,12 @@ let else throw "fetchurl requires either `url` or `urls` to be set: ${lib.generators.toPretty { } args}"; + urls_ = + let + u = lib.lists.filter (url: lib.isString url) (map rewriteURL preRewriteUrls); + in + if u == [ ] then throw "urls is empty after rewriteURL (was ${toString preRewriteUrls})" else u; + hash_ = if with lib.lists; diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 49f0ff040a41..df95cb979fb3 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -181,6 +181,7 @@ let inherit lib; stdenvNoCC = prevStage.ccWrapperStdenv or thisStdenv; curl = bootstrapTools; + inherit (config) rewriteURL; }; inherit cc; diff --git a/pkgs/stdenv/freebsd/default.nix b/pkgs/stdenv/freebsd/default.nix index c0a6f7e8ea08..f2cb2e5e0b29 100644 --- a/pkgs/stdenv/freebsd/default.nix +++ b/pkgs/stdenv/freebsd/default.nix @@ -399,6 +399,7 @@ let fetchurlBoot = import ../../build-support/fetchurl { inherit lib stdenvNoCC; inherit (prevStage) curl; + inherit (config) rewriteURL; }; stdenv = import ../generic { inherit diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 7682419db9d6..d30cc08eac6a 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -190,6 +190,7 @@ let fetchurlBoot = import ../../build-support/fetchurl/boot.nix { inherit system; + inherit (config) rewriteURL; }; cc = diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 0b6a97087eba..83cb0c442f3b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -626,6 +626,7 @@ with pkgs; makeOverridable (import ../build-support/fetchurl) { inherit lib stdenvNoCC buildPackages; inherit cacert; + inherit (config) rewriteURL; curl = buildPackages.curlMinimal.override (old: rec { # break dependency cycles fetchurl = stdenv.fetchurlBoot; diff --git a/pkgs/top-level/config.nix b/pkgs/top-level/config.nix index 4f6ae95b23f6..840c4e03e92d 100644 --- a/pkgs/top-level/config.nix +++ b/pkgs/top-level/config.nix @@ -211,6 +211,27 @@ let Whether to check that the `meta` attribute of derivations are correct during evaluation time. ''; }; + + rewriteURL = mkOption { + type = types.functionTo (types.nullOr types.str); + description = '' + A hook to rewrite/filter URLs before they are fetched. + + The function is passed the URL as a string, and is expected to return a new URL, or null if the given URL should not be attempted. + + This function is applied _prior_ to resolving mirror:// URLs. + + The intended use is to allow URL rewriting to insert company-internal mirrors, or work around company firewalls and similar network restrictions. + ''; + default = lib.id; + defaultText = literalExpression "(url: url)"; + example = literalExpression '' + { + # Use Nix like it's 2024! ;-) + rewriteURL = url: "https://web.archive.org/web/2024/''${url}"; + } + ''; + }; }; in