Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

extensions as minor modes

This patch changes the strategy for loading magit extensions.

Until now, `require'-ing the extension file was sufficient to enable it for
every git repository. This is probably not the right behavior, because some
extensions might not apply to in every case.

For example, there is little sense using both topgit and stgit in the same
repo, but one could to use one or the other depending on the case.
Extensions such as https://github.com/sigma/magit-gh-pulls will make sense only
for repositories hosted in GitHub.

In any case, it would probably be desirable for the user to be able to toggle
the use of a specific extension.

We reach that goal by making extensions minor modes (as was initially quickly
discussed when I introduced extensions). For example, toggling
`magit-topgit-mode' while in the "status" buffer will make the "Topics" section
appear/disappear.

Therefore, extensions can now be loaded with code like:

  (add-hook 'magit-mode-hook 'turn-on-magit-topgit)

Additionally, it is possible to introduce git configuration elements to
automatically load relevant extensions (configured on a global and/or per
repository basis)

  (add-hook 'magit-mode-hook 'magit-load-config-extensions)

This will in effect call "git config --get-all magit.extension" in the
repository and load whatever extensions are required there

In the following case:
$ git config --get-all magit.extension
topgit
svn

the minor modes `magit-topgit-mode' and `magit-svn-mode' will be activated.

Signed-off-by: Yann Hodique <yhodique@vmware.com>
  • Loading branch information...
commit f4063d95cba09cd5fa94e240264ea713195ab7df 1 parent a1bdd47
@sigma sigma authored sigma committed
Showing with 74 additions and 23 deletions.
  1. +30 −9 magit-svn.el
  2. +36 −14 magit-topgit.el
  3. +8 −0 magit.el
