Subject: Re: bug#64088: [PATCH] Make project-root for vc projects return an absolute path

From: [email-masked]
Date: Sat, 19 Aug 2023 12:31:03 +0000 (UTC)

Dmitry Gutov <[email-masked]> writes:
> On 11/07/2023 02:45, Spencer Baugh wrote:
>> Dmitry Gutov <[email-masked]> writes:
>>> On 27/06/2023 23:01, Spencer Baugh wrote:
>>>> OK, how about this?
>>>
>>> Maybe we should go in the other direction? And call
>>> abbreviate-file-name on them?
>>>
>>> Because otherwise in project-prompt-project-dir we'll always show the
>>> expanded directory names, taking up extra space and usually repeating
>>> the full name of the user's home directory for no good reason.
>> That seems reasonable if we let-bind directory-abbrev-alist to nil
>> around it; otherwise we'll be dependent on the user's configuration and
>> we might add a directory in one way, and then they add a new value to
>> directory-abbrev-alist and we add it again a second way.
>
> That's also fair.
>
>> Although maybe that's fine?  And probably users of
>> directory-abbrev-alist would like to have those abbreviations show up in
>> project-prompt-project-dir.
>
> They probably would. But indeed if the list was saved with one
> configuration, and read with another, it could lead to a mistake.
>
>> Also we could always call abbreviate-file-name at
>> project-prompt-project-dir time.
>
> Meaning it will be called N times (for the number of projects) every
> time the list is displayed, instead of just once, when the project is
> saved/visited. But maybe it's fine too? How slow could that be?

I was sad about this but I think I've got the solution now: We just
maintain project--list in abbreviated form and project-list-file in
expanded form.

I think that solves all the problems: the persistent file is independent
of user configuration, so if the user changes their abbreviations
they'll get new ones the next time the file is read (presumably the next
time they run Emacs).  But project--list is abbreviated, so
project-prompt-project-dir gets abbreviated dirs.

It does mean that if they change their directory-abbrev-alist while
Emacs is running they could get duplicate entries, but that already
could happen before this patch, and it's not a big problem IMO.

See patch below.

>From 193a105b40b3a002f51e1f59dd2a3d48443e11fe Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Sat, 19 Aug 2023 08:24:45 -0400
Subject: [PATCH] Expand project file names before storing them

Before, whatever project-root returned, we stored as the root
directory of the project in project-list and project-list-file.  This
could lead to duplicate entries or bad behavior if projects were
accessed by different file names, e.g. both /home/user/src/emacs and
~/src/emacs.

Now project-list-file contains only expanded paths and project--list
contains only abbreviated paths.  We abbreviate filenames before
setting project--list, and expand filenames before writing to
project-list-file.

* lisp/progmodes/project.el (project--write-project-list): Call
expand-file-name.
(project--read-project-list, project-remember-project)
(project--remove-from-project-list): Call abbreviate-file-name.
---
 lisp/progmodes/project.el | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 11fa93fb70d..e99a9061275 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1586,7 +1586,7 @@ project--read-project-list
           (when (file-exists-p filename)
             (with-temp-buffer
               (insert-file-contents filename)
-              (read (current-buffer)))))
+              (mapcar #'abbreviate-file-name (read (current-buffer))))))
     (unless (seq-every-p
              (lambda (elt) (stringp (car-safe elt)))
              project--list)
@@ -1606,7 +1606,7 @@ project--write-project-list
       (insert ";;; -*- lisp-data -*-\n")
       (let ((print-length nil)
             (print-level nil))
-        (pp project--list (current-buffer)))
+        (pp (mapcar #'expand-file-name project--list) (current-buffer)))
       (write-region nil nil filename nil 'silent))))
 
 ;;;###autoload
@@ -1615,7 +1615,7 @@ project-remember-project
 Save the result in `project-list-file' if the list of projects
 has changed, and NO-WRITE is nil."
   (project--ensure-read-project-list)
-  (let ((dir (project-root pr)))
+  (let ((dir (abbreviate-file-name (project-root pr))))
     (unless (equal (caar project--list) dir)
       (dolist (ent project--list)
         (when (equal dir (car ent))
@@ -1631,7 +1631,7 @@ project--remove-from-project-list
 from the list using REPORT-MESSAGE, which is a format string
 passed to `message' as its first argument."
   (project--ensure-read-project-list)
-  (when-let ((ent (assoc project-root project--list)))
+  (when-let ((ent (assoc (abbreviate-file-name project-root) project--list)))
     (setq project--list (delq ent project--list))
     (message report-message project-root)
     (project--write-project-list)))
-- 
2.41.0