Improve file-has-changed-p

* doc/lispref/files.texi: Update the documentation.

* lisp/net/mailcap.el: Add a second argument to the call to
file-has-changed-p (bug#51523).
This commit is contained in:
Gregory Heytings 2021-11-02 15:50:31 +01:00 committed by Lars Ingebrigtsen
parent ff5327d72a
commit 53a9a2de45
3 changed files with 27 additions and 19 deletions

View file

@ -1314,15 +1314,17 @@ on the 19th, @file{aug-20} was written on the 20th, and the file
@end example
@end defun
@defun file-has-changed-p filename
@defun file-has-changed-p filename tag
This function returns non-@code{nil} if the time stamp of
@var{filename} has changed since the last call. When called for the
first time for some @var{filename}, it records the last modification
time of the file and returns non-@code{nil}. Thereafter, when called
for the same @var{filename}, it compares the current time stamp with
the recorded one and returns non-@code{nil} only if they are
different. This is useful when a Lisp program wants to re-read a file
whenever it changes.
time ans size of the file and returns non-@code{nil}. Thereafter,
when called for the same @var{filename}, it compares the current time
stamp and size with the recorded one and returns non-@code{nil} only
if they are different. This is useful when a Lisp program wants to
re-read a file whenever it changes. With an optional argument
@var{tag}, the size and modification time comparisons are limited to
calls with the same tag.
@end defun
@defun file-attributes filename &optional id-format

View file

@ -6181,21 +6181,25 @@ Return nil if DIR is not an existing directory."
(unless mismatch
(file-equal-p root dir)))))))
(defvar file-has-changed-p--hash-table (make-hash-table)
(defvar file-has-changed-p--hash-table (make-hash-table :test #'equal)
"Internal variable used by `file-has-changed-p'.")
(defun file-has-changed-p (file)
(defun file-has-changed-p (file &optional tag)
"Return non-nil if FILE has changed.
The modification time of FILE is compared to the modification
time of FILE during a previous invocation of `file-has-changed-p'.
Therefore the first invocation of `file-has-changed-p' always
returns non-nil."
(let* ((attr (file-attributes file 'integer))
(mtime (file-attribute-modification-time attr))
(saved-mtime (gethash (intern file)
file-has-changed-p--hash-table)))
(when (not (equal mtime saved-mtime))
(puthash (intern file) mtime file-has-changed-p--hash-table))))
The size and modification time of FILE is compared to the size
and modification time of FILE during a previous invocation of
`file-has-changed-p'. Therefore the first invocation of
`file-has-changed-p' always returns non-nil.
The optional argument TAG can be used to limit the comparison to
invocations with identical tags; it can for example be the symbol
of the calling function."
(let* ((fileattr (file-attributes file 'integer))
(attr (cons (file-attribute-size fileattr)
(file-attribute-modification-time fileattr)))
(sym (concat (symbol-name tag) "@" file))
(cachedattr (gethash sym file-has-changed-p--hash-table)))
(when (not (equal attr cachedattr))
(puthash sym attr file-has-changed-p--hash-table))))
(defun copy-directory (directory newname &optional keep-time parents copy-contents)
"Copy DIRECTORY to NEWNAME. Both args must be strings.

View file

@ -447,7 +447,9 @@ MAILCAPS if set; otherwise (on Unix) use the path from RFC 1524, plus
("/etc/mailcap" system)
("/usr/etc/mailcap" system)
("/usr/local/etc/mailcap" system)))))
(when (seq-some (lambda (f) (file-has-changed-p (car f))) path)
(when (seq-some (lambda (f)
(file-has-changed-p (car f) 'mail-parse-mailcaps))
path)
;; The ~/.mailcap entries will end up first in the resulting data.
(dolist (spec (reverse
(if (stringp path)