summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2022-01-05 04:08:10 +0200
committerDmitry Gutov <dgutov@yandex.ru>2022-01-05 04:08:10 +0200
commite7aa3ece52d26cc7e4d3f3990aff56127389779f (patch)
tree1d915d7f1b981c2282fca7c7fac924c2347a2090
parentc0cfbca311e6e07e9f8b9c1c9d0e2fe9792cd08c (diff)
downloademacs-e7aa3ece52d26cc7e4d3f3990aff56127389779f.tar.gz
Fix vc-git with old Git over Tramp and cygwin-mount.el
* 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.
-rw-r--r--etc/NEWS7
-rw-r--r--lisp/progmodes/project.el2
-rw-r--r--lisp/vc/vc-git.el74
3 files changed, 44 insertions, 39 deletions
diff --git a/etc/NEWS b/etc/NEWS
index f007c00b89e..1e882883b5a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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
+++
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index bd2ca421aec..1000e8c87f4 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -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")))
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 3519f08646d..7072b8e483b 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -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)
@@ -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)))
@@ -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))
@@ -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.
@@ -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))))
@@ -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))
@@ -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"))
@@ -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 "")
@@ -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))
@@ -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)
@@ -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
@@ -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)
@@ -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))
@@ -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))
@@ -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))
@@ -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)))
@@ -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
@@ -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