mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-05 22:20:24 -08:00
Add file notification handler for Tramp's "smb" method.
* etc/NEWS: Mention new file notification handler for Tramp "smb". * lisp/filenotify.el (file-notify--expand-file-name): Fix the remote case. (file-notify-callback): Extend for "smb-notify". (file-notify--call-handler): Fix debug message. * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch): * lisp/net/tramp-sh.el (tramp-sh-gio-monitor-process-filter): Use connection property "file-monitor". * lisp/net/tramp-smb.el (tramp-smb-file-name-handler-alist): Use `tramp-smb-handle-file-notify-add-watch'. (tramp-smb-handle-delete-directory): Do not error if there is a pending deletion of a directory under file-watch. (tramp-smb-handle-file-notify-add-watch) (tramp-smb-notify-process-filter): New defuns. (tramp-smb-send-command): New optional argument NOOUTPUT. (tramp-smb-wait-for-output): Improve debug message. * lisp/net/tramp.el (tramp-directory-watched): New defun. (tramp-accept-process-output, tramp-wait-for-regexp): Improve debug message. * test/lisp/filenotify-tests.el (top): Filter also for "smb-notify". Set some other Tramp related variables. (file-notify--test-wait-for-events) (file-notify--test-with-actions-check) (file-notify--test-with-actions): Add debug message. (file-notify--test-cleanup, file-notify--deftest-remote): Keep Tramp debugs buffer. (file-notify--test-monitor): Check for "smb-notify". (file-notify--deftest-remote): Call `file-notify-rm-all-watches'. (file-notify--test-make-temp-name): Use a better name for parent directory. (file-notify--test-event-handler): Use `string-match-p'. (file-notify--test-with-actions): Check also for the `stopped' event as limit. (file-notify-test03-events, file-notify-test04-autorevert) (file-notify-test05-file-validity) (file-notify-test07-many-events, file-notify-test08-backup) (file-notify-test09-watched-file-in-watched-dir): Adapt tests for "smb-notify". (file-notify-test12-unmount): Skip for "smb-notify".
This commit is contained in:
parent
0a1db9b573
commit
aa8afabd49
7 changed files with 283 additions and 57 deletions
3
etc/NEWS
3
etc/NEWS
|
|
@ -1526,6 +1526,9 @@ can be used in parallel. Example: on both remote hosts "host1" and
|
|||
|
||||
This feature is experimental.
|
||||
|
||||
---
|
||||
*** Implementation of filesystem notifications for connection method "smb".
|
||||
|
||||
** Diff
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -123,7 +123,9 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
|
|||
(defun file-notify--expand-file-name (watch file)
|
||||
"Full file name of FILE reported for WATCH."
|
||||
(directory-file-name
|
||||
(expand-file-name file (file-notify--watch-directory watch))))
|
||||
(if (file-name-absolute-p file)
|
||||
(concat (file-remote-p (file-notify--watch-directory watch)) file)
|
||||
(expand-file-name file (file-notify--watch-directory watch)))))
|
||||
|
||||
(cl-defun file-notify--callback-inotify ((desc actions file
|
||||
&optional file1-or-cookie))
|
||||
|
|
@ -189,7 +191,7 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
|
|||
"Notification callback for file name handlers."
|
||||
(file-notify--handle-event
|
||||
desc
|
||||
;; File name handlers use gfilenotify or inotify actions.
|
||||
;; File name handlers use gfilenotify, inotify or w32notify actions.
|
||||
(delq nil (mapcar
|
||||
(lambda (action)
|
||||
(cond
|
||||
|
|
@ -205,7 +207,12 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
|
|||
((memq action '(delete delete-self move-self)) 'deleted)
|
||||
((eq action 'moved-from) 'renamed-from)
|
||||
((eq action 'moved-to) 'renamed-to)
|
||||
((memq action '(ignored unmount)) 'stopped)))
|
||||
((memq action '(ignored unmount)) 'stopped)
|
||||
;; w32notify actions:
|
||||
((eq action 'added) 'created)
|
||||
((eq action 'modified) 'changed)
|
||||
((eq action 'removed) 'deleted)
|
||||
((memq action '(renamed-from renamed-to)) action)))
|
||||
(if (consp actions) actions (list actions))))
|
||||
file file1-or-cookie))
|
||||
|
||||
|
|
@ -237,7 +244,7 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
|
|||
(when (file-notify--watch-callback watch)
|
||||
(when file-notify-debug
|
||||
(message
|
||||
"file-notify-callback %S %S %S %S %S %S %S"
|
||||
"file-notify--call-handler %S %S %S %S %S %S %S"
|
||||
desc action file file1 watch
|
||||
(file-notify--watch-absolute-filename watch)
|
||||
(file-notify--watch-directory watch)))
|
||||
|
|
|
|||
|
|
@ -1516,6 +1516,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
|||
(if (not (processp p))
|
||||
(tramp-error
|
||||
v 'file-notify-error "Monitoring not supported for `%s'" file-name)
|
||||
;; Needed for process filter.
|
||||
(process-put p 'tramp-events events)
|
||||
(process-put p 'tramp-watch-name localname)
|
||||
(set-process-filter p #'tramp-gvfs-monitor-process-filter)
|
||||
|
|
@ -1527,9 +1528,9 @@ If FILE-SYSTEM is non-nil, return file system attributes."
|
|||
(unless (process-live-p p)
|
||||
(tramp-error
|
||||
p 'file-notify-error "Monitoring not supported for `%s'" file-name))
|
||||
;; Set "gio-file-monitor" property. We believe, that "gio
|
||||
;; Set "file-monitor" property. We believe, that "gio
|
||||
;; monitor" uses polling when applied for mounted files.
|
||||
(tramp-set-connection-property p "gio-file-monitor" 'GPollFileMonitor)
|
||||
(tramp-set-connection-property p "file-monitor" 'GPollFileMonitor)
|
||||
p))))
|
||||
|
||||
(defun tramp-gvfs-monitor-process-filter (proc string)
|
||||
|
|
|
|||
|
|
@ -3885,9 +3885,9 @@ Fall back to normal file name handler if no Tramp handler exists."
|
|||
(throw 'doesnt-work nil))
|
||||
|
||||
;; Determine monitor name.
|
||||
(unless (tramp-connection-property-p proc "gio-file-monitor")
|
||||
(unless (tramp-connection-property-p proc "file-monitor")
|
||||
(tramp-set-connection-property
|
||||
proc "gio-file-monitor"
|
||||
proc "file-monitor"
|
||||
(cond
|
||||
;; We have seen this on cygwin gio and on emba. Let's make
|
||||
;; some assumptions.
|
||||
|
|
|
|||
|
|
@ -127,10 +127,10 @@ this variable \"client min protocol=NT1\"."
|
|||
"ERRnomem"
|
||||
"ERRnosuchshare"
|
||||
;; See /usr/include/samba-4.0/core/ntstatus.h.
|
||||
;; Windows 4.0 (Windows NT), Windows 5.0 (Windows 2000),
|
||||
;; Windows 5.1 (Windows XP), Windows 5.2 (Windows Server 2003),
|
||||
;; Windows 6.0 (Windows Vista), Windows 6.1 (Windows 7),
|
||||
;; Windows 6.3 (Windows Server 2012, Windows 10).
|
||||
;; <https://learn.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version>
|
||||
;; Tested with Windows NT, Windows 2000, Windows XP, Windows
|
||||
;; Server 2003, Windows Vista, Windows 7, Windows Server 2012,
|
||||
;; Windows 10, Windows 11.
|
||||
"NT_STATUS_ACCESS_DENIED"
|
||||
"NT_STATUS_ACCOUNT_LOCKED_OUT"
|
||||
"NT_STATUS_BAD_NETWORK_NAME"
|
||||
|
|
@ -261,7 +261,7 @@ See `tramp-actions-before-shell' for more info.")
|
|||
(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-add-watch . tramp-smb-handle-file-notify-add-watch)
|
||||
(file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
|
||||
(file-notify-valid-p . tramp-handle-file-notify-valid-p)
|
||||
(file-ownership-preserved-p . ignore)
|
||||
|
|
@ -686,8 +686,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(tramp-error v 'file-error "%s `%s'" (match-string 0) directory)))
|
||||
|
||||
;; "rmdir" does not report an error. So we check ourselves.
|
||||
(when (file-exists-p directory)
|
||||
(tramp-error v 'file-error "`%s' not removed" directory)))))
|
||||
;; Deletion of a watched directory could be pending.
|
||||
(when (and (not (tramp-directory-watched directory))
|
||||
(file-exists-p directory))
|
||||
(tramp-error v 'file-error "`%s' not removed" directory)))))
|
||||
|
||||
(defun tramp-smb-handle-delete-file (filename &optional trash)
|
||||
"Like `delete-file' for Tramp files."
|
||||
|
|
@ -964,6 +966,108 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
|
|||
(tramp-error
|
||||
v 'file-error "Cannot make local copy of file `%s'" filename)))))
|
||||
|
||||
;; The "notify" command has been added to smbclient 4.3.0.
|
||||
(defun tramp-smb-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 ((default-directory (file-name-directory file-name))
|
||||
(command (format "notify %s" (tramp-smb-shell-quote-localname v)))
|
||||
(events
|
||||
(cond
|
||||
((memq 'change flags)
|
||||
'(added removed modified renamed-from renamed-to))
|
||||
((memq 'attribute-change flags) '(modified))))
|
||||
p)
|
||||
;; Start process.
|
||||
(with-tramp-saved-connection-properties
|
||||
v '(" process-name" " process-buffer")
|
||||
;; Set the new process properties.
|
||||
(tramp-set-connection-property
|
||||
v " process-name" (tramp-get-unique-process-name "smb-notify"))
|
||||
(tramp-set-connection-property
|
||||
v " process-buffer" (generate-new-buffer " *smb-notify*"))
|
||||
(tramp-flush-connection-property v " process-exit-status")
|
||||
(tramp-smb-send-command v command 'nooutput)
|
||||
(setq p (tramp-get-connection-process v))
|
||||
;; Return the process object as watch-descriptor.
|
||||
(if (not (processp p))
|
||||
(tramp-error
|
||||
v 'file-notify-error
|
||||
"`%s' failed to start on remote host" command)
|
||||
;; Needed for process filter.
|
||||
(process-put p 'tramp-events events)
|
||||
(process-put p 'tramp-watch-name localname)
|
||||
(set-process-filter p #'tramp-smb-notify-process-filter)
|
||||
(set-process-sentinel p #'tramp-file-notify-process-sentinel)
|
||||
(tramp-post-process-creation p v)
|
||||
;; There might be an error if the monitor is not supported.
|
||||
;; Give the filter a chance to read the output.
|
||||
(while (tramp-accept-process-output p))
|
||||
(unless (process-live-p p)
|
||||
(tramp-error
|
||||
p 'file-notify-error "Monitoring not supported for `%s'" file-name))
|
||||
;; Set "file-monitor" property. The existence of the "ADMIN$"
|
||||
;; share is an indication for a remote MS Windows host.
|
||||
(tramp-set-connection-property
|
||||
p "file-monitor"
|
||||
(if (member
|
||||
"ADMIN$" (directory-files (tramp-make-tramp-file-name v "/")))
|
||||
'SMBWindows 'SMBSamba))
|
||||
p)))))
|
||||
|
||||
;; FileChangeNotify subsystem was added to Smaba 4.3.0.
|
||||
;; <https://www.samba.org/samba/history/samba-4.3.0.html>
|
||||
(defun tramp-smb-notify-process-filter (proc string)
|
||||
"Read output from \"notify\" and add corresponding `file-notify' events."
|
||||
(let ((events (process-get proc 'tramp-events)))
|
||||
(tramp-message proc 6 "%S\n%s" proc string)
|
||||
(dolist (line (split-string string (rx (+ (any "\r\n"))) 'omit))
|
||||
(catch 'next
|
||||
;; Watched directory is removed.
|
||||
(when (string-match-p "NT_STATUS_DELETE_PENDING" line)
|
||||
(setq line (concat "0002 " (process-get proc 'tramp-watch-name))))
|
||||
;; Stopped.
|
||||
(when (string-match-p tramp-smb-prompt line)
|
||||
(throw 'next 'next))
|
||||
|
||||
;; Check, whether there is a problem.
|
||||
(unless (string-match
|
||||
(rx bol (group (+ digit))
|
||||
(+ blank) (group (+ (not (any "\r\n")))))
|
||||
line)
|
||||
(tramp-error proc 'file-notify-error line))
|
||||
|
||||
;; See libsmbclient.h.
|
||||
;; #define SMBC_NOTIFY_ACTION_ADDED 1
|
||||
;; #define SMBC_NOTIFY_ACTION_REMOVED 2
|
||||
;; #define SMBC_NOTIFY_ACTION_MODIFIED 3
|
||||
;; #define SMBC_NOTIFY_ACTION_OLD_NAME 4
|
||||
;; #define SMBC_NOTIFY_ACTION_NEW_NAME 5
|
||||
;; #define SMBC_NOTIFY_ACTION_ADDED_STREAM 6
|
||||
;; #define SMBC_NOTIFY_ACTION_REMOVED_STREAM 7
|
||||
;; #define SMBC_NOTIFY_ACTION_MODIFIED_STREAM 8
|
||||
(let ((object
|
||||
(list
|
||||
proc
|
||||
(pcase (string-to-number (match-string 1 line))
|
||||
(1 '(added))
|
||||
(2 '(removed))
|
||||
(3 '(modified))
|
||||
(4 '(renamed-from))
|
||||
(5 '(renamed-to))
|
||||
;; Ignore stream events.
|
||||
(_ (throw 'next 'next)))
|
||||
(string-replace "\\" "/" (match-string 2 line)))))
|
||||
;; Add an Emacs event now.
|
||||
;; `insert-special-event' exists since Emacs 31.
|
||||
(when (member (caadr object) events)
|
||||
(tramp-compat-funcall
|
||||
(if (fboundp 'insert-special-event)
|
||||
'insert-special-event
|
||||
(lookup-key special-event-map [file-notify]))
|
||||
`(file-notify ,object file-notify-callback))))))))
|
||||
|
||||
;; This function should return "foo/" for directories and "bar" for
|
||||
;; files.
|
||||
(defun tramp-smb-handle-file-name-all-completions (filename directory)
|
||||
|
|
@ -1823,13 +1927,14 @@ are listed. Result is the list (LOCALNAME MODE SIZE MTIME)."
|
|||
|
||||
;; Connection functions.
|
||||
|
||||
(defun tramp-smb-send-command (vec command)
|
||||
(defun tramp-smb-send-command (vec command &optional nooutput)
|
||||
"Send the COMMAND to connection VEC.
|
||||
Returns nil if there has been an error message from smbclient."
|
||||
Returns nil if there has been an error message from smbclient. The
|
||||
function waits for output unless NOOUTPUT is set."
|
||||
(tramp-smb-maybe-open-connection vec)
|
||||
(tramp-message vec 6 "%s" command)
|
||||
(tramp-send-string vec command)
|
||||
(tramp-smb-wait-for-output vec))
|
||||
(unless nooutput (tramp-smb-wait-for-output vec)))
|
||||
|
||||
(defun tramp-smb-maybe-open-connection (vec &optional argument)
|
||||
"Maybe open a connection to HOST, log in as USER, using `tramp-smb-program'.
|
||||
|
|
@ -2003,7 +2108,7 @@ Removes smb prompt. Returns nil if an error message has appeared."
|
|||
(while (not (search-forward-regexp tramp-smb-prompt nil t))
|
||||
(while (tramp-accept-process-output p))
|
||||
(goto-char (point-min)))
|
||||
(tramp-message vec 6 "\n%s" (buffer-string))
|
||||
(tramp-message vec 6 "%S\n%s" p (buffer-string))
|
||||
|
||||
;; Remove prompt.
|
||||
(goto-char (point-min))
|
||||
|
|
@ -2084,4 +2189,6 @@ Removes smb prompt. Returns nil if an error message has appeared."
|
|||
;;
|
||||
;; * Keep a permanent connection process for `process-file'.
|
||||
|
||||
;; * Implement "scopy" (since Samba 4.3.0).
|
||||
|
||||
;;; tramp-smb.el ends here
|
||||
|
|
|
|||
|
|
@ -5743,6 +5743,16 @@ of."
|
|||
(tramp-message proc 5 "Sentinel called: `%S' `%s'" proc event)
|
||||
(file-notify-rm-watch proc)))
|
||||
|
||||
(defun tramp-directory-watched (directory)
|
||||
"Check, whether a directory is watched."
|
||||
(let (result)
|
||||
(dolist (p (process-list) result)
|
||||
(setq result
|
||||
(or result
|
||||
(and-let* ((dir (process-get p 'tramp-watch-name))
|
||||
((string-equal
|
||||
dir (tramp-file-local-name directory))))))))))
|
||||
|
||||
;;; Functions for establishing connection:
|
||||
|
||||
;; The following functions are actions to be taken when seeing certain
|
||||
|
|
@ -6120,7 +6130,7 @@ If the user quits via `C-g', it is propagated up to `tramp-file-name-handler'."
|
|||
(if (with-local-quit
|
||||
(setq result (accept-process-output proc 0 nil t)) t)
|
||||
(tramp-message
|
||||
proc 10 "%s %s %s\n%s"
|
||||
proc 10 "%S %S %s\n%s"
|
||||
proc (process-status proc) result (buffer-string))
|
||||
;; Propagate quit.
|
||||
(keyboard-quit)))
|
||||
|
|
@ -6197,7 +6207,7 @@ nil."
|
|||
;; timeout of sudo. The process buffer does not exist any longer then.
|
||||
(ignore-errors
|
||||
(tramp-message
|
||||
proc 6 "\n%s" (tramp-get-buffer-string (process-buffer proc))))
|
||||
proc 6 "%S\n%s" proc (tramp-get-buffer-string (process-buffer proc))))
|
||||
(unless found
|
||||
(if timeout
|
||||
(tramp-error
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
;; of a respective command. The first command found is used. In
|
||||
;; order to use a dedicated one, the environment variable
|
||||
;; $REMOTE_FILE_NOTIFY_LIBRARY shall be set, possible values are
|
||||
;; "inotifywait", "gio-monitor" and "gvfs-monitor-dir".
|
||||
;; "inotifywait", "gio-monitor", "gvfs-monitor-dir", and "smb-notify".
|
||||
|
||||
;; Local file-notify libraries are auto-detected during Emacs
|
||||
;; configuration. This can be changed with a respective configuration
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
;; Filter suppressed remote file-notify libraries.
|
||||
(when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY"))
|
||||
(dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir"))
|
||||
(dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir" "smb-notify"))
|
||||
(unless (string-equal (getenv "REMOTE_FILE_NOTIFY_LIBRARY") lib)
|
||||
(add-to-list 'tramp-connection-properties `(nil ,lib nil)))))
|
||||
|
||||
|
|
@ -104,6 +104,9 @@ There are different timeouts for local and remote file notification libraries."
|
|||
TIMEOUT is the maximum time to wait for, in seconds."
|
||||
`(with-timeout (,timeout (ignore))
|
||||
(while (null ,until)
|
||||
(when file-notify-debug
|
||||
(message "file-notify--test-wait-for-events received: %s"
|
||||
(file-notify--test-event-actions)))
|
||||
(file-notify--test-wait-event))))
|
||||
|
||||
(defun file-notify--test-no-descriptors ()
|
||||
|
|
@ -159,7 +162,7 @@ Return nil when any other file notification watch is still active."
|
|||
(ignore-errors
|
||||
(when (file-remote-p temporary-file-directory)
|
||||
(tramp-cleanup-connection
|
||||
(tramp-dissect-file-name temporary-file-directory) nil 'keep-password)))
|
||||
(tramp-dissect-file-name temporary-file-directory) t 'keep-password)))
|
||||
|
||||
(when (hash-table-p file-notify-descriptors)
|
||||
(clrhash file-notify-descriptors))
|
||||
|
|
@ -176,9 +179,13 @@ Return nil when any other file notification watch is still active."
|
|||
file-notify--test-events nil
|
||||
file-notify--test-monitors nil))
|
||||
|
||||
(setq file-notify-debug nil
|
||||
(setq auth-source-cache-expiry nil
|
||||
auth-source-save-behavior nil
|
||||
file-notify-debug nil
|
||||
password-cache-expiry nil
|
||||
;; tramp-verbose (if (getenv "EMACS_EMBA_CI") 10 0)
|
||||
remote-file-name-inhibit-cache nil
|
||||
tramp-allow-unsafe-temporary-files t
|
||||
tramp-cache-read-persistent-data t ;; For auth-sources.
|
||||
tramp-verbose 0
|
||||
;; When the remote user id is 0, Tramp refuses unsafe temporary files.
|
||||
tramp-allow-unsafe-temporary-files
|
||||
|
|
@ -241,13 +248,17 @@ watch descriptor."
|
|||
;; We cache the result, because after `file-notify-rm-watch',
|
||||
;; `gfile-monitor-name' does not return a proper result anymore.
|
||||
;; But we still need this information. So far, we know the monitors
|
||||
;; GFamFileMonitor (gfilenotify on cygwin), GFamDirectoryMonitor
|
||||
;; (gfilenotify on Solaris), GInotifyFileMonitor (gfilenotify and
|
||||
;; gio on GNU/Linux), GKqueueFileMonitor (gfilenotify and gio on
|
||||
;; FreeBSD) and GPollFileMonitor (gio on cygwin).
|
||||
;; - GFamFileMonitor (gfilenotify on cygwin)
|
||||
;; - GFamDirectoryMonitor (gfilenotify on Solaris)
|
||||
;; - GInotifyFileMonitor (gfilenotify and gio on GNU/Linux)
|
||||
;; - GKqueueFileMonitor (gfilenotify and gio on FreeBSD)
|
||||
;; - GPollFileMonitor (gio on cygwin)
|
||||
;; - SMBSamba (smb-notify on Samba server)
|
||||
;; - SMBWindows (smb-notify on MS Windows).
|
||||
(when file-notify--test-desc
|
||||
(or (alist-get file-notify--test-desc file-notify--test-monitors)
|
||||
(when (member (file-notify--test-library) '("gfilenotify" "gio"))
|
||||
(when (member
|
||||
(file-notify--test-library) '("gfilenotify" "gio" "smb-notify"))
|
||||
(add-to-list
|
||||
'file-notify--test-monitors
|
||||
(cons file-notify--test-desc
|
||||
|
|
@ -255,10 +266,10 @@ watch descriptor."
|
|||
;; `file-notify--test-desc' is the connection process.
|
||||
(progn
|
||||
(while (not (tramp-connection-property-p
|
||||
file-notify--test-desc "gio-file-monitor"))
|
||||
file-notify--test-desc "file-monitor"))
|
||||
(accept-process-output file-notify--test-desc 0))
|
||||
(tramp-get-connection-property
|
||||
file-notify--test-desc "gio-file-monitor" nil))
|
||||
file-notify--test-desc "file-monitor" nil))
|
||||
(and (functionp 'gfile-monitor-name)
|
||||
(gfile-monitor-name file-notify--test-desc)))))
|
||||
;; If we don't know the monitor, there are good chances the
|
||||
|
|
@ -282,7 +293,8 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
|
|||
;; Needs further investigation.
|
||||
(skip-when (string-equal (file-notify--test-library) "gio"))
|
||||
(tramp-cleanup-connection
|
||||
(tramp-dissect-file-name temporary-file-directory) nil 'keep-password)
|
||||
(tramp-dissect-file-name temporary-file-directory) t 'keep-password)
|
||||
(file-notify-rm-all-watches)
|
||||
(funcall (ert-test-body ert-test)))))
|
||||
|
||||
(ert-deftest file-notify-test00-availability ()
|
||||
|
|
@ -315,7 +327,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
|
|||
(unless (stringp file-notify--test-tmpdir)
|
||||
(setq file-notify--test-tmpdir
|
||||
(expand-file-name
|
||||
(make-temp-name "file-notify-test") temporary-file-directory)))
|
||||
(make-temp-name "file-notify-test-parent") temporary-file-directory)))
|
||||
(unless (file-directory-p file-notify--test-tmpdir)
|
||||
(make-directory file-notify--test-tmpdir))
|
||||
(expand-file-name
|
||||
|
|
@ -558,7 +570,7 @@ and the event to `file-notify--test-events'."
|
|||
(result
|
||||
(ert-run-test (make-ert-test :body 'file-notify--test-event-test))))
|
||||
;; Do not add lock files, this would confuse the checks.
|
||||
(unless (string-match
|
||||
(unless (string-match-p
|
||||
(regexp-quote ".#")
|
||||
(file-notify--test-event-file file-notify--test-event))
|
||||
(when file-notify-debug
|
||||
|
|
@ -575,6 +587,8 @@ and the event to `file-notify--test-events'."
|
|||
|
||||
(defun file-notify--test-with-actions-check (actions)
|
||||
"Check whether received actions match one of the ACTIONS alternatives."
|
||||
(when file-notify-debug
|
||||
(message "file-notify--test-with-actions-check"))
|
||||
(let (result)
|
||||
(dolist (elt actions result)
|
||||
(setq result
|
||||
|
|
@ -632,11 +646,14 @@ delivered."
|
|||
(not (input-pending-p)))
|
||||
(setq file-notify--test-events nil
|
||||
file-notify--test-results nil)
|
||||
(when file-notify-debug
|
||||
(message "file-notify--test-with-actions expected: %s" actions))
|
||||
,@body
|
||||
(file-notify--test-wait-for-events
|
||||
;; More actions need more time. Use some fudge factor.
|
||||
(* (ceiling max-length 100) (file-notify--test-timeout))
|
||||
(= max-length (length file-notify--test-events)))
|
||||
(or (= max-length (length file-notify--test-events))
|
||||
(memq 'stopped (file-notify--test-event-actions))))
|
||||
;; Check the result sequence just to make sure that all actions
|
||||
;; are as expected.
|
||||
(dolist (result file-notify--test-results)
|
||||
|
|
@ -666,6 +683,9 @@ delivered."
|
|||
'(change) #'file-notify--test-event-handler)))
|
||||
(file-notify--test-with-actions
|
||||
(cond
|
||||
;; SMBSamba reports three `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(created changed changed changed deleted stopped))
|
||||
;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
|
||||
;; GPollFileMonitor do not report the `changed' event.
|
||||
((memq (file-notify--test-monitor)
|
||||
|
|
@ -697,6 +717,9 @@ delivered."
|
|||
'(change) #'file-notify--test-event-handler)))
|
||||
(file-notify--test-with-actions
|
||||
(cond
|
||||
;; SMBSamba reports four `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(changed changed changed changed deleted stopped))
|
||||
;; GFam{File,Directory}Monitor and GPollFileMonitor do
|
||||
;; not detect the `changed' event reliably.
|
||||
((memq (file-notify--test-monitor)
|
||||
|
|
@ -739,6 +762,9 @@ delivered."
|
|||
;; events for the watched directory.
|
||||
((string-equal (file-notify--test-library) "w32notify")
|
||||
'(created changed deleted))
|
||||
;; SMBSamba reports three `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(created changed changed changed deleted deleted stopped))
|
||||
;; On emba, `deleted' and `stopped' events of the
|
||||
;; directory are not detected.
|
||||
((getenv "EMACS_EMBA_CI")
|
||||
|
|
@ -789,6 +815,10 @@ delivered."
|
|||
'(created changed created changed
|
||||
changed changed changed
|
||||
deleted deleted))
|
||||
;; SMBSamba reports three `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(created changed changed changed created changed changed changed
|
||||
deleted deleted deleted stopped))
|
||||
;; There are three `deleted' events, for two files and
|
||||
;; for the directory. Except for
|
||||
;; GFam{File,Directory}Monitor, GPollFileMonitor and
|
||||
|
|
@ -843,6 +873,10 @@ delivered."
|
|||
;; events for the watched directory.
|
||||
((string-equal (file-notify--test-library) "w32notify")
|
||||
'(created changed renamed deleted))
|
||||
;; SMBSamba reports three `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(created changed changed changed
|
||||
renamed changed changed deleted deleted stopped))
|
||||
;; On emba, `deleted' and `stopped' events of the
|
||||
;; directory are not detected.
|
||||
((getenv "EMACS_EMBA_CI")
|
||||
|
|
@ -897,6 +931,14 @@ delivered."
|
|||
((string-equal (file-notify--test-library) "w32notify")
|
||||
'((changed changed)
|
||||
(changed changed changed changed)))
|
||||
;; SMBWindows does not distinguish between `changed' and
|
||||
;; `attribute-changed'.
|
||||
((eq (file-notify--test-monitor) 'SMBWindows)
|
||||
'(changed changed))
|
||||
;; SMBSamba does not distinguish between `changed' and
|
||||
;; `attribute-changed'.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(changed changed changed changed))
|
||||
;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
|
||||
;; GPollFileMonitor do not report the `attribute-changed'
|
||||
;; event.
|
||||
|
|
@ -948,6 +990,7 @@ delivered."
|
|||
(timeout (if (file-remote-p temporary-file-directory)
|
||||
60 ; FIXME: can this be shortened?
|
||||
(* auto-revert-interval 2.5)))
|
||||
(text-quoting-style 'grave)
|
||||
buf)
|
||||
(auto-revert-set-timer)
|
||||
(unwind-protect
|
||||
|
|
@ -995,10 +1038,11 @@ delivered."
|
|||
;; Check, that the buffer has been reverted.
|
||||
(file-notify--test-wait-for-events
|
||||
timeout
|
||||
(string-match
|
||||
(format-message "Reverting buffer `%s'." (buffer-name buf))
|
||||
(string-match-p
|
||||
(rx bol "Reverting buffer `"
|
||||
(literal (buffer-name buf)) "'" eol)
|
||||
captured-messages))
|
||||
(should (string-match "another text" (buffer-string)))))
|
||||
(should (string-match-p "another text" (buffer-string)))))
|
||||
|
||||
;; Stop file notification. Autorevert shall still work via polling.
|
||||
(file-notify-rm-watch auto-revert-notify-watch-descriptor)
|
||||
|
|
@ -1020,10 +1064,11 @@ delivered."
|
|||
;; Check, that the buffer has been reverted.
|
||||
(file-notify--test-wait-for-events
|
||||
timeout
|
||||
(string-match
|
||||
(format-message "Reverting buffer `%s'." (buffer-name buf))
|
||||
(string-match-p
|
||||
(rx bol "Reverting buffer `"
|
||||
(literal (buffer-name buf)) "'" eol)
|
||||
captured-messages))
|
||||
(should (string-match "foo bla" (buffer-string)))))
|
||||
(should (string-match-p "foo bla" (buffer-string)))))
|
||||
|
||||
;; Stop autorevert, in order to cleanup descriptor.
|
||||
(auto-revert-mode -1))
|
||||
|
|
@ -1077,6 +1122,9 @@ delivered."
|
|||
(should (file-notify-valid-p file-notify--test-desc))
|
||||
(file-notify--test-with-actions
|
||||
(cond
|
||||
;; SMBSamba reports three `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(changed changed changed changed deleted stopped))
|
||||
;; GFam{File,Directory}Monitor do not
|
||||
;; detect the `changed' event reliably.
|
||||
((memq (file-notify--test-monitor)
|
||||
|
|
@ -1093,6 +1141,7 @@ delivered."
|
|||
"another text" nil file-notify--test-tmpfile nil 'no-message)
|
||||
(file-notify--test-wait-event)
|
||||
(delete-file file-notify--test-tmpfile))
|
||||
(file-notify--test-wait-event)
|
||||
;; After deleting the file, the descriptor is not valid anymore.
|
||||
(should-not (file-notify-valid-p file-notify--test-desc))
|
||||
(file-notify-rm-watch file-notify--test-desc)
|
||||
|
|
@ -1122,6 +1171,9 @@ delivered."
|
|||
;; events for the watched directory.
|
||||
((string-equal (file-notify--test-library) "w32notify")
|
||||
'(created changed deleted))
|
||||
;; SMBSamba reports three `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(created changed changed changed deleted deleted stopped))
|
||||
;; There are two `deleted' events, for the file and for
|
||||
;; the directory. Except for
|
||||
;; GFam{File,Directory}Monitor, GPollFileMonitor and
|
||||
|
|
@ -1247,7 +1299,14 @@ delivered."
|
|||
(push (expand-file-name (format "y%d" i)) target-file-list))
|
||||
(push (expand-file-name (format "y%d" i)) source-file-list)
|
||||
(push (expand-file-name (format "x%d" i)) target-file-list)))
|
||||
(file-notify--test-with-actions (make-list (+ n n) 'created)
|
||||
(file-notify--test-with-actions
|
||||
(cond
|
||||
;; SMBSamba fires both `created' and `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
(let (r)
|
||||
(dotimes (_i (+ n n) r)
|
||||
(setq r (append '(created changed) r)))))
|
||||
(t (make-list (+ n n) 'created)))
|
||||
(let ((source-file-list source-file-list)
|
||||
(target-file-list target-file-list))
|
||||
(while (and source-file-list target-file-list)
|
||||
|
|
@ -1260,18 +1319,26 @@ delivered."
|
|||
;; w32notify fires both `deleted' and `renamed' events.
|
||||
((string-equal (file-notify--test-library) "w32notify")
|
||||
(let (r)
|
||||
(dotimes (_i n)
|
||||
(setq r (append '(deleted renamed) r)))
|
||||
r))
|
||||
;; GFam{File,Directory}Monitor and GPollFileMonitor fire
|
||||
(dotimes (_i n r)
|
||||
(setq r (append '(deleted renamed) r)))))
|
||||
;; SMBWindows fires both `changed' and `deleted' events.
|
||||
((eq (file-notify--test-monitor) 'SMBWindows)
|
||||
(let (r)
|
||||
(dotimes (_i n r)
|
||||
(setq r (append '(changed deleted) r)))))
|
||||
;; SMBSamba fires both `changed' and `deleted' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
(let (r)
|
||||
(dotimes (_i n r)
|
||||
(setq r (append '(changed changed deleted) r)))))
|
||||
;; GFam{File,Directory}Monitor and GPollFileMonitor fire
|
||||
;; `changed' and `deleted' events, sometimes in random
|
||||
;; order.
|
||||
((memq (file-notify--test-monitor)
|
||||
'(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
|
||||
(let (r)
|
||||
(dotimes (_i n)
|
||||
(setq r (append '(changed deleted) r)))
|
||||
(cons :random r)))
|
||||
(dotimes (_i n (cons :random r))
|
||||
(setq r (append '(changed deleted) r)))))
|
||||
(t (make-list n 'renamed)))
|
||||
(let ((source-file-list source-file-list)
|
||||
(target-file-list target-file-list))
|
||||
|
|
@ -1315,6 +1382,9 @@ delivered."
|
|||
(should (file-notify-valid-p file-notify--test-desc))
|
||||
(file-notify--test-with-actions
|
||||
(cond
|
||||
;; SMBSamba reports four `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(changed changed changed changed))
|
||||
;; GKqueueFileMonitor does not report the `changed' event.
|
||||
((eq (file-notify--test-monitor) 'GKqueueFileMonitor) '())
|
||||
;; There could be one or two `changed' events.
|
||||
|
|
@ -1354,6 +1424,12 @@ delivered."
|
|||
(should (file-notify-valid-p file-notify--test-desc))
|
||||
(file-notify--test-with-actions
|
||||
(cond
|
||||
;; SMBWindows reports two `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBWindows)
|
||||
'(changed changed))
|
||||
;; SMBSamba reports four `changed' events.
|
||||
((eq (file-notify--test-monitor) 'SMBSamba)
|
||||
'(changed changed changed changed))
|
||||
;; GFam{File,Directory}Monitor and GPollFileMonitor
|
||||
;; report only the `changed' event.
|
||||
((memq (file-notify--test-monitor)
|
||||
|
|
@ -1438,7 +1514,27 @@ the file watch."
|
|||
(file-notify--test-with-actions
|
||||
;; There could be one or two `changed' events.
|
||||
(list
|
||||
;; cygwin.
|
||||
;; SMBSamba. Sometimes, tha last `changed' event is
|
||||
;; missing, so we add two alternatives.
|
||||
(append
|
||||
'(:random)
|
||||
;; Just the file monitor.
|
||||
(make-list (* (/ n 2) 5) 'changed)
|
||||
;; Just the directory monitor. Strange, not all
|
||||
;; `changed' events do arrive.
|
||||
(make-list (1- (* (/ n 2) 10)) 'changed)
|
||||
(make-list (/ n 2) 'created)
|
||||
(make-list (/ n 2) 'created))
|
||||
(append
|
||||
'(:random)
|
||||
;; Just the file monitor.
|
||||
(make-list (* (/ n 2) 5) 'changed)
|
||||
;; Just the directory monitor. This is the alternative
|
||||
;; with all `changed' events.
|
||||
(make-list (* (/ n 2) 10) 'changed)
|
||||
(make-list (/ n 2) 'created)
|
||||
(make-list (/ n 2) 'created))
|
||||
;; cygwin.
|
||||
(append
|
||||
'(:random)
|
||||
(make-list (/ n 2) 'changed)
|
||||
|
|
@ -1482,7 +1578,9 @@ the file watch."
|
|||
;; directory and the file monitor. The `stopped' event is
|
||||
;; from the file monitor. It's undecided in which order the
|
||||
;; directory and the file monitor are triggered.
|
||||
(file-notify--test-with-actions '(:random deleted deleted stopped)
|
||||
(file-notify--test-with-actions
|
||||
'((:random deleted deleted stopped)
|
||||
(:random deleted deleted deleted stopped))
|
||||
(delete-file file-notify--test-tmpfile1))
|
||||
(should (file-notify-valid-p file-notify--test-desc1))
|
||||
(should-not (file-notify-valid-p file-notify--test-desc2))
|
||||
|
|
@ -1715,8 +1813,8 @@ the file watch."
|
|||
"Check that file notification stop after unmounting the filesystem."
|
||||
:tags '(:expensive-test)
|
||||
(skip-unless (file-notify--test-local-enabled))
|
||||
;; This test does not work for w32notify.
|
||||
(skip-when (string-equal (file-notify--test-library) "w32notify"))
|
||||
;; This test does not work for w32notify snd smb-notify.
|
||||
(skip-when (member (file-notify--test-library) '("w32notify" "smb-notify")))
|
||||
|
||||
(unwind-protect
|
||||
(progn
|
||||
|
|
@ -1789,8 +1887,8 @@ the file watch."
|
|||
;; the missing directory monitor.
|
||||
;; * For w32notify, no `deleted' and `stopped' events arrive when a
|
||||
;; directory is removed.
|
||||
;; * For cygwin and w32notify, no `attribute-changed' events arrive.
|
||||
;; They send `changed' events instead.
|
||||
;; * For cygwin, w32notify, and smb-notify, no `attribute-changed'
|
||||
;; events arrive. They send `changed' events instead.
|
||||
;; * cygwin does not send all expected `changed' and `deleted' events.
|
||||
;; Probably due to timing issues.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue