;; Port this functionality back from Emacs 23 since it's Really Useful (unless (functionp 'locate-dominating-file) (defun locate-dominating-file (file name) "Look up the directory hierarchy from FILE for a file named NAME. Stop at the first parent directory containing a file NAME, and return the directory. Return nil if not found." ;; We used to use the above locate-dominating-files code, but the ;; directory-files call is very costly, so we're much better off doing ;; multiple calls using the code in here. ;; ;; Represent /home/luser/foo as ~/foo so that we don't try to look for ;; `name' 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) ;; FIXME: Disabled this heuristic because it is sometimes ;; inappropriate. ;; 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 locate-dominating-stop-dir-regexp 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)))) root)) (defvar locate-dominating-stop-dir-regexp "\\`\\(?:[\\/][\\/][^\\/]+\\|/\\(?:net\\|afs\\|\\.\\.\\.\\)/\\)\\'")) (provide 'dominating-file)