Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion doc/build-helpers/fetchers.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ If `pname` and `version` are specified, `fetchurl` will use those values and wil

: The same `url` attribute passed in the argument to `fetchurl`.

`unpacked` (Derivation)

: A convenience derivation for quick access to downloaded archives, as unpacked by the standard [`unpackPhase`](#ssec-unpack-phase) in [`stdenv`](#chap-stdenv).
If `recursiveHash` is set to `true` then this output will avoid unnecessary builds and reference the `fetchurl` result directly.

This attribute can be quickly built with e.g. `nix-build . -A hello.src.unpacked`.
Internally it makes use of `pkgs.srcOnly`, but it will not apply any patches since it is not aware of any.

Using this will push duplicate data to the store.
As such it will raise a warning on instantiation, primarily to disallow use within Nixpkgs.

### Examples {#ssec-pkgs-fetchers-fetchurl-examples}

:::{.example #ex-fetchers-fetchurl-nixpkgs-version}
Expand Down Expand Up @@ -928,4 +939,3 @@ fetchtorrent {

- `config`: When using `transmission` as the `backend`, a json configuration can
be supplied to transmission. Refer to the [upstream documentation](https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md) for information on how to configure.

7 changes: 5 additions & 2 deletions pkgs/build-support/fetchgit/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ lib.makeOverridable (
throw
"Please provide directories/patterns for sparse checkout as a list of strings. Passing a (multi-line) string is not supported any more."
else
stdenvNoCC.mkDerivation {
stdenvNoCC.mkDerivation (finalAttrs: {
name = if name != null then name else urlToName url revWithTag;

builder = ./builder.sh;
Expand Down Expand Up @@ -160,7 +160,10 @@ lib.makeOverridable (
passthru = {
gitRepoUrl = url;
inherit tag;
unpacked = lib.removeAttrs finalAttrs.finalPackage [ "unpacked" ] // {
passthru = removeAttrs finalAttrs.finalPackage.passthru [ "unpacked" ];
};
};
}
})
)
)
10 changes: 8 additions & 2 deletions pkgs/build-support/fetchhg/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if hash != null && sha256 != null then
throw "Only one of sha256 or hash can be set"
else
# TODO: statically check if mercurial as the https support if the url starts with https.
stdenvNoCC.mkDerivation {
stdenvNoCC.mkDerivation (finalAttrs: {
name = "hg-archive" + (lib.optionalString (name != null) "-${name}");
builder = ./builder.sh;
nativeBuildInputs = [ mercurial ];
Expand All @@ -38,4 +38,10 @@ else

inherit url rev;
inherit preferLocalBuild;
}

passthru = {
unpacked = lib.removeAttrs finalAttrs.finalPackage [ "unpacked" ] // {
passthru = removeAttrs finalAttrs.finalPackage.passthru [ "unpacked" ];
};
};
})
10 changes: 8 additions & 2 deletions pkgs/build-support/fetchsvn/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ in
if hash != "" && sha256 != "" then
throw "Only one of sha256 or hash can be set"
else
stdenvNoCC.mkDerivation {
stdenvNoCC.mkDerivation (finalAttrs: {
name = name_;
builder = ./builder.sh;
nativeBuildInputs = [
Expand Down Expand Up @@ -82,4 +82,10 @@ else

impureEnvVars = lib.fetchers.proxyImpureEnvVars;
inherit preferLocalBuild;
}

passthru = {
unpacked = lib.removeAttrs finalAttrs.finalPackage [ "unpacked" ] // {
passthru = removeAttrs finalAttrs.finalPackage.passthru [ "unpacked" ];
};
};
})
56 changes: 56 additions & 0 deletions pkgs/build-support/fetchurl/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
},
stdenvNoCC,
curl, # Note that `curl' may be `null', in case of the native stdenvNoCC.
srcOnly ? null,
cacert ? null,
}:

Expand Down Expand Up @@ -199,6 +200,9 @@ assert
curlOptsList = [ ${lib.concatMapStringsSep " " lib.strings.escapeNixString curlOpts} ];'' true;

stdenvNoCC.mkDerivation (
# This is only for access to '_finalAttrs.finalPackage', please
# avoid referencing '_finalAttrs' for treewide eval performance reasons
_finalAttrs:
(
if (pname != "" && version != "") then
{ inherit pname version; }
Expand Down Expand Up @@ -273,6 +277,58 @@ stdenvNoCC.mkDerivation (
inherit meta;
passthru = {
inherit url;
/**
A convenience derivation for quick access to downloaded
archives, as unpacked by the standard `unpackPhase` in `stdenv`.
If `recursiveHash` is set to `true` then this output will avoid
unnecessary builds and reference the `fetchurl` result directly.

This attribute can be quickly built with e.g. `nix-build . -A hello.src.unpacked`.
Internally it makes use of `pkgs.srcOnly`, but it will not apply any patches
since it is not aware of any.

Using this will push duplicate data to the store.
As such it will raise a warning on instantiation, primarily to disallow use within Nixpkgs.

# Examples

```shell
$ nix-build . -A hello.src.unpacked
trace: evaluation warning: Avoid using `(fetchurl {...}).unpacked` in derivations as it will push duplicate data to the store and any cache.
this derivation will be built:
/nix/store/00b1nzgl2pdnxxardrbxv3349xvhcvz3-hello-2.12.1.tar.gz-unpacked-source.drv
building '/nix/store/00b1nzgl2pdnxxardrbxv3349xvhcvz3-hello-2.12.1.tar.gz-unpacked-source.drv'
Running phase: unpackPhase
unpacking source archive /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz
source root is hello-2.12.1
setting SOURCE_DATE_EPOCH to timestamp 1653865426 of file "hello-2.12.1/ChangeLog"
$ head -n2 result/README
This is the README file for the GNU Hello distribution.
Hello prints a friendly greeting. It also serves as a sample GNU
```
*/
unpacked =
lib.warnOnInstantiate
"Avoid using `(fetchurl {...}).unpacked` in derivations as it will push duplicate data to the store and any cache."
(
if srcOnly == null then
null # early on bootstrap, not needed
Comment on lines +314 to +315
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I would have expected this wouldn't have been added to the attrset in this case, rather than added with a null value.

Copy link
Member Author

@pbsds pbsds Jun 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured having src ? unpacked and attrNames src being consistent to be a good thing, but on a second thought we could instead either avoid adding unpacked or turning the null into a descriptive throw/raise

else if recursiveHash then
lib.removeAttrs _finalAttrs.finalPackage [ "unpacked" ]
// {
passthru = removeAttrs _finalAttrs.finalPackage.passthru [ "unpacked" ];
}
else
srcOnly {
name = "${_finalAttrs.finalPackage.name}-unpacked";
src = _finalAttrs.finalPackage;
stdenv = stdenvNoCC;
inherit preferLocalBuild;
passthru = {
inherit url;
} // passthru;
}
);
} // passthru;
}
)
1 change: 1 addition & 0 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ with pkgs;
makeOverridable (import ../build-support/fetchurl) {
inherit lib stdenvNoCC buildPackages;
inherit cacert;
inherit srcOnly;
curl = buildPackages.curlMinimal.override (old: rec {
# break dependency cycles
fetchurl = stdenv.fetchurlBoot;
Expand Down