3

I've recently upgraded to Magit 2.10.3 and Emacs 25.2.1.

My full config is: Magit 2.10.3, Git 2.13.5 (Apple Git-94), Emacs 25.2.1, darwin.

I was previously on Magit 2.3.1 and Emacs 24.4.1.

Now, when I do a magit-status any open buffers within the project are changed to have auto-revert mode turned on.

Previously, the behaviour was only to revert buffers when Magit operations were performed (eg using Magit to checkout a different commit would revert any buffers whose files had changed). auto-revert mode was never turned on (or if it was it was only temporarily, and I didn't notice it).

Is there a way to get the old behaviour?


UPDATE #1:

Based on tarsius's answer, I've done the following:

(with-eval-after-load 'magit-autorevert
  (defalias 'magit-auto-revert-buffers 'revert-all-unmodified-buffers)
  (magit-auto-revert-mode -1))

revert-all-unmodified-buffers is something I had lying around:

(defun _revert-all-buffers (buffer-predicate)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (funcall buffer-predicate buf))
        (revert-buffer t t t) )))
  (message "Refreshed open files."))

(defun revert-all-unmodified-buffers ()
  "Refreshes all open unmodified buffers from their files."
  (interactive)
  (_revert-all-buffers (lambda (b) (not (buffer-modified-p b)))))

This kind of works. I guess I could change things so that I only revert buffers in the project directory.

One thing I noticed: whenever I refresh the Magit Status buffer, files get reverted. I don't really want that.


UPDATE #2

I believe I have restored the old behaviour, by turning off magit-auto-revert-mode and by doing a (defalias 'magit-auto-revert-buffers ...) that reverts buffers within the repo:

(defun _revert-all-buffers (buffer-predicate)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (funcall buffer-predicate buf))
        (condition-case e
            (revert-buffer t t t)
          (error
           (message "%s" e))))))
  (message "Refreshed open files."))

(defun revert-all-unmodified-buffers-in-git-repo ()
  "Refreshes all open modified buffers in current buffer's Git repo
 from their files."
  (interactive)
  (_revert-all-buffers (lambda (b)
                         (and (not (buffer-modified-p b))
                              (magit-auto-revert-repository-buffer-p b)))))

