Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TRAMP support #29

Closed
wants to merge 2 commits into from

Conversation

siddharthverma314
Copy link
Contributor

Hi,

This PR adds tramp support and closes #27 . It has only been tested by me, so I would appreciate it if others could try it out and see if it works for them!

Copy link
Owner

@purcell purcell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, looking pretty good! I haven't tested it out yet but I spotted a couple of little cosmetic things.

envrc.el Outdated
@@ -178,9 +191,10 @@ called `cd'"
"Update the current buffer's environment if it is managed by direnv.
All envrc.el-managed buffers with this env will have their
environments updated."
(let ((env-dir (envrc--find-env-dir)))
(let ((env-dir (envrc--find-env-dir))
(env (envrc--get-process-environment)))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a tab here? The alignment is off.

envrc.el Outdated
@@ -149,6 +148,20 @@ One of '(none on error).")

;;; Internals

(defun envrc--get-process-environment ()
"Returns correct process envirionment for local and remote buffers"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Returns correct process envirionment for local and remote buffers"
"Returns correct process environment for local and remote buffers."

envrc.el Outdated
process-environment))

(defmacro envrc--with-tramp-vec (vec &rest body)
"Binds the tramp vector to VEC and connection buffer to CONN,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This docstring looks wrong (CONN?) and not conformant with checkdoc.

envrc.el Outdated
@@ -213,16 +227,6 @@ MSG and ARGS are as for that function."
(insert (apply 'format msg args))
(newline))))

(defun envrc--directory-path-deeper-p (a b)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for deleting this bit

@purcell
Copy link
Owner

purcell commented Dec 20, 2021

I tried this out by adding a .envrc containing export FOO=bar on a remote host, then connecting with dired to the directory via an /ssh: TRAMP path. The *envrc* buffer showed the var was parsed, but I don't see any effect on tramp-remote-process-environment, or the expected output when running M-! echo $FOO. What did you try in order to test this out?

@siddharthverma314
Copy link
Contributor Author

Hey, thanks for your feedback! In my initial implementation, I wrongly assumed that the variables must be set in the tramp connection buffer. I've updated my PR to reflect this. Most normal operations should now work. I also fixed all of your suggestions.

However, it seems like shell programs still don't work. Using the test you suggested, tramp-remote-process-environment is updated, but M-! echo $FOO does not output anything, and eshell does not have the correct environment variable set. I'm currently working on resolving this.

@siddharthverma314 siddharthverma314 marked this pull request as draft December 21, 2021 07:15
@siddharthverma314
Copy link
Contributor Author

It seems like tramp-remote-process-environment must be set on the connection buffer in order for (exec-path) to work. I've updated the PR to set the variables on both the connection buffer and local buffer, although ideally the code should use connection-local-variables to update the environment for all tramp-related buffers. Changing the PR to a draft as it needs more work!

@purcell
Copy link
Owner

purcell commented Dec 22, 2021

Thanks for this, I haven't worked much with the tramp machinery, so I appreciate you tackling the issue.

@andir
Copy link

andir commented Dec 15, 2022

Sorry for bumping this almost a year old conversation but as a recent migrant into Emacs I would love this feature :-)

@siddharthverma314 did you continue working the version posted here? Is there something I can do to help testing this?

@purcell
Copy link
Owner

purcell commented Dec 15, 2022

Hey Andi, yeah, I was wondering about this recently too.

@siddharthverma314
Copy link
Contributor Author

Thanks for your interest! Back when I was writing this, the tramp implementation (to my knowledge) did not support buffer local tramp-remote-process-environment, making it impossible to implement an envrc-style approach. This might have changed recently -- I'll need to look into it more. Meanwhile, I have a PR open on emacs-direnv for TRAMP support that should work.

@d-miketa
Copy link

d-miketa commented Dec 27, 2022

Hi, just wanted to say I'd love this feature too! :) Happy to help test it.

@sellout
Copy link
Contributor

sellout commented May 24, 2023

@siddharthverma314 I haven’t done extensive testing yet, but tramp-remote-process-environment can be set buffer-locally (which I’m guessing you know). However, given your comment:

It seems like tramp-remote-process-environment must be set on the connection buffer in order for (exec-path) to work.

if that’s still the case, then buffer-local doesn’t help, because there’s only one relevant buffer per connection.

I had another thought that might help – do what you’re currently doing, but add advice to the various TRAMP functions like

(advice-add 'some-tramp-function
            :before
            (lambda (orig-fn &rest args)
              ;; get the possibly buffer-local variables from the current (non-connection) buffer
              (let ((local-process-env tramp-remote-process-env)
                    (local-path tramp-remote-path))
                (with-current-buffer (tramp-get-connection-buffer default-directory)
                  ;; assign the non-connection buffer values to the connection buffer
                  (setq-local tramp-remote-process-env local-process-env
                              tramp-remote-path local-path)))))

which would hopefully then use the appropriate environment for each command (and buffers that don’t have buffer-local values for these vars would just end up setting the connection buffer’s values to to defaults. (There are coarser variants, like updating the connection-buffer’s variables whenever the selected window changes, like via window-state-change-hook, but that could maybe lead to race conditions?)

@dcunited001
Copy link

👍 if possible, that would be awesome

@bbigras
Copy link

bbigras commented Oct 13, 2023

@andir did you find a workaround to use tramp with a remote nix shell?

@siddharthverma314
Copy link
Contributor Author

siddharthverma314 commented Nov 15, 2023

Hey everyone, I've been working on this locally and I think I have an implementation that works ~20% of the time 🤣. I'd love to gather feedback about whether it works or not, but try at your own risk. Or if you find bugs, let me know and I can fix them.

Also, thank you @sellout for the inspiration, I ended up implementing an advice around tramp-get-connection-buffer and tramp-get-remote-path.

Note that in order to enable direnv over tramp, you will need to set envrc-remote to t. This is the config I'm using locally:

(use-package envrc
  :straight (envrc :host github :repo "purcell/envrc"
                   :fork (:host github :repo "siddharthverma314/envrc"))
  :config
  (setq envrc-remote t)
  (envrc-global-mode))

Thanks for your patience!

@sellout
Copy link
Contributor

sellout commented Nov 15, 2023

Thanks, @siddharthverma314! I should be able to give this a go tomorrow.

@purcell
Copy link
Owner

purcell commented Nov 15, 2023

Nice! In what way does it fail to work the rest of the time?

@hso
Copy link

hso commented Nov 15, 2023

Thanks, @siddharthverma314. I've been looking for something like this for some time. I can't get it working yet, though. When I use your sample config I get envrc/:config: Symbol's value as variable is void: vec when I try to load a file over TRAMP or if I manually call envrc-global-mode. What could I be missing?

@siddharthverma314
Copy link
Contributor Author

siddharthverma314 commented Nov 15, 2023

@hso Thanks for the feedback! I'm assuming you tried the obvious, like restarting emacs, running M-x straight-pull-package and reloading envrc.el. Can you provide the following info:

  1. Which version of tramp are you using? For me, M-x tramp-version outputs 2.7.0-pre, so maybe there is minimum tramp version that is required.
  2. Could you provide a stack trace for when this happens? Easy way of doing that is to M-x toggle-debug-on-error and try to enable envrc-global-mode. I'm mainly curious whether this error happens within envrc-global-mode or envrc-get-remote-path.

@siddharthverma314
Copy link
Contributor Author

@purcell In my testing, things got slow sometimes or the remote path got messed up, but these might have been problems with earlier versions of the code. For now it seems to run fine, but I definitely haven't tested all cases yet.

@lakkiy
Copy link

lakkiy commented Nov 18, 2023

Is this ready to merge?

@purcell
Copy link
Owner

purcell commented Nov 27, 2023

Symbol's value as variable is void: vec when I try to load a file over TRAMP or if I manually call envrc-global-mode. What could I be missing?

Perhaps it's the with-parsed-tramp-file-name call — there's no (eval-when-compile (require 'tramp)) present in the changes, so if that macro is unknown, Emacs would produce an error message like that.

Is this ready to merge?

Not yet. I want to understand how it works and what the trade-offs are, and I haven't had the time for a deep dive. For example, the changes apparently rely on copying buffer-local environments into the connection buffer "just in time" for commands to be executed there, so I worry about collisions or unexpected lingering effects. e.g. If you have multiple envrc-mode-enabled buffers on a tramp connection, and some buffers on that same connection that do not have envrc-mode activated, those latter buffers would presumably see the environment left by the last command run in one of the former buffers.

But I think this is promising.

envrc.el Outdated Show resolved Hide resolved
@hso
Copy link

hso commented Dec 12, 2023

@siddharthverma314 yes, I tried restarting emacs, running straight-pull-package and reloading envrc.el, but I still get that error.

1. Which version of tramp are you using? For me, `M-x tramp-version` outputs `2.7.0-pre`, so maybe there is minimum tramp version that is required.

I don't have that command available, I suppose I have never installed a package for tramp, I'm just using the one that comes with my emacs version: GNU Emacs 29.1 (build 2, x86_64-suse-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8)

2. Could you provide a stack trace for when this happens? Easy way of doing that is to `M-x toggle-debug-on-error` and try to enable `envrc-global-mode`. I'm mainly curious whether this error happens within `envrc-global-mode` or `envrc-get-remote-path`.

Sure:

Debugger entered--Lisp error: (void-variable vec)
  envrc-global-mode(toggle)
  funcall-interactively(envrc-global-mode toggle)
  #<subr call-interactively>(envrc-global-mode record nil)
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> envrc-global-mode record nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (envrc-global-mode record nil))
  call-interactively(envrc-global-mode record nil)
  command-execute(envrc-global-mode record)
  execute-extended-command(nil "envrc-global-mode" nil)
  funcall-interactively(execute-extended-command nil "envrc-global-mode" nil)
  #<subr call-interactively>(execute-extended-command nil nil)
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> execute-extended-command nil nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (execute-extended-command nil nil))
  call-interactively(execute-extended-command nil nil)
  command-execute(execute-extended-command)

@bbigras
Copy link

bbigras commented Apr 11, 2024

Any progress on this? or maybe a workaround.

@bbigras
Copy link

bbigras commented May 9, 2024

with 5c1d1eb, I got env: ‘direnv’: No such file or directory.

I tried with /ssh: and /sshx: with (setq envrc-remote t).

"Whether or not to enable direnv over TRAMP."
:type 'boolean)

(defcustom envrc-supported-tramp-methods '("ssh" "sshx")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose adding "scp" "scpx" here, since they differ only in file transfer method, everything else is the same as for ssh[x]. At least for me, it works well for scpx.

@sgrb
Copy link

sgrb commented Oct 21, 2024

Is there any progress on merging this PR? At least for me it works well with remote direnv + nix.

@purcell
Copy link
Owner

purcell commented Oct 21, 2024

Is there any progress on merging this PR?

Unsure of the current status, and I don't use the changes myself. The merge conflict looks trivial, but @bbigras reported issues above, maybe due to not having direnv installed on the target machine?

@sgrb
Copy link

sgrb commented Nov 18, 2024

@bbigras reported issues above, maybe due to not having direnv installed on the target machine?

It looks plausible (or maybe PATH issues on the remote end). At least I use envrc with this PR applied almost every day (both locally and remotely over TRAMP), and didn't have any issues so far.

@sellout
Copy link
Contributor

sellout commented Nov 18, 2024

I use envrc with this PR applied almost every day (both locally and remotely over TRAMP), and didn't have any issues so far.

Same. In fact, I recently switched to my own fork to test out some unrelated changes, and was immediately affected by the loss of TRAMP support 😆

@purcell
Copy link
Owner

purcell commented Nov 18, 2024

I've resolved this conflict and merged this PR into the main branch. Couple of questions for you all though:

  1. Do you find that shell-command-to-string etc. work okay from remote buffers that use ? I'm wondering if changes to inheritenv might be necessary too.
  2. Any reason to keep the envrc-remote custom var added by this PR? I feel like tramp support should just always be enabled, or am I missing something?

@siddharthverma314
Copy link
Contributor Author

siddharthverma314 commented Nov 19, 2024

Hey! Thanks for merging this PR. Regarding the concerns you raised above:

  1. inheritenv changes may be necessary because I was experiencing odd behavior with magit and couldn't track down why. I think this PR should do it.
  2. We should keep envrc-remote disabled by default because the functionality does not have test coverage 😄. Once I figure out how to do that, it can be removed. As a side note, I have no clue if this works with connection local variables.

Sorry for the delay in pushing this through.

@purcell
Copy link
Owner

purcell commented Nov 19, 2024

We should keep envrc-remote disabled by default because the functionality does not have test coverage 😄. Once I figure out how to do that, it can be removed. As a side note, I have no clue if this works with connection local variables.

Even the existing tests have been a bit broken for a while tbh. :( I'd be inclined to remove the var anyway if that's the only technical reason for it — worst case would be that we get a few helpful bug reports.

@purcell
Copy link
Owner

purcell commented Nov 19, 2024

I'll close this PR to avoid confusion, but feel free to comment further, or open a follow-up issue or PR.

@purcell purcell closed this Nov 19, 2024
@collinarnett
Copy link

For Nix home-manager users if you are SSHing into a machine that manages direnv with SSH, direnv will not be found. Use the snippet outlined in this wiki article to solve the problem.

https://nixos.wiki/wiki/Emacs#Cannot_find_all_binaries_on_a_remote_system_with_TRAMP

This solved my problem since I was running into the same issue as @bbigras

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

eshell can't load .envrc via Tramp