aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2013-07-05 15:34:01 +0200
committerMichael Albinus2013-07-05 15:34:01 +0200
commitddbdfd6f90c513e15ad5896dea156110f048322f (patch)
treed850b54117c1d98f5ce8f32db3b7424958f3dbe1
parent96eb829aa781926a66524237b266de44c564bf60 (diff)
downloademacs-ddbdfd6f90c513e15ad5896dea156110f048322f.tar.gz
emacs-ddbdfd6f90c513e15ad5896dea156110f048322f.zip
* net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support
both "gvfs-monitor-dir" and "inotifywait". (tramp-sh-file-inotifywait-process-filter): Renamed from `tramp-sh-file-notify-process-filter'. (tramp-sh-file-gvfs-monitor-dir-process-filter) (tramp-get-remote-gvfs-monitor-dir): New defuns.
-rw-r--r--lisp/ChangeLog9
-rw-r--r--lisp/net/tramp-sh.el105
2 files changed, 88 insertions, 26 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index d0c53d4d023..3dfa2f4a11b 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,12 @@
12013-07-05 Michael Albinus <michael.albinus@gmx.de>
2
3 * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support
4 both "gvfs-monitor-dir" and "inotifywait".
5 (tramp-sh-file-inotifywait-process-filter): Renamed from
6 `tramp-sh-file-notify-process-filter'.
7 (tramp-sh-file-gvfs-monitor-dir-process-filter)
8 (tramp-get-remote-gvfs-monitor-dir): New defuns.
9
12013-07-05 Leo Liu <sdl.web@gmail.com> 102013-07-05 Leo Liu <sdl.web@gmail.com>
2 11
3 * autoinsert.el (auto-insert-alist): Default to lexical-binding. 12 * autoinsert.el (auto-insert-alist): Default to lexical-binding.
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index f402e2b2774..f0423cbfa68 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -3378,32 +3378,79 @@ Fall back to normal file name handler if no Tramp handler exists."
3378 ;; Default file name handlers, we don't care. 3378 ;; Default file name handlers, we don't care.
3379 (t (tramp-run-real-handler operation args))))))) 3379 (t (tramp-run-real-handler operation args)))))))
3380 3380
3381;; We use inotify for implementation. It is more likely to exist than glib.
3382(defun tramp-sh-handle-file-notify-add-watch (file-name flags callback) 3381(defun tramp-sh-handle-file-notify-add-watch (file-name flags callback)
3383 "Like `file-notify-add-watch' for Tramp files." 3382 "Like `file-notify-add-watch' for Tramp files."
3384 (setq file-name (expand-file-name file-name)) 3383 (setq file-name (expand-file-name file-name))
3385 (with-parsed-tramp-file-name file-name nil 3384 (with-parsed-tramp-file-name file-name nil
3386 (let* ((default-directory (file-name-directory file-name)) 3385 (let* ((default-directory (file-name-directory file-name))
3387 (command (tramp-get-remote-inotifywait v)) 3386 command events filter p)
3388 (events 3387 (cond
3389 (cond 3388 ;; gvfs-monitor-dir.
3390 ((and (memq 'change flags) (memq 'attribute-change flags)) 3389 ((setq command (tramp-get-remote-gvfs-monitor-dir v))
3391 "create,modify,move,delete,attrib") 3390 (setq filter 'tramp-sh-file-gvfs-monitor-dir-process-filter
3392 ((memq 'change flags) "create,modify,move,delete") 3391 p (start-file-process
3393 ((memq 'attribute-change flags) "attrib"))) 3392 "gvfs-monitor-dir" (generate-new-buffer " *gvfs-monitor-dir*")
3394 (p (and command 3393 command localname)))
3395 (start-file-process 3394 ;; inotifywait.
3396 "inotifywait" (generate-new-buffer " *inotifywait*") 3395 ((setq command (tramp-get-remote-inotifywait v))
3397 command "-mq" "-e" events localname)))) 3396 (setq filter 'tramp-sh-file-inotifywait-process-filter
3397 events
3398 (cond
3399 ((and (memq 'change flags) (memq 'attribute-change flags))
3400 "create,modify,move,delete,attrib")
3401 ((memq 'change flags) "create,modify,move,delete")
3402 ((memq 'attribute-change flags) "attrib"))
3403 p (start-file-process
3404 "inotifywait" (generate-new-buffer " *inotifywait*")
3405 command "-mq" "-e" events localname)))
3406 ;; None.
3407 (t (tramp-error
3408 v 'file-notify-error
3409 "No file notification program found on %s"
3410 (file-remote-p file-name))))
3398 ;; Return the process object as watch-descriptor. 3411 ;; Return the process object as watch-descriptor.
3399 (if (not (processp p)) 3412 (if (not (processp p))
3400 (tramp-error 3413 (tramp-error
3401 v 'file-notify-error "`inotifywait' not found on remote host") 3414 v 'file-notify-error "`%s' failed to start on remote host" command)
3402 (tramp-compat-set-process-query-on-exit-flag p nil) 3415 (tramp-compat-set-process-query-on-exit-flag p nil)
3403 (set-process-filter p 'tramp-sh-file-notify-process-filter) 3416 (set-process-filter p filter)
3404 p)))) 3417 p))))
3405 3418
3406(defun tramp-sh-file-notify-process-filter (proc string) 3419(defun tramp-sh-file-gvfs-monitor-dir-process-filter (proc string)
3420 "Read output from \"gvfs-monitor-dir\" and add corresponding file-notify events."
3421 (tramp-message proc 6 (format "%S\n%s" proc string))
3422 (with-current-buffer (process-buffer proc)
3423 (dolist
3424 (line
3425 (split-string string "Directory Monitor Event:[\n\r]+" 'omit-nulls))
3426 ;; Attribute change is returned in unused wording.
3427 (setq line
3428 (replace-regexp-in-string
3429 "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" line))
3430 ;; Check, whether there is a problem.
3431 (unless
3432 (string-match
3433 "^Child = \\([^[:blank:]]+\\)[\n\r]+\\(Other = \\([^[:blank:]]+\\)[\n\r]+\\)?Event = \\([^[:blank:]]+\\)[\n\r]+$" line)
3434 (tramp-error proc 'file-notify-error "%s" line))
3435
3436 (let* ((remote-prefix (file-remote-p default-directory))
3437 (object
3438 (list
3439 proc
3440 (intern-soft
3441 (replace-regexp-in-string
3442 "_" "-" (downcase (match-string 4 line))))
3443 ;; File names are returned as absolute paths. We must
3444 ;; add the remote prefix.
3445 (concat remote-prefix (match-string 1 line))
3446 (when (match-string 3 line)
3447 (concat remote-prefix (match-string 3 line))))))
3448 ;; Usually, we would add an Emacs event now. Unfortunately,
3449 ;; `unread-command-events' does not accept several events at
3450 ;; once. Therefore, we apply the callback directly.
3451 (tramp-compat-funcall 'file-notify-callback object)))))
3452
3453(defun tramp-sh-file-inotifywait-process-filter (proc string)
3407 "Read output from \"inotifywait\" and add corresponding file-notify events." 3454 "Read output from \"inotifywait\" and add corresponding file-notify events."
3408 (tramp-message proc 6 (format "%S\n%s" proc string)) 3455 (tramp-message proc 6 (format "%S\n%s" proc string))
3409 (dolist (line (split-string string "[\n\r]+" 'omit-nulls)) 3456 (dolist (line (split-string string "[\n\r]+" 'omit-nulls))
@@ -3413,17 +3460,17 @@ Fall back to normal file name handler if no Tramp handler exists."
3413 "^[^[:blank:]]+[[:blank:]]+\\([^[:blank:]]+\\)+\\([[:blank:]]+\\([^[:blank:]]+\\)\\)?[[:blank:]]*$" line) 3460 "^[^[:blank:]]+[[:blank:]]+\\([^[:blank:]]+\\)+\\([[:blank:]]+\\([^[:blank:]]+\\)\\)?[[:blank:]]*$" line)
3414 (tramp-error proc 'file-notify-error "%s" line)) 3461 (tramp-error proc 'file-notify-error "%s" line))
3415 3462
3416 ;; Usually, we would add an Emacs event now. Unfortunately, 3463 (let ((object
3417 ;; `unread-command-events' does not accept several events at once. 3464 (list
3418 ;; Therefore, we apply the callback directly. 3465 proc
3419 (let* ((object 3466 (mapcar
3420 (list 3467 (lambda (x)
3421 proc 3468 (intern-soft (replace-regexp-in-string "_" "-" (downcase x))))
3422 (mapcar 3469 (split-string (match-string 1 line) "," 'omit-nulls))
3423 (lambda (x) 3470 (match-string 3 line))))
3424 (intern-soft (replace-regexp-in-string "_" "-" (downcase x)))) 3471 ;; Usually, we would add an Emacs event now. Unfortunately,
3425 (split-string (match-string 1 line) "," 'omit-nulls)) 3472 ;; `unread-command-events' does not accept several events at
3426 (match-string 3 line)))) 3473 ;; once. Therefore, we apply the callback directly.
3427 (tramp-compat-funcall 'file-notify-callback object)))) 3474 (tramp-compat-funcall 'file-notify-callback object))))
3428 3475
3429(defvar file-notify-descriptors) 3476(defvar file-notify-descriptors)
@@ -4923,6 +4970,12 @@ Return ATTR."
4923 (tramp-message vec 5 "Finding a suitable `trash' command") 4970 (tramp-message vec 5 "Finding a suitable `trash' command")
4924 (tramp-find-executable vec "trash" (tramp-get-remote-path vec)))) 4971 (tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
4925 4972
4973(defun tramp-get-remote-gvfs-monitor-dir (vec)
4974 (with-tramp-connection-property vec "gvfs-monitor-dir"
4975 (tramp-message vec 5 "Finding a suitable `gvfs-monitor-dir' command")
4976 (tramp-find-executable
4977 vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t)))
4978
4926(defun tramp-get-remote-inotifywait (vec) 4979(defun tramp-get-remote-inotifywait (vec)
4927 (with-tramp-connection-property vec "inotifywait" 4980 (with-tramp-connection-property vec "inotifywait"
4928 (tramp-message vec 5 "Finding a suitable `inotifywait' command") 4981 (tramp-message vec 5 "Finding a suitable `inotifywait' command")