summary refs log tree commit diff
diff options
context:
space:
mode:
authorCharles Strahan <charles@cstrahan.com>2016-10-26 14:01:13 -0400
committerGitHub <noreply@github.com>2016-10-26 14:01:13 -0400
commitca2b03439f31dca0beee0d9b492dd18db78315cd (patch)
tree0e3a3830d1b797735f786c6ffce9c4e6ebe397e5
parent6f1f1d86c1f6a82b44099d744cc52d150321e07e (diff)
parent3ca3b145ead9ce528b6b8cbf4db8e2a73a26bbe7 (diff)
downloadnixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.tar
nixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.tar.gz
nixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.tar.bz2
nixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.tar.lz
nixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.tar.xz
nixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.tar.zst
nixlib-ca2b03439f31dca0beee0d9b492dd18db78315cd.zip
Merge pull request #19496 from Ericson2314/overridePackages
Make `overridePackages` extend rather than replace existing overrides
-rw-r--r--doc/functions.xml14
-rw-r--r--lib/trivial.nix8
-rw-r--r--pkgs/top-level/all-packages.nix14
-rw-r--r--pkgs/top-level/default.nix111
4 files changed, 80 insertions, 67 deletions
diff --git a/doc/functions.xml b/doc/functions.xml
index 908e9571ed69..e767d01d8431 100644
--- a/doc/functions.xml
+++ b/doc/functions.xml
@@ -52,6 +52,20 @@ in ...</programlisting>
     It's equivalent to <varname>pkgs</varname> in the above example.
   </para>
 
+  <para>
+    Note that in previous versions of nixpkgs, this method replaced any changes from <link 
+    linkend="sec-modify-via-packageOverrides">config.packageOverrides</link>,
+    along with that from previous calls if this function was called repeatedly.
+    Now those previous changes will be preserved so this function can be "chained" meaningfully.
+    To recover the old behavior, make sure <varname>config.packageOverrides<varname> is unset,
+    and call this only once off a "freshly" imported nixpkgs:
+
+    <programlisting>let
+  pkgs = import &lt;nixpkgs&gt; { config: {}; };
+  newpkgs = pkgs.overridePackages ...;
+in ...</programlisting>
+  </para>
+
 </section>
 
 <section xml:id="sec-pkg-override">
diff --git a/lib/trivial.nix b/lib/trivial.nix
index dac8b8d0106d..39cbd67fba36 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -69,9 +69,13 @@ rec {
   #
   #     nix-repl> obj
   #     { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
-  makeExtensible = rattrs:
+  makeExtensible = makeExtensibleWithCustomName "extend";
+
+  # Same as `makeExtensible` but the name of the extending attribute is
+  # customized.
+  makeExtensibleWithCustomName = extenderName: rattrs:
     fix' rattrs // {
-      extend = f: makeExtensible (extends f rattrs);
+      ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
    };
 
   # Flip the order of the arguments of a binary function.
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index abd76cf4a51b..61eb393552b6 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -6,7 +6,6 @@
  * Hint: ### starts category names.
  */
 { system, bootStdenv, noSysDirs, config, crossSystem, platform, lib
-, pkgsWithOverrides
 , ... }:
 self: pkgs:
 
@@ -35,19 +34,6 @@ in
 
   newScope = extra: lib.callPackageWith (defaultScope // extra);
 
-  # Easily override this package set.
-  # Warning: this function is very expensive and must not be used
-  # from within the nixpkgs repository.
-  #
-  # Example:
-  #  pkgs.overridePackages (self: super: {
-  #    foo = super.foo.override { ... };
-  #  }
-  #
-  # The result is `pkgs' where all the derivations depending on `foo'
-  # will use the new version.
-  overridePackages = f: pkgsWithOverrides f;
-
   # Override system. This is useful to build i686 packages on x86_64-linux.
   forceSystem = system: kernel: (import ../..) {
     inherit system;
diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix
index 2eb7fb34b4d2..c54b23853c5d 100644
--- a/pkgs/top-level/default.nix
+++ b/pkgs/top-level/default.nix
@@ -61,6 +61,35 @@ let
     inherit system bootStdenv noSysDirs config crossSystem platform lib;
   };
 
+  stdenvAdapters = self: super:
+    let res = import ../stdenv/adapters.nix self; in res // {
+      stdenvAdapters = res;
+    };
+
+  trivialBuilders = self: super:
+    (import ../build-support/trivial-builders.nix {
+      inherit lib; inherit (self) stdenv stdenvNoCC; inherit (self.xorg) lndir;
+    });
+
+  stdenvDefault = self: super: (import ./stdenv.nix topLevelArguments) {} pkgs;
+
+  allPackages = self: super:
+    let res = import ./all-packages.nix topLevelArguments res self;
+    in res;
+
+  aliases = self: super: import ./aliases.nix super;
+
+  # stdenvOverrides is used to avoid circular dependencies for building
+  # the standard build environment. This mechanism uses the override
+  # mechanism to implement some staged compilation of the stdenv.
+  #
+  # We don't want stdenv overrides in the case of cross-building, or
+  # otherwise the basic overridden packages will not be built with the
+  # crossStdenv adapter.
+  stdenvOverrides = self: super:
+    lib.optionalAttrs (crossSystem == null && super.stdenv ? overrides)
+      (super.stdenv.overrides super);
+
   # Allow packages to be overridden globally via the `packageOverrides'
   # configuration option, which must be a function that takes `pkgs'
   # as an argument and returns a set of new or overridden packages.
