# HG changeset patch # User Chong Yidong # Date 1239463586 0 # Node ID f57e672f2ca5acf7930faea5cb28b80e891fa9c4 # Parent ed0a00c1025ae6b5dc94b6b8592a1ae2f2bf7626 * files.el (dir-locals-directory-cache): Change format to include the mtime of the directory-local variables file (Bug#2833). (dir-locals-set-directory-class): New arg mtime. Store it in dir-locals-directory-cache. (dir-locals-find-file): Check cache validity using the mtime. (dir-locals-read-from-file): Save the file mtime in the cache. (hack-dir-local-variables): Adapt to new dir-locals-directory-cache entry format. diff -r ed0a00c1025a -r f57e672f2ca5 lisp/ChangeLog --- a/lisp/ChangeLog Sat Apr 11 14:44:16 2009 +0000 +++ b/lisp/ChangeLog Sat Apr 11 15:26:26 2009 +0000 @@ -1,5 +1,14 @@ 2009-04-11 Chong Yidong + * files.el (dir-locals-directory-cache): Change format to include + the mtime of the directory-local variables file (Bug#2833). + (dir-locals-set-directory-class): New arg mtime. Store it in + dir-locals-directory-cache. + (dir-locals-find-file): Check cache validity using the mtime. + (dir-locals-read-from-file): Save the file mtime in the cache. + (hack-dir-local-variables): Adapt to new + dir-locals-directory-cache entry format. + * international/mule-diag.el (describe-font-internal): Change ignored argument to IGNORED. (describe-font): Elide unnecessary argument to diff -r ed0a00c1025a -r f57e672f2ca5 lisp/files.el --- a/lisp/files.el Sat Apr 11 14:44:16 2009 +0000 +++ b/lisp/files.el Sat Apr 11 15:26:26 2009 +0000 @@ -3185,10 +3185,19 @@ ;;; Handling directory-local variables, aka project settings. (defvar dir-locals-class-alist '() - "Alist mapping class names (symbols) to variable lists.") - -(defvar dir-locals-directory-alist '() - "Alist mapping directory roots to variable classes.") + "Alist mapping directory-local variable classes (symbols) to variable lists.") + +(defvar dir-locals-directory-cache '() + "List of cached directory roots for directory-local variable classes. +Each element in this list has the form (DIR CLASS MTIME). +DIR is the name of the directory. +CLASS is the name of a variable class (a symbol). +MTIME is the recorded modification time of the directory-local + variables file associated with this entry. This time is a list + of two integers (the same format as `file-attributes'), and is + used to test whether the cache entry is still valid. + Alternatively, MTIME can be nil, which means the entry is always + considered valid.") (defsubst dir-locals-get-class-variables (class) "Return the variable list for CLASS." @@ -3230,18 +3239,20 @@ (setq variables (dir-locals-collect-mode-variables (cdr entry) variables)))))))) -(defun dir-locals-set-directory-class (directory class) +(defun dir-locals-set-directory-class (directory class mtime) "Declare that the DIRECTORY root is an instance of CLASS. DIRECTORY is the name of a directory, a string. CLASS is the name of a project class, a symbol. +MTIME is either the modification time of the directory-local +variables file that defined this this class, or nil. When a file beneath DIRECTORY is visited, the mode-specific -variables from CLASS will be applied to the buffer. The variables +variables from CLASS are applied to the buffer. The variables for a class are defined using `dir-locals-set-class-variables'." (setq directory (file-name-as-directory (expand-file-name directory))) (unless (assq class dir-locals-class-alist) (error "No such class `%s'" (symbol-name class))) - (push (cons directory class) dir-locals-directory-alist)) + (push (list directory class mtime) dir-locals-directory-cache)) (defun dir-locals-set-class-variables (class variables) "Map the type CLASS to a list of variable settings. @@ -3284,12 +3295,15 @@ across different environments and users.") (defun dir-locals-find-file (file) - "Find the directory-local variables FILE. -This searches upward in the directory tree. -If a local variables file is found, the file name is returned. -If the file is already registered, a cons from -`dir-locals-directory-alist' is returned. -Otherwise this returns nil." + "Find the directory-local variables for FILE. +This searches upward in the directory tree from FILE. +If the directory root of FILE has been registered in + `dir-locals-directory-cache' and the directory-local variables + file has not been modified, return the matching entry in + `dir-locals-directory-cache'. +Otherwise, if a directory-local variables file is found, return + the file name. +Otherwise, return nil." (setq file (expand-file-name file)) (let* ((dir-locals-file-name (if (eq system-type 'ms-dos) @@ -3300,19 +3314,31 @@ ;; `locate-dominating-file' may have abbreviated the name. (when locals-file (setq locals-file (expand-file-name dir-locals-file-name locals-file))) - (dolist (elt dir-locals-directory-alist) + ;; Find the best cached value in `dir-locals-directory-cache'. + (dolist (elt dir-locals-directory-cache) (when (and (eq t (compare-strings file nil (length (car elt)) (car elt) nil nil (memq system-type '(windows-nt cygwin ms-dos)))) (> (length (car elt)) (length (car dir-elt)))) (setq dir-elt elt))) - (if (and locals-file dir-elt) - (if (> (length (file-name-directory locals-file)) - (length (car dir-elt))) - locals-file - dir-elt) - (or locals-file dir-elt)))) + (let ((use-cache (and dir-elt + (or (null locals-file) + (<= (length (file-name-directory locals-file)) + (length (car dir-elt))))))) + (if use-cache + ;; Check the validity of the cache. + (if (and (file-readable-p (car dir-elt)) + (or (null (nth 2 dir-elt)) + (equal (nth 2 dir-elt) + (nth 5 (file-attributes (car dir-elt)))))) + ;; 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)) + locals-file) + locals-file)))) (defun dir-locals-read-from-file (file) "Load a variables FILE and register a new class and instance. @@ -3320,14 +3346,13 @@ The new class name is the same as the directory in which FILE is found. Returns the new class name." (with-temp-buffer - ;; We should probably store the modtime of FILE and then - ;; reload it whenever it changes. (insert-file-contents file) (let* ((dir-name (file-name-directory file)) (class-name (intern dir-name)) (variables (read (current-buffer)))) (dir-locals-set-class-variables class-name variables) - (dir-locals-set-directory-class dir-name class-name) + (dir-locals-set-directory-class dir-name class-name + (nth 5 (file-attributes file))) class-name))) (declare-function c-postprocess-file-styles "cc-mode" ()) @@ -3348,8 +3373,8 @@ (setq dir-name (file-name-directory (buffer-file-name))) (setq class (dir-locals-read-from-file variables-file))) ((consp variables-file) - (setq dir-name (car variables-file)) - (setq class (cdr variables-file)))) + (setq dir-name (nth 0 variables-file)) + (setq class (nth 1 variables-file)))) (when class (let ((variables (dir-locals-collect-variables