From 1fdb16866b377b7365768c86c9b4ac45e30bca6c Mon Sep 17 00:00:00 2001
From: Olli Helenius <liff@iki.fi>
Date: Fri, 22 Mar 2019 13:47:49 +0200
Subject: [PATCH] systemd: add support for session variables

Via environment.d(5).
---
 modules/systemd.nix                           | 35 ++++++++++++++++---
 tests/modules/systemd/default.nix             |  1 +
 .../systemd/session-variables-expected.conf   |  2 ++
 tests/modules/systemd/session-variables.nix   | 18 ++++++++++
 4 files changed, 51 insertions(+), 5 deletions(-)
 create mode 100644 tests/modules/systemd/session-variables-expected.conf
 create mode 100644 tests/modules/systemd/session-variables.nix

diff --git a/modules/systemd.nix b/modules/systemd.nix
index f7325b41f..051aee941 100644
--- a/modules/systemd.nix
+++ b/modules/systemd.nix
@@ -12,7 +12,8 @@ let
       || cfg.sockets != {}
       || cfg.targets != {}
       || cfg.timers != {}
-      || cfg.paths != {};
+      || cfg.paths != {}
+      || cfg.sessionVariables != {};
 
   toSystemdIni = generators.toINI {
     mkKeyValue = key: value:
@@ -85,6 +86,13 @@ let
     }
   '';
 
+  sessionVariables = mkIf (cfg.sessionVariables != {}) {
+    "environment.d/10-home-manager.conf".text =
+      concatStringsSep "\n" (
+        mapAttrsToList (n: v: "${n}=${toString v}") cfg.sessionVariables
+      ) + "\n";
+    };
+
 in
 
 {
@@ -156,6 +164,20 @@ in
           start is considered successful.
         '';
       };
+
+      sessionVariables = mkOption {
+        default = {};
+        type = with types; attrsOf (either int str);
+        example = { EDITOR = "vim"; };
+        description = ''
+          Environment variables that will be set for the user session.
+          The variable values must be as described in
+          <citerefentry>
+            <refentrytitle>environment.d</refentrytitle>
+            <manvolnum>5</manvolnum>
+          </citerefentry>.
+        '';
+      };
     };
   };
 
@@ -168,7 +190,7 @@ in
             let
               names = concatStringsSep ", " (
                   attrNames (
-                      cfg.services // cfg.sockets // cfg.targets // cfg.timers // cfg.paths
+                      cfg.services // cfg.sockets // cfg.targets // cfg.timers // cfg.paths // cfg.sessionVariables
                   )
               );
             in
@@ -180,8 +202,8 @@ in
     # If we run under a Linux system we assume that systemd is
     # available, in particular we assume that systemctl is in PATH.
     (mkIf pkgs.stdenv.isLinux {
-      xdg.configFile =
-        listToAttrs (
+      xdg.configFile = mkMerge [
+        (listToAttrs (
           (buildServices "service" cfg.services)
           ++
           (buildServices "socket" cfg.sockets)
@@ -191,7 +213,10 @@ in
           (buildServices "timer" cfg.timers)
           ++
           (buildServices "path" cfg.paths)
-        );
+          ))
+
+          sessionVariables
+        ];
 
       # Run systemd service reload if user is logged in. If we're
       # running this from the NixOS module then XDG_RUNTIME_DIR is not
diff --git a/tests/modules/systemd/default.nix b/tests/modules/systemd/default.nix
index cc1d5b6ba..c1779ac59 100644
--- a/tests/modules/systemd/default.nix
+++ b/tests/modules/systemd/default.nix
@@ -1,4 +1,5 @@
 {
   systemd-services = ./services.nix;
+  systemd-session-variables = ./session-variables.nix;
   systemd-timers = ./timers.nix;
 }
diff --git a/tests/modules/systemd/session-variables-expected.conf b/tests/modules/systemd/session-variables-expected.conf
new file mode 100644
index 000000000..5b6e80bc3
--- /dev/null
+++ b/tests/modules/systemd/session-variables-expected.conf
@@ -0,0 +1,2 @@
+V_int=1
+V_str=2
diff --git a/tests/modules/systemd/session-variables.nix b/tests/modules/systemd/session-variables.nix
new file mode 100644
index 000000000..7cfb4a6c7
--- /dev/null
+++ b/tests/modules/systemd/session-variables.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  config = {
+    systemd.user.sessionVariables = {
+      V_int = 1;
+      V_str = "2";
+    };
+
+    nmt.script = ''
+      local envFile=home-files/.config/environment.d/10-home-manager.conf
+      assertFileExists $envFile
+      assertFileContent $envFile ${./session-variables-expected.conf}
+    '';
+  };
+}