From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id yEaLC4vUMmJLZAEAgWs5BA (envelope-from ) for ; Thu, 17 Mar 2022 07:26:19 +0100 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id GK/fA4vUMmJeIgEAG6o9tA (envelope-from ) for ; Thu, 17 Mar 2022 07:26:19 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 68CCF2F33A for ; Thu, 17 Mar 2022 07:26:18 +0100 (CET) Received: from localhost ([::1]:35674 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nUjaT-00082D-0s for larch@yhetil.org; Thu, 17 Mar 2022 02:26:17 -0400 Received: from eggs.gnu.org ([209.51.188.92]:35580) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nUjZG-0007z5-5V for guix-patches@gnu.org; Thu, 17 Mar 2022 02:25:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:58927) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nUjZF-0005O7-QN for guix-patches@gnu.org; Thu, 17 Mar 2022 02:25:01 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nUjZF-0007P2-Lt for guix-patches@gnu.org; Thu, 17 Mar 2022 02:25:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#54377] [PATCH 3/3] guix home: Add 'container' command. Resent-From: Andrew Tropin Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 17 Mar 2022 06:25:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 54377 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Ludovic =?UTF-8?Q?Court=C3=A8s?= , 54377@debbugs.gnu.org Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= Received: via spool by 54377-submit@debbugs.gnu.org id=B54377.164749826328403 (code B ref 54377); Thu, 17 Mar 2022 06:25:01 +0000 Received: (at 54377) by debbugs.gnu.org; 17 Mar 2022 06:24:23 +0000 Received: from localhost ([127.0.0.1]:52824 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nUjYc-0007O1-2y for submit@debbugs.gnu.org; Thu, 17 Mar 2022 02:24:23 -0400 Received: from mail-lj1-f181.google.com ([209.85.208.181]:38478) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nUjYZ-0007Nn-Qj for 54377@debbugs.gnu.org; Thu, 17 Mar 2022 02:24:21 -0400 Received: by mail-lj1-f181.google.com with SMTP id s25so5961578lji.5 for <54377@debbugs.gnu.org>; Wed, 16 Mar 2022 23:24:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=trop-in.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:in-reply-to:references:date:message-id :mime-version; bh=7HzTX2G+/aQ6pGGnfDCOgtfaOW97JuFHMsM/yal9U34=; b=JOJcOEJp1bjIrMOhbc2LzNhL23TcqgzBDXo0Gqkktcn64czJH4BykHJ+q7ZeQdsaUr Db+LfdN9D/jOScjBMMSkwdzQgO0LKrmjjuctZkXIwFr4FU3PkaYaFU791Pb7r+5I6Rgz kAO7dJhsIoMUyJhFwcpLKzV40l9BbDGdqM8PZizfztm9PVuRLBcGkyVI1UqHlZPhdvFd sQhKW+3UCAJ/t4JNhXlw4vdyZoVg1T5mCWZj5x3el80R8ONTDxGjhN8tLjBkEsxryZO2 4+Otz19jGN8R5Y/WIYJNemdTF8qPkOxKCKC01WVMsurJX7oyHoVnfJoz3DW3WO03Ky/b OVGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:in-reply-to:references:date :message-id:mime-version; bh=7HzTX2G+/aQ6pGGnfDCOgtfaOW97JuFHMsM/yal9U34=; b=WM0QEzhIrcUmJxFAt/bPQByQaDH40pG7DRS3B2fRWgm7okZq8wtCgN/pN4lF1MbxnT BB9dPLd6i6JBTYMe1j7pqXLfBQB4h6GpHmtUrt8o8EMsSyAG3LvMdu3UzlJXdHf6W/I8 KshySRwsrOZGZ5+zBi5Fhw14wM2W4y94txqlA0ty8S1TrqWbZw09sQaDBkpcoZgl/JRs UFWdBe3OUM9ObRmI00kx8It7liBSaaV2OatAeYawTEXpcz3gHYVaYLRlZkQJX86K02mz 7CQgD3PYJ4weko/6NDEfK0IGuAyX6DiSZeaH3YZqgHuZPdURjFXjQ5NywmwGceUk27cm 8K7A== X-Gm-Message-State: AOAM530G3NxHH4MUqCj7WQoLH6n62Ives9ydDKLNaG7juVsgsNd4qZNc XTEK/rZEpxjoPWZBbFwcad5zkg== X-Google-Smtp-Source: ABdhPJzXdzHhNeU5oExIQkYFVRjOw+KBXvxoEXtCaV1xg3ghEN9O7f2haS8sabOh91aQXSJHj9clew== X-Received: by 2002:a05:651c:516:b0:249:23ef:d9c7 with SMTP id o22-20020a05651c051600b0024923efd9c7mr1917615ljp.202.1647498252789; Wed, 16 Mar 2022 23:24:12 -0700 (PDT) Received: from localhost (109-252-132-136.dynamic.spd-mgts.ru. [109.252.132.136]) by smtp.gmail.com with ESMTPSA id be17-20020a05651c171100b00247eaff0ff0sm359491ljb.7.2022.03.16.23.24.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Mar 2022 23:24:12 -0700 (PDT) From: Andrew Tropin In-Reply-To: <20220313215454.9576-3-ludo@gnu.org> References: <20220313215454.9576-1-ludo@gnu.org> <20220313215454.9576-3-ludo@gnu.org> Date: Thu, 17 Mar 2022 09:24:09 +0300 Message-ID: <87y219hzau.fsf@trop.in> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1647498378; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:resent-cc:resent-from:resent-sender: resent-message-id:in-reply-to:in-reply-to:references:references: list-id:list-help:list-unsubscribe:list-subscribe:list-post: dkim-signature; bh=Xb0JevrJHeUfPuPfQ1jLWtWuENgQQOPlQD48uiaTxjw=; b=Uwt/O1wZm7oR1lQUSTYlVz7lhZIHCO662EpWnEuIP8+rO3VZfusn25B/tzyDM1/Al3mBIh k7wYpig4Qrl6SxGB7P+S55+hEFbJ3vOndixyfuG5dR+fGGooMhPhR2yX5w0rCAAjZK/3Ol fz/Zh80P/VJ0/oKdzQRfDLRVWgKWzv2dvLPJR1+qNV6xohul9fX+v7gZQxVgr8j2PecMrC /qXFvPHA1P5oEP8ks4j7/Ziq0SQX+9R/my4Wfwe0xBHHEbswSLnGPuleAu8K5FaINqFBNf YnmcTaYGD3h3PFmz+w/QnYCQyfsrw2vpsT59HiQGTQ3QXHB/QdLHQjpWLD1T1A== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1647498378; a=rsa-sha256; cv=none; b=Pat0WDoqIraBPgf7P6p5ilhc4ebE4BijZzykQsWuekDURlHpJQaVl2x401eXVSh8ZLFEch K2X9p7+5KqlY6+sW4cvDnoauAWh3XLJXzktMGo6WUT6dGpyFC6rgjJ+VEQFNSszwt6q6wk wia9WxCqdWVtfgiVHENltMP84hUm6O5LVhld/+Hc+lHcoIs04iPlcPyASV8t8zGe03/9OM COLFMFG7mzyz+zJQARr+tYlj4Y1oLBFUHbOd0ioD/pOWgc0TC3cnGZo79dDKth7U5kZvZX racvRga6KQPAqEYFQ/wQpscrrWPbICaZx76wvbi6+KsaKA280mEc3bIym5ET8A== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=trop-in.20210112.gappssmtp.com header.s=20210112 header.b=JOJcOEJp; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -1.96 Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=trop-in.20210112.gappssmtp.com header.s=20210112 header.b=JOJcOEJp; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 68CCF2F33A X-Spam-Score: -1.96 X-Migadu-Scanner: scn0.migadu.com X-TUID: DxOYMoQjLCp5 --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 2022-03-13 22:54, Ludovic Court=C3=A8s wrote: > * guix/scripts/home.scm (show-help, %options): Add '--network', > '--share', and '--expose'. > (not-config?, user-shell, spawn-home-container): New procedures. > (%default-system-profile): New variable. > (perform-action): Add #:file-system-mappings, #:container-command, > and #:network?; honor them. > (process-action): Adjust accordingly. > (guix-home)[parse-sub-command]: Add "container". > [parse-args]: New procedure. > Use it instead of 'parse-command-line'. > * tests/guix-home.sh: Add tests. > * doc/guix.texi (Declaring the Home Environment): Mention 'guix home > container' as a way to test configuration. > (Invoking guix home): Document it. > --- > doc/guix.texi | 58 +++++++++ > guix/scripts/home.scm | 271 ++++++++++++++++++++++++++++++++++++++---- > tests/guix-home.sh | 58 ++++++--- > 3 files changed, 349 insertions(+), 38 deletions(-) > > diff --git a/doc/guix.texi b/doc/guix.texi > index 4b71fb7010..ba9199f336 100644 > --- a/doc/guix.texi > +++ b/doc/guix.texi > @@ -38071,6 +38071,21 @@ be confused with Shepherd services (@pxref{Sheph= erd 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. >=20=20 > +@cindex container, for @command{guix home} > +Once the configuration looks good, you can first test it in a throw-away > +``container'': > + > +@example > +guix home container config.scm > +@end example > + > +The command above spawns a shell where your home environment is running. > +The shell runs in a container, meaning it's isolated from the rest of > +the system, so it's a good way to try out your configuration---you can > +see if configuration bits are missing or misbehaving, if daemons get > +started, and so on. Once you exit that shell, you're back to the prompt > +of your original shell ``in the real world''. > + > Once you have a configuration file that suits your needs, you can > reconfigure your home by running: >=20=20 > @@ -38699,6 +38714,49 @@ As for @command{guix search}, the result is writ= ten in > @code{recutils} format, which makes it easy to filter the output > (@pxref{Top, GNU recutils databases,, recutils, GNU recutils manual}). >=20=20 > +@cindex container, for @command{guix home} > +@item container > +Spawn a shell in an isolated environment---a > +@dfn{container}---containing your home as specified by @var{file}. > + > +For example, this is how you would start an interactive shell in a s/interactive/login ? or interactive login shell > +container with your home: > + > +@example > +guix home container config.scm > +@end example > + > +This is a throw-away container where you can lightheartedly fiddle with > +files; any changes made within the container, any process started---all > +this disappears as soon as you exit that shell. > + > +As with @command{guix shell}, several options control that container: > + > +@table @option > +@item --network > +@itemx -N > +Enable networking within the container (it is disabled by default). > + > +@item --expose=3D@var{source}[=3D@var{target}] > +@itemx --share=3D@var{source}[=3D@var{target}] > +As with @command{guix shell}, make directory @var{source} of the host > +system available as @var{target} inside the container---read-only if you > +pass @option{--expose}, and writable if you pass @option{--share} > +(@pxref{Invoking guix shell, @option{--expose} and @option{--share}}). > +@end table > + > +Additionally, you can run a command in that container, instead of > +spawning an interactive shell. For instance, here is how you would In fact the sentence is correct, but gives a feeling that the shell won't be executed at all. Don't know if we need to change it somehow. > +check which Shepherd services are started in a throw-away home > +container: > + > +@example > +guix home container config.scm -- herd status > +@end example > + > +The command to run in the container must come after @code{--} (double > +hyphen). > + > @item reconfigure > Build the home environment described in @var{file}, and switch to it. > Switching means that the activation script will be evaluated and (in > diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm > index 837fd96361..b422cd36e2 100644 > --- a/guix/scripts/home.scm > +++ b/guix/scripts/home.scm > @@ -23,8 +23,21 @@ (define-module (guix scripts home) > #:use-module (gnu packages admin) > #:use-module ((gnu services) #:hide (delete)) > #:use-module (gnu packages) > + #:autoload (gnu packages base) (coreutils) > + #:autoload (gnu packages bash) (bash) > + #:autoload (gnu packages gnupg) (guile-gcrypt) > + #:autoload (gnu packages shells) (fish gash zsh) > #:use-module (gnu home) > #:use-module (gnu home services) > + #:autoload (guix modules) (source-module-closure) > + #:autoload (gnu build linux-container) (call-with-container %namespa= ces) > + #:autoload (gnu system linux-container) (eval/container) > + #:autoload (gnu system file-systems) (file-system-mapping > + file-system-mapping-source > + file-system-mapping->bind-mount > + specification->file-system-map= ping > + %network-file-mappings) > + #:autoload (guix self) (make-config.scm) > #:use-module (guix channels) > #:use-module (guix derivations) > #:use-module (guix ui) > @@ -48,6 +61,7 @@ (define-module (guix scripts home) > #:use-module (srfi srfi-26) > #:use-module (srfi srfi-35) > #:use-module (srfi srfi-37) > + #:use-module (srfi srfi-71) > #:use-module (ice-9 match) > #:export (guix-home)) >=20=20 > @@ -95,6 +109,16 @@ (define (show-help) > (display (G_ " > --allow-downgrades for 'reconfigure', allow downgrades to earlier > channel revisions")) > + (newline) > + (display (G_ " > + -N, --network allow containers to access the network")) Is plural form intended? > + (display (G_ " > + --share=3DSPEC for containers, share writable host file syst= em > + according to SPEC")) > + (display (G_ " > + --expose=3DSPEC for containers, expose read-only host file sy= stem > + according to SPEC")) > + (newline) > (display (G_ " > -v, --verbosity=3DLEVEL use the given verbosity LEVEL")) > (newline) > @@ -136,6 +160,22 @@ (define %options > (alist-cons 'validate-reconfigure > warn-about-backward-reconfigure > result))) > + > + ;; Container options. > + (option '(#\N "network") #f #f > + (lambda (opt name arg result) > + (alist-cons 'network? #t result))) > + (option '("share") #t #f > + (lambda (opt name arg result) > + (alist-cons 'file-system-mapping > + (specification->file-system-mapping arg #= t) > + result))) > + (option '("expose") #t #f > + (lambda (opt name arg result) > + (alist-cons 'file-system-mapping > + (specification->file-system-mapping arg #= f) > + result))) > + > %standard-build-options)) >=20=20 > (define %default-options > @@ -149,6 +189,146 @@ (define %default-options > (debug . 0) > (validate-reconfigure . ,ensure-forward-reconfigure))) >=20=20 > + > +;;; > +;;; Container. > +;;; > + > +(define not-config? > + ;; Select (guix =E2=80=A6) and (gnu =E2=80=A6) modules, except (guix c= onfig). > + (match-lambda > + (('guix 'config) #f) > + (('guix _ ...) #t) > + (('gnu _ ...) #t) > + (_ #f))) > + > +(define (user-shell) > + (match (and=3D> (or (getenv "SHELL") Be aware that in some cases $SHELL can differ from the value in /etc/passwd. For example I set SHELL to the full path to zsh and all interactive non-login shells are zsh for me, but my login shell is bash. > + (passwd:shell (getpwuid (getuid)))) > + basename) > + ("zsh" (file-append zsh "/bin/zsh")) > + ("fish" (file-append fish "/bin/fish")) > + ("gash" (file-append gash "/bin/gash")) > + (_ (file-append bash "/bin/bash")))) Why we use hardcoded shell packages? 1. The will be built in case user use a zsh-patched for example. 2. The version of the shell in the container can differ from one user expects. 3. $SHELL and the value in /etc/passwd should be absolute paths to the store already, we can just add a check and throw an exception if $SHELL is misscofigured and the path isn't absolute. > + > +(define %default-system-profile > + ;; The "system" profile available when running 'guix home container'. = The > + ;; activation script currently expects to run "env -0" (XXX), so provi= de > + ;; Coreutils by default. > + (delay (profile > + (name "home-system-profile") > + (content (packages->manifest (list coreutils)))))) > + > +(define* (spawn-home-container home > + #:key > + network? > + (command '()) > + (mappings '()) > + (system-profile > + (force %default-system-profile))) > + "Spawn a login shell within a container running HOME, a home environme= nt. > +When COMMAND is a non-empty list, execute it in the container and exit > +immediately. Return the exit status of the process in the container." > + (define passwd (getpwuid (getuid))) > + (define home-directory (or (getenv "HOME") (passwd:dir passwd))) > + (define host (gethostname)) > + (define uid 1000) > + (define gid 1000) > + (define user-name (passwd:name passwd)) > + (define user-real-name (passwd:gecos passwd)) > + > + (define (optional-mapping mapping) > + (and (file-exists? (file-system-mapping-source mapping)) > + mapping)) > + > + (define network-mappings > + (if network? > + (filter-map optional-mapping %network-file-mappings) > + '())) > + > + (eval/container > + (with-extensions (list guile-gcrypt) > + (with-imported-modules `(((guix config) =3D> ,(make-config.scm)) > + ,@(source-module-closure > + '((gnu build accounts) > + (guix profiles) > + (guix build utils) > + (guix build syscalls)) > + #:select? not-config?)) > + #~(begin > + (use-modules (guix build utils) > + (gnu build accounts) > + ((guix build syscalls) > + #:select (set-network-interface-up))) > + > + (define shell > + #$(user-shell)) > + > + (define term > + #$(getenv "TERM")) > + > + (define passwd > + (password-entry > + (name #$user-name) > + (real-name #$user-real-name) > + (uid #$uid) (gid #$gid) (shell shell) > + (directory #$home-directory))) > + > + (define groups > + (list (group-entry (name "users") (gid #$gid)) > + (group-entry (gid 65534) ;the overflow GID > + (name "overflow")))) > + > + ;; (guix profiles) loads (guix utils), which calls 'getpw' fr= om the > + ;; top level. Thus, arrange so that it's loaded after /etc/p= asswd > + ;; has been created. > + (module-autoload! (current-module) > + '(guix profiles) '(load-profile)) > + > + ;; Create /etc/passwd for applications that need it, such as = mcron. > + (mkdir-p "/etc") > + (write-passwd (list passwd)) > + (write-group groups) > + > + (unless #$network? > + ;; When isolated from the network, provide a minimal /etc/h= osts > + ;; to resolve "localhost". > + (call-with-output-file "/etc/hosts" > + (lambda (port) > + (display "127.0.0.1 localhost\n" port) > + (chmod port #o444)))) > + > + ;; Set PATH for things that the activation script might expec= t, such > + ;; as "env". > + (load-profile #$system-profile) > + > + (mkdir-p #$home-directory) > + (setenv "HOME" #$home-directory) > + (setenv "GUIX_NEW_HOME" #$home) > + (primitive-load (string-append #$home "/activate")) > + (setenv "GUIX_NEW_HOME" #f) > + > + (when term > + ;; Preserve TERM for proper interactive use. > + (setenv "TERM" term)) Just a note: the shell can missbehave if terminfo files for current TERM isn't present in the container (for example terminal package was removed from home profile). Idk how to properly cover this, but just letting you know. We can use TERM=3Ddumb, but I'm not sure if it worth it. > + > + (chdir #$home-directory) > + > + ;; Invoke SHELL with argv[0] starting with "-": that's how sh= ells > + ;; figure out that they are login shells! > + (execl shell (string-append "-" (basename shell)) > + #$@(match command > + (() #~()) > + ((_ ...) > + #~("-c" #$(string-join command)))))))) > + > + #:namespaces (if network? > + (delq 'net %namespaces) ; share host network > + %namespaces) > + #:mappings (append network-mappings mappings) > + #:guest-uid uid > + #:guest-gid gid)) > + > > ;;; > ;;; Actions. > @@ -159,7 +339,12 @@ (define* (perform-action action he > dry-run? > derivations-only? > use-substitutes? > - (validate-reconfigure ensure-forward-reconfigur= e)) > + (validate-reconfigure ensure-forward-reconfigur= e) > + > + ;; Container options. > + (file-system-mappings '()) > + (container-command '()) > + network?) > "Perform ACTION for home environment. " >=20=20 > (define println > @@ -180,24 +365,37 @@ (define println > (he-out-path -> (derivation->output-path he-drv))) > (if (or dry-run? derivations-only?) > (return #f) > - (begin > - (for-each (compose println derivation->output-path) drvs) > + (case action > + ((reconfigure) > + (let* ((number (generation-number %guix-home)) > + (generation (generation-file-name > + %guix-home (+ 1 number)))) >=20=20 > - (case action > - ((reconfigure) > - (let* ((number (generation-number %guix-home)) > - (generation (generation-file-name > - %guix-home (+ 1 number)))) > - > - (switch-symlinks generation he-out-path) > - (switch-symlinks %guix-home generation) > - (setenv "GUIX_NEW_HOME" he-out-path) > - (primitive-load (string-append he-out-path "/activate")) > - (setenv "GUIX_NEW_HOME" #f) > - (return he-out-path))) > - (else > - (newline) > - (return he-out-path))))))) > + (switch-symlinks generation he-out-path) > + (switch-symlinks %guix-home generation) > + (setenv "GUIX_NEW_HOME" he-out-path) > + (primitive-load (string-append he-out-path "/activate")) > + (setenv "GUIX_NEW_HOME" #f) > + (return he-out-path))) > + ((container) > + (mlet %store-monad ((status (spawn-home-container > + he > + #:network? network? > + #:mappings file-system-mappings > + #:command > + container-command))) > + (match (status:exit-val status) > + (0 (return #t)) > + ((? integer? n) (return (exit n))) > + (#f > + (if (status:term-sig status) > + (leave (G_ "process terminated with signal ~a~%") > + (status:term-sig status)) > + (leave (G_ "process stopped with signal ~a~%") > + (status:stop-sig status))))))) > + (else > + (for-each (compose println derivation->output-path) drvs) > + (return he-out-path)))))) >=20=20 > (define (process-action action args opts) > "Process ACTION, a sub-command, with the arguments are listed in ARGS. > @@ -236,6 +434,10 @@ (define (ensure-home-environment file-or-exp obj) > (else > (leave (G_ "no configuration specified~%"))))))) >=20=20 > + (mappings (filter-map (match-lambda > + (('file-system-mapping . mapping) ma= pping) > + (_ #f)) > + opts)) > (dry? (assoc-ref opts 'dry-run?))) >=20=20 > (with-store store > @@ -256,7 +458,11 @@ (define (ensure-home-environment file-or-exp obj) > #:derivations-only? (assoc-ref opts 'derivat= ions-only?) > #:use-substitutes? (assoc-ref opts 'substitu= tes?) > #:validate-reconfigure > - (assoc-ref opts 'validate-reconfigure)))))) > + (assoc-ref opts 'validate-reconfigure) > + #:network? (assoc-ref opts 'network?) > + #:file-system-mappings mappings > + #:container-command > + (or (assoc-ref opts 'container-command) '())= ))))) > (warn-about-disk-space))) >=20=20 >=20=20 > @@ -345,7 +551,7 @@ (define (parse-sub-command arg result) > list-generations describe > delete-generations roll-back > switch-generation search > - import) > + import container) > (alist-cons 'action action result)) > (else (leave (G_ "~a: unknown action~%") action)))))) >=20=20 > @@ -383,11 +589,28 @@ (define (fail) > (fail)))) > args)) >=20=20 > + (define (parse-args args) > + ;; Parse the list of command line arguments ARGS. > + > + ;; The '--' token is used to separate the command to run from the re= st of > + ;; the operands. > + (let* ((args rest (break (cut string=3D? "--" <>) args)) > + (opts (parse-command-line args %options (list %default-option= s) > + #:argument-handler > + parse-sub-command))) > + (match rest > + (() opts) > + (("--") opts) > + (("--" command ...) > + (match (assoc-ref opts 'action) > + ('container > + (alist-cons 'container-command command opts)) > + (_ > + (leave (G_ "~a: extraneous command~%") > + (string-join command)))))))) > + > (with-error-handling > - (let* ((opts (parse-command-line args %options > - (list %default-options) > - #:argument-handler > - parse-sub-command)) > + (let* ((opts (parse-args args)) > (args (option-arguments opts)) > (command (assoc-ref opts 'action))) > (parameterize ((%graft? (assoc-ref opts 'graft?))) > diff --git a/tests/guix-home.sh b/tests/guix-home.sh > index f054d15172..13c02d6269 100644 > --- a/tests/guix-home.sh > +++ b/tests/guix-home.sh > @@ -26,6 +26,16 @@ set -e >=20=20 > guix home --version >=20=20 > +container_supported () > +{ > + if guile -c '((@ (guix scripts environment) assert-container-feature= s))' > + then > + return 0 > + else > + return 1 > + fi > +} > + > NIX_STORE_DIR=3D"$(guile -c '(use-modules (guix config))(display %stored= ir)')" > localstatedir=3D"$(guile -c '(use-modules (guix config))(display %locals= tatedir)')" > GUIX_DAEMON_SOCKET=3D"$localstatedir/guix/daemon-socket/socket" > @@ -47,20 +57,6 @@ trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_di= rectory"' EXIT > ( > cd "$test_directory" || exit 77 >=20=20 > - HOME=3D"$test_directory" > - export HOME > - > - # > - # Test 'guix home reconfigure'. > - # > - > - echo "# This file will be overridden and backed up." > "$HOME/.bashr= c" > - mkdir "$HOME/.config" > - echo "This file will be overridden too." > "$HOME/.config/test.conf" > - echo "This file will stay around." > "$HOME/.config/random-file" > - > - echo -n "# dot-bashrc test file for guix home" > "dot-bashrc" > - > cat > "home.scm" <<'EOF' > (use-modules (guix gexp) > (gnu home) > @@ -93,6 +89,40 @@ trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_di= rectory"' EXIT > "# the content of bashrc-test-config.sh")))))))) > EOF >=20=20 > + echo -n "# dot-bashrc test file for guix home" > "dot-bashrc" > + > + > + if container_supported > + then > + # Run the home in a container. > + guix home container home.scm -- true > + ! guix home container home.scm -- false > + test "$(guix home container home.scm -- echo '$HOME')" =3D "$HOME" > + guix home container home.scm -- cat '~/.config/test.conf' | \ > + grep "the content of" > + guix home container home.scm -- test -h '~/.bashrc' > + test "$(guix home container home.scm -- id -u)" =3D 1000 > + ! guix home container home.scm -- test -f '$HOME/sample/home.scm' > + guix home container home.scm --expose=3D"$PWD=3D$HOME/sample" -- \ > + test -f '$HOME/sample/home.scm' > + ! guix home container home.scm --expose=3D"$PWD=3D$HOME/sample" -- \ > + rm -v '$HOME/sample/home.scm' > + else > + echo "'guix home container' test SKIPPED" >&2 > + fi > + > + HOME=3D"$test_directory" > + export HOME > + > + # > + # Test 'guix home reconfigure'. > + # > + > + echo "# This file will be overridden and backed up." > "$HOME/.bashr= c" > + mkdir "$HOME/.config" > + echo "This file will be overridden too." > "$HOME/.config/test.conf" > + echo "This file will stay around." > "$HOME/.config/random-file" > + > guix home reconfigure "${test_directory}/home.scm" > test -d "${HOME}/.guix-home" > test -h "${HOME}/.bash_profile" Very cool feature! Looking forward to add it to my workflow.=20 =2D-=20 Best regards, Andrew Tropin --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQJDBAEBCgAtFiEEKEGaxlA4dEDH6S/6IgjSCVjB3rAFAmIy1AkPHGFuZHJld0B0 cm9wLmluAAoJECII0glYwd6wkOoQAIk1tQ4Mgc09D3XcPreRqRcSLvt+/Ln+TQST TSGYgjav5DJ3pjulMh/o2LizMgJCvOy4/HAmFy/mvU8sICYfpg3+ycLFIcUGc76A 4YfP64gjowr+yVqxDjdu7hToz00jMH9LYjzTTpco8RUvhJth1Iwgw3YcDOH7S7kk sAVqHgo3PE/fKQXvbT136Hr2+P0txxuvXaCNFvsW8qxaLUkNDxR3nzIe8MylQlZ4 dethGByEEw+fsSky1nR3AIDizhrhEm1MvlKNNxgcpEck0VF2xb5LRc9JVlnlq8qV GH8ZGT7zls2FGIthzF63nQ8KTSesmhGNcigU76HSL9PmkPa2Id1IXf95vewHM4f0 4YrU3GvVzcO/BYqjxhAmBzmdx5u3hoxkTqenHVcwB5dJntSwWUnlHNzqjQhaenoo eXu+pGon2GdLNtKtE//idTImzuA6aPnxMq8zS55qLXUwLDzgeYLwWF+PjZBNQdfU KceYXRcXnBDv+2MZ7BQ+EGtRgO4EDxsgJyV1RRSMapyfYVcjTozc7cFY/ygcrHdS AiUPV+4rUbpMQxhAeW1JvpxFDLLryuNnNHcbywHdoTc/Kq0xtYpCyj9LVBBdWV1f XRYQiUz63wtstVjNdzVcqpOdZ7PeblAwUIzFHMy9PtnqR4gfnqozm9FhRrdn2mOI Uzmx3l// =9oQN -----END PGP SIGNATURE----- --=-=-=--