query
On this page

doRename

lib.modules.doRename

Docs pulled from | This Revision | 10 minutes ago


Return a module that help declares an option that has been renamed. When a value is defined for the old option, it is forwarded to the to option.


Noogle detected

Aliases

Implementation

The following is the current implementation of this function.

doRename =
    {
      # List of strings representing the attribute path of the old option.
      from,
      # List of strings representing the attribute path of the new option.
      to,
      # Boolean, whether the old option is to be included in documentation.
      visible,
      # Whether to warn when a value is defined for the old option.
      # NOTE: This requires the NixOS assertions module to be imported, so
      #        - this generally does not work in submodules
      #        - this may or may not work outside NixOS
      warn,
      # A function that is applied to the option value, to form the value
      # of the old `from` option.
      #
      # For example, the identity function can be passed, to return the option value unchanged.
      # ```nix
      # use = x: x;
      # ```
      #
      # To add a warning, you can pass the partially applied `warn` function.
      # ```nix
      # use = lib.warn "Obsolete option `${opt.old}' is used. Use `${opt.to}' instead.";
      # ```
      use,
      # Legacy option, enabled by default: whether to preserve the priority of definitions in `old`.
      withPriority ? true,
      # A boolean that defines the `mkIf` condition for `to`.
      # If the condition evaluates to `true`, and the `to` path points into an
      # `attrsOf (submodule ...)`, then `doRename` would cause an empty module to
      # be created, even if the `from` option is undefined.
      # By setting this to an expression that may return `false`, you can inhibit
      # this undesired behavior.
      #
      # Example:
      #
      # ```nix
      # { config, lib, ... }:
      # let
      #   inherit (lib) mkOption mkEnableOption types doRename;
      # in
      # {
      #   options = {
      #
      #     # Old service
      #     services.foo.enable = mkEnableOption "foo";
      #
      #     # New multi-instance service
      #     services.foos = mkOption {
      #       type = types.attrsOf (types.submodule …);
      #     };
      #   };
      #   imports = [
      #     (doRename {
      #       from = [ "services" "foo" "bar" ];
      #       to = [ "services" "foos" "" "bar" ];
      #       visible = true;
      #       warn = false;
      #       use = x: x;
      #       withPriority = true;
      #       # Only define services.foos."" if needed. (It's not just about `bar`)
      #       condition = config.services.foo.enable;
      #     })
      #   ];
      # }
      # ```
      condition ? true,
    }:
    { config, options, ... }:
    let
      fromOpt = getAttrFromPath from options;
      toOf = attrByPath to (abort "Renaming error: option `${showOption to}' does not exist.");
      toType =
        let
          opt = attrByPath to { } options;
        in
        opt.type or (types.submodule { });
    in
    {
      options = setAttrByPath from (
        mkOption {
          inherit visible;
          description = "Alias of {option}`${showOption to}`.";
          apply = x: use (toOf config);
        }
        // optionalAttrs (toType != null) {
          type = toType;
        }
      );
      config = mkIf condition (mkMerge [
        (optionalAttrs (options ? warnings) {
          warnings =
            optional (warn && fromOpt.isDefined)
              "The option `${showOption from}' defined in ${showFiles fromOpt.files} has been renamed to `${showOption to}'.";
        })
        (
          if withPriority then
            mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt
          else
            mkAliasAndWrapDefinitions (setAttrByPath to) fromOpt
        )
      ]);
    };