Subject: Re: [PATCH] guix: Add syntactic sugar for profile generation.

From: [email-masked]
Date: Fri, 27 May 2022 15:39:38 +0300

On 2022-05-26 11:01, Liliana Marie Prikler wrote:

> * guix/profiles.scm (%profile, package-compatibility-helper): New variables.
> (profile): Implement in terms of package-compatibility-helper.
> ---
> Hi Guix,
>
> this is a first step towards managing multiple profiles via Guix Home.
> It makes it so that regular Guix profiles can more easily be specified, though
> I'm not quite sure whether the mlet of packages->profile-entry should not also
> be used here.

The sugar looks reasonable to me.

>
> In any case, with this it should now be relatively easy for users to specify
> profiles such as
>   (profile (name "emacs") (packages emacs emacs-magit emacs-org ...))
>   (profile (name "r") (packages r r-plyr emacs emacs-ess ...))
>   (profile (name "python") (packages python python-beautifulsoup4 ...))
>   ...
> What's still missing is a way to link them up with /var/guix/profiles/per-user

Don't think that they have to be linked to /var/guix/profiles/per-user,
as mentioned earlier profiles built for the home environment should be a
part of home environment, link to the profile will be inside
home-environment directory:
/var/guix/profiles/per-user/bob/guix-home/profiles/PROFILE_NAME

links in /var/guix/profiles/per-user needed for switching between
profile versions, it's not possible in case profile is a part of home
environment, otherwise home environment will stop being reproducible.

> and $HOME – for the latter, there would be a home-*-service-type.

Yep, can be done by home-files-* and symlink-manager I guess.

>
> WDYT?
>
>  guix/profiles.scm  | 23 ++++++++++++++++++++++-
>  tests/profiles.scm | 16 ++++++++++++++++
>  2 files changed, 38 insertions(+), 1 deletion(-)
>
> diff --git a/guix/profiles.scm b/guix/profiles.scm
> index bf50c00a1e..fbc343c456 100644
> --- a/guix/profiles.scm
> +++ b/guix/profiles.scm
> @@ -1974,7 +1974,7 @@ (define builder
>                                             (manifest-entries manifest))))))))
>  
>  ;; Declarative profile.
> -(define-record-type* <profile> profile make-profile
> +(define-record-type* <profile> %profile make-profile
>    profile?
>    (name               profile-name (default "profile")) ;string
>    (content            profile-content)                  ;<manifest>
> @@ -1987,6 +1987,27 @@ (define-record-type* <profile> profile make-profile
>    (relative-symlinks? profile-relative-symlinks?  ;Boolean
>                        (default #f)))
>  
> +(define-syntax package-compatibility-helper
> +  (syntax-rules (packages manifest)
> +    ((_ () (fields ...))
> +     (%profile fields ...))
> +    ((_ ((packages exp) rest ...) (others ...))
> +     (package-compatibility-helper
> +      (rest ...)
> +      (others ... (content (packages->manifest
> +                            (delete-duplicates exp eq?))))))
> +    ((_ ((manifest exp) rest ...) (others ...))
> +     (package-compatibility-helper
> +      (rest ...)
> +      (others ... (content exp))))
> +    ((_ (field rest ...) (others ...))
> +     (package-compatibility-helper (rest ...) (others ... field)))))
> +
> +(define-syntax-rule (profile fields ...)
> +  "Build a <profile> record, automatically converting 'packages' or 'manifest '
> +field specifications to 'content'."
> +  (package-compatibility-helper (fields ...) ()))
> +
>  (define-gexp-compiler (profile-compiler (profile <profile>) system target)
>    "Compile PROFILE to a derivation."
>    (match profile
> diff --git a/tests/profiles.scm b/tests/profiles.scm
> index d59d75985f..970a34b6cc 100644
> --- a/tests/profiles.scm
> +++ b/tests/profiles.scm
> @@ -272,6 +272,22 @@ (define transform1
>                                    (manifest-pattern (name name))))
>             '("gcc" "binutils" "glibc" "coreutils" "grep" "sed"))))
>  
> +(test-assert "profile syntax sugar"
> +  (let ((p1 (dummy-package "p1"))
> +        (p2 (dummy-package "p2")))
> +    (define (profile=? . profiles)
> +      (define (manifest=? . manifests)
> +        ;; Since we're using the same packages, we could also compare via eq?
> +        (apply list= manifest-entry=? (map manifest-entries manifests)))
> +      (apply manifest=? (map profile-content profiles)))
> +
> +    (profile=?
> +     (profile (content (manifest
> +                        (map package->manifest-entry (list p1 p2)))))
> +     (profile (content (packages->manifest (list p1 p2))))
> +     (profile (manifest (packages->manifest (list p1 p2))))
> +     (profile (packages (list p1 p2))))))
> +
>  (test-assertm "profile-derivation"
>    (mlet* %store-monad
>        ((entry ->   (package->manifest-entry %bootstrap-guile))

-- 
Best regards,
Andrew Tropin