Skip to content

Commit

Permalink
Fix vc-git with old Git over Tramp and cygwin-mount.el
Browse files Browse the repository at this point in the history
* lisp/vc/vc-git.el (vc-git-use-literal-pathspecs): New variable.
(vc-git-command, vc-git--call): Use it to determine whether to set
GIT_LITERAL_PATHSPECS=1 (bug#51497).
(vc-git--literal-pathspec, vc-git--literal-pathspecs): Remove.
Update all callers.  This reverts the previous solution for bug#39452.

* lisp/progmodes/project.el (project--vc-list-files):
Use the new variable.
  • Loading branch information
dgutov committed Jan 5, 2022
1 parent c0cfbca commit e7aa3ec
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 39 deletions.
7 changes: 7 additions & 0 deletions etc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -1949,6 +1949,13 @@ String or list of strings specifying switches for Git log under VC.
If you are still using it with any regularity, please file a bug
report with some details.

---
*** New variable 'vc-git-use-literal-pathspecs'.
The Git backend's function now treat all file names "literally", where
some of them previously could interpret file names (pathspecs) as
globs when they contain appropriate characters. Functions can bind
the aforementioned variable to nil locally to avoid this.

** Gnus

+++
Expand Down
2 changes: 2 additions & 0 deletions lisp/progmodes/project.el
Original file line number Diff line number Diff line change
Expand Up @@ -494,10 +494,12 @@ backend implementation of `project-external-roots'.")
(declare-function vc-hg-command "vc-hg")

(defun project--vc-list-files (dir backend extra-ignores)
(defvar vc-git-use-literal-pathspecs)
(pcase backend
(`Git
(let ((default-directory (expand-file-name (file-name-as-directory dir)))
(args '("-z"))
(vc-git-use-literal-pathspecs nil)
files)
;; Include unregistered.
(setq args (append args '("-c" "-o" "--exclude-standard")))
Expand Down
74 changes: 35 additions & 39 deletions lisp/vc/vc-git.el
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@ included in the completions."
;; History of Git commands.
(defvar vc-git-history nil)

;; Default to t because commands which don't support literal pathspecs
;; ignore the environment variable silently.
(defvar vc-git-use-literal-pathspecs t
"Non-nil to treat pathspecs in commands literally.
Good example of file name that needs this: \"test[56].xx\".")

;; Clear up the cache to force vc-call to check again and discover
;; new functions when we reload this file.
(put 'Git 'vc-functions nil)
Expand All @@ -242,20 +248,6 @@ included in the completions."
;;;###autoload (load "vc-git" nil t)
;;;###autoload (vc-git-registered file))))

;; Good example of file name that needs this: "test[56].xx".
(defun vc-git--literal-pathspec (file)
"Prepend :(literal) path magic to FILE."
(when file
;; Expand abbreviated file names.
(when (file-name-absolute-p file)
(setq file (expand-file-name file)))
(concat ":(literal)" (file-local-name file))))

(defun vc-git--literal-pathspecs (files)
"Prepend :(literal) path magic to FILES."
(unless (vc-git--file-list-is-rootdir files)
(mapcar #'vc-git--literal-pathspec files)))

(defun vc-git-registered (file)
"Check whether FILE is registered with git."
(let ((dir (vc-git-root file)))
Expand All @@ -269,12 +261,12 @@ included in the completions."
(name (file-relative-name file dir))
(str (with-demoted-errors "Error: %S"
(cd dir)
(vc-git--out-ok "ls-files" "-c" "-z" "--" (vc-git--literal-pathspec name))
(vc-git--out-ok "ls-files" "-c" "-z" "--" name)
;; If result is empty, use ls-tree to check for deleted
;; file.
(when (eq (point-min) (point-max))
(vc-git--out-ok "ls-tree" "--name-only" "-z" "HEAD"
"--" (vc-git--literal-pathspec name)))
"--" name))
(buffer-string))))
(and str
(> (length str) (length name))
Expand Down Expand Up @@ -356,7 +348,7 @@ in the order given by `git status'."
,@(when (version<= "1.7.6.3" (vc-git--program-version))
'("--ignored"))
"--"))
(status (apply #'vc-git--run-command-string (vc-git--literal-pathspec file) args)))
(status (apply #'vc-git--run-command-string file args)))
(if (null status)
;; If status is nil, there was an error calling git, likely because
;; the file is not in a git repo.
Expand Down Expand Up @@ -634,28 +626,28 @@ or an empty string if none."
(pcase (vc-git-dir-status-state->stage git-state)
('update-index
(if files
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "add" "--refresh" "--")
(vc-git-command (current-buffer) 'async files "add" "--refresh" "--")
(vc-git-command (current-buffer) 'async nil
"update-index" "--refresh")))
('ls-files-added
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files)
(vc-git-command (current-buffer) 'async files
"ls-files" "-z" "-c" "-s" "--"))
('ls-files-up-to-date
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files)
(vc-git-command (current-buffer) 'async files
"ls-files" "-z" "-c" "-s" "--"))
('ls-files-conflict
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files)
(vc-git-command (current-buffer) 'async files
"ls-files" "-z" "-u" "--"))
('ls-files-unknown
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files)
(vc-git-command (current-buffer) 'async files
"ls-files" "-z" "-o" "--exclude-standard" "--"))
('ls-files-ignored
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files)
(vc-git-command (current-buffer) 'async files
"ls-files" "-z" "-o" "-i" "--directory"
"--no-empty-directory" "--exclude-standard" "--"))
;; --relative added in Git 1.5.5.
('diff-index
(vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files)
(vc-git-command (current-buffer) 'async files
"diff-index" "--relative" "-z" "-M" "HEAD" "--")))
(vc-run-delayed
(vc-git-after-dir-status-stage git-state))))
Expand Down Expand Up @@ -883,12 +875,12 @@ The car of the list is the current branch."
(when flist
(vc-git-command nil 0 flist "update-index" "--add" "--"))
(when dlist
(vc-git-command nil 0 (vc-git--literal-pathspecs dlist) "add"))))
(vc-git-command nil 0 dlist "add"))))

(defalias 'vc-git-responsible-p #'vc-git-root)

(defun vc-git-unregister (file)
(vc-git-command nil 0 (vc-git--literal-pathspec file) "rm" "-f" "--cached" "--"))
(vc-git-command nil 0 file "rm" "-f" "--cached" "--"))

(declare-function log-edit-mode "log-edit" ())
(declare-function log-edit-toggle-header "log-edit" (header value))
Expand Down Expand Up @@ -954,7 +946,7 @@ It is based on `log-edit-mode', and has Git-specific extensions.")
(lambda (value) (when (equal value "yes") (list argument)))))
;; When operating on the whole tree, better pass "-a" than ".", since "."
;; fails when we're committing a merge.
(apply #'vc-git-command nil 0 (if only (vc-git--literal-pathspecs files))
(apply #'vc-git-command nil 0 (if only files)
(nconc (if msg-file (list "commit" "-F"
(file-local-name msg-file))
(list "commit" "-m"))
Expand All @@ -981,7 +973,7 @@ It is based on `log-edit-mode', and has Git-specific extensions.")
(coding-system-for-write 'binary)
(fullname
(let ((fn (vc-git--run-command-string
(vc-git--literal-pathspec file) "ls-files" "-z" "--full-name" "--")))
file "ls-files" "-z" "--full-name" "--")))
;; ls-files does not return anything when looking for a
;; revision of a file that has been renamed or removed.
(if (string= fn "")
Expand All @@ -998,14 +990,14 @@ It is based on `log-edit-mode', and has Git-specific extensions.")
(vc-git-root file)))

(defun vc-git-checkout (file &optional rev)
(vc-git-command nil 0 (vc-git--literal-pathspec file) "checkout" (or rev "HEAD")))
(vc-git-command nil 0 file "checkout" (or rev "HEAD")))

(defun vc-git-revert (file &optional contents-done)
"Revert FILE to the version stored in the git repository."
(if contents-done
(vc-git-command nil 0 file "update-index" "--")
(vc-git-command nil 0 (vc-git--literal-pathspec file) "reset" "-q" "--")
(vc-git-command nil nil (vc-git--literal-pathspec file) "checkout" "-q" "--")))
(vc-git-command nil 0 file "reset" "-q" "--")
(vc-git-command nil nil file "checkout" "-q" "--")))

(defvar vc-git-error-regexp-alist
'(("^ \\(.+\\)\\> *|" 1 nil nil 0))
Expand Down Expand Up @@ -1089,7 +1081,7 @@ This prompts for a branch to merge from."
(defun vc-git-conflicted-files (directory)
"Return the list of files with conflicts in DIRECTORY."
(let* ((status
(vc-git--run-command-string (vc-git--literal-pathspec directory) "status" "--porcelain" "--"))
(vc-git--run-command-string directory "status" "--porcelain" "--"))
(lines (when status (split-string status "\n" 'omit-nulls)))
files)
(dolist (line lines files)
Expand Down Expand Up @@ -1178,7 +1170,7 @@ If LIMIT is a revision string, use it as an end-revision."
(let ((inhibit-read-only t))
(with-current-buffer buffer
(apply #'vc-git-command buffer
'async (vc-git--literal-pathspecs files)
'async files
(append
'("log" "--no-color")
(when (and vc-git-print-log-follow
Expand Down Expand Up @@ -1432,7 +1424,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(if vc-git-diff-switches
(apply #'vc-git-command (or buffer "*vc-diff*")
1 ; bug#21969
(vc-git--literal-pathspecs files)
files
command
"--exit-code"
(append (vc-switches 'git 'diff)
Expand Down Expand Up @@ -1517,7 +1509,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(let* ((fname (file-relative-name file))
(prev-rev (with-temp-buffer
(and
(vc-git--out-ok "rev-list" "-2" rev "--" (vc-git--literal-pathspec fname))
(vc-git--out-ok "rev-list" "-2" rev "--" fname)
(goto-char (point-max))
(bolp)
(zerop (forward-line -1))
Expand Down Expand Up @@ -1545,7 +1537,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(current-rev
(with-temp-buffer
(and
(vc-git--out-ok "rev-list" "-1" rev "--" (vc-git--literal-pathspec file))
(vc-git--out-ok "rev-list" "-1" rev "--" file)
(goto-char (point-max))
(bolp)
(zerop (forward-line -1))
Expand All @@ -1557,7 +1549,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(and current-rev
(with-temp-buffer
(and
(vc-git--out-ok "rev-list" "HEAD" "--" (vc-git--literal-pathspec file))
(vc-git--out-ok "rev-list" "HEAD" "--" file)
(goto-char (point-min))
(search-forward current-rev nil t)
(zerop (forward-line -1))
Expand All @@ -1567,13 +1559,13 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(or (vc-git-symbolic-commit next-rev) next-rev)))

(defun vc-git-delete-file (file)
(vc-git-command nil 0 (vc-git--literal-pathspec file) "rm" "-f" "--"))
(vc-git-command nil 0 file "rm" "-f" "--"))

(defun vc-git-rename-file (old new)
(vc-git-command nil 0 (list old new) "mv" "-f" "--"))

(defun vc-git-mark-resolved (files)
(vc-git-command nil 0 (vc-git--literal-pathspecs files) "add"))
(vc-git-command nil 0 files "add"))

(defvar vc-git-extra-menu-map
(let ((map (make-sparse-keymap)))
Expand Down Expand Up @@ -1796,6 +1788,8 @@ The difference to vc-do-command is that this function always invokes
(process-environment
(append
`("GIT_DIR"
,@(when vc-git-use-literal-pathspecs
'("GIT_LITERAL_PATHSPECS=1"))
;; Avoid repository locking during background operations
;; (bug#21559).
,@(when revert-buffer-in-progress-p
Expand Down Expand Up @@ -1833,6 +1827,8 @@ The difference to vc-do-command is that this function always invokes
(process-environment
(append
`("GIT_DIR"
,@(when vc-git-use-literal-pathspecs
'("GIT_LITERAL_PATHSPECS=1"))
;; Avoid repository locking during background operations
;; (bug#21559).
,@(when revert-buffer-in-progress-p
Expand Down

0 comments on commit e7aa3ec

Please sign in to comment.