Differences between revisions 1 and 43 (spanning 42 versions)
Revision 1 as of 2005-09-13 19:00:35
Size: 2448
Editor: ChrisMason
Comment:
Revision 43 as of 2009-01-21 14:49:29
Size: 6100
Comment: Linked to MercurialApi
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
Mercurial features an extension mechanism for adding new commands. It allows you to create new features and use them directly from the main hg command line. The contrib directory includes an extension to mimic some git commands under Mercurial. This is named hgit, and will be used as an example here. ## page was renamed from ExtensionHowto
= Writing Mercurial extensions =
Line 3: Line 4:
To load an extension, you add it to your .hgrc file. You can either specify an absolute path: {{{
[extensions]
hgit=/usr/local/lib/hgit
Mercurial features an extension mechanism for adding new commands.

Extensions allow the creation of new features and using them directly from the main hg command line as if they were builtin commands. The extensions have full access to the MercurialApi.

== Writing your own extension ==

=== File Layout ===

Extensions are usually written as simple python modules. Larger ones are better split into multiple modules of a single package (see ConvertExtension). The package root module gives its name to the extension and implements the `cmdtable` and optional callbacks described below.

=== Command table ===
To write your own extension, your python module can provide an optional dict named `cmdtable` with entries describing each command.

==== The `cmdtable` dictionary ====
The `cmdtable` dictionary uses as key the new command names, and, as value, a tuple containing:

 1. the function name to be called when the command is used.
 1. a list of options the command can take.
 1. a help string for the command.

==== List of options ====
Al the command flag options are documented in the mercurial/fancyopts.py sources.

The options list is a list of tuples containing:
 1. a flag specifying if the option is of the short or long sort, like {{{-o}}} or {{{--option}}}.
 1. an option name.
 1. a default value for the option.
 1. a help string for the option.

==== Example `cmdtable` ====
{{{
cmdtable = {
    # "command-name": (function-call, options-list, help-string)
    "print-parents": (print_parents,
                     [('s', 'short', None, 'print short form'),
                      ('l', 'long', None, 'print long form')],
                     "hg print-parents [options] node")
}
Line 8: Line 44:
Mercurial can also scan the default python library path for a file named 'hgit': {{{
[extensions]
hgit=
=== Command function signatures ===
Functions that implement new commands always receive a {{{ui}}} and usually a {{{repo}}} parameter. Please see the MercurialApi for information on how to use these. The rest of parameters are taken from the command line items that don't start with a dash and are passed in the same order they were written. If no default value is given in the parameter list they are required.

If there is no repo to be associated with the command and consequently no {{{repo}}} passed then {{{commands}}} should be imported from {{{mercurial}}} and the extension name should be added to {{{commands.norep}}} like this:
{{{
from mercurial import commands
...
commands.norepo += " mycommand"
}}}
For examples of {{{norepo}}} see the source code to the RcpathExtension (direct link to attachment:RcpathExtension/rcpath.py extension source) or the ConvertExtension (direct link to [http://hg.intevation.org/mercurial/crew/file/f5f6b7dcd217/hgext/convert/__init__.py#l186 convert] extension source).

=== Extension setup ===
Extensions can implement an optional callback named `extsetup`. It is called after all the extension are pre-loaded, and can be useful in case one extension optionally depends on another extension.

Signature:

{{{
def extsetup():
    # ...
Line 13: Line 65:
hg help will now show the new commands provided by the hgit extension. === Repository setup ===
Extensions can implement an optional callback named `reposetup`. It is called after the main Mercurial repository initialization, and can be used to setup any local state the extension might need.
Line 15: Line 68:
To write your own extension, your python module needs to provide a dict with entries describing each command, and a callback named reposetup. reposetup is called after the main Mercurial repository initialization, and can be used to setup any local state the extension might need. Below is an example extension to help demonstrate how things work: As other command functions it receives an ui object and a repo object (no additional parameters for this, though):
Line 18: Line 71:
def reposetup(ui, repo):
    #do initialization here.
}}}


== Example extension ==

{{{
#!python
Line 21: Line 83:
from mercurial.node import short, hex
Line 28: Line 91:
#
# For experimenting with Mercurial in the python interpreter:
# Getting the repository of the current dir:
# >>> from mercurial import hg, ui
# >>> repo = hg.repository(ui.ui(), path = ".")
Line 37: Line 106:
 # hg.short will return a smaller portion of the sha1
 print "short %s %s" % (hg.short(parents[0]), hg.short(parents[1]))
 # mercurial.node.short returns a smaller portion of the sha1
 print "short %s %s" % (short(parents[0]), short(parents[1]))
Line 40: Line 109:
 # hg.hex will return the full sha1 
 print "long %s %s" % (hg.hex(parents[0]), hg.hex(parents[1]))
 # mercurial.node.hex returns the full sha1
 print "long %s %s" % (hex(parents[0]), hex(parents[1]))
Line 43: Line 112:
 print "default %s %s" % (hg.short(parents[0]), hg.short(parents[1]))  print "default %s %s" % (short(parents[0]), short(parents[1]))
Line 47: Line 116:
    "print-parents": (print_parents,      "print-parents": (print_parents,
Line 52: Line 121:
                     "hg print-parents [options] node")                      "hg print-parents [options] REV")
Line 55: Line 124:
def reposetup(ui, repo):
    pass
    # extension specific setup can go here
Line 59: Line 125:

If `cmdtable` or `reposetup` is not present, your extension will still work. This means that an extension can work "silently", without making new functionality directly visible through the command line interface.

== Where to put extensions in the source tree ==

As of a change shortly after the 0.7 release, the recommended location for installing extensions in the source tree is the `hgext` directory. If you put a file in there called `foo.py`, you will need to refer to it in the `hgrc` file as a qualified package name, `hgext.foo`.

The contents of the `hgext` directory will be installed by the top-level `setup.py` script along with the rest of Mercurial.

----
See CategoryExtension for related pages and ["UsingExtensions"] for a list of readily avaliable extensions bundled with Mercurial or provided by third parties.
----
CategoryExtension CategoryHowTo CategoryInternals

Writing Mercurial extensions

Mercurial features an extension mechanism for adding new commands.

Extensions allow the creation of new features and using them directly from the main hg command line as if they were builtin commands. The extensions have full access to the MercurialApi.

1. Writing your own extension

1.1. File Layout

Extensions are usually written as simple python modules. Larger ones are better split into multiple modules of a single package (see ConvertExtension). The package root module gives its name to the extension and implements the cmdtable and optional callbacks described below.

1.2. Command table

To write your own extension, your python module can provide an optional dict named cmdtable with entries describing each command.

1.2.1. The `cmdtable` dictionary

The cmdtable dictionary uses as key the new command names, and, as value, a tuple containing:

  1. the function name to be called when the command is used.
  2. a list of options the command can take.
  3. a help string for the command.

1.2.2. List of options

Al the command flag options are documented in the mercurial/fancyopts.py sources.

The options list is a list of tuples containing:

  1. a flag specifying if the option is of the short or long sort, like -o or --option.

  2. an option name.
  3. a default value for the option.
  4. a help string for the option.

1.2.3. Example `cmdtable`

cmdtable = {
    # "command-name": (function-call, options-list, help-string)
    "print-parents": (print_parents,
                     [('s', 'short', None, 'print short form'),
                      ('l', 'long', None, 'print long form')],
                     "hg print-parents [options] node")
}

1.3. Command function signatures

Functions that implement new commands always receive a ui and usually a repo parameter. Please see the MercurialApi for information on how to use these. The rest of parameters are taken from the command line items that don't start with a dash and are passed in the same order they were written. If no default value is given in the parameter list they are required.

If there is no repo to be associated with the command and consequently no repo passed then commands should be imported from mercurial and the extension name should be added to commands.norep like this:

from mercurial import commands
...
commands.norepo += " mycommand" 

For examples of norepo see the source code to the RcpathExtension (direct link to attachment:RcpathExtension/rcpath.py extension source) or the ConvertExtension (direct link to [http://hg.intevation.org/mercurial/crew/file/f5f6b7dcd217/hgext/convert/__init__.py#l186 convert] extension source).

1.4. Extension setup

Extensions can implement an optional callback named extsetup. It is called after all the extension are pre-loaded, and can be useful in case one extension optionally depends on another extension.

Signature:

def extsetup():
    # ...

1.5. Repository setup

Extensions can implement an optional callback named reposetup. It is called after the main Mercurial repository initialization, and can be used to setup any local state the extension might need.

As other command functions it receives an ui object and a repo object (no additional parameters for this, though):

def reposetup(ui, repo):
    #do initialization here.

2. Example extension

   1 #!/usr/bin/env python
   2 
   3 from mercurial import hg
   4 from mercurial.node import short, hex
   5 
   6 # every command must take a ui and and repo as arguments.
   7 # opts is a dict where you can find other command line flags
   8 #
   9 # Other parameters are taken in order from items on the command line that
  10 # don't start with a dash.  If no default value is given in the parameter list,
  11 # they are required.
  12 # 
  13 # For experimenting with Mercurial in the python interpreter: 
  14 # Getting the repository of the current dir: 
  15 #    >>> from mercurial import hg, ui
  16 #    >>> repo = hg.repository(ui.ui(), path = ".")
  17 
  18 def print_parents(ui, repo, node, **opts):
  19     # The doc string below will show up in hg help
  20     """Print parent information"""
  21 
  22     # repo.lookup can lookup based on tags, an sha1, or a revision number
  23     node = repo.lookup(node)
  24     parents = repo.changelog.parents(node)
  25 
  26     if opts['short']:
  27         # mercurial.node.short returns a smaller portion of the sha1
  28         print "short %s %s" % (short(parents[0]), short(parents[1]))
  29     elif opts['long']:
  30         # mercurial.node.hex returns the full sha1
  31         print "long %s %s" % (hex(parents[0]), hex(parents[1]))
  32     else:
  33         print "default %s %s" % (short(parents[0]), short(parents[1]))
  34 
  35 cmdtable = {
  36     # cmd name        function call
  37     "print-parents": (print_parents,
  38                      # see mercurial/fancyopts.py for all of the command
  39                      # flag options.
  40                      [('s', 'short', None, 'print short form'),
  41                       ('l', 'long', None, 'print long form')],
  42                      "hg print-parents [options] REV")
  43 }

If cmdtable or reposetup is not present, your extension will still work. This means that an extension can work "silently", without making new functionality directly visible through the command line interface.

3. Where to put extensions in the source tree

As of a change shortly after the 0.7 release, the recommended location for installing extensions in the source tree is the hgext directory. If you put a file in there called foo.py, you will need to refer to it in the hgrc file as a qualified package name, hgext.foo.

The contents of the hgext directory will be installed by the top-level setup.py script along with the rest of Mercurial.


See CategoryExtension for related pages and ["UsingExtensions"] for a list of readily avaliable extensions bundled with Mercurial or provided by third parties.


CategoryExtension CategoryHowTo CategoryInternals

WritingExtensions (last edited 2020-07-29 10:00:07 by aayjaychan)