]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement file modification check in Tramp
authorMichael Albinus <michael.albinus@gmx.de>
Thu, 3 Feb 2022 13:21:23 +0000 (14:21 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Thu, 3 Feb 2022 13:21:23 +0000 (14:21 +0100)
* lisp/net/tramp.el (tramp-handle-lock-file): Check, whether FILE
is modified.

* test/lisp/net/tramp-tests.el (tramp-test39-detect-external-change):
New test.

lisp/net/tramp.el
test/lisp/net/tramp-tests.el

index c6e55ff6889e5438b891dede9bb14cd16858dc80..121ede42c43a527c1ede6d224d2e66196c1b60c3 100644 (file)
@@ -4008,6 +4008,14 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
   ;; was visited.
   (catch 'dont-lock
     (unless (eq (file-locked-p file) t) ;; Locked by me.
+      (when (and buffer-file-truename
+                (not (verify-visited-file-modtime))
+                (file-exists-p file))
+       ;; In filelock.c, `userlock--ask-user-about-supersession-threat'
+       ;; is called, which also checks file contents.  This is unwise
+       ;; for remote files.
+       (ask-user-about-supersession-threat file))
+
       (when-let ((info (tramp-get-lock-file file))
                 (match (string-match tramp-lock-file-info-regexp info)))
        (unless (ask-user-about-lock
index 01fe7355f456dc406f8ca1b3b1a5ebf2364d9e46..b41824a6cf3b34f0ffce5d6c891f59c216250abf 100644 (file)
@@ -6018,6 +6018,78 @@ Use direct async.")
        (ignore-errors (delete-file tmp-name1))
        (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
 
+;; The function was introduced in Emacs 28.1.
+(ert-deftest tramp-test39-detect-external-change ()
+  "Check that an external file modification is reported."
+  (skip-unless (tramp--test-enabled))
+  (skip-unless (not (tramp--test-ange-ftp-p)))
+  ;; Since Emacs 28.1.
+  (skip-unless (fboundp 'file-locked-p))
+
+  (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+    (dolist (create-lockfiles '(nil t))
+      (let ((tmp-name (tramp--test-make-temp-name nil quoted))
+           (remote-file-name-inhibit-cache t)
+           (remote-file-name-inhibit-locks nil)
+           tramp-allow-unsafe-temporary-files
+            (inhibit-message t)
+           ;; tramp-rclone.el and tramp-sshfs.el cache the mounted files.
+           (tramp-fuse-unmount-on-cleanup t)
+            auto-save-default
+           (backup-inhibited t)
+           noninteractive)
+        (with-temp-buffer
+          (unwind-protect
+             (progn
+               (setq buffer-file-name tmp-name
+                     buffer-file-truename tmp-name)
+               (insert "foo")
+               ;; Bug#53207: with `create-lockfiles' nil, saving the
+               ;; buffer results in a prompt.
+               (cl-letf (((symbol-function 'yes-or-no-p)
+                          (lambda (_) (ert-fail "Test failed unexpectedly"))))
+                 (save-buffer))
+               (should-not (file-locked-p tmp-name))
+
+               ;; For local files, just changing the file
+               ;; modification on disk doesn't hurt, because file
+               ;; contents in buffer and on disk are equal.  For
+               ;; remote files, file contents is not compared.  We
+               ;; mock an older modification time in buffer, because
+               ;; Tramp regards modification times equal if they
+               ;; differ for less than 2 seconds.
+               (set-visited-file-modtime (time-add (current-time) -60))
+               ;; Some Tramp methods cannot check the file
+               ;; modification time properly, for them it doesn't
+               ;; make sense to test.
+               (when (not (verify-visited-file-modtime))
+                 (cl-letf (((symbol-function 'read-char-choice)
+                            (lambda (prompt &rest _) (message "%s" prompt) ?y)))
+                   (ert-with-message-capture captured-messages
+                     (insert "bar")
+                     (when create-lockfiles
+                       (should (string-match-p
+                                (format
+                                 "^%s changed on disk; really edit the buffer\\?"
+                                 (if (tramp--test-crypt-p)
+                                     ".+" (file-name-nondirectory tmp-name)))
+                                captured-messages))
+                       (should (file-locked-p tmp-name)))))
+
+                 ;; `save-buffer' removes the file lock.
+                 (cl-letf (((symbol-function 'yes-or-no-p) #'tramp--test-always)
+                           ((symbol-function 'read-char-choice)
+                            (lambda (&rest _) ?y)))
+                   (save-buffer))
+                 (should-not (file-locked-p tmp-name))))
+
+           ;; Cleanup.
+           (set-buffer-modified-p nil)
+           (ignore-errors (delete-file tmp-name))
+           (tramp-cleanup-connection
+            tramp-test-vec 'keep-debug 'keep-password)))))))
+
+;; The functions were introduced in Emacs 26.1.
 (ert-deftest tramp-test40-make-nearby-temp-file ()
   "Check `make-nearby-temp-file' and `temporary-file-directory'."
   (skip-unless (tramp--test-enabled))