/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/bugtracker.py

  • Committer: Jonathan Lange
  • Date: 2007-04-17 07:59:42 UTC
  • mto: This revision was merged to the branch mainline in revision 2446.
  • Revision ID: jml@canonical.com-20070417075942-1vfzpwjf8rvbty1f
Variety of whitespace cleanups, tightening of tests and docstring changes in
response to review of bug support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007 Canonical Ltd
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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
 
16
 
 
17
 
 
18
from bzrlib import registry
 
19
from bzrlib.lazy_import import lazy_import
 
20
lazy_import(globals(), """
 
21
from bzrlib import errors, urlutils
 
22
""")
 
23
 
 
24
 
 
25
"""Provides a shorthand for referring to bugs on a variety of bug trackers.
 
26
 
 
27
'commit --fixes' stores references to bugs as a <bug_url> -> <bug_status>
 
28
mapping in the properties for that revision.
 
29
 
 
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
 
32
branch.
 
33
 
 
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.
 
38
"""
 
39
 
 
40
 
 
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)
 
44
 
 
45
 
 
46
class TrackerRegistry(registry.Registry):
 
47
    """Registry of bug tracker types."""
 
48
 
 
49
    def get_tracker(self, tag, branch):
 
50
        """Return the first registered tracker that understands 'tag'.
 
51
 
 
52
        If no such tracker is found, raise KeyError.
 
53
        """
 
54
        for tracker_name, tracker_type in self.iteritems():
 
55
            tracker = tracker_type.get(tag, branch)
 
56
            if tracker is not None:
 
57
                return tracker
 
58
        raise KeyError("No tracker found for %r on %r" % (tag, branch))
 
59
 
 
60
 
 
61
tracker_registry = TrackerRegistry()
 
62
"""Registry of bug trackers."""
 
63
 
 
64
 
 
65
class UniqueBugTracker(object):
 
66
    """A style of bug tracker that exists in one place only, such as Launchpad.
 
67
 
 
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
 
71
    appended to.
 
72
 
 
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.
 
75
    """
 
76
 
 
77
    @classmethod
 
78
    def get(klass, tag, branch):
 
79
        """Returns the tracker if the tag matches. Returns None otherwise."""
 
80
        if tag != klass.tag:
 
81
            return None
 
82
        return klass()
 
83
 
 
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)
 
88
 
 
89
    def check_bug_id(self, bug_id):
 
90
        """Check that the bug_id is valid.
 
91
 
 
92
        The base implementation assumes that all bug_ids are valid.
 
93
        """
 
94
 
 
95
 
 
96
class UniqueIntegerBugTracker(UniqueBugTracker):
 
97
    """A SimpleBugtracker where the bug ids must be integers"""
 
98
 
 
99
    def check_bug_id(self, bug_id):
 
100
        try:
 
101
            int(bug_id)
 
102
        except ValueError:
 
103
            raise errors.MalformedBugIdentifier(bug_id, "Must be an integer")
 
104
 
 
105
 
 
106
class LaunchpadTracker(UniqueIntegerBugTracker):
 
107
    """The Launchpad bug tracker."""
 
108
    tag = 'lp'
 
109
    base_url = 'https://launchpad.net/bugs/'
 
110
 
 
111
tracker_registry.register('launchpad', LaunchpadTracker)
 
112
 
 
113
 
 
114
class DebianTracker(UniqueIntegerBugTracker):
 
115
    """The Debian bug tracker."""
 
116
    tag = 'deb'
 
117
    base_url = 'http://bugs.debian.org/'
 
118
 
 
119
tracker_registry.register('debian', DebianTracker)
 
120
 
 
121
 
 
122
class TracTracker(object):
 
123
    """A Trac instance."""
 
124
 
 
125
    @classmethod
 
126
    def get(klass, tag, branch):
 
127
        """Return a TracTracker for the given tag.
 
128
 
 
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.
 
131
        e.g.
 
132
            trac_twisted_url = http://twistedmatrix.com
 
133
        """
 
134
        url = branch.get_config().get_user_option('trac_%s_url' % (tag,))
 
135
        if url is None:
 
136
            return None
 
137
        return klass(url)
 
138
 
 
139
    def __init__(self, url):
 
140
        self._url = url
 
141
 
 
142
    def get_bug_url(self, bug_id):
 
143
        """Return a URL for a bug on this Trac instance."""
 
144
        try:
 
145
            int(bug_id)
 
146
        except ValueError:
 
147
            raise errors.MalformedBugIdentifier(bug_id, "Must be an integer")
 
148
        return urlutils.join(self._url, 'ticket', bug_id)
 
149
 
 
150
tracker_registry.register('trac', TracTracker)