branch: elpa/magit commit 11e13640c44b8c12396aa316bcf95845c4d4aae7 Author: Jonas Bernoulli <jo...@bernoul.li> Commit: Jonas Bernoulli <jo...@bernoul.li>
Better support inserting section into multiple buffers Normally buffers are refreshed one by one. However, the sections may be inserted into the process buffer while another buffer is being refreshed, in particular if `magit-git-debug' is enabled. This lead to errors because `magit-insert-headers' which is used to create the header sections in the status buffer adds a function to the global value `magit-insert-section-hook'. If we switch to the inserting a section into the process buffer while this is happening, that hook function adds that section to the list of sections that are later in `magit-insert-heading' processed again. This can be prevented by only adding that function to the local value of the hook. That is enough to address this particular issues, but also add some additional safety measures. In `magit-process-insert-section' bind `magit-insert-section--current' to nil. Currently this is not necessary, but future changes could make it necessary, and since it also conceptually makes sense to bind these when the other `magit-insert-section--*' functions are let-bound, there is no harm in doing this proactively. Make `magit-insert-section--current', `magit-insert-section--parent' and `magit-insert-section--oldroot' automatically buffer local. These variables are always about the sections in just one particular buffer. As long as sections are only ever inserted into one buffer at a time, it does not make a difference if these are local or global, but since this is already not the case (due to additions to process buffer) and we might in the future refresh buffers asynchronously, we need buffer- local values. --- lisp/magit-process.el | 1 + lisp/magit-section.el | 46 +++++++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/lisp/magit-process.el b/lisp/magit-process.el index f24f439394f..9a3df2669a2 100644 --- a/lisp/magit-process.el +++ b/lisp/magit-process.el @@ -693,6 +693,7 @@ Magit status buffer." (defun magit-process-insert-section (pwd program args &optional errcode errlog) (let ((inhibit-read-only t) + (magit-insert-section--current nil) (magit-insert-section--parent magit-root-section) (magit-insert-section--oldroot nil)) (goto-char (1- (point-max))) diff --git a/lisp/magit-section.el b/lisp/magit-section.el index e187e87daa2..7b885f52c64 100644 --- a/lisp/magit-section.el +++ b/lisp/magit-section.el @@ -602,9 +602,9 @@ with SECTION, otherwise return a list of section types." (and-let* ((parent (oref section parent))) (magit-section-lineage parent raw)))) -(defvar magit-insert-section--current nil "For internal use only.") -(defvar magit-insert-section--parent nil "For internal use only.") -(defvar magit-insert-section--oldroot nil "For internal use only.") +(defvar-local magit-insert-section--current nil "For internal use only.") +(defvar-local magit-insert-section--parent nil "For internal use only.") +(defvar-local magit-insert-section--oldroot nil "For internal use only.") ;;; Menu @@ -1593,26 +1593,26 @@ is explicitly expanded." (defun magit-insert-headers (hook) (let* ((header-sections nil) - (magit-insert-section-hook - (cons (lambda () - (push magit-insert-section--current - header-sections)) - (ensure-list magit-insert-section-hook)))) - (magit-run-section-hook hook) - (when header-sections - (insert "\n") - ;; Make the first header into the parent of the rest. - (when (cdr header-sections) - (setq header-sections (nreverse header-sections)) - (let* ((1st-header (pop header-sections)) - (header-parent (oref 1st-header parent))) - (oset header-parent children (list 1st-header)) - (oset 1st-header children header-sections) - (oset 1st-header content (oref (car header-sections) start)) - (oset 1st-header end (oref (car (last header-sections)) end)) - (dolist (sub-header header-sections) - (oset sub-header parent 1st-header)) - (magit-section-maybe-add-heading-map 1st-header)))))) + (fn (lambda () (push magit-insert-section--current header-sections)))) + (unwind-protect + (progn + (add-hook 'magit-insert-section-hook fn -90 t) + (magit-run-section-hook hook) + (when header-sections + (insert "\n") + ;; Make the first header into the parent of the rest. + (when (cdr header-sections) + (setq header-sections (nreverse header-sections)) + (let* ((1st-header (pop header-sections)) + (header-parent (oref 1st-header parent))) + (oset header-parent children (list 1st-header)) + (oset 1st-header children header-sections) + (oset 1st-header content (oref (car header-sections) start)) + (oset 1st-header end (oref (car (last header-sections)) end)) + (dolist (sub-header header-sections) + (oset sub-header parent 1st-header)) + (magit-section-maybe-add-heading-map 1st-header))))) + (remove-hook 'magit-insert-section-hook fn t)))) (defun magit-section-maybe-add-heading-map (section) (when (magit-section-content-p section)