From c3eea81846ae71a246e6b592be74062f4bf26474 Mon Sep 17 00:00:00 2001 From: Chris Marusich Date: Sun, 13 Feb 2022 14:15:14 -0800 Subject: [PATCH] environment: Prevent PS1 from clobbering output in 'check'. Fixes: . * guix/scripts/environment.scm (child-shell-environment): In the script executed the child shell, set PS1 to an empty value and then echo three sentinel lines to try to "flush" the original PS1 value before printing the environment variables. In the parent process, read and discard all lines up to and including the last sentinel line. After that, read the remaining lines as usual. --- guix/scripts/environment.scm | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index ec071402f4..0b137467f9 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2014, 2015, 2018 David Thompson ;;; Copyright © 2015-2022 Ludovic Courtès ;;; Copyright © 2018 Mike Gerwitz +;;; Copyright © 2022 Chris Marusich ;;; ;;; This file is part of GNU Guix. ;;; @@ -420,7 +421,16 @@ by running 'set' in the shell." ;; 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") + ;; + ;; Why print "GUIX_FLUSH" a few times? We are trying to "flush" the + ;; original PS1 value to the port so we can read it (and discard it) + ;; before we start reading the environment variables from the port. If we + ;; don't do this, the original PS1 value can sometimes get interleaved + ;; into the output, which interferes with our parsing logic. It's a hack, + ;; but in practice it seems to do the job. If you know of a more graceful + ;; solution, please implement it! See: https://issues.guix.gnu.org/51466 + "PS1=; for i in 1 2 3; do echo GUIX_FLUSH_$i; done; \ +env || /usr/bin/env || set; echo GUIX-CHECK-DONE; read x; exit\n") (define lines (match (primitive-fork) @@ -439,6 +449,12 @@ by running 'set' in the shell." (let* ((port (fdopen controller "r+l")) (result (begin (display script port) + ;; Ignore all lines up to and including the final + ;; "GUIX_FLUSH" line. + (while (not (string=? "GUIX_FLUSH_3\r" + (read-line port)))) + ;; Now (hopefully) the original PS1 value will not be + ;; interleaved in the remaining lines. (let loop ((lines '())) (match (read-line port) ((? eof-object?) (reverse lines)) base-commit: d65979c46c99dc36324ca94aa9650b9de37f22de -- 2.26.3