From 71b20b31c8ee25bcd0de1a954c9ca7b49140b3b2 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sat, 30 Jan 2016 16:14:52 +0000 Subject: [PATCH] Backport: * lisp/files.el: Remove support for extra .dir-locals file (dir-locals-file-2, dir-locals--all-files): Remove. (dir-locals-collect-variables, dir-locals-file, dir-locals-find-file) (dir-locals-read-from-file, hack-dir-local-variables): Revert changes. * lisp/files-x.el (modify-dir-local-variable): Revert changes. * lisp/help-fns.el (describe-variable): Revert changes. * doc/emacs/custom.texi (Directory Variables): Revert changes. * etc/NEWS: Revert changes. --- doc/emacs/custom.texi | 6 +- etc/NEWS | 4 - lisp/files-x.el | 30 +++---- lisp/files.el | 198 ++++++++++++++++-------------------------- lisp/help-fns.el | 42 ++++----- 5 files changed, 106 insertions(+), 174 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 7be660c85d1..c1093353757 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -1298,11 +1298,7 @@ accomplished with @dfn{directory-local variables}. named @file{.dir-locals.el}@footnote{ On MS-DOS, the name of this file should be @file{_dir-locals.el}, due to limitations of the DOS filesystems. If the filesystem is limited to 8+3 file names, the name -of the file will be truncated by the OS to @file{_dir-loc.el}. -}@footnote{ You can also use @file{.dir-locals-2.el}, which -is loaded in addition. This is useful when @file{.dir-locals.el} is -under version control in a shared repository and can't be used for -personal customizations. } in a +of the file will be truncated by the OS to @file{_dir-loc.el}. } in a directory. Whenever Emacs visits any file in that directory or any of its subdirectories, it will apply the directory-local variables specified in @file{.dir-locals.el}, as though they had been defined as diff --git a/etc/NEWS b/etc/NEWS index d0415a22f95..a7348e4e6f2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -180,10 +180,6 @@ change in future releases. For that reason, their support is disabled by default, and must be enabled by using the `--with-modules' option at configure time. -+++ -** A second dir-local file (.dir-locals-2.el) is now accepted. -See the variable `dir-locals-file-2' for more information. - +++ ** Network security (TLS/SSL certificate validity and the like) is added via the new Network Security Manager (NSM) and controlled via diff --git a/lisp/files-x.el b/lisp/files-x.el index 05ad7f57c57..f0102fd83af 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -429,24 +429,18 @@ from the MODE alist ignoring the input argument VALUE." (catch 'exit (unless enable-local-variables (throw 'exit (message "Directory-local variables are disabled"))) - (let* ((dir-or-cache (and (buffer-file-name) - (not (file-remote-p (buffer-file-name))) - (dir-locals-find-file (buffer-file-name)))) - (variables-file - ;; If there are several .dir-locals, the user probably - ;; wants to edit the last one (the highest priority). - (cond ((stringp dir-or-cache) - (car (last (dir-locals--all-files dir-or-cache)))) - ((consp dir-or-cache) ; result from cache - ;; If cache element has an mtime, assume it came - ;; from a file. Otherwise, assume it was set - ;; directly. - (if (nth 2 dir-or-cache) - (car (last (dir-locals--all-files (car dir-or-cache)))) - (cadr dir-or-cache))) - ;; Try to make a proper file-name. - (t (expand-file-name dir-locals-file)))) - variables) + (let ((variables-file (or (and (buffer-file-name) + (not (file-remote-p (buffer-file-name))) + (dir-locals-find-file (buffer-file-name))) + dir-locals-file)) + variables) + (if (consp variables-file) ; result from cache + ;; If cache element has an mtime, assume it came from a file. + ;; Otherwise, assume it was set directly. + (setq variables-file (if (nth 2 variables-file) + (expand-file-name dir-locals-file + (car variables-file)) + (cadr variables-file)))) ;; I can't be bothered to handle this case right now. ;; Dir locals were set directly from a class. You need to ;; directly modify the class in dir-locals-class-alist. diff --git a/lisp/files.el b/lisp/files.el index 92ae4344e1c..3898dff0383 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3663,7 +3663,7 @@ Return the new variables list." (error ;; The file's content might be invalid (e.g. have a merge conflict), but ;; that shouldn't prevent the user from opening the file. - (message "%s error: %s" dir-locals-file (error-message-string err)) + (message ".dir-locals error: %s" (error-message-string err)) nil)))) (defun dir-locals-set-directory-class (directory class &optional mtime) @@ -3715,41 +3715,8 @@ VARIABLES list of the class. The list is processed in order. (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.") - -(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 (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))) +It has to be constant to enforce uniform values +across different environments and users.") (defun dir-locals-find-file (file) "Find the directory-local variables for FILE. @@ -3764,93 +3731,78 @@ 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." +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." (setq file (expand-file-name file)) - (let* ((locals-dir (locate-dominating-file (file-name-directory file) - #'dir-locals--all-files)) - dir-elt) + (let* ((dir-locals-file-name + (if (eq system-type 'ms-dos) + (dosified-file-name dir-locals-file) + dir-locals-file)) + (locals-file (locate-dominating-file file dir-locals-file-name)) + (dir-elt nil)) ;; `locate-dominating-file' may have abbreviated the name. - (when locals-dir - (setq locals-dir (expand-file-name locals-dir))) + (and locals-file + (setq locals-file (expand-file-name dir-locals-file-name locals-file))) + ;; Let dir-locals-read-from-file inform us via demoted-errors + ;; about unreadable files, etc. + ;; Maybe we'd want to keep searching though - that is + ;; a locate-dominating-file issue. +;;; (or (not (file-readable-p locals-file)) +;;; (not (file-regular-p locals-file))) +;;; (setq locals-file nil)) ;; 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))) + (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-to-seconds (nth 2 dir-elt)) - (apply #'max (mapcar (lambda (f) (time-to-seconds (nth 5 (file-attributes f)))) - cached-files)))))) - ;; 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) + (or (null locals-file) + (<= (length (file-name-directory locals-file)) + (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-file (expand-file-name dir-locals-file-name + (car dir-elt)))) + (and (file-readable-p cached-file) + (equal (nth 2 dir-elt) + (nth 5 (file-attributes cached-file)))))) + ;; 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-file) ;; No cache entry. - 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* ((class-name (intern dir)) - (files (dir-locals--all-files dir)) - (read-circle nil) - (success nil) - (variables)) + locals-file))) + +(defun dir-locals-read-from-file (file) + "Load a variables FILE and register a new class and instance. +FILE is the name of the file holding the variables to apply. +The new class name is the same as the directory in which FILE +is found. Returns the new class name." + (with-temp-buffer (with-demoted-errors "Error reading dir-locals: %S" - (dolist (file files) - (with-temp-buffer - (insert-file-contents file) - (condition-case-unless-debug nil - (setq variables - (map-merge-with 'list (lambda (a b) (map-merge 'list a b)) - variables - (read (current-buffer)))) - (end-of-file nil)))) - (setq success t)) - (dir-locals-set-class-variables class-name variables) - (dir-locals-set-directory-class - dir class-name - (seconds-to-time - (if success - (apply #'max (mapcar (lambda (file) - (time-to-seconds (nth 5 (file-attributes file)))) - files)) - ;; If there was a problem, use the values we could get but - ;; don't let the cache prevent future reads. - 0))) - class-name)) - -(define-obsolete-function-alias 'dir-locals-read-from-file - 'dir-locals-read-from-dir "25.1") + (insert-file-contents file) + (unless (zerop (buffer-size)) + (let* ((dir-name (file-name-directory file)) + (class-name (intern dir-name)) + (variables (let ((read-circle nil)) + (read (current-buffer))))) + (dir-locals-set-class-variables class-name variables) + (dir-locals-set-directory-class dir-name class-name + (nth 5 (file-attributes file))) + class-name))))) (defcustom enable-remote-dir-locals nil "Non-nil means dir-local variables will be applied to remote files." @@ -3873,17 +3825,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 ((dir-or-cache (dir-locals-find-file - (or (buffer-file-name) default-directory))) + (let ((variables-file (dir-locals-find-file + (or (buffer-file-name) default-directory))) (class nil) (dir-name nil)) (cond - ((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)))) + ((stringp variables-file) + (setq dir-name (file-name-directory variables-file) + class (dir-locals-read-from-file variables-file))) + ((consp variables-file) + (setq dir-name (nth 0 variables-file)) + (setq class (nth 1 variables-file)))) (when class (let ((variables (dir-locals-collect-variables diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 2021885e996..547bc7ee63a 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -911,35 +911,29 @@ if it is given a local binding.\n")))) (buffer-file-name buffer))) (dir-locals-find-file (buffer-file-name buffer)))) - (is-directory nil)) + (dir-file t)) (princ (substitute-command-keys " This variable's value is directory-local")) - (when (consp file) ; result from cache - ;; If the cache element has an mtime, we - ;; assume it came from a file. - (if (nth 2 file) - ;; (car file) is a directory. - (setq file (dir-locals--all-files (car file))) - ;; Otherwise, assume it was set directly. - (setq file (car file) - is-directory t))) - (if (null file) - (princ ".\n") - (princ ", set ") - (princ (substitute-command-keys - (cond - (is-directory "for the directory\n `") - ;; Many files matched. - ((and (consp file) (cdr file)) - (setq file (file-name-directory (car file))) - (format "by one of the\n %s files in the directory\n `" - dir-locals-file)) - (t (setq file (car file)) - "by the file\n `")))) + (if (null file) + (princ ".\n") + (princ ", set ") + (if (consp file) ; result from cache + ;; If the cache element has an mtime, we + ;; assume it came from a file. + (if (nth 2 file) + (setq file (expand-file-name + dir-locals-file (car file))) + ;; Otherwise, assume it was set directly. + (setq file (car file) + dir-file nil))) + (princ (substitute-command-keys + (if dir-file + "by the file\n `" + "for the directory\n `"))) (with-current-buffer standard-output (insert-text-button file 'type 'help-dir-local-var-def - 'help-args (list variable file))) + 'help-args (list variable file))) (princ (substitute-command-keys "'.\n")))) (princ (substitute-command-keys " This variable's value is file-local.\n")))) -- 2.39.2