emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master daea9b3 1/2: Read mailcaps again only when necessary


From: Lars Ingebrigtsen
Subject: master daea9b3 1/2: Read mailcaps again only when necessary
Date: Mon, 1 Nov 2021 09:53:46 -0400 (EDT)

branch: master
commit daea9b3b44a4dc09017c3d2d5b8eaa4c68cdd2b0
Author: Gregory Heytings <gregory@heytings.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Read mailcaps again only when necessary
    
    * doc/lispref/files.texi (File Attributes): Document it.
    
    * lisp/files.el (file-has-changed-p): New function.
    (file-has-changed-p--hash-table): Internal variable used by the
    new function (bug#51523).
    * lisp/emacs-lisp/shortdoc.el (file): Mention it.
    
    * lisp/net/mailcap.el (mailcap-parse-mailcaps): Read mailcaps again
    only when at least one of the mailcap files has changed.  Fixes
    bug#51523.
---
 doc/lispref/files.texi      |  9 +++++++++
 etc/NEWS                    |  5 +++++
 lisp/emacs-lisp/shortdoc.el |  3 +++
 lisp/files.el               | 16 ++++++++++++++++
 lisp/net/mailcap.el         | 25 +++++++++++++------------
 5 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 59e18b3..250f7a3 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1314,6 +1314,15 @@ on the 19th, @file{aug-20} was written on the 20th, and 
the file
 @end example
 @end defun
 
+@defun file-has-changed-p filename
+This convenience function is useful when, for instance, parsing files
+run-time, and you typically want to re-read a file when it has
+changed.  This function returns non-@code{nil} the first time it's
+called on @var{filename} in an Emacs session, but will return
+@code{nil} on subsequent calls in that session (unless the file
+changes its modification time).
+@end defun
+
 @defun file-attributes filename &optional id-format
 @anchor{Definition of file-attributes}
 This function returns a list of attributes of file @var{filename}.  If
diff --git a/etc/NEWS b/etc/NEWS
index 57c64f7..62cfb79 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -360,6 +360,11 @@ Use 'exif-parse-file' and 'exif-field' instead.
 
 * Lisp Changes in Emacs 29.1
 
+*** New function 'file-has-changed-p'.
+This convenience function is useful when writing code that parses
+files run-time, and allows you to easily re-parse files when they have
+changed (but not otherwise).
+
 ---
 *** New function 'font-has-char-p'.
 This can be used to check whether a specific font has a glyph for a
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index daf362d..c3d6c74 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -358,6 +358,9 @@ There can be any number of :example/:result elements."
   (file-newer-than-file-p
    :no-eval (file-newer-than-file-p "/tmp/foo" "/tmp/bar")
    :eg-result nil)
+  (file-has-changed-p
+   :no-eval (file-has-changed-p "/tmp/foo")
+   :eg-result t)
   (file-equal-p
    :no-eval (file-equal-p "/tmp/foo" "/tmp/bar")
    :eg-result nil)
diff --git a/lisp/files.el b/lisp/files.el
index 1e65d0c..5e7be38 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6181,6 +6181,22 @@ 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)
+  "Internal variable used by `file-has-changed-p'.")
+
+(defun file-has-changed-p (file)
+  "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))))
+
 (defun copy-directory (directory newname &optional keep-time parents 
copy-contents)
   "Copy DIRECTORY to NEWNAME.  Both args must be strings.
 This function always sets the file modes of the output files to match
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index 83d0eee..4dedd38 100644
--- a/lisp/net/mailcap.el
+++ b/lisp/net/mailcap.el
@@ -447,18 +447,19 @@ 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)))))
-    ;; The ~/.mailcap entries will end up first in the resulting data.
-    (dolist (spec (reverse
-                   (if (stringp path)
-                       (split-string path path-separator t)
-                     path)))
-      (let ((source (and (consp spec) (cadr spec)))
-            (file-name (if (stringp spec)
-                           spec
-                         (car spec))))
-        (when (and (file-readable-p file-name)
-                   (file-regular-p file-name))
-          (mailcap-parse-mailcap file-name source))))
+    (when (seq-some (lambda (f) (file-has-changed-p (car f))) path)
+      ;; The ~/.mailcap entries will end up first in the resulting data.
+      (dolist (spec (reverse
+                    (if (stringp path)
+                        (split-string path path-separator t)
+                      path)))
+       (let ((source (and (consp spec) (cadr spec)))
+             (file-name (if (stringp spec)
+                            spec
+                          (car spec))))
+         (when (and (file-readable-p file-name)
+                    (file-regular-p file-name))
+           (mailcap-parse-mailcap file-name source)))))
     (setq mailcap-parsed-p t)))
 
 (defun mailcap-parse-mailcap (fname &optional source)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]