]> git.eshelyaron.com Git - emacs.git/commitdiff
project--files-in-directory: Fix handling of ignores
authorDmitry Gutov <dgutov@yandex.ru>
Mon, 6 Sep 2021 02:01:07 +0000 (05:01 +0300)
committerDmitry Gutov <dgutov@yandex.ru>
Mon, 6 Sep 2021 02:01:07 +0000 (05:01 +0300)
* lisp/progmodes/project.el (project--files-in-directory):
Pass "." as the DIR argument to 'find' because otherwise the ignore
expression can match the project root directory name, which we don't
want to happen (bug#50240).  Fixup the resulting file names at the end
with concatenation.
Originally I thought it could lead to worse performance, but the
results show equal or slightly better timings.

* lisp/progmodes/xref.el (xref-matches-in-directory):
Apply a similar fix.
(xref--find-ignores-arguments): Use file-name-as-directory, so
that when passed "." replace-match still had the expected effect.

* test/lisp/progmodes/project-tests.el (project-ignores-bug-50240):
New test.

* test/lisp/progmodes/xref-tests.el
(xref-matches-in-directory-filters-with-ignores): New test.

lisp/progmodes/project.el
lisp/progmodes/xref.el
test/lisp/progmodes/project-tests.el
test/lisp/progmodes/xref-tests.el

index e420a4ccca7c9e4a7a759c0e5a6b2e7517019d9f..b6eea7e27e475d73688e07f25bd26a962e1c38d4 100644 (file)
@@ -302,11 +302,10 @@ to find the list of ignores for each directory."
          ;; expanded and not left for the shell command
          ;; to interpret.
          (localdir (file-name-unquote (file-local-name (expand-file-name dir))))
-         (command (format "%s -H %s %s -type f %s -print0"
+         (dfn (directory-file-name localdir))
+         (command (format "%s -H . %s -type f %s -print0"
                           find-program
-                          (shell-quote-argument
-                           (directory-file-name localdir)) ; Bug#48471
-                          (xref--find-ignores-arguments ignores localdir)
+                          (xref--find-ignores-arguments ignores "./")
                           (if files
                               (concat (shell-quote-argument "(")
                                       " " find-name-arg " "
@@ -324,8 +323,9 @@ to find the list of ignores for each directory."
                        (unless (zerop status)
                          (error "File listing failed: %s" (buffer-string))))))))
     (project--remote-file-names
-     (sort (split-string output "\0" t)
-           #'string<))))
+     (mapcar (lambda (s) (concat dfn (substring s 1)))
+             (sort (split-string output "\0" t)
+                   #'string<)))))
 
 (defun project--remote-file-names (local-files)
   "Return LOCAL-FILES as if they were on the system of `default-directory'.
index e594624573bee69ba41e2d5c2fb3ba8cdf98a0e2..ec8b05d2943e1df5e6986db63b65dedca392495c 100644 (file)
@@ -1553,18 +1553,18 @@ IGNORES is a list of glob patterns for files to ignore."
        ;; do that reliably enough, without creating false negatives?
        (command (xref--rgrep-command (xref--regexp-to-extended regexp)
                                      files
-                                     (directory-file-name
-                                      (file-name-unquote
-                                       (file-local-name (expand-file-name dir))))
+                                     "."
                                      ignores))
-       (def default-directory)
+       (local-dir (directory-file-name
+                   (file-name-unquote
+                    (file-local-name (expand-file-name dir)))))
        (buf (get-buffer-create " *xref-grep*"))
        (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
        (status nil)
        (hits nil))
     (with-current-buffer buf
       (erase-buffer)
-      (setq default-directory def)
+      (setq default-directory dir)
       (setq status
             (process-file-shell-command command nil t))
       (goto-char (point-min))
@@ -1577,7 +1577,7 @@ IGNORES is a list of glob patterns for files to ignore."
         (user-error "Search failed with status %d: %s" status (buffer-string)))
       (while (re-search-forward grep-re nil t)
         (push (list (string-to-number (match-string line-group))
-                    (match-string file-group)
+                    (concat local-dir (substring (match-string file-group) 1))
                     (buffer-substring-no-properties (point) (line-end-position)))
               hits)))
     (xref--convert-hits (nreverse hits) regexp)))
@@ -1746,6 +1746,11 @@ directory, used as the root of the ignore globs."
   (cl-assert (not (string-match-p "\\`~" dir)))
   (if (not ignores)
       ""
+    ;; TODO: All in-tree callers are passing in just "." or "./".
+    ;; We can simplify.
+    ;; And, if we ever end up deleting xref-matches-in-directory, move
+    ;; this function to the project package.
+    (setq dir (file-name-as-directory dir))
     (concat
      (shell-quote-argument "(")
      " -path "
index 68460a9fa5bddae9542f4b6e1f7789c0b5e7cdcf..1e3f258ac2a2d0fb7752101a022d1081650d64ce 100644 (file)
@@ -107,4 +107,19 @@ directory name (Bug#48471)."
                      collect (file-relative-name file dir))))
       (should (equal relative-files '("some-file"))))))
 
+(ert-deftest project-ignores-bug-50240 ()
+  "Check that `project-files' does not ignore all files.
+When `project-ignores' includes a name matching project dir."
+  (skip-unless (executable-find find-program))
+  (project-tests--with-temporary-directory dir
+    (make-empty-file (expand-file-name "some-file" dir))
+    (let* ((project (make-project-tests--trivial
+                     :root (file-name-as-directory dir)
+                     :ignores (list (file-name-nondirectory
+                                     (directory-file-name dir)))))
+           (files (project-files project)))
+      (should (equal files
+                     (list
+                      (expand-file-name "some-file" dir)))))))
+
 ;;; project-tests.el ends here
index d29452243b2bca124a0ba62e13ee789146b295a1..ff4b647ae0f50935eeae1259dc9b48ad9154d39f 100644 (file)
     (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 0 locs))))
     (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 1 locs))))))
 
+(ert-deftest xref-matches-in-directory-filters-with-ignores ()
+  (let ((locs (xref-matches-in-directory "bar" "*" xref-tests--data-dir
+                                         '("./file1.*"))))
+    (should (= 1 (length locs)))
+    (should (string-match-p "file2\\.txt\\'" (xref-location-group
+                                              (xref-item-location
+                                               (nth 0 locs)))))))
+
 (ert-deftest xref-matches-in-directory-finds-two-matches-on-the-same-line ()
   (let ((locs (xref-tests--locations-in-data-dir "foo")))
     (should (= 2 (length locs)))