Hi folks,

some time ago I hacked magit to support extension points, so that one
can externally extend the set of available commands/sections. The reason
is that I would like to be able to write small extensions to support my
very own git helpers, and integrate nicely into magit, even though they
have nothing to do upstream (like integration with internal bug tracker
or code review interface, that kind of things). Also I'd love to see
optional (as in "if you don't need it, just don't load it) extensions to
support for example git-p4, stgit, and so on (need them for work :p)

Ok, that was for the rationale :) The fact is that I have something
working for my needs and would like to know:
- first if there is any interest at all in integrating something similar
  upstream
- if so, how to do it properly.

Anyone interested can have a look at my "extensions" branch:
http://github.com/sigma/magit/tree/t/new/extensions

Basically that's the same feature-set as regular magit (a bit lagging
behind though), except that all git-svn and topgit related features lie
in magit-svn.el and magit-topgit.el and are totally optional.
(so that one has to explicitly require them to activate them)




For those interested, here are a couple of technical "details":

In this patch I distinguish between magit "commands" and "actions"
(yeah, I should have better terminology)
- commands are "global" calls, like magit-create-branch, that result in
  a constant behavior
- actions on the other hands are context-aware, and translate to
  different git invocations, typically depending on the section they're
  applied to. (magit-discard-item for example)

There are basically 4 things I want to be able to express in an
extension:
1. define new extension-specific commands (like
   `magit-svn-dcommit'). This is almost a no-brainer. All that's needed
   is an appropriate key and menu.
2. define new sections to display relevant information for the extension
   in the "status" buffer ("topgit" section for example)
3. override the behavior of existing commands for certain inputs (like
   `magit-create-branch' using topgit when branch is named "t/something")
4. define behavior of existing actions for new sections (like
   `magit-discard-item', applied to the "topgit" section)


To achieve these goals, the "core" magit is altered in the following
ways:

- define commands using new `magit-define-command'

  this automatically declares hooks that can be populated
  from extensions. First hook that returns non-nil "wins" and command
  stops there. This covers 3. above

  This allows to write code such as:

--8<---------------cut here---------------start------------->8---
(defun magit-topgit-create-branch (branch parent)
  (when (zerop (or (string-match "t/" branch) -1))
    (magit-run* (list magit-topgit-executable "create"
                      branch (magit-rev-to-git parent))
                nil nil nil t)
    t))
--8<---------------cut here---------------end--------------->8---

- define inserters using new `magit-define-inserter'

  this declares before/after hooks that allow to place sections in
  a relative way to existing sections. This covers 2.

  This allows the following:

--8<---------------cut here---------------start------------->8---
(defvar magit-topgit-extension-inserters
  '((:after stashes magit-insert-topics)))
--8<---------------cut here---------------end--------------->8---

- introduce "dynamic clauses"

  the way it works now, magit defines "actions" using a nice and tricky
  macro `magit-section-case' that relies on the fact that every possible
  context (clause) is known at compile time. The patch adds support for
  injecting dynamically more clauses, using the same nice syntax. This
  covers 4.

  Note that here there *is* a runtime overhead, of course. Still, as
  long as the number of loaded extensions stays reasonable, I don't
  expect too much trouble

  This allows:

--8<---------------cut here---------------start------------->8---
(defvar magit-topgit-extension-actions
  '(("discard" ((topic)
                (when (yes-or-no-p "Discard topic? ")
                  (magit-run* (list magit-topgit-executable "delete" "-f" info)
                              nil nil nil t))))
    ("visit" ((topic)
              (magit-checkout info)))))
--8<---------------cut here---------------end--------------->8---



Sorry for the long mail, I tried to be rather complete in this
introduction ;)

Now if there is any interest in porting this upstream (with necessary
changes, the patch is not complete, just sufficient for what I really
needed), I'm willing to do what it takes to go there properly.
After all, that would *also* make my life easier not to have to maintain
this as an external patch ;)

Feedback and comments are highly welcome !

Yann.

--
When the center of the storm does not move, you are in its path.

  -- Ancient Fremen Wisdom

Reply via email to