summary refs log tree commit diff
path: root/lib/modules.nix
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-10-14 18:05:50 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-10-14 18:18:47 +0200
commit5f077e229625583072ebf63ea48b11170771b0ed (patch)
treefcd1a6ee296febd5d0ba956dcff2f0176c9661b0 /lib/modules.nix
parent7b001ed68a6cc0dd4c2982fdf72c9c26d0595eee (diff)
downloadnixlib-5f077e229625583072ebf63ea48b11170771b0ed.tar
nixlib-5f077e229625583072ebf63ea48b11170771b0ed.tar.gz
nixlib-5f077e229625583072ebf63ea48b11170771b0ed.tar.bz2
nixlib-5f077e229625583072ebf63ea48b11170771b0ed.tar.lz
nixlib-5f077e229625583072ebf63ea48b11170771b0ed.tar.xz
nixlib-5f077e229625583072ebf63ea48b11170771b0ed.tar.zst
nixlib-5f077e229625583072ebf63ea48b11170771b0ed.zip
Factor out option renaming
Option aliases/deprecations can now be declared in any NixOS module,
not just in nixos/modules/rename.nix. This is more modular (since it
allows for example grub-related aliases to be declared in the grub
module), and allows aliases outside of NixOS (e.g. in NixOps modules).

The syntax is a bit funky. Ideally we'd have something like:

  options = {
    foo.bar.newOption = mkOption { ... };
    foo.bar.oldOption = mkAliasOption [ "foo" "bar" "newOption" ];
  };

but that's not possible because options cannot define values in
*other* options - you need to have a "config" for that. So instead we
have functions that return a *module*: mkRemovedOptionModule,
mkRenamedOptionModule and mkAliasOptionModule. These can be used via
"imports", e.g.

  imports = [
    (mkAliasOptionModule [ "foo" "bar" "oldOption" ] [ "foo" "bar" "newOption" ]);
  ];

As an added bonus, deprecation warnings now show the file name of the
offending module.

Fixes #10385.
Diffstat (limited to 'lib/modules.nix')
-rw-r--r--lib/modules.nix65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/modules.nix b/lib/modules.nix
index 3e4d0547ecc5..12ec7004d1ee 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -469,6 +469,7 @@ rec {
   mkBefore = mkOrder 500;
   mkAfter = mkOrder 1500;
 
+
   # Convenient property used to transfer all definitions and their
   # properties from one option to another. This property is useful for
   # renaming options, and also for including properties from another module
@@ -498,4 +499,68 @@ rec {
   /* Compatibility. */
   fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
 
+
+  /* Return a module that causes a warning to be shown if the
+     specified option is defined. For example,
+
+       mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ]
+
+     causes a warning if the user defines boot.loader.grub.bootDevice.
+  */
+  mkRemovedOptionModule = optionName:
+    { options, ... }:
+    { options = setAttrByPath optionName (mkOption {
+        visible = false;
+      });
+      config.warnings =
+        let opt = getAttrFromPath optionName options; in
+        optional opt.isDefined
+          "The option definition `${showOption optionName}' in ${showFiles opt.files} no longer has any effect; please remove it.";
+    };
+
+  /* Return a module that causes a warning to be shown if the
+     specified "from" option is defined; the defined value is however
+     forwarded to the "to" option. This can be used to rename options
+     while providing backward compatibility. For example,
+
+       mkRenamedOptionModule [ "boot" "copyKernels" ] [ "boot" "loader" "grub" "copyKernels" ]
+
+     forwards any definitions of boot.copyKernels to
+     boot.loader.grub.copyKernels while printing a warning.
+  */
+  mkRenamedOptionModule = from: to: doRename {
+    inherit from to;
+    visible = false;
+    warn = true;
+    use = builtins.trace "Obsolete option `${showOption from}' is used. It was renamed to `${showOption to}'.";
+  };
+
+  /* Like ‘mkRenamedOptionModule’, but doesn't show a warning. */
+  mkAliasOptionModule = from: to: doRename {
+    inherit from to;
+    visible = true;
+    warn = false;
+    use = id;
+  };
+
+  doRename = { from, to, visible, warn, use }:
+    let
+      toOf = attrByPath to
+        (abort "Renaming error: option `${showOption to}' does not exists.");
+    in
+      { config, options, ... }:
+      { options = setAttrByPath from (mkOption {
+          description = "Alias of <option>${showOption to}</option>.";
+          apply = x: use (toOf config);
+        });
+        config = {
+        /*
+          warnings =
+            let opt = getAttrFromPath from options; in
+            optional (warn && opt.isDefined)
+              "The option `${showOption from}' defined in ${showFiles opt.files} has been renamed to `${showOption to}'.";
+              */
+        } // setAttrByPath to (mkAliasDefinitions (getAttrFromPath from options));
+      };
+
 }