Subject: Re: 25.0.50; auto-revert-mode breaks git rebase

From: Alexei Khlebnikov <[email-masked]>
Date: Thu, 15 Feb 2018 23:32:44 +0100

I am sending patch that fixes the issue. It fixes the issue for me on
Emacs' current master branch. The patch also cleanly applies to emacs-26
branch.

I tested using Mitchel Humpherys' repro method, i.e.

    $ cd /path/to/emacs
    $ ./src/emacs -Q lisp/*.el
    [ M-x global-auto-revert-mode ]
    $ for i in $(seq 30); do for f in lisp/*.el; do echo "; $i" >> $f;
done; git commit -am "test $i"; done

Without the fix I could reproduce the issue, and with the fix I could not
reproduce even if running the loop 100 times instead of 30. Emacs was
reloading a lot of files very fast, but no locking errors happened in the
shell which ran the loop.

2018-02-15 20:08 GMT+01:00 Alexei Khlebnikov <[email-masked]>:

> Judging from the comment of the commit implementing the
> "--no-optional-locks" switch,
>
> https://github.com/git/git/commit/27344d6a6c8056664966e11acf674e5da6dd7ee3
> ​
> , the switch was implemented exactly for background refresh in "tools like
> IDEs or fancy editors".
> I.e. for mitigating this particular bug! Now we only have to use this
> switch in our "fancy editor".
>
>
From 4bba51ded42954a62c99696453c17e7fa3f2b730 Mon Sep 17 00:00:00 2001
From: Alexei Khlebnikov <[email-masked]>
Date: Thu, 15 Feb 2018 21:18:01 +0100
Subject: [PATCH] Fix for: "25.0.50; auto-revert-mode breaks git rebase"
 (Bug#21559)

* lisp/vc/vc-git.el (vc-git-state, vc-git-conflicted-files)
  Use "--no-optional-locks" switch when doing "git status".
---
 lisp/vc/vc-git.el | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 47172dd52f..06db43c311 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -292,13 +292,16 @@ vc-git-state
   ;; upstream.  We'd need to check against the upstream tracking
   ;; branch for that (an extra process call or two).
   (let* ((args
-          `("status" "--porcelain" "-z"
+          `(;; Avoid locking repository during "git status" (bug#21559).
+            ,@(when (version<= "2.15.0" (vc-git--program-version))
+                '("--no-optional-locks"))
+            "status" "--porcelain" "-z"
             ;; Just to be explicit, it's the default anyway.
             "--untracked-files"
             ,@(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 file args)))
     ;; Alternatively, the `ignored' state could be detected with 'git
     ;; ls-files -i -o --exclude-standard', but that's an extra process
     ;; call, and the `ignored' state is rarely needed.
@@ -939,8 +942,12 @@ vc-git-merge-branch
 
 (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" "--"))
+  (let* ((args
+          `(;; Avoid locking repository during "git status" (bug#21559).
+            ,@(when (version<= "2.15.0" (vc-git--program-version))
+                '("--no-optional-locks"))
+            "status" "--porcelain" "--"))
+         (status (apply #'vc-git--run-command-string directory args))
          (lines (when status (split-string status "\n" 'omit-nulls)))
          files)
     ;; TODO: Look into reimplementing `vc-git-state', as well as
-- 
2.15.1