guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] scripts: Add 'environment' command.


From: Ludovic Courtès
Subject: Re: [PATCH] scripts: Add 'environment' command.
Date: Thu, 09 Oct 2014 21:30:43 +0200
User-agent: Gnus/5.130011 (Ma Gnus v0.11) Emacs/24.3 (gnu/linux)

Hey!

David Thompson <address@hidden> skribis:

> The purpose of 'guix environment' is to assist hackers in creating
> reproducible development environments without polluting their package
> profile.  'guix environment' takes a package (or packages), builds all
> of the necessary inputs, and creates a shell environment to use them.

Awesome!

[...]

> By default, running 'guix environment' spawns a new $SHELL process,
> because it is usually what one would want to do.  However, the '--exec'
> flag can be used to specify the command to run.
>
> Additionally, the default behavior is to prepend search paths to the
> existing environment variable values so that one has access to other
> installed software e.g. git.  To clear the existing environment firstf,
> the '--pure' flag can be used.
>
> Finally, the '--load' flag can be used to read a package from a file
> instead of searching $GUIX_PACKAGE_PATH.

This looks good to me.

> From 298dcc1dd3aac49e033debeea154c91b25229c14 Mon Sep 17 00:00:00 2001
> From: David Thompson <address@hidden>
> Date: Sun, 21 Sep 2014 13:40:05 -0400
> Subject: [PATCH] scripts: Add 'environment' command.
>
> * guix/scripts/environment.scm: New file.
> * Makefile.am (MODULES): Add it.

[...]

> +(define (purify-environment)
> +  "Unset almost all environment variables.  A small number of variables such
> +as 'HOME' and 'USER' are left untouched."
> +  (for-each unsetenv
> +            (filter (lambda (variable)
> +                      ;; Protect some env vars from purification.  Borrowed
> +                      ;; from nix-shell.
> +                      (not (member variable
> +                                   '("HOME" "USER" "LOGNAME" "DISPLAY"
> +                                     "TERM" "TZ" "PAGER"))))
> +                    (map car (get-environment-variables)))))

Maybe put the list of env. vars in a global variable, say
‘%precious-variables’, and then:

  (remove (cut member <> %precious-variables)
          (match (get-environment-variables)
            (((names . values) ...)
             names)))

(My allergy to ‘car’ goes this far.  ;-))

> +  (display (_ "
> +  -e, --exec             shell command to execute"))

Perhaps make it -E, and use -e consistently with ‘guix build’?  It may
be possible to reuse ‘options/resolve-packages’ for that.

> +(define %default-options
> +  ;; Default to opening a new shell.
> +  `((exec . ,(getenv "SHELL"))

(or (getenv "SHELL") "/bin/sh")

> +(define (build-inputs inputs opts)
> +  "Build the packages in INPUTS using the build options in OPTS."
> +  (with-store store
> +    (run-with-store store
> +      (mlet* %store-monad ((drvs (sequence %store-monad
> +                                           (map package->derivation 
> inputs))))
> +        (mbegin %store-monad
> +          (show-what-to-build* drvs
> +                               #:use-substitutes? (assoc-ref opts 
> 'substitutes?)
> +                               #:dry-run? #f)
> +          (set-build-options-from-command-line* opts)
> +          (built-derivations drvs)
> +          (return drvs))))))

The store should rather be kept open around (system command).  Otherwise
the above derivations and their outputs could be GC’d (it should be
possible to check that by trying to run ‘guix gc -d XXX’ on one of them
from within the sub-shell.)

> +;; Entry point.
> +(define (guix-environment . args)
> +  (define (parse-options)
> +    (args-fold* args %options
> +                (lambda (opt name arg result)
> +                  (leave (_ "~A: unrecognized option~%") name))
> +                (lambda (arg result)
> +                  (alist-cons 'package arg result))
> +                %default-options))
> +
> +  (let* ((opts (parse-options))
> +         (pure? (assoc-ref opts 'pure))
> +         (command (assoc-ref opts 'exec))
> +         ;; Load from file if given, otherwise search for packages.
> +         (inputs (packages->transitive-inputs
> +                  (or (and=> (assoc-ref opts 'load) load)
> +                      (map specification->package
> +                           (pick-all opts 'package)))))
> +         (drvs (build-inputs inputs opts)))

Would be good to honor --dry-run as well.  It would just print what
needs to be built and exit.

Thank you!

Ludo’.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]