View
39 magit-svn.el
@@ -170,6 +170,7 @@ If USE-CACHE is non nil, use the cached information."
nil
"Git SVN extension menu"
'("Git SVN"
+ :visible magit-svn-mode
["Create branch" magit-svn-create-branch (magit-svn-enabled)]
["Rebase" magit-svn-rebase (magit-svn-enabled)]
["Fetch" magit-svn-remote-update (magit-svn-enabled)]
@@ -179,14 +180,6 @@ If USE-CACHE is non nil, use the cached information."
'("Extensions")
magit-svn-extension-menu)
-(add-hook 'magit-after-insert-unpulled-commits-hook
- (lambda () (magit-insert-svn-unpulled t)))
-
-(add-hook 'magit-after-insert-unpushed-commits-hook
- (lambda () (magit-insert-svn-unpushed t)))
-
-(add-hook 'magit-remote-string-hook 'magit-svn-remote-string)
-
;; add the group and its keys
(progn
;; (re-)create the group
@@ -201,7 +194,35 @@ If USE-CACHE is non nil, use the cached information."
;; generate and bind the menu popup function
(magit-key-mode-generate 'svn))
-(define-key magit-mode-map (kbd "N") 'magit-key-mode-popup-svn)
+(defvar magit-svn-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "N") 'magit-key-mode-popup-svn)
+ map))
+
+;;;###autoload
+(define-minor-mode magit-svn-mode "SVN support for Magit"
+ :lighter " SVN" :require 'magit-svn :keymap 'magit-svn-mode-map
+ (or (derived-mode-p 'magit-mode)
+ (error "This mode only makes sense with magit"))
+ (let ((unpulled-hook (lambda () (magit-insert-svn-unpulled t)))
+ (unpushed-hook (lambda () (magit-insert-svn-unpushed t)))
+ (remote-hook 'magit-svn-remote-string))
+ (if magit-svn-mode
+ (progn
+ (add-hook 'magit-after-insert-unpulled-commits-hook unpulled-hook nil t)
+ (add-hook 'magit-after-insert-unpushed-commits-hook unpushed-hook nil t)
+ (add-hook 'magit-remote-string-hook remote-hook nil t))
+ (progn
+ (remove-hook 'magit-after-insert-unpulled-commits-hook unpulled-hook t)
+ (remove-hook 'magit-after-insert-unpushed-commits-hook unpushed-hook t)
+ (remove-hook 'magit-remote-string-hook remote-hook t)))
+ (when (called-interactively-p 'any)
+ (magit-refresh))))
+
+;;;###autoload
+(defun turn-on-magit-svn ()
+ "Unconditionally turn on `magit-svn-mode'."
+ (magit-svn-mode 1))
(provide 'magit-svn)
;;; magit-svn.el ends here
View
50 magit-topgit.el
@@ -143,13 +143,6 @@
((topic)
(magit-checkout info)))
-(add-hook 'magit-after-insert-stashes-hook 'magit-insert-topics)
-
-(add-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch)
-(add-hook 'magit-pull-command-hook 'magit-topgit-pull)
-(add-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update)
-(add-hook 'magit-push-command-hook 'magit-topgit-push)
-
(defun magit-topgit-get-top-bases-color (suffix)
(list nil nil))
@@ -157,13 +150,42 @@
(when (string-match "^\\(?:[^/]+\\)/top-bases" suffix)
(list nil nil)))
-;; hide refs in the top-bases namespace, as they're not meant for the user
-(add-to-list 'magit-refs-namespaces
- '("top-bases" magit-topgit-get-top-bases-color))
-
-;; same thing for top-bases namespace in any remote
-(add-hook 'magit-log-remotes-color-hook
- 'magit-topgit-get-remote-top-bases-color)
+(defconst magit-topgit-ignored-namespace
+ '("top-bases" magit-topgit-get-top-bases-color))
+
+;;;###autoload
+(define-minor-mode magit-topgit-mode "Topgit support for Magit"
+ :lighter " Topgit" :require 'magit-topgit
+ (or (derived-mode-p 'magit-mode)
+ (error "This mode only makes sense with magit"))
+ (if magit-topgit-mode
+ (progn
+ (add-hook 'magit-after-insert-stashes-hook 'magit-insert-topics nil t)
+ (add-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch nil t)
+ (add-hook 'magit-pull-command-hook 'magit-topgit-pull nil t)
+ (add-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update nil t)
+ (add-hook 'magit-push-command-hook 'magit-topgit-push nil t)
+ ;; hide refs for top-bases namespace in any remote
+ (add-hook 'magit-log-remotes-color-hook
+ 'magit-topgit-get-remote-top-bases-color)
+ ;; hide refs in the top-bases namespace, as they're not meant for the user
+ (add-to-list 'magit-refs-namespaces magit-topgit-ignored-namespace))
+ (progn
+ (remove-hook 'magit-after-insert-stashes-hook 'magit-insert-topics t)
+ (remove-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch t)
+ (remove-hook 'magit-pull-command-hook 'magit-topgit-pull t)
+ (remove-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update t)
+ (remove-hook 'magit-push-command-hook 'magit-topgit-push t)
+ (remove-hook 'magit-log-remotes-color-hook
+ 'magit-topgit-get-remote-top-bases-color)
+ (delete magit-topgit-ignored-namespace magit-refs-namespaces)))
+ (when (called-interactively-p 'any)
+ (magit-refresh)))
+
+;;;###autoload
+(defun turn-on-magit-topgit ()
+ "Unconditionally turn on `magit-topgit-mode'."
+ (magit-topgit-mode 1))
(provide 'magit-topgit)
;;; magit-topgit.el ends here
View
8 magit.el
@@ -5346,6 +5346,14 @@ With a prefix arg, do a submodule update --init"
(t
(magit-start-process "Gitk" nil magit-gitk-executable "--all")))))
+(defun magit-load-config-extensions ()
+ "Try to load magit extensions that are defined at git config
+layer. This can be added to `magit-mode-hook' for example"
+ (dolist (ext (magit-get-all "magit.extension"))
+ (let ((sym (intern (format "magit-%s-mode" ext))))
+ (when (fboundp sym)
+ (funcall sym 1)))))
+
(provide 'magit)
;; rest of magit core
Please sign in to comment.
Something went wrong with that request. Please try again.