[bug#77882] scripts: home: Support extracting home-environment from Guix System declaration.

Message ID bd25c3eb130c6f2b5d7839c416de3e9be269aac5.1744943121.git.hako@ultrarare.space
State New
Headers
Series [bug#77882] scripts: home: Support extracting home-environment from Guix System declaration. |

Commit Message

Hilton Chain April 18, 2025, 2:26 a.m. UTC
  * guix/scripts/home.scm (process-action): Handle operating-system declaration
and extract home environment for current user.
* doc/guix.texi (Guix Services)[Guix Home Service]: Document it.

Change-Id: I995f79c2549e6edc76322542d0422159e0b79996
---
 doc/guix.texi         |  5 +++++
 guix/scripts/home.scm | 31 +++++++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 4 deletions(-)


base-commit: f3fb333f7c7827780884d2e202f215e75db527af
prerequisite-patch-id: df261270810df64de08b358af11031330674eb28
prerequisite-patch-id: 3f82b9ffbffb403a77631567c4af11a2493ee8a7
  

Comments

Maxim Cournoyer April 21, 2025, 1:33 a.m. UTC | #1
Hi,

Hilton Chain <hako@ultrarare.space> writes:

> * guix/scripts/home.scm (process-action): Handle operating-system declaration
> and extract home environment for current user.
> * doc/guix.texi (Guix Services)[Guix Home Service]: Document it.

The use case is a bit unclear for me, despite reading...

> Change-Id: I995f79c2549e6edc76322542d0422159e0b79996
> ---
>  doc/guix.texi         |  5 +++++
>  guix/scripts/home.scm | 31 +++++++++++++++++++++++++++----
>  2 files changed, 32 insertions(+), 4 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 070528667f..a58326debf 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -42255,6 +42255,11 @@ Guix Services
>  everything consistently at once, saving users the need to run
>  @command{guix home reconfigure} independently.
>  
> +@command{guix home} can operate on the home environment configured for
> +current user via this service, but its effect won't last beyond the next
> +system activation.  This can be used for quick testing and may avoid the
> +need of keeping a separate home configuration.

... this.

How do you declare a home environment in an `operating-system'
declaration?  Is this already supported?

Oh! 'guix-home-service-type'.  It seems I'm late in the news.  That's
cool!

>  @defvar guix-home-service-type
>  Service type for the Guix Home service.  Its value must be a list of
>  lists containing user and home environment pairs.  The key of each pair
> diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm
> index b4c82d275f..6d0a68166e 100644
> --- a/guix/scripts/home.scm
> +++ b/guix/scripts/home.scm
> @@ -35,6 +35,8 @@ (define-module (guix scripts home)
>                                               shepherd-service-requirement)
>    #:autoload   (guix modules) (source-module-closure)
>    #:autoload   (gnu build linux-container) (call-with-container %namespaces)
> +  #:use-module ((gnu system) #:select (operating-system?
> +                                       operating-system-user-services))
>    #:autoload   (gnu system linux-container) (eval/container)
>    #:autoload   (gnu system file-systems) (file-system-mapping
>                                            file-system-mapping-source
> @@ -478,10 +480,31 @@ (define (process-action action args opts)
>  declaration as an argument (a file name.)  OPTS is the raw alist of options
>  resulting from command-line parsing."
>    (define (ensure-home-environment file-or-exp obj)
> -    (unless (home-environment? obj)
> -      (leave (G_ "'~a' does not return a home environment~%")
> -             file-or-exp))
> -    obj)
> +    (let* ((username
> +            (or (getenv "LOGNAME")
> +                (passwd:name (getpwuid (getuid)))))

First time I've heard of LOGNAME :-).  Typically I see 'USER' used in
its place; shouldn't that be consulted as well, or used instead?

As for the second clause of the above or, it can be simplified to just
'(getpwnam (getuid))'.

> +           (os-home-env-config
> +            (and (operating-system? obj)
> +                 (and=> (find (lambda (%service)
> +                                (eq? (service-type-name (service-kind %service))
> +                                     'guix-home))
> +                              (operating-system-user-services obj))
> +                        service-value)))
> +           (os-home-env
> +            (and os-home-env-config
> +                 (and=> (find (lambda (home-env-config)
> +                                (string=? (first home-env-config) username))
> +                              os-home-env-config)
> +                        second)))
> +           (home-env
> +            (or os-home-env obj)))
> +      (unless (home-environment? home-env)
> +        (if (operating-system? obj)
> +            (leave (G_ "'~a' does not contain a home environment for user '~a'~%")
> +                   file-or-exp username)
> +            (leave (G_ "'~a' does not return a home environment~%")
> +                   file-or-exp)))
> +      home-env))

LGTM.

Reviewed-by: Maxim Cournoyer <maxim.cournoyer@gmail>
  
Hilton Chain May 3, 2025, 11:48 a.m. UTC | #2
On Mon, 21 Apr 2025 09:33:12 +0800,
Maxim Cournoyer wrote:
>
> Hi,
>
> Hilton Chain <hako@ultrarare.space> writes:
>
> > * guix/scripts/home.scm (process-action): Handle operating-system declaration
> > and extract home environment for current user.
> > * doc/guix.texi (Guix Services)[Guix Home Service]: Document it.
>
> The use case is a bit unclear for me, despite reading...
>
> > Change-Id: I995f79c2549e6edc76322542d0422159e0b79996
> > ---
> >  doc/guix.texi         |  5 +++++
> >  guix/scripts/home.scm | 31 +++++++++++++++++++++++++++----
> >  2 files changed, 32 insertions(+), 4 deletions(-)
> >
> > diff --git a/doc/guix.texi b/doc/guix.texi
> > index 070528667f..a58326debf 100644
> > --- a/doc/guix.texi
> > +++ b/doc/guix.texi
> > @@ -42255,6 +42255,11 @@ Guix Services
> >  everything consistently at once, saving users the need to run
> >  @command{guix home reconfigure} independently.
> >
> > +@command{guix home} can operate on the home environment configured for
> > +current user via this service, but its effect won't last beyond the next
> > +system activation.  This can be used for quick testing and may avoid the
> > +need of keeping a separate home configuration.
>
> ... this.
>
> How do you declare a home environment in an `operating-system'
> declaration?  Is this already supported?
>
> Oh! 'guix-home-service-type'.  It seems I'm late in the news.  That's
> cool!
>
> >  @defvar guix-home-service-type
> >  Service type for the Guix Home service.  Its value must be a list of
> >  lists containing user and home environment pairs.  The key of each pair
> > diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm
> > index b4c82d275f..6d0a68166e 100644
> > --- a/guix/scripts/home.scm
> > +++ b/guix/scripts/home.scm
> > @@ -35,6 +35,8 @@ (define-module (guix scripts home)
> >                                               shepherd-service-requirement)
> >    #:autoload   (guix modules) (source-module-closure)
> >    #:autoload   (gnu build linux-container) (call-with-container %namespaces)
> > +  #:use-module ((gnu system) #:select (operating-system?
> > +                                       operating-system-user-services))
> >    #:autoload   (gnu system linux-container) (eval/container)
> >    #:autoload   (gnu system file-systems) (file-system-mapping
> >                                            file-system-mapping-source
> > @@ -478,10 +480,31 @@ (define (process-action action args opts)
> >  declaration as an argument (a file name.)  OPTS is the raw alist of options
> >  resulting from command-line parsing."
> >    (define (ensure-home-environment file-or-exp obj)
> > -    (unless (home-environment? obj)
> > -      (leave (G_ "'~a' does not return a home environment~%")
> > -             file-or-exp))
> > -    obj)
> > +    (let* ((username
> > +            (or (getenv "LOGNAME")
> > +                (passwd:name (getpwuid (getuid)))))
>
> First time I've heard of LOGNAME :-).  Typically I see 'USER' used in
> its place; shouldn't that be consulted as well, or used instead?

OK, I have changed to use USER instead.

> As for the second clause of the above or, it can be simplified to just
> '(getpwnam (getuid))'.

Tried it in REPL, the result is the same as ‘(getpwuid (getuid))’.  So I left it
unchanged.

> > +           (os-home-env-config
> > +            (and (operating-system? obj)
> > +                 (and=> (find (lambda (%service)
> > +                                (eq? (service-type-name (service-kind %service))
> > +                                     'guix-home))
> > +                              (operating-system-user-services obj))
> > +                        service-value)))
> > +           (os-home-env
> > +            (and os-home-env-config
> > +                 (and=> (find (lambda (home-env-config)
> > +                                (string=? (first home-env-config) username))
> > +                              os-home-env-config)
> > +                        second)))
> > +           (home-env
> > +            (or os-home-env obj)))
> > +      (unless (home-environment? home-env)
> > +        (if (operating-system? obj)
> > +            (leave (G_ "'~a' does not contain a home environment for user '~a'~%")
> > +                   file-or-exp username)
> > +            (leave (G_ "'~a' does not return a home environment~%")
> > +                   file-or-exp)))
> > +      home-env))
>
> LGTM.
>
> Reviewed-by: Maxim Cournoyer <maxim.cournoyer@gmail>

Thanks for the review!  Applied as 415e3d98d6faf5fd3d1b7b3daa2f20636e4ff822.
  

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 070528667f..a58326debf 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -42255,6 +42255,11 @@  Guix Services
 everything consistently at once, saving users the need to run
 @command{guix home reconfigure} independently.
 
+@command{guix home} can operate on the home environment configured for
+current user via this service, but its effect won't last beyond the next
+system activation.  This can be used for quick testing and may avoid the
+need of keeping a separate home configuration.
+
 @defvar guix-home-service-type
 Service type for the Guix Home service.  Its value must be a list of
 lists containing user and home environment pairs.  The key of each pair
diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm
index b4c82d275f..6d0a68166e 100644
--- a/guix/scripts/home.scm
+++ b/guix/scripts/home.scm
@@ -35,6 +35,8 @@  (define-module (guix scripts home)
                                              shepherd-service-requirement)
   #:autoload   (guix modules) (source-module-closure)
   #:autoload   (gnu build linux-container) (call-with-container %namespaces)
+  #:use-module ((gnu system) #:select (operating-system?
+                                       operating-system-user-services))
   #:autoload   (gnu system linux-container) (eval/container)
   #:autoload   (gnu system file-systems) (file-system-mapping
                                           file-system-mapping-source
