* autorevert.el (auto-revert-use-notify): Use
authorMichael Albinus <michael.albinus@gmx.de>
Tue, 29 Jan 2013 16:03:40 +0000 (17:03 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Tue, 29 Jan 2013 16:03:40 +0000 (17:03 +0100)
`custom-initialize-default' for initialization.  (Bug#13583)

lisp/ChangeLog
lisp/autorevert.el
lisp/net/tramp-sh.el

index ba98225..807e44b 100644 (file)
@@ -1,5 +1,8 @@
 2013-01-29  Michael Albinus  <michael.albinus@gmx.de>
 
+       * autorevert.el (auto-revert-use-notify): Use
+       `custom-initialize-default' for initialization.  (Bug#13583)
+
        * net/ange-ftp.el (ange-ftp-skip-msgs): Add another message.
 
        * net/tramp-sh.el (tramp-sh-handle-start-file-process): Catch
index 9270b98..e44d4a8 100644 (file)
@@ -289,6 +289,7 @@ variable through Custom only."
               (with-current-buffer buf
                 (when (symbol-value 'auto-revert-notify-watch-descriptor)
                   (auto-revert-notify-rm-watch)))))))
+  :initialize 'custom-initialize-default
   :version "24.4")
 
 (defcustom auto-revert-notify-exclude-dir-regexp
index 63e966b..65a514c 100644 (file)
@@ -988,7 +988,8 @@ This is used to map a mode number to a permission string.")
     (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
     (file-acl . tramp-sh-handle-file-acl)
     (set-file-acl . tramp-sh-handle-set-file-acl)
-    (vc-registered . tramp-sh-handle-vc-registered))
+    (vc-registered . tramp-sh-handle-vc-registered)
+    (inotify-add-watch . tramp-sh-handle-inotify-add-watch))
   "Alist of handler functions.
 Operations not mentioned here will be handled by the normal Emacs functions.")
 
@@ -3487,6 +3488,64 @@ Fall back to normal file name handler if no Tramp handler exists."
         ;; Default file name handlers, we don't care.
         (t (tramp-run-real-handler operation args)))))))
 
+(defun tramp-sh-handle-inotify-add-watch (file-name aspect callback)
+  "Like `inotify-add-watch' for Tramp files."
+  (setq file-name (expand-file-name file-name))
+  (unless (consp aspect) (setq aspect (cons aspect nil)))
+  (with-parsed-tramp-file-name file-name nil
+    (let* ((default-directory (file-name-directory file-name))
+          (command (tramp-get-remote-inotifywait v))
+          (aspect (mapconcat
+                   (lambda (x)
+                     (replace-regexp-in-string "-" "_" (symbol-name x)))
+                   aspect ","))
+          (p (and command
+                  (start-file-process
+                   "inotifywait" nil command "-mq" "-e" aspect localname))))
+      (when (processp p)
+       (tramp-compat-set-process-query-on-exit-flag p nil)
+       (set-process-filter p 'tramp-sh-inotify-process-filter)
+       (tramp-set-connection-property p "inotify-callback" callback)
+       ;; Return the file-name vector as watch-descriptor.
+       (tramp-set-connection-property p "inotify-watch-descriptor" v)))))
+
+(defun tramp-sh-inotify-process-filter (proc string)
+  "Read output from \"inotifywait\" and add corresponding inotify events."
+  (tramp-message
+   (tramp-get-connection-property proc "vector" nil) 6
+   (format "%s\n%s" proc string))
+  (dolist (line (split-string string "[\n\r]+" 'omit-nulls))
+    ;; Check, whether there is a problem.
+    (unless
+       (string-match
+        "^[^[:blank:]]+[[:blank:]]+\\([^[:blank:]]+\\)+\\([[:blank:]]+\\([^[:blank:]]+\\)\\)?[[:blank:]]*$" line)
+      (tramp-error proc 'filewatch-error "%s" line))
+
+    (let* ((object
+           (list
+            (tramp-get-connection-property
+             proc "inotify-watch-descriptor" nil)
+            ;; Aspect symbols.  We filter out MOVE and CLOSE, which
+            ;; are convenience macros.  See INOTIFY(7).
+            (mapcar
+             (lambda (x)
+               (intern-soft (replace-regexp-in-string "_" "-" (downcase x))))
+             (delete "MOVE" (delete "CLOSE"
+               (split-string (match-string 1 line) "," 'omit-nulls))))
+            ;; We cannot gather any cookie value.  So we return 0 as
+            ;; "don't know".
+            0 (match-string 3 line)))
+          (callback
+           (tramp-get-connection-property proc "inotify-callback" nil))
+          (event `(file-inotify ,object ,callback)))
+
+      ;; 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.
+      ;(setq unread-command-events (cons event unread-command-events)))))
+      (let ((last-input-event event))
+       (funcall callback object)))))
+
 ;;; Internal Functions:
 
 (defun tramp-maybe-send-script (vec script name)
@@ -5046,6 +5105,11 @@ This is used internally by `tramp-file-mode-from-int'."
     (tramp-message vec 5 "Finding a suitable `trash' command")
     (tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
 
+(defun tramp-get-remote-inotifywait (vec)
+  (with-tramp-connection-property vec "inotifywait"
+    (tramp-message vec 5 "Finding a suitable `inotifywait' command")
+    (tramp-find-executable vec "inotifywait" (tramp-get-remote-path vec) t t)))
+
 (defun tramp-get-remote-id (vec)
   (with-tramp-connection-property vec "id"
     (tramp-message vec 5 "Finding POSIX `id' command")