]> code.delx.au - gnu-emacs/blobdiff - lisp/files.el
; Merge from origin/emacs-25
[gnu-emacs] / lisp / files.el
index 9cb46fcd0a9382e07862a14c3fe4aa82465282f3..aca7b3593d973caa137db78fa258b1ab54cad207 100644 (file)
@@ -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