From: Gregory Heytings Date: Tue, 2 Nov 2021 14:50:31 +0000 (+0100) Subject: Improve file-has-changed-p X-Git-Tag: emacs-29.0.90~3671^2~289 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=53a9a2de456b2db8d126bbc71becd5ae86a1f172;p=emacs.git 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). --- diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index b7420fc678f..84da6eba2fc 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -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 diff --git a/lisp/files.el b/lisp/files.el index 5e7be3844eb..d7dfa9399e2 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -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. diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el index 4dedd38c22c..e40cf2a336d 100644 --- a/lisp/net/mailcap.el +++ b/lisp/net/mailcap.el @@ -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)