| 1 | # -*- coding: iso-8859-1 -*-
|
|---|
| 2 | #
|
|---|
| 3 | # Copyright (C) 2011-2012 Edgewall Software
|
|---|
| 4 | # All rights reserved.
|
|---|
| 5 | #
|
|---|
| 6 | # This software may be used and distributed according to the terms
|
|---|
| 7 | # of the GNU General Public License, incorporated herein by reference.
|
|---|
| 8 | #
|
|---|
| 9 | # This software consists of voluntary contributions made by many
|
|---|
| 10 | # individuals. For the exact contribution history, see the revision
|
|---|
| 11 | # history and logs, available at http://trac.edgewall.org/log/.
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 | """
|
|---|
| 15 | Mercurial hook calling `trac-admin $ENV changeset added` for newly added
|
|---|
| 16 | changesets
|
|---|
| 17 |
|
|---|
| 18 | The Trac environments to be notified are configured in the `[trac]` section
|
|---|
| 19 | of `hgrc`. The path to an environment is specified in the `env` key. More
|
|---|
| 20 | environments can be specified by adding a suffix separated by a dot.
|
|---|
| 21 |
|
|---|
| 22 | The path to the `trac-admin` executable can be specified in the `trac-admin`
|
|---|
| 23 | key. A specific path can be set for each environment, by adding the same
|
|---|
| 24 | suffix to the `trac-admin` key.
|
|---|
| 25 |
|
|---|
| 26 | The maximum number of changesets to pass per call to `trac-admin` can be
|
|---|
| 27 | configured with the `revs_per_call` key. The default is relatively low (80
|
|---|
| 28 | on Windows, 500 on other systems) for maximum compatibility, and can be
|
|---|
| 29 | increased if you often push thousands of changesets and the system supports
|
|---|
| 30 | it.
|
|---|
| 31 |
|
|---|
| 32 | If the `trac-admin` option is left empty, the hook opens the Trac environment
|
|---|
| 33 | and calls the relevant Trac hook directly in the same process. This will only
|
|---|
| 34 | work if Trac can be imported by the Python interpreter running Mercurial (e.g.
|
|---|
| 35 | if both are installed globally). Note that this may result in increased memory
|
|---|
| 36 | usage if Mercurial is executed as a long-running process (e.g. hgweb in WSGI
|
|---|
| 37 | mode). In this last case, the option `cache_env` can be set to `true` to
|
|---|
| 38 | cache the Trac environments across invocations, therefore avoiding the
|
|---|
| 39 | environment setup time on each invocation.
|
|---|
| 40 |
|
|---|
| 41 | If the Mercurial plugin is installed globally (i.e. not in one of Trac's
|
|---|
| 42 | plugins directories), the hooks can be configured as follows:
|
|---|
| 43 | {{{
|
|---|
| 44 | [hooks]
|
|---|
| 45 | commit = python:tracext.hg.hooks.add_changesets
|
|---|
| 46 | changegroup = python:tracext.hg.hooks.add_changesets
|
|---|
| 47 | }}}
|
|---|
| 48 |
|
|---|
| 49 | Otherwise, place this file somewhere accessible, and configure the hooks as
|
|---|
| 50 | follows:
|
|---|
| 51 | {{{
|
|---|
| 52 | [hooks]
|
|---|
| 53 | commit = python:/path/to/hooks.py:add_changesets
|
|---|
| 54 | changegroup = python:/path/to/hooks.py:add_changesets
|
|---|
| 55 | }}}
|
|---|
| 56 |
|
|---|
| 57 | A typical configuration for three environments looks like this:
|
|---|
| 58 | {{{
|
|---|
| 59 | [trac]
|
|---|
| 60 | ; For a single Trac environment
|
|---|
| 61 | env = /path/to/env
|
|---|
| 62 | trac-admin = /path/to/trac-admin
|
|---|
| 63 |
|
|---|
| 64 | ; Two more environments, with a specific trac-admin for the second
|
|---|
| 65 | env.other = /path/to/other/env
|
|---|
| 66 | env.third = /path/to/third/env
|
|---|
| 67 | trac-admin.third = /path/to/third/trac-admin
|
|---|
| 68 | }}}
|
|---|
| 69 | """
|
|---|
| 70 |
|
|---|
| 71 | import os.path
|
|---|
| 72 | import subprocess
|
|---|
| 73 |
|
|---|
| 74 | close_fds = os.name == 'posix'
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 | def expand_path(path):
|
|---|
| 78 | """Expand user references and environment variables in a path."""
|
|---|
| 79 | return os.path.expanduser(os.path.expandvars(path))
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 | def add_changesets(ui, repo, node, **kwargs):
|
|---|
| 83 | """Commit hook calling `trac-admin $ENV changeset added $REPO $NODE ...`
|
|---|
| 84 | on all configured Trac environments, for all newly added changesets.
|
|---|
| 85 | """
|
|---|
| 86 | revs = range(repo[node].rev(), len(repo))
|
|---|
| 87 | error = False
|
|---|
| 88 | for name, env in ui.configitems('trac'):
|
|---|
| 89 | p = name.split('.', 1)
|
|---|
| 90 | if p[0] != 'env' or not env:
|
|---|
| 91 | continue
|
|---|
| 92 | env = expand_path(env)
|
|---|
| 93 |
|
|---|
| 94 | trac_admin = ui.config('trac', 'trac-admin', '')
|
|---|
| 95 | if len(p) > 1:
|
|---|
| 96 | trac_admin = ui.config('trac', 'trac-admin.' + p[1], trac_admin)
|
|---|
| 97 |
|
|---|
| 98 | if not trac_admin:
|
|---|
| 99 | cache_env = ui.configbool('trac', 'cache_env')
|
|---|
| 100 | from trac.env import open_environment
|
|---|
| 101 | from trac.versioncontrol.api import RepositoryManager
|
|---|
| 102 | env = open_environment(env, use_cache=cache_env)
|
|---|
| 103 | RepositoryManager(env).notify('changeset_added', repo.root, revs)
|
|---|
| 104 | continue
|
|---|
| 105 |
|
|---|
| 106 | try:
|
|---|
| 107 | revs_per_call = int(ui.config('trac', 'revs_per_call'))
|
|---|
| 108 | except (TypeError, ValueError):
|
|---|
| 109 | revs_per_call = 160 if os.name == 'nt' else 1000
|
|---|
| 110 |
|
|---|
| 111 | trac_admin = expand_path(trac_admin)
|
|---|
| 112 | for i in xrange(0, len(revs), revs_per_call):
|
|---|
| 113 | command = [trac_admin, env, 'changeset', 'added', repo.root]
|
|---|
| 114 | command.extend(str(r) for r in revs[i : i + revs_per_call])
|
|---|
| 115 | ui.debug("Calling %r\n" % (command,))
|
|---|
| 116 | proc = subprocess.Popen(command, close_fds=close_fds,
|
|---|
| 117 | stdout=subprocess.PIPE,
|
|---|
| 118 | stdin=subprocess.PIPE,
|
|---|
| 119 | stderr=subprocess.STDOUT)
|
|---|
| 120 | stdout, stderr = proc.communicate()
|
|---|
| 121 | ui.write(stdout)
|
|---|
| 122 | if proc.returncode != 0:
|
|---|
| 123 | error = True
|
|---|
| 124 | ui.warn("trac-admin failed with return code %d for "
|
|---|
| 125 | "environment:\n %s\n" % (proc.returncode, env))
|
|---|
| 126 | return error
|
|---|