comparison lisp/files.el @ 102935:f57e672f2ca5

* 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.
author Chong Yidong <cyd@stupidchicken.com>
date Sat, 11 Apr 2009 15:26:26 +0000
parents fb16f3bdad15
children 64ac89a8b9a8
comparison
equal deleted inserted replaced
102934:ed0a00c1025a 102935:f57e672f2ca5
3183 (set (make-local-variable var) val)))) 3183 (set (make-local-variable var) val))))
3184 3184
3185 ;;; Handling directory-local variables, aka project settings. 3185 ;;; Handling directory-local variables, aka project settings.
3186 3186
3187 (defvar dir-locals-class-alist '() 3187 (defvar dir-locals-class-alist '()
3188 "Alist mapping class names (symbols) to variable lists.") 3188 "Alist mapping directory-local variable classes (symbols) to variable lists.")
3189 3189
3190 (defvar dir-locals-directory-alist '() 3190 (defvar dir-locals-directory-cache '()
3191 "Alist mapping directory roots to variable classes.") 3191 "List of cached directory roots for directory-local variable classes.
3192 Each element in this list has the form (DIR CLASS MTIME).
3193 DIR is the name of the directory.
3194 CLASS is the name of a variable class (a symbol).
3195 MTIME is the recorded modification time of the directory-local
3196 variables file associated with this entry. This time is a list
3197 of two integers (the same format as `file-attributes'), and is
3198 used to test whether the cache entry is still valid.
3199 Alternatively, MTIME can be nil, which means the entry is always
3200 considered valid.")
3192 3201
3193 (defsubst dir-locals-get-class-variables (class) 3202 (defsubst dir-locals-get-class-variables (class)
3194 "Return the variable list for CLASS." 3203 "Return the variable list for CLASS."
3195 (cdr (assq class dir-locals-class-alist))) 3204 (cdr (assq class dir-locals-class-alist)))
3196 3205
3228 ((or (not key) 3237 ((or (not key)
3229 (derived-mode-p key)) 3238 (derived-mode-p key))
3230 (setq variables (dir-locals-collect-mode-variables 3239 (setq variables (dir-locals-collect-mode-variables
3231 (cdr entry) variables)))))))) 3240 (cdr entry) variables))))))))
3232 3241
3233 (defun dir-locals-set-directory-class (directory class) 3242 (defun dir-locals-set-directory-class (directory class mtime)
3234 "Declare that the DIRECTORY root is an instance of CLASS. 3243 "Declare that the DIRECTORY root is an instance of CLASS.
3235 DIRECTORY is the name of a directory, a string. 3244 DIRECTORY is the name of a directory, a string.
3236 CLASS is the name of a project class, a symbol. 3245 CLASS is the name of a project class, a symbol.
3246 MTIME is either the modification time of the directory-local
3247 variables file that defined this this class, or nil.
3237 3248
3238 When a file beneath DIRECTORY is visited, the mode-specific 3249 When a file beneath DIRECTORY is visited, the mode-specific
3239 variables from CLASS will be applied to the buffer. The variables 3250 variables from CLASS are applied to the buffer. The variables
3240 for a class are defined using `dir-locals-set-class-variables'." 3251 for a class are defined using `dir-locals-set-class-variables'."
3241 (setq directory (file-name-as-directory (expand-file-name directory))) 3252 (setq directory (file-name-as-directory (expand-file-name directory)))
3242 (unless (assq class dir-locals-class-alist) 3253 (unless (assq class dir-locals-class-alist)
3243 (error "No such class `%s'" (symbol-name class))) 3254 (error "No such class `%s'" (symbol-name class)))
3244 (push (cons directory class) dir-locals-directory-alist)) 3255 (push (list directory class mtime) dir-locals-directory-cache))
3245 3256
3246 (defun dir-locals-set-class-variables (class variables) 3257 (defun dir-locals-set-class-variables (class variables)
3247 "Map the type CLASS to a list of variable settings. 3258 "Map the type CLASS to a list of variable settings.
3248 CLASS is the project class, a symbol. VARIABLES is a list 3259 CLASS is the project class, a symbol. VARIABLES is a list
3249 that declares directory-local variables for the class. 3260 that declares directory-local variables for the class.
3282 "File that contains directory-local variables. 3293 "File that contains directory-local variables.
3283 It has to be constant to enforce uniform values 3294 It has to be constant to enforce uniform values
3284 across different environments and users.") 3295 across different environments and users.")
3285 3296
3286 (defun dir-locals-find-file (file) 3297 (defun dir-locals-find-file (file)
3287 "Find the directory-local variables FILE. 3298 "Find the directory-local variables for FILE.
3288 This searches upward in the directory tree. 3299 This searches upward in the directory tree from FILE.
3289 If a local variables file is found, the file name is returned. 3300 If the directory root of FILE has been registered in
3290 If the file is already registered, a cons from 3301 `dir-locals-directory-cache' and the directory-local variables
3291 `dir-locals-directory-alist' is returned. 3302 file has not been modified, return the matching entry in
3292 Otherwise this returns nil." 3303 `dir-locals-directory-cache'.
3304 Otherwise, if a directory-local variables file is found, return
3305 the file name.
3306 Otherwise, return nil."
3293 (setq file (expand-file-name file)) 3307 (setq file (expand-file-name file))
3294 (let* ((dir-locals-file-name 3308 (let* ((dir-locals-file-name
3295 (if (eq system-type 'ms-dos) 3309 (if (eq system-type 'ms-dos)
3296 (dosified-file-name dir-locals-file) 3310 (dosified-file-name dir-locals-file)
3297 dir-locals-file)) 3311 dir-locals-file))
3298 (locals-file (locate-dominating-file file dir-locals-file-name)) 3312 (locals-file (locate-dominating-file file dir-locals-file-name))
3299 (dir-elt nil)) 3313 (dir-elt nil))
3300 ;; `locate-dominating-file' may have abbreviated the name. 3314 ;; `locate-dominating-file' may have abbreviated the name.
3301 (when locals-file 3315 (when locals-file
3302 (setq locals-file (expand-file-name dir-locals-file-name locals-file))) 3316 (setq locals-file (expand-file-name dir-locals-file-name locals-file)))
3303 (dolist (elt dir-locals-directory-alist) 3317 ;; Find the best cached value in `dir-locals-directory-cache'.
3318 (dolist (elt dir-locals-directory-cache)
3304 (when (and (eq t (compare-strings file nil (length (car elt)) 3319 (when (and (eq t (compare-strings file nil (length (car elt))
3305 (car elt) nil nil 3320 (car elt) nil nil
3306 (memq system-type 3321 (memq system-type
3307 '(windows-nt cygwin ms-dos)))) 3322 '(windows-nt cygwin ms-dos))))
3308 (> (length (car elt)) (length (car dir-elt)))) 3323 (> (length (car elt)) (length (car dir-elt))))
3309 (setq dir-elt elt))) 3324 (setq dir-elt elt)))
3310 (if (and locals-file dir-elt) 3325 (let ((use-cache (and dir-elt
3311 (if (> (length (file-name-directory locals-file)) 3326 (or (null locals-file)
3312 (length (car dir-elt))) 3327 (<= (length (file-name-directory locals-file))
3313 locals-file 3328 (length (car dir-elt)))))))
3314 dir-elt) 3329 (if use-cache
3315 (or locals-file dir-elt)))) 3330 ;; Check the validity of the cache.
3331 (if (and (file-readable-p (car dir-elt))
3332 (or (null (nth 2 dir-elt))
3333 (equal (nth 2 dir-elt)
3334 (nth 5 (file-attributes (car dir-elt))))))
3335 ;; This cache entry is OK.
3336 dir-elt
3337 ;; This cache entry is invalid; clear it.
3338 (setq dir-locals-directory-cache
3339 (delq dir-elt dir-locals-directory-cache))
3340 locals-file)
3341 locals-file))))
3316 3342
3317 (defun dir-locals-read-from-file (file) 3343 (defun dir-locals-read-from-file (file)
3318 "Load a variables FILE and register a new class and instance. 3344 "Load a variables FILE and register a new class and instance.
3319 FILE is the name of the file holding the variables to apply. 3345 FILE is the name of the file holding the variables to apply.
3320 The new class name is the same as the directory in which FILE 3346 The new class name is the same as the directory in which FILE
3321 is found. Returns the new class name." 3347 is found. Returns the new class name."
3322 (with-temp-buffer 3348 (with-temp-buffer
3323 ;; We should probably store the modtime of FILE and then
3324 ;; reload it whenever it changes.
3325 (insert-file-contents file) 3349 (insert-file-contents file)
3326 (let* ((dir-name (file-name-directory file)) 3350 (let* ((dir-name (file-name-directory file))
3327 (class-name (intern dir-name)) 3351 (class-name (intern dir-name))
3328 (variables (read (current-buffer)))) 3352 (variables (read (current-buffer))))
3329 (dir-locals-set-class-variables class-name variables) 3353 (dir-locals-set-class-variables class-name variables)
3330 (dir-locals-set-directory-class dir-name class-name) 3354 (dir-locals-set-directory-class dir-name class-name
3355 (nth 5 (file-attributes file)))
3331 class-name))) 3356 class-name)))
3332 3357
3333 (declare-function c-postprocess-file-styles "cc-mode" ()) 3358 (declare-function c-postprocess-file-styles "cc-mode" ())
3334 3359
3335 (defun hack-dir-local-variables () 3360 (defun hack-dir-local-variables ()
3346 (cond 3371 (cond
3347 ((stringp variables-file) 3372 ((stringp variables-file)
3348 (setq dir-name (file-name-directory (buffer-file-name))) 3373 (setq dir-name (file-name-directory (buffer-file-name)))
3349 (setq class (dir-locals-read-from-file variables-file))) 3374 (setq class (dir-locals-read-from-file variables-file)))
3350 ((consp variables-file) 3375 ((consp variables-file)
3351 (setq dir-name (car variables-file)) 3376 (setq dir-name (nth 0 variables-file))
3352 (setq class (cdr variables-file)))) 3377 (setq class (nth 1 variables-file))))
3353 (when class 3378 (when class
3354 (let ((variables 3379 (let ((variables
3355 (dir-locals-collect-variables 3380 (dir-locals-collect-variables
3356 (dir-locals-get-class-variables class) dir-name nil))) 3381 (dir-locals-get-class-variables class) dir-name nil)))
3357 (when variables 3382 (when variables