Index: lisp/files.el =================================================================== RCS file: /sources/emacs/emacs/lisp/files.el,v retrieving revision 1.1005 diff -U 8 -r1.1005 files.el --- lisp/files.el 18 Oct 2008 18:40:25 -0000 1.1005 +++ lisp/files.el 24 Oct 2008 23:37:19 -0000 @@ -711,18 +711,59 @@ (defun locate-file-completion (string path-and-suffixes action) "Do completion for file names passed to `locate-file'. PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)." (locate-file-completion-table (car path-and-suffixes) (cdr path-and-suffixes) string nil action)) (make-obsolete 'locate-file-completion 'locate-file-completion-table "23.1") -(defun locate-dominating-file (file regexp) - "Look up the directory hierarchy from FILE for a file matching REGEXP." +(defun locate-dominating-file (file name) + "Look up the directory hierarchy from FILE for a file named NAME. +If found, return the file named NAME's full name and path, otherwise +return nil. See locate-dominating-file-by-regexp if you have more +complex requirements than a simple whole-string match on the name, +though beware it is slower." + ;; copied from vc-find-root, then changed to return file + ;; rather than containing dir. + ;; Represent /home/luser/foo as ~/foo so that we don't try to look for + ;; witnesses in /home or in /. + (setq file (abbreviate-file-name file)) + (let ((root nil) + (prev-file file) + ;; `user' is not initialized outside the loop because + ;; `file' may not exist, so we may have to walk up part of the + ;; hierarchy before we find the "initial UID". + (user nil) + try) + (while (not (or root + (null file) + ;; As a heuristic, we stop looking up the hierarchy of + ;; directories as soon as we find a directory belonging + ;; to another user. This should save us from looking in + ;; things like /net and /afs. This assumes that all the + ;; files inside a project belong to the same user. + (let ((prev-user user)) + (setq user (nth 2 (file-attributes file))) + (and prev-user (not (equal user prev-user)))) + (string-match + ;; from vc-ignore-dir-regexp ! + "\\`\\(?:[\\/][\\/]\\|/\\(?:net\\|afs\\|\\.\\.\\.\\)/\\)\\'" + file))) + (setq try (file-exists-p (expand-file-name name file))) + (cond (try (setq root file)) + ((equal file (setq prev-file file + file (file-name-directory + (directory-file-name file)))) + (setq file nil)))) + (when root (expand-file-name name root)))) + +(defun locate-dominating-file-by-regexp (file regexp) + "Look up the directory hierarchy from FILE for a file matching REGEXP. +This function is slower than `locate-dominating-file', only use if necessary." (catch 'found ;; `user' is not initialized yet because `file' may not exist, so we may ;; have to walk up part of the hierarchy before we find the "initial UID". (let ((user nil) ;; Abbreviate, so as to stop when we cross ~/. (dir (abbreviate-file-name (file-name-as-directory file))) files) (while (and dir @@ -3154,17 +3195,17 @@ (defun project-find-settings-file (file) "Find the settings file for FILE. This searches upward in the directory tree. If a settings file is found, the file name is returned. If the file is in a registered project, a cons from `project-directory-alist' is returned. Otherwise this returns nil." (setq file (expand-file-name file)) - (let* ((settings (locate-dominating-file file "\\`\\.dir-settings\\.el\\'")) + (let* ((settings (locate-dominating-file file ".dir-settings.el")) (pda nil)) ;; `locate-dominating-file' may have abbreviated the name. (if settings (setq settings (expand-file-name settings))) (dolist (x project-directory-alist) (when (and (eq t (compare-strings file nil (length (car x)) (car x) nil nil)) (> (length (car x)) (length (car pda)))) (setq pda x)))