[bug#77882] scripts: home: Support extracting home-environment from Guix System declaration.
Commit Message
* 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
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>
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.
@@ -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
@@ -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)