From a43dc4243c667d2033a9e7fe5cc1d499b35a1651 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Thu, 1 Aug 2013 13:10:31 +0200 Subject: [PATCH] Complete file name handlers. * net/tramp.el (tramp-handle-set-visited-file-modtime) (tramp-handle-verify-visited-file-modtime) (tramp-handle-file-notify-rm-watch): New functions. (tramp-call-process): Do not bind `default-directory'. * net/tramp-adb.el (tramp-adb-file-name-handler-alist): Order alphabetically. [access-file, add-name-to-file, dired-call-process]: [dired-compress-file, file-acl, file-notify-rm-watch]: [file-ownership-preserved-p, file-selinux-context]: [make-directory-internal, make-symbolic-link, set-file-acl]: [set-file-selinux-context, set-visited-file-modtime]: [verify-visited-file-modtime]: Add handler. (tramp-adb-handle-write-region): Apply `set-visited-file-modtime'. * net/tramp-gvfs.el (tramp-gvfs-file-name-handler-alist) [file-notify-add-watch, file-notify-rm-watch]: [set-file-times, set-visited-file-modtime]: [verify-visited-file-modtime]: Add handler. (with-tramp-gvfs-error-message) (tramp-gvfs-handle-set-visited-file-modtime) (tramp-gvfs-fuse-file-name): Remove. (tramp-gvfs-handle-file-notify-add-watch) (tramp-gvfs-file-gvfs-monitor-file-process-filter): New defuns. (tramp-gvfs-handle-write-region): Fix error in moving tmpfile. * net/tramp-sh.el (tramp-sh-file-name-handler-alist): Order alphabetically. [file-notify-rm-watch ]: Use default Tramp handler. [executable-find]: Remove private handler. (tramp-do-copy-or-rename-file-out-of-band): Do not bind `default-directory'. (tramp-sh-handle-executable-find) (tramp-sh-handle-file-notify-rm-watch): Remove functions. (tramp-sh-file-gvfs-monitor-dir-process-filter) (tramp-sh-file-inotifywait-process-filter, tramp-set-remote-path): Do not use `format' in `tramp-message'. * net/tramp-smb.el (tramp-smb-file-name-handler-alist) [file-notify-rm-watch, set-visited-file-modtime]: [verify-visited-file-modtime]: Add handler. (tramp-smb-call-winexe): Do not bind `default-directory'. --- lisp/ChangeLog | 47 ++++++++++++++ lisp/net/tramp-adb.el | 86 ++++++++++++++++---------- lisp/net/tramp-gvfs.el | 136 ++++++++++++++++++++-------------------- lisp/net/tramp-sh.el | 137 +++++++++++++++++++---------------------- lisp/net/tramp-smb.el | 19 +++--- lisp/net/tramp.el | 88 +++++++++++++++++++++----- 6 files changed, 318 insertions(+), 195 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4a7e0e13bd1..e80c34d3842 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,50 @@ +2013-08-01 Michael Albinus + + Complete file name handlers. + + * net/tramp.el (tramp-handle-set-visited-file-modtime) + (tramp-handle-verify-visited-file-modtime) + (tramp-handle-file-notify-rm-watch): New functions. + (tramp-call-process): Do not bind `default-directory'. + + * net/tramp-adb.el (tramp-adb-file-name-handler-alist): Order + alphabetically. + [access-file, add-name-to-file, dired-call-process]: + [dired-compress-file, file-acl, file-notify-rm-watch]: + [file-ownership-preserved-p, file-selinux-context]: + [make-directory-internal, make-symbolic-link, set-file-acl]: + [set-file-selinux-context, set-visited-file-modtime]: + [verify-visited-file-modtime]: Add handler. + (tramp-adb-handle-write-region): Apply `set-visited-file-modtime'. + + * net/tramp-gvfs.el (tramp-gvfs-file-name-handler-alist) + [file-notify-add-watch, file-notify-rm-watch]: + [set-file-times, set-visited-file-modtime]: + [verify-visited-file-modtime]: Add handler. + (with-tramp-gvfs-error-message) + (tramp-gvfs-handle-set-visited-file-modtime) + (tramp-gvfs-fuse-file-name): Remove. + (tramp-gvfs-handle-file-notify-add-watch) + (tramp-gvfs-file-gvfs-monitor-file-process-filter): New defuns. + (tramp-gvfs-handle-write-region): Fix error in moving tmpfile. + + * net/tramp-sh.el (tramp-sh-file-name-handler-alist): Order + alphabetically. + [file-notify-rm-watch ]: Use default Tramp handler. + [executable-find]: Remove private handler. + (tramp-do-copy-or-rename-file-out-of-band): Do not bind + `default-directory'. + (tramp-sh-handle-executable-find) + (tramp-sh-handle-file-notify-rm-watch): Remove functions. + (tramp-sh-file-gvfs-monitor-dir-process-filter) + (tramp-sh-file-inotifywait-process-filter, tramp-set-remote-path): + Do not use `format' in `tramp-message'. + + * net/tramp-smb.el (tramp-smb-file-name-handler-alist) + [file-notify-rm-watch, set-visited-file-modtime]: + [verify-visited-file-modtime]: Add handler. + (tramp-smb-call-winexe): Do not bind `default-directory'. + 2013-08-01 Xue Fuqiao * vc/vc-hooks.el (vc-menu-map): Fix menu entry for vc-ignore. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 82b017fa230..33e9e5aa44b 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -85,53 +85,74 @@ (cons 'tramp-adb-file-name-p 'tramp-adb-file-name-handler)) (defconst tramp-adb-file-name-handler-alist - '((directory-file-name . tramp-handle-directory-file-name) + '((access-file . ignore) + (add-name-to-file . tramp-adb-handle-copy-file) + ;; `byte-compiler-base-file-name' performed by default handler. + ;; `copy-directory' performed by default handler. + (copy-file . tramp-adb-handle-copy-file) + (delete-directory . tramp-adb-handle-delete-directory) + (delete-file . tramp-adb-handle-delete-file) + ;; `diff-latest-backup-file' performed by default handler. + (directory-file-name . tramp-handle-directory-file-name) + (directory-files . tramp-handle-directory-files) + (directory-files-and-attributes + . tramp-adb-handle-directory-files-and-attributes) + (dired-call-process . ignore) + (dired-compress-file . ignore) (dired-uncache . tramp-handle-dired-uncache) + (expand-file-name . tramp-adb-handle-expand-file-name) + (file-accessible-directory-p . tramp-handle-file-accessible-directory-p) + (file-acl . ignore) + (file-attributes . tramp-adb-handle-file-attributes) + (file-directory-p . tramp-adb-handle-file-directory-p) + ;; `file-equal-p' performed by default handler. + ;; FIXME: This is too sloppy. + (file-executable-p . tramp-handle-file-exists-p) + (file-exists-p . tramp-handle-file-exists-p) + ;; `file-in-directory-p' performed by default handler. + (file-local-copy . tramp-adb-handle-file-local-copy) + (file-modes . tramp-handle-file-modes) + (file-name-all-completions . tramp-adb-handle-file-name-all-completions) (file-name-as-directory . tramp-handle-file-name-as-directory) (file-name-completion . tramp-handle-file-name-completion) - (file-name-all-completions . tramp-adb-handle-file-name-all-completions) - (file-attributes . tramp-adb-handle-file-attributes) (file-name-directory . tramp-handle-file-name-directory) (file-name-nondirectory . tramp-handle-file-name-nondirectory) - (file-truename . tramp-adb-handle-file-truename) + ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) - (file-name-as-directory . tramp-handle-file-name-as-directory) + (file-notify-add-watch . tramp-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) + (file-ownership-preserved-p . ignore) + (file-readable-p . tramp-handle-file-exists-p) (file-regular-p . tramp-handle-file-regular-p) (file-remote-p . tramp-handle-file-remote-p) - (file-accessible-directory-p . tramp-handle-file-accessible-directory-p) - (file-directory-p . tramp-adb-handle-file-directory-p) + (file-selinux-context . ignore) (file-symlink-p . tramp-handle-file-symlink-p) - ;; FIXME: This is too sloppy. - (file-executable-p . tramp-handle-file-exists-p) - (file-exists-p . tramp-handle-file-exists-p) - (file-readable-p . tramp-handle-file-exists-p) + (file-truename . tramp-adb-handle-file-truename) (file-writable-p . tramp-adb-handle-file-writable-p) - (file-local-copy . tramp-adb-handle-file-local-copy) - (file-modes . tramp-handle-file-modes) - (file-notify-add-watch . tramp-handle-file-notify-add-watch) - (file-notify-rm-watch . ignore) - (expand-file-name . tramp-adb-handle-expand-file-name) (find-backup-file-name . tramp-handle-find-backup-file-name) - (directory-files . tramp-handle-directory-files) - (directory-files-and-attributes - . tramp-adb-handle-directory-files-and-attributes) - (make-directory . tramp-adb-handle-make-directory) - (delete-directory . tramp-adb-handle-delete-directory) - (delete-file . tramp-adb-handle-delete-file) - (load . tramp-handle-load) + ;; `find-file-noselect' performed by default handler. + ;; `get-file-buffer' performed by default handler. (insert-directory . tramp-adb-handle-insert-directory) (insert-file-contents . tramp-handle-insert-file-contents) - (substitute-in-file-name . tramp-handle-substitute-in-file-name) - (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory) - (vc-registered . ignore) ;no vc control files on Android devices - (write-region . tramp-adb-handle-write-region) + (load . tramp-handle-load) + ;; `make-auto-save-file-name' performed by default handler. + (make-directory . tramp-adb-handle-make-directory) + (make-directory-internal . ignore) + (make-symbolic-link . ignore) + (process-file . tramp-adb-handle-process-file) + (rename-file . tramp-adb-handle-rename-file) + (set-file-acl . ignore) (set-file-modes . tramp-adb-handle-set-file-modes) + (set-file-selinux-context . ignore) (set-file-times . tramp-adb-handle-set-file-times) - (copy-file . tramp-adb-handle-copy-file) - (rename-file . tramp-adb-handle-rename-file) - (process-file . tramp-adb-handle-process-file) + (set-visited-file-modtime . tramp-handle-set-visited-file-modtime) (shell-command . tramp-adb-handle-shell-command) - (start-file-process . tramp-adb-handle-start-file-process)) + (start-file-process . tramp-adb-handle-start-file-process) + (substitute-in-file-name . tramp-handle-substitute-in-file-name) + (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory) + (vc-registered . ignore) + (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime) + (write-region . tramp-adb-handle-write-region)) "Alist of handler functions for Tramp ADB method.") ;; It must be a `defsubst' in order to push the whole code into @@ -599,6 +620,9 @@ But handle the case, if the \"test\" command is not available." (tramp-error v 'file-error "Cannot write: `%s' filename")) (delete-file tmpfile))) + (when (or (eq visit t) (stringp visit)) + (set-visited-file-modtime)) + (unless (equal curbuf (current-buffer)) (tramp-error v 'file-error diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index e25c9bd4caf..5bb30b04643 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -403,10 +403,10 @@ Every entry is a list (NAME ADDRESS).") ;; New handlers should be added here. (defconst tramp-gvfs-file-name-handler-alist - '( - (access-file . ignore) + '((access-file . ignore) (add-name-to-file . tramp-gvfs-handle-copy-file) ;; `byte-compiler-base-file-name' performed by default handler. + ;; `copy-directory' performed by default handler. (copy-file . tramp-gvfs-handle-copy-file) (delete-directory . tramp-gvfs-handle-delete-directory) (delete-file . tramp-gvfs-handle-delete-file) @@ -418,14 +418,15 @@ Every entry is a list (NAME ADDRESS).") (dired-call-process . ignore) (dired-compress-file . ignore) (dired-uncache . tramp-handle-dired-uncache) - ;; `executable-find' is not official yet. performed by default handler. (expand-file-name . tramp-gvfs-handle-expand-file-name) (file-accessible-directory-p . tramp-handle-file-accessible-directory-p) (file-acl . ignore) (file-attributes . tramp-gvfs-handle-file-attributes) (file-directory-p . tramp-gvfs-handle-file-directory-p) + ;; `file-equal-p' performed by default handler. (file-executable-p . tramp-gvfs-handle-file-executable-p) (file-exists-p . tramp-handle-file-exists-p) + ;; `file-in-directory-p' performed by default handler. (file-local-copy . tramp-gvfs-handle-file-local-copy) (file-modes . tramp-handle-file-modes) (file-name-all-completions . tramp-gvfs-handle-file-name-all-completions) @@ -435,8 +436,8 @@ Every entry is a list (NAME ADDRESS).") (file-name-nondirectory . tramp-handle-file-name-nondirectory) ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) - (file-notify-add-watch . tramp-handle-file-notify-add-watch) - (file-notify-rm-watch . ignore) + (file-notify-add-watch . tramp-gvfs-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) (file-ownership-preserved-p . ignore) (file-readable-p . tramp-gvfs-handle-file-readable-p) (file-regular-p . tramp-handle-file-regular-p) @@ -451,6 +452,7 @@ Every entry is a list (NAME ADDRESS).") (insert-directory . tramp-gvfs-handle-insert-directory) (insert-file-contents . tramp-gvfs-handle-insert-file-contents) (load . tramp-handle-load) + ;; `make-auto-save-file-name' performed by default handler. (make-directory . tramp-gvfs-handle-make-directory) (make-directory-internal . ignore) (make-symbolic-link . ignore) @@ -459,15 +461,15 @@ Every entry is a list (NAME ADDRESS).") (set-file-acl . ignore) (set-file-modes . ignore) (set-file-selinux-context . ignore) - (set-visited-file-modtime . tramp-gvfs-handle-set-visited-file-modtime) + (set-file-times . ignore) + (set-visited-file-modtime . tramp-handle-set-visited-file-modtime) (shell-command . ignore) (start-file-process . ignore) (substitute-in-file-name . tramp-handle-substitute-in-file-name) (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory) (vc-registered . ignore) - ;; `verify-visited-file-modtime' performed by default handler. - (write-region . tramp-gvfs-handle-write-region) -) + (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime) + (write-region . tramp-gvfs-handle-write-region)) "Alist of handler functions for Tramp GVFS method. Operations not mentioned here will be handled by the default Emacs primitives.") @@ -555,28 +557,6 @@ will be traced by Tramp with trace level 6." (tramp-compat-font-lock-add-keywords 'emacs-lisp-mode '("\\")) -(defmacro with-tramp-gvfs-error-message (filename handler &rest args) - "Apply a Tramp GVFS `handler'. -In case of an error, modify the error message by replacing -`filename' with its GVFS mounted name." - `(let ((fuse-file-name (regexp-quote (tramp-gvfs-fuse-file-name ,filename))) - elt) - (condition-case err - (tramp-compat-funcall ,handler ,@args) - (error - (setq elt (cdr err)) - (while elt - (when (and (stringp (car elt)) - (string-match fuse-file-name (car elt))) - (setcar elt (replace-match ,filename t t (car elt)))) - (setq elt (cdr elt))) - (signal (car err) (cdr err)))))) - -(put 'with-tramp-gvfs-error-message 'lisp-indent-function 2) -(put 'with-tramp-gvfs-error-message 'edebug-form-spec '(form symbolp body)) -(tramp-compat-font-lock-add-keywords - 'emacs-lisp-mode '("\\")) - (defvar tramp-gvfs-dbus-event-vector nil "Current Tramp file name to be used, as vector. It is needed when D-Bus signals or errors arrive, because there @@ -943,6 +923,64 @@ is no information where to trace the message.") v (concat localname filename) "file-name-all-completions" result)))))))) +(defun tramp-gvfs-handle-file-notify-add-watch (file-name flags callback) + "Like `file-notify-add-watch' for Tramp files." + (setq file-name (expand-file-name file-name)) + (with-parsed-tramp-file-name file-name nil + (let ((p (start-process + "gvfs-monitor-file" (generate-new-buffer " *gvfs-monitor-file*") + "gvfs-monitor-file" (tramp-gvfs-url-file-name file-name)))) + (if (not (processp p)) + (tramp-error + v 'file-notify-error "gvfs-monitor-file failed to start") + (tramp-compat-set-process-query-on-exit-flag p nil) + (set-process-filter p 'tramp-gvfs-file-gvfs-monitor-file-process-filter) + (with-current-buffer (process-buffer p) + (setq default-directory (file-name-directory file-name))) + p)))) + +(defun tramp-gvfs-file-gvfs-monitor-file-process-filter (proc string) + "Read output from \"gvfs-monitor-file\" and add corresponding file-notify events." + (let* ((rest-string (tramp-compat-process-get proc 'rest-string)) + (dd (with-current-buffer (process-buffer proc) default-directory)) + (ddu (regexp-quote (tramp-gvfs-url-file-name dd)))) + (when rest-string + (tramp-message proc 10 "Previous string:\n%s" rest-string)) + (tramp-message proc 6 "%S\n%s" proc string) + (setq string (concat rest-string string) + ;; Attribute change is returned in unused wording. + string (replace-regexp-in-string + "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) + + (while (string-match + (concat "^[\n\r]*" + "File Monitor Event:[\n\r]+" + "File = \\([^\n\r]+\\)[\n\r]+" + "Event = \\([^[:blank:]]+\\)[\n\r]+") + string) + (let ((action (intern-soft + (replace-regexp-in-string + "_" "-" (downcase (match-string 2 string))))) + (file (match-string 1 string))) + (setq string (replace-match "" nil nil string)) + ;; File names are returned as URL paths. We must convert them. + (when (string-match ddu file) + (setq file (replace-match dd nil nil file))) + (while (string-match "%\\([0-9A-F]\\{2\\}\\)" file) + (setq file + (replace-match + (char-to-string (string-to-number (match-string 1 file) 16)) + nil nil file))) + ;; Usually, we would add an Emacs event now. Unfortunately, + ;; `unread-command-events' does not accept several events at + ;; once. Therefore, we apply the callback directly. + (tramp-compat-funcall 'file-notify-callback (list proc action file)))) + + ;; Save rest of the string. + (when (zerop (length string)) (setq string nil)) + (when string (tramp-message proc 10 "Rest string:\n%s" string)) + (tramp-compat-process-put proc 'rest-string string))) + (defun tramp-gvfs-handle-file-readable-p (filename) "Like `file-readable-p' for Tramp files." (with-parsed-tramp-file-name filename nil @@ -1054,22 +1092,6 @@ is no information where to trace the message.") (tramp-flush-file-property v (file-name-directory localname)) (tramp-flush-file-property v localname)))))) -(defun tramp-gvfs-handle-set-visited-file-modtime (&optional time-list) - "Like `set-visited-file-modtime' for Tramp files." - (unless (buffer-file-name) - (error "Can't set-visited-file-modtime: buffer `%s' not visiting a file" - (buffer-name))) - (unless time-list - (let ((f (buffer-file-name))) - (with-parsed-tramp-file-name f nil - (let ((remote-file-name-inhibit-cache t) - (attr (file-attributes f))) - ;; '(-1 65535) means file doesn't exists yet. - (setq time-list (or (nth 5 attr) '(-1 65535))))))) - ;; We use '(0 0) as a don't-know value. - (unless (not (equal time-list '(0 0))) - (tramp-run-real-handler 'set-visited-file-modtime (list time-list)))) - (defun tramp-gvfs-handle-write-region (start end filename &optional append visit lockname confirm) "Like `write-region' for Tramp files." @@ -1082,7 +1104,7 @@ is no information where to trace the message.") (let ((tmpfile (tramp-compat-make-temp-file filename))) (write-region start end tmpfile) (condition-case nil - (rename-file tmpfile filename) + (rename-file tmpfile filename 'ok-if-already-exists) (error (delete-file tmpfile) (tramp-error @@ -1137,24 +1159,6 @@ is no information where to trace the message.") (dbus-unescape-from-identifier (replace-regexp-in-string "^.*/\\([^/]+\\)$" "\\1" object-path))) -(defun tramp-gvfs-fuse-file-name (filename) - "Return FUSE file name, which is directly accessible." - (with-parsed-tramp-file-name (expand-file-name filename) nil - (tramp-gvfs-maybe-open-connection v) - (let ((prefix (tramp-get-file-property v "/" "prefix" "")) - (fuse-mountpoint - (tramp-get-file-property v "/" "fuse-mountpoint" nil))) - (unless fuse-mountpoint - (tramp-error - v 'file-error "There is no FUSE mount point for `%s'" filename)) - ;; We must hide the prefix, if any. - (when (string-match (concat "^" (regexp-quote prefix)) localname) - (setq localname (replace-match "" t t localname))) - (tramp-message - v 10 "remote file `%s' is local file `%s'" - filename (concat fuse-mountpoint localname)) - (concat fuse-mountpoint localname)))) - (defun tramp-bluez-address (device) "Return bluetooth device address from a given bluetooth DEVICE name." (when (stringp device) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 441849fd2af..f9e68d0dad0 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -801,73 +801,78 @@ existence, and file readability. Input shall be read via here-document, otherwise the command could exceed maximum length of command line.") -;; New handlers should be added here. The following operations can be -;; handled using the normal primitives: file-name-sans-versions, -;; get-file-buffer. +;; New handlers should be added here. (defconst tramp-sh-file-name-handler-alist - '((load . tramp-handle-load) - (make-symbolic-link . tramp-sh-handle-make-symbolic-link) - (file-name-as-directory . tramp-handle-file-name-as-directory) - (file-name-directory . tramp-handle-file-name-directory) - (file-name-nondirectory . tramp-handle-file-name-nondirectory) - (file-truename . tramp-sh-handle-file-truename) - (file-exists-p . tramp-sh-handle-file-exists-p) - (file-accessible-directory-p . tramp-handle-file-accessible-directory-p) - (file-directory-p . tramp-sh-handle-file-directory-p) - (file-executable-p . tramp-sh-handle-file-executable-p) - (file-readable-p . tramp-sh-handle-file-readable-p) - (file-regular-p . tramp-handle-file-regular-p) - (file-symlink-p . tramp-handle-file-symlink-p) - (file-writable-p . tramp-sh-handle-file-writable-p) - (file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p) - (file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p) - (file-attributes . tramp-sh-handle-file-attributes) - (file-modes . tramp-handle-file-modes) - (directory-files . tramp-handle-directory-files) - (directory-files-and-attributes - . tramp-sh-handle-directory-files-and-attributes) - (file-name-all-completions . tramp-sh-handle-file-name-all-completions) - (file-name-completion . tramp-handle-file-name-completion) + '(;; `access-file' performed by default handler. (add-name-to-file . tramp-sh-handle-add-name-to-file) - (copy-file . tramp-sh-handle-copy-file) + ;; `byte-compiler-base-file-name' performed by default handler. (copy-directory . tramp-sh-handle-copy-directory) - (rename-file . tramp-sh-handle-rename-file) - (set-file-modes . tramp-sh-handle-set-file-modes) - (set-file-times . tramp-sh-handle-set-file-times) - (make-directory . tramp-sh-handle-make-directory) + (copy-file . tramp-sh-handle-copy-file) (delete-directory . tramp-sh-handle-delete-directory) (delete-file . tramp-sh-handle-delete-file) + ;; `diff-latest-backup-file' performed by default handler. (directory-file-name . tramp-handle-directory-file-name) - ;; `executable-find' is not official yet. - (executable-find . tramp-sh-handle-executable-find) - (start-file-process . tramp-sh-handle-start-file-process) - (process-file . tramp-sh-handle-process-file) - (shell-command . tramp-handle-shell-command) - (insert-directory . tramp-sh-handle-insert-directory) + (directory-files . tramp-handle-directory-files) + (directory-files-and-attributes + . tramp-sh-handle-directory-files-and-attributes) + ;; `dired-call-process' performed by default handler. + (dired-compress-file . tramp-sh-handle-dired-compress-file) + (dired-recursive-delete-directory + . tramp-sh-handle-dired-recursive-delete-directory) + (dired-uncache . tramp-handle-dired-uncache) (expand-file-name . tramp-sh-handle-expand-file-name) - (substitute-in-file-name . tramp-handle-substitute-in-file-name) + (file-accessible-directory-p . tramp-handle-file-accessible-directory-p) + (file-acl . tramp-sh-handle-file-acl) + (file-attributes . tramp-sh-handle-file-attributes) + (file-directory-p . tramp-sh-handle-file-directory-p) + ;; `file-equal-p' performed by default handler. + (file-executable-p . tramp-sh-handle-file-executable-p) + (file-exists-p . tramp-sh-handle-file-exists-p) + ;; `file-in-directory-p' performed by default handler. (file-local-copy . tramp-sh-handle-file-local-copy) + (file-modes . tramp-handle-file-modes) + (file-name-all-completions . tramp-sh-handle-file-name-all-completions) + (file-name-as-directory . tramp-handle-file-name-as-directory) + (file-name-completion . tramp-handle-file-name-completion) + (file-name-directory . tramp-handle-file-name-directory) + (file-name-nondirectory . tramp-handle-file-name-nondirectory) + ;; `file-name-sans-versions' performed by default handler. + (file-newer-than-file-p . tramp-sh-handle-file-newer-than-file-p) + (file-notify-add-watch . tramp-sh-handle-file-notify-add-watch) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) + (file-ownership-preserved-p . tramp-sh-handle-file-ownership-preserved-p) + (file-readable-p . tramp-sh-handle-file-readable-p) + (file-regular-p . tramp-handle-file-regular-p) (file-remote-p . tramp-handle-file-remote-p) + (file-selinux-context . tramp-sh-handle-file-selinux-context) + (file-symlink-p . tramp-handle-file-symlink-p) + (file-truename . tramp-sh-handle-file-truename) + (file-writable-p . tramp-sh-handle-file-writable-p) + (find-backup-file-name . tramp-handle-find-backup-file-name) + ;; `find-file-noselect' performed by default handler. + ;; `get-file-buffer' performed by default handler. + (insert-directory . tramp-sh-handle-insert-directory) (insert-file-contents . tramp-handle-insert-file-contents) (insert-file-contents-literally . tramp-sh-handle-insert-file-contents-literally) - (write-region . tramp-sh-handle-write-region) - (find-backup-file-name . tramp-handle-find-backup-file-name) + (load . tramp-handle-load) (make-auto-save-file-name . tramp-sh-handle-make-auto-save-file-name) - (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory) - (dired-compress-file . tramp-sh-handle-dired-compress-file) - (dired-recursive-delete-directory - . tramp-sh-handle-dired-recursive-delete-directory) - (dired-uncache . tramp-handle-dired-uncache) - (set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime) - (verify-visited-file-modtime . tramp-sh-handle-verify-visited-file-modtime) - (file-selinux-context . tramp-sh-handle-file-selinux-context) - (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context) - (file-acl . tramp-sh-handle-file-acl) + (make-directory . tramp-sh-handle-make-directory) + (make-symbolic-link . tramp-sh-handle-make-symbolic-link) + (process-file . tramp-sh-handle-process-file) + (rename-file . tramp-sh-handle-rename-file) (set-file-acl . tramp-sh-handle-set-file-acl) + (set-file-modes . tramp-sh-handle-set-file-modes) + (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context) + (set-file-times . tramp-sh-handle-set-file-times) + (set-visited-file-modtime . tramp-sh-handle-set-visited-file-modtime) + (shell-command . tramp-handle-shell-command) + (start-file-process . tramp-sh-handle-start-file-process) + (substitute-in-file-name . tramp-handle-substitute-in-file-name) + (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory) (vc-registered . tramp-sh-handle-vc-registered) - (file-notify-add-watch . tramp-sh-handle-file-notify-add-watch) - (file-notify-rm-watch . tramp-sh-handle-file-notify-rm-watch)) + (verify-visited-file-modtime . tramp-sh-handle-verify-visited-file-modtime) + (write-region . tramp-sh-handle-write-region)) "Alist of handler functions. Operations not mentioned here will be handled by the normal Emacs functions.") @@ -2284,9 +2289,7 @@ The method used must be an out-of-band method." (tramp-get-method-parameter method 'tramp-copy-env)))) ;; Check for program. - (unless (let ((default-directory - (tramp-compat-temporary-file-directory))) - (executable-find copy-program)) + (unless (executable-find copy-program) (tramp-error v 'file-error "Cannot find copy program: %s" copy-program)) @@ -2667,11 +2670,6 @@ the result will be a local, non-Tramp, filename." ;;; Remote commands: -(defun tramp-sh-handle-executable-find (command) - "Like `executable-find' for Tramp files." - (with-parsed-tramp-file-name default-directory nil - (tramp-find-executable v command (tramp-get-remote-path v) t))) - (defun tramp-process-sentinel (proc event) "Flush file caches." (unless (memq (process-status proc) '(run open)) @@ -3430,8 +3428,8 @@ Fall back to normal file name handler if no Tramp handler exists." (file-remote-p default-directory))) (rest-string (tramp-compat-process-get proc 'rest-string))) (when rest-string - (tramp-message proc 10 (format "Previous string:\n%s" rest-string))) - (tramp-message proc 6 (format "%S\n%s" proc string)) + (tramp-message proc 10 "Previous string:\n%s" rest-string)) + (tramp-message proc 6 "%S\n%s" proc string) (setq string (concat rest-string string) ;; Attribute change is returned in unused wording. string (replace-regexp-in-string @@ -3463,12 +3461,12 @@ Fall back to normal file name handler if no Tramp handler exists." ;; Save rest of the string. (when (zerop (length string)) (setq string nil)) - (when string (tramp-message proc 10 (format "Rest string:\n%s" string))) + (when string (tramp-message proc 10 "Rest string:\n%s" string)) (tramp-compat-process-put proc 'rest-string string))) (defun tramp-sh-file-inotifywait-process-filter (proc string) "Read output from \"inotifywait\" and add corresponding file-notify events." - (tramp-message proc 6 (format "%S\n%s" proc string)) + (tramp-message proc 6 "%S\n%s" proc string) (dolist (line (split-string string "[\n\r]+" 'omit-nulls)) ;; Check, whether there is a problem. (unless @@ -3492,15 +3490,6 @@ Fall back to normal file name handler if no Tramp handler exists." ;; once. Therefore, we apply the callback directly. (tramp-compat-funcall 'file-notify-callback object)))) -(defvar file-notify-descriptors) -(defun tramp-sh-handle-file-notify-rm-watch (proc) - "Like `file-notify-rm-watch' for Tramp files." - ;; The descriptor must be a process object. - (unless (and (processp proc) (gethash proc file-notify-descriptors)) - (tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc)) - (tramp-message proc 6 (format "Kill %S" proc)) - (kill-process proc)) - ;;; Internal Functions: (defun tramp-maybe-send-script (vec script name) @@ -3618,7 +3607,7 @@ This function expects to be in the right *tramp* buffer." I.e., for each directory in `tramp-remote-path', it is tested whether it exists and if so, it is added to the environment variable PATH." - (tramp-message vec 5 (format "Setting $PATH environment variable")) + (tramp-message vec 5 "Setting $PATH environment variable") (tramp-send-command vec (format "PATH=%s; export PATH" (mapconcat 'identity (tramp-get-remote-path vec) ":")))) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index fee34f856dd..29847556dfe 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -177,8 +177,7 @@ See `tramp-actions-before-shell' for more info.") ;; New handlers should be added here. (defconst tramp-smb-file-name-handler-alist - '( - ;; `access-file' performed by default handler. + '(;; `access-file' performed by default handler. (add-name-to-file . tramp-smb-handle-add-name-to-file) ;; `byte-compiler-base-file-name' performed by default handler. (copy-directory . tramp-smb-handle-copy-directory) @@ -198,8 +197,10 @@ See `tramp-actions-before-shell' for more info.") (file-acl . tramp-smb-handle-file-acl) (file-attributes . tramp-smb-handle-file-attributes) (file-directory-p . tramp-smb-handle-file-directory-p) + ;; `file-equal-p' performed by default handler. (file-executable-p . tramp-handle-file-exists-p) (file-exists-p . tramp-handle-file-exists-p) + ;; `file-in-directory-p' performed by default handler. (file-local-copy . tramp-smb-handle-file-local-copy) (file-modes . tramp-handle-file-modes) (file-name-all-completions . tramp-smb-handle-file-name-all-completions) @@ -210,7 +211,7 @@ See `tramp-actions-before-shell' for more info.") ;; `file-name-sans-versions' performed by default handler. (file-newer-than-file-p . tramp-handle-file-newer-than-file-p) (file-notify-add-watch . tramp-handle-file-notify-add-watch) - (file-notify-rm-watch . ignore) + (file-notify-rm-watch . tramp-handle-file-notify-rm-watch) (file-ownership-preserved-p . ignore) (file-readable-p . tramp-handle-file-exists-p) (file-regular-p . tramp-handle-file-regular-p) @@ -225,6 +226,7 @@ See `tramp-actions-before-shell' for more info.") (insert-directory . tramp-smb-handle-insert-directory) (insert-file-contents . tramp-handle-insert-file-contents) (load . tramp-handle-load) + ;; `make-auto-save-file-name' performed by default handler. (make-directory . tramp-smb-handle-make-directory) (make-directory-internal . tramp-smb-handle-make-directory-internal) (make-symbolic-link . tramp-smb-handle-make-symbolic-link) @@ -234,15 +236,14 @@ See `tramp-actions-before-shell' for more info.") (set-file-modes . tramp-smb-handle-set-file-modes) (set-file-selinux-context . ignore) (set-file-times . ignore) - (set-visited-file-modtime . ignore) + (set-visited-file-modtime . tramp-handle-set-visited-file-modtime) (shell-command . tramp-handle-shell-command) (start-file-process . tramp-smb-handle-start-file-process) (substitute-in-file-name . tramp-smb-handle-substitute-in-file-name) (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory) (vc-registered . ignore) - (verify-visited-file-modtime . ignore) - (write-region . tramp-smb-handle-write-region) -) + (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime) + (write-region . tramp-smb-handle-write-region)) "Alist of handler functions for Tramp SMB method. Operations not mentioned here will be handled by the default Emacs primitives.") @@ -1786,9 +1787,7 @@ Returns nil if an error message has appeared." (tramp-get-buffer vec) ;; Check for program. - (unless (let ((default-directory - (tramp-compat-temporary-file-directory))) - (executable-find tramp-smb-winexe-program)) + (unless (executable-find tramp-smb-winexe-program) (tramp-error vec 'file-error "Cannot find program: %s" tramp-smb-winexe-program)) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 48e13004c36..8ce5f2eae9b 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1975,11 +1975,11 @@ ARGS are the arguments OPERATION has been called with." 'dired-compress-file 'dired-uncache 'file-accessible-directory-p 'file-attributes 'file-directory-p 'file-executable-p 'file-exists-p - 'file-local-copy 'file-remote-p 'file-modes + 'file-local-copy 'file-modes 'file-name-as-directory 'file-name-directory 'file-name-nondirectory 'file-name-sans-versions 'file-ownership-preserved-p 'file-readable-p - 'file-regular-p 'file-symlink-p 'file-truename + 'file-regular-p 'file-remote-p 'file-symlink-p 'file-truename 'file-writable-p 'find-backup-file-name 'find-file-noselect 'get-file-buffer 'insert-directory 'insert-file-contents 'load 'make-directory 'make-directory-internal @@ -2008,7 +2008,7 @@ ARGS are the arguments OPERATION has been called with." ;; Emacs 23+ only. 'copy-directory ;; Emacs 24+ only. - 'file-in-directory-p 'file-equal-p + 'file-equal-p 'file-in-directory-p ;; XEmacs only. 'dired-make-relative-symlink 'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail)) @@ -3287,14 +3287,78 @@ beginning of local filename are not substituted." ;; for backward compatibility. (expand-file-name "~/")) +(defun tramp-handle-set-visited-file-modtime (&optional time-list) + "Like `set-visited-file-modtime' for Tramp files." + (unless (buffer-file-name) + (error "Can't set-visited-file-modtime: buffer `%s' not visiting a file" + (buffer-name))) + (unless time-list + (let ((remote-file-name-inhibit-cache t)) + ;; '(-1 65535) means file doesn't exists yet. + (setq time-list + (or (nth 5 (file-attributes (buffer-file-name))) '(-1 65535))))) + ;; We use '(0 0) as a don't-know value. + (unless (equal time-list '(0 0)) + (tramp-run-real-handler 'set-visited-file-modtime (list time-list)))) + +(defun tramp-handle-verify-visited-file-modtime (&optional buf) + "Like `verify-visited-file-modtime' for Tramp files. +At the time `verify-visited-file-modtime' calls this function, we +already know that the buffer is visiting a file and that +`visited-file-modtime' does not return 0. Do not call this +function directly, unless those two cases are already taken care +of." + (with-current-buffer (or buf (current-buffer)) + (let ((f (buffer-file-name))) + ;; There is no file visiting the buffer, or the buffer has no + ;; recorded last modification time, or there is no established + ;; connection. + (if (or (not f) + (eq (visited-file-modtime) 0) + (not (tramp-file-name-handler 'file-remote-p f nil 'connected))) + t + (with-parsed-tramp-file-name f nil + (let* ((remote-file-name-inhibit-cache t) + (attr (file-attributes f)) + (modtime (nth 5 attr)) + (mt (visited-file-modtime))) + + (cond + ;; File exists, and has a known modtime. + ((and attr (not (equal modtime '(0 0)))) + (< (abs (tramp-time-diff + modtime + ;; For compatibility, deal with both the old + ;; (HIGH . LOW) and the new (HIGH LOW) return + ;; values of `visited-file-modtime'. + (if (atom (cdr mt)) + (list (car mt) (cdr mt)) + mt))) + 2)) + ;; Modtime has the don't know value. + (attr t) + ;; If file does not exist, say it is not modified if and + ;; only if that agrees with the buffer's record. + (t (equal mt '(-1 65535)))))))))) + (defun tramp-handle-file-notify-add-watch (filename flags callback) "Like `file-notify-add-watch' for Tramp files." - ;; This is the default handler. Some packages might have its own one. + ;; This is the default handler. tramp-gvfs.el and tramp-sh.el have + ;; its own one. (setq filename (expand-file-name filename)) (with-parsed-tramp-file-name filename nil (tramp-error v 'file-notify-error "File notification not supported for `%s'" filename))) +(defvar file-notify-descriptors) +(defun tramp-handle-file-notify-rm-watch (proc) + "Like `file-notify-rm-watch' for Tramp files." + ;; The descriptor must be a process object. + (unless (and (processp proc) (gethash proc file-notify-descriptors)) + (tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc)) + (tramp-message proc 6 "Kill %S" proc) + (kill-process proc)) + ;;; Functions for establishing connection: ;; The following functions are actions to be taken when seeing certain @@ -3951,16 +4015,12 @@ This is needed because for some Emacs flavors Tramp has defadvised `call-process' to behave like `process-file'. The Lisp error raised when PROGRAM is nil is trapped also, returning 1. Furthermore, traces are written with verbosity of 6." - (let ((default-directory - (if (file-remote-p default-directory) - (tramp-compat-temporary-file-directory) - default-directory))) - (tramp-message - (vector tramp-current-method tramp-current-user tramp-current-host nil nil) - 6 "%s %s %s" program infile args) - (if (executable-find program) - (apply 'call-process program infile destination display args) - 1))) + (tramp-message + (vector tramp-current-method tramp-current-user tramp-current-host nil nil) + 6 "%s %s %s" program infile args) + (if (executable-find program) + (apply 'call-process program infile destination display args) + 1)) ;;;###tramp-autoload (defun tramp-read-passwd (proc &optional prompt) -- 2.39.2