Stacey Marshall <[email protected]> writes:
Hi Stacey,
Thanks for this exhaustive bug report, and the proper analysis.
> 3. In another terminal session clear up caches, start emacs, and access
> directory via tramp path
>
> rm -rf ~/.cache/emacs ~/.emacs.d/tramp
> emacs -nw -Q --eval '(add-to-list `load-path "~/emacs/tramp/lisp/")' \
> --eval '(require `tramp)' --eval '(setq tramp-verbose 11)' \
> --eval '(find-file
> "/scp:foobar@localhost:/export/home/foobar/tmp/is_it_the_length_of_path_and_not_the_d")'
>
> At this point, if necessary accept the connection and type password
> as required... And then emacs appears hung. A C-g (Control-G)
> aborts the transfer. Switching to the debug buffer
> `(switch-to-buffer "*debug tramp/scp foobar@localhost*")` and
> duplicating it (M-n) (before it gets contaminated/removed).
> It shows some output, though this tends to differ slightly each time!
Yep. According to the debug buffer you've sent, Tramp has sent the
following command:
--8<---------------cut here---------------start------------->8---
16:34:47.760152 tramp-send-command (6) # (if test -h
"/export/home/foobar/tmp/is_it_the_length_of_path_and_not_the_d/"; then echo t;
else echo nil; fi) && /usr/bin/readlink --canonicalize-missing
/export/home/foobar/tmp/is_it_the_length_of_path_and_not_the_d/ 2>/dev/null;
echo tramp_exit_status $?
--8<---------------cut here---------------end--------------->8---
The "(if test ... tramp_exit_status $?" sequence is 257 characters long,
it seems to exceed the shell line length on Solaris. The problem is,
that the looooongish file name is used twice.
> diff --git a/lisp/tramp-sh.el b/lisp/tramp-sh.el
> index 047d93a5..e0ccc0ce 100644
> --- a/lisp/tramp-sh.el
> +++ b/lisp/tramp-sh.el
> @@ -1292,20 +1292,12 @@ Operations not mentioned here will be handled by the
> normal Emacs functions.")
> ;; Use GNU readlink --canonicalize-missing where available.
> ((tramp-get-remote-readlink v)
> (tramp-send-command-and-check
> - v (format
> - (concat
> - "(if %s -h \"%s\"; then echo t; else echo nil; fi) && "
> - "%s --canonicalize-missing %s")
> - (tramp-get-test-command v)
> - (tramp-shell-quote-argument localname)
> - (tramp-get-remote-readlink v)
> - (tramp-shell-quote-argument localname)))
> + v (format "%s --canonicalize-missing %s"
> + (tramp-get-remote-readlink v)
> + (tramp-shell-quote-argument localname)))
> (with-current-buffer (tramp-get-connection-buffer v)
> (goto-char (point-min))
> - (tramp-set-file-property v localname "file-symlink-marker" (read
> (current-buffer)))
> - ;; We cannot call `read', the file name isn't quoted.
> - (forward-line)
> - (buffer-substring (point) (line-end-position))))
> + (buffer-substring (point-min) (line-end-position))))
Yes. But this removes the performance optimization, to return both the
information, whether a give file is a symlink, and its true name. This
optimization avoids one round trip.
> At this point I thought I should raise it with yourselves.
Instead, I've puzzled the attached patch, which uses a shell function
instead. Could you please check?
> Stace
Best regards, Michael.
diff --git a/lisp/tramp-sh.el b/lisp/tramp-sh.el
index 047d93a5..481a3979 100644
--- a/lisp/tramp-sh.el
+++ b/lisp/tramp-sh.el
@@ -648,6 +648,14 @@ we have this shell function.
Format specifiers are replaced by `tramp-expand-script', percent
characters need to be doubled.")
+(defconst tramp-readlink-file-truename
+ "if %s -h \"$1\"; then echo t; else echo nil; fi
+%s --canonicalize-missing \"$1\""
+ "Shell script to produce output suitable for use with `file-truename'
+on the remote file system.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
+
(defconst tramp-perl-file-truename
"%p -e '
use File::Spec;
@@ -1291,14 +1299,12 @@ Operations not mentioned here will be handled by the normal Emacs functions.")
(cond
;; Use GNU readlink --canonicalize-missing where available.
((tramp-get-remote-readlink v)
+ (tramp-maybe-send-script
+ v (format tramp-readlink-file-truename
+ (tramp-get-test-command v) (tramp-get-remote-readlink v))
+ "tramp_readlink_file_truename")
(tramp-send-command-and-check
- v (format
- (concat
- "(if %s -h \"%s\"; then echo t; else echo nil; fi) && "
- "%s --canonicalize-missing %s")
- (tramp-get-test-command v)
- (tramp-shell-quote-argument localname)
- (tramp-get-remote-readlink v)
- (tramp-shell-quote-argument localname)))
+ v (format "tramp_readlink_file_truename %s"
+ (tramp-shell-quote-argument localname)))
(with-current-buffer (tramp-get-connection-buffer v)
(goto-char (point-min))
(tramp-set-file-property v localname "file-symlink-marker" (read (current-buffer)))