@@ -478,10 +480,31 @@  (define (process-action action args opts)
 declaration as an argument (a file name.)  OPTS is the raw alist of options
 resulting from command-line parsing."
   (define (ensure-home-environment file-or-exp obj)
-    (unless (home-environment? obj)
-      (leave (G_ "'~a' does not return a home environment~%")
-             file-or-exp))
-    obj)
+    (let* ((username
+            (or (getenv "LOGNAME")
+                (passwd:name (getpwuid (getuid)))))
+           (os-home-env-config
+            (and (operating-system? obj)
+                 (and=> (find (lambda (%service)
+                                (eq? (service-type-name (service-kind %service))
+                                     'guix-home))
+                              (operating-system-user-services obj))
+                        service-value)))
+           (os-home-env
+            (and os-home-env-config
+                 (and=> (find (lambda (home-env-config)
+                                (string=? (first home-env-config) username))
+                              os-home-env-config)
+                        second)))
+           (home-env
+            (or os-home-env obj)))
+      (unless (home-environment? home-env)
+        (if (operating-system? obj)
+            (leave (G_ "'~a' does not contain a home environment for user '~a'~%")
+                   file-or-exp username)
+            (leave (G_ "'~a' does not return a home environment~%")
+                   file-or-exp)))
+      home-env))
 
   (let* ((file   (match args
                    (() #f)