From 3572613550f5d1d0b3392dbc809b32f3989e2981 Mon Sep 17 00:00:00 2001 From: Wolfgang Scherer Date: Sun, 15 Aug 2021 04:02:23 +0300 Subject: [PATCH] Fix vc-git-state for filenames with wildcards * lisp/vc/vc-git.el: (vc-git--literal-pathspec-inner), (vc-git--literal-pathspec), (vc-git--literal-pathspecs) new functions to add ":(literal)" pathspec magic (bug#39452). (vc-git-registered), (vc-git-state), (vc-git-dir-status-goto-stage), (vc-git-register), (vc-git-unregister), (vc-git-checkin), (vc-git-find-revision), (vc-git-checkout), (vc-git-revert), (vc-git-conflicted-files), (vc-git-print-log), (vc-git-diff), (vc-git-previous-revision), (vc-git-next-revision), (vc-git-delete-file), (vc-git-rename-file) functions vc-git--literal-pathspec, vc-git--literal-pathspecs applied. --- lisp/vc/vc-git.el | 63 +++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 5828a83debc..ffe1e6832ce 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -242,6 +242,15 @@ included in the completions." ;;;###autoload (load "vc-git" nil t) ;;;###autoload (vc-git-registered file)))) +(defun vc-git--literal-pathspec (pathspec) + "Prepend :(literal) path magic to PATHSPEC." + ;; Good example of PATHSPEC that needs this: "test[56].xx". + (and pathspec (concat ":(literal)" pathspec))) + +(defun vc-git--literal-pathspecs (pathspecs) + "Prepend :(literal) path magic to PATHSPECS." + (mapcar #'vc-git--literal-pathspec pathspecs)) + (defun vc-git-registered (file) "Check whether FILE is registered with git." (let ((dir (vc-git-root file))) @@ -255,12 +264,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" "--" name) + (vc-git--out-ok "ls-files" "-c" "-z" "--" (vc-git--literal-pathspec 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" - "--" name)) + "--" (vc-git--literal-pathspec name))) (buffer-string)))) (and str (> (length str) (length name)) @@ -342,7 +351,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 file args))) + (status (apply #'vc-git--run-command-string (vc-git--literal-pathspec 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. @@ -620,28 +629,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 files "add" "--refresh" "--") + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "add" "--refresh" "--") (vc-git-command (current-buffer) 'async nil "update-index" "--refresh"))) ('ls-files-added - (vc-git-command (current-buffer) 'async files + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "ls-files" "-z" "-c" "-s" "--")) ('ls-files-up-to-date - (vc-git-command (current-buffer) 'async files + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "ls-files" "-z" "-c" "-s" "--")) ('ls-files-conflict - (vc-git-command (current-buffer) 'async files + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "ls-files" "-z" "-u" "--")) ('ls-files-unknown - (vc-git-command (current-buffer) 'async files + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "ls-files" "-z" "-o" "--exclude-standard" "--")) ('ls-files-ignored - (vc-git-command (current-buffer) 'async files + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs 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 files + (vc-git-command (current-buffer) 'async (vc-git--literal-pathspecs files) "diff-index" "--relative" "-z" "-M" "HEAD" "--"))) (vc-run-delayed (vc-git-after-dir-status-stage git-state)))) @@ -867,14 +876,14 @@ The car of the list is the current branch." (push crt dlist) (push crt flist))) (when flist - (vc-git-command nil 0 flist "update-index" "--add" "--")) + (vc-git-command nil 0 (vc-git--literal-pathspecs flist) "update-index" "--add" "--")) (when dlist - (vc-git-command nil 0 dlist "add")))) + (vc-git-command nil 0 (vc-git--literal-pathspecs dlist) "add")))) (defalias 'vc-git-responsible-p #'vc-git-root) (defun vc-git-unregister (file) - (vc-git-command nil 0 file "rm" "-f" "--cached" "--")) + (vc-git-command nil 0 (vc-git--literal-pathspec file) "rm" "-f" "--cached" "--")) (declare-function log-edit-mode "log-edit" ()) (declare-function log-edit-toggle-header "log-edit" (header value)) @@ -941,7 +950,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 files) + (apply #'vc-git-command nil 0 (if only (vc-git--literal-pathspecs files)) (nconc (if msg-file (list "commit" "-F" (file-local-name msg-file)) (list "commit" "-m")) @@ -968,7 +977,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 - file "ls-files" "-z" "--full-name" "--"))) + (vc-git--literal-pathspec 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 "") @@ -985,14 +994,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 file "checkout" (or rev "HEAD"))) + (vc-git-command nil 0 (vc-git--literal-pathspec 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 file "reset" "-q" "--") - (vc-git-command nil nil file "checkout" "-q" "--"))) + (vc-git-command nil 0 (vc-git--literal-pathspec file) "reset" "-q" "--") + (vc-git-command nil nil (vc-git--literal-pathspec file) "checkout" "-q" "--"))) (defvar vc-git-error-regexp-alist '(("^ \\(.+\\)\\> *|" 1 nil nil 0)) @@ -1076,7 +1085,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 directory "status" "--porcelain" "--")) + (vc-git--run-command-string (vc-git--literal-pathspec directory) "status" "--porcelain" "--")) (lines (when status (split-string status "\n" 'omit-nulls))) files) (dolist (line lines files) @@ -1157,7 +1166,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 files + 'async (vc-git--literal-pathspecs files) (append '("log" "--no-color") (when (and vc-git-print-log-follow @@ -1408,7 +1417,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 - files + (vc-git--literal-pathspecs files) command "--exit-code" (append (vc-switches 'git 'diff) @@ -1493,7 +1502,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 "--" fname) + (vc-git--out-ok "rev-list" "-2" rev "--" (vc-git--literal-pathspec fname)) (goto-char (point-max)) (bolp) (zerop (forward-line -1)) @@ -1521,7 +1530,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 "--" file) + (vc-git--out-ok "rev-list" "-1" rev "--" (vc-git--literal-pathspec file)) (goto-char (point-max)) (bolp) (zerop (forward-line -1)) @@ -1533,7 +1542,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" "--" file) + (vc-git--out-ok "rev-list" "HEAD" "--" (vc-git--literal-pathspec file)) (goto-char (point-min)) (search-forward current-rev nil t) (zerop (forward-line -1)) @@ -1543,13 +1552,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 file "rm" "-f" "--")) + (vc-git-command nil 0 (vc-git--literal-pathspecs file) "rm" "-f" "--")) (defun vc-git-rename-file (old new) - (vc-git-command nil 0 (list old new) "mv" "-f" "--")) + (vc-git-command nil 0 (vc-git--literal-pathspecs (list old new)) "mv" "-f" "--")) (defun vc-git-mark-resolved (files) - (vc-git-command nil 0 files "add")) + (vc-git-command nil 0 (vc-git--literal-pathspecs files) "add")) (defvar vc-git-extra-menu-map (let ((map (make-sparse-keymap))) -- 2.39.5