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
		       (equal (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)))