Message ID | 10354f31e0be9bcb88b78da2fb8a2a3c3acbde10.camel@gmail.com |
---|---|
State | New |
Headers |
Return-Path: <guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org> X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 66BE027BBEA; Thu, 26 May 2022 10:22:17 +0100 (BST) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI, PP_MIME_FAKE_ASCII_TEXT,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id DFD3527BBE9 for <patchwork@mira.cbaines.net>; Thu, 26 May 2022 10:22:16 +0100 (BST) Received: from localhost ([::1]:57764 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org>) id 1nu9h9-0002z9-Gw for patchwork@mira.cbaines.net; Thu, 26 May 2022 05:22:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60810) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1nu9f1-0001tP-7Z for guix-patches@gnu.org; Thu, 26 May 2022 05:20:03 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:34939) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1nu9f0-00016C-Tb for guix-patches@gnu.org; Thu, 26 May 2022 05:20:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1nu9f0-0005rj-Jk for guix-patches@gnu.org; Thu, 26 May 2022 05:20:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#55653] [PATCH] guix: Add syntactic sugar for profile generation. Resent-From: Liliana Marie Prikler <liliana.prikler@gmail.com> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces@debbugs.gnu.org> Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 26 May 2022 09:20:02 +0000 Resent-Message-ID: <handler.55653.B.165355680022532@debbugs.gnu.org> Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 55653 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 55653@debbugs.gnu.org Cc: Andrew Tropin <andrewtropin@gmail.com>, Ludovic =?utf-8?q?Court=C3=A8s?= <ludo@gnu.org>, Maxime Devos <maximedevos@telenet.be>, zimoun <zimon.toutoune@gmail.com> X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.165355680022532 (code B ref -1); Thu, 26 May 2022 09:20:02 +0000 Received: (at submit) by debbugs.gnu.org; 26 May 2022 09:20:00 +0000 Received: from localhost ([127.0.0.1]:57069 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces@debbugs.gnu.org>) id 1nu9ex-0005rM-J9 for submit@debbugs.gnu.org; Thu, 26 May 2022 05:19:59 -0400 Received: from lists.gnu.org ([209.51.188.17]:35406) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <liliana.prikler@gmail.com>) id 1nu9ew-0005rF-2q for submit@debbugs.gnu.org; Thu, 26 May 2022 05:19:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60778) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <liliana.prikler@gmail.com>) id 1nu9ev-0001m3-NR for guix-patches@gnu.org; Thu, 26 May 2022 05:19:57 -0400 Received: from mail-ej1-x642.google.com ([2a00:1450:4864:20::642]:40906) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <liliana.prikler@gmail.com>) id 1nu9et-00014e-Kn; Thu, 26 May 2022 05:19:57 -0400 Received: by mail-ej1-x642.google.com with SMTP id wh22so1881281ejb.7; Thu, 26 May 2022 02:19:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:date:subject:to:cc:content-transfer-encoding:message-id :mime-version; bh=GxpEctlAdt0wUFnQfKpzU+e9a9lIOiX1Xv06mV+7FWI=; b=kLkWy8N3jhA6ZWDCzmtjJRG14VkMXotVSjOXXHs5yEkIRqDbvfw72sB/TGG+B2fQsf KaA1t4RmwjVM0+LwdLGACU3/25wr9tdCg0L28QraRXzw7vN1V2JXsvfow8T61RilTidw aCyZfmQ1Ig3etAZxLAJIANLhiN3kJw8CEvcYnPAUVdGSJwVJiGnOguycsaqOwieMpfVn mB5YUSPCcsYTntsIweSss6Sue1bqevUZWruLRd1HC1Sc0R+Y+0dFJ4W9DyROKf9Pe/HG TrsI4zsLv0sNC/bN18H2EM1FeuxWZyySmvA0oky+OGcgv9vT8qKVGcXIJCz30UF8lUut fbqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:date:subject:to:cc :content-transfer-encoding:message-id:mime-version; bh=GxpEctlAdt0wUFnQfKpzU+e9a9lIOiX1Xv06mV+7FWI=; b=bXEJVTNJc59ememgVi7tAly834eZpC5P5lKwaa21v5DqSBjj/IBjhWqyfb/W2kchrg DkCIUKyDQp5GJqk7AFElHNTRrqt72c3YdrWCdPD3fu5i5lraJxQqW3D5wAVlXzdXjLdF AnKxFdsa7M/vwf7PQuAxL7Wn3qDkGMpdsBadTfn43b9JKD5mbYAr/brYnvIGlKR50s1y QfzpVbuYuZCZxOnKQOnNtPpQykkZ6BCoZToWsQL7/R4QG53N6pYyZ8msFRDG3n2+FV52 6XybBkBYRGHS0ge5doZnpARe4kfb1T5n7y4n1xrGsAj5q0TTmSoPfnYPXKZrIvpmqgbd YXBw== X-Gm-Message-State: AOAM531osU8os0S6byRHbXRfsmLCcnObYhQdl07HbLrnaEAMfLyLNYkn DwRVEDeirjy766PS249qznh3fS4k4Jc= X-Google-Smtp-Source: ABdhPJxHc/0Got+LrL1FC330LQpbff3pMYE+BRSVMYonql6fDZAGnOAih6OCxocxkGJA64XysPSF3A== X-Received: by 2002:a17:907:8a01:b0:6ff:8b8:ca85 with SMTP id sc1-20020a1709078a0100b006ff08b8ca85mr9985812ejc.602.1653556791717; Thu, 26 May 2022 02:19:51 -0700 (PDT) Received: from nijino.fritz.box (85-127-52-93.dsl.dynamic.surfer.at. [85.127.52.93]) by smtp.gmail.com with ESMTPSA id e12-20020a170906374c00b006fec41b21e1sm332952ejc.171.2022.05.26.02.19.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 May 2022 02:19:51 -0700 (PDT) From: Liliana Marie Prikler <liliana.prikler@gmail.com> Date: Thu, 26 May 2022 11:01:02 +0200 Content-Transfer-Encoding: 8bit Message-ID: <10354f31e0be9bcb88b78da2fb8a2a3c3acbde10.camel@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::642; envelope-from=liliana.prikler@gmail.com; helo=mail-ej1-x642.google.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, PP_MIME_FAKE_ASCII_TEXT=0.999, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: <guix-patches.gnu.org> List-Unsubscribe: <https://lists.gnu.org/mailman/options/guix-patches>, <mailto:guix-patches-request@gnu.org?subject=unsubscribe> List-Archive: <https://lists.gnu.org/archive/html/guix-patches> List-Post: <mailto:guix-patches@gnu.org> List-Help: <mailto:guix-patches-request@gnu.org?subject=help> List-Subscribe: <https://lists.gnu.org/mailman/listinfo/guix-patches>, <mailto:guix-patches-request@gnu.org?subject=subscribe> Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: "Guix-patches" <guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org> X-getmail-retrieved-from-mailbox: Patches |
Series |
[bug#55653] guix: Add syntactic sugar for profile generation.
|
|
Commit Message
Liliana Marie Prikler
May 26, 2022, 9:01 a.m. UTC
* 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. 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 and $HOME – for the latter, there would be a home-*-service-type. WDYT? guix/profiles.scm | 23 ++++++++++++++++++++++- tests/profiles.scm | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-)
Comments
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))
Hello! Liliana Marie Prikler <liliana.prikler@gmail.com> skribis: > * 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. > > 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 ...)) > ... So the goal is to make things slightly more concise than: (profile (content (packages->manifest (list …)))) right? We don’t have syntactic sugar like this elsewhere, and I would prefer to remain consistent here. However, if that helps, we could have a procedure, like: (define (packages->profile name packages) (profile (name name) …)) Thoughts? Ludo’.
Hi, Am Dienstag, dem 31.05.2022 um 15:47 +0200 schrieb Ludovic Courtès: > So the goal is to make things slightly more concise than: > > (profile (content (packages->manifest (list …)))) > > right? More or less. However, I also feel that "content" is somewhat confusing if it were to be user-facing so I added a syntactic manifest noop as well. > We don’t have syntactic sugar like this elsewhere, and I would prefer > to remain consistent here. We do have origin sha256, which sets both hash-algo and hash-content, so it's not unprecedented in my opinion. > However, if that helps, we could have a procedure, like: > > (define (packages->profile name packages) > (profile (name name) …)) > > Thoughts? I do think syntactic constructors feel better here, because the end goal would be embedding things in (thunked) configuration fields. Having a procedure might be acceptable, but feels more clunky in the context of Guix. Chees
Hi, Liliana Marie Prikler <liliana.prikler@gmail.com> skribis: > Am Dienstag, dem 31.05.2022 um 15:47 +0200 schrieb Ludovic Courtès: >> So the goal is to make things slightly more concise than: >> >> (profile (content (packages->manifest (list …)))) >> >> right? > More or less. However, I also feel that "content" is somewhat > confusing if it were to be user-facing so I added a syntactic manifest > noop as well. OK. >> We don’t have syntactic sugar like this elsewhere, and I would prefer >> to remain consistent here. > We do have origin sha256, which sets both hash-algo and hash-content, > so it's not unprecedented in my opinion. ‘sha256’ is a backward-compatibility hack for ‘content-hash’, so it’s a bit different in my view. To be clear, what I meant is that record construction always look like this: (constructor (field1 value1) (field2 value2)) whereas here the proposal (IIUC) is: (constructor (field1 several values that get bundled together magically)) >> However, if that helps, we could have a procedure, like: >> >> (define (packages->profile name packages) >> (profile (name name) …)) >> >> Thoughts? > I do think syntactic constructors feel better here, because the end > goal would be embedding things in (thunked) configuration fields. > Having a procedure might be acceptable, but feels more clunky in the > context of Guix. To me, ‘packages->profile’ doesn’t look any more clunky than ‘packages->manifest’ or similar procedures. Do you think a procedure like this would address the verbosity problem that prompted you to propose this patch? Thanks, Ludo’.
Hi, Am Mittwoch, dem 01.06.2022 um 21:43 +0200 schrieb Ludovic Courtès: > [...] > > > > > > We don’t have syntactic sugar like this elsewhere, and I would > > > prefer to remain consistent here. > > We do have origin sha256, which sets both hash-algo and hash- > > content, so it's not unprecedented in my opinion. > > ‘sha256’ is a backward-compatibility hack for ‘content-hash’, so it’s > a bit different in my view. > > To be clear, what I meant is that record construction always look > like this: > > (constructor > (field1 value1) > (field2 value2)) > > whereas here the proposal (IIUC) is: > > (constructor > (field1 several values that get bundled together magically)) If it reads like that, then that's probably a mistake somewhere. My actual proposal to allow both of the following: (package other-fields ... (manifest some-manifest)) (package other-fields ... (packages (list bash coreutils emacs ...))) > > > However, if that helps, we could have a procedure, like: > > > > > > (define (packages->profile name packages) > > > (profile (name name) …)) > > > > > > Thoughts? > > I do think syntactic constructors feel better here, because the end > > goal would be embedding things in (thunked) configuration fields. > > Having a procedure might be acceptable, but feels more clunky in > > the context of Guix. > > To me, ‘packages->profile’ doesn’t look any more clunky than > ‘packages->manifest’ or similar procedures. > > Do you think a procedure like this would address the verbosity > problem that prompted you to propose this patch? I don't think it does tbh. We currently have two implementations of packages->profile-entry, one for Guix System, one for Guix Home, which at the time of writing are exactly the same. My use case of naming profiles would be served by such a procedure, but using a syntactic constructor has other benefits in that all of the fields of the profile become accessible. That means that users could (once profile management via Guix Home is implemented) for instance run less hooks or additional hooks for certain profiles, allow collisions, use relative symlinks, etc. for basically free, not to mention that changes which break record ABI (such as added fields) get promoted directly through syntax but not through a plain procedure. Cheers
Liliana Marie Prikler schreef op wo 01-06-2022 om 22:15 [+0200]: > not to mention that changes which > break record ABI (such as added fields) get promoted directly through > syntax but not through a plain procedure. Using a procedure instead of the record construction macro would make the ABI stable (*). ABI-wise, wouldn't a stable ABI (regular procudure) be better than an unstable ABI? There might be some benefits for a macro concerning readability or such, but I don't see any benefits ABI-wise. (*) assuming no inlining. Greetings, Maxime.
Hallo! Liliana Marie Prikler <liliana.prikler@gmail.com> skribis: > If it reads like that, then that's probably a mistake somewhere. My > actual proposal to allow both of the following: > > (package > other-fields ... > (manifest some-manifest)) > (package > other-fields ... > (packages (list bash coreutils emacs ...))) Oh OK, I got it wrong, sorry. Still I’m not a fan of having syntax that looks like a field but is not an actual field, if we can avoid it. I prefer to expose the data structure as it exists and, if needed, to build abstractions on top of it. (The ABI issue that Maxime mention is real but I don’t think it’s a big problem in practice.) >> > > However, if that helps, we could have a procedure, like: >> > > >> > > (define (packages->profile name packages) >> > > (profile (name name) …)) >> > > >> > > Thoughts? >> > I do think syntactic constructors feel better here, because the end >> > goal would be embedding things in (thunked) configuration fields. >> > Having a procedure might be acceptable, but feels more clunky in >> > the context of Guix. >> >> To me, ‘packages->profile’ doesn’t look any more clunky than >> ‘packages->manifest’ or similar procedures. >> >> Do you think a procedure like this would address the verbosity >> problem that prompted you to propose this patch? > I don't think it does tbh. We currently have two implementations of > packages->profile-entry, one for Guix System, one for Guix Home, which > at the time of writing are exactly the same. Looks like we could start by factorizing it. :-) > My use case of naming profiles would be served by such a procedure, > but using a syntactic constructor has other benefits in that all of > the fields of the profile become accessible. That means that users > could (once profile management via Guix Home is implemented) for > instance run less hooks or additional hooks for certain profiles, > allow collisions, use relative symlinks, etc. for basically free, not > to mention that changes which break record ABI (such as added fields) > get promoted directly through syntax but not through a plain > procedure. This is an argument (and probably a good one) in favor of using <profile> records. I don’t read it as an argument in favor of the ‘packages’ pseudo field though? Thanks, Ludo’.
Ludovic Courtès schreef op do 02-06-2022 om 15:32 [+0200]: > Still I’m not a fan of having syntax that looks like a field but is not > an actual field, if we can avoid it. I prefer to expose the data > structure as it exists and, if needed, to build abstractions on top of > it. (The ABI issue that Maxime mention is real but I don’t think it’s a > big problem in practice.) FWIW I've some ideas for stable ABIs for record constructors even when fields are added/removed or change from direct/thunked/delayed, a stable ABI can be defined later. Greetings, Maxime.
Am Donnerstag, dem 02.06.2022 um 15:32 +0200 schrieb Ludovic Courtès: > Hallo! > > Liliana Marie Prikler <liliana.prikler@gmail.com> skribis: > > > If it reads like that, then that's probably a mistake somewhere. > > My actual proposal to allow both of the following: > > > > (package > > other-fields ... > > (manifest some-manifest)) > > (package > > other-fields ... > > (packages (list bash coreutils emacs ...))) > > Oh OK, I got it wrong, sorry. Actually, I too got it wrong in the patch description. The implementation and test should be fine though. > Still I’m not a fan of having syntax that looks like a field but is > not an actual field, if we can avoid it. I prefer to expose the data > structure as it exists and, if needed, to build abstractions on top > of it. I can see where you're coming from, but IMHO the content field does not itself provide a useful abstraction, and changing the profile record + constructor would itself break ABI. Thus the syntactic sugar. > [...] > > My use case of naming profiles would be served by such a procedure, > > but using a syntactic constructor has other benefits in that all of > > the fields of the profile become accessible. That means that users > > could (once profile management via Guix Home is implemented) for > > instance run less hooks or additional hooks for certain profiles, > > allow collisions, use relative symlinks, etc. for basically free, > > not to mention that changes which break record ABI (such as added > > fields) get promoted directly through syntax but not through a > > plain procedure. > > This is an argument (and probably a good one) in favor of using > <profile> records. I don’t read it as an argument in favor of the > ‘packages’ pseudo field though? Indeed, my argument for the pseudo-field is mere readability. Compare the four semantically equivalent ways of writing a profile in the test case I added. Cheers
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))