Subject: Re: bug#51497: 29.0.50; (vc-print-log) broken over TRAMP

From: Dmitry Gutov <[email-masked]>
Date: Wed, 3 Nov 2021 05:03:56 +0300

On 31.10.2021 09:58, Dima Kogan wrote:
> Note the :(literal) stuff. This is what was added in the commit that the
> bisection found to be the cause of the issue. I can try to run this
> command directly (outside of emacs) on the target box:
> 
>    $ git --no-pager ls-files -c -z -- ':(literal)FILE.c' </dev/null
> 
>    fatal: Invalid pathspec magic 'literal' in ':(literal)FILE.c'
> 
> The issue is that this target box has a version of git too old to know
> about :(literal):
> 
>    kogan@aargh:~/stereo-server$ git --version
>    git version 1.8.3.1

Sounds like CentOS 7. Released 7 years ago, but updated last year, even.

> Yeah, it's ancient, but I don't control this particular machine, and I
> don't think basic stuff like "C-x v l" should be non-functional here.
> Can we add some logic to emacs to not hard-depend on this stuff?

Any idea which version of Git introduced literal pathspecs?

The docs on the official website only go back to 2.1.4 (also from 2014), 
which had it already.

Anyway, with Michael's code, see the attached patch you can try.

diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 3f89fad235..80455b2010 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -249,7 +249,9 @@ vc-git--literal-pathspec
     ;; Expand abbreviated file names.
     (when (file-name-absolute-p file)
       (setq file (expand-file-name file)))
-    (concat ":(literal)" (file-local-name file))))
+    (if (version<= "2.1.4" (vc-git--program-version))
+        (concat ":(literal)" (file-local-name file))
+      (file-local-name file))))
 
 (defun vc-git--literal-pathspecs (files)
   "Prepend :(literal) path magic to FILES."
@@ -293,18 +295,32 @@ vc-git--state-code
 (defvar vc-git--program-version nil)
 
 (defun vc-git--program-version ()
-  (or vc-git--program-version
-      (let ((version-string
-             (vc-git--run-command-string nil "version")))
-        (setq vc-git--program-version
-              (if (and version-string
-                       ;; Git for Windows appends ".windows.N" to the
-                       ;; numerical version reported by Git.
-                       (string-match
-                        "git version \\([0-9.]+\\)\\(\\.windows\\.[0-9]+\\)?$"
-                        version-string))
-                  (match-string 1 version-string)
-                "0")))))
+  (let ((current
+         (if (file-remote-p default-directory)
+             (with-connection-local-variables
+              (and (local-variable-p 'vc-git--program-version)
+                   vc-git--program-version))
+           vc-git--program-version)))
+    (or current
+        (let ((version-string
+               (vc-git--run-command-string nil "version")))
+          (setq version-string
+                (if (and version-string
+                         ;; Git for Windows appends ".windows.N" to the
+                         ;; numerical version reported by Git.
+                         (string-match
+                          "git version \\([0-9.]+\\)\\(\\.windows\\.[0-9]+\\)?$"
+                          version-string))
+                    (match-string 1 version-string)
+                  "0"))
+          (if (file-remote-p default-directory)
+              (let ((profile (gensym "connection-local-profile-")))
+                (connection-local-set-profile-variables
+                 profile `((vc-git--program-version . ,version-string))) ;
+                (connection-local-set-profiles
+                 (connection-local-criteria-for-default-directory) profile))
+            (setq vc-git--program-version version-string))
+          version-string))))
 
 (defun vc-git--git-status-to-vc-state (code-list)
   "Convert CODE-LIST to a VC status.