emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: locate-dominating-file calls `stat' too eagerly


From: Eli Zaretskii
Subject: Re: locate-dominating-file calls `stat' too eagerly
Date: Mon, 29 Sep 2008 17:36:53 +0300

> From: Stefan Monnier <address@hidden>
> Cc: address@hidden
> Date: Mon, 29 Sep 2008 10:06:54 -0400
> 
> Wouldn't it be simpler to wrap the `directroy-files' call inside
> a condition-case and drop the file-directory-p altogether?

That would work as well, but I'm not sure about the ``simpler'' part.
The code is already pretty convoluted, and I'm not sure why.  All it
needs to do is (1) to find an existing parent directory of its
argument FILE by chopping directories from the end until it finds an
existing one, and (2) go up the tree of existing directories until it
finds one whose owner is different.  This looks like 2 separate loops
to me, but the code for some reason insists on doing it in a single
loop.

How about this:

(defun locate-dominating-file (file regexp)
  "Look up the directory hierarchy from FILE for a file matching REGEXP."
  ;; If FILE does not exist, find its parent directory that does.
  (or (file-exists-p file)
      (while (and file (not (file-directory-p file)))
        (setq file (file-name-directory (directory-file-name file)))))
  (catch 'found
    (let ((user (nth 2 (file-attributes file)))
          ;; Abbreviate, so as to stop when we cross ~/.
          (dir (abbreviate-file-name (file-name-as-directory file)))
          files)
      (while (and dir
                  ;; 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 dir)))
                    (equal user prev-user)))
        (if (setq files (directory-files dir 'full regexp))
            (throw 'found (car files))
          (if (equal dir
                     (setq dir (file-name-directory
                                (directory-file-name dir))))
              (setq dir nil))))
      nil)))

And btw, won't the user test cover the case of crossing ~/ as well?
If so, we don't need to abbreviate-file-name, which then incurs
further overhead inside expand-file-name.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]