| [4247] | 1 | #!/usr/bin/env python |
|---|
| 2 | """ |
|---|
| 3 | Repository Change Listener plugin for trac |
|---|
| 4 | |
|---|
| 5 | This module provides an entry point for trac callable |
|---|
| 6 | from the command line |
|---|
| 7 | """ |
|---|
| 8 | |
|---|
| 9 | import os |
|---|
| 10 | import sys |
|---|
| 11 | |
|---|
| 12 | from optparse import OptionParser |
|---|
| 13 | from repository_hook_system.interface import IRepositoryChangeListener |
|---|
| 14 | from trac.core import * |
|---|
| 15 | from trac.env import open_environment |
|---|
| 16 | from trac.versioncontrol.api import NoSuchChangeset |
|---|
| 17 | |
|---|
| 18 | class RepositoryChangeListener(object): |
|---|
| 19 | # XXX this doesn't need to be a class...yet! |
|---|
| 20 | |
|---|
| 21 | def __init__(self, project, hook, *args): |
|---|
| 22 | """ |
|---|
| 23 | * project : path to the trac project environment |
|---|
| 24 | * hook : name of the hook called from |
|---|
| 25 | * args : arguments for the particular implementation of IRepositoryChangeListener |
|---|
| 26 | """ |
|---|
| 27 | |
|---|
| 28 | # open the trac environment |
|---|
| 29 | env = open_environment(project) |
|---|
| 30 | repo = env.get_repository() # XXX multiproject branch |
|---|
| 31 | repo.sync() |
|---|
| 32 | |
|---|
| 33 | # find the active listeners |
|---|
| 34 | listeners = ExtensionPoint(IRepositoryChangeListener).extensions(env) |
|---|
| [5055] | 35 | |
|---|
| [4247] | 36 | # find the listener for the given repository type and invoke the hook |
|---|
| 37 | for listener in listeners: |
|---|
| 38 | if env.config.get('trac', 'repository_type') in listener.type(): |
|---|
| [5077] | 39 | changeset = listener.changeset(repo, hook, *args) |
|---|
| [4247] | 40 | subscribers = listener.subscribers(hook) |
|---|
| 41 | for subscriber in subscribers: |
|---|
| [5055] | 42 | subscriber.invoke(changeset) |
|---|
| [4247] | 43 | |
|---|
| 44 | def filename(): |
|---|
| 45 | return os.path.abspath(__file__.rstrip('c')) |
|---|
| 46 | |
|---|
| 47 | def command_line(projects, hook, *args): |
|---|
| 48 | """return a generic command line for invoking this file""" |
|---|
| 49 | |
|---|
| 50 | # arguments to the command line |
|---|
| 51 | # XXX this could be returned as a list, if there is a reason to do so |
|---|
| 52 | retval = [ sys.executable, filename() ] |
|---|
| 53 | |
|---|
| 54 | # enable passing just one argument |
|---|
| 55 | if isinstance(projects, basestring): |
|---|
| 56 | projects = [ projects ] |
|---|
| 57 | |
|---|
| 58 | # append the projects to the command line |
|---|
| 59 | for project in projects: |
|---|
| 60 | retval.extend(['-p', project]) |
|---|
| 61 | |
|---|
| 62 | # add the hook |
|---|
| 63 | retval.extend(['--hook', hook]) |
|---|
| 64 | |
|---|
| 65 | # add the arguments |
|---|
| 66 | retval.extend(args) |
|---|
| 67 | |
|---|
| 68 | return ' '.join(retval) |
|---|
| 69 | |
|---|
| 70 | def option_parser(): |
|---|
| 71 | parser = OptionParser() |
|---|
| 72 | parser.add_option('-p', '--project', '--projects', |
|---|
| 73 | dest='projects', action='append', |
|---|
| 74 | default=[], |
|---|
| 75 | help='projects to apply to', |
|---|
| 76 | ) |
|---|
| 77 | parser.add_option('--hook', |
|---|
| 78 | dest='hook', |
|---|
| 79 | help='hook called') |
|---|
| 80 | return parser |
|---|
| 81 | |
|---|
| 82 | if __name__ == '__main__': |
|---|
| 83 | |
|---|
| 84 | # obtain command line options |
|---|
| 85 | # the arguments should be those needed for the particular |
|---|
| 86 | # implementation of IRepositoryChangeListener |
|---|
| 87 | parser = option_parser() |
|---|
| 88 | options, args = parser.parse_args() |
|---|
| 89 | |
|---|
| 90 | # TODO: ensure --hook is passed |
|---|
| 91 | |
|---|
| 92 | for project in options.projects: |
|---|
| 93 | RepositoryChangeListener(project, options.hook, *args) |
|---|