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