Subject: [PATCH 15/17] services: mpd: Provision a default cache directory and set HOME.

From: Maxim Cournoyer <[email-masked]>
Date: Fri, 28 Apr 2023 10:27:08 -0400

Relates to <https://issues.guix.gnu.org/63082>.

* gnu/services/audio.scm (mpd-shepherd-service): Create a default .cache
directory.  Use mkdir-p/perms and refactor loop.  Set the HOME environment
variables.
---
 doc/guix.texi          |  3 +-
 gnu/services/audio.scm | 76 ++++++++++++++++++++++++++----------------
 2 files changed, 49 insertions(+), 30 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 23f3070f39..9be59f9f02 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -33603,7 +33603,8 @@ Audio Services
 The directory to store playlists.
 
 @item @code{db-file} (type: maybe-string)
-The location of the music database.
+The location of the music database.  When left unspecified,
+@file{~/.cache/db} is used.
 
 @item @code{state-file} (type: maybe-string)
 The location of the file that stores current MPD's state.
diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm
index f0587b9106..7c577ff73b 100644
--- a/gnu/services/audio.scm
+++ b/gnu/services/audio.scm
@@ -25,6 +25,7 @@ (define-module (gnu services audio)
   #:use-module (guix deprecation)
   #:use-module (guix diagnostics)
   #:use-module (guix i18n)
+  #:use-module (guix modules)
   #:use-module (gnu services)
   #:use-module (gnu services admin)
   #:use-module (gnu services configuration)
@@ -463,7 +464,8 @@ (define-configuration mpd-configuration
 
   (db-file
    maybe-string
-   "The location of the music database.")
+   "The location of the music database.  When left unspecified,
+@file{~/.cache/db} is used.")
 
   (state-file
    maybe-string
@@ -597,34 +599,50 @@ (define (mpd-shepherd-service config)
        (documentation "Run the MPD (Music Player Daemon)")
        (requirement `(user-processes loopback ,@shepherd-requirement))
        (provision '(mpd))
-       (start #~(begin
-                  (let ((user (getpw #$username)))
-                    (for-each
-                     (lambda (x)
-                       ;; Take action on absolute file names, to filter out
-                       ;; the 'syslog' special value.
-                       (when (and x (string-prefix? "/" x)
-                                  (not (file-exists? x)))
-                         (mkdir-p x)
-                         (chown x (passwd:uid user) (passwd:gid user))))
-                     (list #$(maybe-value playlist-directory)
-                           (and=> #$(maybe-value db-file) dirname)
-                           (and=> #$(maybe-value log-file) dirname)
-                           (and=> #$(maybe-value state-file) dirname)
-                           (and=> #$(maybe-value sticker-file) dirname))))
-
-                  (make-forkexec-constructor
-                   (list #$(file-append package "/bin/mpd")
-                         "--no-daemon"
-                         #$config-file)
-                   #:environment-variables
-                   ;; Use the system-configured pulse configuration.
-                   (list "PULSE_CLIENTCONFIG=/etc/pulse/client.conf"
-                         "PULSE_CONFIG=/etc/pulse/daemon.conf")
-                   #:user #$username
-                   #:group #$(user-account-group user)
-                   #:supplementary-groups
-                   '#$(user-account-supplementary-groups user))))
+       (start
+        (with-imported-modules (source-module-closure
+                                '((gnu build activation)))
+          #~(begin
+              (use-modules (gnu build activation))
+
+              (let ((home #$(user-account-home-directory user)))
+                (let ((user (getpw #$username))
+                      (default-cache-dir (string-append home "/.cache")))
+
+                  (define (init-directory directory)
+                    (unless (file-exists? directory)
+                      (mkdir-p/perms directory user #o755)))
+
+                  ;; Define a cache location that can be automatically used
+                  ;; for the database file, in case it hasn't been explicitly
+                  ;; specified.
+                  (for-each
+                   init-directory
+                   (cons default-cache-dir
+                         '#$(map dirname
+                                 ;; XXX: Delete the potential "syslog"
+                                 ;; log-file value, which is not a directory.
+                                 (delete "syslog"
+                                         (filter-map maybe-value
+                                                     (list db-file
+                                                           log-file
+                                                           state-file
+                                                           sticker-file)))))))
+
+                (make-forkexec-constructor
+                 (list #$(file-append package "/bin/mpd") "--no-daemon"
+                       #$config-file)
+                 #:environment-variables
+                 ;; Use the system-configured pulse configuration.  Set HOME
+                 ;; so MPD can infer default paths, such as for the database
+                 ;; file.
+                 (list (string-append "HOME=" home)
+                       "PULSE_CLIENTCONFIG=/etc/pulse/client.conf"
+                       "PULSE_CONFIG=/etc/pulse/daemon.conf")
+                 #:user #$username
+                 #:group #$(user-account-group user)
+                 #:supplementary-groups
+                 '#$(user-account-supplementary-groups user))))))
        (stop  #~(make-kill-destructor))
        (actions
         (list (shepherd-configuration-action config-file)
-- 
2.39.2