(with-eval-after-load 'magit-autorevert
  (magit-auto-revert-mode 0)
  (defalias 'magit-auto-revert-buffers
    'revert-all-unmodified-buffers-in-git-repo))

Thanks, tarsius, for pointing me in the right direction.

I wonder if something like this could be supported without having to hack things? (My concern is that my hack might break when I next update Magit.)

Simon K
  • 246
  • 1
  • 9
  • 1
    Have you tried customizing `magit-auto-revert-mode`? – npostavs Sep 23 '17 at 16:06
  • @npostavs: I tried turning off `magit-auto-revert-mode`. The effect was to completely turn off reverting — even when a Magit operation changes files. – Simon K Sep 23 '17 at 16:30

2 Answers2

2

(Answering my own question…)

I decided to address the issue I mentioned about files being reverted when I refresh the Magit Status buffer. (BTW, the doc strings for magit-refresh and magit-refresh-all are interesting. Only the latter mentions reverting buffers. Maybe that was the original intention and things have changed over time.)

This is what I have ended up with. I'd be interested in any comments.

I'm also interested in whether this behaviour could be made part of Magit.

;;;; Don't revert buffers other than after performing a Magit operation that
;;;; changes files.
;;;; See https://emacs.stackexchange.com/questions/35701/magit-sets-auto-revert-mode-annoying

;;;; This is more heavy-handed than I would like. A change to a single file
;;;; (eg by discarding changes to the file) causes all buffers in the repo
;;;; to be reverted.

(defun _revert-all-buffers (buffer-predicate)
  (dolist (buf (buffer-list))
    (with-current-buffer buf
      (when (and (buffer-file-name) (funcall buffer-predicate buf))
        (condition-case e
            (revert-buffer t t t)
          (error
           (message "%s" e))))))
  (message "Refreshed open files."))

(defun revert-all-unmodified-buffers-in-git-repo ()
  "Refreshes all open unmodified buffers in current buffer's Git repo
 from their files."
  (interactive)
  (_revert-all-buffers (lambda (b)
                         (and (not (buffer-modified-p b))
                              (magit-auto-revert-repository-buffer-p b)))))

(defun -nomis/fix-magit-auto-revert/2.10.3 ()

  (with-eval-after-load 'magit-autorevert

    (magit-auto-revert-mode 0)

    (defvar *nomis/magit-revert-buffers?* t)

    (defun nomis/magit-refresh ()
      "A replacement for the \"g\" key binding in `magit-mode-map`. This does
not revert buffers."
      (interactive)
      (let* ((*nomis/magit-revert-buffers?* nil))
        (magit-refresh)))

    (define-key magit-mode-map "g" 'nomis/magit-refresh)

    (advice-add 'magit-auto-revert-buffers
                :around
                (lambda (_)
                  (when *nomis/magit-revert-buffers?*
                    (revert-all-unmodified-buffers-in-git-repo)))
                '((name . -nomis/hack-auto-refresh)))))

(defun -nomis/fix-magit-auto-revert ()
  (cond
   ((equal magit-version "2.10.3")
    (-nomis/fix-magit-auto-revert/2.10.3))
   (t
    (message-box (s-join " "
                         '("Revisit `-nomis/fix-magit-auto-revert`"
                       "for this version of Magit."))))))    

(add-hook 'magit-mode-hook '-nomis/fix-magit-auto-revert)
Simon K
  • 246
  • 1
  • 9
1

Try this:

(with-eval-after-load 'magit-autorevert
  (defalias 'magit-auto-revert-buffers 'auto-revert-buffers)
  (magit-auto-revert-mode -1))

Edit: This won't work because auto-revert-buffers assumes that auto-revert-mode is on. It was worth a shot, but this outcome isn't really surprising.

So I am afraid the answer is no. Magit cannot automatically revert without using auto-revert-mode anymore. But you haven't explained why it is annoying that auto-revert-mode is being turned on now. Maybe there's something else that can be done to make you happy.

One thing I noticed: whenever I refresh the Magit Status buffer, files get reverted. I don't really want that.

That already happened before. I am pretty sure every thing you do in Magit that now triggers a revert also did so before. So what action outside of Magit did not use to do so but now does? (Or in other words, how did you notice that something had changed?)

tarsius
  • 25,298
  • 4
  • 69
  • 109
  • (EDITED for clarity.) The effect was to completely turn off reverting — even when a Magit operation changes files – Simon K Sep 23 '17 at 18:32
  • Ah, I just tried again and noticed stuff in the *Messages* buffer that makes it look like something is trying to revert bufers. Not sure I can get this to format nicely... `Discard unstaged changes in project.clj? (y or n) y [2 times]` `cancel-timer: Wrong type argument: timerp, nil` So it looks like something tried to revert buffers. – Simon K Sep 23 '17 at 20:25
  • Hmmm, that previous comment of mine doesn't make a lot of sense. But I guess the point is that there's an error with `cancel-timer`. – Simon K Sep 23 '17 at 21:05
  • You are right that refreshing the Magit Status buffer used to cause reverts (I reverted my Emacs config to check). I hadn't noticed it before. I guess I've noticed it now because I've been doing lots of playing around. But note that bringing up the Magit Status buffer in the first place did not and does not cause a revert -- and I like that. – Simon K Sep 24 '17 at 10:24
  • As to why auto-revert is annoying, I will try to explain. Without auto-revert, if files change outside of Emacs, for whatever reason, I get to know about it. (If I try to edit a file that has changed on disc, Emacs asks whether I really want to do that.) And at any time, I can use my `revert-all-unmodified-buffers` command, so if a lot of files have changed I can use that. I appreciate that other people have different workflows, but I know and like mine. – Simon K Sep 24 '17 at 10:24
  • Understood, and thanks for implementing an alternative! – tarsius Sep 24 '17 at 17:47
  • I think it's worth saying this too… I don't think it's just about whether someone might find auto-revert annoying. It's that auto-revert is not the default in Emacs, and Magit turning on auto-revert (by default) changes what people are used to. So I think Magit's default should be to never turn on auto-revert. – Simon K Sep 27 '17 at 11:56
  • It's not that you are the only one who has expressed that opinion, but it still appears to be a minority opinion. One potential concern is that using auto-revert is potentially dangerous, so I have written https://magit.vc/manual/magit/Risk-of-Reverting-Automatically.html. – tarsius Sep 27 '17 at 12:39
  • I don't think that addresses the point about the change from Emacs's default behaviour. Anyway, I would urge you to consider providing a supported Magit option to never turn on auto-update, so that people like me can have the behaviour they want and upgrade without fear. :-) (And, BTW, I appreciate the effort you are putting into improving Magit. I don't want to seem ungrateful.) – Simon K Sep 27 '17 at 13:15