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.
This commit is contained in:
Artur Malabarba 2016-01-30 16:14:52 +00:00
parent ae26c8a7a4
commit 71b20b31c8
5 changed files with 105 additions and 173 deletions

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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)))
locals-file)))
(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))
(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

View file

@ -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"))))