Message ID | 20211002163834.29583-13-go.wigust@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series | [bug#50967,01/14] tests: Add tests for guix home cli. | expand |
On Sat, Oct 02 2021, Oleg Pykhalov wrote: > * gnu/home/services/configuration.scm (interpose): Include content of files. > (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like > object. I would call it ‘file-like-or-string-or-gexp?’, just ‘files’ doesn’t really make it clear that it should be a “file-like object”. > (serialize-string-or-gexp): Rename to 'serialize-file-or-string-or-gexp'. > (text-config?): Call 'file-or-string-or-gexp?' intead of 'string-or-gexp?'. > * guix/scripts/home/import.scm: > (generate-bash-module+configuration): Don't call slurp-file-gexp. > --- > gnu/home/services/configuration.scm | 14 ++++++++++---- > guix/scripts/home/import.scm | 8 +++----- > 2 files changed, 13 insertions(+), 9 deletions(-) > > diff --git a/gnu/home/services/configuration.scm b/gnu/home/services/configuration.scm > index 5e7743e7d6..39db7a5693 100644 > --- a/gnu/home/services/configuration.scm > +++ b/gnu/home/services/configuration.scm > @@ -59,7 +59,12 @@ DELIMITER interposed LS. Support 'infix and 'suffix GRAMMAR values." > (G_ "The GRAMMAR value must be 'infix or 'suffix, but ~a provided.") > grammar))) > (fold-right (lambda (e acc) > - (cons e > + (cons (if (file-like? e) > + #~(begin > + (use-modules (ice-9 rdelim)) > + (with-fluids ((%default-port-encoding "UTF-8")) > + (with-input-from-file #$e read-string))) > + e) > (if (and (null? acc) (eq? grammar 'infix)) > acc > (cons delimiter acc)))) > @@ -79,11 +84,12 @@ the list result in @code{#t} when applying PRED? on them." > > (define alist? list?) > > -(define (string-or-gexp? sg) (or (string? sg) (gexp? sg))) > -(define (serialize-string-or-gexp field-name val) "") > +(define (file-or-string-or-gexp? fsg) > + (or (string? fsg) (gexp? fsg) (file-like? fsg))) > +(define (serialize-file-or-string-or-gexp field-name val) "") This could defined as ‘empty-serializer’ from (gnu services configuration). > > (define (text-config? config) > - (and (list? config) (every string-or-gexp? config))) > + (and (list? config) (every file-or-string-or-gexp? config))) ‘text-config?’ could be defined as (list-of file-or-string-or-gexp?) > (define (serialize-text-config field-name val) > #~(string-append #$@(interpose val "\n" 'suffix))) > > diff --git a/guix/scripts/home/import.scm b/guix/scripts/home/import.scm > index c977ec3861..611f580e85 100644 > --- a/guix/scripts/home/import.scm > +++ b/guix/scripts/home/import.scm > @@ -46,17 +46,15 @@ > (home-bash-configuration > ,@(if (file-exists? rc) > `((bashrc > - (list (slurp-file-gexp (local-file ,rc))))) > + (list (local-file ,rc)))) > '()) > ,@(if (file-exists? profile) > `((bash-profile > - (list (slurp-file-gexp > - (local-file ,profile))))) > + (list (local-file ,profile)))) > '()) > ,@(if (file-exists? logout) > `((bash-logout > - (list (slurp-file-gexp > - (local-file ,logout))))) > + (list (local-file ,logout)))) > '())))))) > > > -- > 2.33.0
Xinglu Chen <public@yoctocell.xyz> skribis: > On Sat, Oct 02 2021, Oleg Pykhalov wrote: > >> * gnu/home/services/configuration.scm (interpose): Include content of files. >> (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like >> object. > > I would call it ‘file-like-or-string-or-gexp?’, just ‘files’ doesn’t > really make it clear that it should be a “file-like object”. As a matter of API, I would make it monomorphic: accept a file-like object, period. This is what’s done for System services (and polymorphic APIs are rare in general in Guix). ‘plain-file’ and ‘scheme-file’ allow users to “convert” a string or a gexp into a file-like object. WDYT? Ludo’.
On 2021-10-04 16:04, Ludovic Courtès wrote: > Xinglu Chen <public@yoctocell.xyz> skribis: > >> On Sat, Oct 02 2021, Oleg Pykhalov wrote: >> >>> * gnu/home/services/configuration.scm (interpose): Include content of files. >>> (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like >>> object. >> >> I would call it ‘file-like-or-string-or-gexp?’, just ‘files’ doesn’t >> really make it clear that it should be a “file-like object”. > > As a matter of API, I would make it monomorphic: accept a file-like > object, period. This is what’s done for System services (and > polymorphic APIs are rare in general in Guix). At least some of system services are far from ideal, recently I tried to add rtmp section to nginx configuration using nginx system service. I had two options and both does look hacky, I could use extra-content starting with closing curly bracket: --8<---------------cut here---------------start------------->8--- (service nginx-service-type (nginx-configuration (modules (list (file-append nginx-rtmp-module "\ /etc/nginx/modules/ngx_rtmp_module.so"))) (extra-content (format #f "\ } rtmp { server { listen 1935; chunk_size 4096; application live { live on; record off; push rtmp://a.rtmp.youtube.com/live2/~a; push rtmp://diode.zone:1935/live/~a; } } " youtube-key peertube-key)) (server-blocks (list (nginx-server-configuration ;; (locations ;; (list ;; (nginx-location-configuration ;; (uri "/stat") ;; (body '("rtmp_stat all;" ;; "rtmp_stat_stylesheet stat.xsl;"))))) (server-name `(,ip)) (listen '("8088")) (root "/var/www/")))))) --8<---------------cut here---------------end--------------->8--- or use file field of nginx-configuration record and generate the whole configuration myself inside computed-file, loosing all the benifits of other nginx-configuration fields. Personally, I don't find both of these approaches appealing and convenient. Maybe it's an issue of exact system service, but the way the configuration for this service is implemented is getting in the way of the user. > > ‘plain-file’ and ‘scheme-file’ allow users to “convert” a string or a > gexp into a file-like object. > > WDYT? > > Ludo’. > > > Imagine the following use case: I want to create a home service, which accepts a package (zsh plugin) and adds a code for loading this package to zshrc, currently it's implemented like that: https://git.sr.ht/~abcdw/rde/tree/69dd2baf0384c899a4a4f97bdac8bf0b6e499b82/item/gnu/home-services/shellutils.scm#L18 Exteding the service above with `(list zsh-autosuggestions)` will add the following line to zshrc: source /gnu/store/w7d43gk1qszplj9i0rkzqvzz6kp88qfm-zsh-autosuggestions-0.7.0/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh Or the same thing can be done manually by user: --8<---------------cut here---------------start------------->8--- (service home-zsh-service-type (home-zsh-configuration (zshrc (list #~(string-append "source " #$zsh-autosuggestions "/share/zs../..ions.zsh") ;; or "source \\" (file-append zsh-autosuggestions "/share/zs../..ions.zsh"))))) --8<---------------cut here---------------end--------------->8--- gexps returns a string, file-like object returns a path to the file in the store, kinda expected behavior. Both implementations looks quite simple. Now I'll try to reimplement it with file-like objects. The code below is a pseudo code, but should demonstrate the overall concerns I have: --8<---------------cut here---------------start------------->8--- ;; Some generic functions (define get-file-like-object-path (file-like) "Because all file-like object get inserted literally by home services, we need a function, which returns a file, which contains a path to the file." (computed-file "tmp-file" #~#$file-like)) (define fl-append-strings (lst) "Accepts a list of strings and file-like object, reads the content of the file-like objects (to be consistent with behavior of home services configuration)." (define file-like->str (mb-file-like) (if (string? mb-file-like) mb-file-like #~(begin (use-modules (ice-9 rdelim)) (with-fluids ((%default-port-encoding "UTF-8")) (with-input-from-file #$mb-file-like read-string))))) (computed-file "tmp-file" #~(apply string-append '#$(map file-like->str lst)))) ;; A home service, declared in home-environment. (service home-zsh-service-type (home-zsh-configuration (zshrc (list (fl-append-strings (list "source " (get-file-like-object-path zsh-autosuggestions) "/share/zs../..ions.zsh")) ;; or "source \\" (get-file-like-object-path (file-append zsh-autosuggestions "/share/zs../..ions.zsh")))))) --8<---------------cut here---------------end--------------->8--- Here we don't use gexps inside configuration and all file-like objects are "expanded" as their content instead of path in the store. It can work, but looks a little strange and hard to copmose. Perhaps, I miss something and doesn't see the whole picture, but for now expanding file-like objects to their content and throwing out gexps doesn't look appealing to me. BTW, I've skimmed through the paper "Code Staging in GNU Guix" and limitations section, still not sure what your concerns are, I'll try to re-read the paper and your message <87pmvqckws.fsf@gnu.org> one more time a few days later to better understand it. If you have a spare time, please make a simple code snippet, which demonstrates the problem you've mentioned in the message, which will hit the users of home services. It will help me to figure out possible shortcommings and better understand the problem. Ludovic, sorry for spending your time on that, but I really need to understand this thing better. Thank you in advance for hepling on that. Oleg, thank you for working on this patch series, much appreciate)
Hi Andrew, Andrew Tropin <andrew@trop.in> skribis: > On 2021-10-04 16:04, Ludovic Courtès wrote: > >> Xinglu Chen <public@yoctocell.xyz> skribis: >> >>> On Sat, Oct 02 2021, Oleg Pykhalov wrote: >>> >>>> * gnu/home/services/configuration.scm (interpose): Include content of files. >>>> (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like >>>> object. >>> >>> I would call it ‘file-like-or-string-or-gexp?’, just ‘files’ doesn’t >>> really make it clear that it should be a “file-like object”. >> >> As a matter of API, I would make it monomorphic: accept a file-like >> object, period. This is what’s done for System services (and >> polymorphic APIs are rare in general in Guix). > > At least some of system services are far from ideal, recently I tried to > add rtmp section to nginx configuration using nginx system service. I agree that nginx config is problematic: https://issues.guix.gnu.org/37388 But IMO that’s off-topic. :-) > Imagine the following use case: I want to create a home service, which > accepts a package (zsh plugin) and adds a code for loading this package > to zshrc, currently it's implemented like that: > > https://git.sr.ht/~abcdw/rde/tree/69dd2baf0384c899a4a4f97bdac8bf0b6e499b82/item/gnu/home-services/shellutils.scm#L18 > > Exteding the service above with `(list zsh-autosuggestions)` will add > the following line to zshrc: > > source /gnu/store/w7d43gk1qszplj9i0rkzqvzz6kp88qfm-zsh-autosuggestions-0.7.0/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh OK. Then that’s fine: you can have special code that emits those “source” lines in .zshrc while still allowing users to provide their own file-like object for .zshrc lines they want to add. Again, see how ‘torrc’ is generated in ‘tor-service-type’. I’m happy to discuss specific service examples in mode details if you want. Overall, I’m confident Home services don’t require any pattern that’s not already found in one of the many System services. :-) HTH, Ludo’.
On 2021-10-08 09:56, Ludovic Courtès wrote: > Hi Andrew, > > Andrew Tropin <andrew@trop.in> skribis: > >> On 2021-10-04 16:04, Ludovic Courtès wrote: >> >>> Xinglu Chen <public@yoctocell.xyz> skribis: >>> >>>> On Sat, Oct 02 2021, Oleg Pykhalov wrote: >>>> >>>>> * gnu/home/services/configuration.scm (interpose): Include content of files. >>>>> (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like >>>>> object. >>>> >>>> I would call it ‘file-like-or-string-or-gexp?’, just ‘files’ doesn’t >>>> really make it clear that it should be a “file-like object”. >>> >>> As a matter of API, I would make it monomorphic: accept a file-like >>> object, period. This is what’s done for System services (and >>> polymorphic APIs are rare in general in Guix). >> >> At least some of system services are far from ideal, recently I tried to >> add rtmp section to nginx configuration using nginx system service. > > I agree that nginx config is problematic: > > https://issues.guix.gnu.org/37388 > > But IMO that’s off-topic. :-) > Even not taking into account that ngixn-configuration is not ideally implemented, probably it still relevant: 1. Highlights the problem of current service configuration implementation approach with records: we will need to mimic the whole underlying configuration language with records, for some small languages it's possible, but in general it's very thankless job, which also force use to keep an eye on upstream configuration language, possible extensions to it and keep our implementation in sync. In addition to that in most cases provided set of nested records requires destructuring and custom serialization code. Other system services also affected by this issue. 2. Usage of separate config-file fields with file-like object values is problematic: For nginx service it substitutes the whole file, for tor service it will be inserted at the end of the file for service X it will be inserted at the middle. Using a slightly different approach, implemented in many home services we get ultimate configuration flexibility, we don't need to handle existing file as some special case, create a separate field for it and wonder where it should be inserted, when provided. I'll provide more details in a separate thread, but for now just take a look at too implementations of sway services using both approaches: https://notabug.org/jbranso/guix-config/src/master/sway-service.scm#L110 https://git.sr.ht/~abcdw/rde/tree/master/item/gnu/home-services/wm.scm#L33 >> Imagine the following use case: I want to create a home service, which >> accepts a package (zsh plugin) and adds a code for loading this package >> to zshrc, currently it's implemented like that: >> >> https://git.sr.ht/~abcdw/rde/tree/69dd2baf0384c899a4a4f97bdac8bf0b6e499b82/item/gnu/home-services/shellutils.scm#L18 >> >> Exteding the service above with `(list zsh-autosuggestions)` will add >> the following line to zshrc: >> >> source /gnu/store/w7d43gk1qszplj9i0rkzqvzz6kp88qfm-zsh-autosuggestions-0.7.0/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh > > OK. > > Then that’s fine: you can have special code that emits those “source” > lines in .zshrc while still allowing users to provide their own > file-like object for .zshrc lines they want to add. Again, see how > ‘torrc’ is generated in ‘tor-service-type’. From what I understand you want a separate bashrc-file, bash-profile-file and bash-logout-file fields to be present, but where the content of those files should be inserted? At the beginning/end or instead of the rest of configuration? We already can achieve the same result by providing gexp, which will read the content of the file-like object, a very small helper for that (slurp-file-gexp) makes it even easier to do. Such approach is more flexible and doesn't seem much harder. I remember that you had concerns about slurp-file-gexp, but still don't understand what exactly you are concerned about. > > I’m happy to discuss specific service examples in mode details if you > want. Overall, I’m confident Home services don’t require any pattern > that’s not already found in one of the many System services. :-) > > HTH, > Ludo’. I'll write a few examples of service configurations and rationale behind the design descisions for that next week, to make the discussion more practically oriented.
On 2021-10-02 19:38, Oleg Pykhalov wrote: > * gnu/home/services/configuration.scm (interpose): Include content of files. > (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like > object. > (serialize-string-or-gexp): Rename to 'serialize-file-or-string-or-gexp'. > (text-config?): Call 'file-or-string-or-gexp?' intead of 'string-or-gexp?'. > * guix/scripts/home/import.scm: > (generate-bash-module+configuration): Don't call slurp-file-gexp. > --- > gnu/home/services/configuration.scm | 14 ++++++++++---- > guix/scripts/home/import.scm | 8 +++----- > 2 files changed, 13 insertions(+), 9 deletions(-) > > diff --git a/gnu/home/services/configuration.scm b/gnu/home/services/configuration.scm > index 5e7743e7d6..39db7a5693 100644 > --- a/gnu/home/services/configuration.scm > +++ b/gnu/home/services/configuration.scm > @@ -59,7 +59,12 @@ DELIMITER interposed LS. Support 'infix and 'suffix GRAMMAR values." > (G_ "The GRAMMAR value must be 'infix or 'suffix, but ~a provided.") > grammar))) > (fold-right (lambda (e acc) > - (cons e > + (cons (if (file-like? e) > + #~(begin > + (use-modules (ice-9 rdelim)) > + (with-fluids ((%default-port-encoding "UTF-8")) > + (with-input-from-file #$e read-string))) > + e) > (if (and (null? acc) (eq? grammar 'infix)) > acc > (cons delimiter acc)))) > @@ -79,11 +84,12 @@ the list result in @code{#t} when applying PRED? on them." > > (define alist? list?) > > -(define (string-or-gexp? sg) (or (string? sg) (gexp? sg))) > -(define (serialize-string-or-gexp field-name val) "") > +(define (file-or-string-or-gexp? fsg) > + (or (string? fsg) (gexp? fsg) (file-like? fsg))) > +(define (serialize-file-or-string-or-gexp field-name val) "") > > (define (text-config? config) > - (and (list? config) (every string-or-gexp? config))) > + (and (list? config) (every file-or-string-or-gexp? config))) > (define (serialize-text-config field-name val) > #~(string-append #$@(interpose val "\n" 'suffix))) > > diff --git a/guix/scripts/home/import.scm b/guix/scripts/home/import.scm > index c977ec3861..611f580e85 100644 > --- a/guix/scripts/home/import.scm > +++ b/guix/scripts/home/import.scm > @@ -46,17 +46,15 @@ > (home-bash-configuration > ,@(if (file-exists? rc) > `((bashrc > - (list (slurp-file-gexp (local-file ,rc))))) > + (list (local-file ,rc)))) > '()) > ,@(if (file-exists? profile) > `((bash-profile > - (list (slurp-file-gexp > - (local-file ,profile))))) > + (list (local-file ,profile)))) > '()) > ,@(if (file-exists? logout) > `((bash-logout > - (list (slurp-file-gexp > - (local-file ,logout))))) > + (list (local-file ,logout)))) > '())))))) I think this patch requires more discussion and better to keep it outside of this patch series. Skimmed throught other patches, overall LGTM.
On Wed, Oct 06 2021, Andrew Tropin wrote: > Imagine the following use case: I want to create a home service, which > accepts a package (zsh plugin) and adds a code for loading this package > to zshrc, currently it's implemented like that: > > https://git.sr.ht/~abcdw/rde/tree/69dd2baf0384c899a4a4f97bdac8bf0b6e499b82/item/gnu/home-services/shellutils.scm#L18 > > Exteding the service above with `(list zsh-autosuggestions)` will add > the following line to zshrc: > > source /gnu/store/w7d43gk1qszplj9i0rkzqvzz6kp88qfm-zsh-autosuggestions-0.7.0/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh > > Or the same thing can be done manually by user: > > --8<---------------cut here---------------start------------->8--- > (service > home-zsh-service-type > (home-zsh-configuration > (zshrc > (list > #~(string-append "source " #$zsh-autosuggestions "/share/zs../..ions.zsh") > ;; or > "source \\" > (file-append zsh-autosuggestions "/share/zs../..ions.zsh"))))) > --8<---------------cut here---------------end--------------->8--- > > gexps returns a string, file-like object returns a path to the file in > the store, kinda expected behavior. Both implementations looks quite > simple. > > > Now I'll try to reimplement it with file-like objects. The code below > is a pseudo code, but should demonstrate the overall concerns I have: > > --8<---------------cut here---------------start------------->8--- > ;; Some generic functions > (define get-file-like-object-path (file-like) > "Because all file-like object get inserted literally by home services, > we need a function, which returns a file, which contains a path to the > file." > (computed-file > "tmp-file" > #~#$file-like)) > > (define fl-append-strings (lst) > "Accepts a list of strings and file-like object, reads the content of > the file-like objects (to be consistent with behavior of home services > configuration)." > (define file-like->str (mb-file-like) > (if (string? mb-file-like) > mb-file-like > #~(begin > (use-modules (ice-9 rdelim)) > (with-fluids ((%default-port-encoding "UTF-8")) > (with-input-from-file #$mb-file-like read-string))))) > (computed-file > "tmp-file" > #~(apply string-append '#$(map file-like->str lst)))) > > > ;; A home service, declared in home-environment. > (service > home-zsh-service-type > (home-zsh-configuration > (zshrc > (list > (fl-append-strings > (list > "source " > (get-file-like-object-path zsh-autosuggestions) > "/share/zs../..ions.zsh")) > ;; or > "source \\" > (get-file-like-object-path > (file-append zsh-autosuggestions "/share/zs../..ions.zsh")))))) > --8<---------------cut here---------------end--------------->8--- Wouldn’t something like the following work --8<---------------cut here---------------start------------->8--- (service home-zsh-service-type (home-zsh-configuration (zshrc (list (mixed-text-file "zshrc" "source " (file-append zsh-autosuggestions "/share/zsh/...")) (local-file "./some-zshrc"))))) --8<---------------cut here---------------end--------------->8--- and since ‘zshrc’ is already a list of file-like objects, we could implement ‘serialize-text-config’ using something like ‘fl-append-strings’, which would read the contents of the two files and append them. That way users don’t have to deal with ‘fl-append-strings’ or ‘slurp-file-gexp’.
On 2021-10-08 15:45, Xinglu Chen wrote: > On Wed, Oct 06 2021, Andrew Tropin wrote: > >> Imagine the following use case: I want to create a home service, which >> accepts a package (zsh plugin) and adds a code for loading this package >> to zshrc, currently it's implemented like that: >> >> https://git.sr.ht/~abcdw/rde/tree/69dd2baf0384c899a4a4f97bdac8bf0b6e499b82/item/gnu/home-services/shellutils.scm#L18 >> >> Exteding the service above with `(list zsh-autosuggestions)` will add >> the following line to zshrc: >> >> source /gnu/store/w7d43gk1qszplj9i0rkzqvzz6kp88qfm-zsh-autosuggestions-0.7.0/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh >> >> Or the same thing can be done manually by user: >> >> --8<---------------cut here---------------start------------->8--- >> (service >> home-zsh-service-type >> (home-zsh-configuration >> (zshrc >> (list >> #~(string-append "source " #$zsh-autosuggestions "/share/zs../..ions.zsh") >> ;; or >> "source \\" >> (file-append zsh-autosuggestions "/share/zs../..ions.zsh"))))) >> --8<---------------cut here---------------end--------------->8--- >> >> gexps returns a string, file-like object returns a path to the file in >> the store, kinda expected behavior. Both implementations looks quite >> simple. >> >> >> Now I'll try to reimplement it with file-like objects. The code below >> is a pseudo code, but should demonstrate the overall concerns I have: >> >> --8<---------------cut here---------------start------------->8--- >> ;; Some generic functions >> (define get-file-like-object-path (file-like) >> "Because all file-like object get inserted literally by home services, >> we need a function, which returns a file, which contains a path to the >> file." >> (computed-file >> "tmp-file" >> #~#$file-like)) >> >> (define fl-append-strings (lst) >> "Accepts a list of strings and file-like object, reads the content of >> the file-like objects (to be consistent with behavior of home services >> configuration)." >> (define file-like->str (mb-file-like) >> (if (string? mb-file-like) >> mb-file-like >> #~(begin >> (use-modules (ice-9 rdelim)) >> (with-fluids ((%default-port-encoding "UTF-8")) >> (with-input-from-file #$mb-file-like read-string))))) >> (computed-file >> "tmp-file" >> #~(apply string-append '#$(map file-like->str lst)))) >> >> >> ;; A home service, declared in home-environment. >> (service >> home-zsh-service-type >> (home-zsh-configuration >> (zshrc >> (list >> (fl-append-strings >> (list >> "source " >> (get-file-like-object-path zsh-autosuggestions) >> "/share/zs../..ions.zsh")) >> ;; or >> "source \\" >> (get-file-like-object-path >> (file-append zsh-autosuggestions "/share/zs../..ions.zsh")))))) >> --8<---------------cut here---------------end--------------->8--- > > Wouldn’t something like the following work > > --8<---------------cut here---------------start------------->8--- > (service home-zsh-service-type > (home-zsh-configuration > (zshrc > (list (mixed-text-file > "zshrc" > "source " > (file-append zsh-autosuggestions "/share/zsh/...")) ^ place1 > (local-file "./some-zshrc"))))) ^ place2 > --8<---------------cut here---------------end--------------->8--- > > and since ‘zshrc’ is already a list of file-like objects, we could > implement ‘serialize-text-config’ using something like > ‘fl-append-strings’, which would read the contents of the two files and > append them. That way users don’t have to deal with ‘fl-append-strings’ > or ‘slurp-file-gexp’. Yep, it looks much better than what I was trying to prototype. Still feels inconsistent that file-like object in place1 will be evaluated to the path in the store, but in place2 to the content of the file.
Hi Andrew, Preamble: Guix Home is now committed and there are bug reports coming in. To me, that means our discussion needs to be focused on addressing specific issues; we’re not going to redesign Guix services in this thread. Andrew Tropin <andrew@trop.in> skribis: [...] >> Then that’s fine: you can have special code that emits those “source” >> lines in .zshrc while still allowing users to provide their own >> file-like object for .zshrc lines they want to add. Again, see how >> ‘torrc’ is generated in ‘tor-service-type’. > > From what I understand you want a separate bashrc-file, > bash-profile-file and bash-logout-file fields to be present, but where > the content of those files should be inserted? At the beginning/end or > instead of the rest of configuration? > > We already can achieve the same result by providing gexp, which will > read the content of the file-like object, a very small helper for that > (slurp-file-gexp) makes it even easier to do. Such approach is more > flexible and doesn't seem much harder. > > I remember that you had concerns about slurp-file-gexp, but still don't > understand what exactly you are concerned about. Let me restate my concerns: 1. Users are unlikely to fathom what this does, given the name. It will end up in user configurations, yet: “slurp”? “gexp”? 2. ‘slurp-file-gexp’ returns code, as a gexp. Depending on the place where that gexp is inserted, it may or may not work. Consider: (define (foo x) #~(frob '(#$x))) (foo (slurp-file-gexp …)) ;d’oh! 3. Use of ‘slurp-file-gexp’ and gexps in configuration records is not consistent with the rest of the service APIs (and I think we can humbly recognize that those APIs have been doing the job for a while already.) Let’s just to the (call-with-input-file file get-string-all) dance in places where it’s needed rather than let users call ‘slurp-file-gexp’. This is roughly what the ‘tor-service-type’ example I gave does. > I'll write a few examples of service configurations and rationale behind > the design descisions for that next week, to make the discussion more > practically oriented. People are starting to use the tool and to report bugs. So, unfortunately, we have to sort out interface issues quickly now. If some of the things being discussed turn out to be too complex to address under those time constraints, we can consider taking them out until we have a better idea on how to address them. How does that sound? Thanks, Ludo’.
On 2021-10-02 19:38, Oleg Pykhalov wrote: > * gnu/home/services/configuration.scm (interpose): Include content of files. > (string-or-gexp?): Rename to 'file-or-string-or-gexp?' and check for file-like > object. > (serialize-string-or-gexp): Rename to 'serialize-file-or-string-or-gexp'. > (text-config?): Call 'file-or-string-or-gexp?' intead of 'string-or-gexp?'. > * guix/scripts/home/import.scm: > (generate-bash-module+configuration): Don't call slurp-file-gexp. > --- > gnu/home/services/configuration.scm | 14 ++++++++++---- > guix/scripts/home/import.scm | 8 +++----- > 2 files changed, 13 insertions(+), 9 deletions(-) > > diff --git a/gnu/home/services/configuration.scm b/gnu/home/services/configuration.scm > index 5e7743e7d6..39db7a5693 100644 > --- a/gnu/home/services/configuration.scm > +++ b/gnu/home/services/configuration.scm > @@ -59,7 +59,12 @@ DELIMITER interposed LS. Support 'infix and 'suffix GRAMMAR values." > (G_ "The GRAMMAR value must be 'infix or 'suffix, but ~a provided.") > grammar))) > (fold-right (lambda (e acc) > - (cons e > + (cons (if (file-like? e) > + #~(begin > + (use-modules (ice-9 rdelim)) > + (with-fluids ((%default-port-encoding "UTF-8")) > + (with-input-from-file #$e read-string))) This transformation should not be a part of interpose function, interpose does know nothing about elements type and doesn't have to know. This addition is semantically incorrect and also contradictionary to docstring. It also breaks downstream channels. The version of change in master is different, it doesn't even check element type. I'm strongly against this change. If it necessary to make transformation of elements of the list it should be done outside of interpose. > + e) > (if (and (null? acc) (eq? grammar 'infix)) > acc > (cons delimiter acc)))) > @@ -79,11 +84,12 @@ the list result in @code{#t} when applying PRED? on them." > > (define alist? list?) > > -(define (string-or-gexp? sg) (or (string? sg) (gexp? sg))) > -(define (serialize-string-or-gexp field-name val) "") > +(define (file-or-string-or-gexp? fsg) > + (or (string? fsg) (gexp? fsg) (file-like? fsg))) > +(define (serialize-file-or-string-or-gexp field-name val) "") > > (define (text-config? config) > - (and (list? config) (every string-or-gexp? config))) > + (and (list? config) (every file-or-string-or-gexp? config))) > (define (serialize-text-config field-name val) > #~(string-append #$@(interpose val "\n" 'suffix))) > > diff --git a/guix/scripts/home/import.scm b/guix/scripts/home/import.scm > index c977ec3861..611f580e85 100644 > --- a/guix/scripts/home/import.scm > +++ b/guix/scripts/home/import.scm > @@ -46,17 +46,15 @@ > (home-bash-configuration > ,@(if (file-exists? rc) > `((bashrc > - (list (slurp-file-gexp (local-file ,rc))))) > + (list (local-file ,rc)))) > '()) > ,@(if (file-exists? profile) > `((bash-profile > - (list (slurp-file-gexp > - (local-file ,profile))))) > + (list (local-file ,profile)))) > '()) > ,@(if (file-exists? logout) > `((bash-logout > - (list (slurp-file-gexp > - (local-file ,logout))))) > + (list (local-file ,logout)))) > '()))))))
On 2021-10-09 15:34, Ludovic Courtès wrote: > Hi Andrew, > > Preamble: Guix Home is now committed and there are bug reports coming > in. To me, that means our discussion needs to be focused on addressing > specific issues; we’re not going to redesign Guix services in this > thread. > > Andrew Tropin <andrew@trop.in> skribis: > > [...] > >>> Then that’s fine: you can have special code that emits those “source” >>> lines in .zshrc while still allowing users to provide their own >>> file-like object for .zshrc lines they want to add. Again, see how >>> ‘torrc’ is generated in ‘tor-service-type’. >> >> From what I understand you want a separate bashrc-file, >> bash-profile-file and bash-logout-file fields to be present, but where >> the content of those files should be inserted? At the beginning/end or >> instead of the rest of configuration? >> >> We already can achieve the same result by providing gexp, which will >> read the content of the file-like object, a very small helper for that >> (slurp-file-gexp) makes it even easier to do. Such approach is more >> flexible and doesn't seem much harder. >> >> I remember that you had concerns about slurp-file-gexp, but still don't >> understand what exactly you are concerned about. > > Let me restate my concerns: > > 1. Users are unlikely to fathom what this does, given the name. It > will end up in user configurations, yet: “slurp”? “gexp”? Sounds like a naming conecrn, I brought "slurp" word from clojure lang, but we can call it whatever sounds better for guile community generate-read-whole-file-gexp or anything else. Actually, we don't even need to have this wrapper to be present, just allow people to do #~(call-with-input-file file-like-object get-string-all) > > 2. ‘slurp-file-gexp’ returns code, as a gexp. Depending on the place > where that gexp is inserted, it may or may not work. Consider: > > (define (foo x) > #~(frob '(#$x))) > > (foo (slurp-file-gexp …)) ;d’oh! Yep, users can make mistakes, but it's not a technical problem, also, I see it quite unlikely to happen according to my experience supporting Guix Home users. > > 3. Use of ‘slurp-file-gexp’ and gexps in configuration records is not > consistent with the rest of the service APIs (and I think we can > humbly recognize that those APIs have been doing the job for a > while already.) It's not actually true, there are system services, which accept a list of strings/gexps and state it in the documentation, some of them do it in a less exlicit way, but still do, I found that trick looking at system service and made it an explicit pattern for home services. I tried to extract and follow patterns from system services, but found them quite inconsistent, so I took a few of them and wrote a few on my own. To name a few: extra-options @ alsa-configuration extra-config @ nix-configuration extra-config @ xorg-configuration extra-content @ nginx-configuration extra-config @ httpd-config-file contents @ httpd-virtualhost To make guix services configurations consistent (at least new ones) I think it would be cool to have a `Writing Service Configuration Guideline` section. I can share the design descisions I've made for home services configurations and after a discussion it can end up in a manual section giving a clean guideline, reducing subjective preferences and increasing consistency. If you are interested. > > Let’s just to the (call-with-input-file file get-string-all) dance in > places where it’s needed rather than let users call ‘slurp-file-gexp’. > This is roughly what the ‘tor-service-type’ example I gave does. > >> I'll write a few examples of service configurations and rationale behind >> the design descisions for that next week, to make the discussion more >> practically oriented. > > People are starting to use the tool and to report bugs. So, > unfortunately, we have to sort out interface issues quickly now. > > If some of the things being discussed turn out to be too complex to > address under those time constraints, we can consider taking them out > until we have a better idea on how to address them. > > How does that sound? > > Thanks, > Ludo’.
diff --git a/gnu/home/services/configuration.scm b/gnu/home/services/configuration.scm index 5e7743e7d6..39db7a5693 100644 --- a/gnu/home/services/configuration.scm +++ b/gnu/home/services/configuration.scm @@ -59,7 +59,12 @@ DELIMITER interposed LS. Support 'infix and 'suffix GRAMMAR values." (G_ "The GRAMMAR value must be 'infix or 'suffix, but ~a provided.") grammar))) (fold-right (lambda (e acc) - (cons e + (cons (if (file-like? e) + #~(begin + (use-modules (ice-9 rdelim)) + (with-fluids ((%default-port-encoding "UTF-8")) + (with-input-from-file #$e read-string))) + e) (if (and (null? acc) (eq? grammar 'infix)) acc (cons delimiter acc)))) @@ -79,11 +84,12 @@ the list result in @code{#t} when applying PRED? on them." (define alist? list?) -(define (string-or-gexp? sg) (or (string? sg) (gexp? sg))) -(define (serialize-string-or-gexp field-name val) "") +(define (file-or-string-or-gexp? fsg) + (or (string? fsg) (gexp? fsg) (file-like? fsg))) +(define (serialize-file-or-string-or-gexp field-name val) "") (define (text-config? config) - (and (list? config) (every string-or-gexp? config))) + (and (list? config) (every file-or-string-or-gexp? config))) (define (serialize-text-config field-name val) #~(string-append #$@(interpose val "\n" 'suffix))) diff --git a/guix/scripts/home/import.scm b/guix/scripts/home/import.scm index c977ec3861..611f580e85 100644 --- a/guix/scripts/home/import.scm +++ b/guix/scripts/home/import.scm @@ -46,17 +46,15 @@ (home-bash-configuration ,@(if (file-exists? rc) `((bashrc - (list (slurp-file-gexp (local-file ,rc))))) + (list (local-file ,rc)))) '()) ,@(if (file-exists? profile) `((bash-profile - (list (slurp-file-gexp - (local-file ,profile))))) + (list (local-file ,profile)))) '()) ,@(if (file-exists? logout) `((bash-logout - (list (slurp-file-gexp - (local-file ,logout))))) + (list (local-file ,logout)))) '()))))))