9404.1.2
by Jonathan Lange
start hacking on autoland. |
1 |
"""Land an approved merge proposal."""
|
2 |
||
10430.2.1
by Brad Crittenden
Fixed comparison between launchpad._root_uri and *_SERVICE_ROOT to account for the fact the former has a version tacked onto it now. |
3 |
from launchpadlib.launchpad import Launchpad |
4 |
from launchpadlib.uris import ( |
|
5 |
DEV_SERVICE_ROOT, EDGE_SERVICE_ROOT, LPNET_SERVICE_ROOT, |
|
6 |
STAGING_SERVICE_ROOT) |
|
9404.1.2
by Jonathan Lange
start hacking on autoland. |
7 |
from lazr.uri import URI |
9644.4.1
by Brad Crittenden
Make ec2 land figure out the merge proposal based on the current branch. |
8 |
from bzrlib.errors import BzrCommandError |
9 |
||
9404.1.2
by Jonathan Lange
start hacking on autoland. |
10 |
|
9404.1.29
by Jonathan Lange
Handle the case when there are no reviewers. |
11 |
class MissingReviewError(Exception): |
12 |
"""Raised when we try to get a review message without enough reviewers."""
|
|
9404.1.2
by Jonathan Lange
start hacking on autoland. |
13 |
|
14 |
||
11079.1.1
by Ursula Junque (Ursinha)
Added the no_qa parameter and how to deal with it in the get_commit_message method. Added an exception class to describe this error: MissingBugsError. |
15 |
class MissingBugsError(Exception): |
11079.1.15
by Ursula Junque (Ursinha)
changed all variables and options from incr to incremental, more self explainable; raising MissingBugs exceptions without a message |
16 |
"""Merge proposal has no linked bugs and no [no-qa] tag."""
|
17 |
||
18 |
||
19 |
class MissingBugsIncrementalError(Exception): |
|
20 |
"""Merge proposal has the [incr] tag but no linked bugs."""
|
|
11079.1.6
by Ursula Junque (Ursinha)
Adding MissingBugsIncrError exception and incr commit tag to the check_qa_clauses method, now changed to check both tags, no-qa and incr. |
21 |
|
22 |
||
9404.1.2
by Jonathan Lange
start hacking on autoland. |
23 |
class LaunchpadBranchLander: |
24 |
||
25 |
name = 'launchpad-branch-lander' |
|
26 |
||
27 |
def __init__(self, launchpad): |
|
28 |
self._launchpad = launchpad |
|
29 |
||
30 |
@classmethod
|
|
11677.3.3
by Robert Collins
More edge removal. |
31 |
def load(cls, service_root='production'): |
9404.1.25
by Jonathan Lange
Compliant XXXs |
32 |
# XXX: JonathanLange 2009-09-24: No unit tests.
|
33 |
# XXX: JonathanLange 2009-09-24 bug=435813: If cached data invalid,
|
|
34 |
# there's no easy way to delete it and try again.
|
|
12143.3.2
by Leonard Richardson
Updated to support the new Launchpad constructor and the return of login_with. |
35 |
launchpad = Launchpad.login_with(cls.name, service_root) |
9404.1.2
by Jonathan Lange
start hacking on autoland. |
36 |
return cls(launchpad) |
37 |
||
38 |
def load_merge_proposal(self, mp_url): |
|
39 |
"""Get the merge proposal object for the 'mp_url'."""
|
|
9404.1.25
by Jonathan Lange
Compliant XXXs |
40 |
# XXX: JonathanLange 2009-09-24: No unit tests.
|
9404.1.2
by Jonathan Lange
start hacking on autoland. |
41 |
web_mp_uri = URI(mp_url) |
42 |
api_mp_uri = self._launchpad._root_uri.append( |
|
43 |
web_mp_uri.path.lstrip('/')) |
|
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
44 |
return MergeProposal(self._launchpad.load(str(api_mp_uri))) |
45 |
||
9644.4.4
by Brad Crittenden
Changes from code review. Fixed get_reviewer_clause to account for multiple review types and mentored reviews. |
46 |
def get_lp_branch(self, branch): |
47 |
"""Get the launchpadlib branch based on a bzr branch."""
|
|
48 |
# First try the public branch.
|
|
49 |
branch_url = branch.get_public_branch() |
|
50 |
if branch_url: |
|
51 |
lp_branch = self._launchpad.branches.getByUrl( |
|
52 |
url=branch_url) |
|
53 |
if lp_branch is not None: |
|
54 |
return lp_branch |
|
55 |
# If that didn't work try the push location.
|
|
56 |
branch_url = branch.get_push_location() |
|
57 |
if branch_url: |
|
58 |
lp_branch = self._launchpad.branches.getByUrl( |
|
59 |
url=branch_url) |
|
60 |
if lp_branch is not None: |
|
61 |
return lp_branch |
|
62 |
raise BzrCommandError( |
|
63 |
"No public branch could be found. Please re-run and specify "
|
|
64 |
"the URL for the merge proposal.") |
|
65 |
||
9644.4.1
by Brad Crittenden
Make ec2 land figure out the merge proposal based on the current branch. |
66 |
def get_merge_proposal_from_branch(self, branch): |
67 |
"""Get the merge proposal from the branch."""
|
|
9644.4.4
by Brad Crittenden
Changes from code review. Fixed get_reviewer_clause to account for multiple review types and mentored reviews. |
68 |
|
69 |
lp_branch = self.get_lp_branch(branch) |
|
9644.4.1
by Brad Crittenden
Make ec2 land figure out the merge proposal based on the current branch. |
70 |
proposals = lp_branch.landing_targets |
9644.4.2
by Brad Crittenden
Fixed error handling for the case when there are no merge proposals. |
71 |
if len(proposals) == 0: |
72 |
raise BzrCommandError( |
|
73 |
"The public branch has no source merge proposals. "
|
|
74 |
"You must have a merge proposal before attempting to "
|
|
75 |
"land the branch.") |
|
76 |
elif len(proposals) > 1: |
|
9644.4.1
by Brad Crittenden
Make ec2 land figure out the merge proposal based on the current branch. |
77 |
raise BzrCommandError( |
78 |
"The public branch has multiple source merge proposals. "
|
|
79 |
"You must provide the URL to the one you wish to use.") |
|
80 |
return MergeProposal(proposals[0]) |
|
81 |
||
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
82 |
|
83 |
class MergeProposal: |
|
9404.1.15
by Jonathan Lange
Docstrings. |
84 |
"""Wrapper around launchpadlib `IBranchMergeProposal` for landing."""
|
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
85 |
|
86 |
def __init__(self, mp): |
|
9404.1.15
by Jonathan Lange
Docstrings. |
87 |
"""Construct a merge proposal.
|
88 |
||
89 |
:param mp: A launchpadlib `IBranchMergeProposal`.
|
|
90 |
"""
|
|
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
91 |
self._mp = mp |
92 |
self._launchpad = mp._root |
|
93 |
||
94 |
@property
|
|
95 |
def source_branch(self): |
|
9404.1.15
by Jonathan Lange
Docstrings. |
96 |
"""The push URL of the source branch."""
|
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
97 |
return str(self._get_push_url(self._mp.source_branch)) |
98 |
||
99 |
@property
|
|
100 |
def target_branch(self): |
|
9404.1.15
by Jonathan Lange
Docstrings. |
101 |
"""The push URL of the target branch."""
|
9404.1.35
by Jonathan Lange
Make target_branch better. |
102 |
return str(self._get_push_url(self._mp.target_branch)) |
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
103 |
|
9404.1.27
by Jonathan Lange
Use EDGE, fix up commit message API. |
104 |
@property
|
105 |
def commit_message(self): |
|
106 |
"""The commit message specified on the merge proposal."""
|
|
107 |
return self._mp.commit_message |
|
108 |
||
9404.1.28
by Jonathan Lange
Check that the merge proposal is approved before landing it. |
109 |
@property
|
110 |
def is_approved(self): |
|
111 |
"""Is this merge proposal approved for landing."""
|
|
112 |
return self._mp.queue_status == 'Approved' |
|
113 |
||
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
114 |
def get_stakeholder_emails(self): |
115 |
"""Return a collection of people who should know about branch landing.
|
|
116 |
||
117 |
Used to determine who to email with the ec2 test results.
|
|
118 |
||
119 |
:return: A set of `IPerson`s.
|
|
120 |
"""
|
|
9404.1.25
by Jonathan Lange
Compliant XXXs |
121 |
# XXX: JonathanLange 2009-09-24: No unit tests.
|
9404.1.30
by Jonathan Lange
Don't specify duplicate email addresses. |
122 |
return set( |
9644.4.5
by Brad Crittenden
Assume no review type is a code review. |
123 |
map(get_email, |
124 |
[self._mp.source_branch.owner, self._launchpad.me])) |
|
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
125 |
|
126 |
def get_reviews(self): |
|
127 |
"""Return a dictionary of all Approved reviews.
|
|
128 |
||
129 |
Used to determine who has actually approved a branch for landing. The
|
|
130 |
key of the dictionary is the type of review, and the value is the list
|
|
131 |
of people who have voted Approve with that type.
|
|
132 |
||
133 |
Common types include 'code', 'db', 'ui' and of course `None`.
|
|
134 |
"""
|
|
135 |
reviews = {} |
|
136 |
for vote in self._mp.votes: |
|
137 |
comment = vote.comment |
|
138 |
if comment is None or comment.vote != "Approve": |
|
139 |
continue
|
|
140 |
reviewers = reviews.setdefault(vote.review_type, []) |
|
141 |
reviewers.append(vote.reviewer) |
|
142 |
return reviews |
|
143 |
||
144 |
def get_bugs(self): |
|
9404.1.15
by Jonathan Lange
Docstrings. |
145 |
"""Return a collection of bugs linked to the source branch."""
|
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
146 |
return self._mp.source_branch.linked_bugs |
147 |
||
148 |
def _get_push_url(self, branch): |
|
9404.1.9
by Jonathan Lange
Make get_push_url work and use it a little. |
149 |
"""Return the push URL for 'branch'.
|
150 |
||
151 |
This function is a work-around for Launchpad's lack of exposing the
|
|
152 |
branch's push URL.
|
|
153 |
||
154 |
:param branch: A launchpadlib `IBranch`.
|
|
155 |
"""
|
|
9404.1.25
by Jonathan Lange
Compliant XXXs |
156 |
# XXX: JonathanLange 2009-09-24: No unit tests.
|
9404.1.9
by Jonathan Lange
Make get_push_url work and use it a little. |
157 |
host = get_bazaar_host(str(self._launchpad._root_uri)) |
9404.1.24
by Jonathan Lange
Substantial amount of comment cleanup. |
158 |
# XXX: JonathanLange 2009-09-24 bug=435790: lazr.uri allows a path
|
159 |
# without a leading '/' and then doesn't insert a '/' in the final
|
|
160 |
# URL. Do it ourselves.
|
|
9404.1.9
by Jonathan Lange
Make get_push_url work and use it a little. |
161 |
return URI(scheme='bzr+ssh', host=host, path='/' + branch.unique_name) |
9404.1.2
by Jonathan Lange
start hacking on autoland. |
162 |
|
11869.5.2
by Diogo Matsubara
change get_commit_message to build_commit_message since that's what the method is actually doing. |
163 |
def build_commit_message(self, commit_text, testfix=False, no_qa=False, |
11490.1.2
by Diogo Matsubara
implement the rollback option and add more tests for the no-qa and incr options |
164 |
incremental=False, rollback=None): |
9404.1.14
by Jonathan Lange
Extract a merge proposal wrapper class out of the functions. |
165 |
"""Get the Launchpad-style commit message for a merge proposal."""
|
166 |
reviews = self.get_reviews() |
|
167 |
bugs = self.get_bugs() |
|
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
168 |
|
11869.5.3
by Diogo Matsubara
add code to remove duplicate tags from commit message |
169 |
tags = [ |
11079.1.19
by Ursula Junque (Ursinha)
changes suggested by jtv: how to generate clauses string and some elifs |
170 |
get_testfix_clause(testfix), |
171 |
get_reviewer_clause(reviews), |
|
172 |
get_bugs_clause(bugs), |
|
173 |
get_qa_clause(bugs, no_qa, |
|
11490.1.2
by Diogo Matsubara
implement the rollback option and add more tests for the no-qa and incr options |
174 |
incremental, rollback=rollback), |
11869.5.3
by Diogo Matsubara
add code to remove duplicate tags from commit message |
175 |
]
|
176 |
||
177 |
# Make sure we don't add duplicated tags to commit_text.
|
|
178 |
commit_tags = tags[:] |
|
179 |
for tag in tags: |
|
180 |
if tag in commit_text: |
|
181 |
commit_tags.remove(tag) |
|
182 |
||
183 |
if commit_tags: |
|
184 |
return '%s %s' % (''.join(commit_tags), commit_text) |
|
185 |
else: |
|
186 |
return commit_text |
|
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
187 |
|
11869.5.1
by Diogo Matsubara
set the commit message in the merge proposal from the built commit message. |
188 |
def set_commit_message(self, commit_message): |
189 |
"""Set the Launchpad-style commit message for a merge proposal."""
|
|
190 |
self._mp.commit_message = commit_message |
|
191 |
self._mp.lp_save() |
|
192 |
||
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
193 |
|
194 |
def get_testfix_clause(testfix=False): |
|
195 |
"""Get the testfix clause."""
|
|
11079.1.19
by Ursula Junque (Ursinha)
changes suggested by jtv: how to generate clauses string and some elifs |
196 |
if testfix: |
197 |
testfix_clause = '[testfix]' |
|
198 |
else: |
|
199 |
testfix_clause = '' |
|
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
200 |
return testfix_clause |
201 |
||
202 |
||
11490.1.2
by Diogo Matsubara
implement the rollback option and add more tests for the no-qa and incr options |
203 |
def get_qa_clause(bugs, no_qa=False, incremental=False, rollback=None): |
11079.1.15
by Ursula Junque (Ursinha)
changed all variables and options from incr to incremental, more self explainable; raising MissingBugs exceptions without a message |
204 |
"""Check the no-qa and incremental options, getting the qa clause.
|
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
205 |
|
11490.1.1
by Diogo Matsubara
implement the no-qa and incr use case in the autoland.py script |
206 |
The qa clause will always be or no-qa, or incremental, or no-qa and
|
11490.1.2
by Diogo Matsubara
implement the rollback option and add more tests for the no-qa and incr options |
207 |
incremental, or a revno for the rollback clause, or no tags.
|
208 |
||
209 |
See https://dev.launchpad.net/QAProcessContinuousRollouts for detailed
|
|
210 |
explanation of each clause.
|
|
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
211 |
"""
|
212 |
qa_clause = "" |
|
11079.1.6
by Ursula Junque (Ursinha)
Adding MissingBugsIncrError exception and incr commit tag to the check_qa_clauses method, now changed to check both tags, no-qa and incr. |
213 |
|
11490.1.2
by Diogo Matsubara
implement the rollback option and add more tests for the no-qa and incr options |
214 |
if not bugs and not no_qa and not incremental and not rollback: |
11079.1.15
by Ursula Junque (Ursinha)
changed all variables and options from incr to incremental, more self explainable; raising MissingBugs exceptions without a message |
215 |
raise MissingBugsError |
216 |
||
217 |
if incremental and not bugs: |
|
218 |
raise MissingBugsIncrementalError |
|
219 |
||
11490.1.1
by Diogo Matsubara
implement the no-qa and incr use case in the autoland.py script |
220 |
if no_qa and incremental: |
221 |
qa_clause = '[no-qa][incr]' |
|
222 |
elif incremental: |
|
11079.1.19
by Ursula Junque (Ursinha)
changes suggested by jtv: how to generate clauses string and some elifs |
223 |
qa_clause = '[incr]' |
224 |
elif no_qa: |
|
225 |
qa_clause = '[no-qa]' |
|
11490.1.2
by Diogo Matsubara
implement the rollback option and add more tests for the no-qa and incr options |
226 |
elif rollback: |
227 |
qa_clause = '[rollback=%d]' % rollback |
|
11079.1.19
by Ursula Junque (Ursinha)
changes suggested by jtv: how to generate clauses string and some elifs |
228 |
else: |
229 |
qa_clause = '' |
|
11079.1.6
by Ursula Junque (Ursinha)
Adding MissingBugsIncrError exception and incr commit tag to the check_qa_clauses method, now changed to check both tags, no-qa and incr. |
230 |
|
11079.1.12
by Ursula Junque (Ursinha)
applied changes suggested by jtv: strip the string handling and trying to use tags, inside get_commit_message now I just join the clauses and create the commit msg. |
231 |
return qa_clause |
11079.1.3
by Ursula Junque (Ursinha)
created a separated method to take care of the no-qa tag, check_qa_clause |
232 |
|
233 |
||
9404.1.11
by Jonathan Lange
Tie everything together to make the default command line. |
234 |
def get_email(person): |
9404.1.17
by Jonathan Lange
More docstrings. |
235 |
"""Get the preferred email address for 'person'."""
|
9404.1.11
by Jonathan Lange
Tie everything together to make the default command line. |
236 |
email_object = person.preferred_email_address |
9404.1.24
by Jonathan Lange
Substantial amount of comment cleanup. |
237 |
# XXX: JonathanLange 2009-09-24 bug=319432: This raises a very obscure
|
238 |
# error when the email address isn't set. e.g. with name12 in the sample
|
|
239 |
# data. e.g. "httplib2.RelativeURIError: Only absolute URIs are allowed.
|
|
240 |
# uri = tag:launchpad.net:2008:redacted".
|
|
9404.1.11
by Jonathan Lange
Tie everything together to make the default command line. |
241 |
return email_object.email |
242 |
||
9404.1.2
by Jonathan Lange
start hacking on autoland. |
243 |
|
244 |
def get_bugs_clause(bugs): |
|
9404.1.4
by Jonathan Lange
More tests. |
245 |
"""Return the bugs clause of a commit message.
|
246 |
||
247 |
:param bugs: A collection of `IBug` objects.
|
|
248 |
:return: A string of the form "[bug=A,B,C]".
|
|
249 |
"""
|
|
9404.1.2
by Jonathan Lange
start hacking on autoland. |
250 |
if not bugs: |
251 |
return '' |
|
252 |
return '[bug=%s]' % ','.join(str(bug.id) for bug in bugs) |
|
253 |
||
254 |
||
9404.1.4
by Jonathan Lange
More tests. |
255 |
def get_reviewer_handle(reviewer): |
256 |
"""Get the handle for 'reviewer'.
|
|
257 |
||
258 |
The handles of reviewers are included in the commit message for Launchpad
|
|
259 |
changes. Historically, these handles have been the IRC nicks. Thus, if
|
|
260 |
'reviewer' has an IRC nickname for Freenode, we use that. Otherwise we use
|
|
261 |
their Launchpad username.
|
|
262 |
||
263 |
:param reviewer: A launchpadlib `IPerson` object.
|
|
9404.1.5
by Jonathan Lange
Get the reviewer string. |
264 |
:return: unicode text.
|
9404.1.4
by Jonathan Lange
More tests. |
265 |
"""
|
266 |
irc_handles = reviewer.irc_nicknames |
|
267 |
for handle in irc_handles: |
|
268 |
if handle.network == 'irc.freenode.net': |
|
269 |
return handle.nickname |
|
270 |
return reviewer.name |
|
271 |
||
272 |
||
9404.1.26
by Jonathan Lange
Release-critical support added. |
273 |
def _comma_separated_names(things): |
9644.4.7
by Brad Crittenden
Fixed test failures and added a test for mentored reviews. |
274 |
"""Return a string of comma-separated names of 'things'.
|
275 |
||
276 |
The list is sorted before being joined.
|
|
277 |
"""
|
|
278 |
return ','.join(sorted(thing.name for thing in things)) |
|
9404.1.26
by Jonathan Lange
Release-critical support added. |
279 |
|
280 |
||
9404.1.5
by Jonathan Lange
Get the reviewer string. |
281 |
def get_reviewer_clause(reviewers): |
282 |
"""Get the reviewer section of a commit message, given the reviewers.
|
|
283 |
||
284 |
:param reviewers: A dict mapping review types to lists of reviewers, as
|
|
285 |
returned by 'get_reviews'.
|
|
286 |
:return: A string like u'[r=foo,bar][ui=plop]'.
|
|
287 |
"""
|
|
9862.1.2
by Aaron Bentley
Handle the case where the reviewer field is ''. |
288 |
# If no review type is specified it is assumed to be a code review.
|
9644.4.5
by Brad Crittenden
Assume no review type is a code review. |
289 |
code_reviewers = reviewers.get(None, []) |
9644.4.4
by Brad Crittenden
Changes from code review. Fixed get_reviewer_clause to account for multiple review types and mentored reviews. |
290 |
ui_reviewers = [] |
291 |
rc_reviewers = [] |
|
292 |
for review_type, reviewer in reviewers.items(): |
|
9644.4.7
by Brad Crittenden
Fixed test failures and added a test for mentored reviews. |
293 |
if review_type is None: |
294 |
continue
|
|
9862.1.2
by Aaron Bentley
Handle the case where the reviewer field is ''. |
295 |
if review_type == '': |
296 |
code_reviewers.extend(reviewer) |
|
9644.4.7
by Brad Crittenden
Fixed test failures and added a test for mentored reviews. |
297 |
if 'code' in review_type or 'db' in review_type: |
9644.4.4
by Brad Crittenden
Changes from code review. Fixed get_reviewer_clause to account for multiple review types and mentored reviews. |
298 |
code_reviewers.extend(reviewer) |
299 |
if 'ui' in review_type: |
|
300 |
ui_reviewers.extend(reviewer) |
|
301 |
if 'release-critical' in review_type: |
|
302 |
rc_reviewers.extend(reviewer) |
|
9404.1.29
by Jonathan Lange
Handle the case when there are no reviewers. |
303 |
if not code_reviewers: |
304 |
raise MissingReviewError("Need approved votes in order to land.") |
|
9404.1.5
by Jonathan Lange
Get the reviewer string. |
305 |
if ui_reviewers: |
12289.3.1
by William Grant
Don't add [ui=none] if there are no UI reviewers. The PQM regexp no longer requires it. |
306 |
ui_clause = '[ui=%s]' % _comma_separated_names(ui_reviewers) |
9404.1.5
by Jonathan Lange
Get the reviewer string. |
307 |
else: |
12289.3.1
by William Grant
Don't add [ui=none] if there are no UI reviewers. The PQM regexp no longer requires it. |
308 |
ui_clause = '' |
9404.1.26
by Jonathan Lange
Release-critical support added. |
309 |
if rc_reviewers: |
310 |
rc_clause = ( |
|
311 |
'[release-critical=%s]' % _comma_separated_names(rc_reviewers)) |
|
312 |
else: |
|
313 |
rc_clause = '' |
|
12289.3.1
by William Grant
Don't add [ui=none] if there are no UI reviewers. The PQM regexp no longer requires it. |
314 |
return '%s[r=%s]%s' % ( |
9404.1.26
by Jonathan Lange
Release-critical support added. |
315 |
rc_clause, _comma_separated_names(code_reviewers), ui_clause) |
9404.1.5
by Jonathan Lange
Get the reviewer string. |
316 |
|
317 |
||
9404.1.7
by Jonathan Lange
Add a function that will return the bazaar host given an API root. |
318 |
def get_bazaar_host(api_root): |
319 |
"""Get the Bazaar service for the given API root."""
|
|
9404.1.24
by Jonathan Lange
Substantial amount of comment cleanup. |
320 |
# XXX: JonathanLange 2009-09-24 bug=435803: This is only needed because
|
321 |
# Launchpad doesn't expose the push URL for branches.
|
|
10430.2.1
by Brad Crittenden
Fixed comparison between launchpad._root_uri and *_SERVICE_ROOT to account for the fact the former has a version tacked onto it now. |
322 |
if api_root.startswith(EDGE_SERVICE_ROOT): |
9404.1.7
by Jonathan Lange
Add a function that will return the bazaar host given an API root. |
323 |
return 'bazaar.launchpad.net' |
10430.2.1
by Brad Crittenden
Fixed comparison between launchpad._root_uri and *_SERVICE_ROOT to account for the fact the former has a version tacked onto it now. |
324 |
elif api_root.startswith(DEV_SERVICE_ROOT): |
9404.1.7
by Jonathan Lange
Add a function that will return the bazaar host given an API root. |
325 |
return 'bazaar.launchpad.dev' |
10430.2.1
by Brad Crittenden
Fixed comparison between launchpad._root_uri and *_SERVICE_ROOT to account for the fact the former has a version tacked onto it now. |
326 |
elif api_root.startswith(STAGING_SERVICE_ROOT): |
9404.1.7
by Jonathan Lange
Add a function that will return the bazaar host given an API root. |
327 |
return 'bazaar.staging.launchpad.net' |
10430.2.1
by Brad Crittenden
Fixed comparison between launchpad._root_uri and *_SERVICE_ROOT to account for the fact the former has a version tacked onto it now. |
328 |
elif api_root.startswith(LPNET_SERVICE_ROOT): |
9404.1.7
by Jonathan Lange
Add a function that will return the bazaar host given an API root. |
329 |
return 'bazaar.launchpad.net' |
330 |
else: |
|
331 |
raise ValueError( |
|
332 |
'Cannot determine Bazaar host. "%s" not a recognized Launchpad ' |
|
333 |
'API root.' % (api_root,)) |