Ludovic Courtès writes: [...] >> +(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. ;-)) > Done. Very elegant. >> + (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. > Done. Flag changed to '-E', and '-e'/'--expression' flag added. I wrote my another version of 'options/resolve-packages' since my needs are different than 'guix build'. >> +(define %default-options >> + ;; Default to opening a new shell. >> + `((exec . ,(getenv "SHELL")) > > (or (getenv "SHELL") "/bin/sh") > Done. >> +(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.) > Great point. Done. >> +;; 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. > Done. Updated patch attached. Thanks for the feedback!