unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Buffer-local process environments
@ 2021-04-29 10:56 Augusto Stoffel
  2021-04-29 12:30 ` Eli Zaretskii
                   ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-29 10:56 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2503 bytes --]

When developing software, it's often not possible or desirable to
install compilers and related tools globally, so (barring the
availability of fancy build tools) one has to fiddle with environment
variables.

Currently it's quite hard to set up Emacs to interact correctly with
external tools on a per-project basis, because there is no unified way
adjust the environment.  For instance:

- `M-x compile' has the `compilation-environment' variable.
- python-mode uses `python-shell-virtualenv-root' when launching a
  REPL.
- Eglot provides no other mechanism than setting `exec-path' and
  `process-environment' buffer-locally.
- etc.

Of course, the buffer-local variable approach will work with any
command that doesn't switch buffers, even if that command invents its
own method to adjust the environment.

So why not make buffer-local process environments an official thing?
By this I mean:

1. Fix commands that start external processes after switching buffers
   to do what the user means.

2. Provide a convenient way to set the process environment buffer
   locally.

Point 1 is simple.  I've attached a patch for `compile' as an example.
In the Python REPL case, I'm not sure whether it would be better to
just adapt `run-python' or make a change in comint itself.

Proposal for point 2
--------------------

Add two more special keywords to the file local variable mechanism
(besides `mode', `eval', etc):

- `env' to add an entry to `process-environment'.
- `path' to add an entry to `exec-path' and modify the PATH variable at
  the same time.

Hence, the local variables section of a Python file might look like
this:

# Local Variables:
# path: "~/path/to/some/virtualenv/bin"
# env: "VIRTUAL_ENV=$HOME/path/to/some/virtualenv"
# env: "LANG=C"
# End:

Of course, in practice it's more useful to include this in
.dir-locals.el, but the mechanism is the same.

Closing remarks
---------------

As an indication that this is a real problem, let me point out a list
of MELPA packages just to deal with Python virtualenvs:

- auto-virtualenv
- auto-virtualenvwrapper
- conda
- pungi
- python-environment
- pyvenv
- virtualenv
- virtualenvwrapper

I've tried a couple of those and was never satisfied.

My proposal here is inspired by the `inherienv' [1] and `envrc' [2]
MELPA packages.  The former provides an advice to solve point 1, the
latter solves point 2 by means of an external program called direnv.

[1]: https://github.com/purcell/inheritenv/
[2]: https://github.com/purcell/envrc


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Make-compile-respect-buffer-local-process-environmen.patch --]
[-- Type: text/x-patch, Size: 1877 bytes --]

