Message ID | 20221027035100.28852-4-maxim.cournoyer@gmail.com |
---|---|
State | New |
Headers | show |
Series | Add --symlink option to 'guix shell'. | expand |
Context | Check | Description |
---|---|---|
cbaines/comparison | success | View comparision |
cbaines/git-branch | success | View Git branch |
cbaines/applying patch | success | |
cbaines/issue | success | View issue |
Hi, That looks like a useful improvement! Some comments below. Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > +@item --symlink=@var{spec} > +@itemx -S @var{spec} > +For containers, create the symbolic links specified by @var{spec}, as > +documented in @ref{pack-symlink-option}. We should refrain from using @ref in sentences (info "(texinfo) @ref"). Instead, I’d write: documented for @command{guix pack} (@pxref{pack-symlink-option}). > (define-module (gnu build install) > + #:use-module ((guix build union) #:select (relative-file-name)) > #:use-module (guix build syscalls) > #:use-module (guix build utils) > #:use-module (guix build store-copy) > @@ -26,6 +27,7 @@ (define-module (gnu build install) > #:use-module (ice-9 match) > #:export (install-boot-config > evaluate-populate-directive > + make-symlink->directives > populate-root-file-system > install-database-and-gc-roots > populate-single-profile-directory > @@ -124,6 +126,22 @@ (define target* (if (string-suffix? "/" target) > directive) > (apply throw args))))) > > +(define (make-symlink->directives directory) > + "Return a procedure that turn symlinks specs into directives that target > +DIRECTORY." > + (match-lambda > + ((source '-> target) > + (let ((target (string-append directory "/" target)) > + (parent (dirname source))) > + ;; Never add a 'directory' directive for "/" so as to preserve its > + ;; ownership and avoid adding the same entries multiple times. > + `(,@(if (string=? parent "/") > + '() > + `((directory ,parent))) > + ;; Note: a relative file name is used for compatibility with > + ;; relocatable packs. > + (,source -> ,(relative-file-name parent target))))))) I think it’s a case where I would refrain from factorizing because this procedure, as shown by the comments and the use of ‘relative-file-name’, is specifically tailored for the needs to ‘guix pack -f tarball’. I’d prefer to have a similar but independently maintained variant of this procedure in (guix scripts environment) to avoid difficulties down the road. > +++ b/guix/scripts/environment.scm > @@ -33,8 +33,10 @@ (define-module (guix scripts environment) > #:use-module ((guix gexp) #:select (lower-object)) > #:use-module (guix scripts) > #:use-module (guix scripts build) > + #:use-module ((guix scripts pack) #:select (symlink-spec-option-parser)) You can turn this into #:autoload so we don’t pay the price when not using ‘--symlink’. > +++ b/tests/guix-shell.sh > @@ -20,6 +20,8 @@ > # Test the 'guix shell' alias. > # > > +. tests/utils.sh > + > guix shell --version > > configdir="t-guix-shell-config-$$" > @@ -32,6 +34,21 @@ export XDG_CONFIG_HOME > > guix shell --bootstrap --pure guile-bootstrap -- guile --version > > +# '--symlink' can only be used with --container. > +! guix shell --bootstrap guile-bootstrap -S /dummy=bin/guile > + > +if has_container_support; then > + # '--symlink' works. > + echo "TESTING SYMLINK IN CONTAINER" > + guix shell --bootstrap guile-bootstrap --container \ > + --symlink=/usr/bin/guile=bin/guile -- \ > + /usr/bin/guile --version This should go to ‘tests/guix-environment-container.sh’, which has all the container-related tests. Thanks, Ludo’.
Hi Ludo! Ludovic Courtès <ludo@gnu.org> writes: > Hi, > > That looks like a useful improvement! Some comments below. Thanks! > Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > >> +@item --symlink=@var{spec} >> +@itemx -S @var{spec} >> +For containers, create the symbolic links specified by @var{spec}, as >> +documented in @ref{pack-symlink-option}. > > We should refrain from using @ref in sentences (info "(texinfo) @ref"). > Instead, I’d write: > > documented for @command{guix pack} (@pxref{pack-symlink-option}). I've heard that from you before, but is there a reason against? I like to know the rationale for doing things a certain way, lest I forget :-). From info '(texinfo) @ref': --8<---------------cut here---------------start------------->8--- 6.6 '@ref' ========== '@ref' is nearly the same as '@xref' except that it does not generate a 'See' in the printed output, just the reference itself. This makes it useful as the last part of a sentence. For example, For more information, @pxref{This}, and @ref{That}. produces in Info: For more information, *note This::, and *note That::. --8<---------------cut here---------------end--------------->8--- >> (define-module (gnu build install) >> + #:use-module ((guix build union) #:select (relative-file-name)) >> #:use-module (guix build syscalls) >> #:use-module (guix build utils) >> #:use-module (guix build store-copy) >> @@ -26,6 +27,7 @@ (define-module (gnu build install) >> #:use-module (ice-9 match) >> #:export (install-boot-config >> evaluate-populate-directive >> + make-symlink->directives >> populate-root-file-system >> install-database-and-gc-roots >> populate-single-profile-directory >> @@ -124,6 +126,22 @@ (define target* (if (string-suffix? "/" target) >> directive) >> (apply throw args))))) >> >> +(define (make-symlink->directives directory) >> + "Return a procedure that turn symlinks specs into directives that target >> +DIRECTORY." >> + (match-lambda >> + ((source '-> target) >> + (let ((target (string-append directory "/" target)) >> + (parent (dirname source))) >> + ;; Never add a 'directory' directive for "/" so as to preserve its >> + ;; ownership and avoid adding the same entries multiple times. >> + `(,@(if (string=? parent "/") >> + '() >> + `((directory ,parent))) >> + ;; Note: a relative file name is used for compatibility with >> + ;; relocatable packs. >> + (,source -> ,(relative-file-name parent target))))))) > > I think it’s a case where I would refrain from factorizing because this > procedure, as shown by the comments and the use of ‘relative-file-name’, > is specifically tailored for the needs to ‘guix pack -f tarball’. > > I’d prefer to have a similar but independently maintained variant of > this procedure in (guix scripts environment) to avoid difficulties down > the road. I considered to duplicate it, but I opted to reuse it in the end because I care that the behavior is exactly the same between the two actions (guix shell --symlink vs guix pack --symlink). If the way we handle this is to be changed in the future, I'd want both to be changed at once, so they remain consistent. Does this make sense? >> +++ b/guix/scripts/environment.scm >> @@ -33,8 +33,10 @@ (define-module (guix scripts environment) >> #:use-module ((guix gexp) #:select (lower-object)) >> #:use-module (guix scripts) >> #:use-module (guix scripts build) >> + #:use-module ((guix scripts pack) #:select (symlink-spec-option-parser)) > > You can turn this into #:autoload so we don’t pay the price when not > using ‘--symlink’. Done! Could Guile simply always use lazy loading (autoload by default)? Otherwise, when is it OK to use autoload and when is it not? >> +++ b/tests/guix-shell.sh >> @@ -20,6 +20,8 @@ >> # Test the 'guix shell' alias. >> # >> >> +. tests/utils.sh >> + >> guix shell --version >> >> configdir="t-guix-shell-config-$$" >> @@ -32,6 +34,21 @@ export XDG_CONFIG_HOME >> >> guix shell --bootstrap --pure guile-bootstrap -- guile --version >> >> +# '--symlink' can only be used with --container. >> +! guix shell --bootstrap guile-bootstrap -S /dummy=bin/guile >> + >> +if has_container_support; then >> + # '--symlink' works. >> + echo "TESTING SYMLINK IN CONTAINER" >> + guix shell --bootstrap guile-bootstrap --container \ >> + --symlink=/usr/bin/guile=bin/guile -- \ >> + /usr/bin/guile --version > > This should go to ‘tests/guix-environment-container.sh’, which has all > the container-related tests. Done, for the "has_container_support" conditional tests. Thanks for taking a peek! Maxim
Hi Maxim! Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: >> We should refrain from using @ref in sentences (info "(texinfo) @ref"). >> Instead, I’d write: >> >> documented for @command{guix pack} (@pxref{pack-symlink-option}). > > I've heard that from you before, but is there a reason against? I like > to know the rationale for doing things a certain way, lest I forget :-). > From info '(texinfo) @ref': It’s right below the bit you quoted: The '@ref' command can tempt writers to express themselves in a manner that is suitable for a printed manual but looks awkward in the Info format. Bear in mind that your audience could be using both the printed and the Info format. For example: […] >>> +(define (make-symlink->directives directory) >>> + "Return a procedure that turn symlinks specs into directives that target >>> +DIRECTORY." >>> + (match-lambda >>> + ((source '-> target) >>> + (let ((target (string-append directory "/" target)) >>> + (parent (dirname source))) >>> + ;; Never add a 'directory' directive for "/" so as to preserve its >>> + ;; ownership and avoid adding the same entries multiple times. >>> + `(,@(if (string=? parent "/") >>> + '() >>> + `((directory ,parent))) >>> + ;; Note: a relative file name is used for compatibility with >>> + ;; relocatable packs. >>> + (,source -> ,(relative-file-name parent target))))))) >> >> I think it’s a case where I would refrain from factorizing because this >> procedure, as shown by the comments and the use of ‘relative-file-name’, >> is specifically tailored for the needs to ‘guix pack -f tarball’. >> >> I’d prefer to have a similar but independently maintained variant of >> this procedure in (guix scripts environment) to avoid difficulties down >> the road. > > I considered to duplicate it, but I opted to reuse it in the end because > I care that the behavior is exactly the same between the two actions > (guix shell --symlink vs guix pack --symlink). If the way we handle > this is to be changed in the future, I'd want both to be changed at > once, so they remain consistent. Does this make sense? They don’t have to be consistent. Use of ‘relative-file-name’ here for example is dictated by the needs of relocatable packs. It doesn’t have to be this way here. I think it’s best to keep separate copies here (they likely won’t be exactly the same). >>> +++ b/guix/scripts/environment.scm >>> @@ -33,8 +33,10 @@ (define-module (guix scripts environment) >>> #:use-module ((guix gexp) #:select (lower-object)) >>> #:use-module (guix scripts) >>> #:use-module (guix scripts build) >>> + #:use-module ((guix scripts pack) #:select (symlink-spec-option-parser)) >> >> You can turn this into #:autoload so we don’t pay the price when not >> using ‘--symlink’. > > Done! Could Guile simply always use lazy loading (autoload by default)? #:select could be synonymous with #:autoload, if that’s what you mean, but in general Guile cannot know whether autoloading is semantically equivalent to eagerly loading: there might be side-effects happening when the top-level of the module runs. > Otherwise, when is it OK to use autoload and when is it not? #:autoload exists as a way to amortize initialization costs and make sure only necessary functionality gets loaded, thereby reducing CPU and memory usage. Only the module user can tell whether #:autoload is appropriate. In general you’d use it for optional functionality that has a non-negligible memory footprint or that would noticeably degrade startup time. Ludo’.
Hi Ludo! Ludovic Courtès <ludo@gnu.org> writes: > Hi Maxim! > > Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > >>> We should refrain from using @ref in sentences (info "(texinfo) @ref"). >>> Instead, I’d write: >>> >>> documented for @command{guix pack} (@pxref{pack-symlink-option}). >> >> I've heard that from you before, but is there a reason against? I like >> to know the rationale for doing things a certain way, lest I forget :-). >> From info '(texinfo) @ref': > > It’s right below the bit you quoted: > > The '@ref' command can tempt writers to express themselves in a > manner that is suitable for a printed manual but looks awkward in the > Info format. Bear in mind that your audience could be using both the > printed and the Info format. For example: […] Yes, and I don't get it :-) --8<---------------cut here---------------start------------->8--- The '@ref' command can tempt writers to express themselves in a manner that is suitable for a printed manual but looks awkward in the Info format. Bear in mind that your audience could be using both the printed and the Info format. For example: Sea surges are described in @ref{Hurricanes}. looks ok in the printed output: Sea surges are described in Section 6.7 [Hurricanes], page 72. but is awkward to read in Info, "note" being a verb: Sea surges are described in *note Hurricanes::. --8<---------------cut here---------------end--------------->8--- I don't see a "note" in the final sentence that should make it awkward? It's lacking a "see " prefix though, which could help to make things a bit clearer, I guess. It looks the same in info as in the pxref example given above: --8<---------------cut here---------------start------------->8--- For example, For more information, @pxref{This}, and @ref{That}. produces in Info: For more information, *note This::, and *note That::. --8<---------------cut here---------------end--------------->8--- I'm also unsure where the "see" comes before That:: above. Is it a mistake in the manual? >>>> +(define (make-symlink->directives directory) >>>> + "Return a procedure that turn symlinks specs into directives that target >>>> +DIRECTORY." >>>> + (match-lambda >>>> + ((source '-> target) >>>> + (let ((target (string-append directory "/" target)) >>>> + (parent (dirname source))) >>>> + ;; Never add a 'directory' directive for "/" so as to preserve its >>>> + ;; ownership and avoid adding the same entries multiple times. >>>> + `(,@(if (string=? parent "/") >>>> + '() >>>> + `((directory ,parent))) >>>> + ;; Note: a relative file name is used for compatibility with >>>> + ;; relocatable packs. >>>> + (,source -> ,(relative-file-name parent target))))))) >>> >>> I think it’s a case where I would refrain from factorizing because this >>> procedure, as shown by the comments and the use of ‘relative-file-name’, >>> is specifically tailored for the needs to ‘guix pack -f tarball’. >>> >>> I’d prefer to have a similar but independently maintained variant of >>> this procedure in (guix scripts environment) to avoid difficulties down >>> the road. >> >> I considered to duplicate it, but I opted to reuse it in the end because >> I care that the behavior is exactly the same between the two actions >> (guix shell --symlink vs guix pack --symlink). If the way we handle >> this is to be changed in the future, I'd want both to be changed at >> once, so they remain consistent. Does this make sense? > > They don’t have to be consistent. Use of ‘relative-file-name’ here for > example is dictated by the needs of relocatable packs. It doesn’t have > to be this way here. > > I think it’s best to keep separate copies here (they likely won’t be > exactly the same). OK, I see you point about relative-file-name not being needed. I'll make the change. >>>> +++ b/guix/scripts/environment.scm >>>> @@ -33,8 +33,10 @@ (define-module (guix scripts environment) >>>> #:use-module ((guix gexp) #:select (lower-object)) >>>> #:use-module (guix scripts) >>>> #:use-module (guix scripts build) >>>> + #:use-module ((guix scripts pack) #:select (symlink-spec-option-parser)) >>> >>> You can turn this into #:autoload so we don’t pay the price when not >>> using ‘--symlink’. >> >> Done! Could Guile simply always use lazy loading (autoload by default)? > > #:select could be synonymous with #:autoload, if that’s what you mean, > but in general Guile cannot know whether autoloading is semantically > equivalent to eagerly loading: there might be side-effects happening > when the top-level of the module runs. Perhaps there could be a strict execution mode where it is assumed that side effects are not used when modules run? That seems a seldom used feature anyway, and could enable making lazy loading of modules the default. >> Otherwise, when is it OK to use autoload and when is it not? > > #:autoload exists as a way to amortize initialization costs and make > sure only necessary functionality gets loaded, thereby reducing CPU and > memory usage. > > Only the module user can tell whether #:autoload is appropriate. In > general you’d use it for optional functionality that has a > non-negligible memory footprint or that would noticeably degrade startup > time. > > Ludo’. Thank you for the explanations and review! I'll send a v3 shortly. -- Maxim
Hello, Maxim Cournoyer <maxim.cournoyer@gmail.com> writes: > Hi Ludo! > > Ludovic Courtès <ludo@gnu.org> writes: > >> Hi Maxim! >> >> Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: >> >>>> We should refrain from using @ref in sentences (info "(texinfo) @ref"). >>>> Instead, I’d write: >>>> >>>> documented for @command{guix pack} (@pxref{pack-symlink-option}). >>> >>> I've heard that from you before, but is there a reason against? I like >>> to know the rationale for doing things a certain way, lest I forget :-). >>> From info '(texinfo) @ref': >> >> It’s right below the bit you quoted: >> >> The '@ref' command can tempt writers to express themselves in a >> manner that is suitable for a printed manual but looks awkward in the >> Info format. Bear in mind that your audience could be using both the >> printed and the Info format. For example: […] > > Yes, and I don't get it :-) To be more concrete, this is what it looks currently: --8<---------------cut here---------------start------------->8--- ‘--symlink=SPEC’ ‘-S SPEC’ For containers, create the symbolic links specified by SPEC, as documented in *note pack-symlink-option::. --8<---------------cut here---------------end--------------->8--- This is what it'd look if I use (see: @pxref ...) instead: --8<---------------cut here---------------start------------->8--- ‘--symlink=SPEC’ ‘-S SPEC’ For containers, create the symbolic links specified by SPEC (see: *note pack-symlink-option::). --8<---------------cut here---------------end--------------->8--- Contrary to what the Texinfo manual says, pxref seems to be the one introducing the awkward "*note" verb in the resulting info.
Hi, Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > Contrary to what the Texinfo manual says, pxref seems to be the one > introducing the awkward "*note" verb in the resulting info. If you read it in Emacs, it looks a bit different; I think info.el adds removes “note” and adds “see” in some cases (e.g., see ‘Info-hide-note-references’). Ludo’.
Hi Maxim, On Wed, 09 Nov 2022 at 21:58, Ludovic Courtès <ludo@gnu.org> wrote: >> +@item --symlink=@var{spec} >> +@itemx -S @var{spec} >> +For containers, create the symbolic links specified by @var{spec}, as >> +documented in @ref{pack-symlink-option}. > > We should refrain from using @ref in sentences (info "(texinfo) @ref"). > Instead, I’d write: > > documented for @command{guix pack} (@pxref{pack-symlink-option}). Well, for what it is worth, I have marked this email [1] by Eli Zaretskii from Emacs. Somehow, the message provides some rules of thumb to write Texinfo. :-) Quoting about cross-reference: 5. Cross-references: As a separate sentence: @xref{Node name}, for the details. In the middle of a sentence ... see @ref{Node name}, for more. In parentheses: Some text (@pxref{Some node}) more text. 1: https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00525.html Cheers, simon
Hi Simon, zimoun <zimon.toutoune@gmail.com> writes: > Hi Maxim, > > On Wed, 09 Nov 2022 at 21:58, Ludovic Courtès <ludo@gnu.org> wrote: > >>> +@item --symlink=@var{spec} >>> +@itemx -S @var{spec} >>> +For containers, create the symbolic links specified by @var{spec}, as >>> +documented in @ref{pack-symlink-option}. >> >> We should refrain from using @ref in sentences (info "(texinfo) @ref"). >> Instead, I’d write: >> >> documented for @command{guix pack} (@pxref{pack-symlink-option}). > > Well, for what it is worth, I have marked this email [1] by Eli > Zaretskii from Emacs. Somehow, the message provides some rules of thumb > to write Texinfo. :-) Quoting about cross-reference: > > 5. Cross-references: > > As a separate sentence: @xref{Node name}, for the details. > In the middle of a sentence ... see @ref{Node name}, for more. > In parentheses: Some text (@pxref{Some node}) more text. > > 1: https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00525.html I like it, it takes the occult out of the equation :-).
diff --git a/doc/guix.texi b/doc/guix.texi index 2f7ab61aec..4bd3c18223 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -49,7 +49,7 @@ Copyright @copyright{} 2017 humanitiesNerd@* Copyright @copyright{} 2017, 2021 Christine Lemmer-Webber@* Copyright @copyright{} 2017, 2018, 2019, 2020, 2021, 2022 Marius Bakke@* Copyright @copyright{} 2017, 2019, 2020, 2022 Hartmut Goebel@* -Copyright @copyright{} 2017, 2019, 2020, 2021 Maxim Cournoyer@* +Copyright @copyright{} 2017, 2019, 2020, 2021, 2022 Maxim Cournoyer@* Copyright @copyright{} 2017–2022 Tobias Geerinckx-Rice@* Copyright @copyright{} 2017 George Clemmer@* Copyright @copyright{} 2017 Andy Wingo@* @@ -6230,6 +6230,12 @@ directory: guix shell --container --expose=$HOME=/exchange guile -- guile @end example +@cindex symbolic links, guix shell +@item --symlink=@var{spec} +@itemx -S @var{spec} +For containers, create the symbolic links specified by @var{spec}, as +documented in @ref{pack-symlink-option}. + @cindex file system hierarchy standard (FHS) @cindex FHS (file system hierarchy standard) @item --emulate-fhs @@ -7022,6 +7028,7 @@ Compress the resulting tarball using @var{tool}---one of @code{gzip}, @code{zstd}, @code{bzip2}, @code{xz}, @code{lzip}, or @code{none} for no compression. +@anchor{pack-symlink-option} @item --symlink=@var{spec} @itemx -S @var{spec} Add the symlinks specified by @var{spec} to the pack. This option can diff --git a/gnu/build/install.scm b/gnu/build/install.scm index 15cc29b2c8..8cf772f3ea 100644 --- a/gnu/build/install.scm +++ b/gnu/build/install.scm @@ -19,6 +19,7 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (gnu build install) + #:use-module ((guix build union) #:select (relative-file-name)) #:use-module (guix build syscalls) #:use-module (guix build utils) #:use-module (guix build store-copy) @@ -26,6 +27,7 @@ (define-module (gnu build install) #:use-module (ice-9 match) #:export (install-boot-config evaluate-populate-directive + make-symlink->directives populate-root-file-system install-database-and-gc-roots populate-single-profile-directory @@ -124,6 +126,22 @@ (define target* (if (string-suffix? "/" target) directive) (apply throw args))))) +(define (make-symlink->directives directory) + "Return a procedure that turn symlinks specs into directives that target +DIRECTORY." + (match-lambda + ((source '-> target) + (let ((target (string-append directory "/" target)) + (parent (dirname source))) + ;; Never add a 'directory' directive for "/" so as to preserve its + ;; ownership and avoid adding the same entries multiple times. + `(,@(if (string=? parent "/") + '() + `((directory ,parent))) + ;; Note: a relative file name is used for compatibility with + ;; relocatable packs. + (,source -> ,(relative-file-name parent target))))))) + (define (directives store) "Return a list of directives to populate the root file system that will host STORE." diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index de9bc8f98d..bd95329c5c 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -33,8 +33,10 @@ (define-module (guix scripts environment) #:use-module ((guix gexp) #:select (lower-object)) #:use-module (guix scripts) #:use-module (guix scripts build) + #:use-module ((guix scripts pack) #:select (symlink-spec-option-parser)) #:use-module (guix transformations) #:autoload (ice-9 ftw) (scandir) + #:use-module (gnu build install) #:autoload (gnu build linux-container) (call-with-container %namespaces user-namespace-supported? unprivileged-user-namespace-supported? @@ -120,6 +122,9 @@ (define (show-environment-options-help) --expose=SPEC for containers, expose read-only host file system according to SPEC")) (display (G_ " + -S, --symlink=SPEC for containers, add symlinks to the profile according + to SPEC, e.g. \"/usr/bin/env=bin/env\".")) + (display (G_ " -v, --verbosity=LEVEL use the given verbosity LEVEL")) (display (G_ " --bootstrap use bootstrap binaries to build the environment"))) @@ -157,6 +162,7 @@ (define (show-help) (define %default-options `((system . ,(%current-system)) (substitutes? . #t) + (symlinks . ()) (offload? . #t) (graft? . #t) (print-build-trace? . #t) @@ -256,6 +262,7 @@ (define %options (alist-cons 'file-system-mapping (specification->file-system-mapping arg #f) result))) + (option '(#\S "symlink") #t #f symlink-spec-option-parser) (option '(#\r "root") #t #f (lambda (opt name arg result) (alist-cons 'gc-root arg result))) @@ -672,7 +679,7 @@ (define* (launch-environment/fork command profile manifest (define* (launch-environment/container #:key command bash user user-mappings profile manifest link-profile? network? map-cwd? emulate-fhs? (setup-hook #f) - (white-list '())) + (symlinks '()) (white-list '())) "Run COMMAND within a container that features the software in PROFILE. Environment variables are set according to the search paths of MANIFEST. The global shell is BASH, a file name for a GNU Bash binary in the store. When @@ -690,6 +697,9 @@ (define* (launch-environment/container #:key command bash user user-mappings LINK-PROFILE? creates a symbolic link from ~/.guix-profile to the environment profile. +SYMLINKS must be a list of (SOURCE -> TARGET) tuples denoting symlinks to be +added to the container. + Preserve environment variables whose name matches the one of the regexps in WHILE-LIST." (define (optional-mapping->fs mapping) @@ -797,6 +807,10 @@ (define fhs-mappings (mkdir-p home-dir) (setenv "HOME" home-dir) + ;; Create symlinks. + (for-each (cut evaluate-populate-directive <> ".") + (append-map (make-symlink->directives profile) symlinks)) + ;; Call an additional setup procedure, if provided. (when setup-hook (setup-hook profile)) @@ -970,6 +984,7 @@ (define (guix-environment* opts) (let* ((pure? (assoc-ref opts 'pure)) (container? (assoc-ref opts 'container?)) (link-prof? (assoc-ref opts 'link-profile?)) + (symlinks (assoc-ref opts 'symlinks)) (network? (assoc-ref opts 'network?)) (no-cwd? (assoc-ref opts 'no-cwd?)) (emulate-fhs? (assoc-ref opts 'emulate-fhs?)) @@ -1010,15 +1025,17 @@ (define-syntax-rule (with-store/maybe store exp ...) (when container? (assert-container-features)) - (when (and (not container?) link-prof?) - (leave (G_ "'--link-profile' cannot be used without '--container'~%"))) - (when (and (not container?) user) - (leave (G_ "'--user' cannot be used without '--container'~%"))) - (when (and (not container?) no-cwd?) - (leave (G_ "--no-cwd cannot be used without '--container'~%"))) - (when (and (not container?) emulate-fhs?) - (leave (G_ "'--emulate-fhs' cannot be used without '--container~%'"))) - + (when (not container?) + (when link-prof? + (leave (G_ "'--link-profile' cannot be used without '--container'~%"))) + (when user + (leave (G_ "'--user' cannot be used without '--container'~%"))) + (when no-cwd? + (leave (G_ "--no-cwd cannot be used without '--container'~%"))) + (when emulate-fhs? + (leave (G_ "'--emulate-fhs' cannot be used without '--container~%'"))) + (when (pair? symlinks) + (leave (G_ "'--symlink' cannot be used without '--container~%'")))) (with-store/maybe store (with-status-verbosity (assoc-ref opts 'verbosity) @@ -1099,6 +1116,7 @@ (define manifest #:network? network? #:map-cwd? (not no-cwd?) #:emulate-fhs? emulate-fhs? + #:symlinks symlinks #:setup-hook (and emulate-fhs? setup-fhs)))) diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm index 06849e4761..e3bddc4274 100644 --- a/guix/scripts/pack.scm +++ b/guix/scripts/pack.scm @@ -61,7 +61,9 @@ (define-module (guix scripts pack) #:use-module (srfi srfi-26) #:use-module (srfi srfi-37) #:use-module (ice-9 match) - #:export (self-contained-tarball + #:export (symlink-spec-option-parser + + self-contained-tarball debian-archive docker-image squashfs-image @@ -160,6 +162,21 @@ (define str (string-join names "-")) ((_) str) ((names ... _) (loop names)))))) +(define (symlink-spec-option-parser opt name arg result) + "A SRFI-37 option parser for the --symlink option." + ;; Note: Using 'string-split' allows us to handle empty + ;; TARGET (as in "/opt/guile=", meaning that /opt/guile is + ;; a symlink to the profile) correctly. + (match (string-split arg (char-set #\=)) + ((source target) + (let ((symlinks (assoc-ref result 'symlinks))) + (alist-cons 'symlinks + `((,source -> ,target) ,@symlinks) + (alist-delete 'symlinks result eq?)))) + (x + (leave (G_ "~a: invalid symlink specification~%") + arg)))) + ;;; ;;; Tarball format. @@ -204,30 +221,15 @@ (define (import-module? module) (use-modules (guix build pack) (guix build store-copy) (guix build utils) - ((guix build union) #:select (relative-file-name)) (gnu build install) (srfi srfi-1) - (srfi srfi-26) - (ice-9 match)) + (srfi srfi-26)) (define %root "root") - (define symlink->directives - ;; Return "populate directives" to make the given symlink and its - ;; parent directories. - (match-lambda - ((source '-> target) - (let ((target (string-append #$profile "/" target)) - (parent (dirname source))) - ;; Never add a 'directory' directive for "/" so as to - ;; preserve its ownership when extracting the archive (see - ;; below), and also because this would lead to adding the - ;; same entries twice in the tarball. - `(,@(if (string=? parent "/") - '() - `((directory ,parent))) - (,source - -> ,(relative-file-name parent target))))))) + ;; Return "populate directives" to make the given symlink and its + ;; parent directories. + (define symlink->directives (make-symlink->directives #$profile)) (define directives ;; Fully-qualified symlinks. @@ -1208,20 +1210,7 @@ (define %options (lambda (opt name arg result) (alist-cons 'compressor (lookup-compressor arg) result))) - (option '(#\S "symlink") #t #f - (lambda (opt name arg result) - ;; Note: Using 'string-split' allows us to handle empty - ;; TARGET (as in "/opt/guile=", meaning that /opt/guile is - ;; a symlink to the profile) correctly. - (match (string-split arg (char-set #\=)) - ((source target) - (let ((symlinks (assoc-ref result 'symlinks))) - (alist-cons 'symlinks - `((,source -> ,target) ,@symlinks) - (alist-delete 'symlinks result eq?)))) - (x - (leave (G_ "~a: invalid symlink specification~%") - arg))))) + (option '(#\S "symlink") #t #f symlink-spec-option-parser) (option '("save-provenance") #f #f (lambda (opt name arg result) (alist-cons 'save-provenance? #t result))) diff --git a/tests/guix-shell.sh b/tests/guix-shell.sh index 9a6b055264..32dd997fe7 100644 --- a/tests/guix-shell.sh +++ b/tests/guix-shell.sh @@ -20,6 +20,8 @@ # Test the 'guix shell' alias. # +. tests/utils.sh + guix shell --version configdir="t-guix-shell-config-$$" @@ -32,6 +34,21 @@ export XDG_CONFIG_HOME guix shell --bootstrap --pure guile-bootstrap -- guile --version +# '--symlink' can only be used with --container. +! guix shell --bootstrap guile-bootstrap -S /dummy=bin/guile + +if has_container_support; then + # '--symlink' works. + echo "TESTING SYMLINK IN CONTAINER" + guix shell --bootstrap guile-bootstrap --container \ + --symlink=/usr/bin/guile=bin/guile -- \ + /usr/bin/guile --version + + # A bad symlink spec causes the command to fail. + ! guix shell --bootstrap -CS bin/guile=/usr/bin/guile guile-bootstrap \ + -- exit +fi + # '--ad-hoc' is a thing of the past. ! guix shell --ad-hoc guile-bootstrap