1
# Copyright (C) 2007 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from bzrlib import registry
19
from bzrlib.lazy_import import lazy_import
20
lazy_import(globals(), """
21
from bzrlib import errors, urlutils
25
"""Provides a shorthand for referring to bugs on a variety of bug trackers.
27
'commit --fixes' stores references to bugs as a <bug_url> -> <bug_status>
28
mapping in the properties for that revision.
30
However, it's inconvenient to type out full URLs for bugs on the command line,
31
particularly given that many users will be using only a single bug tracker per
34
Thus, this module provides a registry of types of bug tracker (e.g. Launchpad,
35
Trac). Given a short-hand tag (e.g. 'lp', 'twisted') and a branch with
36
configuration information, these tracker types can return an instance capable
37
of converting bug IDs into URLs.
41
def get_bug_url(tag, branch, bug_id):
42
"""Return a URL pointing to the bug identified by 'bug_id'."""
43
return tracker_registry.get_tracker(tag, branch).get_bug_url(bug_id)
46
class TrackerRegistry(registry.Registry):
47
"""Registry of bug tracker types."""
49
def get_tracker(self, tag, branch):
50
"""Return the first registered tracker that understands 'tag'.
52
If no such tracker is found, raise KeyError.
54
for tracker_name, tracker_type in self.iteritems():
55
tracker = tracker_type.get(tag, branch)
56
if tracker is not None:
58
raise KeyError("No tracker found for %r on %r" % (tag, branch))
61
tracker_registry = TrackerRegistry()
62
"""Registry of bug trackers."""
65
class UniqueBugTracker(object):
66
"""A style of bug tracker that exists in one place only, such as Launchpad.
68
If you have one of these trackers then subclass this and add attributes
69
named 'tag' and 'base_url'. The former is the tag that the user will use
70
on the command line. The latter is the url that the bug ids will be
73
If the bug_id must have a special form then override check_bug_id and
74
raise an exception if the bug_id is not valid.
78
def get(klass, tag, branch):
79
"""Returns the tracker if the tag matches. Returns None otherwise."""
84
def get_bug_url(self, bug_id):
85
"""Return the URL for bug_id."""
86
self.check_bug_id(bug_id)
87
return urlutils.join(self.base_url, bug_id)
89
def check_bug_id(self, bug_id):
90
"""Check that the bug_id is valid.
92
The base implementation assumes that all bug_ids are valid.
96
class UniqueIntegerBugTracker(UniqueBugTracker):
97
"""A SimpleBugtracker where the bug ids must be integers"""
99
def check_bug_id(self, bug_id):
103
raise errors.MalformedBugIdentifier(bug_id, "Must be an integer")
106
class LaunchpadTracker(UniqueIntegerBugTracker):
107
"""The Launchpad bug tracker."""
109
base_url = 'https://launchpad.net/bugs/'
111
tracker_registry.register('launchpad', LaunchpadTracker)
114
class DebianTracker(UniqueIntegerBugTracker):
115
"""The Debian bug tracker."""
117
base_url = 'http://bugs.debian.org/'
119
tracker_registry.register('debian', DebianTracker)
122
class TracTracker(object):
123
"""A Trac instance."""
126
def get(klass, tag, branch):
127
"""Return a TracTracker for the given tag.
129
Looks in the configuration of 'branch' for a 'trac_<tag>_url' setting,
130
which should refer to the base URL of a project's Trac instance.
132
trac_twisted_url = http://twistedmatrix.com
134
url = branch.get_config().get_user_option('trac_%s_url' % (tag,))
139
def __init__(self, url):
142
def get_bug_url(self, bug_id):
143
"""Return a URL for a bug on this Trac instance."""
147
raise errors.MalformedBugIdentifier(bug_id, "Must be an integer")
148
return urlutils.join(self._url, 'ticket', bug_id)
150
tracker_registry.register('trac', TracTracker)