From ece87c73bcb5f8e2a59769cfe981c1486e19857b Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <arstoffel@gmail.com>
Date: Thu, 29 Apr 2021 12:45:04 +0200
Subject: [PATCH] Make `compile' respect buffer-local process environment

* lisp/progmodes/compile.el (compilation-start): Use
`process-environment' from original buffer in the compilation process.
---
 lisp/progmodes/compile.el | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 7a02c3a896..ee73f03c93 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -1779,6 +1779,8 @@ compilation-start
 	    (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
 	 (thisdir default-directory)
 	 (thisenv compilation-environment)
+         (this-process-environment process-environment)
+         (env-buffer (when (local-variable-p 'process-environment) (buffer-name)))
 	 outwin outbuf)
     (with-current-buffer
 	(setq outbuf
@@ -1856,6 +1858,9 @@ compilation-start
 		"; default-directory: "
                 (prin1-to-string (abbreviate-file-name default-directory))
 		" -*-\n"
+                (if env-buffer
+                    (format "Process environment is local to buffer `%s'\n" env-buffer)
+                  "")
 		(format "%s started at %s\n\n"
 			mode-name
 			(substring (current-time-string) 0 19))
@@ -1875,7 +1880,7 @@ compilation-start
               (and (derived-mode-p 'comint-mode)
                    (comint-term-environment))
 	      (list (format "INSIDE_EMACS=%s,compile" emacs-version))
-	      (copy-sequence process-environment))))
+	      (copy-sequence this-process-environment))))
         (setq-local compilation-arguments
                     (list command mode name-function highlight-regexp))
         (setq-local revert-buffer-function 'compilation-revert-buffer)
-- 
2.30.2


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 10:56 Buffer-local process environments Augusto Stoffel
@ 2021-04-29 12:30 ` Eli Zaretskii
  2021-04-29 12:40   ` Augusto Stoffel
  2021-04-29 14:02 ` Stefan Monnier
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 24+ messages in thread
From: Eli Zaretskii @ 2021-04-29 12:30 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

> From: Augusto Stoffel <arstoffel@gmail.com>
> Date: Thu, 29 Apr 2021 12:56:36 +0200
> 
> When developing software, it's often not possible or desirable to
> install compilers and related tools globally, so (barring the
> availability of fancy build tools) one has to fiddle with environment
> variables.
> 
> Currently it's quite hard to set up Emacs to interact correctly with
> external tools on a per-project basis, because there is no unified way
> adjust the environment.  For instance:
> 
> - `M-x compile' has the `compilation-environment' variable.
> - python-mode uses `python-shell-virtualenv-root' when launching a
>   REPL.
> - Eglot provides no other mechanism than setting `exec-path' and
>   `process-environment' buffer-locally.
> - etc.

Can you explain why Eglot's way does not provide a solution for these
situations?

Thanks.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 12:30 ` Eli Zaretskii
@ 2021-04-29 12:40   ` Augusto Stoffel
  2021-04-29 12:52     ` Eli Zaretskii
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-29 12:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On Thu, 29 Apr 2021 at 15:30, Eli Zaretskii <eliz@gnu.org> wrote:

> Can you explain why Eglot's way does not provide a solution for these
> situations?

Unlike, say, M-x compile with its `compilation-environment' variable,
Eglot does not provide its own mechanism to specify the environment in
which a language server is executed.  (For the record, I think this is
the correct thing to do.)

Still, there are several options to make Eglot launch the correct
language server: you can write a little wrapper script for language
server, or launch Emacs from a terminal with the correct environment,
etc, etc.  But setting `process-environment' and `exec-path'
buffer-locally is by far the most pleasant option in my opinion.

>
> Thanks.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 12:40   ` Augusto Stoffel
@ 2021-04-29 12:52     ` Eli Zaretskii
  2021-04-29 13:06       ` Augusto Stoffel
  0 siblings, 1 reply; 24+ messages in thread
From: Eli Zaretskii @ 2021-04-29 12:52 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

> From: Augusto Stoffel <arstoffel@gmail.com>
> Cc: emacs-devel@gnu.org
> Date: Thu, 29 Apr 2021 14:40:26 +0200
> 
> On Thu, 29 Apr 2021 at 15:30, Eli Zaretskii <eliz@gnu.org> wrote:
> 
> > Can you explain why Eglot's way does not provide a solution for these
> > situations?
> 
> Unlike, say, M-x compile with its `compilation-environment' variable,
> Eglot does not provide its own mechanism to specify the environment in
> which a language server is executed.  (For the record, I think this is
> the correct thing to do.)
> 
> Still, there are several options to make Eglot launch the correct
> language server: you can write a little wrapper script for language
> server, or launch Emacs from a terminal with the correct environment,
> etc, etc.  But setting `process-environment' and `exec-path'
> buffer-locally is by far the most pleasant option in my opinion.

That's exactly why I asked: you said that Eglot provides the ability
to do the latter, so it sounds like the correct solution is for all
the other packages to follow Eglot's example, no?



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 12:52     ` Eli Zaretskii
@ 2021-04-29 13:06       ` Augusto Stoffel
  0 siblings, 0 replies; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-29 13:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

On Thu, 29 Apr 2021 at 15:52, Eli Zaretskii <eliz@gnu.org> wrote:

> That's exactly why I asked: you said that Eglot provides the ability
> to do the latter, so it sounds like the correct solution is for all
> the other packages to follow Eglot's example, no?

Yes, I believe it's correct for all other packages and commands to
follow Eglot's example and not break if the environment or exec-path are
set buffer-locally.

In Eglot's case, this is not a big feat, since it calls make-process in
without ever changing buffers.  For other packages and commands, a bit
of extra care may be necessary (cf. my patch to `compile').



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 10:56 Buffer-local process environments Augusto Stoffel
  2021-04-29 12:30 ` Eli Zaretskii
@ 2021-04-29 14:02 ` Stefan Monnier
  2021-04-29 17:26   ` Augusto Stoffel
  2021-04-29 15:37 ` Michael Albinus
  2021-05-02 13:45 ` Stephen Leake
  3 siblings, 1 reply; 24+ messages in thread
From: Stefan Monnier @ 2021-04-29 14:02 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

> So why not make buffer-local process environments an official thing?

Sounds fine to me.

To fix cases like `compile` or `run-python`, I think patches would be
welcome regardless of what is decided in this discussion: those
behaviors look like plain bugs to me.

> # Local Variables:
> # path: "~/path/to/some/virtualenv/bin"
> # env: "VIRTUAL_ENV=$HOME/path/to/some/virtualenv"
> # env: "LANG=C"
> # End:

A few comments:
- I don't much like "special local vars" (like `eval` and `mode`), so if
  we can find a more general solution (i.e. one that can be useful for
  other settings), that would be better.  Maybe

    # push exec-path: "~/path/to/some/virtualenv/bin"

- both `exec-path` and `process-environment` are "dangerous" variables,
  so encouraging such uses sounds rather risky.

- I'd write `path` above as `exec-path` or `PATH`, or even `$PATH`,
  otherwise it's unclear which "path" is meant.

> --- a/lisp/progmodes/compile.el
> +++ b/lisp/progmodes/compile.el
> @@ -1779,6 +1779,8 @@ compilation-start
>  	    (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
>  	 (thisdir default-directory)
>  	 (thisenv compilation-environment)
> +         (this-process-environment process-environment)
> +         (env-buffer (when (local-variable-p 'process-environment) (buffer-name)))
>  	 outwin outbuf)
>      (with-current-buffer
>  	(setq outbuf
> @@ -1856,6 +1858,9 @@ compilation-start
>  		"; default-directory: "
>                  (prin1-to-string (abbreviate-file-name default-directory))
>  		" -*-\n"
> +                (if env-buffer
> +                    (format "Process environment is local to buffer `%s'\n" env-buffer)
> +                  "")
>  		(format "%s started at %s\n\n"
>  			mode-name
>  			(substring (current-time-string) 0 19))
> @@ -1875,7 +1880,7 @@ compilation-start
>                (and (derived-mode-p 'comint-mode)
>                     (comint-term-environment))
>  	      (list (format "INSIDE_EMACS=%s,compile" emacs-version))
> -	      (copy-sequence process-environment))))
> +	      (copy-sequence this-process-environment))))
>          (setq-local compilation-arguments
>                      (list command mode name-function highlight-regexp))
>          (setq-local revert-buffer-function 'compilation-revert-buffer)

Does this work correctly when you `M-x recompile`?


        Stefan




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 10:56 Buffer-local process environments Augusto Stoffel
  2021-04-29 12:30 ` Eli Zaretskii
  2021-04-29 14:02 ` Stefan Monnier
@ 2021-04-29 15:37 ` Michael Albinus
  2021-04-29 17:31   ` Augusto Stoffel
  2021-05-02 13:45 ` Stephen Leake
  3 siblings, 1 reply; 24+ messages in thread
From: Michael Albinus @ 2021-04-29 15:37 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

Hi Augusto,

> So why not make buffer-local process environments an official thing?
> By this I mean:
>
> 1. Fix commands that start external processes after switching buffers
>    to do what the user means.
>
> 2. Provide a convenient way to set the process environment buffer
>    locally.
>
> Point 1 is simple.  I've attached a patch for `compile' as an example.
> In the Python REPL case, I'm not sure whether it would be better to
> just adapt `run-python' or make a change in comint itself.

Have you checked, that this works for remote processes? this is already
hairy, and I fear it would be even more complicate. If we are going to
change something in this department, I'd be happy to have also a
rock-solid solution for remote processes.

See also connection-local variables, which are an attempt to make life easier.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 14:02 ` Stefan Monnier
@ 2021-04-29 17:26   ` Augusto Stoffel
  2021-04-29 17:34     ` Michael Albinus
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-29 17:26 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Michael Albinus, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 3392 bytes --]

On Thu, 29 Apr 2021 at 10:02, Stefan Monnier <monnier@iro.umontreal.ca> wrote:

>> So why not make buffer-local process environments an official thing?
>
> Sounds fine to me.
>
> To fix cases like `compile` or `run-python`, I think patches would be
> welcome regardless of what is decided in this discussion: those
> behaviors look like plain bugs to me.

Great!

>
>> # Local Variables:
>> # path: "~/path/to/some/virtualenv/bin"
>> # env: "VIRTUAL_ENV=$HOME/path/to/some/virtualenv"
>> # env: "LANG=C"
>> # End:
>
> A few comments:
> - I don't much like "special local vars" (like `eval` and `mode`), so if
>   we can find a more general solution (i.e. one that can be useful for
>   other settings), that would be better.  Maybe
>
>     # push exec-path: "~/path/to/some/virtualenv/bin"

Some notation equivalent to

# eval: (add-to-list (make-local-variable var) value)

might be handy, as well as checkable for safety.  But in the env var
case it would be important to run `substitute-env-vars', so it's a
special case.

>
> - both `exec-path` and `process-environment` are "dangerous" variables,
>   so encouraging such uses sounds rather risky.

True, but setting the environment for buffers in a project is something
one needs to do all the time.  After confirming once, it has to get out
of the way and just happen automatically.  The details of how this works
of course are worth discussing.

>
> - I'd write `path` above as `exec-path` or `PATH`, or even `$PATH`,
>   otherwise it's unclear which "path" is meant.
>
>> --- a/lisp/progmodes/compile.el
>> +++ b/lisp/progmodes/compile.el
>> @@ -1779,6 +1779,8 @@ compilation-start
>>  	    (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
>>  	 (thisdir default-directory)
>>  	 (thisenv compilation-environment)
>> +         (this-process-environment process-environment)
>> +         (env-buffer (when (local-variable-p 'process-environment) (buffer-name)))
>>  	 outwin outbuf)
>>      (with-current-buffer
>>  	(setq outbuf
>> @@ -1856,6 +1858,9 @@ compilation-start
>>  		"; default-directory: "
>>                  (prin1-to-string (abbreviate-file-name default-directory))
>>  		" -*-\n"
>> +                (if env-buffer
>> +                    (format "Process environment is local to buffer `%s'\n" env-buffer)
>> +                  "")
>>  		(format "%s started at %s\n\n"
>>  			mode-name
>>  			(substring (current-time-string) 0 19))
>> @@ -1875,7 +1880,7 @@ compilation-start
>>                (and (derived-mode-p 'comint-mode)
>>                     (comint-term-environment))
>>  	      (list (format "INSIDE_EMACS=%s,compile" emacs-version))
>> -	      (copy-sequence process-environment))))
>> +	      (copy-sequence this-process-environment))))
>>          (setq-local compilation-arguments
>>                      (list command mode name-function highlight-regexp))
>>          (setq-local revert-buffer-function 'compilation-revert-buffer)
>
> Does this work correctly when you `M-x recompile`?

I wasn't aware of recompile.  The attached patch works with it.  The
attached version breaks with Tramp, but I think this is a Tramp bug.

In fact, even without the patch, if I make my `process-environment'
buffer local, then `M-x cd' to a ssh path, then do `M-! env', I see a
mixture of my machine's environment and the remote machine's environment.
For instance, PATH has the local machine value.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Make-compile-respect-buffer-local-process-environmen.patch --]
[-- Type: text/x-patch, Size: 1508 bytes --]

