Function: dir-locals-find-file
dir-locals-find-file is a byte-compiled function defined in
files.el.gz.
Signature
(dir-locals-find-file FILE)
Documentation
Find the directory-local variables for FILE.
This searches upward in the directory tree from FILE.
It stops at the first directory that has been registered in
dir-locals-directory-cache or contains a dir-locals-file.
If it finds an entry in the cache, it checks that it is valid.
A cache entry with no modification time element (normally, one that
has been assigned directly using dir-locals-set-directory-class, not
set from a file) is always valid.
A cache entry based on a dir-locals-file is valid if the modification
time stored in the cache matches the current file modification time.
If not, the cache entry is cleared so that the file will be re-read.
This function returns either:
- nil (no directory local variables found),
- the matching entry from dir-locals-directory-cache (a list),
- or the full path to the directory (a string) containing at
least one dir-locals-file in the case of no valid cache
entry.
Source Code
;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun dir-locals-find-file (file)
"Find the directory-local variables for FILE.
This searches upward in the directory tree from FILE.
It stops at the first directory that has been registered in
`dir-locals-directory-cache' or contains a `dir-locals-file'.
If it finds an entry in the cache, it checks that it is valid.
A cache entry with no modification time element (normally, one that
has been assigned directly using `dir-locals-set-directory-class', not
set from a file) is always valid.
A cache entry based on a `dir-locals-file' is valid if the modification
time stored in the cache matches the current file modification time.
If not, the cache entry is cleared so that the file will be re-read.
This function returns either:
- nil (no directory local variables found),
- the matching entry from `dir-locals-directory-cache' (a list),
- or the full path to the directory (a string) containing at
least one `dir-locals-file' in the case of no valid cache
entry."
(setq file (expand-file-name file))
(let* ((locals-dir (locate-dominating-file (file-name-directory file)
#'dir-locals--all-files))
dir-elt)
;; `locate-dominating-file' may have abbreviated the name.
(when locals-dir
(setq locals-dir (expand-file-name locals-dir)))
;; Find the best cached value in `dir-locals-directory-cache'.
(dolist (elt dir-locals-directory-cache)
(when (and (string-prefix-p (car elt) file
(memq system-type
'(windows-nt cygwin ms-dos)))
(> (length (car elt)) (length (car dir-elt))))
(setq dir-elt elt)))
(if (and dir-elt
(or (null locals-dir)
(<= (length locals-dir)
(length (car dir-elt)))))
;; Found a potential cache entry. Check validity.
;; A cache entry with no MTIME is assumed to always be valid
;; (ie, set directly, not from a dir-locals file).
;; Note, we don't bother to check that there is a matching class
;; element in dir-locals-class-alist, since that's done by
;; dir-locals-set-directory-class.
(if (or (null (nth 2 dir-elt))
(let ((cached-files (dir-locals--all-files (car dir-elt))))
;; The entry MTIME should match the most recent
;; MTIME among matching files.
(and cached-files
(time-equal-p
(nth 2 dir-elt)
(let ((latest 0))
(dolist (f cached-files latest)
(let ((f-time
(file-attribute-modification-time
(file-attributes f))))
(if (time-less-p latest f-time)
(setq latest f-time)))))))))
;; This cache entry is OK.
dir-elt
;; This cache entry is invalid; clear it.
(setq dir-locals-directory-cache
(delq dir-elt dir-locals-directory-cache))
;; Return the first existing dir-locals file. Might be the same
;; as dir-elt's, might not (eg latter might have been deleted).
locals-dir)
;; No cache entry.
locals-dir)))