diff options
| author | Michael Albinus | 2015-11-20 18:06:42 +0000 |
|---|---|---|
| committer | Michael Albinus | 2015-11-25 15:07:12 +0100 |
| commit | 0247489fed0f70b2abf960de48bc4432381a581b (patch) | |
| tree | 28e4de085d082377dfee71b800fff0b644cea3e1 | |
| parent | 5154781141c2305c24103beb358453d30a838921 (diff) | |
| download | emacs-0247489fed0f70b2abf960de48bc4432381a581b.tar.gz emacs-0247489fed0f70b2abf960de48bc4432381a581b.zip | |
Rework file notifications, kqueue has problems with directory monitors
* lisp/filenotify.el (file-notify-add-watch): Call the native
add-watch function on the file, not on the dir.
* src/kqueue.c (kqueue_compare_dir_list): Make also bookkeeping
about already deleted entries.
* test/automated/auto-revert-tests.el
(auto-revert-test01-auto-revert-several-files): Do not call "cp -f"
since this deletes the target file first.
* test/automated/file-notify-tests.el (file-notify--test-event-test):
Make stronger checks.
(file-notify-test01-add-watch, file-notify-test02-events)
(file-notify-test04-file-validity, file-notify-test05-dir-validity):
Rewrite in order to call file monitors but directory monitors.
(file-notify-test06-many-events): Ler rename work in both directions.
| -rw-r--r-- | lisp/filenotify.el | 6 | ||||
| -rw-r--r-- | src/kqueue.c | 48 | ||||
| -rw-r--r-- | test/automated/auto-revert-tests.el | 2 | ||||
| -rw-r--r-- | test/automated/file-notify-tests.el | 295 |
4 files changed, 203 insertions, 148 deletions
diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 5072bf414bf..0d7a2b914c6 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el | |||
| @@ -236,7 +236,7 @@ EVENT is the cadr of the event in `file-notify-handle-event' | |||
| 236 | (setq pending-event nil)) | 236 | (setq pending-event nil)) |
| 237 | 237 | ||
| 238 | ;; Check for stopped. | 238 | ;; Check for stopped. |
| 239 | ;;(message "file-notify-callback %S %S" file registered) | 239 | ;;(message "file-notify-callback %S %S %S" file file1 registered) |
| 240 | (setq | 240 | (setq |
| 241 | stopped | 241 | stopped |
| 242 | (or | 242 | (or |
| @@ -342,7 +342,7 @@ FILE is the name of the file whose event is being reported." | |||
| 342 | ;; A file name handler could exist even if there is no local | 342 | ;; A file name handler could exist even if there is no local |
| 343 | ;; file notification support. | 343 | ;; file notification support. |
| 344 | (setq desc (funcall | 344 | (setq desc (funcall |
| 345 | handler 'file-notify-add-watch dir flags callback)) | 345 | handler 'file-notify-add-watch file flags callback)) |
| 346 | 346 | ||
| 347 | ;; Check, whether Emacs has been compiled with file notification | 347 | ;; Check, whether Emacs has been compiled with file notification |
| 348 | ;; support. | 348 | ;; support. |
| @@ -379,7 +379,7 @@ FILE is the name of the file whose event is being reported." | |||
| 379 | l-flags))) | 379 | l-flags))) |
| 380 | 380 | ||
| 381 | ;; Call low-level function. | 381 | ;; Call low-level function. |
| 382 | (setq desc (funcall func dir l-flags 'file-notify-callback))) | 382 | (setq desc (funcall func file l-flags 'file-notify-callback))) |
| 383 | 383 | ||
| 384 | ;; Modify `file-notify-descriptors'. | 384 | ;; Modify `file-notify-descriptors'. |
| 385 | (setq file (unless (file-directory-p file) (file-name-nondirectory file)) | 385 | (setq file (unless (file-directory-p file) (file-name-nondirectory file)) |
diff --git a/src/kqueue.c b/src/kqueue.c index ca0e3e7e1ca..1830040637e 100644 --- a/src/kqueue.c +++ b/src/kqueue.c | |||
| @@ -111,11 +111,12 @@ static void | |||
| 111 | kqueue_compare_dir_list | 111 | kqueue_compare_dir_list |
| 112 | (Lisp_Object watch_object) | 112 | (Lisp_Object watch_object) |
| 113 | { | 113 | { |
| 114 | Lisp_Object dir, pending_events; | 114 | Lisp_Object dir, pending_dl, deleted_dl; |
| 115 | Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl; | 115 | Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl; |
| 116 | 116 | ||
| 117 | dir = XCAR (XCDR (watch_object)); | 117 | dir = XCAR (XCDR (watch_object)); |
| 118 | pending_events = Qnil; | 118 | pending_dl = Qnil; |
| 119 | deleted_dl = Qnil; | ||
| 119 | 120 | ||
| 120 | old_directory_files = Fnth (make_number (4), watch_object); | 121 | old_directory_files = Fnth (make_number (4), watch_object); |
| 121 | old_dl = kqueue_directory_listing (old_directory_files); | 122 | old_dl = kqueue_directory_listing (old_directory_files); |
| @@ -168,6 +169,7 @@ kqueue_compare_dir_list | |||
| 168 | kqueue_generate_event | 169 | kqueue_generate_event |
| 169 | (watch_object, Fcons (Qrename, Qnil), | 170 | (watch_object, Fcons (Qrename, Qnil), |
| 170 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); | 171 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); |
| 172 | deleted_dl = Fcons (new_entry, deleted_dl); | ||
| 171 | } | 173 | } |
| 172 | new_dl = Fdelq (new_entry, new_dl); | 174 | new_dl = Fdelq (new_entry, new_dl); |
| 173 | goto the_end; | 175 | goto the_end; |
| @@ -179,24 +181,35 @@ kqueue_compare_dir_list | |||
| 179 | new_entry = XCAR (dl1); | 181 | new_entry = XCAR (dl1); |
| 180 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), | 182 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), |
| 181 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { | 183 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { |
| 182 | pending_events = Fcons (new_entry, pending_events); | 184 | pending_dl = Fcons (new_entry, pending_dl); |
| 183 | new_dl = Fdelq (new_entry, new_dl); | 185 | new_dl = Fdelq (new_entry, new_dl); |
| 184 | goto the_end; | 186 | goto the_end; |
| 185 | } | 187 | } |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 188 | new_entry = assq_no_quit (XCAR (old_entry), pending_events); | 190 | /* Check, whether this a pending file. */ |
| 189 | if (NILP (new_entry)) | 191 | new_entry = assq_no_quit (XCAR (old_entry), pending_dl); |
| 192 | |||
| 193 | if (NILP (new_entry)) { | ||
| 194 | /* Check, whether this is an already deleted file (by rename). */ | ||
| 195 | for (dl1 = deleted_dl; ! NILP (dl1); dl1 = XCDR (dl1)) { | ||
| 196 | new_entry = XCAR (dl1); | ||
| 197 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), | ||
| 198 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { | ||
| 199 | deleted_dl = Fdelq (new_entry, deleted_dl); | ||
| 200 | goto the_end; | ||
| 201 | } | ||
| 202 | } | ||
| 190 | /* The file has been deleted. */ | 203 | /* The file has been deleted. */ |
| 191 | kqueue_generate_event | 204 | kqueue_generate_event |
| 192 | (watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil); | 205 | (watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil); |
| 193 | else { | 206 | |
| 207 | } else { | ||
| 194 | /* The file has been renamed. */ | 208 | /* The file has been renamed. */ |
| 195 | kqueue_generate_event | 209 | kqueue_generate_event |
| 196 | (watch_object, Fcons (Qrename, Qnil), | 210 | (watch_object, Fcons (Qrename, Qnil), |
| 197 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); | 211 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); |
| 198 | new_dl = Fdelq (new_entry, new_dl); | 212 | pending_dl = Fdelq (new_entry, pending_dl); |
| 199 | pending_events = Fdelq (new_entry, pending_events); | ||
| 200 | } | 213 | } |
| 201 | 214 | ||
| 202 | the_end: | 215 | the_end: |
| @@ -226,8 +239,8 @@ kqueue_compare_dir_list | |||
| 226 | new_dl = Fdelq (entry, new_dl); | 239 | new_dl = Fdelq (entry, new_dl); |
| 227 | } | 240 | } |
| 228 | 241 | ||
| 229 | /* Parse through the resulting pending_events_list. */ | 242 | /* Parse through the resulting pending_dl list. */ |
| 230 | dl = pending_events; | 243 | dl = pending_dl; |
| 231 | while (1) { | 244 | while (1) { |
| 232 | Lisp_Object entry; | 245 | Lisp_Object entry; |
| 233 | if (NILP (dl)) | 246 | if (NILP (dl)) |
| @@ -239,18 +252,21 @@ kqueue_compare_dir_list | |||
| 239 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil); | 252 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil); |
| 240 | 253 | ||
| 241 | dl = XCDR (dl); | 254 | dl = XCDR (dl); |
| 242 | pending_events = Fdelq (entry, pending_events); | 255 | pending_dl = Fdelq (entry, pending_dl); |
| 243 | } | 256 | } |
| 244 | 257 | ||
| 245 | /* At this point, old_dl, new_dl and pending_events shall be empty. | 258 | /* At this point, old_dl, new_dl and pending_dl shall be empty. |
| 246 | Let's make a check for this (might be removed once the code is | 259 | deleted_dl might not be empty when there was a rename to a |
| 247 | stable). */ | 260 | nonexisting file. Let's make a check for this (might be removed |
| 261 | once the code is stable). */ | ||
| 248 | if (! NILP (old_dl)) | 262 | if (! NILP (old_dl)) |
| 249 | report_file_error ("Old list not empty", old_dl); | 263 | report_file_error ("Old list not empty", old_dl); |
| 250 | if (! NILP (new_dl)) | 264 | if (! NILP (new_dl)) |
| 251 | report_file_error ("New list not empty", new_dl); | 265 | report_file_error ("New list not empty", new_dl); |
| 252 | if (! NILP (pending_events)) | 266 | if (! NILP (pending_dl)) |
| 253 | report_file_error ("Pending events not empty", new_dl); | 267 | report_file_error ("Pending events list not empty", pending_dl); |
| 268 | // if (! NILP (deleted_dl)) | ||
| 269 | // report_file_error ("Deleted events list not empty", deleted_dl); | ||
| 254 | 270 | ||
| 255 | /* Replace old directory listing with the new one. */ | 271 | /* Replace old directory listing with the new one. */ |
| 256 | XSETCDR (Fnthcdr (make_number (3), watch_object), | 272 | XSETCDR (Fnthcdr (make_number (3), watch_object), |
diff --git a/test/automated/auto-revert-tests.el b/test/automated/auto-revert-tests.el index 2745f106087..6f186973ee7 100644 --- a/test/automated/auto-revert-tests.el +++ b/test/automated/auto-revert-tests.el | |||
| @@ -136,7 +136,7 @@ | |||
| 136 | ;; Strange, that `copy-directory' does not work as expected. | 136 | ;; Strange, that `copy-directory' does not work as expected. |
| 137 | ;; The following shell command is not portable on all | 137 | ;; The following shell command is not portable on all |
| 138 | ;; platforms, unfortunately. | 138 | ;; platforms, unfortunately. |
| 139 | (shell-command (format "%s -f %s/* %s" cp tmpdir2 tmpdir1)) | 139 | (shell-command (format "%s %s/* %s" cp tmpdir2 tmpdir1)) |
| 140 | 140 | ||
| 141 | ;; Check, that the buffers have been reverted. | 141 | ;; Check, that the buffers have been reverted. |
| 142 | (dolist (buf (list buf1 buf2)) | 142 | (dolist (buf (list buf1 buf2)) |
diff --git a/test/automated/file-notify-tests.el b/test/automated/file-notify-tests.el index 81fb42e13b1..7bacddd8855 100644 --- a/test/automated/file-notify-tests.el +++ b/test/automated/file-notify-tests.el | |||
| @@ -196,12 +196,13 @@ remote host, or nil." | |||
| 196 | (file-notify-add-watch | 196 | (file-notify-add-watch |
| 197 | temporary-file-directory '(change attribute-change) 'ignore))) | 197 | temporary-file-directory '(change attribute-change) 'ignore))) |
| 198 | (file-notify-rm-watch file-notify--test-desc) | 198 | (file-notify-rm-watch file-notify--test-desc) |
| 199 | ;; The file does not need to exist, just the upper directory. | 199 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 200 | (should | 200 | (should |
| 201 | (setq file-notify--test-desc | 201 | (setq file-notify--test-desc |
| 202 | (file-notify-add-watch | 202 | (file-notify-add-watch |
| 203 | file-notify--test-tmpfile '(change attribute-change) 'ignore))) | 203 | file-notify--test-tmpfile '(change attribute-change) 'ignore))) |
| 204 | (file-notify-rm-watch file-notify--test-desc) | 204 | (file-notify-rm-watch file-notify--test-desc) |
| 205 | (delete-file file-notify--test-tmpfile) | ||
| 205 | 206 | ||
| 206 | ;; Check error handling. | 207 | ;; Check error handling. |
| 207 | (should-error (file-notify-add-watch 1 2 3 4) | 208 | (should-error (file-notify-add-watch 1 2 3 4) |
| @@ -242,16 +243,17 @@ is bound somewhere." | |||
| 242 | (should | 243 | (should |
| 243 | (or (string-equal (file-notify--event-file-name file-notify--test-event) | 244 | (or (string-equal (file-notify--event-file-name file-notify--test-event) |
| 244 | file-notify--test-tmpfile) | 245 | file-notify--test-tmpfile) |
| 245 | (string-equal (directory-file-name | 246 | (string-equal (file-notify--event-file-name file-notify--test-event) |
| 246 | (file-name-directory | 247 | file-notify--test-tmpfile1) |
| 247 | (file-notify--event-file-name file-notify--test-event))) | 248 | (string-equal (file-notify--event-file-name file-notify--test-event) |
| 248 | file-notify--test-tmpfile))) | 249 | temporary-file-directory))) |
| 249 | ;; Check the second file name if exists. | 250 | ;; Check the second file name if exists. |
| 250 | (when (eq (nth 1 file-notify--test-event) 'renamed) | 251 | (when (eq (nth 1 file-notify--test-event) 'renamed) |
| 251 | (should | 252 | (should |
| 252 | (string-equal | 253 | (or (string-equal (file-notify--event-file1-name file-notify--test-event) |
| 253 | (file-notify--event-file1-name file-notify--test-event) | 254 | file-notify--test-tmpfile1) |
| 254 | file-notify--test-tmpfile1)))) | 255 | (string-equal (file-notify--event-file1-name file-notify--test-event) |
| 256 | temporary-file-directory))))) | ||
| 255 | 257 | ||
| 256 | (defun file-notify--test-event-handler (event) | 258 | (defun file-notify--test-event-handler (event) |
| 257 | "Run a test over FILE-NOTIFY--TEST-EVENT. | 259 | "Run a test over FILE-NOTIFY--TEST-EVENT. |
| @@ -306,103 +308,111 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 306 | ;; Under cygwin there are so bad timings that it doesn't make sense to test. | 308 | ;; Under cygwin there are so bad timings that it doesn't make sense to test. |
| 307 | (skip-unless (not (eq system-type 'cygwin))) | 309 | (skip-unless (not (eq system-type 'cygwin))) |
| 308 | 310 | ||
| 309 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | ||
| 310 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) | ||
| 311 | |||
| 312 | (unwind-protect | 311 | (unwind-protect |
| 313 | (progn | 312 | (progn |
| 314 | ;; Check creation, change and deletion. | 313 | ;; Check file change and deletion. |
| 315 | (setq file-notify--test-desc | 314 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) |
| 316 | (file-notify-add-watch | 315 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 317 | file-notify--test-tmpfile | 316 | (should |
| 318 | '(change) 'file-notify--test-event-handler)) | 317 | (setq file-notify--test-desc |
| 319 | (file-notify--test-with-events '(created changed deleted) | 318 | (file-notify-add-watch |
| 319 | file-notify--test-tmpfile | ||
| 320 | '(change) 'file-notify--test-event-handler))) | ||
| 321 | (file-notify--test-with-events '(changed deleted) | ||
| 320 | (write-region | 322 | (write-region |
| 321 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 323 | "another text" nil file-notify--test-tmpfile nil 'no-message) |
| 322 | (read-event nil nil 0.1) | ||
| 323 | (delete-file file-notify--test-tmpfile)) | 324 | (delete-file file-notify--test-tmpfile)) |
| 324 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 325 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. |
| 325 | (let (file-notify--test-events) | 326 | (let (file-notify--test-events) |
| 326 | (file-notify-rm-watch file-notify--test-desc)) | 327 | (file-notify-rm-watch file-notify--test-desc)) |
| 327 | 328 | ||
| 328 | ;; Check creation, change and deletion. There must be a | 329 | ;; Check file creation, change and deletion when watching a |
| 329 | ;; `stopped' event when deleting the directory. It doesn't | 330 | ;; directory. There must be a `stopped' event when deleting |
| 330 | ;; work for w32notify. | 331 | ;; the directory. It doesn't work for w32notify. |
| 331 | (unless (string-equal (file-notify--test-library) "w32notify") | 332 | (unless (string-equal (file-notify--test-library) "w32notify") |
| 332 | (make-directory file-notify--test-tmpfile) | 333 | (let ((temporary-file-directory |
| 333 | (setq file-notify--test-desc | 334 | (make-temp-file "file-notify-test-parent" t))) |
| 334 | (file-notify-add-watch | 335 | (should |
| 335 | file-notify--test-tmpfile | 336 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 336 | '(change) 'file-notify--test-event-handler)) | 337 | file-notify--test-desc |
| 338 | (file-notify-add-watch | ||
| 339 | temporary-file-directory | ||
| 340 | '(change) 'file-notify--test-event-handler))) | ||
| 341 | (file-notify--test-with-events | ||
| 342 | ;; There are two `deleted' events, for the file and | ||
| 343 | ;; for the directory. Except for kqueue. | ||
| 344 | (if (string-equal (file-notify--test-library) "kqueue") | ||
| 345 | '(created changed deleted stopped) | ||
| 346 | '(created changed deleted deleted stopped)) | ||
| 347 | (write-region | ||
| 348 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 349 | (read-event nil nil 0.1) | ||
| 350 | (delete-directory temporary-file-directory 'recursive)) | ||
| 351 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | ||
| 352 | (let (file-notify--test-events) | ||
| 353 | (file-notify-rm-watch file-notify--test-desc)))) | ||
| 354 | |||
| 355 | ;; Check copy of files inside a directory. | ||
| 356 | (let ((temporary-file-directory | ||
| 357 | (make-temp-file "file-notify-test-parent" t))) | ||
| 358 | (should | ||
| 359 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | ||
| 360 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name) | ||
| 361 | file-notify--test-desc | ||
| 362 | (file-notify-add-watch | ||
| 363 | temporary-file-directory | ||
| 364 | '(change) 'file-notify--test-event-handler))) | ||
| 337 | (file-notify--test-with-events | 365 | (file-notify--test-with-events |
| 338 | ;; There are two `deleted' events, for the file and for | 366 | ;; w32notify does not distinguish between `changed' and |
| 339 | ;; the directory. Except for kqueue. | 367 | ;; `attribute-changed'. |
| 340 | (if (string-equal (file-notify--test-library) "kqueue") | 368 | (if (string-equal (file-notify--test-library) "w32notify") |
| 341 | '(created changed deleted stopped) | 369 | '(created changed changed deleted) |
| 342 | '(created changed deleted deleted stopped)) | 370 | '(created changed created changed deleted stopped)) |
| 343 | (write-region | 371 | (write-region |
| 344 | "any text" nil (expand-file-name "foo" file-notify--test-tmpfile) | 372 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 345 | nil 'no-message) | 373 | (read-event nil nil 0.1) |
| 374 | (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) | ||
| 375 | ;; The next two events shall not be visible. | ||
| 376 | (read-event nil nil 0.1) | ||
| 377 | (set-file-modes file-notify--test-tmpfile 000) | ||
| 378 | (read-event nil nil 0.1) | ||
| 379 | (set-file-times file-notify--test-tmpfile '(0 0)) | ||
| 346 | (read-event nil nil 0.1) | 380 | (read-event nil nil 0.1) |
| 347 | (delete-directory file-notify--test-tmpfile 'recursive)) | 381 | (delete-directory temporary-file-directory 'recursive)) |
| 348 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | 382 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. |
| 349 | (let (file-notify--test-events) | 383 | (let (file-notify--test-events) |
| 350 | (file-notify-rm-watch file-notify--test-desc))) | 384 | (file-notify-rm-watch file-notify--test-desc))) |
| 351 | 385 | ||
| 352 | ;; Check copy. | 386 | ;; Check rename of files inside a directory. |
| 353 | (setq file-notify--test-desc | 387 | (let ((temporary-file-directory |
| 354 | (file-notify-add-watch | 388 | (make-temp-file "file-notify-test-parent" t))) |
| 355 | file-notify--test-tmpfile | 389 | (should |
| 356 | '(change) 'file-notify--test-event-handler)) | 390 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 357 | (should file-notify--test-desc) | 391 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name) |
| 358 | (file-notify--test-with-events | 392 | file-notify--test-desc |
| 359 | ;; w32notify does not distinguish between `changed' and | 393 | (file-notify-add-watch |
| 360 | ;; `attribute-changed'. | 394 | temporary-file-directory |
| 361 | (if (string-equal (file-notify--test-library) "w32notify") | 395 | '(change) 'file-notify--test-event-handler))) |
| 362 | '(created changed changed deleted) | 396 | (file-notify--test-with-events '(created changed renamed) |
| 363 | '(created changed deleted)) | 397 | (write-region |
| 364 | (write-region | 398 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 365 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 399 | (read-event nil nil 0.1) |
| 366 | (read-event nil nil 0.1) | 400 | (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) |
| 367 | (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) | 401 | ;; After the rename, we won't get events anymore. |
| 368 | ;; The next two events shall not be visible. | 402 | (read-event nil nil 0.1) |
| 369 | (read-event nil nil 0.1) | 403 | (delete-directory temporary-file-directory 'recursive)) |
| 370 | (set-file-modes file-notify--test-tmpfile 000) | 404 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. |
| 371 | (read-event nil nil 0.1) | 405 | (let (file-notify--test-events) |
| 372 | (set-file-times file-notify--test-tmpfile '(0 0)) | 406 | (file-notify-rm-watch file-notify--test-desc))) |
| 373 | (read-event nil nil 0.1) | ||
| 374 | (delete-file file-notify--test-tmpfile) | ||
| 375 | (read-event nil nil 0.1) | ||
| 376 | (delete-file file-notify--test-tmpfile1)) | ||
| 377 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | ||
| 378 | (let (file-notify--test-events) | ||
| 379 | (file-notify-rm-watch file-notify--test-desc)) | ||
| 380 | |||
| 381 | ;; Check rename. | ||
| 382 | (setq file-notify--test-desc | ||
| 383 | (file-notify-add-watch | ||
| 384 | file-notify--test-tmpfile | ||
| 385 | '(change) 'file-notify--test-event-handler)) | ||
| 386 | (should file-notify--test-desc) | ||
| 387 | (file-notify--test-with-events '(created changed renamed) | ||
| 388 | (write-region | ||
| 389 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 390 | (read-event nil nil 0.1) | ||
| 391 | (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) | ||
| 392 | ;; After the rename, we won't get events anymore. | ||
| 393 | (read-event nil nil 0.1) | ||
| 394 | (delete-file file-notify--test-tmpfile1)) | ||
| 395 | ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. | ||
| 396 | (let (file-notify--test-events) | ||
| 397 | (file-notify-rm-watch file-notify--test-desc)) | ||
| 398 | 407 | ||
| 399 | ;; Check attribute change. It doesn't work for kqueue and w32notify. | 408 | ;; Check attribute change. It doesn't work for kqueue and w32notify. |
| 400 | (unless (or (string-equal (file-notify--test-library) "kqueue") | 409 | (unless (or (string-equal (file-notify--test-library) "kqueue") |
| 401 | (string-equal (file-notify--test-library) "w32notify")) | 410 | (string-equal (file-notify--test-library) "w32notify")) |
| 402 | (setq file-notify--test-desc | 411 | (should |
| 403 | (file-notify-add-watch | 412 | (setq file-notify--test-desc |
| 404 | file-notify--test-tmpfile | 413 | (file-notify-add-watch |
| 405 | '(attribute-change) 'file-notify--test-event-handler)) | 414 | file-notify--test-tmpfile |
| 415 | '(attribute-change) 'file-notify--test-event-handler))) | ||
| 406 | (file-notify--test-with-events | 416 | (file-notify--test-with-events |
| 407 | (if (file-remote-p temporary-file-directory) | 417 | (if (file-remote-p temporary-file-directory) |
| 408 | ;; In the remote case, `write-region' raises also an | 418 | ;; In the remote case, `write-region' raises also an |
| @@ -533,23 +543,41 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 533 | 543 | ||
| 534 | (unwind-protect | 544 | (unwind-protect |
| 535 | (progn | 545 | (progn |
| 536 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | 546 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) |
| 537 | file-notify--test-desc | 547 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 538 | (file-notify-add-watch | 548 | (should |
| 539 | file-notify--test-tmpfile | 549 | (setq file-notify--test-desc |
| 540 | '(change) #'file-notify--test-event-handler)) | 550 | (file-notify-add-watch |
| 541 | (file-notify--test-with-events '(created changed deleted) | 551 | file-notify--test-tmpfile |
| 552 | '(change) #'file-notify--test-event-handler))) | ||
| 553 | (should (file-notify-valid-p file-notify--test-desc)) | ||
| 554 | ;; After calling `file-notify-rm-watch', the descriptor is not | ||
| 555 | ;; valid anymore. | ||
| 556 | (file-notify-rm-watch file-notify--test-desc) | ||
| 557 | (should-not (file-notify-valid-p file-notify--test-desc)) | ||
| 558 | (delete-file file-notify--test-tmpfile)) | ||
| 559 | |||
| 560 | ;; Cleanup. | ||
| 561 | (file-notify--test-cleanup)) | ||
| 562 | |||
| 563 | (unwind-protect | ||
| 564 | (progn | ||
| 565 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) | ||
| 566 | (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 567 | (should | ||
| 568 | (setq file-notify--test-desc | ||
| 569 | (file-notify-add-watch | ||
| 570 | file-notify--test-tmpfile | ||
| 571 | '(change) #'file-notify--test-event-handler))) | ||
| 572 | (file-notify--test-with-events '(changed deleted) | ||
| 542 | (should (file-notify-valid-p file-notify--test-desc)) | 573 | (should (file-notify-valid-p file-notify--test-desc)) |
| 543 | (write-region | 574 | (write-region |
| 544 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 575 | "another text" nil file-notify--test-tmpfile nil 'no-message) |
| 545 | (read-event nil nil 0.1) | 576 | (read-event nil nil 0.1) |
| 546 | (delete-file file-notify--test-tmpfile)) | 577 | (delete-file file-notify--test-tmpfile)) |
| 547 | ;; After deleting the file, the descriptor is still valid. | 578 | ;; After deleting the file, the descriptor is not valid anymore. |
| 548 | (should (file-notify-valid-p file-notify--test-desc)) | 579 | (should-not (file-notify-valid-p file-notify--test-desc)) |
| 549 | ;; After removing the watch, the descriptor must not be valid | 580 | (file-notify-rm-watch file-notify--test-desc)) |
| 550 | ;; anymore. | ||
| 551 | (file-notify-rm-watch file-notify--test-desc) | ||
| 552 | (should-not (file-notify-valid-p file-notify--test-desc))) | ||
| 553 | 581 | ||
| 554 | ;; Cleanup. | 582 | ;; Cleanup. |
| 555 | (file-notify--test-cleanup)) | 583 | (file-notify--test-cleanup)) |
| @@ -560,11 +588,12 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 560 | (unless (string-equal (file-notify--test-library) "w32notify") | 588 | (unless (string-equal (file-notify--test-library) "w32notify") |
| 561 | (let ((temporary-file-directory | 589 | (let ((temporary-file-directory |
| 562 | (make-temp-file "file-notify-test-parent" t))) | 590 | (make-temp-file "file-notify-test-parent" t))) |
| 563 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) | 591 | (should |
| 564 | file-notify--test-desc | 592 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 565 | (file-notify-add-watch | 593 | file-notify--test-desc |
| 566 | file-notify--test-tmpfile | 594 | (file-notify-add-watch |
| 567 | '(change) #'file-notify--test-event-handler)) | 595 | temporary-file-directory |
| 596 | '(change) #'file-notify--test-event-handler))) | ||
| 568 | (file-notify--test-with-events | 597 | (file-notify--test-with-events |
| 569 | ;; There are two `deleted' events, for the file and for | 598 | ;; There are two `deleted' events, for the file and for |
| 570 | ;; the directory. Except for kqueue. | 599 | ;; the directory. Except for kqueue. |
| @@ -595,10 +624,11 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 595 | (setq file-notify--test-tmpfile | 624 | (setq file-notify--test-tmpfile |
| 596 | (file-name-as-directory (file-notify--test-make-temp-name))) | 625 | (file-name-as-directory (file-notify--test-make-temp-name))) |
| 597 | (make-directory file-notify--test-tmpfile) | 626 | (make-directory file-notify--test-tmpfile) |
| 598 | (setq file-notify--test-desc | 627 | (should |
| 599 | (file-notify-add-watch | 628 | (setq file-notify--test-desc |
| 600 | file-notify--test-tmpfile | 629 | (file-notify-add-watch |
| 601 | '(change) #'file-notify--test-event-handler)) | 630 | file-notify--test-tmpfile |
| 631 | '(change) #'file-notify--test-event-handler))) | ||
| 602 | (should (file-notify-valid-p file-notify--test-desc)) | 632 | (should (file-notify-valid-p file-notify--test-desc)) |
| 603 | ;; After removing the watch, the descriptor must not be valid | 633 | ;; After removing the watch, the descriptor must not be valid |
| 604 | ;; anymore. | 634 | ;; anymore. |
| @@ -619,10 +649,11 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 619 | (setq file-notify--test-tmpfile | 649 | (setq file-notify--test-tmpfile |
| 620 | (file-name-as-directory (file-notify--test-make-temp-name))) | 650 | (file-name-as-directory (file-notify--test-make-temp-name))) |
| 621 | (make-directory file-notify--test-tmpfile) | 651 | (make-directory file-notify--test-tmpfile) |
| 622 | (setq file-notify--test-desc | 652 | (should |
| 623 | (file-notify-add-watch | 653 | (setq file-notify--test-desc |
| 624 | file-notify--test-tmpfile | 654 | (file-notify-add-watch |
| 625 | '(change) #'file-notify--test-event-handler)) | 655 | file-notify--test-tmpfile |
| 656 | '(change) #'file-notify--test-event-handler))) | ||
| 626 | (should (file-notify-valid-p file-notify--test-desc)) | 657 | (should (file-notify-valid-p file-notify--test-desc)) |
| 627 | ;; After deleting the directory, the descriptor must not be | 658 | ;; After deleting the directory, the descriptor must not be |
| 628 | ;; valid anymore. | 659 | ;; valid anymore. |
| @@ -645,31 +676,39 @@ Don't wait longer than timeout seconds for the events to be delivered." | |||
| 645 | (skip-unless (not (eq system-type 'cygwin))) | 676 | (skip-unless (not (eq system-type 'cygwin))) |
| 646 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) | 677 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) |
| 647 | (make-directory file-notify--test-tmpfile) | 678 | (make-directory file-notify--test-tmpfile) |
| 648 | (setq file-notify--test-desc | 679 | (should |
| 649 | (file-notify-add-watch | 680 | (setq file-notify--test-desc |
| 650 | file-notify--test-tmpfile | 681 | (file-notify-add-watch |
| 651 | '(change) 'file-notify--test-event-handler)) | 682 | file-notify--test-tmpfile |
| 683 | '(change) 'file-notify--test-event-handler))) | ||
| 652 | (unwind-protect | 684 | (unwind-protect |
| 653 | (let ((n 1000) | 685 | (let ((n 1000) |
| 654 | x-file-list y-file-list | 686 | source-file-list target-file-list |
| 655 | (default-directory file-notify--test-tmpfile)) | 687 | (default-directory file-notify--test-tmpfile)) |
| 656 | (dotimes (i n) | 688 | (dotimes (i n) |
| 657 | (push (expand-file-name (format "x%d" i)) x-file-list) | 689 | ;; It matters which direction we rename, at least for |
| 658 | (push (expand-file-name (format "y%d" i)) y-file-list)) | 690 | ;; kqueue. This backend parses directories in alphabetic |
| 691 | ;; order (x%d before y%d). So we rename both directions. | ||
| 692 | (if (zerop (mod i 2)) | ||
| 693 | (progn | ||
| 694 | (push (expand-file-name (format "x%d" i)) source-file-list) | ||
| 695 | (push (expand-file-name (format "y%d" i)) target-file-list)) | ||
| 696 | (push (expand-file-name (format "y%d" i)) source-file-list) | ||
| 697 | (push (expand-file-name (format "x%d" i)) target-file-list))) | ||
| 659 | (file-notify--test-with-events (make-list (+ n n) 'created) | 698 | (file-notify--test-with-events (make-list (+ n n) 'created) |
| 660 | (let ((x-file-list x-file-list) | 699 | (let ((source-file-list source-file-list) |
| 661 | (y-file-list y-file-list)) | 700 | (target-file-list target-file-list)) |
| 662 | (while (and x-file-list y-file-list) | 701 | (while (and source-file-list target-file-list) |
| 663 | (write-region "" nil (pop x-file-list) nil 'no-message) | 702 | (write-region "" nil (pop source-file-list) nil 'no-message) |
| 664 | (read-event nil nil 0.1) | 703 | (read-event nil nil 0.1) |
| 665 | (write-region "" nil (pop y-file-list) nil 'no-message)))) | 704 | (write-region "" nil (pop target-file-list) nil 'no-message)))) |
| 666 | (file-notify--test-with-events (make-list n 'renamed) | 705 | (file-notify--test-with-events (make-list n 'renamed) |
| 667 | (let ((x-file-list x-file-list) | 706 | (let ((source-file-list source-file-list) |
| 668 | (y-file-list y-file-list)) | 707 | (target-file-list target-file-list)) |
| 669 | (while (and x-file-list y-file-list) | 708 | (while (and source-file-list target-file-list) |
| 670 | (rename-file (pop x-file-list) (pop y-file-list) t)))) | 709 | (rename-file (pop source-file-list) (pop target-file-list) t)))) |
| 671 | (file-notify--test-with-events (make-list n 'deleted) | 710 | (file-notify--test-with-events (make-list n 'deleted) |
| 672 | (dolist (file y-file-list) | 711 | (dolist (file target-file-list) |
| 673 | (delete-file file)))) | 712 | (delete-file file)))) |
| 674 | (file-notify--test-cleanup))) | 713 | (file-notify--test-cleanup))) |
| 675 | 714 | ||