From f803ce025b4161bea68f115ac50ba1174ef863e3 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <arstoffel@gmail.com>
Date: Thu, 29 Apr 2021 12:45:04 +0200
Subject: [PATCH] Make `compile' respect buffer-local process environment

* lisp/progmodes/compile.el (compilation-start): Use
`process-environment' from original buffer in the compilation process.
---
 lisp/progmodes/compile.el | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 7a02c3a896..52873d2f29 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -1779,6 +1779,9 @@ compilation-start
 	    (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
 	 (thisdir default-directory)
 	 (thisenv compilation-environment)
+         (bufferenv (if (local-variable-p 'process-environment)
+                        process-environment
+                      'global))
 	 outwin outbuf)
     (with-current-buffer
 	(setq outbuf
@@ -1846,6 +1849,9 @@ compilation-start
         ;; NB: must be done after (funcall mode) as that resets local variables
         (setq-local compilation-directory thisdir)
         (setq-local compilation-environment thisenv)
+        (if (eq bufferenv 'global)
+            (kill-local-variable 'process-environment)
+          (setq-local process-environment bufferenv))
 	(if highlight-regexp
             (setq-local compilation-highlight-regexp highlight-regexp))
         (if (or compilation-auto-jump-to-first-error
-- 
2.30.2


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 15:37 ` Michael Albinus
@ 2021-04-29 17:31   ` Augusto Stoffel
  2021-04-29 17:44     ` Michael Albinus
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-29 17:31 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

On Thu, 29 Apr 2021 at 17:37, Michael Albinus <michael.albinus@gmx.de> wrote:

> Augusto Stoffel <arstoffel@gmail.com> writes:
>
> Hi Augusto,
>

Hi Michael,

>> Point 1 is simple.  I've attached a patch for `compile' as an example.
>> In the Python REPL case, I'm not sure whether it would be better to
>> just adapt `run-python' or make a change in comint itself.
>
> Have you checked, that this works for remote processes? this is already

In fact it breaks with remote processes, see at the end of my previous
message in reply to Stefan.

But I think it's a Tramp bug.  Tramp is supposed to completely ignore
`process-environment', right?  So it shouldn't matter if that variable
is buffer local or not.

> hairy, and I fear it would be even more complicate. If we are going to
> change something in this department, I'd be happy to have also a
> rock-solid solution for remote processes.

True.  "Connection-local variable" sounds a lot like "project-local
variable" to me.  Maybe there could be a unified mechanism.

>
> See also connection-local variables, which are an attempt to make life easier.
>
> Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 17:26   ` Augusto Stoffel
@ 2021-04-29 17:34     ` Michael Albinus
  2021-04-30  7:29       ` Augusto Stoffel
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Albinus @ 2021-04-29 17:34 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: Stefan Monnier, emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> I wasn't aware of recompile.  The attached patch works with it.  The
> attached version breaks with Tramp, but I think this is a Tramp bug.
>
> In fact, even without the patch, if I make my `process-environment'
> buffer local, then `M-x cd' to a ssh path, then do `M-! env', I see a
> mixture of my machine's environment and the remote machine's environment.
> For instance, PATH has the local machine value.

Tramp uses already a hack. Obviously, it cannot use process-environment
as-it-is on a remote machine, because it is, ahem, a remote machine and
not the local one. Therefore, Tramp forces only environemt variables,
which are not set in the defauzlt value of process-environment, to the
remote. The idea is, that specific remote environment variables are
added to process-environment via a let-binding.

A buffer-local process-environment is another, new game player.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 17:31   ` Augusto Stoffel
@ 2021-04-29 17:44     ` Michael Albinus
  2021-04-30  7:00       ` Augusto Stoffel
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Albinus @ 2021-04-29 17:44 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> Hi Michael,

Hi Augusto,

>> Have you checked, that this works for remote processes? this is already
>
> In fact it breaks with remote processes, see at the end of my previous
> message in reply to Stefan.
>
> But I think it's a Tramp bug.  Tramp is supposed to completely ignore
> `process-environment', right?  So it shouldn't matter if that variable
> is buffer local or not.

No. See my reply the other message.

Granted, it is a hack. I would be happy if we could use something else,
but this is the state of affairs we cannot break reckless.

>> hairy, and I fear it would be even more complicate. If we are going to
>> change something in this department, I'd be happy to have also a
>> rock-solid solution for remote processes.
>
> True.  "Connection-local variable" sounds a lot like "project-local
> variable" to me.  Maybe there could be a unified mechanism.

No, they are not project-local. For example, via connection-local
variables you could specify which shell to use on remote.

About the syntax ... Tramp is backwards compatible down to Emacs
25. Connection-local variables were introduced in Emacs 26. I'm all ears
to new proposals, but we must ensure this compatibility.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 17:44     ` Michael Albinus
@ 2021-04-30  7:00       ` Augusto Stoffel
  2021-04-30  7:25         ` Michael Albinus
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-30  7:00 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

Hi again,

>> But I think it's a Tramp bug.  Tramp is supposed to completely ignore
>> `process-environment', right?  So it shouldn't matter if that variable
>> is buffer local or not.
>
> No. See my reply the other message.

The following prints the words "dangerous" on emacs -Q.  Also if I
replace "/sudo::/" by any of the ssh hosts I have access to.  This isn't
expected, is it?

(let ((default-directory "/sudo::/"))
  (setq-local process-environment (cons
                                   (concat "PATH=/dangerous:" (getenv "PATH"))
                                   process-environment))
  (shell-command "echo $PATH" t))

>> True.  "Connection-local variable" sounds a lot like "project-local
>> variable" to me.  Maybe there could be a unified mechanism.
>
> No, they are not project-local. For example, via connection-local
> variables you could specify which shell to use on remote.

I was just saying there's perhaps an analogy here.  "Project-local
variables" isn't a thing, as far as I know, but perhaps something like
that could be introduced.  I'm not trying to make a concrete suggestion
right now. :-)



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30  7:00       ` Augusto Stoffel
@ 2021-04-30  7:25         ` Michael Albinus
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Albinus @ 2021-04-30  7:25 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> Hi again,

Hi Augusto,

>>> But I think it's a Tramp bug.  Tramp is supposed to completely ignore
>>> `process-environment', right?  So it shouldn't matter if that variable
>>> is buffer local or not.
>>
>> No. See my reply the other message.
>
> The following prints the words "dangerous" on emacs -Q.  Also if I
> replace "/sudo::/" by any of the ssh hosts I have access to.  This isn't
> expected, is it?
>
> (let ((default-directory "/sudo::/"))
>   (setq-local process-environment (cons
>                                    (concat "PATH=/dangerous:" (getenv "PATH"))
>                                    process-environment))
>   (shell-command "echo $PATH" t))

It is expected. Tramp does not analyze your settings. If you do (concat
"PATH=/dangerous:" (getenv "PATH")), Tramp won't object. Your decision.

>> No, they are not project-local. For example, via connection-local
>> variables you could specify which shell to use on remote.
>
> I was just saying there's perhaps an analogy here.  "Project-local
> variables" isn't a thing, as far as I know, but perhaps something like
> that could be introduced.  I'm not trying to make a concrete suggestion
> right now. :-)

Perhaps. The concepts of connection-local and project-local have been
added to Emacs independently of each other.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 17:34     ` Michael Albinus
@ 2021-04-30  7:29       ` Augusto Stoffel
  2021-04-30  7:48         ` Michael Albinus
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-30  7:29 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Stefan Monnier, emacs-devel

>> In fact, even without the patch, if I make my `process-environment'
>> buffer local, then `M-x cd' to a ssh path, then do `M-! env', I see a
>> mixture of my machine's environment and the remote machine's environment.
>> For instance, PATH has the local machine value.
>
> Tramp uses already a hack. Obviously, it cannot use process-environment
> as-it-is on a remote machine, because it is, ahem, a remote machine and
> not the local one. Therefore, Tramp forces only environemt variables,
> which are not set in the defauzlt value of process-environment, to the
> remote. The idea is, that specific remote environment variables are
> added to process-environment via a let-binding.

Ah, now I see why this happens.  But I'm not sure I like the idea.  Why
not introduce a specific dynamic var for this purpose, similar to
`compilation-environment' in compile.el?

PS: Is there a single place to tell Tramp not to change the environment
of the remote host at all?  I understand the rationale for all the
automagic stuff, and I would appreciate it if I had to access lots of
remotes.  However, in my case, I only access a very small number of
servers, each of which requires a very specific configuration.

>
> A buffer-local process-environment is another, new game player.
>
> Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30  7:29       ` Augusto Stoffel
@ 2021-04-30  7:48         ` Michael Albinus
  2021-04-30 15:19           ` Augusto Stoffel
  2021-04-30 15:32           ` Augusto Stoffel
  0 siblings, 2 replies; 24+ messages in thread
From: Michael Albinus @ 2021-04-30  7:48 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: Stefan Monnier, emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> Ah, now I see why this happens.  But I'm not sure I like the idea.  Why
> not introduce a specific dynamic var for this purpose, similar to
> `compilation-environment' in compile.el?

Because there's a lot of functions out there, which work for the local
host, and should work also for remote hosts. See for example
vc-git-grep, which has

--8<---------------cut here---------------start------------->8---
(let ((default-directory dir)
      (compilation-environment (cons "PAGER=" compilation-environment)))
--8<---------------cut here---------------end--------------->8---

compilation-environment will be propagated to process-environment later
on. And the setting for PAGER is needed for both local and remote
instances of vc-git-grep. There's no special code in vc-git-grep for the
remote case.

> PS: Is there a single place to tell Tramp not to change the environment
> of the remote host at all?  I understand the rationale for all the
> automagic stuff, and I would appreciate it if I had to access lots of
> remotes.  However, in my case, I only access a very small number of
> servers, each of which requires a very specific configuration.

Hmm, I don't see it immediately. Maybe we could discuss this in a
separate thread, where you specify in more detail what you like?
Perhaps, connection-local variables are the solution for you.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30  7:48         ` Michael Albinus
@ 2021-04-30 15:19           ` Augusto Stoffel
  2021-04-30 15:51             ` Michael Albinus
  2021-04-30 15:32           ` Augusto Stoffel
  1 sibling, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-30 15:19 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Stefan Monnier, emacs-devel

> Because there's a lot of functions out there, which work for the local
> host, and should work also for remote hosts. See for example
> vc-git-grep, which has
>
> (let ((default-directory dir)
>       (compilation-environment (cons "PAGER=" compilation-environment)))
>
> compilation-environment will be propagated to process-environment later
> on. And the setting for PAGER is needed for both local and remote
> instances of vc-git-grep. There's no special code in vc-git-grep for the
> remote case.

Some observations:

1. In this case, one could call "git --no-pager" instead of relying on
   an env var.

2. PAGER is overridden by `tramp-remote-process-environment' anyway,
   right?  And unlike something of the likes of PYTHONPATH, I see no
   reason to customize PAGER.

3. If Tramp checked for the buffer-local value of process-environment
   instead of the default value, then the patch for compile.el I
   attached yesterday wouldn't break for remote directories, and the
   let-binding trick in your example would still work.

So I wonder:

A. Are there more compelling examples showing that Lisp code needs
   fine-grained control over variables being exported to a remote host?

B. There is probably a small list of variables that should be preserved
   across machines, while there is an unbounded quantity of variables
   that probably only make sense machine-locally (e.g., any variable
   holding directory names).

In view of 3., one could introduce the convention that the buffer-local
value of `process-environment' is for "project-local" variables, and the
let-bound value is for variables that make sense even on remote machines.

I'm not sure this is a good proposal, though.  It's a subtle rule, and
it could be quite brittle and hard to use.

An alternative proposal is to introduce a variable
`remote-exported-variables', which anyone could set or let-bind or even
override on a connection-local basis.  The value of any variable whose
name appears in this list would be passed though a remote connection.
This proposal would make a lot of sense if assumption B. is true.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30  7:48         ` Michael Albinus
  2021-04-30 15:19           ` Augusto Stoffel
@ 2021-04-30 15:32           ` Augusto Stoffel
  2021-04-30 15:55             ` Michael Albinus
  1 sibling, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-04-30 15:32 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Stefan Monnier, emacs-devel

> Because there's a lot of functions out there, which work for the local
> host, and should work also for remote hosts. See for example
> vc-git-grep, which has
>
> (let ((default-directory dir)
>       (compilation-environment (cons "PAGER=" compilation-environment)))
>
> compilation-environment will be propagated to process-environment later
> on. And the setting for PAGER is needed for both local and remote
> instances of vc-git-grep. There's no special code in vc-git-grep for the
> remote case.

In fact, if one launches Emacs via `PAGER= emacs', then Tramp will stop
setting PAGER on the remote as desired.  (Well, it won't, because PAGER
is in `tramp-remote-process-environment', but you see my point.)



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30 15:19           ` Augusto Stoffel
@ 2021-04-30 15:51             ` Michael Albinus
  2021-05-02  6:13               ` Augusto Stoffel
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Albinus @ 2021-04-30 15:51 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: Stefan Monnier, emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

>> Because there's a lot of functions out there, which work for the local
>> host, and should work also for remote hosts. See for example
>> vc-git-grep, which has
>>
>> (let ((default-directory dir)
>>       (compilation-environment (cons "PAGER=" compilation-environment)))
>>
>> compilation-environment will be propagated to process-environment later
>> on. And the setting for PAGER is needed for both local and remote
>> instances of vc-git-grep. There's no special code in vc-git-grep for the
>> remote case.
>
> Some observations:
>
> 1. In this case, one could call "git --no-pager" instead of relying on
>    an env var.
>
> 2. PAGER is overridden by `tramp-remote-process-environment' anyway,
>    right?  And unlike something of the likes of PYTHONPATH, I see no
>    reason to customize PAGER.
>
> 3. If Tramp checked for the buffer-local value of process-environment
>    instead of the default value, then the patch for compile.el I
>    attached yesterday wouldn't break for remote directories, and the
>    let-binding trick in your example would still work.

Please, it is just an example. And Tramp settings, like PAGER, have been
added later on.

A simple rgrep for "(process-environment" over Emacs' lisp directory
shows you several other hits, some of them are good for this discussion:

./vc/vc-bzr.el97:      (let ((process-environment (cons (format "BZR_LOG=%s" null-device)
./vc/vc-hg.el1432:             (process-environment (cons "HGPLAIN=1" process-environment))
./vc/vc-hg.el1507:         (process-environment (cons "HGPLAIN=1" process-environment))
./vc/vc-hg.el1522:  (let ((process-environment (cons "HGPLAIN=1" process-environment))
./vc/vc-dispatcher.el328:	      (process-environment (cons "LC_MESSAGES=C" process-environment))

This list is not comprehensive, of course. And again, I have no idea
what is used in the wild.

> So I wonder:
>
> A. Are there more compelling examples showing that Lisp code needs
>    fine-grained control over variables being exported to a remote host?
>
> B. There is probably a small list of variables that should be preserved
>    across machines, while there is an unbounded quantity of variables
>    that probably only make sense machine-locally (e.g., any variable
>    holding directory names).
>
> In view of 3., one could introduce the convention that the buffer-local
> value of `process-environment' is for "project-local" variables, and the
> let-bound value is for variables that make sense even on remote machines.
>
> I'm not sure this is a good proposal, though.  It's a subtle rule, and
> it could be quite brittle and hard to use.

Honestly, the hack we have now is already annoying, at least to me. I
would prefer to have something more solid to apply.

> An alternative proposal is to introduce a variable
> `remote-exported-variables', which anyone could set or let-bind or even
> override on a connection-local basis.  The value of any variable whose
> name appears in this list would be passed though a remote connection.
> This proposal would make a lot of sense if assumption B. is true.

There is already tramp-remote-process-environment, for many years. Not
much appreciated by package authors.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30 15:32           ` Augusto Stoffel
@ 2021-04-30 15:55             ` Michael Albinus
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Albinus @ 2021-04-30 15:55 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: Stefan Monnier, emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

>> Because there's a lot of functions out there, which work for the local
>> host, and should work also for remote hosts. See for example
>> vc-git-grep, which has
>>
>> (let ((default-directory dir)
>>       (compilation-environment (cons "PAGER=" compilation-environment)))
>>
>> compilation-environment will be propagated to process-environment later
>> on. And the setting for PAGER is needed for both local and remote
>> instances of vc-git-grep. There's no special code in vc-git-grep for the
>> remote case.
>
> In fact, if one launches Emacs via `PAGER= emacs', then Tramp will stop
> setting PAGER on the remote as desired.  (Well, it won't, because PAGER
> is in `tramp-remote-process-environment', but you see my point.)

Sure. But reality is, that a lot of packages are written w/o any care of
Tramp. People call remote processes w/o any care of such
environment. They simply expect that Tramp works (and bash me otherwise :-)

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-30 15:51             ` Michael Albinus
@ 2021-05-02  6:13               ` Augusto Stoffel
  2021-05-08 17:51                 ` Michael Albinus
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-05-02  6:13 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Stefan Monnier, emacs-devel

> Honestly, the hack we have now is already annoying, at least to me. I
> would prefer to have something more solid to apply.

Hi Michael,

I can only think of two alternatives:

1. Introduce a whitelist of variables that can be exported to a remote.
   Then drop entirely the current hack and just check whether
   `process-environment' contains any exportable variables.  For
   flexibility, you can allow whitelisting a variable name (any value),
   or a specific VAR=VALUE pair.

   The whitelist can be set globally or dynamically.  So, for instance,
   the vc files could just append "BZR_LOG", "HGPLAIN" and whatnot
   globally to this list and never worry again.

   Obviously, this will break third-party code, but the fix is quite
   easy.  Nobody could bash you for that.

2. Introduce a blacklist of variables that are never exported to a
   remote.  This can be done by extending
   `tramp-remote-process-environment' to follow the same convention of
   `process-environment' that an entry of the form VAR, without the
   =VALUE, means removing the variable.

   So, for instance, entries "PATH" and "TERM" should be added to the
   default value of `tramp-remote-process-environment'.  This would
   solve the unintuitive (if not buggy) behavior I pointed out a few
   messages back in this thread.

   As another example, python.el would append "PYTHONPATH" and
   "PYTHONHOME" globally to `tramp-remote-process-environment', since
   these variables hold directory names.

   This option is fully backwards compatible, but keeps the hack you
   said you don't like anyway.

It's also conceivable do to both things, but instead of enforcing 1.,
just give a warning.  Then eventually you could get rid of the hack
without breaking other packages.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-04-29 10:56 Buffer-local process environments Augusto Stoffel
                   ` (2 preceding siblings ...)
  2021-04-29 15:37 ` Michael Albinus
@ 2021-05-02 13:45 ` Stephen Leake
  3 siblings, 0 replies; 24+ messages in thread
From: Stephen Leake @ 2021-05-02 13:45 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> When developing software, it's often not possible or desirable to
> install compilers and related tools globally, so (barring the
> availability of fancy build tools) one has to fiddle with environment
> variables.

The GNU ELPA package 'wisi' provides that capability.


-- 
-- Stephe



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-05-02  6:13               ` Augusto Stoffel
@ 2021-05-08 17:51                 ` Michael Albinus
  2021-05-09  5:06                   ` Augusto Stoffel
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Albinus @ 2021-05-08 17:51 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: Stefan Monnier, emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> Hi Michael,

Hi Augusto,

> I can only think of two alternatives:
>
> 1. Introduce a whitelist of variables that can be exported to a remote.
>    Then drop entirely the current hack and just check whether
>    `process-environment' contains any exportable variables.  For
>    flexibility, you can allow whitelisting a variable name (any value),
>    or a specific VAR=VALUE pair.
>
>    The whitelist can be set globally or dynamically.  So, for instance,
>    the vc files could just append "BZR_LOG", "HGPLAIN" and whatnot
>    globally to this list and never worry again.
>
>    Obviously, this will break third-party code, but the fix is quite
>    easy.  Nobody could bash you for that.

We have already a white list, which is tramp-remote-process-environment.
I'm reluctant to add package specific entries there by default, it would
be an endless story. PAGER is included as being a general purpose
environment variable, BZR_LOG and HGPLAIN are not. If packages believe
they shall be added, this could be done in vc-bzr.el or vc-hg.el. Tramp
is a stupid library, it shouldn't try to be clever.

> 2. Introduce a blacklist of variables that are never exported to a
>    remote.  This can be done by extending
>    `tramp-remote-process-environment' to follow the same convention of
>    `process-environment' that an entry of the form VAR, without the
>    =VALUE, means removing the variable.

There are already such variables to be unset. These are the variables
without any value, like "HISTORY="

>    So, for instance, entries "PATH" and "TERM" should be added to the
>    default value of `tramp-remote-process-environment'.  This would
>    solve the unintuitive (if not buggy) behavior I pointed out a few
>    messages back in this thread.

TERM is handled special. All Tramp connections add "TERM=dumb",
hard-coded. Since this shall not be changed by a user, it isn't
configurable here.

PATH is handled by tramp-remote-path. This is a variable on its own,
because just setting a simple string "PATH=/abc:/def" isn't sufficient,
often.

>    As another example, python.el would append "PYTHONPATH" and
>    "PYTHONHOME" globally to `tramp-remote-process-environment', since
>    these variables hold directory names.

Yes, if python.el developers prefer that. However, I doubt, that this
value is always the same for all different remote hosts, the value might
differ depending on the OS the remote host is running.

>    This option is fully backwards compatible, but keeps the hack you
>    said you don't like anyway.

So in fact, this solution is almost the current implementation.

> It's also conceivable do to both things, but instead of enforcing 1.,
> just give a warning.  Then eventually you could get rid of the hack
> without breaking other packages.

As said, variant 1. isn't applicable in my eyes.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-05-08 17:51                 ` Michael Albinus
@ 2021-05-09  5:06                   ` Augusto Stoffel
  2021-05-09 16:38                     ` Michael Albinus
  0 siblings, 1 reply; 24+ messages in thread
From: Augusto Stoffel @ 2021-05-09  5:06 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Stefan Monnier, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2826 bytes --]

On Sat,  8 May 2021 at 19:51, Michael Albinus <michael.albinus@gmx.de> wrote:

Hi Michael,

> We have already a white list, which is tramp-remote-process-environment.
> I'm reluctant to add package specific entries there by default, it would
> be an endless story. PAGER is included as being a general purpose
> environment variable, BZR_LOG and HGPLAIN are not. If packages believe
> they shall be added, this could be done in vc-bzr.el or vc-hg.el. Tramp
> is a stupid library, it shouldn't try to be clever.

Fair enough.  Let's cross out the first idea then.

>> 2. Introduce a blacklist of variables that are never exported to a
>>    remote.  This can be done by extending
>>    `tramp-remote-process-environment' to follow the same convention of
>>    `process-environment' that an entry of the form VAR, without the
>>    =VALUE, means removing the variable.
>
> There are already such variables to be unset. These are the variables
> without any value, like "HISTORY="

This only works for entries in the default toplevel value of
`process-environment'.  Not for things added buffer-locally or
in a let-binding.

The heuristic that every env var which is not in the default toplevel
value of `process-environment' will be exported to the remote works
pretty well.  But it needs a simple way to be overridden, since it can't
read the user's mind.

> TERM is handled special. All Tramp connections add "TERM=dumb",
> hard-coded. Since this shall not be changed by a user, it isn't
> configurable here.

Not all connections add "TERM=dumb".  Here's a counterexample:

    (let ((default-directory "/sudo::/")
          (process-environment `("TERM=dumber"
                                 ,@process-environment)))
      (shell-command "echo $TERM" t))
    => dumber

How do I tell Tramp not to export TERM=dumber to the remote in this
case?

To be clear: this may be a dumb example, but there are plenty of
interesting use-cases involving PATH, PYTHONPATH, and so on, which are
analogous.  How can I set PYTHONPATH buffer-locally, but disallow Tramp
to export this variable to a remote?

>>    As another example, python.el would append "PYTHONPATH" and
>>    "PYTHONHOME" globally to `tramp-remote-process-environment', since
>>    these variables hold directory names.
>
> Yes, if python.el developers prefer that. However, I doubt, that this
> value is always the same for all different remote hosts, the value might
> differ depending on the OS the remote host is running.

That's precisely what I meant: you *do not* want to export those variables
to a remote.  But currently Tramp effectively forbids anyone to set
PYTHONPATH buffer-locally, because this will cause them to be exported.

My suggestion is easier to implement than explain.  So let me repeat it
in the form of a little (possibly incomplete) patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tramp-env.patch --]
[-- Type: text/x-patch, Size: 1208 bytes --]

diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 015f458a63..3749f84e21 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3938,21 +3938,23 @@ tramp-handle-make-process
 		       (when (string-match-p "=" elt) elt))
 		     tramp-remote-process-environment))
 	       ;; We use as environment the difference to toplevel
 	       ;; `process-environment'.
 	       (env (dolist (elt process-environment env)
 		      (when
 			  (and
 			   (string-match-p "=" elt)
 			   (not
 			    (member
-			     elt (default-toplevel-value 'process-environment))))
+			     elt (default-toplevel-value 'process-environment)))
+                           (not (member (car (split-string elt "="))
+                                        tramp-remote-process-environment)))
 			(setq env (cons elt env)))))
 	       (env (setenv-internal
 		     env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
 	       (env (mapcar #'tramp-shell-quote-argument (delq nil env)))
 	       ;; Quote command.
 	       (command (mapconcat #'tramp-shell-quote-argument command " "))
 	       ;; Set cwd and environment variables.
 	       (command
 	        (append `("cd" ,localname "&&" "(" "env") env `(,command ")"))))
 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Buffer-local process environments
  2021-05-09  5:06                   ` Augusto Stoffel
@ 2021-05-09 16:38                     ` Michael Albinus
  0 siblings, 0 replies; 24+ messages in thread
From: Michael Albinus @ 2021-05-09 16:38 UTC (permalink / raw)
  To: Augusto Stoffel; +Cc: Stefan Monnier, emacs-devel

Augusto Stoffel <arstoffel@gmail.com> writes:

> Hi Michael,

Hi Augusto,

>>> 2. Introduce a blacklist of variables that are never exported to a
>>>    remote.  This can be done by extending
>>>    `tramp-remote-process-environment' to follow the same convention of
>>>    `process-environment' that an entry of the form VAR, without the
>>>    =VALUE, means removing the variable.
>>
>> There are already such variables to be unset. These are the variables
>> without any value, like "HISTORY="
>
> This only works for entries in the default toplevel value of
> `process-environment'.  Not for things added buffer-locally or
> in a let-binding.

Yes, this is a bug (rather a missing feature) of Tramp. It is
implemented for synchronous processes, but not for asynchronous
processes. I'm aware of this, but I haven't found the mood to implement
it until now.

> The heuristic that every env var which is not in the default toplevel
> value of `process-environment' will be exported to the remote works
> pretty well.  But it needs a simple way to be overridden, since it can't
> read the user's mind.

Sure. Tramp shall not read the user's mind.

(As side remark, my wife expects always that I read her mind. I fail
miserably, usually.)

>> TERM is handled special. All Tramp connections add "TERM=dumb",
>> hard-coded. Since this shall not be changed by a user, it isn't
>> configurable here.
>
> Not all connections add "TERM=dumb".  Here's a counterexample:
>
>     (let ((default-directory "/sudo::/")
>           (process-environment `("TERM=dumber"
>                                  ,@process-environment)))
>       (shell-command "echo $TERM" t))
>     => dumber
>
> How do I tell Tramp not to export TERM=dumber to the remote in this
> case?

You can always shoot yourself in your feed.

> To be clear: this may be a dumb example, but there are plenty of
> interesting use-cases involving PATH, PYTHONPATH, and so on, which are
> analogous.  How can I set PYTHONPATH buffer-locally, but disallow Tramp
> to export this variable to a remote?

Set it only, when the buffer is not remote. Something like

(unless (file-remote-p default-directory) ...)

>>>    As another example, python.el would append "PYTHONPATH" and
>>>    "PYTHONHOME" globally to `tramp-remote-process-environment', since
>>>    these variables hold directory names.
>>
>> Yes, if python.el developers prefer that. However, I doubt, that this
>> value is always the same for all different remote hosts, the value might
>> differ depending on the OS the remote host is running.
>
> That's precisely what I meant: you *do not* want to export those variables
> to a remote.  But currently Tramp effectively forbids anyone to set
> PYTHONPATH buffer-locally, because this will cause them to be exported.

No. See above.

> My suggestion is easier to implement than explain.  So let me repeat it
> in the form of a little (possibly incomplete) patch:
>
> diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
> index 015f458a63..3749f84e21 100644
> --- a/lisp/net/tramp.el
> +++ b/lisp/net/tramp.el
> @@ -3938,21 +3938,23 @@ tramp-handle-make-process
>  		       (when (string-match-p "=" elt) elt))
>  		     tramp-remote-process-environment))
>  	       ;; We use as environment the difference to toplevel
>  	       ;; `process-environment'.
>  	       (env (dolist (elt process-environment env)
>  		      (when
>  			  (and
>  			   (string-match-p "=" elt)
>  			   (not
>  			    (member
> -			     elt (default-toplevel-value 'process-environment))))
> +			     elt (default-toplevel-value 'process-environment)))
> +                           (not (member (car (split-string elt "="))
> +                                        tramp-remote-process-environment)))
>  			(setq env (cons elt env)))))
>  	       (env (setenv-internal
>  		     env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
>  	       (env (mapcar #'tramp-shell-quote-argument (delq nil env)))
>  	       ;; Quote command.
>  	       (command (mapconcat #'tramp-shell-quote-argument command " "))
>  	       ;; Set cwd and environment variables.
>  	       (command
>  	        (append `("cd" ,localname "&&" "(" "env") env `(,command ")"))))
>

I see. Interesting.

But this still means, that you use something global in
tramp-remote-process-environment for all remote processes.

What, if you want to set PYTHONPATH for hosta, and not for hostb?

Best regards, Michael.



^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2021-05-09 16:38 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-29 10:56 Buffer-local process environments Augusto Stoffel
2021-04-29 12:30 ` Eli Zaretskii
2021-04-29 12:40   ` Augusto Stoffel
2021-04-29 12:52     ` Eli Zaretskii
2021-04-29 13:06       ` Augusto Stoffel
2021-04-29 14:02 ` Stefan Monnier
2021-04-29 17:26   ` Augusto Stoffel
2021-04-29 17:34     ` Michael Albinus
2021-04-30  7:29       ` Augusto Stoffel
2021-04-30  7:48         ` Michael Albinus
2021-04-30 15:19           ` Augusto Stoffel
2021-04-30 15:51             ` Michael Albinus
2021-05-02  6:13               ` Augusto Stoffel
2021-05-08 17:51                 ` Michael Albinus
2021-05-09  5:06                   ` Augusto Stoffel
2021-05-09 16:38                     ` Michael Albinus
2021-04-30 15:32           ` Augusto Stoffel
2021-04-30 15:55             ` Michael Albinus
2021-04-29 15:37 ` Michael Albinus
2021-04-29 17:31   ` Augusto Stoffel
2021-04-29 17:44     ` Michael Albinus
2021-04-30  7:00       ` Augusto Stoffel
2021-04-30  7:25         ` Michael Albinus
2021-05-02 13:45 ` Stephen Leake

unofficial mirror of emacs-devel@gnu.org 

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://yhetil.org/emacs-devel/0 emacs-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 emacs-devel emacs-devel/ https://yhetil.org/emacs-devel \
		emacs-devel@gnu.org
	public-inbox-index emacs-devel

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.yhetil.org/yhetil.emacs.devel
	nntp://news.gmane.io/gmane.emacs.devel


code repositories for project(s) associated with this inbox:

	https://git.savannah.gnu.org/cgit/emacs.git

AGPL code for this site: git clone http://ou63pmih66umazou.onion/public-inbox.git