From 731e0fa7423ae34cf25bf967c90228ec7ea99e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benno=20F=C3=BCnfst=C3=BCck?= <benno.fuenfstueck@gmail.com> Date: Wed, 19 Aug 2015 11:23:28 +0200 Subject: [PATCH] haskell: preserve overrideScope on override We want code such as `(pkg.override {}).overrideScope (self: super: {})` to work. This didn't work before, since `override` will call the original package again, and the attribute `overideScope`, which `callPackageWithScope` added, wasn't added again. The fix for this is to modify the package function itself to include the `callPackageWithScope` attribute, so it'll be re-added whenever the function is overriden for with arguments. There is a small problem here though: since callPackage uses some magic (`builtins.functionArgs`) to determine the auto-arguments of a function, we can't just write `callPackageWith scope drvScope`, since `builtins.functionArgs drvScope` will be `{}`. To fix this, we implement our own `callPackageWith`. Fixes https://github.com/NixOS/nixpkgs/issues/7953. Closes https://github.com/NixOS/nixpkgs/pull/9336. --- .../haskell-modules/make-package-set.nix | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pkgs/development/haskell-modules/make-package-set.nix b/pkgs/development/haskell-modules/make-package-set.nix index 29b294619e6d..ee584b3c2ecb 100644 --- a/pkgs/development/haskell-modules/make-package-set.nix +++ b/pkgs/development/haskell-modules/make-package-set.nix @@ -44,9 +44,23 @@ self: let mkDerivation = makeOverridable mkDerivationImpl; - callPackageWithScope = scope: drv: args: (stdenv.lib.callPackageWith scope drv args) // { - overrideScope = f: callPackageWithScope (mkScope (fix' (extends f scope.__unfix__))) drv args; - }; + callPackageWithScope = scope: fn: manualArgs: + let + # this code is copied from callPackage in lib/customisation.nix + # + # we cannot use `callPackage` here because we want to call `makeOverridable` + # on `drvScope` (we cannot add `overrideScope` after calling `callPackage` because then it is + # lost on `.override`) but determine the auto-args based on `drv` (the problem here + # is that nix has no way to "passthrough" args while preserving the reflection + # info that callPackage uses to determine the arguments). + drv = if builtins.isFunction fn then fn else import fn; + auto = builtins.intersectAttrs (builtins.functionArgs drv) scope; + drvScope = allArgs: drv allArgs // { + overrideScope = f: + let newScope = mkScope (fix' (extends f scope.__unfix__)); + in callPackageWithScope newScope drv manualArgs; + }; + in stdenv.lib.makeOverridable drvScope (auto // manualArgs); mkScope = scope: pkgs // pkgs.xorg // pkgs.gnome2 // scope; defaultScope = mkScope self;