aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2015-11-20 18:06:42 +0000
committerMichael Albinus2015-11-25 15:07:12 +0100
commit0247489fed0f70b2abf960de48bc4432381a581b (patch)
tree28e4de085d082377dfee71b800fff0b644cea3e1
parent5154781141c2305c24103beb358453d30a838921 (diff)
downloademacs-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.el6
-rw-r--r--src/kqueue.c48
-rw-r--r--test/automated/auto-revert-tests.el2
-rw-r--r--test/automated/file-notify-tests.el295
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
111kqueue_compare_dir_list 111kqueue_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