From 5f45fc7ee24d025a6292bca82c4eed556be76e77 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Wed, 2 Dec 2020 04:28:35 +0200 Subject: [PATCH] Improve .gitignore and project-vc-ignores handling * lisp/progmodes/project.el (project-ignores): Convert .gitignore entries more faithfully. (project--vc-list-files): Convert "our" ignore entries to "proper" globs, which is what Git pathspec requires. --- lisp/progmodes/project.el | 51 +++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index fd4c256e97d..449eadc3de7 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -322,7 +322,7 @@ to find the list of ignores for each directory." :group 'project) (defcustom project-vc-ignores nil - "List of patterns to include in `project-ignores'." + "List of patterns to add to `project-ignores'." :type '(repeat string) :safe #'listp) @@ -468,9 +468,26 @@ backend implementation of `project-external-roots'.") (cons "--" (mapcar (lambda (i) - (if (string-match "\\./" i) - (format ":!/:%s" (substring i 2)) - (format ":!:%s" i))) + (format + ":(exclude,glob,top)%s" + (if (string-match "\\*\\*" i) + ;; Looks like pathspec glob + ;; format already. + i + (if (string-match "\\./" i) + ;; ./abc -> abc + (setq i (substring i 2)) + ;; abc -> **/abc + (setq i (concat "**/" i)) + ;; FIXME: '**/abc' should also + ;; match a directory with that + ;; name, but doesn't (git 2.25.1). + ;; Maybe we should replace + ;; such entries with two. + (if (string-match "/\\'" i) + ;; abc/ -> abc/** + (setq i (concat i "**")))) + i))) extra-ignores))))) (setq files (mapcar @@ -535,12 +552,26 @@ backend implementation of `project-external-roots'.") (append (when (file-equal-p dir root) (setq backend (vc-responsible-backend root)) - (mapcar - (lambda (entry) - (if (string-match "\\`/" entry) - (replace-match "./" t t entry) - entry)) - (vc-call-backend backend 'ignore-completion-table root))) + (delq + nil + (mapcar + (lambda (entry) + (cond + ((eq ?! (aref entry 0)) + ;; No support for whitelisting (yet). + nil) + ((string-match "\\(/\\)[^/]" entry) + ;; FIXME: This seems to be Git-specific. + ;; And / in the entry (start or even the middle) means + ;; the pattern is "rooted". Or actually it is then + ;; relative to its respective .gitignore (of which there + ;; could be several), but we only support .gitignore at + ;; the root. + (if (= (match-beginning 0) 0) + (replace-match "./" t t entry 1) + (concat "./" entry))) + (t entry))) + (vc-call-backend backend 'ignore-completion-table root)))) (project--value-in-dir 'project-vc-ignores root) (mapcar (lambda (dir) -- 2.39.5