Subject: bug#58784: 28.2; project-buffers incorrect under let-bound default-directory

From: Sean Devlin <[email-masked]>
Date: Tue, 25 Oct 2022 20:13:36 -0400

Hi folks,

The project.el function project-buffers can return incorrect results
when invoked while a let-binding for default-directory is in
effect. This is because project-buffers (both the default and vc-based
implementations) does its work by inspecting the local value of
default-directory in each buffer, and the let-binding temporarily
affects this value.

To see this in action, start emacs with -Q and evaluate the following
forms in order:

(require 'project)

(find-file-noselect "/tmp/tmpfile")
(setq my-project '(transient . "/tmp/"))

;; just the tmpfile
(project-buffers my-project)

;; both tmpfile and scratch
(let ((default-directory "/tmp/"))
  (project-buffers my-project))

In the last form, project-buffers includes the current buffer (i.e. the
scratch buffer in our example) with the results. (This is true even if
the current buffer is visiting a file in some unrelated directory.)

This matters because the command project-switch-project let-binds
default-directory before calling project-switch-commands. This means
that if you set project-switch-commands to some function that calls
project-buffers, you will get incorrect results.

For example, evaluate the following forms in order:

(defun my-list-project-buffers ()
  "List the current project's buffers."
  (interactive)
  (let ((buffer-list (project-buffers (project-current t)))
	(buffer-name (project-prefixed-buffer-name "my-project-buffer-list")))
    (with-current-buffer (get-buffer-create buffer-name)
      (erase-buffer)
      (save-excursion
	(dolist (buffer buffer-list)
	  (insert (buffer-name buffer))
	  (insert ?\n))))
    (switch-to-buffer buffer-name)))

(setq project-switch-commands #'my-list-project-buffers)

;; list tmpfile but also scratch
(project-switch-project "/tmp/")

In GNU Emacs 28.2
System Description:  macOS

Configured using:
'configure --disable-silent-rules
--enable-locallisppath=/opt/homebrew/share/emacs/site-lisp
--infodir=/opt/homebrew/Cellar/emacs/28.2/share/info/emacs
--prefix=/opt/homebrew/Cellar/emacs/28.2 --with-gnutls --without-x
--with-xml2 --without-dbus --with-modules --without-ns
--without-imagemagick --without-selinux'

Configured features:
ACL GMP GNUTLS JSON LIBXML2 MODULES NOTIFY KQUEUE PDUMPER THREADS ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: ELisp/d

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow regexp-opt sort mail-extr emacsbug message rmc puny dired
dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config
gnus-util rmail rmail-loaddefs auth-source cl-seq eieio eieio-core
cl-macs eieio-loaddefs password-cache json map text-property-search
time-date subr-x mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums
mm-util mail-prsvr mail-utils cl-print edebug backtrace help-mode
tool-bar find-func vc-mtn vc-hg vc-git diff-mode easy-mmode vc-bzr
vc-src vc-sccs vc-svn vc-cvs vc-rcs vc cl-loaddefs cl-lib vc-dispatcher
image project seq term/xterm xterm byte-opt gv bytecomp byte-compile
cconv iso-transl tooltip eldoc paren electric uniquify ediff-hook
vc-hooks lisp-float-type elisp-mode tabulated-list replace newcomment
text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow
isearch easymenu timer select mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite emoji-zwj charscript charprop case-table
epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice
button loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote threads kqueue multi-tty
make-network-process emacs)

Memory information:
((conses 16 72031 7674)
(symbols 48 8797 1)
(strings 32 26201 1172)
(string-bytes 1 817049)
(vectors 16 14915)
(vector-slots 8 168301 9701)
(floats 8 42 454)
(intervals 56 324 3)
(buffers 992 14))