diff --git a/modules/misc/xdg-user-dirs.nix b/modules/misc/xdg-user-dirs.nix index e3d3db5449ef..7cfcbb662246 100644 --- a/modules/misc/xdg-user-dirs.nix +++ b/modules/misc/xdg-user-dirs.nix @@ -36,6 +36,8 @@ in ''; }; + package = lib.mkPackageOption pkgs "xdg-user-dirs" { nullable = true; }; + # Well-known directory list from # https://gitlab.freedesktop.org/xdg/xdg-user-dirs/blob/master/man/user-dirs.dirs.xml @@ -101,45 +103,76 @@ in defaultText = literalExpression "{ }"; example = literalExpression '' { - XDG_MISC_DIR = "''${config.home.homeDirectory}/Misc"; + MISC = "''${config.home.homeDirectory}/Misc"; } ''; - description = "Other user directories."; + description = '' + Other user directories. + + Prior to 25.11, these should be named like `XDG_MISC_DIR`. + ''; }; createDirectories = lib.mkEnableOption "automatic creation of the XDG user directories"; + + setSessionVariables = mkOption { + type = with types; bool; + default = lib.versionOlder config.home.stateVersion "25.11"; + defaultText = literalExpression '' + lib.versionOlder config.home.stateVersion "25.11" + ''; + description = '' + Whether to set the XDG user dir environment variables, like + `XDG_DESKTOP_DIR`. The recommended way to get these values is via the + `xdg-user-dir` command or by processing + `$XDG_CONFIG_HOME/user-dirs.dirs` directly in your application. + + This defaults to `true` for state version < 25.11 and `false` otherwise. + ''; + }; }; config = let directories = (lib.filterAttrs (n: v: !isNull v) { - XDG_DESKTOP_DIR = cfg.desktop; - XDG_DOCUMENTS_DIR = cfg.documents; - XDG_DOWNLOAD_DIR = cfg.download; - XDG_MUSIC_DIR = cfg.music; - XDG_PICTURES_DIR = cfg.pictures; - XDG_PUBLICSHARE_DIR = cfg.publicShare; - XDG_TEMPLATES_DIR = cfg.templates; - XDG_VIDEOS_DIR = cfg.videos; + DESKTOP = cfg.desktop; + DOCUMENTS = cfg.documents; + DOWNLOAD = cfg.download; + MUSIC = cfg.music; + PICTURES = cfg.pictures; + PUBLICSHARE = cfg.publicShare; + TEMPLATES = cfg.templates; + VIDEOS = cfg.videos; }) - // cfg.extraConfig; + // ( + if lib.versionOlder config.home.stateVersion "25.11" then + lib.mapAttrs' ( + k: + let + name = lib.match "XDG_(.*)_DIR" k; + in + lib.nameValuePair (if name == null then k else lib.elemAt name 0) + ) cfg.extraConfig + else + cfg.extraConfig + ); + + bindings = lib.mapAttrs' (k: lib.nameValuePair "XDG_${k}_DIR") directories; in lib.mkIf cfg.enable { - assertions = [ - (lib.hm.assertions.assertPlatform "xdg.userDirs" pkgs lib.platforms.linux) - ]; - xdg.configFile."user-dirs.dirs".text = let # For some reason, these need to be wrapped with quotes to be valid. - wrapped = lib.mapAttrs (_: value: ''"${value}"'') directories; + wrapped = lib.mapAttrs (_: value: ''"${value}"'') bindings; in lib.generators.toKeyValue { } wrapped; xdg.configFile."user-dirs.conf".text = "enabled=False"; - home.sessionVariables = directories; + home.packages = lib.mkIf (cfg.package != null) [ cfg.package ]; + + home.sessionVariables = lib.mkIf cfg.setSessionVariables bindings; home.activation.createXdgUserDirectories = lib.mkIf cfg.createDirectories ( let diff --git a/tests/modules/misc/xdg/default.nix b/tests/modules/misc/xdg/default.nix index 9212694f50b7..53ab57cd7c2b 100644 --- a/tests/modules/misc/xdg/default.nix +++ b/tests/modules/misc/xdg/default.nix @@ -4,4 +4,7 @@ xdg-mime-disabled = ./mime-disabled.nix; xdg-autostart = ./autostart.nix; xdg-autostart-readonly = ./autostart-readonly.nix; + xdg-user-dirs-mixed = ./user-dirs-mixed.nix; + xdg-user-dirs-null = ./user-dirs-null.nix; + xdg-user-dirs-short = ./user-dirs-short.nix; } diff --git a/tests/modules/misc/xdg/linux.nix b/tests/modules/misc/xdg/linux.nix index b0a6bb043987..ed1773496701 100644 --- a/tests/modules/misc/xdg/linux.nix +++ b/tests/modules/misc/xdg/linux.nix @@ -2,7 +2,6 @@ xdg-mime-apps-basics = ./mime-apps-basics.nix; xdg-system-dirs = ./system-dirs.nix; xdg-desktop-entries = ./desktop-entries.nix; - xdg-user-dirs-null = ./user-dirs-null.nix; xdg-portal = ./portal.nix; xdg-mime = ./mime.nix; xdg-mime-package = ./mime-packages.nix; diff --git a/tests/modules/misc/xdg/user-dirs-mixed.nix b/tests/modules/misc/xdg/user-dirs-mixed.nix new file mode 100644 index 000000000000..45e465aae919 --- /dev/null +++ b/tests/modules/misc/xdg/user-dirs-mixed.nix @@ -0,0 +1,35 @@ +{ + config, + pkgs, + ... +}: + +{ + config = { + home.stateVersion = "25.05"; + + xdg.userDirs = { + enable = true; + extraConfig.PROJECTS = "${config.home.homeDirectory}/Projects"; + ## This will stop working with stateVersion 25.11. + extraConfig.XDG_MISC_DIR = "${config.home.homeDirectory}/Misc"; + }; + + nmt.script = '' + configFile=home-files/.config/user-dirs.dirs + assertFileExists $configFile + assertFileContent $configFile ${pkgs.writeText "expected" '' + XDG_DESKTOP_DIR="/home/hm-user/Desktop" + XDG_DOCUMENTS_DIR="/home/hm-user/Documents" + XDG_DOWNLOAD_DIR="/home/hm-user/Downloads" + XDG_MISC_DIR="/home/hm-user/Misc" + XDG_MUSIC_DIR="/home/hm-user/Music" + XDG_PICTURES_DIR="/home/hm-user/Pictures" + XDG_PROJECTS_DIR="/home/hm-user/Projects" + XDG_PUBLICSHARE_DIR="/home/hm-user/Public" + XDG_TEMPLATES_DIR="/home/hm-user/Templates" + XDG_VIDEOS_DIR="/home/hm-user/Videos" + ''} + ''; + }; +} diff --git a/tests/modules/misc/xdg/user-dirs-short.nix b/tests/modules/misc/xdg/user-dirs-short.nix new file mode 100644 index 000000000000..4dfe529cb161 --- /dev/null +++ b/tests/modules/misc/xdg/user-dirs-short.nix @@ -0,0 +1,30 @@ +{ + config, + pkgs, + ... +}: + +{ + config = { + xdg.userDirs = { + enable = true; + extraConfig.PROJECTS = "${config.home.homeDirectory}/Projects"; + }; + + nmt.script = '' + configFile=home-files/.config/user-dirs.dirs + assertFileExists $configFile + assertFileContent $configFile ${pkgs.writeText "expected" '' + XDG_DESKTOP_DIR="/home/hm-user/Desktop" + XDG_DOCUMENTS_DIR="/home/hm-user/Documents" + XDG_DOWNLOAD_DIR="/home/hm-user/Downloads" + XDG_MUSIC_DIR="/home/hm-user/Music" + XDG_PICTURES_DIR="/home/hm-user/Pictures" + XDG_PROJECTS_DIR="/home/hm-user/Projects" + XDG_PUBLICSHARE_DIR="/home/hm-user/Public" + XDG_TEMPLATES_DIR="/home/hm-user/Templates" + XDG_VIDEOS_DIR="/home/hm-user/Videos" + ''} + ''; + }; +}