Some further adaptions wrt Tramp file name locks

* lisp/files.el (files--transform-file-name): Rename from
`auto-save--transform-file-name'.  Wrap with `save-match-data'.
(make-auto-save-file-name): Use it.
(make-lock-file-name): Use it.  Call file name handler.

* lisp/net/tramp.el (tramp-handle-write-region):
* lisp/net/tramp-adb.el (tramp-adb-handle-write-region):
* lisp/net/tramp-sh.el (tramp-sh-handle-write-region):
* lisp/net/tramp-smb.el (tramp-smb-handle-write-region):
Suppress file lock for temporary file.

* lisp/net/tramp-compat.el (tramp-compat-make-lock-file-name):
New defalias.

* lisp/net/tramp.el (tramp-get-lock-file)
(tramp-handle-lock-file, tramp-handle-unlock-file): Use it.
(tramp-make-lock-name): Remove.

* test/lisp/filenotify-tests.el (file-notify-test03-events-remote):
Tag it :unstable temporarily.
This commit is contained in:
Michael Albinus 2021-07-08 07:48:40 +02:00
parent 7d6d14023a
commit 6d580b00e4
7 changed files with 87 additions and 75 deletions

View file

@ -6679,12 +6679,12 @@ Does not consider `auto-save-visited-file-name' as that variable is checked
before calling this function.
See also `auto-save-file-name-p'."
(if buffer-file-name
(let ((handler (find-file-name-handler buffer-file-name
'make-auto-save-file-name)))
(let ((handler (find-file-name-handler
buffer-file-name 'make-auto-save-file-name)))
(if handler
(funcall handler 'make-auto-save-file-name)
(auto-save--transform-file-name buffer-file-name
auto-save-file-name-transforms
(files--transform-file-name
buffer-file-name auto-save-file-name-transforms
"#" "#")))
;; Deal with buffers that don't have any associated files. (Mail
;; mode tends to create a good number of these.)
@ -6735,73 +6735,73 @@ See also `auto-save-file-name-p'."
(file-error nil))
file-name)))
(defun auto-save--transform-file-name (filename transforms
prefix suffix)
(defun files--transform-file-name (filename transforms prefix suffix)
"Transform FILENAME according to TRANSFORMS.
See `auto-save-file-name-transforms' for the format of
TRANSFORMS. PREFIX is prepended to the non-directory portion of
the resulting file name, and SUFFIX is appended."
(let (result uniq)
;; Apply user-specified translations
;; to the file name.
(while (and transforms (not result))
(if (string-match (car (car transforms)) filename)
(setq result (replace-match (cadr (car transforms)) t nil
filename)
uniq (car (cddr (car transforms)))))
(setq transforms (cdr transforms)))
(when result
(setq filename
(cond
((memq uniq (secure-hash-algorithms))
(concat
(file-name-directory result)
(secure-hash uniq filename)))
(uniq
(concat
(file-name-directory result)
(subst-char-in-string
?/ ?!
(replace-regexp-in-string
"!" "!!" filename))))
(t result))))
(setq result
(if (and (eq system-type 'ms-dos)
(not (msdos-long-file-names)))
;; We truncate the file name to DOS 8+3 limits
;; before doing anything else, because the regexp
;; passed to string-match below cannot handle
;; extensions longer than 3 characters, multiple
;; dots, and other atrocities.
(let ((fn (dos-8+3-filename
(file-name-nondirectory buffer-file-name))))
(string-match
"\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'"
fn)
(concat (file-name-directory buffer-file-name)
prefix (match-string 1 fn)
"." (match-string 3 fn) suffix))
(concat (file-name-directory filename)
prefix
(file-name-nondirectory filename)
suffix)))
;; Make sure auto-save file names don't contain characters
;; invalid for the underlying filesystem.
(expand-file-name
(if (and (memq system-type '(ms-dos windows-nt cygwin))
;; Don't modify remote filenames
(not (file-remote-p result)))
(convert-standard-filename result)
result))))
(save-match-data
(let (result uniq)
;; Apply user-specified translations to the file name.
(while (and transforms (not result))
(if (string-match (car (car transforms)) filename)
(setq result (replace-match (cadr (car transforms)) t nil
filename)
uniq (car (cddr (car transforms)))))
(setq transforms (cdr transforms)))
(when result
(setq filename
(cond
((memq uniq (secure-hash-algorithms))
(concat
(file-name-directory result)
(secure-hash uniq filename)))
(uniq
(concat
(file-name-directory result)
(subst-char-in-string
?/ ?!
(replace-regexp-in-string
"!" "!!" filename))))
(t result))))
(setq result
(if (and (eq system-type 'ms-dos)
(not (msdos-long-file-names)))
;; We truncate the file name to DOS 8+3 limits before
;; doing anything else, because the regexp passed to
;; string-match below cannot handle extensions longer
;; than 3 characters, multiple dots, and other
;; atrocities.
(let ((fn (dos-8+3-filename
(file-name-nondirectory buffer-file-name))))
(string-match
"\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'"
fn)
(concat (file-name-directory buffer-file-name)
prefix (match-string 1 fn)
"." (match-string 3 fn) suffix))
(concat (file-name-directory filename)
prefix
(file-name-nondirectory filename)
suffix)))
;; Make sure auto-save file names don't contain characters
;; invalid for the underlying filesystem.
(expand-file-name
(if (and (memq system-type '(ms-dos windows-nt cygwin))
;; Don't modify remote filenames
(not (file-remote-p result)))
(convert-standard-filename result)
result)))))
(defun make-lock-file-name (filename)
"Make a lock file name for FILENAME.
By default, this just prepends \".*\" to the non-directory part
of FILENAME, but the transforms in `lock-file-name-transforms'
are done first."
(save-match-data
(auto-save--transform-file-name
filename lock-file-name-transforms ".#" "")))
(let ((handler (find-file-name-handler filename 'make-lock-file-name)))
(if handler
(funcall handler 'make-lock-file-name filename)
(files--transform-file-name filename lock-file-name-transforms ".#" ""))))
(defun auto-save-file-name-p (filename)
"Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.

View file

@ -564,7 +564,8 @@ But handle the case, if the \"test\" command is not available."
(when (and append (file-exists-p filename))
(copy-file filename tmpfile 'ok)
(set-file-modes tmpfile (logior (or (file-modes tmpfile) 0) #o0600)))
(write-region start end tmpfile append 'no-message)
(let (create-lockfiles)
(write-region start end tmpfile append 'no-message))
(with-tramp-progress-reporter
v 3 (format-message
"Moving tmp file `%s' to `%s'" tmpfile filename)

View file

@ -353,6 +353,16 @@ A nil value for either argument stands for the current time."
(lambda (fromstring tostring instring)
(replace-regexp-in-string (regexp-quote fromstring) tostring instring))))
;; Function `make-lock-file-name' is new in Emacs 28.1.
(defalias 'tramp-compat-make-lock-file-name
(if (fboundp 'make-lock-file-name)
#'make-lock-file-name
(lambda (filename)
(expand-file-name
(concat
".#" (file-name-nondirectory filename))
(file-name-directory filename)))))
(dolist (elt (all-completions "tramp-compat-" obarray 'functionp))
(put (intern elt) 'tramp-suppress-trace t))

View file

@ -3274,7 +3274,9 @@ implementation will be used."
(or (file-directory-p localname)
(file-writable-p localname)))))
;; Short track: if we are on the local host, we can run directly.
(write-region start end localname append 'no-message)
(write-region
start end localname append 'no-message
(and lockname (file-local-name lockname)))
(let* ((modes (tramp-default-file-modes
filename (and (eq mustbenew 'excl) 'nofollow)))
@ -3308,7 +3310,8 @@ implementation will be used."
;; on. We must ensure that `file-coding-system-alist'
;; matches `tmpfile'.
(let ((file-coding-system-alist
(tramp-find-file-name-coding-system-alist filename tmpfile)))
(tramp-find-file-name-coding-system-alist filename tmpfile))
create-lockfiles)
(condition-case err
(write-region start end tmpfile append 'no-message)
((error quit)

View file

@ -1606,7 +1606,8 @@ errors for shares like \"C$/\", which are common in Microsoft Windows."
;; We say `no-message' here because we don't want the visited file
;; modtime data to be clobbered from the temp file. We call
;; `set-visited-file-modtime' ourselves later on.
(write-region start end tmpfile append 'no-message)
(let (create-lockfiles)
(write-region start end tmpfile append 'no-message))
(with-tramp-progress-reporter
v 3 (format "Moving tmp file %s to %s" tmpfile filename)

View file

@ -3818,15 +3818,10 @@ User is always nil."
;; Result.
(cons (expand-file-name filename) (cdr result)))))
(defun tramp-make-lock-name (file)
"Implement MAKE_LOCK_NAME of filelock.c."
(expand-file-name
(concat ".#" (file-name-nondirectory file)) (file-name-directory file)))
(defun tramp-get-lock-file (file)
"Read lockfile of FILE.
Return nil when there is no lockfile"
(let ((lockname (tramp-make-lock-name file)))
(let ((lockname (tramp-compat-make-lock-file-name file)))
(or (file-symlink-p lockname)
(and (file-readable-p lockname)
(with-temp-buffer
@ -3873,7 +3868,7 @@ Return nil when there is no lockfile"
(match-string 2 contents) (match-string 3 contents)))
(throw 'dont-lock nil)))
(let ((lockname (tramp-make-lock-name file))
(let ((lockname (tramp-compat-make-lock-file-name file))
;; USER@HOST.PID[:BOOT_TIME]
(contents
(format
@ -3886,7 +3881,8 @@ Return nil when there is no lockfile"
(defun tramp-handle-unlock-file (file)
"Like `unlock-file' for Tramp files."
(delete-file (tramp-make-lock-name file)))
(ignore-errors
(delete-file (tramp-compat-make-lock-file-name file))))
(defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix)
"Like `load' for Tramp files."
@ -4470,7 +4466,8 @@ of."
;; We say `no-message' here because we don't want the visited file
;; modtime data to be clobbered from the temp file. We call
;; `set-visited-file-modtime' ourselves later on.
(write-region start end tmpfile append 'no-message)
(let (create-lockfiles)
(write-region start end tmpfile append 'no-message))
(condition-case nil
(rename-file tmpfile filename 'ok-if-already-exists)
(error

View file

@ -927,7 +927,7 @@ delivered."
(file-notify--test-cleanup)))
(file-notify--deftest-remote file-notify-test03-events
"Check file creation/change/removal notifications for remote files.")
"Check file creation/change/removal notifications for remote files." t)
(require 'autorevert)
(setq auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"