From 96c747cb29c0b762c8a2999a3dcc16085efd3e46 Mon Sep 17 00:00:00 2001 From: Tobias Geerinckx-Rice Date: Tue, 19 Oct 2021 23:36:57 +0200 Subject: doc: Fix typo. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc/guix.texi (Invoking guix system, Invoking guix home): Fix ‘are […] two month old’ typo. --- doc/guix.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index a49abc0554..63bb22764a 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -33901,7 +33901,7 @@ guix system delete-generations @end example You can also select the generations you want to delete. The example below -deletes all the system generations that are more than two month old: +deletes all the system generations that are more than two months old: @example guix system delete-generations 2m @@ -36059,7 +36059,7 @@ guix home delete-generations @end example You can also select the generations you want to delete. The example below -deletes all the home generations that are more than two month old: +deletes all the home generations that are more than two months old: @example guix home delete-generations 2m -- cgit v1.2.3 From 1ea032fb5fc8dd6f7a10e5bc705e526d25fbe1b4 Mon Sep 17 00:00:00 2001 From: Jacob Adams Date: Sun, 26 Sep 2021 13:31:31 -0400 Subject: services: rsync: support binding rsync to a specific IP address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/rsync.scm ()[address]: New field. (rsync-config-file): Honor it. * doc/guix.texi (Networking Services): Document new address rsync configuration option. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 4 ++++ gnu/services/rsync.scm | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 63bb22764a..b1a1e71055 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -17158,6 +17158,10 @@ Data type representing the configuration for @code{rsync-service}. @item @code{package} (default: @var{rsync}) @code{rsync} package to use. +@item @code{address} (default: @code{#f}) +IP address on which @command{rsync} listens for incoming connections. +If unspecified, it defaults to listening on all available addresses. + @item @code{port-number} (default: @code{873}) TCP port on which @command{rsync} listens for incoming connections. If port is less than @code{1024} @command{rsync} needs to be started as the diff --git a/gnu/services/rsync.scm b/gnu/services/rsync.scm index 6c117bbda4..59faed78f6 100644 --- a/gnu/services/rsync.scm +++ b/gnu/services/rsync.scm @@ -45,6 +45,8 @@ rsync-configuration? (package rsync-configuration-package ; package (default rsync)) + (address rsync-configuration-address ; string | #f + (default #f)) (port-number rsync-configuration-port-number ; integer (default 873)) (pid-file rsync-configuration-pid-file ; string @@ -110,7 +112,7 @@ (define rsync-config-file ;; Return the rsync configuration file corresponding to CONFIG. (match-lambda - (($ package port-number pid-file lock-file log-file + (($ package address port-number pid-file lock-file log-file use-chroot? share-path share-comment read-only? timeout user group uid gid) (if (not (string=? user "root")) @@ -132,6 +134,7 @@ "pid file = " pid-file "\n" "lock file = " lock-file "\n" "log file = " log-file "\n" + (if address (string-append "address = " address "\n") "") "port = " (number->string port-number) "\n" "use chroot = " (if use-chroot? "true" "false") "\n" (if uid (string-append "uid = " uid "\n") "") -- cgit v1.2.3 From fb368f4e760777e399aa58b08b89df1832fda8ba Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 1 Oct 2021 10:49:22 +0200 Subject: packages: Add 'package-development-inputs'. * guix/packages.scm (package-development-inputs): New procedure. * guix/scripts/environment.scm (package-environment-inputs): Use it. * tests/packages.scm ("package-development-inputs") ("package-development-inputs, cross-compilation"): New tests. * doc/guix.texi (package Reference): Document it. --- doc/guix.texi | 41 +++++++++++++++++++++++++++++++++++++++++ guix/packages.scm | 10 ++++++++++ guix/scripts/environment.scm | 2 +- tests/packages.scm | 14 ++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index b1a1e71055..31b8cd7069 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -6848,6 +6848,47 @@ cross-compiling: It is an error to refer to @code{this-package} outside a package definition. @end deffn +@cindex development inputs, of a package +@cindex implicit inputs, of a package +Sometimes you will want to obtain the list of inputs needed to +@emph{develop} a package---all the inputs that are visible when the +package is compiled. This is what the @code{package-development-inputs} +procedure returns. + +@deffn {Scheme Procedure} package-development-inputs @var{package} @ + [@var{system}] [#:target #f] +Return the list of inputs required by @var{package} for development +purposes on @var{system}. When @var{target} is true, return the inputs +needed to cross-compile @var{package} from @var{system} to +@var{triplet}, where @var{triplet} is a triplet such as +@code{"aarch64-linux-gnu"}. + +Note that the result includes both explicit inputs and implicit +inputs---inputs automatically added by the build system (@pxref{Build +Systems}). Let us take the @code{hello} package to illustrate that: + +@lisp +(use-modules (gnu packages base) (guix packages)) + +hello +@result{} # + +(package-direct-inputs hello) +@result{} () + +(package-development-inputs hello) +@result{} (("source" @dots{}) ("tar" #) @dots{}) +@end lisp + +In this example, @code{package-direct-inputs} returns the empty list, +because @code{hello} has zero explicit dependencies. Conversely, +@code{package-development-inputs} includes inputs implicitly added by +@code{gnu-build-system} that are required to build @code{hello}: tar, +gzip, GCC, libc, Bash, and more. To visualize it, @command{guix graph +hello} would show you explicit inputs, whereas @command{guix graph -t +bag hello} would include implicit inputs (@pxref{Invoking guix graph}). +@end deffn + Because packages are regular Scheme objects that capture a complete dependency graph and associated build procedures, it is often useful to write procedures that take a package and return a modified version diff --git a/guix/packages.scm b/guix/packages.scm index e5a9d08bce..b99689b9a4 100644 --- a/guix/packages.scm +++ b/guix/packages.scm @@ -153,6 +153,7 @@ bag-transitive-host-inputs bag-transitive-build-inputs bag-transitive-target-inputs + package-development-inputs package-closure default-guile @@ -1070,6 +1071,15 @@ dependencies are known to build on SYSTEM." (%current-system (bag-system bag))) (transitive-inputs (bag-target-inputs bag)))) +(define* (package-development-inputs package + #:optional (system (%current-system)) + #:key target) + "Return the list of inputs required by PACKAGE for development purposes on +SYSTEM. When TARGET is true, return the inputs needed to cross-compile +PACKAGE from SYSTEM to TRIPLET, where TRIPLET is a triplet such as +\"aarch64-linux-gnu\"." + (bag-transitive-inputs (package->bag package system target))) + (define* (package-closure packages #:key (system (%current-system))) "Return the closure of PACKAGES on SYSTEM--i.e., PACKAGES and the list of packages they depend on, recursively." diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index 6958bd6238..418f11c37e 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -82,7 +82,7 @@ package." packages for PACKAGE." ;; Remove non-package inputs such as origin records. (filter-map input->manifest-entry - (bag-transitive-inputs (package->bag package)))) + (package-development-inputs package))) (define (show-help) (display (G_ "Usage: guix environment [OPTION]... PACKAGE... [-- COMMAND...] diff --git a/tests/packages.scm b/tests/packages.scm index 3756877270..266b5aeb7a 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -353,6 +353,20 @@ (package-transitive-supported-systems d) (package-transitive-supported-systems e)))) +(test-assert "package-development-inputs" + ;; Note: Due to propagated inputs, 'package-development-inputs' returns a + ;; couple more inputs, such as 'linux-libre-headers'. + (lset<= equal? + `(("source" ,(package-source hello)) ,@(standard-packages)) + (package-development-inputs hello))) + +(test-assert "package-development-inputs, cross-compilation" + (lset<= equal? + `(("source" ,(package-source hello)) + ,@(standard-cross-packages "mips64el-linux-gnu" 'host) + ,@(standard-cross-packages "mips64el-linux-gnu" 'target)) + (package-development-inputs hello #:target "mips64el-linux-gnu"))) + (test-assert "package-closure" (let-syntax ((dummy-package/no-implicit (syntax-rules () -- cgit v1.2.3 From 23f99f1a299ed0e19d926a0f719980b3c151c9c0 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 1 Oct 2021 11:14:58 +0200 Subject: profiles: Add 'package->development-manifest'. * guix/profiles.scm (package->development-manifest): New procedure. * guix/scripts/environment.scm (input->manifest-entry) (package-environment-inputs): Remove. * guix/scripts/environment.scm (options/resolve-packages): Use 'package->development-manifest' instead of 'package-environment-inputs'. * tests/profiles.scm ("package->development-manifest"): New test. --- doc/guix.texi | 11 +++++++++++ guix/profiles.scm | 19 +++++++++++++++++++ guix/scripts/environment.scm | 27 +++++---------------------- tests/profiles.scm | 7 +++++++ 4 files changed, 42 insertions(+), 22 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 31b8cd7069..37d31d5fa9 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -3341,6 +3341,17 @@ objects, like this: '("emacs" "guile@@2.2" "guile@@2.2:debug")) @end lisp +@findex package->development-manifest +You might also want to create a manifest for all the dependencies of a +package, rather than the package itself: + +@lisp +(package->development-manifest (specification->package "emacs")) +@end lisp + +The example above gives you all the software required to develop Emacs, +similar to what @command{guix environment emacs} provides. + @xref{export-manifest, @option{--export-manifest}}, to learn how to obtain a manifest file from an existing profile. diff --git a/guix/profiles.scm b/guix/profiles.scm index 2486f91d09..9f30349c69 100644 --- a/guix/profiles.scm +++ b/guix/profiles.scm @@ -124,6 +124,7 @@ profile-manifest package->manifest-entry + package->development-manifest packages->manifest ca-certificate-bundle %default-profile-hooks @@ -400,6 +401,24 @@ file name." (properties properties)))) entry)) +(define* (package->development-manifest package + #:optional + (system (%current-system)) + #:key target) + "Return a manifest for the \"development inputs\" of PACKAGE for SYSTEM, +optionally when cross-compiling to TARGET. Development inputs include both +explicit and implicit inputs of PACKAGE." + (manifest + (filter-map (match-lambda + ((label (? package? package)) + (package->manifest-entry package)) + ((label (? package? package) output) + (package->manifest-entry package output)) + ;; TODO: Support . + (_ + #f)) + (package-development-inputs package system #:target target)))) + (define (packages->manifest packages) "Return a list of manifest entries, one for each item listed in PACKAGES. Elements of PACKAGES can be either package objects or package/string tuples diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index 418f11c37e..54f48a7482 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -66,24 +66,6 @@ do not augment existing environment variables with additional search paths." (newline))) (profile-search-paths profile manifest))) -(define (input->manifest-entry input) - "Return a manifest entry for INPUT, or #f if INPUT does not correspond to a -package." - (match input - ((_ (? package? package)) - (package->manifest-entry package)) - ((_ (? package? package) output) - (package->manifest-entry package output)) - (_ - #f))) - -(define (package-environment-inputs package) - "Return a list of manifest entries corresponding to the transitive input -packages for PACKAGE." - ;; Remove non-package inputs such as origin records. - (filter-map input->manifest-entry - (package-development-inputs package))) - (define (show-help) (display (G_ "Usage: guix environment [OPTION]... PACKAGE... [-- COMMAND...] Build an environment that includes the dependencies of PACKAGE and execute @@ -297,11 +279,11 @@ for the corresponding packages." ((? package? package) (if (eq? mode 'ad-hoc-package) (list (package->manifest-entry* package)) - (package-environment-inputs package))) + (manifest-entries (package->development-manifest package)))) (((? package? package) (? string? output)) (if (eq? mode 'ad-hoc-package) (list (package->manifest-entry* package output)) - (package-environment-inputs package))) + (manifest-entries (package->development-manifest package)))) ((lst ...) (append-map (cut packages->outputs <> mode) lst)))) @@ -313,8 +295,9 @@ for the corresponding packages." (specification->package+output spec))) (list (package->manifest-entry* package output)))) (('package 'package (? string? spec)) - (package-environment-inputs - (transform (specification->package+output spec)))) + (manifest-entries + (package->development-manifest + (transform (specification->package+output spec))))) (('expression mode str) ;; Add all the outputs of the package STR evaluates to. (packages->outputs (read/eval str) mode)) diff --git a/tests/profiles.scm b/tests/profiles.scm index 06a0387221..cac5b73347 100644 --- a/tests/profiles.scm +++ b/tests/profiles.scm @@ -265,6 +265,13 @@ (manifest-transaction-removal-candidate? guile-2.0.9 t) (null? install) (null? downgrade) (null? upgrade))))) +(test-assert "package->development-manifest" + (let ((manifest (package->development-manifest packages:hello))) + (every (lambda (name) + (manifest-installed? manifest + (manifest-pattern (name name)))) + '("gcc" "binutils" "glibc" "coreutils" "grep" "sed")))) + (test-assertm "profile-derivation" (mlet* %store-monad ((entry -> (package->manifest-entry %bootstrap-guile)) -- cgit v1.2.3 From 80edb7df6586464aa40e84e103f0045452de95db Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 1 Oct 2021 15:19:54 +0200 Subject: Add 'guix shell'. * guix/scripts/shell.scm, tests/guix-shell.sh: New files. * Makefile.am (MODULES): Add 'shell.scm'. (SH_TESTS): Add 'tests/guix-shell.sh'. * guix/scripts/environment.scm (show-environment-options-help): New procedure. (show-help): Use it. (guix-environment*): New procedure. (guix-environment): Use it. * po/guix/POTFILES.in: Add it. * doc/guix.texi (Features): Refer to "guix shell" (Invoking guix package): Likewise. (Development): Likewise. (Invoking guix shell): New node. (Invoking guix environment): Add deprecation warning. (Debugging Build Failures): Use 'guix shell' in examples. (Invoking guix container): Refer to 'guix shell'. (Invoking guix processes, Virtualization Services): Adjust examples to use 'guix shell'. * doc/contributing.texi (Building from Git): Refer to 'guix shell'. * etc/completion/bash/guix: Handle "shell". --- Makefile.am | 2 + doc/contributing.texi | 8 +- doc/guix.texi | 368 ++++++++++++++++++++++++++++++++++++++++--- etc/completion/bash/guix | 6 +- guix/scripts/environment.scm | 52 ++++-- guix/scripts/shell.scm | 135 ++++++++++++++++ po/guix/POTFILES.in | 1 + tests/guix-shell.sh | 54 +++++++ 8 files changed, 579 insertions(+), 47 deletions(-) create mode 100644 guix/scripts/shell.scm create mode 100644 tests/guix-shell.sh (limited to 'doc/guix.texi') diff --git a/Makefile.am b/Makefile.am index 41ec19eb89..239387c2f4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -316,6 +316,7 @@ MODULES = \ guix/scripts/import/stackage.scm \ guix/scripts/import/texlive.scm \ guix/scripts/environment.scm \ + guix/scripts/shell.scm \ guix/scripts/publish.scm \ guix/scripts/edit.scm \ guix/scripts/size.scm \ @@ -552,6 +553,7 @@ SH_TESTS = \ tests/guix-authenticate.sh \ tests/guix-environment.sh \ tests/guix-environment-container.sh \ + tests/guix-shell.sh \ tests/guix-graph.sh \ tests/guix-describe.sh \ tests/guix-repl.sh \ diff --git a/doc/contributing.texi b/doc/contributing.texi index 76ab913b0d..db0f836157 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -73,10 +73,10 @@ all the dependencies and appropriate environment variables are set up to hack on Guix: @example -guix environment guix --pure +guix shell -D guix --pure @end example -@xref{Invoking guix environment}, for more information on that command. +@xref{Invoking guix shell}, for more information on that command. If you are unable to use Guix when building Guix from a checkout, the following are the required packages in addition to those mentioned in the @@ -92,10 +92,10 @@ installation instructions (@pxref{Requirements}). @end itemize On Guix, extra dependencies can be added by instead running @command{guix -environment} with @option{--ad-hoc}: +shell}: @example -guix environment guix --pure --ad-hoc help2man git strace +guix shell -D guix help2man git strace --pure @end example Run @command{./bootstrap} to generate the build system infrastructure diff --git a/doc/guix.texi b/doc/guix.texi index 37d31d5fa9..f5bfb59229 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -119,6 +119,7 @@ Documentation License''. @dircategory Software development @direntry +* guix shell: (guix)Invoking guix shell. Creating software environments. * guix environment: (guix)Invoking guix environment. Building development environments with Guix. * guix build: (guix)Invoking guix build. Building packages. * guix pack: (guix)Invoking guix pack. Creating binary bundles. @@ -262,6 +263,7 @@ Channels Development +* Invoking guix shell:: Spawning one-off software environments. * Invoking guix environment:: Setting up development environments. * Invoking guix pack:: Creating software bundles. * The GCC toolchain:: Working with languages supported by GCC. @@ -3067,10 +3069,10 @@ substitutes: they can force a local build and @emph{challenge} providers (@pxref{Invoking guix challenge}). Control over the build environment is a feature that is also useful for -developers. The @command{guix environment} command allows developers of +developers. The @command{guix shell} command allows developers of a package to quickly set up the right development environment for their package, without having to manually install the dependencies of the -package into their profile (@pxref{Invoking guix environment}). +package into their profile (@pxref{Invoking guix shell}). @cindex replication, of software environments @cindex provenance tracking, of software artifacts @@ -3234,7 +3236,7 @@ As an example, @var{file} might contain a definition like this Developers may find it useful to include such a @file{guix.scm} file in the root of their project source tree that can be used to test development snapshots and create reproducible development environments -(@pxref{Invoking guix environment}). +(@pxref{Invoking guix shell}). The @var{file} may also contain a JSON representation of one or more package definitions. Running @code{guix package -f} on @@ -5559,31 +5561,352 @@ If you are a software developer, Guix provides tools that you should find helpful---independently of the language you're developing in. This is what this chapter is about. -The @command{guix environment} command provides a convenient way to set up -@dfn{development environments} containing all the dependencies and tools -necessary to work on the software package of your choice. The @command{guix +The @command{guix shell} command provides a convenient way to set up +one-off software environments, be it for development purposes or to run +a command without installing it in your profile. The @command{guix pack} command allows you to create @dfn{application bundles} that can be easily distributed to users who do not run Guix. @menu +* Invoking guix shell:: Spawning one-off software environments. * Invoking guix environment:: Setting up development environments. * Invoking guix pack:: Creating software bundles. * The GCC toolchain:: Working with languages supported by GCC. * Invoking guix git authenticate:: Authenticating Git repositories. @end menu -@node Invoking guix environment -@section Invoking @command{guix environment} +@node Invoking guix shell +@section Invoking @command{guix shell} @cindex reproducible build environments @cindex development environments @cindex @command{guix environment} @cindex environment, package build environment -The purpose of @command{guix environment} is to assist hackers in -creating reproducible development environments without polluting their -package profile. The @command{guix environment} tool takes one or more -packages, builds all of their inputs, and creates a shell -environment to use them. +The purpose of @command{guix shell} is to make it easy to create one-off +software environments, without changing one's profile. It is typically +used to create development environments; it is also a convenient way to +run applications without ``polluting'' your profile. + +@quotation Note +The @command{guix shell} command was recently introduced to supersede +@command{guix environment} (@pxref{Invoking guix environment}). If you +are familiar with @command{guix environment}, you will notice that it is +similar but also---we hope!---more convenient. +@end quotation + +The general syntax is: + +@example +guix shell [@var{options}] [@var{package}@dots{}] +@end example + +The following example creates an environment containing Python and NumPy, +building or downloading any missing package, and runs the +@command{python3} command in that environment: + +@example +guix shell python python-numpy -- python3 +@end example + +Development environments can be created as in the example below, which +spawns an interactive shell containing all the dependencies and +environment variables needed to work on Inkscape: + +@example +guix shell --development inkscape +@end example + +Exiting the shell places the user back in the original environment +before @command{guix shell} was invoked. The next garbage collection +(@pxref{Invoking guix gc}) may clean up packages that were installed in +the environment and that are no longer used outside of it. + +By default, the shell session or command runs in an @emph{augmented} +environment, where the new packages are added to search path environment +variables such as @code{PATH}. You can, instead, choose to create an +@emph{isolated} environment containing nothing but the packages you +asked for. Passing the @option{--pure} option clears environment +variable definitions found in the parent environment@footnote{Users +sometimes wrongfully augment environment variables such as @env{PATH} in +their @file{~/.bashrc} file. As a consequence, when @command{guix +environment} launches it, Bash may read @file{~/.bashrc}, thereby +introducing ``impurities'' in these environment variables. It is an +error to define such environment variables in @file{.bashrc}; instead, +they should be defined in @file{.bash_profile}, which is sourced only by +log-in shells. @xref{Bash Startup Files,,, bash, The GNU Bash Reference +Manual}, for details on Bash start-up files.}; passing +@option{--container} goes one step further by spawning a @dfn{container} +isolated from the rest of the system: + +@example +guix shell --container emacs gcc-toolchain +@end example + +The command above spawns an interactive shell in a container when +nothing but @code{emacs}, @code{gcc-toolchain}, and their dependencies +is available. The container lacks network access and shares no files +other than the current working directory with the surrounding +environment. This is useful to prevent access to system-wide resources +such as @file{/usr/bin} on foreign distros. + +This @option{--container} option can also prove useful if you wish to +run a security-sensitive application, such as a web browser, in an +isolated environment. For example, the command below launches +Ungoogled-Chromium in an isolated environment, this time sharing network +access with the host and preserving its @code{DISPLAY} environment +variable, but without even sharing the current directory: + +@example +guix shell --container --network --no-cwd ungoogled-chromium \ + --preserve='^DISPLAY$' -- chromium +@end example + +@vindex GUIX_ENVIRONMENT +@command{guix shell} defines the @env{GUIX_ENVIRONMENT} +variable in the shell it spawns; its value is the file name of the +profile of this environment. This allows users to, say, define a +specific prompt for development environments in their @file{.bashrc} +(@pxref{Bash Startup Files,,, bash, The GNU Bash Reference Manual}): + +@example +if [ -n "$GUIX_ENVIRONMENT" ] +then + export PS1="\u@@\h \w [dev]\$ " +fi +@end example + +@noindent +...@: or to browse the profile: + +@example +$ ls "$GUIX_ENVIRONMENT/bin" +@end example + +The available options are summarized below. + +@table @code +@item --development +@itemx -D +Cause @command{guix shell} to include in the environment the +dependencies of the following package rather than the package itself. +This can be combined with other packages. For instance, the command +below starts an interactive shell containing the build-time dependencies +of GNU@tie{}Guile, plus Autoconf, Automake, and Libtool: + +@example +guix shell -D guile autoconf automake libtool +@end example + +@item --expression=@var{expr} +@itemx -e @var{expr} +Create an environment for the package or list of packages that +@var{expr} evaluates to. + +For example, running: + +@example +guix shell -D -e '(@@ (gnu packages maths) petsc-openmpi)' +@end example + +starts a shell with the environment for this specific variant of the +PETSc package. + +Running: + +@example +guix shell -e '(@@ (gnu) %base-packages)' +@end example + +starts a shell with all the base system packages available. + +The above commands only use the default output of the given packages. +To select other outputs, two element tuples can be specified: + +@example +guix shell -e '(list (@@ (gnu packages bash) bash) "include")' +@end example + +@item --file=@var{file} +@itemx -f @var{file} +Create an environment containing the package or list of packages that +the code within @var{file} evaluates to. + +As an example, @var{file} might contain a definition like this +(@pxref{Defining Packages}): + +@lisp +@verbatiminclude environment-gdb.scm +@end lisp + +With the file above, you can enter a development environment for GDB by +running: + +@example +guix shell -D -f gdb-devel.scm +@end example + +@item --manifest=@var{file} +@itemx -m @var{file} +Create an environment for the packages contained in the manifest object +returned by the Scheme code in @var{file}. This option can be repeated +several times, in which case the manifests are concatenated. + +This is similar to the same-named option in @command{guix package} +(@pxref{profile-manifest, @option{--manifest}}) and uses the same +manifest files. + +@item --pure +Unset existing environment variables when building the new environment, except +those specified with @option{--preserve} (see below). This has the effect of +creating an environment in which search paths only contain package inputs. + +@item --preserve=@var{regexp} +@itemx -E @var{regexp} +When used alongside @option{--pure}, preserve the environment variables +matching @var{regexp}---in other words, put them on a ``white list'' of +environment variables that must be preserved. This option can be repeated +several times. + +@example +guix shell --pure --preserve=^SLURM openmpi @dots{} \ + -- mpirun @dots{} +@end example + +This example runs @command{mpirun} in a context where the only environment +variables defined are @env{PATH}, environment variables whose name starts +with @samp{SLURM}, as well as the usual ``precious'' variables (@env{HOME}, +@env{USER}, etc.). + +@item --search-paths +Display the environment variable definitions that make up the +environment. + +@item --system=@var{system} +@itemx -s @var{system} +Attempt to build for @var{system}---e.g., @code{i686-linux}. + +@item --container +@itemx -C +@cindex container +Run @var{command} within an isolated container. The current working +directory outside the container is mapped inside the container. +Additionally, unless overridden with @option{--user}, a dummy home +directory is created that matches the current user's home directory, and +@file{/etc/passwd} is configured accordingly. + +The spawned process runs as the current user outside the container. Inside +the container, it has the same UID and GID as the current user, unless +@option{--user} is passed (see below). + +@item --network +@itemx -N +For containers, share the network namespace with the host system. +Containers created without this flag only have access to the loopback +device. + +@item --link-profile +@itemx -P +For containers, link the environment profile to @file{~/.guix-profile} +within the container and set @code{GUIX_ENVIRONMENT} to that. +This is equivalent to making @file{~/.guix-profile} a symlink to the +actual profile within the container. +Linking will fail and abort the environment if the directory already +exists, which will certainly be the case if @command{guix shell} +was invoked in the user's home directory. + +Certain packages are configured to look in @file{~/.guix-profile} for +configuration files and data;@footnote{For example, the +@code{fontconfig} package inspects @file{~/.guix-profile/share/fonts} +for additional fonts.} @option{--link-profile} allows these programs to +behave as expected within the environment. + +@item --user=@var{user} +@itemx -u @var{user} +For containers, use the username @var{user} in place of the current +user. The generated @file{/etc/passwd} entry within the container will +contain the name @var{user}, the home directory will be +@file{/home/@var{user}}, and no user GECOS data will be copied. Furthermore, +the UID and GID inside the container are 1000. @var{user} +need not exist on the system. + +Additionally, any shared or exposed path (see @option{--share} and +@option{--expose} respectively) whose target is within the current user's +home directory will be remapped relative to @file{/home/USER}; this +includes the automatic mapping of the current working directory. + +@example +# will expose paths as /home/foo/wd, /home/foo/test, and /home/foo/target +cd $HOME/wd +guix shell --container --user=foo \ + --expose=$HOME/test \ + --expose=/tmp/target=$HOME/target +@end example + +While this will limit the leaking of user identity through home paths +and each of the user fields, this is only one useful component of a +broader privacy/anonymity solution---not one in and of itself. + +@item --no-cwd +For containers, the default behavior is to share the current working +directory with the isolated container and immediately change to that +directory within the container. If this is undesirable, +@option{--no-cwd} will cause the current working directory to @emph{not} +be automatically shared and will change to the user's home directory +within the container instead. See also @option{--user}. + +@item --expose=@var{source}[=@var{target}] +@itemx --share=@var{source}[=@var{target}] +For containers, @option{--expose} (resp. @option{--share}) exposes the +file system @var{source} from the host system as the read-only +(resp. writable) file system @var{target} within the container. If +@var{target} is not specified, @var{source} is used as the target mount +point in the container. + +The example below spawns a Guile REPL in a container in which the user's +home directory is accessible read-only via the @file{/exchange} +directory: + +@example +guix shell --container --expose=$HOME=/exchange guile -- guile +@end example + +@item --root=@var{file} +@itemx -r @var{file} +@cindex persistent environment +@cindex garbage collector root, for environments +Make @var{file} a symlink to the profile for this environment, and +register it as a garbage collector root. + +This is useful if you want to protect your environment from garbage +collection, to make it ``persistent''. + +When this option is omitted, the environment is protected from garbage +collection only for the duration of the @command{guix shell} +session. This means that next time you recreate the same environment, +you could have to rebuild or re-download packages. @xref{Invoking guix +gc}, for more on GC roots. +@end table + +@command{guix shell} also supports all of the common build options that +@command{guix build} supports (@pxref{Common Build Options}) as well as +package transformation options (@pxref{Package Transformation Options}). + +@node Invoking guix environment +@section Invoking @command{guix environment} + +The purpose of @command{guix environment} is to assist in creating +development environments. + +@quotation Deprecation warning +The @command{guix environment} command is deprecated in favor of +@command{guix shell}, which performs similar functions but is more +convenient to use. @xref{Invoking guix shell}. + +Being deprecated, @command{guix environment} is slated for eventual +removal, but the Guix project is committed to keeping it until May 1st, +2023. Please get in touch with us at @email{guix-devel@@gnu.org} if you +would like to discuss it. +@end quotation The general syntax is: @@ -11099,14 +11422,14 @@ a container similar to the one the build daemon creates: $ guix build -K foo @dots{} $ cd /tmp/guix-build-foo.drv-0 -$ guix environment --no-grafts -C foo --ad-hoc strace gdb +$ guix shell --no-grafts -C foo strace gdb [env]# source ./environment-variables [env]# cd foo-1.2 @end example -Here, @command{guix environment -C} creates a container and spawns a new -shell in it (@pxref{Invoking guix environment}). The @command{--ad-hoc -strace gdb} part adds the @command{strace} and @command{gdb} commands to +Here, @command{guix shell -C} creates a container and spawns a new +shell in it (@pxref{Invoking guix shell}). The @command{strace gdb} +part adds the @command{strace} and @command{gdb} commands to the container, which you may find handy while debugging. The @option{--no-grafts} option makes sure we get the exact same environment, with ungrafted packages (@pxref{Security Updates}, for more @@ -11120,7 +11443,7 @@ remove @file{/bin/sh}: @end example (Don't worry, this is harmless: this is all happening in the throw-away -container created by @command{guix environment}.) +container created by @command{guix shell}.) The @command{strace} command is probably not in the search path, but we can run: @@ -13316,8 +13639,8 @@ is subject to radical change in the future. The purpose of @command{guix container} is to manipulate processes running within an isolated environment, commonly known as a -``container'', typically created by the @command{guix environment} -(@pxref{Invoking guix environment}) and @command{guix system container} +``container'', typically created by the @command{guix shell} +(@pxref{Invoking guix shell}) and @command{guix system container} (@pxref{Invoking guix system}) commands. The general syntax is: @@ -13503,7 +13826,7 @@ listed.}. Here's an example of the information it returns: $ sudo guix processes SessionPID: 19002 ClientPID: 19090 -ClientCommand: guix environment --ad-hoc python +ClientCommand: guix shell python SessionPID: 19402 ClientPID: 19367 @@ -29699,8 +30022,7 @@ When the service is running, you can view its console by connecting to it with a VNC client, for example with: @example -guix environment --ad-hoc tigervnc-client -- \ - vncviewer localhost:5900 +guix shell tigervnc-client -- vncviewer localhost:5900 @end example The default configuration (see @code{hurd-vm-configuration} below) diff --git a/etc/completion/bash/guix b/etc/completion/bash/guix index 87d9911e53..ec6adfdb22 100644 --- a/etc/completion/bash/guix +++ b/etc/completion/bash/guix @@ -1,5 +1,5 @@ # GNU Guix --- Functional package management for GNU -# Copyright © 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès +# Copyright © 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès # Copyright © 2021 Tobias Geerinck-Rice # # This file is part of GNU Guix. @@ -215,7 +215,7 @@ _guix_complete () if [[ "$word" = "--" ]] then case "$command" in - environment) + environment|shell) break ;; time-machine) @@ -265,7 +265,7 @@ _guix_complete () else _guix_complete_available_package_or_store_file "$word_at_point" fi - elif [[ "$command" = "environment" ]] + elif [[ "$command" = "environment" || "$command" = "shell" ]] then if _guix_is_dash_L || _guix_is_dash_m || _guix_is_dash_p || _guix_is_dash_l then diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index 54f48a7482..77956fc018 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -50,7 +50,11 @@ #:use-module (srfi srfi-37) #:use-module (srfi srfi-98) #:export (assert-container-features - guix-environment)) + guix-environment + guix-environment* + show-environment-options-help + (%options . %environment-options) + (%default-options . %environment-default-options))) (define %default-shell (or (getenv "SHELL") "/bin/sh")) @@ -66,23 +70,16 @@ do not augment existing environment variables with additional search paths." (newline))) (profile-search-paths profile manifest))) -(define (show-help) - (display (G_ "Usage: guix environment [OPTION]... PACKAGE... [-- COMMAND...] -Build an environment that includes the dependencies of PACKAGE and execute -COMMAND or an interactive shell in that environment.\n")) +(define (show-environment-options-help) + "Print help about options shared between 'guix environment' and 'guix +shell'." (display (G_ " -e, --expression=EXPR create environment for the package that EXPR evaluates to")) (display (G_ " - -l, --load=FILE create environment for the package that the code within - FILE evaluates to")) - (display (G_ " -m, --manifest=FILE create environment with the manifest from FILE")) (display (G_ " -p, --profile=PATH create environment from profile at PATH")) - (display (G_ " - --ad-hoc include all specified packages in the environment instead - of only their inputs")) (display (G_ " --pure unset existing environment variables")) (display (G_ " @@ -118,7 +115,24 @@ COMMAND or an interactive shell in that environment.\n")) (display (G_ " -v, --verbosity=LEVEL use the given verbosity LEVEL")) (display (G_ " - --bootstrap use bootstrap binaries to build the environment")) + --bootstrap use bootstrap binaries to build the environment"))) + +(define (show-help) + (display (G_ "Usage: guix environment [OPTION]... PACKAGE... [-- COMMAND...] +Build an environment that includes the dependencies of PACKAGE and execute +COMMAND or an interactive shell in that environment.\n")) + (warning (G_ "This command is deprecated in favor of 'guix shell'.\n")) + (newline) + + ;; These two options are left out in 'guix shell'. + (display (G_ " + -l, --load=FILE create environment for the package that the code within + FILE evaluates to")) + (display (G_ " + --ad-hoc include all specified packages in the environment instead + of only their inputs")) + + (show-environment-options-help) (newline) (show-build-options-help) (newline) @@ -649,11 +663,15 @@ message if any test fails." (define-command (guix-environment . args) (category development) - (synopsis "spawn one-off software environments") + (synopsis "spawn one-off software environments (deprecated)") + + (guix-environment* (parse-args args))) +(define (guix-environment* opts) + "Run the 'guix environment' command on OPTS, an alist resulting for +command-line option processing with 'parse-command-line'." (with-error-handling - (let* ((opts (parse-args args)) - (pure? (assoc-ref opts 'pure)) + (let* ((pure? (assoc-ref opts 'pure)) (container? (assoc-ref opts 'container?)) (link-prof? (assoc-ref opts 'link-profile?)) (network? (assoc-ref opts 'network?)) @@ -724,8 +742,8 @@ message if any test fails." (prof-drv (manifest->derivation manifest system bootstrap?)) (profile -> (if profile - (readlink* profile) - (derivation->output-path prof-drv))) + (readlink* profile) + (derivation->output-path prof-drv))) (gc-root -> (assoc-ref opts 'gc-root))) ;; First build the inputs. This is necessary even for diff --git a/guix/scripts/shell.scm b/guix/scripts/shell.scm new file mode 100644 index 0000000000..190dd8837d --- /dev/null +++ b/guix/scripts/shell.scm @@ -0,0 +1,135 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts shell) + #:use-module (guix ui) + #:use-module (guix scripts environment) + #:autoload (guix scripts build) (show-build-options-help) + #:autoload (guix transformations) (show-transformation-options-help) + #:use-module (guix scripts) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) + #:use-module (ice-9 match) + #:export (guix-shell)) + +(define (show-help) + (display (G_ "Usage: guix shell [OPTION] PACKAGES... [-- COMMAND...] +Build an environment that includes PACKAGES and execute COMMAND or an +interactive shell in that environment.\n")) + (newline) + + ;; These two options differ from 'guix environment'. + (display (G_ " + -D, --development include the development inputs of the next package")) + (display (G_ " + -f, --file=FILE create environment for the package that the code within + FILE evaluates to")) + + (show-environment-options-help) + (newline) + (show-build-options-help) + (newline) + (show-transformation-options-help) + (newline) + (display (G_ " + -h, --help display this help and exit")) + (display (G_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define (tag-package-arg opts arg) + "Return a two-element list with the form (TAG ARG) that tags ARG with either +'ad-hoc' in OPTS has the 'ad-hoc?' key set to #t, or 'inputs' otherwise." + (if (assoc-ref opts 'ad-hoc?) + `(ad-hoc-package ,arg) + `(package ,arg))) + +(define (ensure-ad-hoc alist) + (if (assq-ref alist 'ad-hoc?) + alist + `((ad-hoc? . #t) ,@alist))) + +(define (wrapped-option opt) + "Wrap OPT, a SRFI-37 option, such that its processor always adds the +'ad-hoc?' flag to the resulting alist." + (option (option-names opt) + (option-required-arg? opt) + (option-optional-arg? opt) + (compose ensure-ad-hoc (option-processor opt)))) + +(define %options + ;; Specification of the command-line options. + (let ((to-remove '("ad-hoc" "inherit" "load" "help" "version"))) + (append + (list (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix shell"))) + + (option '(#\D "development") #f #f + (lambda (opt name arg result) + ;; Temporarily remove the 'ad-hoc?' flag from result. + ;; The next option will put it back thanks to + ;; 'wrapped-option'. + (alist-delete 'ad-hoc? result))) + + ;; For consistency with 'guix package', support '-f' rather than + ;; '-l' like 'guix environment' does. + (option '(#\f "file") #t #f + (lambda (opt name arg result) + (alist-cons 'load (tag-package-arg result arg) + result)))) + (filter-map (lambda (opt) + (and (not (any (lambda (name) + (member name to-remove)) + (option-names opt))) + (wrapped-option opt))) + %environment-options)))) + +(define %default-options + `((ad-hoc? . #t) ;always true + ,@%environment-default-options)) + +(define (parse-args args) + "Parse the list of command line arguments ARGS." + (define (handle-argument arg result) + (alist-cons 'package (tag-package-arg result arg) + (ensure-ad-hoc result))) + + ;; The '--' token is used to separate the command to run from the rest of + ;; the operands. + (let ((args command (break (cut string=? "--" <>) args))) + (let ((opts (parse-command-line args %options (list %default-options) + #:argument-handler handle-argument))) + (match command + (() opts) + (("--") opts) + (("--" command ...) (alist-cons 'exec command opts)))))) + + +(define-command (guix-shell . args) + (category development) + (synopsis "spawn one-off software environments") + + (guix-environment* (parse-args args))) diff --git a/po/guix/POTFILES.in b/po/guix/POTFILES.in index 5e77b3c230..ee0adbcf3c 100644 --- a/po/guix/POTFILES.in +++ b/po/guix/POTFILES.in @@ -140,5 +140,6 @@ guix/scripts/offload.scm guix/scripts/perform-download.scm guix/scripts/refresh.scm guix/scripts/repl.scm +guix/scripts/shell.scm guix/scripts/system/reconfigure.scm nix/nix-daemon/guix-daemon.cc diff --git a/tests/guix-shell.sh b/tests/guix-shell.sh new file mode 100644 index 0000000000..f08637f7ff --- /dev/null +++ b/tests/guix-shell.sh @@ -0,0 +1,54 @@ +# GNU Guix --- Functional package management for GNU +# Copyright © 2021 Ludovic Courtès +# +# This file is part of GNU Guix. +# +# GNU Guix is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# GNU Guix is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Guix. If not, see . + +# +# Test the 'guix shell' alias. +# + +guix shell --version + +tmpdir="t-guix-shell-$$" +trap 'rm -r "$tmpdir"' EXIT +mkdir "$tmpdir" + +guix shell --bootstrap --pure guile-bootstrap -- guile --version + +# '--ad-hoc' is a thing of the past. +! guix shell --ad-hoc guile-bootstrap + +if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null +then + # Compute the build environment for the initial GNU Make. + guix shell --bootstrap --no-substitutes --search-paths --pure \ + -D -e '(@ (guix tests) gnu-make-for-tests)' > "$tmpdir/a" + + # Make sure bootstrap binaries are in the profile. + profile=`grep "^export PATH" "$tmpdir/a" | sed -r 's|^.*="(.*)/bin"|\1|'` + + # Make sure the bootstrap binaries are all listed where they belong. + grep -E "^export PATH=\"$profile/bin\"" "$tmpdir/a" + grep -E "^export CPATH=\"$profile/include\"" "$tmpdir/a" + grep -E "^export LIBRARY_PATH=\"$profile/lib\"" "$tmpdir/a" + for dep in bootstrap-binaries-0 gcc-bootstrap-0 glibc-bootstrap-0 + do + guix gc --references "$profile" | grep "$dep" + done + + # 'make-boot0' itself must not be listed. + ! guix gc --references "$profile" | grep make-boot0 +fi -- cgit v1.2.3 From 746584e0ca200e7bf51b139ceb36c19ea81d6ef1 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 1 Oct 2021 17:18:43 +0200 Subject: shell: By default load the local 'manifest.scm' or 'guix.scm' file. * guix/scripts/shell.scm (parse-args): Add call to 'auto-detect-manifest'. (authorized-directory-file, authorized-shell-directory?) (find-file-in-parent-directories, auto-detect-manifest): New procedures. * tests/guix-shell.sh: Add test. * doc/guix.texi (Invoking guix shell): Document it. --- doc/guix.texi | 14 ++++++ guix/scripts/shell.scm | 119 ++++++++++++++++++++++++++++++++++++++++++++++--- tests/guix-shell.sh | 50 ++++++++++++++++++++- 3 files changed, 176 insertions(+), 7 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index f5bfb59229..5809bbacd4 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -5621,6 +5621,20 @@ before @command{guix shell} was invoked. The next garbage collection (@pxref{Invoking guix gc}) may clean up packages that were installed in the environment and that are no longer used outside of it. +As an added convenience, when running from a directory that contains a +@file{manifest.scm} or a @file{guix.scm} file (in this order), possibly +in a parent directory, @command{guix shell} automatically loads the +file---provided the directory is listed in +@file{~/.config/guix/shell-authorized-directories}, and only for +interactive use: + +@example +guix shell +@end example + +This provides an easy way to define, share, and enter development +environments. + By default, the shell session or command runs in an @emph{augmented} environment, where the new packages are added to search path environment variables such as @code{PATH}. You can, instead, choose to create an diff --git a/guix/scripts/shell.scm b/guix/scripts/shell.scm index 190dd8837d..bee3192a9d 100644 --- a/guix/scripts/shell.scm +++ b/guix/scripts/shell.scm @@ -18,15 +18,20 @@ (define-module (guix scripts shell) #:use-module (guix ui) + #:use-module ((guix diagnostics) #:select (location)) #:use-module (guix scripts environment) #:autoload (guix scripts build) (show-build-options-help) #:autoload (guix transformations) (show-transformation-options-help) #:use-module (guix scripts) + #:use-module (guix packages) + #:use-module (guix profiles) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (srfi srfi-37) #:use-module (srfi srfi-71) #:use-module (ice-9 match) + #:autoload (ice-9 rdelim) (read-line) + #:autoload (guix utils) (config-directory) #:export (guix-shell)) (define (show-help) @@ -41,6 +46,8 @@ interactive shell in that environment.\n")) (display (G_ " -f, --file=FILE create environment for the package that the code within FILE evaluates to")) + (display (G_ " + -q inhibit loading of 'guix.scm' and 'manifest.scm'")) (show-environment-options-help) (newline) @@ -99,7 +106,10 @@ interactive shell in that environment.\n")) (option '(#\f "file") #t #f (lambda (opt name arg result) (alist-cons 'load (tag-package-arg result arg) - result)))) + result))) + (option '(#\q) #f #f + (lambda (opt name arg result) + (alist-cons 'explicit-loading? #t result)))) (filter-map (lambda (opt) (and (not (any (lambda (name) (member name to-remove)) @@ -122,10 +132,109 @@ interactive shell in that environment.\n")) (let ((args command (break (cut string=? "--" <>) args))) (let ((opts (parse-command-line args %options (list %default-options) #:argument-handler handle-argument))) - (match command - (() opts) - (("--") opts) - (("--" command ...) (alist-cons 'exec command opts)))))) + (auto-detect-manifest + (match command + (() opts) + (("--") opts) + (("--" command ...) (alist-cons 'exec command opts))))))) + +(define (find-file-in-parent-directories candidates) + "Find one of CANDIDATES in the current directory or one of its ancestors." + (define start (getcwd)) + (define device (stat:dev (stat start))) + + (let loop ((directory start)) + (let ((stat (stat directory))) + (and (= (stat:uid stat) (getuid)) + (= (stat:dev stat) device) + (or (any (lambda (candidate) + (let ((candidate (string-append directory "/" candidate))) + (and (file-exists? candidate) candidate))) + candidates) + (and (not (string=? directory "/")) + (loop (dirname directory)))))))) ;lexical ".." resolution + +(define (authorized-directory-file) + "Return the name of the file listing directories for which 'guix shell' may +automatically load 'guix.scm' or 'manifest.scm' files." + (string-append (config-directory) "/shell-authorized-directories")) + +(define (authorized-shell-directory? directory) + "Return true if DIRECTORY is among the authorized directories for automatic +loading. The list of authorized directories is read from +'authorized-directory-file'; each line must be either: an absolute file name, +a hash-prefixed comment, or a blank line." + (catch 'system-error + (lambda () + (call-with-input-file (authorized-directory-file) + (lambda (port) + (let loop () + (match (read-line port) + ((? eof-object?) #f) + ((= string-trim line) + (cond ((string-prefix? "#" line) ;comment + (loop)) + ((string-prefix? "/" line) ;absolute file name + (or (string=? line directory) + (loop))) + ((string-null? (string-trim-right line)) ;blank line + (loop)) + (else ;bogus line + (let ((loc (location (port-filename port) + (port-line port) + (port-column port)))) + (warning loc (G_ "ignoring invalid file name: '~a'~%") + line)))))))))) + (const #f))) + +(define (auto-detect-manifest opts) + "If OPTS do not specify packages or a manifest, load a \"guix.scm\" or +\"manifest.scm\" file from the current directory or one of its ancestors. +Return the modified OPTS." + (define (options-contain-payload? opts) + (match opts + (() #f) + ((('package . _) . _) #t) + ((('load . _) . _) #t) + ((('manifest . _) . _) #t) + ((('expression . _) . _) #t) + ((_ . rest) (options-contain-payload? rest)))) + + (define interactive? + (not (assoc-ref opts 'exec))) + + (define disallow-implicit-load? + (assoc-ref opts 'explicit-loading?)) + + (if (or (not interactive?) + disallow-implicit-load? + (options-contain-payload? opts)) + opts + (match (find-file-in-parent-directories '("manifest.scm" "guix.scm")) + (#f + (warning (G_ "no packages specified; creating an empty environment~%")) + opts) + (file + (if (authorized-shell-directory? (dirname file)) + (begin + (info (G_ "loading environment from '~a'...~%") file) + (match (basename file) + ("guix.scm" (alist-cons 'load `(package ,file) opts)) + ("manifest.scm" (alist-cons 'manifest file opts)))) + (begin + (warning (G_ "not loading '~a' because not authorized to do so~%") + file) + (display-hint (format #f (G_ "To allow automatic loading of +@file{~a} when running @command{guix shell}, you must explicitly authorize its +directory, like so: + +@example +echo ~a >> ~a +@end example\n") + file + (dirname file) + (authorized-directory-file))) + opts)))))) (define-command (guix-shell . args) diff --git a/tests/guix-shell.sh b/tests/guix-shell.sh index f08637f7ff..95725cba2d 100644 --- a/tests/guix-shell.sh +++ b/tests/guix-shell.sh @@ -22,15 +22,55 @@ guix shell --version +configdir="t-guix-shell-config-$$" tmpdir="t-guix-shell-$$" -trap 'rm -r "$tmpdir"' EXIT -mkdir "$tmpdir" +trap 'rm -r "$tmpdir" "$configdir"' EXIT +mkdir "$tmpdir" "$configdir" "$configdir/guix" + +XDG_CONFIG_HOME="$(realpath $configdir)" +export XDG_CONFIG_HOME guix shell --bootstrap --pure guile-bootstrap -- guile --version # '--ad-hoc' is a thing of the past. ! guix shell --ad-hoc guile-bootstrap +# Ignoring unauthorized files. +cat > "$tmpdir/guix.scm" < "$configdir/guix/shell-authorized-directories" + +# Ignoring 'manifest.scm' and 'guix.scm' in non-interactive use. +(cd "$tmpdir"; guix shell --bootstrap -- true) +mv "$tmpdir/guix.scm" "$tmpdir/manifest.scm" +(cd "$tmpdir"; guix shell --bootstrap -- true) +rm "$tmpdir/manifest.scm" + +# Honoring the local 'manifest.scm' file. +cat > "$tmpdir/manifest.scm" <manifest '("guile-bootstrap")) +EOF +cat > "$tmpdir/fake-shell.sh" < "$tmpdir/manifest.scm" +(cd "$tmpdir"; SHELL="$(realpath fake-shell.sh)" guix shell --bootstrap -q) +rm "$tmpdir/manifest.scm" + if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null then # Compute the build environment for the initial GNU Make. @@ -51,4 +91,10 @@ then # 'make-boot0' itself must not be listed. ! guix gc --references "$profile" | grep make-boot0 + + # Honoring the local 'guix.scm' file. + echo '(@ (guix tests) gnu-make-for-tests)' > "$tmpdir/guix.scm" + (cd "$tmpdir"; guix shell --bootstrap --search-paths --pure > "b") + cmp "$tmpdir/a" "$tmpdir/b" + rm "$tmpdir/guix.scm" fi -- cgit v1.2.3 From 9730692d9f06f8c412b45ef108006921298983c4 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 1 Oct 2021 22:47:33 +0200 Subject: shell: Maintain a profile cache. shell: Maintain a profile cache. With this change, running "guix shell" (no arguments) is equivalent to: guix environment -r ~/.cache/guix/profiles/some-root -l guix.scm This is the cache miss. On cache hit, it's equivalent to: guix environment -p ~/.cache/guix/profiles/some-root ... which can run in 0.1s. * guix/scripts/shell.scm (options-with-caching): New procedure. (parse-args): Use it. (%profile-cache-directory): New variable. (profile-cache-key, profile-cached-gc-root): New procedures. (show-help, %options): Add '--rebuild-cache'. (guix-shell)[cache-entries, entry-expiration]: New procedures. Add call to 'maybe-remove-expired-cache-entries'. * doc/guix.texi (Invoking guix shell): Document '--rebuild-cache'. --- doc/guix.texi | 11 +++++ guix/scripts/shell.scm | 127 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 130 insertions(+), 8 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 5809bbacd4..093e354509 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -5769,6 +5769,17 @@ This is similar to the same-named option in @command{guix package} (@pxref{profile-manifest, @option{--manifest}}) and uses the same manifest files. +@item --rebuild-cache +When using @option{--manifest}, @option{--file}, or when invoked without +arguments, @command{guix shell} caches the environment so that +subsequent uses are instantaneous. The cache is invalidated anytime the +file is modified. + +The @option{--rebuild-cache} forces the cached environment to be +refreshed even if the file has not changed. This is useful if the +@command{guix.scm} or @command{manifest.scm} has external dependencies, +or if its behavior depends, say, on environment variables. + @item --pure Unset existing environment variables when building the new environment, except those specified with @option{--preserve} (see below). This has the effect of diff --git a/guix/scripts/shell.scm b/guix/scripts/shell.scm index bee3192a9d..05b6f98656 100644 --- a/guix/scripts/shell.scm +++ b/guix/scripts/shell.scm @@ -31,7 +31,15 @@ #:use-module (srfi srfi-71) #:use-module (ice-9 match) #:autoload (ice-9 rdelim) (read-line) - #:autoload (guix utils) (config-directory) + #:autoload (guix base32) (bytevector->base32-string) + #:autoload (rnrs bytevectors) (string->utf8) + #:autoload (guix utils) (config-directory cache-directory) + #:autoload (guix describe) (current-channels) + #:autoload (guix channels) (channel-commit) + #:autoload (gcrypt hash) (sha256) + #:use-module ((guix build utils) #:select (mkdir-p)) + #:use-module (guix cache) + #:use-module ((ice-9 ftw) #:select (scandir)) #:export (guix-shell)) (define (show-help) @@ -48,6 +56,8 @@ interactive shell in that environment.\n")) FILE evaluates to")) (display (G_ " -q inhibit loading of 'guix.scm' and 'manifest.scm'")) + (display (G_ " + --rebuild-cache rebuild cached environment, if any")) (show-environment-options-help) (newline) @@ -109,7 +119,10 @@ interactive shell in that environment.\n")) result))) (option '(#\q) #f #f (lambda (opt name arg result) - (alist-cons 'explicit-loading? #t result)))) + (alist-cons 'explicit-loading? #t result))) + (option '("rebuild-cache") #f #f + (lambda (opt name arg result) + (alist-cons 'rebuild-cache? #t result)))) (filter-map (lambda (opt) (and (not (any (lambda (name) (member name to-remove)) @@ -132,11 +145,12 @@ interactive shell in that environment.\n")) (let ((args command (break (cut string=? "--" <>) args))) (let ((opts (parse-command-line args %options (list %default-options) #:argument-handler handle-argument))) - (auto-detect-manifest - (match command - (() opts) - (("--") opts) - (("--" command ...) (alist-cons 'exec command opts))))))) + (options-with-caching + (auto-detect-manifest + (match command + (() opts) + (("--") opts) + (("--" command ...) (alist-cons 'exec command opts)))))))) (define (find-file-in-parent-directories candidates) "Find one of CANDIDATES in the current directory or one of its ancestors." @@ -187,6 +201,53 @@ a hash-prefixed comment, or a blank line." line)))))))))) (const #f))) +(define (options-with-caching opts) + "If OPTS contains exactly one 'load' or one 'manifest' key, automatically +add a 'profile' key (when a profile for that file is already in cache) or a +'gc-root' key (to add the profile to cache)." + (define (single-file-for-caching opts) + (let loop ((opts opts) + (file #f)) + (match opts + (() file) + ((('package . _) . _) #f) + ((('load . ('package candidate)) . rest) + (and (not file) (loop rest candidate))) + ((('manifest . candidate) . rest) + (and (not file) (loop rest candidate))) + ((('expression . _) . _) #f) + ((_ . rest) (loop rest file))))) + + ;; Check whether there's a single 'load' or 'manifest' option. When that is + ;; the case, arrange to automatically cache the resulting profile. + (match (single-file-for-caching opts) + (#f opts) + (file + (let* ((root (profile-cached-gc-root file)) + (stat (and root (false-if-exception (lstat root))))) + (if (and (not (assoc-ref opts 'rebuild-cache?)) + stat + (<= (stat:mtime ((@ (guile) stat) file)) + (stat:mtime stat))) + (let ((now (current-time))) + ;; Update the atime on ROOT to reflect usage. + (utime root + now (stat:mtime stat) 0 (stat:mtimensec stat) + AT_SYMLINK_NOFOLLOW) + (alist-cons 'profile root + (remove (match-lambda + (('load . _) #t) + (('manifest . _) #t) + (_ #f)) + opts))) ;load right away + (if (and root (not (assq-ref opts 'gc-root))) + (begin + (if stat + (delete-file root) + (mkdir-p (dirname root))) + (alist-cons 'gc-root root opts)) + opts)))))) + (define (auto-detect-manifest opts) "If OPTS do not specify packages or a manifest, load a \"guix.scm\" or \"manifest.scm\" file from the current directory or one of its ancestors. @@ -236,9 +297,59 @@ echo ~a >> ~a (authorized-directory-file))) opts)))))) + +;;; +;;; Profile cache. +;;; + +(define %profile-cache-directory + ;; Directory where profiles created by 'guix shell' alone (without extra + ;; options) are cached. + (make-parameter (string-append (cache-directory #:ensure? #f) + "/profiles"))) + +(define (profile-cache-key file) + "Return the cache key for the profile corresponding to FILE, a 'guix.scm' or +'manifest.scm' file, or #f if we lack channel information." + (match (current-channels) + (() #f) + (((= channel-commit commits) ...) + (let ((stat (stat file))) + (bytevector->base32-string + ;; Since FILE is not canonicalized, only include the device/inode + ;; numbers. XXX: In some rare cases involving Btrfs and NFS, this can + ;; be insufficient: . + (sha256 (string->utf8 + (string-append (string-join commits) ":" + (number->string (stat:dev stat)) ":" + (number->string (stat:ino stat)))))))))) + +(define (profile-cached-gc-root file) + "Return the cached GC root for FILE, a 'guix.scm' or 'manifest.scm' file, or +#f if we lack information to cache it." + (match (profile-cache-key file) + (#f #f) + (key (string-append (%profile-cache-directory) "/" key)))) + (define-command (guix-shell . args) (category development) (synopsis "spawn one-off software environments") - (guix-environment* (parse-args args))) + (define (cache-entries directory) + (filter-map (match-lambda + ((or "." "..") #f) + (file (string-append directory "/" file))) + (or (scandir directory) '()))) + + (define* (entry-expiration file) + ;; Return the time at which FILE, a cached profile, is considered expired. + (match (false-if-exception (lstat file)) + (#f 0) ;FILE may have been deleted in the meantime + (st (+ (stat:atime st) (* 60 60 24 7))))) + + (let ((result (guix-environment* (parse-args args)))) + (maybe-remove-expired-cache-entries (%profile-cache-directory) + cache-entries + #:entry-expiration entry-expiration) + result)) -- cgit v1.2.3 From 9e46942c1c8e719af97026d89d64b25da759eff8 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Tue, 19 Oct 2021 11:17:24 +0200 Subject: environment: Add '--check'. * guix/scripts/environment.scm (show-environment-options-help) (%options): Add '--check'. * guix/scripts/environment.scm (child-shell-environment) (validate-child-shell-environment): New procedures. (guix-environment*): Call 'validate-child-shell-environment' when 'check?' key is in OPTS. * doc/guix.texi (Invoking guix shell): Shorten footnote about Bash startup files. Document '--check' and mention startup files. (Invoking guix environment): Document '--check'. --- doc/guix.texi | 39 ++++++++--- guix/scripts/environment.scm | 162 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 12 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 093e354509..22215214e0 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -5640,17 +5640,11 @@ environment, where the new packages are added to search path environment variables such as @code{PATH}. You can, instead, choose to create an @emph{isolated} environment containing nothing but the packages you asked for. Passing the @option{--pure} option clears environment -variable definitions found in the parent environment@footnote{Users -sometimes wrongfully augment environment variables such as @env{PATH} in -their @file{~/.bashrc} file. As a consequence, when @command{guix -environment} launches it, Bash may read @file{~/.bashrc}, thereby -introducing ``impurities'' in these environment variables. It is an -error to define such environment variables in @file{.bashrc}; instead, -they should be defined in @file{.bash_profile}, which is sourced only by -log-in shells. @xref{Bash Startup Files,,, bash, The GNU Bash Reference -Manual}, for details on Bash start-up files.}; passing -@option{--container} goes one step further by spawning a @dfn{container} -isolated from the rest of the system: +variable definitions found in the parent environment@footnote{Be sure to +use the @option{--check} option the first time you use @command{guix +shell} interactively to make sure the shell does not undo the effect of +@option{--pure}.}; passing @option{--container} goes one step further by +spawning a @dfn{container} isolated from the rest of the system: @example guix shell --container emacs gcc-toolchain @@ -5699,6 +5693,24 @@ $ ls "$GUIX_ENVIRONMENT/bin" The available options are summarized below. @table @code +@item --check +Set up the environment and check whether the shell would clobber +environment variables. It's a good idea to use this option the first +time you run @command{guix shell} for an interactive session to make +sure your setup is correct. + +For example, if the shell modifies the @env{PATH} environment variable, +report it since you would get a different environment than what you +asked for. + +Such problems usually indicate that the shell startup files are +unexpectedly modifying those environment variables. For example, if you +are using Bash, make sure that environment variables are set or modified +in @file{~/.bash_profile} and @emph{not} in @file{~/.bashrc}---the +former is sourced only by log-in shells. @xref{Bash Startup Files,,, +bash, The GNU Bash Reference Manual}, for details on Bash start-up +files. + @item --development @itemx -D Cause @command{guix shell} to include in the environment the @@ -6065,6 +6077,11 @@ guix environment --preserve='^DISPLAY$' --container --network \ The available options are summarized below. @table @code +@item --check +Set up the environment and check whether the shell would clobber +environment variables. @xref{Invoking guix shell, @option{--check}}, +for more info. + @item --root=@var{file} @itemx -r @var{file} @cindex persistent environment diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index 05a43659da..7b97a8e39a 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -41,12 +41,14 @@ #:autoload (gnu build accounts) (password-entry group-entry password-entry-name password-entry-directory write-passwd write-group) - #:autoload (guix build syscalls) (set-network-interface-up) + #:autoload (guix build syscalls) (set-network-interface-up openpty login-tty) #:use-module (gnu system file-systems) #:autoload (gnu packages) (specification->package+output) #:autoload (gnu packages bash) (bash) #:autoload (gnu packages bootstrap) (bootstrap-executable %bootstrap-guile) #:use-module (ice-9 match) + #:autoload (ice-9 rdelim) (read-line) + #:use-module (ice-9 vlist) #:use-module (srfi srfi-1) #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) @@ -83,6 +85,8 @@ shell'." -m, --manifest=FILE create environment with the manifest from FILE")) (display (G_ " -p, --profile=PATH create environment from profile at PATH")) + (display (G_ " + --check check if the shell clobbers environment variables")) (display (G_ " --pure unset existing environment variables")) (display (G_ " @@ -178,6 +182,9 @@ COMMAND or an interactive shell in that environment.\n")) (option '(#\V "version") #f #f (lambda args (show-version-and-exit "guix environment"))) + (option '("check") #f #f + (lambda (opt name arg result) + (alist-cons 'check? #t result))) (option '("pure") #f #f (lambda (opt name arg result) (alist-cons 'pure #t result))) @@ -396,6 +403,155 @@ regexps in WHITE-LIST." ((program . args) (apply execlp program program args)))) +(define (child-shell-environment shell profile manifest) + "Create a child process, load PROFILE and MANIFEST, and then run SHELL in +interactive mode in it. Return a name/value vhash for all the variables shown +by running 'set' in the shell." + (define-values (controller inferior) + (openpty)) + + (define script + ;; Script to obtain the list of environment variable values. On a POSIX + ;; shell we can rely on 'set', but on fish we have to use 'env' (fish's + ;; 'set' truncates values and prints them in a different format.) + "env || /usr/bin/env || set; echo GUIX-CHECK-DONE; read x; exit\n") + + (define lines + (match (primitive-fork) + (0 + (catch #t + (lambda () + (load-profile profile manifest #:pure? #t) + (setenv "GUIX_ENVIRONMENT" profile) + (close-fdes controller) + (login-tty inferior) + (execl shell shell)) + (lambda _ + (primitive-exit 127)))) + (pid + (close-fdes inferior) + (let* ((port (fdopen controller "r+l")) + (result (begin + (display script port) + (let loop ((lines '())) + (match (read-line port) + ((? eof-object?) (reverse lines)) + ("GUIX-CHECK-DONE\r" + (display "done\n" port) + (reverse lines)) + (line + ;; Drop the '\r' from LINE. + (loop (cons (string-drop-right line 1) + lines)))))))) + (close-port port) + (waitpid pid) + result)))) + + (fold (lambda (line table) + ;; Note: 'set' in fish outputs "NAME VALUE" instead of "NAME=VALUE" + ;; but it also truncates values anyway, so don't try to support it. + (let ((index (string-index line #\=))) + (if index + (vhash-cons (string-take line index) + (string-drop line (+ 1 index)) + table) + table))) + vlist-null + lines)) + +(define* (validate-child-shell-environment profile manifest + #:optional (shell %default-shell)) + "Run SHELL in interactive mode in an environment for PROFILE and MANIFEST +and report clobbered environment variables." + (define warned? #f) + (define-syntax-rule (warn exp ...) + (begin + (set! warned? #t) + (warning exp ...))) + + (info (G_ "checking the environment variables visible from shell '~a'...~%") + shell) + (let ((actual (child-shell-environment shell profile manifest))) + (when (vlist-null? actual) + (leave (G_ "failed to determine environment of shell '~a'~%") + shell)) + (for-each (match-lambda + ((spec . expected) + (let ((name (search-path-specification-variable spec))) + (match (vhash-assoc name actual) + (#f + (warn (G_ "variable '~a' is missing from shell \ +environment~%") + name)) + ((_ . actual) + (cond ((string=? expected actual) + #t) + ((string-prefix? expected actual) + (warn (G_ "variable '~a' has unexpected \ +suffix '~a'~%") + name + (string-drop actual + (string-length expected)))) + (else + (warn (G_ "variable '~a' is clobbered: '~a'~%") + name actual)))))))) + (profile-search-paths profile manifest)) + + ;; Special case. + (match (vhash-assoc "GUIX_ENVIRONMENT" actual) + (#f + (warn (G_ "'GUIX_ENVIRONMENT' is missing from the shell \ +environment~%"))) + ((_ . value) + (unless (string=? value profile) + (warn (G_ "'GUIX_ENVIRONMENT' is set to '~a' instead of '~a'~%") + value profile)))) + + ;; Check the prompt unless we have more important warnings. + (unless warned? + (match (vhash-assoc "PS1" actual) + (#f #f) + (str + (when (and (getenv "PS1") (string=? str (getenv "PS1"))) + (warning (G_ "'PS1' is the same in sub-shell~%")) + (display-hint (G_ "Consider setting a different prompt for +environment shells to make them distinguishable. + +If you are using Bash, you can do that by adding these lines to +@file{~/.bashrc}: + +@example +if [ -n \"$GUIX_ENVIRONMENT\" ] +then + export PS1=\"\\u@@\\h \\w [env]\\$ \" +fi +@end example +")))))) + + (if warned? + (begin + (display-hint (G_ "One or more environment variables have a +different value in the shell than the one we set. This means that you may +find yourself running code in an environment different from the one you asked +Guix to prepare. + +This usually indicates that your shell startup files are unexpectedly +modifying those environment variables. For example, if you are using Bash, +make sure that environment variables are set or modified in +@file{~/.bash_profile} and @emph{not} in @file{~/.bashrc}. For more +information on Bash startup files, run: + +@example +info \"(bash) Bash Startup Files\" +@end example + +Alternatively, you can avoid the problem by passing the @option{--container} +or @option{-C} option. That will give you a fully isolated environment +running in a \"container\", immune to the issue described above.")) + (exit 1)) + (info (G_ "All is good! The shell gets correct environment \ +variables.~%"))))) + (define* (launch-environment/fork command profile manifest #:key pure? (white-list '())) "Run COMMAND in a new process with an environment containing PROFILE, with @@ -775,6 +931,10 @@ command-line option processing with 'parse-command-line'." (mwhen gc-root (register-gc-root profile gc-root)) + (mwhen (assoc-ref opts 'check?) + (return + (validate-child-shell-environment profile manifest))) + (cond ((assoc-ref opts 'search-paths) (show-search-paths profile manifest #:pure? pure?) -- cgit v1.2.3 From 87c04b0e170a62aa60c8f2054ad039d169751b9c Mon Sep 17 00:00:00 2001 From: Xinglu Chen Date: Sat, 30 Oct 2021 12:42:39 +0200 Subject: doc: Document the ‘guix home import’ subcommand. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc/guix.texi (Invoking guix home): Document ‘guix home import’. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 22215214e0..066971b995 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -36509,6 +36509,38 @@ generations that are up to 10 days old: $ guix home list-generations 10d @end example +@item import +Generate a @dfn{home environment} from the packages in the default +profile and configuration files found in the user's home directory. The +configuration files will be copied to the specified directory. Note +that not every home service that exists is supported (@pxref{Home +Services}). + +@example +$ guix home import ~/guix-config +;; This "home-environment" file can be passed to 'guix home reconfigure' +;; to reproduce the content of your profile. This is "symbolic": it only +;; specifies package names. To reproduce the exact same profile, you also +;; need to capture the channels being used, as returned by "guix describe". +;; See the "Replicating Guix" section in the manual. + +(use-modules + (gnu home) + (gnu packages) + (gnu home services shells)) + +(home-environment + (packages + (map specification->package + (list "glibc-locales" "nss-certs" "nss"))) + (services + (list (service + home-bash-service-type + (home-bash-configuration + (bashrc + (list (local-file "/home/charlie/guix-config/.bashrc")))))))) +@end example + @end table @var{options} can contain any of the common build options (@pxref{Common -- cgit v1.2.3 From 7711a6c3f41b0791f9fac60d31954f5ce478b7b8 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 31 Oct 2021 00:16:44 +0200 Subject: doc: Mention "guix home import" upfront. * doc/guix.texi (Declaring the Home Environment): Mention "guix home import". --- doc/guix.texi | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 066971b995..c78dbdc451 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -35853,12 +35853,27 @@ still in an experimental stage, though. @section Declaring the Home Environment The home environment is configured by providing a @code{home-environment} declaration in a file that can be passed to the -@command{guix home} command (@pxref{Invoking guix home}). A simple -setup can include Bash and a custom text configuration, like in the -example below. Don't be afraid to declare home environment parts, which -overlaps with your current dotfiles, before installing any configuration -files, Guix Home will back up existing config files to a separate place -in the home folder. +@command{guix home} command (@pxref{Invoking guix home}). The easiest +way to get started is by generating an initial configuration with +@command{guix home import}: + +@example +guix home import ~/src/guix-config +@end example + +The @command{guix home import} command reads some of the ``dot files'' +such as @file{~/.bashrc} found in your home directory and copies them to +the given directory, @file{~/src/guix-config} in this case; it also +reads the contents of your profile, @file{~/.guix-profile}, and, based +on that, it outputs a Home configuration that resembles your current +configuration. You can dump that configuration to a file and you're +ready to go! + +A simple setup can include Bash and a custom text configuration, like in +the example below. Don't be afraid to declare home environment parts, +which overlaps with your current dot files: before installing any +configuration files, Guix Home will back up existing config files to a +separate place in the home directory. @quotation Note It is highly recommended that you manage your shell or shells with Guix -- cgit v1.2.3 From 971a69d8e33bf3fe37755798b142b18515ad6e06 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 31 Oct 2021 00:19:45 +0200 Subject: doc: Avoid misuse of @ref. * doc/guix.texi (Declaring the Home Environment): Avoid @ref in the middle of a sentence. --- doc/guix.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index c78dbdc451..9206c0d907 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -35896,7 +35896,7 @@ There is no daemon (at least not necessarily) related to a home service, a home service is just an element that is used to declare part of home environment and extend other parts of it. The extension mechanism discussed in the previous chapter (@pxref{Defining Services}) should not -be confused with @ref{Shepherd Services}. Using this extension +be confused with Shepherd services (@pxref{Shepherd Services}). Using this extension mechanism and some Scheme code that glues things together gives the user the freedom to declare their own, very custom, home environments. -- cgit v1.2.3 From c4ac8cf4f61c730ef7e699831f697b853394e3d0 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 31 Oct 2021 00:49:31 +0200 Subject: doc: Mention 'guix home reconfigure' upfront. * doc/guix.texi (Declaring the Home Environment): Mention 'guix home reconfigure'. --- doc/guix.texi | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 9206c0d907..ea1973f02c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -35900,6 +35900,16 @@ be confused with Shepherd services (@pxref{Shepherd Services}). Using this exte mechanism and some Scheme code that glues things together gives the user the freedom to declare their own, very custom, home environments. +Once you have a configuration file that suits your needs, you can +reconfigure your home by running: + +@example +guix home reconfigure config.scm +@end example + +This ``builds'' your home environment and creates @file{~/.guix-home} +pointing to it. Voilà! + @node Configuring the Shell @section Configuring the Shell This section is safe to skip if your shell or shells are managed by -- cgit v1.2.3