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

Tramp with multihop #16

Closed
farosas opened this issue Jul 14, 2015 · 8 comments
Closed

Tramp with multihop #16

farosas opened this issue Jul 14, 2015 · 8 comments

Comments

@farosas
Copy link
Contributor

farosas commented Jul 14, 2015

When using tramp with multihop (local host --> intermediate host --> remote host):

C-x C-f /ssh:intermediate_user@intermediate_host|ssh:remote_user@remote_host:path/filename

the persp-auto-save file gets written with:

(def-buffer "filename" "/ssh:remote_user@remote_host:path/filename" mode)

when restoring persp contents, tramp will timeout because remote_user@remote_host is not accessible.

Is there a way to restore these tramp buffers?

EDIT: I just noticed that after tramp times out, persp-mode will output a warning saying that the file no longer exists.

@farosas
Copy link
Contributor Author

farosas commented Jul 16, 2015

Just found out about tramp-default-proxies-alist:

tramp-default-proxies-alist is a variable defined in `tramp.el'.
Its value is
(("192\\.168\\.123\\.29" "root" "/ssh:user@host.com:"))

Original value was nil

Documentation:
Route to be followed for specific host/user pairs.
This is an alist of items (HOST USER PROXY).  The first matching
item specifies the proxy to be passed for a file name located on
a remote target matching USER@HOST.  HOST and USER are regular
expressions.  PROXY must be a Tramp filename without a localname
part.  Method and user name on PROXY are optional, which is
interpreted with the default values.  PROXY can contain the
patterns %h and %u, which are replaced by the strings matching
HOST or USER, respectively.

HOST, USER or PROXY could also be Lisp forms, which will be
evaluated.  The result must be a string or nil, which is
interpreted as a regular expression which always matches.

Linking this with my previous comment we have:

(def-buffer "filename" "/ssh:root@192.168.123.29:path/filename" mode)

If I edit persp-auto-save by hand to make it look like this:

(def-buffer "filename" "/ssh:user@host.com|root@192.168.123.29:path/filename" mode)

It works.

So I think it would be just a matter of checking the tramp-default-proxies-alist and concatenating the corresponding hosts to the path of the file.

What do you think?

@Bad-ptr
Copy link
Owner

Bad-ptr commented Jul 17, 2015

What do you think?

But how will we know which item from proxies-alist to concatenate?
Hm...

I can not check that by myself, so could you post here a value of the tramp-current-connection variable when you edit such a file?
C-x C-f /ssh:intermediate_user@intermediate_host|ssh:remote_user@remote_host:path/filename RET
M-: (message "TCC: %s" tramp-current-connection) RET

@Bad-ptr
Copy link
Owner

Bad-ptr commented Jul 19, 2015

But how will we know which item from proxies-alist to concatenate?

heh nevermind, I misunderstood you. Just realised that the tramp-default-proxies-alist is an alist.)

@farosas
Copy link
Contributor Author

farosas commented Jul 19, 2015

Yes, but I still didn't find a way to know for sure that the buffer is a tramp buffer. I don't think checking the start of the buffer name for '/ssh:' is very reliable.

And btw, tramp-current-connection will not help us very much because it just shows the latest connection stabilished.

I'll look further into this today. Perhaps there is a 'trampp' predicate. =)

@farosas
Copy link
Contributor Author

farosas commented Aug 2, 2015

Hi, just an update on this. There really is a tramp-p predicate: tramp-tramp-file-p. And after almost writing it from scratch, I found a very handy function called: tramp-compute-multi-hops. I think these two will be enough. However, the return of tramp-compute-multi-hops is a list, so there is still a bit of work to do to produce a suitable file name.

I'll get back to you when I have something.

@Bad-ptr
Copy link
Owner

Bad-ptr commented Aug 2, 2015

Ok, then something like this should work for you, I think:

(with-eval-after-load "persp-mode-autoloads"
  (defun persp-tramp-multi-hop-save-buffer-file-name (b)
    (let ((ret (buffer-file-name b))
          (tmh (tramp-compute-multi-hops
                (tramp-dissect-file-name (buffer-file-name b)))))
      (when tmh
        (let* (method user host filename proxy (out "")
                      (temp-out
                       (concat "/"
                               (dolist (item tmh out)
                                 (setq method   (aref item 0)
                                       user     (aref item 1)
                                       host     (aref item 2)
                                       filename (aref item 3)
                                       proxy    (aref item 4))
                                 (setq out
                                       (concat proxy
                                               out method ":" user "@" host
                                               (if (= (string-width filename) 0)
                                                   "|"
                                                 (concat ":" filename))))))))
          (setq ret
                (if (yes-or-no-p (concat
                                  "You are about to save a tramp file. Is it a correct file name to save?"
                                  "(" temp-out ")"))
                    temp-out
                  (read-string "Please enter a correct file name: " temp-out nil ret)))))
      ret))

  (add-to-list 'persp-save-buffer-functions
               #'(lambda (b)
                   (when (tramp-tramp-file-p (buffer-file-name b))
                     `(def-buffer ,(buffer-name b)
                        ,(persp-tramp-multi-hop-save-buffer-file-name b)
                        ,(buffer-local-value 'major-mode b))))))

@farosas
Copy link
Contributor Author

farosas commented Aug 3, 2015

Cool, it worked!

I used a slightly different function though (but it does the same):

(with-eval-after-load "persp-mode-autoloads"
  (defun persp-tramp-save-buffer-file-name (b)
    (let ((persp-tramp-file-name tramp-prefix-format)
          (tmh (tramp-compute-multi-hops (tramp-dissect-file-name (buffer-file-name b)))))
      (while tmh
        (let* ((hop (car tmh))
               (method   (tramp-file-name-method hop))
               (user     (tramp-file-name-user hop))
               (host     (tramp-file-name-host hop))
               (filename (tramp-file-name-localname hop)))
          (setq persp-tramp-file-name (concat
                                       persp-tramp-file-name
                                       method tramp-postfix-method-format
                                       user tramp-postfix-user-format
                                       host (if (= (string-width filename) 0)
                                                tramp-postfix-hop-format
                                              (concat tramp-postfix-host-format filename)))
                tmh (cdr tmh))
          persp-tramp-file-name))))

    (add-to-list 'persp-save-buffer-functions
               #'(lambda (b)
                   (when (tramp-tramp-file-p (buffer-file-name b))
                     `(def-buffer ,(buffer-name b)
                        ,(persp-tramp-save-buffer-file-name b)
                        ,(buffer-local-value 'major-mode b))))))
  • Used constants and functions from tramp.el for more flexibility.
  • Changed the function name to persp-tramp-save-buffer-file-name because this works for single-hop as well as local tramp files.
  • Removed the prompt because I usually have a large number of tramp files open at a time.

Do you intend to merge this? I could send a pull request with the new function.

Anyway, I think we can close this, thanks! =)

@Bad-ptr
Copy link
Owner

Bad-ptr commented Aug 4, 2015

I could send a pull request with the new function.

It would be great.

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

No branches or pull requests

2 participants