query
On this page

doRename

lib.modules.doRename

Docs pulled from | This Revision | 11 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)
      ]);
    };