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

From: Mitchel Humpherys <[email-masked]>
Date: Sat, 06 Feb 2016 17:34:49 -0800

On Sat, Feb 06 2016 at 01:34:06 PM, Ben Gamari <[email-masked]> wrote:
> Mitchel Humpherys <[email-masked]> writes:
>
>> On Fri, Sep 25 2015 at 03:45:56 PM, Ben Gamari <[email-masked]> wrote:
>>> Arguably `git rebase` should be holding the `index.lock` for the entire
>>> duration of the process (or be more resilient to the lock being taken)
>>> but sadly this isn't the case. Emacs should behave appropriately to
>>> accomodate this behavior.
>>
>> I don't think this is quite right.  As I understand it, git only takes
>> index.lock for operations that mutate the index [1].
>>
>> It wouldn't make sense for git to hold index.lock for the entirety of
>> the rebase operation since you can stop in the middle of an interactive
>> rebase and do anything you want (mess with the index, add new commits,
>> anything).
>>
> Ahh, yes. You are quite right.
>
>> I think the real question is: why is vc-find-file-hook (or
>> vc-refresh-state) trying to mutate the index?  Shouldn't refreshing a
>> buffer be a read-only operation (at least with respect to the VCS)?
>>
> As far as I can tell vc-find-file-hook is merely calling `git ls-files
> -c -z -- $FILE`, which sounds to me like it should indeed be a read-only
> operation.

I'm able to reliably reproduce this on the tip of the emacs-25 branch
with emacs -Q with:

    $ 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

You might need to increase the `30' value in order to see it happen
depending on your disk speed, etc.

I took a quick look at the git source and the main source of this
particular error seems to be from the `git update-index' command.  I see
that vc-git.el is calling `git update-index' in a few places but my
attempts at instrumenting the code to track down where it was coming
from were fruitless.  I tried:

    (setq vc-command-messages t)

as well as:

    (defun vc-git-command (buffer okstatus file-or-list &rest flags)
      "A wrapper around `vc-do-command' for use in vc-git.el.
    The difference to vc-do-command is that this function always invokes
     `vc-git-program'."
       (let ((coding-system-for-read vc-git-commits-coding-system)
     	(coding-system-for-write vc-git-commits-coding-system))
    +    (message "git: %s %s" file-or-list flags)

Any ideas on how we can trace every git command that vc-git.el is
running?  I'm suspicious that we're calling `git update-index' in the
auto revert path somewhere...