@@ -68,54 +97,34 @@ let
   # (un-overridden) set of packages, allowing packageOverrides
   # attributes to refer to the original attributes (e.g. "foo =
   # ... pkgs.foo ...").
-  pkgs = pkgsWithOverrides (self: config.packageOverrides or (super: {}));
-
-  # Return the complete set of packages, after applying the overrides
-  # returned by the `overrider' function (see above).  Warning: this
-  # function is very expensive!
-  pkgsWithOverrides = overrider:
-    let
-      stdenvAdapters = self: super:
-        let res = import ../stdenv/adapters.nix self; in res // {
-          stdenvAdapters = res;
-        };
-
-      trivialBuilders = self: super:
-        (import ../build-support/trivial-builders.nix {
-          inherit lib; inherit (self) stdenv stdenvNoCC; inherit (self.xorg) lndir;
-        });
-
-      stdenvDefault = self: super: (import ./stdenv.nix topLevelArguments) {} pkgs;
-
-      allPackagesArgs = topLevelArguments // { inherit pkgsWithOverrides; };
-      allPackages = self: super:
-        let res = import ./all-packages.nix allPackagesArgs res self;
-        in res;
-
-      aliases = self: super: import ./aliases.nix super;
-
-      # stdenvOverrides is used to avoid circular dependencies for building
-      # the standard build environment. This mechanism uses the override
-      # mechanism to implement some staged compilation of the stdenv.
-      #
-      # We don't want stdenv overrides in the case of cross-building, or
-      # otherwise the basic overridden packages will not be built with the
-      # crossStdenv adapter.
-      stdenvOverrides = self: super:
-        lib.optionalAttrs (crossSystem == null && super.stdenv ? overrides)
-          (super.stdenv.overrides super);
-
-      customOverrides = self: super:
-        lib.optionalAttrs (bootStdenv == null) (overrider self super);
-    in
-      lib.fix' (
-        lib.extends customOverrides (
-          lib.extends stdenvOverrides (
-            lib.extends aliases (
-              lib.extends allPackages (
-                lib.extends stdenvDefault (
-                  lib.extends trivialBuilders (
-                    lib.extends stdenvAdapters (
-                      self: {}))))))));
-in
-  pkgs
+  configOverrides = self: super:
+    lib.optionalAttrs (bootStdenv == null)
+      ((config.packageOverrides or (super: {})) super);
+
+  # The complete chain of package set builders, applied from top to bottom
+  toFix = lib.foldl' (lib.flip lib.extends) (self: {}) [
+    stdenvAdapters
+    trivialBuilders
+    stdenvDefault
+    allPackages
+    aliases
+    stdenvOverrides
+    configOverrides
+  ];
+
+  # Use `overridePackages` to easily override this package set.
+  # Warning: this function is very expensive and must not be used
+  # from within the nixpkgs repository.
+  #
+  # Example:
+  #  pkgs.overridePackages (self: super: {
+  #    foo = super.foo.override { ... };
+  #  }
+  #
+  # The result is `pkgs' where all the derivations depending on `foo'
+  # will use the new version.
+
+  # Return the complete set of packages. Warning: this function is very
+  # expensive!
+  pkgs = lib.makeExtensibleWithCustomName "overridePackages" toFix;
+in pkgs