Subject: bug#65704: 29.1; Most code of `project-ignores' seems to be dead code

From: Dmitry Gutov <[email-masked]>
Date: Mon, 4 Sep 2023 21:30:01 +0300

On 04/09/2023 19:03, Damien Cassou wrote:
> Dmitry Gutov <[email-masked]> writes:
>> much. Maybe just that that code path isn't exercised by any in-tree
>> function if the backend is Git (with recent enough git installed)
> 
> My Git repository has several .gitignore files in several directories,
> something that `project-ignores' (for VC) seems to not support:
> 
>      ;; we only support .gitignore at the root.

Yes. That's not really the fault of project-vc's implementation, but the 
way vc-default-ignore-completion-table and vc-git-find-ignore-file are 
implemented. But again, it shouldn't be a problem for most users/uses.

> My project looks like this:
> 
> .
> ├── client
> │   ├── .gitignore
> │   ├── node_modules
> │   └── .project
> ├── .git
> └── .gitignore
> 
> Because I spend most of my time in the client/ directory, I want the
> `project' library to consider client/ to be a project on its own. I use
> the code below and the client/.project file to do this:

Also an aside: you could add ".project" or ".gitignore" to 
project-vc-extra-root-markers if your project.el is recent enough (e.g. 
from Emacs 29).

>      (defconst my/project-root-marker ".project"
>        "File indicating the root of a project.")
> 
>      (defun my/project-find-root (path)
>        "Search up the PATH for `my/project-root-marker'."
>        (when-let* ((root (locate-dominating-file path my/project-root-marker)))
>          (cons 'transient root)))
> 
>      (add-to-list 'project-find-functions #'my/project-find-root)
> 
> The client/.gitignore file contains a line "node_modules/" which is a
> very large directory. The command `project-find-file' doesn't see my
> client/.gitignore and thus suggests 83k files and make the completion UI
> very slow.

The above customization going against the general recommendation in 
project.el's Commentary and ends up with Emacs detecting an instance of 
a different backend: 'transient'. Which doesn't have a dedicaded 
definition for project-ignores and falls back to the default one (lines 
292:307). Naturally, it doesn't scan for ignore files in any VC backend.

That's the reason I've added project-vc-extra-root-markers: so that 
honoring files like .gitignore still makes sense, but the user can split 
the project into pieces using these markers while keeping the same 
backend in use.

> So I'm not using it but this instead:
> 
>    (project-find-file-in (thing-at-point 'filename)
>                          (list "/my/project/client")
>                          (project-current nil "/my/project"))
> 
> The function `project-find-file-in' uses `project-files' which in turn
> uses `project--dir-ignores'.

Just keep in mind that 'project-files' also has two definition in core 
(and however many outside of it): one default that always calls 
project--dir-ignores, and one for 'vc' (lines 609:629) that only calls 
project--dir-ignores in fallback situations (backend is not Git or Hg, 
or when Git is older than 1.9, or when DIR is not the project root). The 
last case might still be reconsidered, but it works for 'C-u M-x 
project-find-regexp' when you want to search inside an ignored dir 
(fully or partially).

> Am I doing something reasonable? Is there a better way? It looks like a
> lot of setup to get Emacs to ignore directories listed .gitignore files.

To reiterate: use 'project-vc-extra-root-markers'.

And the nested .gitignore should also use used automatically without 
that too by 'C-x p f' if you remove #'my/project-find-root from 
project-find-functions.

Anyway, thank you for the explanation, it's valuable feedback.

If anything is unclear, further question welcome.