X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/641a3472ef245157ebcb2114f2d608cb3cb401a7..c69aef14ddc150da07dcd3527b5a9fb99d6cef34:/lisp/files.el diff --git a/lisp/files.el b/lisp/files.el index 9cb46fcd0a..aca7b3593d 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3426,7 +3426,11 @@ local variables, but directory-local variables may still be applied." (format-message "%s: `lexical-binding' at end of file unreliable" (file-name-nondirectory - (or buffer-file-name "")))))) + ;; We are called from + ;; 'with-temp-buffer', so we need + ;; to use 'thisbuf's name in the + ;; warning message. + (or (buffer-file-name thisbuf) "")))))) (t (ignore-errors (push (cons (if (eq var 'eval) @@ -3713,33 +3717,43 @@ VARIABLES list of the class. The list is processed in order. applied by recursively following these rules." (setf (alist-get class dir-locals-class-alist) variables)) -(defconst dir-locals-file ".dir-locals*.el" - "Pattern for files that contain directory-local variables. +(defconst dir-locals-file ".dir-locals.el" + "File that contains directory-local variables. It has to be constant to enforce uniform values across different environments and users. +See also `dir-locals-file-2', whose values override this one's. +See Info node `(elisp)Directory Local Variables' for details.") -Multiple dir-locals files in the same directory are loaded in -`string<' order. +(defconst dir-locals-file-2 ".dir-locals-2.el" + "File that contains directory-local variables. +This essentially a second file that can be used like +`dir-locals-file', so that users can have specify their personal +dir-local variables even if the current directory already has a +`dir-locals-file' that is shared with other users (such as in a +git repository). See Info node `(elisp)Directory Local Variables' for details.") -(defun dir-locals--all-files (file-or-dir) - "Return a list of all readable dir-locals files matching FILE-OR-DIR. -If FILE-OR-DIR is a file pattern, expand wildcards in it and -return a sorted list of the results. If it is a directory name, -return a sorted list of all files matching `dir-locals-file' in -this directory. -The returned list is sorted by `string<' order." - (require 'seq) - (let ((default-directory (if (file-directory-p file-or-dir) - file-or-dir - default-directory))) - (seq-filter (lambda (f) (and (file-readable-p f) - (file-regular-p f))) - (file-expand-wildcards - (cond ((not (file-directory-p file-or-dir)) file-or-dir) - ((eq system-type 'ms-dos) (dosified-file-name dir-locals-file)) - (t dir-locals-file)) - 'full)))) +(defun dir-locals--all-files (directory) + "Return a list of all readable dir-locals files in DIRECTORY. +The returned list is sorted by increasing priority. That is, +values specified in the last file should take precedence over +those in the first." + (when (file-readable-p directory) + (let* ((file-1 (expand-file-name (if (eq system-type 'ms-dos) + (dosified-file-name dir-locals-file) + dir-locals-file) + directory)) + (file-2 (when (string-match "\\.el\\'" file-1) + (replace-match "-2.el" t nil file-1))) + (out nil)) + ;; The order here is important. + (dolist (f (list file-2 file-1)) + (when (and f + (file-readable-p f) + (file-regular-p f) + (not (file-directory-p f))) + (push f out))) + out))) (defun dir-locals-find-file (file) "Find the directory-local variables for FILE. @@ -3754,24 +3768,19 @@ 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), -or the matching entry from `dir-locals-directory-cache' (a list), -or the full path to the `dir-locals-file' (a string) in the case -of no valid cache entry. If `dir-locals-file' contains -wildcards, then the return value is not a proper filename, it is -an absolute version of `dir-locals-file' which is guaranteed to -expand to at least one file." +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)) - locals-file dir-elt) + dir-elt) ;; `locate-dominating-file' may have abbreviated the name. (when locals-dir - (setq locals-dir (expand-file-name locals-dir)) - (setq locals-file (expand-file-name (if (eq system-type 'ms-dos) - (dosified-file-name dir-locals-file) - dir-locals-file) - 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 @@ -3804,20 +3813,19 @@ expand to at least one file." (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-file) + locals-dir) ;; No cache entry. - locals-file))) - -(defun dir-locals-read-from-file (file) - "Load a variables FILE and register a new class and instance. -FILE is the absolute name of the file holding the variables to -apply. It may contain wildcards. -The new class name is the same as the directory in which FILE -is found. Returns the new class name." + locals-dir))) + +(defun dir-locals-read-from-dir (dir) + "Load all variables files in DIR and register a new class and instance. +DIR is the absolute name of a directory which must contain at +least one dir-local file (which is a file holding variables to +apply). +Return the new class name, which is a symbol named DIR." (require 'map) - (let* ((dir-name (file-name-directory file)) - (class-name (intern dir-name)) - (files (dir-locals--all-files file)) + (let* ((class-name (intern dir)) + (files (dir-locals--all-files dir)) (read-circle nil) (success nil) (variables)) @@ -3834,7 +3842,7 @@ is found. Returns the new class name." (setq success t)) (dir-locals-set-class-variables class-name variables) (dir-locals-set-directory-class - dir-name class-name + dir class-name (seconds-to-time (if success (apply #'max (mapcar (lambda (file) @@ -3845,6 +3853,9 @@ is found. Returns the new class name." 0))) class-name)) +(define-obsolete-function-alias 'dir-locals-read-from-file + 'dir-locals-read-from-dir "25.1") + (defcustom enable-remote-dir-locals nil "Non-nil means dir-local variables will be applied to remote files." :version "24.3" @@ -3866,17 +3877,17 @@ This does nothing if either `enable-local-variables' or (not (file-remote-p (or (buffer-file-name) default-directory))))) ;; Find the variables file. - (let ((file-pattern-or-cache (dir-locals-find-file - (or (buffer-file-name) default-directory))) + (let ((dir-or-cache (dir-locals-find-file + (or (buffer-file-name) default-directory))) (class nil) (dir-name nil)) (cond - ((stringp file-pattern-or-cache) - (setq dir-name (file-name-directory file-pattern-or-cache) - class (dir-locals-read-from-file file-pattern-or-cache))) - ((consp file-pattern-or-cache) - (setq dir-name (nth 0 file-pattern-or-cache)) - (setq class (nth 1 file-pattern-or-cache)))) + ((stringp dir-or-cache) + (setq dir-name dir-or-cache + class (dir-locals-read-from-dir dir-or-cache))) + ((consp dir-or-cache) + (setq dir-name (nth 0 dir-or-cache)) + (setq class (nth 1 dir-or-cache)))) (when class (let ((variables (dir-locals-collect-variables