kqueue_compare_dir_list
(Lisp_Object watch_object)
{
- Lisp_Object dir, pending_events;
+ Lisp_Object dir, pending_dl, deleted_dl;
Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl;
dir = XCAR (XCDR (watch_object));
- pending_events = Qnil;
+ pending_dl = Qnil;
+ deleted_dl = Qnil;
old_directory_files = Fnth (make_number (4), watch_object);
old_dl = kqueue_directory_listing (old_directory_files);
kqueue_generate_event
(watch_object, Fcons (Qrename, Qnil),
XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry)));
+ deleted_dl = Fcons (new_entry, deleted_dl);
}
new_dl = Fdelq (new_entry, new_dl);
goto the_end;
new_entry = XCAR (dl1);
if (strcmp (SSDATA (XCAR (XCDR (old_entry))),
SSDATA (XCAR (XCDR (new_entry)))) == 0) {
- pending_events = Fcons (new_entry, pending_events);
+ pending_dl = Fcons (new_entry, pending_dl);
new_dl = Fdelq (new_entry, new_dl);
goto the_end;
}
}
- new_entry = assq_no_quit (XCAR (old_entry), pending_events);
- if (NILP (new_entry))
+ /* Check, whether this a pending file. */
+ new_entry = assq_no_quit (XCAR (old_entry), pending_dl);
+
+ if (NILP (new_entry)) {
+ /* Check, whether this is an already deleted file (by rename). */
+ for (dl1 = deleted_dl; ! NILP (dl1); dl1 = XCDR (dl1)) {
+ new_entry = XCAR (dl1);
+ if (strcmp (SSDATA (XCAR (XCDR (old_entry))),
+ SSDATA (XCAR (XCDR (new_entry)))) == 0) {
+ deleted_dl = Fdelq (new_entry, deleted_dl);
+ goto the_end;
+ }
+ }
/* The file has been deleted. */
kqueue_generate_event
(watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil);
- else {
+
+ } else {
/* The file has been renamed. */
kqueue_generate_event
(watch_object, Fcons (Qrename, Qnil),
XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry)));
- new_dl = Fdelq (new_entry, new_dl);
- pending_events = Fdelq (new_entry, pending_events);
+ pending_dl = Fdelq (new_entry, pending_dl);
}
the_end:
new_dl = Fdelq (entry, new_dl);
}
- /* Parse through the resulting pending_events_list. */
- dl = pending_events;
+ /* Parse through the resulting pending_dl list. */
+ dl = pending_dl;
while (1) {
Lisp_Object entry;
if (NILP (dl))
(watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil);
dl = XCDR (dl);
- pending_events = Fdelq (entry, pending_events);
+ pending_dl = Fdelq (entry, pending_dl);
}
- /* At this point, old_dl, new_dl and pending_events shall be empty.
- Let's make a check for this (might be removed once the code is
- stable). */
+ /* At this point, old_dl, new_dl and pending_dl shall be empty.
+ deleted_dl might not be empty when there was a rename to a
+ nonexisting file. Let's make a check for this (might be removed
+ once the code is stable). */
if (! NILP (old_dl))
report_file_error ("Old list not empty", old_dl);
if (! NILP (new_dl))
report_file_error ("New list not empty", new_dl);
- if (! NILP (pending_events))
- report_file_error ("Pending events not empty", new_dl);
+ if (! NILP (pending_dl))
+ report_file_error ("Pending events list not empty", pending_dl);
+ // if (! NILP (deleted_dl))
+ // report_file_error ("Deleted events list not empty", deleted_dl);
/* Replace old directory listing with the new one. */
XSETCDR (Fnthcdr (make_number (3), watch_object),
(file-notify-add-watch
temporary-file-directory '(change attribute-change) 'ignore)))
(file-notify-rm-watch file-notify--test-desc)
- ;; The file does not need to exist, just the upper directory.
+ (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
(should
(setq file-notify--test-desc
(file-notify-add-watch
file-notify--test-tmpfile '(change attribute-change) 'ignore)))
(file-notify-rm-watch file-notify--test-desc)
+ (delete-file file-notify--test-tmpfile)
;; Check error handling.
(should-error (file-notify-add-watch 1 2 3 4)
(should
(or (string-equal (file-notify--event-file-name file-notify--test-event)
file-notify--test-tmpfile)
- (string-equal (directory-file-name
- (file-name-directory
- (file-notify--event-file-name file-notify--test-event)))
- file-notify--test-tmpfile)))
+ (string-equal (file-notify--event-file-name file-notify--test-event)
+ file-notify--test-tmpfile1)
+ (string-equal (file-notify--event-file-name file-notify--test-event)
+ temporary-file-directory)))
;; Check the second file name if exists.
(when (eq (nth 1 file-notify--test-event) 'renamed)
(should
- (string-equal
- (file-notify--event-file1-name file-notify--test-event)
- file-notify--test-tmpfile1))))
+ (or (string-equal (file-notify--event-file1-name file-notify--test-event)
+ file-notify--test-tmpfile1)
+ (string-equal (file-notify--event-file1-name file-notify--test-event)
+ temporary-file-directory)))))
(defun file-notify--test-event-handler (event)
"Run a test over FILE-NOTIFY--TEST-EVENT.
;; Under cygwin there are so bad timings that it doesn't make sense to test.
(skip-unless (not (eq system-type 'cygwin)))
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
-
(unwind-protect
(progn
- ;; Check creation, change and deletion.
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) 'file-notify--test-event-handler))
- (file-notify--test-with-events '(created changed deleted)
+ ;; Check file change and deletion.
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) 'file-notify--test-event-handler)))
+ (file-notify--test-with-events '(changed deleted)
(write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (read-event nil nil 0.1)
+ "another text" nil file-notify--test-tmpfile nil 'no-message)
(delete-file file-notify--test-tmpfile))
;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
(let (file-notify--test-events)
(file-notify-rm-watch file-notify--test-desc))
- ;; Check creation, change and deletion. There must be a
- ;; `stopped' event when deleting the directory. It doesn't
- ;; work for w32notify.
+ ;; Check file creation, change and deletion when watching a
+ ;; directory. There must be a `stopped' event when deleting
+ ;; the directory. It doesn't work for w32notify.
(unless (string-equal (file-notify--test-library) "w32notify")
- (make-directory file-notify--test-tmpfile)
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) 'file-notify--test-event-handler))
+ (let ((temporary-file-directory
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify-add-watch
+ temporary-file-directory
+ '(change) 'file-notify--test-event-handler)))
+ (file-notify--test-with-events
+ ;; There are two `deleted' events, for the file and
+ ;; for the directory. Except for kqueue.
+ (if (string-equal (file-notify--test-library) "kqueue")
+ '(created changed deleted stopped)
+ '(created changed deleted deleted stopped))
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (read-event nil nil 0.1)
+ (delete-directory temporary-file-directory 'recursive))
+ ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
+ (let (file-notify--test-events)
+ (file-notify-rm-watch file-notify--test-desc))))
+
+ ;; Check copy of files inside a directory.
+ (let ((temporary-file-directory
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify-add-watch
+ temporary-file-directory
+ '(change) 'file-notify--test-event-handler)))
(file-notify--test-with-events
- ;; There are two `deleted' events, for the file and for
- ;; the directory. Except for kqueue.
- (if (string-equal (file-notify--test-library) "kqueue")
- '(created changed deleted stopped)
- '(created changed deleted deleted stopped))
+ ;; w32notify does not distinguish between `changed' and
+ ;; `attribute-changed'.
+ (if (string-equal (file-notify--test-library) "w32notify")
+ '(created changed changed deleted)
+ '(created changed created changed deleted stopped))
(write-region
- "any text" nil (expand-file-name "foo" file-notify--test-tmpfile)
- nil 'no-message)
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (read-event nil nil 0.1)
+ (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
+ ;; The next two events shall not be visible.
+ (read-event nil nil 0.1)
+ (set-file-modes file-notify--test-tmpfile 000)
+ (read-event nil nil 0.1)
+ (set-file-times file-notify--test-tmpfile '(0 0))
(read-event nil nil 0.1)
- (delete-directory file-notify--test-tmpfile 'recursive))
+ (delete-directory temporary-file-directory 'recursive))
;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
(let (file-notify--test-events)
(file-notify-rm-watch file-notify--test-desc)))
- ;; Check copy.
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) 'file-notify--test-event-handler))
- (should file-notify--test-desc)
- (file-notify--test-with-events
- ;; w32notify does not distinguish between `changed' and
- ;; `attribute-changed'.
- (if (string-equal (file-notify--test-library) "w32notify")
- '(created changed changed deleted)
- '(created changed deleted))
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (read-event nil nil 0.1)
- (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1)
- ;; The next two events shall not be visible.
- (read-event nil nil 0.1)
- (set-file-modes file-notify--test-tmpfile 000)
- (read-event nil nil 0.1)
- (set-file-times file-notify--test-tmpfile '(0 0))
- (read-event nil nil 0.1)
- (delete-file file-notify--test-tmpfile)
- (read-event nil nil 0.1)
- (delete-file file-notify--test-tmpfile1))
- ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
- (let (file-notify--test-events)
- (file-notify-rm-watch file-notify--test-desc))
-
- ;; Check rename.
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) 'file-notify--test-event-handler))
- (should file-notify--test-desc)
- (file-notify--test-with-events '(created changed renamed)
- (write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
- (read-event nil nil 0.1)
- (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
- ;; After the rename, we won't get events anymore.
- (read-event nil nil 0.1)
- (delete-file file-notify--test-tmpfile1))
- ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
- (let (file-notify--test-events)
- (file-notify-rm-watch file-notify--test-desc))
+ ;; Check rename of files inside a directory.
+ (let ((temporary-file-directory
+ (make-temp-file "file-notify-test-parent" t)))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-tmpfile1 (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify-add-watch
+ temporary-file-directory
+ '(change) 'file-notify--test-event-handler)))
+ (file-notify--test-with-events '(created changed renamed)
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (read-event nil nil 0.1)
+ (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
+ ;; After the rename, we won't get events anymore.
+ (read-event nil nil 0.1)
+ (delete-directory temporary-file-directory 'recursive))
+ ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it.
+ (let (file-notify--test-events)
+ (file-notify-rm-watch file-notify--test-desc)))
;; Check attribute change. It doesn't work for kqueue and w32notify.
(unless (or (string-equal (file-notify--test-library) "kqueue")
(string-equal (file-notify--test-library) "w32notify"))
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(attribute-change) 'file-notify--test-event-handler))
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(attribute-change) 'file-notify--test-event-handler)))
(file-notify--test-with-events
(if (file-remote-p temporary-file-directory)
;; In the remote case, `write-region' raises also an
(unwind-protect
(progn
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'file-notify--test-event-handler))
- (file-notify--test-with-events '(created changed deleted)
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) #'file-notify--test-event-handler)))
+ (should (file-notify-valid-p file-notify--test-desc))
+ ;; After calling `file-notify-rm-watch', the descriptor is not
+ ;; valid anymore.
+ (file-notify-rm-watch file-notify--test-desc)
+ (should-not (file-notify-valid-p file-notify--test-desc))
+ (delete-file file-notify--test-tmpfile))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup))
+
+ (unwind-protect
+ (progn
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ (write-region "any text" nil file-notify--test-tmpfile nil 'no-message)
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) #'file-notify--test-event-handler)))
+ (file-notify--test-with-events '(changed deleted)
(should (file-notify-valid-p file-notify--test-desc))
(write-region
- "any text" nil file-notify--test-tmpfile nil 'no-message)
+ "another text" nil file-notify--test-tmpfile nil 'no-message)
(read-event nil nil 0.1)
(delete-file file-notify--test-tmpfile))
- ;; After deleting the file, the descriptor is still valid.
- (should (file-notify-valid-p file-notify--test-desc))
- ;; After removing the watch, the descriptor must not be valid
- ;; anymore.
- (file-notify-rm-watch file-notify--test-desc)
- (should-not (file-notify-valid-p file-notify--test-desc)))
+ ;; 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))
;; Cleanup.
(file-notify--test-cleanup))
(unless (string-equal (file-notify--test-library) "w32notify")
(let ((temporary-file-directory
(make-temp-file "file-notify-test-parent" t)))
- (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
- file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'file-notify--test-event-handler))
+ (should
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
+ file-notify--test-desc
+ (file-notify-add-watch
+ temporary-file-directory
+ '(change) #'file-notify--test-event-handler)))
(file-notify--test-with-events
;; There are two `deleted' events, for the file and for
;; the directory. Except for kqueue.
(setq file-notify--test-tmpfile
(file-name-as-directory (file-notify--test-make-temp-name)))
(make-directory file-notify--test-tmpfile)
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'file-notify--test-event-handler))
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) #'file-notify--test-event-handler)))
(should (file-notify-valid-p file-notify--test-desc))
;; After removing the watch, the descriptor must not be valid
;; anymore.
(setq file-notify--test-tmpfile
(file-name-as-directory (file-notify--test-make-temp-name)))
(make-directory file-notify--test-tmpfile)
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) #'file-notify--test-event-handler))
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) #'file-notify--test-event-handler)))
(should (file-notify-valid-p file-notify--test-desc))
;; After deleting the directory, the descriptor must not be
;; valid anymore.
(skip-unless (not (eq system-type 'cygwin)))
(setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
(make-directory file-notify--test-tmpfile)
- (setq file-notify--test-desc
- (file-notify-add-watch
- file-notify--test-tmpfile
- '(change) 'file-notify--test-event-handler))
+ (should
+ (setq file-notify--test-desc
+ (file-notify-add-watch
+ file-notify--test-tmpfile
+ '(change) 'file-notify--test-event-handler)))
(unwind-protect
(let ((n 1000)
- x-file-list y-file-list
+ source-file-list target-file-list
(default-directory file-notify--test-tmpfile))
(dotimes (i n)
- (push (expand-file-name (format "x%d" i)) x-file-list)
- (push (expand-file-name (format "y%d" i)) y-file-list))
+ ;; It matters which direction we rename, at least for
+ ;; kqueue. This backend parses directories in alphabetic
+ ;; order (x%d before y%d). So we rename both directions.
+ (if (zerop (mod i 2))
+ (progn
+ (push (expand-file-name (format "x%d" i)) source-file-list)
+ (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-events (make-list (+ n n) 'created)
- (let ((x-file-list x-file-list)
- (y-file-list y-file-list))
- (while (and x-file-list y-file-list)
- (write-region "" nil (pop x-file-list) nil 'no-message)
+ (let ((source-file-list source-file-list)
+ (target-file-list target-file-list))
+ (while (and source-file-list target-file-list)
+ (write-region "" nil (pop source-file-list) nil 'no-message)
(read-event nil nil 0.1)
- (write-region "" nil (pop y-file-list) nil 'no-message))))
+ (write-region "" nil (pop target-file-list) nil 'no-message))))
(file-notify--test-with-events (make-list n 'renamed)
- (let ((x-file-list x-file-list)
- (y-file-list y-file-list))
- (while (and x-file-list y-file-list)
- (rename-file (pop x-file-list) (pop y-file-list) t))))
+ (let ((source-file-list source-file-list)
+ (target-file-list target-file-list))
+ (while (and source-file-list target-file-list)
+ (rename-file (pop source-file-list) (pop target-file-list) t))))
(file-notify--test-with-events (make-list n 'deleted)
- (dolist (file y-file-list)
+ (dolist (file target-file-list)
(delete-file file))))
(file-notify--test-cleanup)))