[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#9879: 23.3; making script executable with tramp
From: |
Michael Albinus |
Subject: |
bug#9879: 23.3; making script executable with tramp |
Date: |
Wed, 16 Nov 2011 20:59:56 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.0.90 (gnu/linux) |
Michael Albinus <michael.albinus@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@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@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.