Subject: bug#39452: [PATCH] vc-git-state fails for filenames with wildcards

From: Wolfgang Scherer <[email-masked]>
Date: Fri, 7 Feb 2020 18:25:27 +0100

Hi Dmitry,

Am 07.02.20 um 00:00 schrieb Dmitry Gutov:
>
> On 06.02.2020 16:59, Wolfgang Scherer wrote:
>> When a filename contains shell wildcard characters matching one or more files, e.g. `test[56].xx` matching both `test5.xx` and `test6.xx`:
>> The command `vc-git-state` does not work correctly.
>>
>> The attched patch fixes this:
>>
>> -        (status (apply #'vc-git--run-command-string file args)))
>> +        (status (apply #'vc-git--run-command-string (shell-quote-argument file) args)))
>>
>
> Thanks for the report and the patch.
>
> I wonder how many other backends commands are broken for files like that: we basically never shell-quote file names.

I finally decided to fully implement the vc ignore feature for all backends. So once I am finished, I will have tested all vs-backend-state functions with filenames containing glob special characters.

Since call-process is already used in vc-git, the function shell-quote-argument is not really appropriate.

For the ongoing vc ignore implementation I needed a glob escape function, which only escapes special glob characters and backslash (see http://sw-amt.ws/emacs/doc/_build/html/emacs-vc-ignore-feature.html):

(defun vc-glob-escape (string)
  "Escape special glob characters in STRING."
  (save-match-data
    (if (string-match "[\\?*[]" string)
        (mapconcat (lambda (c)
                     (pcase c
                       (?\\ "\\\\")
                       (?? "\\?")
                       (?* "\\*")
                       (?\[ "\\[")
                       (_ (char-to-string c))))
                   string "")
      string)))

As for other occurences of glob errors in vc-git, The function vc-git-dir-status-files also suffers from this bug, when the FILES argument is non-nil:

;; (let ((default-directory "/srv/install/linux/emacs/check-git/")) (vc-git-dir-status-files nil '("/srv/install/linux/emacs/check-git/test[56].xx") (lambda (&rest args) args)))

fatal: pathspec 'test[56].xx' did not match any files
[email-masked]^@test[56].xx^@

Various other git commands, like vc-git-revert, vc-git-checkin also use glob expansion and are therefore broken.