Package: emacs;
Reported by: Dan Gildea <gildea <at> pobox.com>
Date: Wed, 26 Oct 2011 19:05:02 UTC
Severity: normal
Found in version 23.3
Done: Michael Albinus <michael.albinus <at> gmx.de>
Bug is archived. No further changes may be made.
Message #26 received at 9879 <at> debbugs.gnu.org (full text, mbox):
From: Michael Albinus <michael.albinus <at> gmx.de> To: Daniel Gildea <gildea <at> cs.rochester.edu> Cc: Glenn Morris <rgm <at> gnu.org>, 9879 <at> debbugs.gnu.org, Dan Gildea <gildea <at> pobox.com> Subject: Re: bug#9879: 23.3; making script executable with tramp Date: Wed, 16 Nov 2011 20:59:56 +0100
Michael Albinus <michael.albinus <at> gmx.de> writes: > You are working on "/u/gildea/xx.sh", which is a symlink to > "/home/vax7/u19/gildea/xx.sh". You have written "/u/gildea/xx.sh". Tramp > tries to check "/home/vax7/u19/gildea/xx.sh" file properties afterwards, > and it decides that this file doesn't exist. > > This is likely because of Tramp's cache, which hasn't been refreshed > accordingly for the symlink's target after writing. > > I will check how to fix this; unfortunately there is no simple patch. It > might take a day, or two. The following two patches shall solve the problem, could you, please verify? The patches are for Emacs 23.3, however, the line numbers might be a little bit different. --8<---------------cut here---------------start------------->8--- Index: tramp.el =================================================================== RCS file: /sources/tramp/tramp/lisp/tramp.el,v retrieving revision 2.814.2.16 diff -c -r2.814.2.16 tramp.el *** tramp.el 12 Oct 2011 14:56:21 -0000 2.814.2.16 --- tramp.el 16 Nov 2011 19:50:48 -0000 *************** *** 2671,2776 **** (defun tramp-handle-file-truename (filename &optional counter prev-dirs) "Like `file-truename' for Tramp files." (with-parsed-tramp-file-name (expand-file-name filename) nil ! (with-file-property v localname "file-truename" ! (let ((result nil)) ; result steps in reverse order ! (tramp-message v 4 "Finding true name for `%s'" filename) ! (cond ! ;; Use GNU readlink --canonicalize-missing where available. ! ((tramp-get-remote-readlink v) ! (setq result ! (tramp-send-command-and-read ! v ! (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\"" ! (tramp-get-remote-readlink v) ! (tramp-shell-quote-argument localname))))) ! ! ;; Use Perl implementation. ! ((and (tramp-get-remote-perl v) ! (tramp-get-connection-property v "perl-file-spec" nil) ! (tramp-get-connection-property v "perl-cwd-realpath" nil)) ! (tramp-maybe-send-script ! v tramp-perl-file-truename "tramp_perl_file_truename") ! (setq result ! (tramp-send-command-and-read ! v ! (format "tramp_perl_file_truename %s" ! (tramp-shell-quote-argument localname))))) ! ! ;; Do it yourself. We bind `directory-sep-char' here for ! ;; XEmacs on Windows, which would otherwise use backslash. ! (t (let* ((directory-sep-char ?/) ! (steps (tramp-compat-split-string localname "/")) ! (localnamedir (tramp-run-real-handler ! 'file-name-as-directory (list localname))) ! (is-dir (string= localname localnamedir)) ! (thisstep nil) ! (numchase 0) ! ;; Don't make the following value larger than ! ;; necessary. People expect an error message in a ! ;; timely fashion when something is wrong; ! ;; otherwise they might think that Emacs is hung. ! ;; Of course, correctness has to come first. ! (numchase-limit 20) ! symlink-target) ! (while (and steps (< numchase numchase-limit)) ! (setq thisstep (pop steps)) ! (tramp-message ! v 5 "Check %s" ! (mapconcat 'identity ! (append '("") (reverse result) (list thisstep)) ! "/")) ! (setq symlink-target ! (nth 0 (file-attributes ! (tramp-make-tramp-file-name ! method user host ! (mapconcat 'identity ! (append '("") ! (reverse result) ! (list thisstep)) ! "/"))))) ! (cond ((string= "." thisstep) ! (tramp-message v 5 "Ignoring step `.'")) ! ((string= ".." thisstep) ! (tramp-message v 5 "Processing step `..'") ! (pop result)) ! ((stringp symlink-target) ! ;; It's a symlink, follow it. ! (tramp-message v 5 "Follow symlink to %s" symlink-target) ! (setq numchase (1+ numchase)) ! (when (file-name-absolute-p symlink-target) ! (setq result nil)) ! ;; If the symlink was absolute, we'll get a string like ! ;; "/user <at> host:/some/target"; extract the ! ;; "/some/target" part from it. ! (when (tramp-tramp-file-p symlink-target) ! (unless (tramp-equal-remote filename symlink-target) ! (tramp-error ! v 'file-error ! "Symlink target `%s' on wrong host" symlink-target)) ! (setq symlink-target localname)) ! (setq steps ! (append (tramp-compat-split-string ! symlink-target "/") ! steps))) ! (t ! ;; It's a file. ! (setq result (cons thisstep result))))) ! (when (>= numchase numchase-limit) ! (tramp-error ! v 'file-error ! "Maximum number (%d) of symlinks exceeded" numchase-limit)) ! (setq result (reverse result)) ! ;; Combine list to form string. ! (setq result ! (if result ! (mapconcat 'identity (cons "" result) "/") ! "/")) ! (when (and is-dir (or (string= "" result) ! (not (string= (substring result -1) "/")))) ! (setq result (concat result "/")))))) ! (tramp-message v 4 "True name of `%s' is `%s'" filename result) ! (tramp-make-tramp-file-name method user host result))))) ;; Basic functions. --- 2671,2780 ---- (defun tramp-handle-file-truename (filename &optional counter prev-dirs) "Like `file-truename' for Tramp files." (with-parsed-tramp-file-name (expand-file-name filename) nil ! (tramp-make-tramp-file-name method user host ! (with-file-property v localname "file-truename" ! (let ((result nil)) ; result steps in reverse order ! (tramp-message v 4 "Finding true name for `%s'" filename) ! (cond ! ;; Use GNU readlink --canonicalize-missing where available. ! ((tramp-get-remote-readlink v) ! (setq result ! (tramp-send-command-and-read ! v ! (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\"" ! (tramp-get-remote-readlink v) ! (tramp-shell-quote-argument localname))))) ! ! ;; Use Perl implementation. ! ((and (tramp-get-remote-perl v) ! (tramp-get-connection-property v "perl-file-spec" nil) ! (tramp-get-connection-property v "perl-cwd-realpath" nil)) ! (tramp-maybe-send-script ! v tramp-perl-file-truename "tramp_perl_file_truename") ! (setq result ! (tramp-send-command-and-read ! v ! (format "tramp_perl_file_truename %s" ! (tramp-shell-quote-argument localname))))) ! ! ;; Do it yourself. We bind `directory-sep-char' here for ! ;; XEmacs on Windows, which would otherwise use backslash. ! (t (let* ((directory-sep-char ?/) ! (steps (tramp-compat-split-string localname "/")) ! (localnamedir (tramp-run-real-handler ! 'file-name-as-directory (list localname))) ! (is-dir (string= localname localnamedir)) ! (thisstep nil) ! (numchase 0) ! ;; Don't make the following value larger than ! ;; necessary. People expect an error message in ! ;; a timely fashion when something is wrong; ! ;; otherwise they might think that Emacs is hung. ! ;; Of course, correctness has to come first. ! (numchase-limit 20) ! symlink-target) ! (while (and steps (< numchase numchase-limit)) ! (setq thisstep (pop steps)) ! (tramp-message ! v 5 "Check %s" ! (mapconcat 'identity ! (append '("") (reverse result) (list thisstep)) ! "/")) ! (setq symlink-target ! (nth 0 (file-attributes ! (tramp-make-tramp-file-name ! method user host ! (mapconcat 'identity ! (append '("") ! (reverse result) ! (list thisstep)) ! "/"))))) ! (cond ((string= "." thisstep) ! (tramp-message v 5 "Ignoring step `.'")) ! ((string= ".." thisstep) ! (tramp-message v 5 "Processing step `..'") ! (pop result)) ! ((stringp symlink-target) ! ;; It's a symlink, follow it. ! (tramp-message ! v 5 "Follow symlink to %s" symlink-target) ! (setq numchase (1+ numchase)) ! (when (file-name-absolute-p symlink-target) ! (setq result nil)) ! ;; If the symlink was absolute, we'll get a ! ;; string like "/user <at> host:/some/target"; ! ;; extract the "/some/target" part from it. ! (when (tramp-tramp-file-p symlink-target) ! (unless (tramp-equal-remote filename symlink-target) ! (tramp-error ! v 'file-error ! "Symlink target `%s' on wrong host" ! symlink-target)) ! (setq symlink-target localname)) ! (setq steps ! (append (tramp-compat-split-string ! symlink-target "/") ! steps))) ! (t ! ;; It's a file. ! (setq result (cons thisstep result))))) ! (when (>= numchase numchase-limit) ! (tramp-error ! v 'file-error ! "Maximum number (%d) of symlinks exceeded" numchase-limit)) ! (setq result (reverse result)) ! ;; Combine list to form string. ! (setq result ! (if result ! (mapconcat 'identity (cons "" result) "/") ! "/")) ! (when (and is-dir ! (or (string= "" result) ! (not (string= (substring result -1) "/")))) ! (setq result (concat result "/")))))) ! (tramp-message v 4 "True name of `%s' is `%s'" filename result) ! result))))) ;; Basic functions. --8<---------------cut here---------------end--------------->8--- --8<---------------cut here---------------start------------->8--- Index: tramp-cache.el =================================================================== RCS file: /sources/tramp/tramp/lisp/tramp-cache.el,v retrieving revision 2.57.2.1 diff -c -r2.57.2.1 tramp-cache.el *** tramp-cache.el 24 Jan 2011 10:09:40 -0000 2.57.2.1 --- tramp-cache.el 16 Nov 2011 19:54:34 -0000 *************** *** 145,150 **** --- 145,155 ---- (defun tramp-flush-file-property (vec file) "Remove all properties of FILE in the cache context of VEC." + ;; Remove file property of symlinks. + (let ((truename (tramp-get-file-property vec file "file-truename" nil))) + (when (and (stringp truename) + (not (string-equal file truename))) + (tramp-flush-file-property vec truename))) ;; Unify localname. (setq vec (copy-sequence vec)) (aset vec 3 (tramp-run-real-handler 'directory-file-name (list file))) --8<---------------cut here---------------end--------------->8--- Best regards, Michael.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.