12293.1.11
by Curtis Hovey
Updated copyright. |
1 |
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
|
8687.15.17
by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
1102.1.74
by David Allouche
$branch/+edit form |
3 |
|
4 |
"""Branch views."""
|
|
5 |
||
6 |
__metaclass__ = type |
|
7 |
||
1102.1.143
by David Allouche
Review fixes to Branch view. |
8 |
__all__ = [ |
8120.2.11
by Jonathan Lange
Delete PersonBranchAddView and ProductBranchAddView, since the only |
9 |
'BranchAddView', |
1102.1.143
by David Allouche
Review fixes to Branch view. |
10 |
'BranchContextMenu', |
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
11 |
'BranchDeletionView', |
9570.12.1
by Tim Penhey
Add a link and simple view for editing the status. |
12 |
'BranchEditStatusView', |
1102.1.143
by David Allouche
Review fixes to Branch view. |
13 |
'BranchEditView', |
5350.3.2
by Tim Penhey
Allow any logged in user to edit the branch whiteboard. |
14 |
'BranchEditWhiteboardView', |
6233.6.1
by Michael Hudson
stuff |
15 |
'BranchRequestImportView', |
7211.1.4
by Tim Penhey
Changed view names and added test. |
16 |
'BranchReviewerEditView', |
5579.2.1
by Tim Penhey
Some queue management |
17 |
'BranchMergeQueueView', |
4795.2.10
by jml at canonical
Rename mirror failure to mirror status |
18 |
'BranchMirrorStatusView', |
11515.8.3
by Brad Crittenden
Redesign code product page. Created code +portlet-codestatistics. |
19 |
'BranchMirrorMixin', |
10456.2.13
by Brad Crittenden
Added browser support for other +setbranch options |
20 |
'BranchNameValidationMixin', |
3283.3.2
by Brad Bollenbach
fixes based on talking to the sab this morning. tightening up the security model a bit by basing privileges on an IHasBug interface. |
21 |
'BranchNavigation', |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
22 |
'BranchEditMenu', |
3277.3.2
by David Allouche
better branch listings |
23 |
'BranchInProductView', |
7675.477.1
by Paul Hummer
Reverted the reversion of the patch that went into devel by mistake |
24 |
'BranchUpgradeView', |
7362.4.14
by Jonathan Lange
Move the URL specification into a class in Python, rather than ZCML. |
25 |
'BranchURL', |
1102.1.143
by David Allouche
Review fixes to Branch view. |
26 |
'BranchView', |
4333.2.2
by Tim Penhey
linked, albiet weirdly |
27 |
'BranchSubscriptionsView', |
4414.5.4
by Tim Penhey
First cut at getting a page to register a merge proposal |
28 |
'RegisterBranchMergeProposalView', |
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
29 |
'TryImportAgainView', |
1102.1.143
by David Allouche
Review fixes to Branch view. |
30 |
]
|
31 |
||
3691.112.6
by David Allouche
properly validate branch name in branch/+edit |
32 |
import cgi |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
33 |
from datetime import ( |
34 |
datetime, |
|
35 |
timedelta, |
|
36 |
)
|
|
8137.17.24
by Barry Warsaw
thread merge |
37 |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
38 |
from lazr.enum import ( |
39 |
EnumeratedType, |
|
40 |
Item, |
|
41 |
)
|
|
42 |
from lazr.lifecycle.event import ObjectModifiedEvent |
|
43 |
from lazr.lifecycle.snapshot import Snapshot |
|
44 |
from lazr.restful.interface import ( |
|
45 |
copy_field, |
|
46 |
use_template, |
|
47 |
)
|
|
13931.2.1
by Steve Kowalik
Chip away at canonical.lazr a little more. |
48 |
from lazr.restful.utils import smartquote |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
49 |
from lazr.uri import URI |
1102.1.123
by david
schema supports ghost revisions |
50 |
import pytz |
13760.3.6
by Ian Booth
Fix imports |
51 |
from zope.app.form import CustomWidgetFactory |
7573.2.10
by Paul Hummer
Made the merge proposal creation form use a fixed width font |
52 |
from zope.app.form.browser import TextAreaWidget |
13760.3.6
by Ian Booth
Fix imports |
53 |
from zope.app.form.browser.boolwidgets import CheckBoxWidget |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
54 |
from zope.component import ( |
55 |
getUtility, |
|
56 |
queryAdapter, |
|
57 |
)
|
|
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
58 |
from zope.event import notify |
6096.6.3
by Tim Penhey
Make Bazaar Experts and Launchpad administrators able to reassign a branch to anyone. |
59 |
from zope.formlib import form |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
60 |
from zope.interface import ( |
61 |
implements, |
|
62 |
Interface, |
|
63 |
providedBy, |
|
64 |
)
|
|
5430.1.1
by Tim Penhey
Remove the ability for junk branches to traverse to +register-merge. |
65 |
from zope.publisher.interfaces import NotFound |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
66 |
from zope.schema import ( |
67 |
Bool, |
|
68 |
Choice, |
|
69 |
Text, |
|
70 |
)
|
|
71 |
from zope.schema.vocabulary import ( |
|
72 |
SimpleTerm, |
|
73 |
SimpleVocabulary, |
|
74 |
)
|
|
75 |
from zope.traversing.interfaces import IPathAdapter |
|
1102.1.74
by David Allouche
$branch/+edit form |
76 |
|
14605.1.1
by Curtis Hovey
Moved canonical.config to lp.services. |
77 |
from lp.services.config import config |
5001.2.1
by Tim Penhey
Add column and update the date_last_modified on UI updates. |
78 |
from canonical.database.constants import UTC_NOW |
14600.1.12
by Curtis Hovey
Move i18n to lp. |
79 |
from lp import _ |
14593.2.9
by Curtis Hovey
Moved searchbuilder to lp.services. |
80 |
from lp.services import searchbuilder |
14557.1.11
by Curtis Hovey
Moved feeds to lp.feeds. |
81 |
from lp.services.feeds.browser import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
82 |
BranchFeedLink, |
83 |
FeedsMixin, |
|
84 |
)
|
|
14593.2.15
by Curtis Hovey
Moved helpers to lp.services. |
85 |
from lp.services.helpers import truncate_text |
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
86 |
from lp.services.webapp import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
87 |
canonical_url, |
88 |
ContextMenu, |
|
89 |
enabled_with_permission, |
|
90 |
LaunchpadView, |
|
91 |
Link, |
|
92 |
Navigation, |
|
93 |
NavigationMenu, |
|
94 |
stepthrough, |
|
95 |
stepto, |
|
96 |
)
|
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
97 |
from lp.services.webapp.authorization import ( |
14550.3.3
by Ian Booth
Improve sql used in security adaptor, migrate doc test to unit test, add tests |
98 |
check_permission, |
99 |
precache_permission_for_objects, |
|
100 |
)
|
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
101 |
from lp.services.webapp.interfaces import ICanonicalUrlData |
102 |
from lp.services.webapp.menu import structured |
|
13130.1.12
by Curtis Hovey
Sorted imports. |
103 |
from lp.app.browser.launchpad import Hierarchy |
11929.9.1
by Tim Penhey
Move launchpadform into lp.app.browser. |
104 |
from lp.app.browser.launchpadform import ( |
105 |
action, |
|
106 |
custom_widget, |
|
107 |
LaunchpadEditFormView, |
|
108 |
LaunchpadFormView, |
|
109 |
)
|
|
14550.1.1
by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad |
110 |
from lp.app.browser.lazrjs import EnumChoiceWidget |
7675.822.7
by Jeroen Vermeulen
Got TAL rendering. Probably ugly though. |
111 |
from lp.app.errors import NotFoundError |
13130.1.12
by Curtis Hovey
Sorted imports. |
112 |
from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
12293.1.10
by Curtis Hovey
Formatted imports. |
113 |
from lp.app.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription |
114 |
from lp.app.widgets.suggestion import TargetBranchWidget |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
115 |
from lp.blueprints.interfaces.specificationbranch import ISpecificationBranch |
116 |
from lp.bugs.interfaces.bug import IBugSet |
|
117 |
from lp.bugs.interfaces.bugbranch import IBugBranch |
|
10974.1.3
by Tim Penhey
Decorate the branch to make it cache most of the query calls. |
118 |
from lp.bugs.interfaces.bugtask import UNRESOLVED_BUGTASK_STATUSES |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
119 |
from lp.code.browser.branchmergeproposal import ( |
120 |
latest_proposals_for_each_branch, |
|
121 |
)
|
|
8120.2.6
by Jonathan Lange
Sort imports. |
122 |
from lp.code.browser.branchref import BranchRef |
11019.3.1
by Tim Penhey
Extract the DecoratedBug and DecorateBranch out of the browser/branch module and into its own. Use a DecoratedBranch for the new revisions. |
123 |
from lp.code.browser.decorations import DecoratedBranch |
7675.618.24
by Paul Hummer
Added links to the recipes pages and accompanying tests. |
124 |
from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin |
9570.12.3
by Tim Penhey
More js bits. |
125 |
from lp.code.enums import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
126 |
BranchType, |
127 |
CodeImportResultStatus, |
|
128 |
CodeImportReviewStatus, |
|
129 |
RevisionControlSystems, |
|
130 |
UICreatableBranchType, |
|
131 |
)
|
|
10454.12.4
by James Westby
Use the new method from the existing browser code. |
132 |
from lp.code.errors import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
133 |
BranchCreationForbidden, |
134 |
BranchExists, |
|
13750.1.4
by Aaron Bentley
Ensure view produces a nice notification. |
135 |
CannotUpgradeBranch, |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
136 |
CodeImportAlreadyRequested, |
137 |
CodeImportAlreadyRunning, |
|
138 |
CodeImportNotInReviewedState, |
|
139 |
InvalidBranchMergeProposal, |
|
140 |
)
|
|
8138.1.2
by Jonathan Lange
Run migrater over lp.code. Many tests broken and imports failing. |
141 |
from lp.code.interfaces.branch import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
142 |
IBranch, |
143 |
user_has_special_branch_access, |
|
144 |
)
|
|
12082.2.3
by Ian Booth
Add tests and clean up tales |
145 |
from lp.code.interfaces.branchcollection import IAllBranches |
10155.5.1
by Tim Penhey
Make the less used fields on register merge proposal extra options. |
146 |
from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
147 |
from lp.code.interfaces.branchnamespace import IBranchNamespacePolicy |
8120.2.7
by Jonathan Lange
Forbid product from being specified on the add form. |
148 |
from lp.code.interfaces.branchtarget import IBranchTarget |
8120.2.6
by Jonathan Lange
Sort imports. |
149 |
from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
150 |
from lp.registry.interfaces.person import ( |
151 |
IPerson, |
|
152 |
IPersonSet, |
|
153 |
)
|
|
8138.1.2
by Jonathan Lange
Run migrater over lp.code. Many tests broken and imports failing. |
154 |
from lp.registry.interfaces.productseries import IProductSeries |
10843.3.7
by Tim Penhey
If we are in the situation where the branch editor isn't in the team of the branch owner (as we get in the situation where an official package branch is being edited by an uploader), add the owner to the vocabulary used for the owner field.~ |
155 |
from lp.registry.vocabularies import UserTeamsParticipationPlusSelfVocabulary |
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
156 |
from lp.services.propertycache import cachedproperty |
7675.822.7
by Jeroen Vermeulen
Got TAL rendering. Probably ugly though. |
157 |
from lp.translations.interfaces.translationtemplatesbuild import ( |
158 |
ITranslationTemplatesBuildSource, |
|
159 |
)
|
|
4414.5.7
by Tim Penhey
merge initial and custom widget |
160 |
|
3283.3.3
by Brad Bollenbach
pair code reviewing with lifeless |
161 |
|
3691.112.6
by David Allouche
properly validate branch name in branch/+edit |
162 |
def quote(text): |
163 |
return cgi.escape(text, quote=True) |
|
164 |
||
165 |
||
7362.4.14
by Jonathan Lange
Move the URL specification into a class in Python, rather than ZCML. |
166 |
class BranchURL: |
167 |
"""Branch URL creation rules."""
|
|
168 |
||
169 |
implements(ICanonicalUrlData) |
|
170 |
||
171 |
rootsite = 'code' |
|
9084.2.1
by Tim Penhey
Make the canonical url of the branch not hit the database to traverse the object. |
172 |
inside = None |
7362.4.14
by Jonathan Lange
Move the URL specification into a class in Python, rather than ZCML. |
173 |
|
174 |
def __init__(self, branch): |
|
175 |
self.branch = branch |
|
176 |
||
177 |
@property
|
|
178 |
def path(self): |
|
9084.2.1
by Tim Penhey
Make the canonical url of the branch not hit the database to traverse the object. |
179 |
return self.branch.unique_name |
7362.4.14
by Jonathan Lange
Move the URL specification into a class in Python, rather than ZCML. |
180 |
|
181 |
||
9129.3.2
by Tim Penhey
Add adapters for IBranch to IRootContext. |
182 |
def branch_root_context(branch): |
183 |
"""Return the IRootContext for the branch."""
|
|
184 |
return branch.target.components[0] |
|
185 |
||
186 |
||
6753.6.1
by Tim Penhey
Make the default context for branches to be the product if there is one. |
187 |
class BranchHierarchy(Hierarchy): |
188 |
"""The hierarchy for a branch should be the product if there is one."""
|
|
189 |
||
9087.4.7
by Guilherme Salgado
Fix a couple stupid mistakes |
190 |
@property
|
9087.4.3
by Guilherme Salgado
Finally, something that works with all examples |
191 |
def objects(self): |
6753.6.1
by Tim Penhey
Make the default context for branches to be the product if there is one. |
192 |
"""See `Hierarchy`."""
|
9476.1.3
by Tim Penhey
Breadcrumbs for branches, and fix bmp-index a bit. |
193 |
traversed = list(self.request.traversed_objects) |
194 |
# Pass back the root object.
|
|
195 |
yield traversed.pop(0) |
|
196 |
# Now pop until we find the branch.
|
|
197 |
branch = traversed.pop(0) |
|
198 |
while not IBranch.providedBy(branch): |
|
199 |
branch = traversed.pop(0) |
|
200 |
# Now pass back the branch components.
|
|
201 |
for component in branch.target.components: |
|
202 |
yield component |
|
203 |
# Now the branch.
|
|
204 |
yield branch |
|
205 |
# Now whatever is left.
|
|
206 |
for obj in traversed: |
|
207 |
yield obj |
|
6753.6.1
by Tim Penhey
Make the default context for branches to be the product if there is one. |
208 |
|
209 |
||
3283.3.2
by Brad Bollenbach
fixes based on talking to the sab this morning. tightening up the security model a bit by basing privileges on an IHasBug interface. |
210 |
class BranchNavigation(Navigation): |
3283.3.3
by Brad Bollenbach
pair code reviewing with lifeless |
211 |
|
3283.3.2
by Brad Bollenbach
fixes based on talking to the sab this morning. tightening up the security model a bit by basing privileges on an IHasBug interface. |
212 |
usedfor = IBranch |
213 |
||
214 |
@stepthrough("+bug") |
|
215 |
def traverse_bug_branch(self, bugid): |
|
4414.3.4
by Tim Penhey
Adjustments following review comments. |
216 |
"""Traverses to an `IBugBranch`."""
|
3283.3.2
by Brad Bollenbach
fixes based on talking to the sab this morning. tightening up the security model a bit by basing privileges on an IHasBug interface. |
217 |
bug = getUtility(IBugSet).get(bugid) |
218 |
||
8698.10.4
by Paul Hummer
Fixed references to broken code |
219 |
for bug_branch in bug.linked_branches: |
3283.3.2
by Brad Bollenbach
fixes based on talking to the sab this morning. tightening up the security model a bit by basing privileges on an IHasBug interface. |
220 |
if bug_branch.branch == self.context: |
221 |
return bug_branch |
|
1102.1.74
by David Allouche
$branch/+edit form |
222 |
|
3691.160.1
by James Henstridge
Add support for Bazaar branch references to branch, product and product series pages |
223 |
@stepto(".bzr") |
224 |
def dotbzr(self): |
|
225 |
return BranchRef(self.context) |
|
226 |
||
4333.2.2
by Tim Penhey
linked, albiet weirdly |
227 |
@stepthrough("+subscription") |
228 |
def traverse_subscription(self, name): |
|
4414.3.4
by Tim Penhey
Adjustments following review comments. |
229 |
"""Traverses to an `IBranchSubcription`."""
|
4333.2.2
by Tim Penhey
linked, albiet weirdly |
230 |
person = getUtility(IPersonSet).getByName(name) |
231 |
||
232 |
if person is not None: |
|
233 |
return self.context.getSubscription(person) |
|
234 |
||
4414.5.12
by Tim Penhey
work in progress |
235 |
@stepthrough("+merge") |
236 |
def traverse_merge_proposal(self, id): |
|
237 |
"""Traverse to an `IBranchMergeProposal`."""
|
|
238 |
try: |
|
239 |
id = int(id) |
|
240 |
except ValueError: |
|
241 |
# Not a number.
|
|
242 |
return None |
|
243 |
for proposal in self.context.landing_targets: |
|
244 |
if proposal.id == id: |
|
245 |
return proposal |
|
246 |
||
10454.3.1
by James Westby
Basic export of ICodeImport. |
247 |
@stepto("+code-import") |
248 |
def traverse_code_import(self): |
|
249 |
"""Traverses to the `ICodeImport` for the branch."""
|
|
250 |
return self.context.code_import |
|
251 |
||
7675.822.7
by Jeroen Vermeulen
Got TAL rendering. Probably ugly though. |
252 |
@stepthrough("+translation-templates-build") |
253 |
def traverse_translation_templates_build(self, id_string): |
|
254 |
"""Traverses to a `TranslationTemplatesBuild`."""
|
|
255 |
try: |
|
12979.2.1
by William Grant
TTBJ URLs now use the TTBJ ID, not the BFJ ID. |
256 |
ttbj_id = int(id_string) |
7675.822.7
by Jeroen Vermeulen
Got TAL rendering. Probably ugly though. |
257 |
except ValueError: |
258 |
raise NotFoundError(id_string) |
|
259 |
source = getUtility(ITranslationTemplatesBuildSource) |
|
12979.2.1
by William Grant
TTBJ URLs now use the TTBJ ID, not the BFJ ID. |
260 |
return source.getByID(ttbj_id) |
7675.822.7
by Jeroen Vermeulen
Got TAL rendering. Probably ugly though. |
261 |
|
9636.5.4
by Jonathan Lange
XXX notes. |
262 |
|
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
263 |
class BranchEditMenu(NavigationMenu): |
264 |
"""Edit menu for IBranch."""
|
|
265 |
||
266 |
usedfor = IBranch |
|
6648.3.1
by Paul Hummer
Adds IBranchNavigationMenu interface |
267 |
facet = 'branches' |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
268 |
title = 'Edit branch' |
9562.1.1
by Paul Hummer
Shifted around the BranchEditMenu item ordering |
269 |
links = ( |
10891.1.2
by Paul Hummer
Added code for the source package recipe count section |
270 |
'edit', 'reviewer', 'edit_whiteboard', 'delete') |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
271 |
|
272 |
def branch_is_import(self): |
|
273 |
return self.context.branch_type == BranchType.IMPORTED |
|
274 |
||
275 |
@enabled_with_permission('launchpad.Edit') |
|
276 |
def edit(self): |
|
9301.2.29
by Paul Hummer
Fixed xx-upload-directions |
277 |
text = 'Change branch details' |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
278 |
return Link('+edit', text, icon='edit') |
279 |
||
280 |
@enabled_with_permission('launchpad.Edit') |
|
281 |
def delete(self): |
|
282 |
text = 'Delete branch' |
|
9301.2.27
by Paul Hummer
Fixed verbage |
283 |
return Link('+delete', text, icon='trash-icon') |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
284 |
|
9301.2.40
by Paul Hummer
Responded to Aaron's review |
285 |
@enabled_with_permission('launchpad.AnyPerson') |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
286 |
def edit_whiteboard(self): |
287 |
text = 'Edit whiteboard' |
|
9301.2.38
by Paul Hummer
Fixed some lint |
288 |
enabled = self.branch_is_import() |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
289 |
return Link( |
9301.2.38
by Paul Hummer
Fixed some lint |
290 |
'+whiteboard', text, icon='edit', enabled=enabled) |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
291 |
|
292 |
@enabled_with_permission('launchpad.Edit') |
|
293 |
def reviewer(self): |
|
294 |
text = 'Set branch reviewer' |
|
295 |
return Link('+reviewer', text, icon='edit') |
|
7211.1.4
by Tim Penhey
Changed view names and added test. |
296 |
|
6648.3.1
by Paul Hummer
Adds IBranchNavigationMenu interface |
297 |
|
7675.618.24
by Paul Hummer
Added links to the recipes pages and accompanying tests. |
298 |
class BranchContextMenu(ContextMenu, HasRecipesMenuMixin): |
1102.1.98
by David Allouche
remove branch-portlet-actions.pt, add BranchContextMenu, add PersonNavigation.traverse_branch, add zcml declaration for RevisionNumber |
299 |
"""Context menu for branches."""
|
300 |
||
301 |
usedfor = IBranch |
|
3412.1.19
by David Allouche
use branches facet for all branch pages |
302 |
facet = 'branches' |
9301.2.37
by Paul Hummer
Merge from trunk, resolve conflicts |
303 |
links = [ |
10891.1.2
by Paul Hummer
Added code for the source package recipe count section |
304 |
'add_subscriber', 'browse_revisions', 'create_recipe', 'link_bug', |
9570.12.1
by Tim Penhey
Add a link and simple view for editing the status. |
305 |
'link_blueprint', 'register_merge', 'source', 'subscription', |
7675.899.8
by Paul Hummer
Add +create-queue view |
306 |
'edit_status', 'edit_import', 'upgrade_branch', 'view_recipes', |
7675.899.14
by Paul Hummer
Removed link_branch link |
307 |
'create_queue'] |
9570.12.1
by Tim Penhey
Add a link and simple view for editing the status. |
308 |
|
309 |
@enabled_with_permission('launchpad.Edit') |
|
310 |
def edit_status(self): |
|
311 |
text = 'Change branch status' |
|
312 |
return Link('+edit-status', text, icon='edit') |
|
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
313 |
|
4813.5.1
by Michael Hudson
change the browse code link, add the browse revisions link, add simple test |
314 |
def browse_revisions(self): |
4813.5.3
by Michael Hudson
add two docstrings |
315 |
"""Return a link to the branch's revisions on codebrowse."""
|
6757.1.1
by Paul Hummer
Changes 'Older revisions' to 'All revisions' |
316 |
text = 'All revisions' |
4813.5.1
by Michael Hudson
change the browse code link, add the browse revisions link, add simple test |
317 |
enabled = self.context.code_is_browseable |
7622.1.2
by Michael Hudson
some progress |
318 |
url = self.context.codebrowse_url('changes') |
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
319 |
return Link(url, text, enabled=enabled) |
3948.1.1
by James Henstridge
add codebrowse link to branch context menu |
320 |
|
3691.431.11
by Tim Penhey
Branch subscription pages edited |
321 |
@enabled_with_permission('launchpad.AnyPerson') |
1102.1.98
by David Allouche
remove branch-portlet-actions.pt, add BranchContextMenu, add PersonNavigation.traverse_branch, add zcml declaration for RevisionNumber |
322 |
def subscription(self): |
3691.431.11
by Tim Penhey
Branch subscription pages edited |
323 |
if self.context.hasSubscription(self.user): |
324 |
url = '+edit-subscription' |
|
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
325 |
text = 'Edit your subscription' |
3691.431.11
by Tim Penhey
Branch subscription pages edited |
326 |
icon = 'edit' |
1102.1.98
by David Allouche
remove branch-portlet-actions.pt, add BranchContextMenu, add PersonNavigation.traverse_branch, add zcml declaration for RevisionNumber |
327 |
else: |
3691.431.11
by Tim Penhey
Branch subscription pages edited |
328 |
url = '+subscribe' |
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
329 |
text = 'Subscribe yourself' |
3691.431.11
by Tim Penhey
Branch subscription pages edited |
330 |
icon = 'add' |
331 |
return Link(url, text, icon=icon) |
|
1102.1.98
by David Allouche
remove branch-portlet-actions.pt, add BranchContextMenu, add PersonNavigation.traverse_branch, add zcml declaration for RevisionNumber |
332 |
|
4333.2.1
by Tim Penhey
Initial subscription works, now how to edit... |
333 |
@enabled_with_permission('launchpad.AnyPerson') |
5579.2.7
by Tim Penhey
Update the existing pagetest for new actions. |
334 |
def add_subscriber(self): |
4333.2.1
by Tim Penhey
Initial subscription works, now how to edit... |
335 |
text = 'Subscribe someone else' |
336 |
return Link('+addsubscriber', text, icon='add') |
|
337 |
||
5579.2.7
by Tim Penhey
Update the existing pagetest for new actions. |
338 |
def register_merge(self): |
9586.2.1
by Tim Penhey
First hack at it. |
339 |
text = 'Propose for merging' |
9301.2.40
by Paul Hummer
Responded to Aaron's review |
340 |
enabled = ( |
341 |
self.context.target.supports_merge_proposals and |
|
342 |
not self.context.branch_type == BranchType.IMPORTED) |
|
10054.13.1
by Tim Penhey
Use the add icon instead of the merge proposal icon for registering a new proposal. |
343 |
return Link('+register-merge', text, icon='add', enabled=enabled) |
4414.5.4
by Tim Penhey
First cut at getting a page to register a merge proposal |
344 |
|
5579.2.7
by Tim Penhey
Update the existing pagetest for new actions. |
345 |
def link_bug(self): |
12457.2.3
by Robert Collins
Lock down scaling of branch:+index for product bugtasks - still to do productseries and distroseries. |
346 |
text = 'Link a bug report' |
6369.1.1
by Paul Hummer
Added link to blueprint and link to bug items from the action menu |
347 |
return Link('+linkbug', text, icon='add') |
4789.3.1
by Tim Penhey
First cut. |
348 |
|
5099.10.9
by Tim Penhey
Updates following review. |
349 |
def link_blueprint(self): |
6369.1.3
by Paul Hummer
Adds text for "Link to [a|another] [bug|blueprint]" |
350 |
if self.context.spec_links: |
351 |
text = 'Link to another blueprint' |
|
352 |
else: |
|
353 |
text = 'Link to a blueprint' |
|
8418.1.1
by Jonathan Lange
Remove a stack of code that lets you move branches. |
354 |
# XXX: JonathanLange 2009-05-13 spec=package-branches: Actually,
|
355 |
# distroseries can also have blueprints, so it makes sense to
|
|
356 |
# associate package-branches with them.
|
|
357 |
#
|
|
5099.10.4
by Tim Penhey
Put the product in the launchbag when traversing the branch. |
358 |
# Since the blueprints are only related to products, there is no
|
359 |
# point showing this link if the branch is junk.
|
|
5099.10.5
by Tim Penhey
Some drive by clean up making buttons and links consistent. |
360 |
enabled = self.context.product is not None |
6369.1.1
by Paul Hummer
Added link to blueprint and link to bug items from the action menu |
361 |
return Link('+linkblueprint', text, icon='add', enabled=enabled) |
5099.10.3
by Tim Penhey
Add 'Link to blueprint' to the branch page. |
362 |
|
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
363 |
def source(self): |
364 |
"""Return a link to the branch's file listing on codebrowse."""
|
|
12707.2.1
by Huw Wilkins
Renamed "View the branch content" to "Browse the code". |
365 |
text = 'Browse the code' |
9301.2.26
by Paul Hummer
Added minor changes for details where portlets don't have anything to put in them |
366 |
enabled = self.context.code_is_browseable |
9301.2.20
by Paul Hummer
Added BranchEditMenu, removed BranchNavigationMenu |
367 |
url = self.context.codebrowse_url('files') |
368 |
return Link(url, text, icon='info', enabled=enabled) |
|
6757.1.4
by Paul Hummer
Changes "Edit import" link to actually be a Link |
369 |
|
10174.1.2
by Paul Hummer
Moved the code import section back inline. |
370 |
def edit_import(self): |
371 |
text = 'Edit import source or review import' |
|
372 |
enabled = True |
|
373 |
enabled = ( |
|
374 |
self.context.branch_type == BranchType.IMPORTED and |
|
375 |
check_permission('launchpad.Edit', self.context.code_import)) |
|
376 |
return Link( |
|
377 |
'+edit-import', text, icon='edit', enabled=enabled) |
|
378 |
||
7675.477.1
by Paul Hummer
Reverted the reversion of the patch that went into devel by mistake |
379 |
@enabled_with_permission('launchpad.Edit') |
380 |
def upgrade_branch(self): |
|
381 |
enabled = False |
|
382 |
if self.context.needs_upgrading: |
|
383 |
enabled = True |
|
384 |
return Link( |
|
385 |
'+upgrade', 'Upgrade this branch', icon='edit', enabled=enabled) |
|
386 |
||
10891.1.2
by Paul Hummer
Added code for the source package recipe count section |
387 |
def create_recipe(self): |
12373.1.2
by Tim Penhey
Make all recipe beta and enablement checks user feature flags. |
388 |
# You can't create a recipe for a private branch.
|
389 |
enabled = not self.context.private |
|
10891.1.2
by Paul Hummer
Added code for the source package recipe count section |
390 |
text = 'Create packaging recipe' |
391 |
return Link('+new-recipe', text, enabled=enabled, icon='add') |
|
392 |
||
7675.899.8
by Paul Hummer
Add +create-queue view |
393 |
@enabled_with_permission('launchpad.Edit') |
394 |
def create_queue(self): |
|
395 |
return Link('+create-queue', 'Create a new queue', icon='add') |
|
396 |
||
1102.1.98
by David Allouche
remove branch-portlet-actions.pt, add BranchContextMenu, add PersonNavigation.traverse_branch, add zcml declaration for RevisionNumber |
397 |
|
11515.8.3
by Brad Crittenden
Redesign code product page. Created code +portlet-codestatistics. |
398 |
class BranchMirrorMixin: |
399 |
"""Provide mirror_location property.
|
|
400 |
||
401 |
Requires self.branch to be set by the class using this mixin.
|
|
402 |
"""
|
|
403 |
||
404 |
@property
|
|
405 |
def mirror_location(self): |
|
406 |
"""Check the mirror location to see if it is a private one."""
|
|
407 |
branch = self.branch |
|
408 |
||
409 |
# If the user has edit permissions, then show the actual location.
|
|
12276.1.1
by William Grant
Empty remote branch URLs are always OK, so don't attempt to check their non-existent domain. |
410 |
if branch.url is None or check_permission('launchpad.Edit', branch): |
11515.8.3
by Brad Crittenden
Redesign code product page. Created code +portlet-codestatistics. |
411 |
return branch.url |
412 |
||
12924.3.3
by Tim Penhey
Fix up the branch_type vocabulary, and remove some XXX comments that are not worthy. |
413 |
# XXX: Tim Penhey, 2008-05-30, bug 235916
|
11515.8.3
by Brad Crittenden
Redesign code product page. Created code +portlet-codestatistics. |
414 |
# Instead of a configuration hack we should support the users
|
415 |
# specifying whether or not they want the mirror location
|
|
416 |
# hidden or not. Given that this is a database patch,
|
|
417 |
# it isn't going to happen today.
|
|
418 |
hosts = config.codehosting.private_mirror_hosts.split(',') |
|
419 |
private_mirror_hosts = [name.strip() for name in hosts] |
|
420 |
||
421 |
uri = URI(branch.url) |
|
422 |
for private_host in private_mirror_hosts: |
|
423 |
if uri.underDomain(private_host): |
|
424 |
return '<private server>' |
|
425 |
||
426 |
return branch.url |
|
427 |
||
428 |
||
429 |
class BranchView(LaunchpadView, FeedsMixin, BranchMirrorMixin): |
|
1102.1.75
by David Allouche
wrap branch urls in the page index page |
430 |
|
5204.6.26
by Brad Crittenden
Added feed for latest revisions on a given branch. |
431 |
feed_types = ( |
432 |
BranchFeedLink, |
|
433 |
)
|
|
434 |
||
9301.2.39
by Paul Hummer
Moved registrant up to registering slot |
435 |
@property
|
436 |
def page_title(self): |
|
437 |
return self.context.bzr_identity |
|
438 |
||
439 |
label = page_title |
|
440 |
||
1102.1.128
by david
hide comitters in branch-index if not logged in |
441 |
def initialize(self): |
11515.8.3
by Brad Crittenden
Redesign code product page. Created code +portlet-codestatistics. |
442 |
self.branch = self.context |
1102.1.85
by David Allouche
can subscribe to and unsubscribe from branch |
443 |
self.notices = [] |
14550.3.3
by Ian Booth
Improve sql used in security adaptor, migrate doc test to unit test, add tests |
444 |
# Cache permission so private team owner can be rendered.
|
445 |
# The security adaptor will do the job also but we don't want or need
|
|
446 |
# the expense of running several complex SQL queries.
|
|
447 |
authorised_people = [self.branch.owner] |
|
448 |
if self.user is not None: |
|
449 |
precache_permission_for_objects( |
|
450 |
self.request, "launchpad.LimitedView", authorised_people) |
|
10974.1.7
by Tim Penhey
Use isinstance. |
451 |
# Replace our context with a decorated branch, if it is not already
|
452 |
# decorated.
|
|
453 |
if not isinstance(self.context, DecoratedBranch): |
|
10974.1.3
by Tim Penhey
Decorate the branch to make it cache most of the query calls. |
454 |
self.context = DecoratedBranch(self.context) |
1102.1.75
by David Allouche
wrap branch urls in the page index page |
455 |
|
1102.1.143
by David Allouche
Review fixes to Branch view. |
456 |
def user_is_subscribed(self): |
457 |
"""Is the current user subscribed to this branch?"""
|
|
1102.1.85
by David Allouche
can subscribe to and unsubscribe from branch |
458 |
if self.user is None: |
1102.1.143
by David Allouche
Review fixes to Branch view. |
459 |
return False |
3691.431.11
by Tim Penhey
Branch subscription pages edited |
460 |
return self.context.hasSubscription(self.user) |
1102.1.85
by David Allouche
can subscribe to and unsubscribe from branch |
461 |
|
3024.1.39
by Christian Reis
Improve the person-branches page by caching in the view code and using a small amount of prejoining; based on recent oops report for the vcs-imports user |
462 |
def recent_revision_count(self, days=30): |
1102.1.121
by david
show author of revisions and number of revisions in the last 30 days |
463 |
"""Number of revisions committed during the last N days."""
|
1102.1.123
by david
schema supports ghost revisions |
464 |
timestamp = datetime.now(pytz.UTC) - timedelta(days=days) |
9984.4.1
by Tim Penhey
Rename revisions_since to follow the LP coding standard. |
465 |
return self.context.getRevisionsSince(timestamp).count() |
1102.1.121
by david
show author of revisions and number of revisions in the last 30 days |
466 |
|
5786.1.1
by Tim Penhey
Changed nearby to use owned/registered and person branch links to be Registered/Owned/Subscribed. |
467 |
def owner_is_registrant(self): |
468 |
"""Is the branch owner the registrant?"""
|
|
469 |
return self.context.owner == self.context.registrant |
|
1102.1.134
by David Allouche
cosmetic fixes |
470 |
|
9301.2.40
by Paul Hummer
Responded to Aaron's review |
471 |
def owner_is_reviewer(self): |
472 |
"""Is the branch owner the default reviewer?"""
|
|
473 |
if self.context.reviewer == None: |
|
474 |
return True |
|
475 |
return self.context.owner == self.context.reviewer |
|
476 |
||
8137.17.24
by Barry Warsaw
thread merge |
477 |
def show_whiteboard(self): |
478 |
"""Return whether or not the whiteboard should be shown.
|
|
479 |
||
480 |
The whiteboard is only shown for import branches.
|
|
481 |
"""
|
|
9301.2.25
by Paul Hummer
Fixed the branch page to work well with import branches |
482 |
if (self.context.branch_type == BranchType.IMPORTED and |
483 |
self.context.whiteboard): |
|
8137.17.24
by Barry Warsaw
thread merge |
484 |
return True |
485 |
else: |
|
486 |
return False |
|
487 |
||
9301.2.32
by Paul Hummer
Fixed xx-branch-index |
488 |
def has_metadata(self): |
489 |
"""Return whether there is branch metadata to display."""
|
|
9301.2.26
by Paul Hummer
Added minor changes for details where portlets don't have anything to put in them |
490 |
return ( |
491 |
self.context.branch_format or |
|
492 |
self.context.repository_format or |
|
9301.2.32
by Paul Hummer
Fixed xx-branch-index |
493 |
self.context.control_format or |
494 |
self.context.stacked_on) |
|
9301.2.26
by Paul Hummer
Added minor changes for details where portlets don't have anything to put in them |
495 |
|
4743.2.1
by Tim Penhey
Revision numbers on branch details page now link to codebrowse. |
496 |
@property
|
12054.1.1
by Aaron Bentley
Suggest --use-existing for empty branches |
497 |
def is_empty_directory(self): |
498 |
"""True if the branch is an empty directory without even a '.bzr'."""
|
|
499 |
return self.context.control_format is None |
|
500 |
||
501 |
@property
|
|
4743.2.1
by Tim Penhey
Revision numbers on branch details page now link to codebrowse. |
502 |
def codebrowse_url(self): |
503 |
"""Return the link to codebrowse for this branch."""
|
|
7622.1.2
by Michael Hudson
some progress |
504 |
return self.context.codebrowse_url() |
4743.2.1
by Tim Penhey
Revision numbers on branch details page now link to codebrowse. |
505 |
|
8128.7.7
by Jonathan Lange
Make the template use the view for obtaining pending-writes, since the |
506 |
@property
|
507 |
def pending_writes(self): |
|
508 |
"""Whether or not there are pending writes for this branch."""
|
|
509 |
return self.context.pending_writes |
|
510 |
||
4813.8.1
by Tim Penhey
Lots of url moving on the branch index page. |
511 |
def bzr_download_url(self): |
512 |
"""Return the generic URL for downloading the branch."""
|
|
513 |
if self.user_can_download(): |
|
5805.2.7
by Tim Penhey
Fixed branch tests. |
514 |
return self.context.bzr_identity |
4813.8.5
by Tim Penhey
Updates following review. |
515 |
else: |
516 |
return None |
|
4813.8.1
by Tim Penhey
Lots of url moving on the branch index page. |
517 |
|
518 |
def bzr_upload_url(self): |
|
519 |
"""Return the generic URL for uploading the branch."""
|
|
520 |
if self.user_can_upload(): |
|
5805.2.7
by Tim Penhey
Fixed branch tests. |
521 |
return self.context.bzr_identity |
4813.8.5
by Tim Penhey
Updates following review. |
522 |
else: |
523 |
return None |
|
2868.2.1
by David Allouche
[incomplete] optional-branch-title |
524 |
|
10355.2.1
by Tim Penhey
Change the method for identifying whether a person can upload to use Launchpad.Edit. |
525 |
@property
|
3691.303.1
by David Allouche
display contextual upload directions on the index page of upload branches |
526 |
def user_can_upload(self): |
527 |
"""Whether the user can upload to this branch."""
|
|
10355.2.1
by Tim Penhey
Change the method for identifying whether a person can upload to use Launchpad.Edit. |
528 |
branch = self.context |
529 |
if branch.branch_type != BranchType.HOSTED: |
|
530 |
return False |
|
531 |
return check_permission('launchpad.Edit', branch) |
|
3691.303.1
by David Allouche
display contextual upload directions on the index page of upload branches |
532 |
|
4813.8.1
by Tim Penhey
Lots of url moving on the branch index page. |
533 |
def user_can_download(self): |
534 |
"""Whether the user can download this branch."""
|
|
535 |
return (self.context.branch_type != BranchType.REMOTE and |
|
536 |
self.context.revision_count > 0) |
|
3691.303.1
by David Allouche
display contextual upload directions on the index page of upload branches |
537 |
|
4414.5.12
by Tim Penhey
work in progress |
538 |
@cachedproperty
|
539 |
def landing_targets(self): |
|
9691.7.9
by Tim Penhey
Extract the logic into a common method and test it. |
540 |
"""Return a filtered list of landing targets."""
|
14414.2.5
by Ian Booth
Remove old code |
541 |
return latest_proposals_for_each_branch(self.context.landing_targets) |
4414.5.12
by Tim Penhey
work in progress |
542 |
|
5280.4.25
by Tim Penhey
Updates following review. |
543 |
@property
|
4414.5.13
by Tim Penhey
Still work in progress |
544 |
def latest_landing_candidates(self): |
545 |
"""Return a decorated filtered list of landing candidates."""
|
|
546 |
# Only show the most recent 5 landing_candidates
|
|
5280.4.25
by Tim Penhey
Updates following review. |
547 |
return self.landing_candidates[:5] |
4414.5.13
by Tim Penhey
Still work in progress |
548 |
|
549 |
@cachedproperty
|
|
550 |
def landing_candidates(self): |
|
551 |
"""Return a decorated list of landing candidates."""
|
|
552 |
candidates = self.context.landing_candidates |
|
9691.7.8
by Tim Penhey
Rip out the DecoratedMergeProposal as it is only used in a deprecated macro. |
553 |
return [proposal for proposal in candidates |
8537.7.1
by Tim Penhey
Filter the branches and proposals in the view to not include those that the user cannot see. |
554 |
if check_permission('launchpad.View', proposal)] |
4414.5.13
by Tim Penhey
Still work in progress |
555 |
|
9301.2.40
by Paul Hummer
Responded to Aaron's review |
556 |
@property
|
10891.1.2
by Paul Hummer
Added code for the source package recipe count section |
557 |
def recipe_count_text(self): |
12397.2.8
by Ian Booth
Change from using getter methods to properties for exported recipe and build accessors |
558 |
count = self.context.recipes.count() |
10891.1.2
by Paul Hummer
Added code for the source package recipe count section |
559 |
if count == 0: |
560 |
return 'No recipes' |
|
561 |
elif count == 1: |
|
562 |
return '1 recipe' |
|
563 |
else: |
|
564 |
return '%s recipes' % count |
|
565 |
||
566 |
@property
|
|
9301.2.40
by Paul Hummer
Responded to Aaron's review |
567 |
def is_import_branch_with_no_landing_candidates(self): |
568 |
"""Is the branch an import branch with no landing candidates?"""
|
|
569 |
if self.landing_candidates: |
|
570 |
return False |
|
571 |
if not self.context.branch_type == BranchType.IMPORTED: |
|
572 |
return False |
|
573 |
return True |
|
574 |
||
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
575 |
def _getBranchCountText(self, count): |
576 |
"""Help to show user friendly text."""
|
|
577 |
if count == 0: |
|
578 |
return 'No branches' |
|
579 |
elif count == 1: |
|
580 |
return '1 branch' |
|
581 |
else: |
|
582 |
return '%s branches' % count |
|
583 |
||
584 |
@cachedproperty
|
|
585 |
def dependent_branch_count_text(self): |
|
8537.7.1
by Tim Penhey
Filter the branches and proposals in the view to not include those that the user cannot see. |
586 |
branch_count = len(self.dependent_branches) |
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
587 |
return self._getBranchCountText(branch_count) |
588 |
||
589 |
@cachedproperty
|
|
590 |
def landing_candidate_count_text(self): |
|
8537.7.1
by Tim Penhey
Filter the branches and proposals in the view to not include those that the user cannot see. |
591 |
branch_count = len(self.landing_candidates) |
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
592 |
return self._getBranchCountText(branch_count) |
593 |
||
6699.2.22
by Paul Hummer
UI changes |
594 |
@cachedproperty
|
6699.2.24
by Tim Penhey
UI updates |
595 |
def dependent_branches(self): |
8537.7.1
by Tim Penhey
Filter the branches and proposals in the view to not include those that the user cannot see. |
596 |
return [branch for branch in self.context.dependent_branches |
597 |
if check_permission('launchpad.View', branch)] |
|
6699.2.24
by Tim Penhey
UI updates |
598 |
|
599 |
@cachedproperty
|
|
6699.2.22
by Paul Hummer
UI changes |
600 |
def no_merges(self): |
601 |
"""Return true if there are no pending merges"""
|
|
602 |
return (len(self.landing_targets) + |
|
6699.2.24
by Tim Penhey
UI updates |
603 |
len(self.landing_candidates) + |
604 |
len(self.dependent_branches) == 0) |
|
6699.2.22
by Paul Hummer
UI changes |
605 |
|
5280.4.25
by Tim Penhey
Updates following review. |
606 |
@property
|
607 |
def show_candidate_more_link(self): |
|
608 |
"""Only show the link if there are more than five."""
|
|
609 |
return len(self.landing_candidates) > 5 |
|
610 |
||
12082.2.5
by Ian Booth
Move revision_info implementation to branch collection and add tests |
611 |
@cachedproperty
|
12457.2.3
by Robert Collins
Lock down scaling of branch:+index for product bugtasks - still to do productseries and distroseries. |
612 |
def linked_bugtasks(self): |
12457.2.6
by Robert Collins
Review feedback: use a shortlist, don't spread the any pollution of default symbols. Docstring fixup and unbreak the legacy linked_bugs. |
613 |
"""Return a list of bugtasks linked to the branch."""
|
12082.2.5
by Ian Booth
Move revision_info implementation to branch collection and add tests |
614 |
if self.context.is_series_branch: |
12457.2.6
by Robert Collins
Review feedback: use a shortlist, don't spread the any pollution of default symbols. Docstring fixup and unbreak the legacy linked_bugs. |
615 |
status_filter = searchbuilder.any(*UNRESOLVED_BUGTASK_STATUSES) |
12457.2.3
by Robert Collins
Lock down scaling of branch:+index for product bugtasks - still to do productseries and distroseries. |
616 |
else: |
617 |
status_filter = None |
|
618 |
return list(self.context.getLinkedBugTasks( |
|
619 |
self.user, status_filter)) |
|
8752.4.16
by Paul Hummer
Implemented linked_bugs into the templates |
620 |
|
621 |
@cachedproperty
|
|
12082.2.3
by Ian Booth
Add tests and clean up tales |
622 |
def revision_info(self): |
623 |
collection = getUtility(IAllBranches).visibleByUser(self.user) |
|
12082.2.5
by Ian Booth
Move revision_info implementation to branch collection and add tests |
624 |
return collection.getExtendedRevisionDetails( |
12505.6.1
by Ian Booth
Remove DecoratedBug and refactor mp linked_bugs to use branch.getRelatedBugTasks |
625 |
self.user, self.context.latest_revisions) |
12082.2.3
by Ian Booth
Add tests and clean up tales |
626 |
|
627 |
@cachedproperty
|
|
6233.7.1
by Tim Penhey
Make the page look right. |
628 |
def latest_code_import_results(self): |
629 |
"""Return the last 10 CodeImportResults."""
|
|
6233.7.7
by Tim Penhey
Add TestCodeImportResultsAttribute. |
630 |
return list(self.context.code_import.results[:10]) |
6233.7.1
by Tim Penhey
Make the page look right. |
631 |
|
10224.12.9
by Michael Hudson
self-review begins |
632 |
def iconForCodeImportResultStatus(self, status): |
633 |
"""The icon to represent the `CodeImportResultStatus` `status`."""
|
|
10365.2.2
by Michael Hudson
oops, still get the icon right |
634 |
if status == CodeImportResultStatus.SUCCESS_PARTIAL: |
635 |
return "/@@/yes-gray" |
|
636 |
elif status in CodeImportResultStatus.successes: |
|
10224.12.6
by Michael Hudson
changes to model/view code |
637 |
return "/@@/yes" |
638 |
else: |
|
639 |
return "/@@/no" |
|
640 |
||
6387.1.1
by Tim Penhey
Add a configuration option for private_mirror_hosts, and hide the branch location for branches that are under one of those domains unless the user is able to edit the branch. |
641 |
@property
|
9946.1.10
by Michael Hudson
some kind of fix |
642 |
def is_svn_import(self): |
643 |
"""True if an imported branch is a SVN import."""
|
|
9946.1.15
by Michael Hudson
review comments |
644 |
# You should only be calling this if it's a code import
|
9946.1.10
by Michael Hudson
some kind of fix |
645 |
assert self.context.code_import |
646 |
return self.context.code_import.rcs_type in \ |
|
647 |
(RevisionControlSystems.SVN, RevisionControlSystems.BZR_SVN) |
|
648 |
||
649 |
@property
|
|
13756.5.15
by Jelmer Vernooij
Fix UI. |
650 |
def url_is_web(self): |
651 |
"""True if an imported branch's URL is HTTP or HTTPS."""
|
|
652 |
# You should only be calling this if it's an SVN, BZR, GIT or HG code
|
|
653 |
# import
|
|
6721.2.22
by Christian Reis
Address jml's review comments: better comments and simplify svn_url_is_web |
654 |
assert self.context.code_import |
10129.6.9
by Tim Penhey
Yet more test fixes. |
655 |
url = self.context.code_import.url |
656 |
assert url |
|
6721.2.22
by Christian Reis
Address jml's review comments: better comments and simplify svn_url_is_web |
657 |
# https starts with http too!
|
658 |
return url.startswith("http") |
|
6721.2.15
by Christian Reis
Linkify imported branch URLs if they are HTTP/HTTPs. |
659 |
|
660 |
@property
|
|
8269.7.1
by Paul Hummer
Added BranchView.show_merge_links and accompanying tests. |
661 |
def show_merge_links(self): |
662 |
"""Return whether or not merge proposal links should be shown.
|
|
663 |
||
11350.1.3
by Paul Hummer
Fixed lint |
664 |
Merge proposal links should not be shown if there is only one branch
|
665 |
in a non-final state.
|
|
8269.7.1
by Paul Hummer
Added BranchView.show_merge_links and accompanying tests. |
666 |
"""
|
8377.8.14
by Tim Penhey
Enable the links on the page. |
667 |
if not self.context.target.supports_merge_proposals: |
8269.7.1
by Paul Hummer
Added BranchView.show_merge_links and accompanying tests. |
668 |
return False |
8269.7.10
by Paul Hummer
Working on tests |
669 |
return self.context.target.collection.getBranches().count() > 1 |
8269.7.1
by Paul Hummer
Added BranchView.show_merge_links and accompanying tests. |
670 |
|
8771.6.1
by Jeroen Vermeulen
UI for exporting translations to bzr branch. |
671 |
def translations_sources(self): |
672 |
"""Anything that automatically exports its translations here.
|
|
673 |
||
674 |
Produces a list, so that the template can easily check whether
|
|
675 |
there are any translations sources.
|
|
676 |
"""
|
|
677 |
# Actually only ProductSeries currently do that.
|
|
678 |
return list(self.context.getProductSeriesPushingTranslations()) |
|
679 |
||
9570.12.3
by Tim Penhey
More js bits. |
680 |
@property
|
12534.2.1
by Tim Penhey
Add an EnumChoiceWidget, and use it on the branch page. |
681 |
def status_widget(self): |
9570.12.3
by Tim Penhey
More js bits. |
682 |
"""The config to configure the ChoiceSource JS widget."""
|
12534.2.1
by Tim Penhey
Add an EnumChoiceWidget, and use it on the branch page. |
683 |
return EnumChoiceWidget( |
684 |
self.context.branch, IBranch['lifecycle_status'], |
|
685 |
header='Change status to', css_class_prefix='branchstatus') |
|
9570.12.3
by Tim Penhey
More js bits. |
686 |
|
4414.5.12
by Tim Penhey
work in progress |
687 |
|
3277.3.2
by David Allouche
better branch listings |
688 |
class BranchInProductView(BranchView): |
689 |
||
690 |
show_person_link = True |
|
691 |
show_product_link = False |
|
692 |
||
693 |
||
3691.112.6
by David Allouche
properly validate branch name in branch/+edit |
694 |
class BranchNameValidationMixin: |
695 |
"""Provide name validation logic used by several branch view classes."""
|
|
696 |
||
10456.2.13
by Brad Crittenden
Added browser support for other +setbranch options |
697 |
def _setBranchExists(self, existing_branch, field_name='name'): |
7362.3.4
by Jonathan Lange
Factor out branch existence failure logic. |
698 |
owner = existing_branch.owner |
699 |
if owner == self.user: |
|
700 |
prefix = "You already have" |
|
701 |
else: |
|
702 |
prefix = "%s already has" % cgi.escape(owner.displayname) |
|
8120.2.3
by Jonathan Lange
No need to refer to product here. |
703 |
message = ( |
704 |
"%s a branch for <em>%s</em> called <em>%s</em>." |
|
8120.2.24
by Jonathan Lange
Use display name |
705 |
% (prefix, existing_branch.target.displayname, |
706 |
existing_branch.name)) |
|
10456.2.13
by Brad Crittenden
Added browser support for other +setbranch options |
707 |
self.setFieldError(field_name, structured(message)) |
7362.3.4
by Jonathan Lange
Factor out branch existence failure logic. |
708 |
|
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
709 |
|
8137.17.24
by Barry Warsaw
thread merge |
710 |
class BranchEditSchema(Interface): |
711 |
"""Defines the fields for the edit form.
|
|
712 |
||
713 |
This is necessary so as to make an editable field for the branch privacy.
|
|
714 |
Normally the field is not editable through the interface in order to stop
|
|
715 |
direct setting of the private attribute, but in this case we actually want
|
|
716 |
the user to be able to edit it.
|
|
717 |
"""
|
|
718 |
use_template(IBranch, include=[ |
|
8418.1.1
by Jonathan Lange
Remove a stack of code that lets you move branches. |
719 |
'name', |
720 |
'url', |
|
8503.2.1
by Paul Hummer
Re-introduced IBranch.description |
721 |
'description', |
8418.1.1
by Jonathan Lange
Remove a stack of code that lets you move branches. |
722 |
'lifecycle_status', |
723 |
'whiteboard', |
|
724 |
])
|
|
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
725 |
explicitly_private = copy_field( |
726 |
IBranch['explicitly_private'], readonly=False) |
|
9041.5.1
by Tim Penhey
Mid change when I realise I need trunk. |
727 |
reviewer = copy_field(IBranch['reviewer'], required=True) |
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
728 |
owner = copy_field(IBranch['owner'], readonly=False) |
8137.17.24
by Barry Warsaw
thread merge |
729 |
|
730 |
||
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
731 |
class BranchEditFormView(LaunchpadEditFormView): |
732 |
"""Base class for forms that edit a branch."""
|
|
733 |
||
8137.17.24
by Barry Warsaw
thread merge |
734 |
schema = BranchEditSchema |
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
735 |
field_names = None |
736 |
||
8137.17.24
by Barry Warsaw
thread merge |
737 |
@property
|
9041.5.1
by Tim Penhey
Mid change when I realise I need trunk. |
738 |
def page_title(self): |
9041.5.4
by Tim Penhey
Remove the h1 on the edit page and add a label. |
739 |
return 'Edit %s' % self.context.displayname |
740 |
||
741 |
@property
|
|
742 |
def label(self): |
|
743 |
return self.page_title |
|
9041.5.1
by Tim Penhey
Mid change when I realise I need trunk. |
744 |
|
745 |
@property
|
|
8137.17.24
by Barry Warsaw
thread merge |
746 |
def adapters(self): |
747 |
"""See `LaunchpadFormView`"""
|
|
748 |
return {BranchEditSchema: self.context} |
|
749 |
||
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
750 |
@action('Change Branch', name='change') |
751 |
def change_action(self, action, data): |
|
6096.6.1
by Tim Penhey
Add owner to the branch edit page (and removed author). |
752 |
# If the owner or product has changed, add an explicit notification.
|
8971.24.27
by Tim Penhey
Updates following review. Just some more tests for error conditions to go. |
753 |
# We take our own snapshot here to make sure that the snapshot records
|
754 |
# changes to the owner and private, and we notify the listeners
|
|
755 |
# explicitly below rather than the notification that would normally be
|
|
756 |
# sent in updateContextFromData.
|
|
9041.5.3
by Tim Penhey
Clean up setting the reviewer. |
757 |
changed = False |
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
758 |
branch_before_modification = Snapshot( |
759 |
self.context, providing=providedBy(self.context)) |
|
6096.6.1
by Tim Penhey
Add owner to the branch edit page (and removed author). |
760 |
if 'owner' in data: |
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
761 |
new_owner = data.pop('owner') |
6096.6.1
by Tim Penhey
Add owner to the branch edit page (and removed author). |
762 |
if new_owner != self.context.owner: |
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
763 |
self.context.setOwner(new_owner, self.user) |
9041.5.3
by Tim Penhey
Clean up setting the reviewer. |
764 |
changed = True |
6096.6.1
by Tim Penhey
Add owner to the branch edit page (and removed author). |
765 |
self.request.response.addNotification( |
766 |
"The branch owner has been changed to %s (%s)" |
|
767 |
% (new_owner.displayname, new_owner.name)) |
|
8137.17.24
by Barry Warsaw
thread merge |
768 |
if 'private' in data: |
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
769 |
# Read only for display.
|
770 |
data.pop('private') |
|
771 |
if 'explicitly_private' in data: |
|
772 |
private = data.pop('explicitly_private') |
|
13760.3.5
by Ian Booth
Add story tests and implementation for branch edit page |
773 |
if (private != self.context.private |
774 |
and self.context.private == self.context.explicitly_private): |
|
8137.17.24
by Barry Warsaw
thread merge |
775 |
# We only want to show notifications if it actually changed.
|
9941.1.4
by Tim Penhey
Update the view class to pass through the user and update the story. |
776 |
self.context.setPrivate(private, self.user) |
9041.5.3
by Tim Penhey
Clean up setting the reviewer. |
777 |
changed = True |
8137.17.24
by Barry Warsaw
thread merge |
778 |
if private: |
779 |
self.request.response.addNotification( |
|
780 |
"The branch is now private, and only visible to the "
|
|
781 |
"owner and to subscribers.") |
|
782 |
else: |
|
783 |
self.request.response.addNotification( |
|
784 |
"The branch is now publicly accessible.") |
|
9041.5.3
by Tim Penhey
Clean up setting the reviewer. |
785 |
if 'reviewer' in data: |
9084.1.11
by Tim Penhey
Fix the test. |
786 |
reviewer = data.pop('reviewer') |
9041.5.3
by Tim Penhey
Clean up setting the reviewer. |
787 |
if reviewer != self.context.code_reviewer: |
788 |
if reviewer == self.context.owner: |
|
789 |
# Clear the reviewer if set to the same as the owner.
|
|
790 |
self.context.reviewer = None |
|
791 |
else: |
|
792 |
self.context.reviewer = reviewer |
|
793 |
changed = True |
|
794 |
||
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
795 |
if self.updateContextFromData(data, notify_modified=False): |
9041.5.3
by Tim Penhey
Clean up setting the reviewer. |
796 |
changed = True |
797 |
||
798 |
if changed: |
|
8971.24.15
by Tim Penhey
Make the edit view notify owner updates. |
799 |
# Notify the object has changed with the snapshot that was taken
|
800 |
# earler.
|
|
801 |
field_names = [ |
|
802 |
form_field.__name__ for form_field in self.form_fields] |
|
803 |
notify(ObjectModifiedEvent( |
|
804 |
self.context, branch_before_modification, field_names)) |
|
5001.2.5
by Tim Penhey
Only update last modified if there were in fact changes. |
805 |
# Only specify that the context was modified if there
|
806 |
# was in fact a change.
|
|
807 |
self.context.date_last_modified = UTC_NOW |
|
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
808 |
|
809 |
@property
|
|
810 |
def next_url(self): |
|
811 |
return canonical_url(self.context) |
|
812 |
||
6096.6.5
by Tim Penhey
Change cancel button to cancel link. |
813 |
cancel_url = next_url |
814 |
||
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
815 |
|
8211.5.3
by Paul Hummer
Don't want to completely remove whiteboards, because vcs-imports have a valid use case for them |
816 |
class BranchEditWhiteboardView(BranchEditFormView): |
817 |
"""A view for editing the whiteboard only."""
|
|
818 |
||
819 |
field_names = ['whiteboard'] |
|
820 |
||
821 |
||
9570.12.1
by Tim Penhey
Add a link and simple view for editing the status. |
822 |
class BranchEditStatusView(BranchEditFormView): |
823 |
"""A view for editing the lifecycle status only."""
|
|
824 |
||
825 |
field_names = ['lifecycle_status'] |
|
826 |
||
827 |
||
4795.2.10
by jml at canonical
Rename mirror failure to mirror status |
828 |
class BranchMirrorStatusView(LaunchpadFormView): |
829 |
"""This view displays the mirror status of a branch.
|
|
830 |
||
831 |
This includes the next mirror time and any failures that may have
|
|
832 |
occurred.
|
|
833 |
"""
|
|
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
834 |
|
835 |
MAXIMUM_STATUS_MESSAGE_LENGTH = 128 |
|
836 |
||
837 |
schema = Interface |
|
838 |
||
839 |
field_names = [] |
|
840 |
||
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
841 |
@property
|
842 |
def show_detailed_error_message(self): |
|
843 |
"""Show detailed error message for branch owner and experts."""
|
|
844 |
if self.user is None: |
|
845 |
return False |
|
846 |
else: |
|
847 |
celebs = getUtility(ILaunchpadCelebrities) |
|
848 |
return (self.user.inTeam(self.context.owner) or |
|
13401.2.2
by Steve Kowalik
Kill all references to the celebrity. |
849 |
self.user.inTeam(celebs.admin)) |
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
850 |
|
851 |
@property
|
|
852 |
def mirror_of_ssh(self): |
|
853 |
"""True if this a mirror branch with an sftp or bzr+ssh URL."""
|
|
854 |
if not self.context.url: |
|
13717.1.5
by Aaron Bentley
Fix lint. |
855 |
return False # not a mirror branch |
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
856 |
uri = URI(self.context.url) |
857 |
return uri.scheme in ('sftp', 'bzr+ssh') |
|
858 |
||
859 |
@property
|
|
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
860 |
def in_mirror_queue(self): |
861 |
"""Is it likely that the branch is being mirrored in the next run of
|
|
862 |
the puller?
|
|
863 |
"""
|
|
5223.7.2
by jml at canonical
Rename mirror_request_time to next_mirror_time in code. |
864 |
return self.context.next_mirror_time < datetime.now(pytz.UTC) |
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
865 |
|
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
866 |
@property
|
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
867 |
def mirror_disabled(self): |
868 |
"""Has mirroring this branch been disabled?"""
|
|
5223.7.2
by jml at canonical
Rename mirror_request_time to next_mirror_time in code. |
869 |
return self.context.next_mirror_time is None |
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
870 |
|
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
871 |
@property
|
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
872 |
def mirror_failed_once(self): |
873 |
"""Has there been exactly one failed attempt to mirror this branch?"""
|
|
874 |
return self.context.mirror_failures == 1 |
|
875 |
||
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
876 |
@property
|
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
877 |
def mirror_status_message(self): |
878 |
"""A message from a bad scan or pull, truncated for display."""
|
|
879 |
message = self.context.mirror_status_message |
|
880 |
if len(message) <= self.MAXIMUM_STATUS_MESSAGE_LENGTH: |
|
881 |
return message |
|
882 |
return truncate_text( |
|
883 |
message, self.MAXIMUM_STATUS_MESSAGE_LENGTH) + ' ...' |
|
884 |
||
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
885 |
@property
|
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
886 |
def show_mirror_failure(self): |
887 |
"""True if mirror_of_ssh is false and branch mirroring failed."""
|
|
5637.2.1
by Tim Penhey
Moved the error text around and fixed for Bazaar experts. |
888 |
return not self.mirror_of_ssh and self.context.mirror_failures |
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
889 |
|
4795.2.15
by jml at canonical
Add proper urls for status view. |
890 |
@property
|
891 |
def action_url(self): |
|
4795.2.16
by jml at canonical
Fully rename to mirror-status and fix up a couple of bugs. |
892 |
return "%s/+mirror-status" % canonical_url(self.context) |
4795.2.15
by jml at canonical
Add proper urls for status view. |
893 |
|
894 |
@property
|
|
895 |
def next_url(self): |
|
896 |
return canonical_url(self.context) |
|
897 |
||
4795.2.7
by jml at canonical
Make the "Try Again" button work at the expense of breaking a couple of |
898 |
@action('Try again', name='try-again') |
899 |
def retry(self, action, data): |
|
900 |
self.context.requestMirror() |
|
901 |
||
902 |
||
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
903 |
class BranchDeletionView(LaunchpadFormView): |
904 |
"""Used to delete a branch."""
|
|
905 |
||
906 |
schema = IBranch |
|
907 |
field_names = [] |
|
908 |
||
9084.3.3
by Tim Penhey
Update branch-delete.pt |
909 |
@property
|
910 |
def page_title(self): |
|
911 |
return smartquote('Delete branch "%s"' % self.context.displayname) |
|
912 |
||
5616.3.35
by Aaron Bentley
Updates from review |
913 |
@cachedproperty
|
914 |
def display_deletion_requirements(self): |
|
5616.3.11
by Aaron Bentley
Refactor and document interface |
915 |
"""Normal deletion requirements, indication of permissions.
|
916 |
||
917 |
:return: A list of tuples of (item, action, reason, allowed)
|
|
918 |
"""
|
|
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
919 |
reqs = [] |
920 |
for item, (action, reason) in ( |
|
921 |
self.context.deletionRequirements().iteritems()): |
|
922 |
allowed = check_permission('launchpad.Edit', item) |
|
923 |
reqs.append((item, action, reason, allowed)) |
|
924 |
return reqs |
|
925 |
||
7735.1.1
by Tim Penhey
Don't allow branches with other branches stacked on them to be deleted. |
926 |
@cachedproperty
|
927 |
def stacked_branches_count(self): |
|
928 |
"""Cache a count of the branches stacked on this."""
|
|
929 |
return self.context.getStackedBranches().count() |
|
930 |
||
7735.1.2
by Tim Penhey
Fix plural text. |
931 |
def stacked_branches_text(self): |
932 |
"""Cache a count of the branches stacked on this."""
|
|
933 |
if self.stacked_branches_count == 1: |
|
934 |
return _('branch') |
|
935 |
else: |
|
936 |
return _('branches') |
|
937 |
||
5616.3.2
by Aaron Bentley
Only show delete button when deletion will succeed |
938 |
def all_permitted(self): |
5616.3.11
by Aaron Bentley
Refactor and document interface |
939 |
"""Return True if all deletion requirements are permitted, else False.
|
940 |
||
5616.3.35
by Aaron Bentley
Updates from review |
941 |
Uses display_deletion_requirements as its source data.
|
5616.3.11
by Aaron Bentley
Refactor and document interface |
942 |
"""
|
7735.1.1
by Tim Penhey
Don't allow branches with other branches stacked on them to be deleted. |
943 |
# Not permitted if there are any branches stacked on this.
|
944 |
if self.stacked_branches_count > 0: |
|
945 |
return False |
|
5616.3.2
by Aaron Bentley
Only show delete button when deletion will succeed |
946 |
return len([item for item, action, reason, allowed in |
5616.3.35
by Aaron Bentley
Updates from review |
947 |
self.display_deletion_requirements if not allowed]) == 0 |
5616.3.2
by Aaron Bentley
Only show delete button when deletion will succeed |
948 |
|
5616.3.35
by Aaron Bentley
Updates from review |
949 |
@action('Delete', name='delete_branch', |
5616.3.2
by Aaron Bentley
Only show delete button when deletion will succeed |
950 |
condition=lambda x, y: x.all_permitted()) |
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
951 |
def delete_branch_action(self, action, data): |
952 |
branch = self.context |
|
5616.3.2
by Aaron Bentley
Only show delete button when deletion will succeed |
953 |
if self.all_permitted(): |
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
954 |
# Since the user is going to delete the branch, we need to have
|
7847.1.23
by Jonathan Lange
Make deleting a package branch go back to the package branch listing |
955 |
# somewhere valid to send them next.
|
7847.1.25
by Jonathan Lange
Simplify by just getting the canonical url of the branch target. |
956 |
self.next_url = canonical_url(branch.target) |
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
957 |
message = "Branch %s deleted." % branch.unique_name |
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
958 |
self.context.destroySelf(break_references=True) |
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
959 |
self.request.response.addNotification(message) |
960 |
else: |
|
961 |
self.request.response.addNotification( |
|
962 |
"This branch cannot be deleted.") |
|
963 |
self.next_url = canonical_url(branch) |
|
964 |
||
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
965 |
@property
|
966 |
def branch_deletion_actions(self): |
|
5616.3.11
by Aaron Bentley
Refactor and document interface |
967 |
"""Return the branch deletion actions as a zpt-friendly dict.
|
968 |
||
969 |
The keys are 'delete' and 'alter'; the values are dicts of
|
|
970 |
'item', 'reason' and 'allowed'.
|
|
971 |
"""
|
|
5616.3.12
by Aaron Bentley
Update from comments |
972 |
row_dict = {'delete': [], 'alter': [], 'break_link': []} |
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
973 |
for item, action, reason, allowed in ( |
5616.3.35
by Aaron Bentley
Updates from review |
974 |
self.display_deletion_requirements): |
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
975 |
if IBugBranch.providedBy(item): |
5616.3.12
by Aaron Bentley
Update from comments |
976 |
action = 'break_link' |
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
977 |
elif ISpecificationBranch.providedBy(item): |
5616.3.12
by Aaron Bentley
Update from comments |
978 |
action = 'break_link' |
979 |
elif IProductSeries.providedBy(item): |
|
980 |
action = 'break_link' |
|
5616.3.1
by Aaron Bentley
Initial implementation of smart branch deletion page |
981 |
row = {'item': item, |
982 |
'reason': reason, |
|
983 |
'allowed': allowed, |
|
984 |
}
|
|
985 |
row_dict[action].append(row) |
|
986 |
return row_dict |
|
987 |
||
6618.2.1
by Paul Hummer
Adds cancel_url, fixes tests |
988 |
@property
|
989 |
def cancel_url(self): |
|
990 |
return canonical_url(self.context) |
|
5616.3.35
by Aaron Bentley
Updates from review |
991 |
|
4629.4.1
by Tim Penhey
First cut, and some branch cleanup. |
992 |
|
7675.477.1
by Paul Hummer
Reverted the reversion of the patch that went into devel by mistake |
993 |
class BranchUpgradeView(LaunchpadFormView): |
994 |
"""Used to upgrade a branch."""
|
|
995 |
||
996 |
schema = IBranch |
|
997 |
field_names = [] |
|
998 |
||
999 |
@property
|
|
1000 |
def page_title(self): |
|
1001 |
return smartquote('Upgrade branch "%s"' % self.context.displayname) |
|
1002 |
||
1003 |
@property
|
|
1004 |
def next_url(self): |
|
1005 |
return canonical_url(self.context) |
|
1006 |
||
1007 |
cancel_url = next_url |
|
1008 |
||
1009 |
@action('Upgrade', name='upgrade_branch') |
|
1010 |
def upgrade_branch_action(self, action, data): |
|
13750.1.4
by Aaron Bentley
Ensure view produces a nice notification. |
1011 |
try: |
1012 |
self.context.requestUpgrade(self.user) |
|
1013 |
except CannotUpgradeBranch as e: |
|
1014 |
self.request.response.addErrorNotification(e) |
|
7675.477.1
by Paul Hummer
Reverted the reversion of the patch that went into devel by mistake |
1015 |
|
1016 |
||
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
1017 |
class BranchEditView(BranchEditFormView, BranchNameValidationMixin): |
5350.3.2
by Tim Penhey
Allow any logged in user to edit the branch whiteboard. |
1018 |
"""The main branch view for editing the branch attributes."""
|
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1019 |
|
6096.6.1
by Tim Penhey
Add owner to the branch edit page (and removed author). |
1020 |
field_names = [ |
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
1021 |
'owner', 'name', 'explicitly_private', 'url', 'description', |
1022 |
'lifecycle_status'] |
|
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1023 |
|
5430.5.2
by Tim Penhey
Setting the radio button for the status widget when editing |
1024 |
custom_widget('lifecycle_status', LaunchpadRadioWidgetWithDescription) |
1025 |
||
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1026 |
def setUpFields(self): |
1027 |
LaunchpadFormView.setUpFields(self) |
|
1028 |
# This is to prevent users from converting push/import
|
|
1029 |
# branches to pull branches.
|
|
4333.6.1
by Tim Penhey
Allow the user to toggle branch privacy if the should be allowed to. |
1030 |
branch = self.context |
4693.1.1
by Tim Penhey
First part of remote branches. |
1031 |
if branch.branch_type in (BranchType.HOSTED, BranchType.IMPORTED): |
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1032 |
self.form_fields = self.form_fields.omit('url') |
1033 |
||
8137.17.24
by Barry Warsaw
thread merge |
1034 |
policy = IBranchNamespacePolicy(branch.namespace) |
1035 |
if branch.private: |
|
1036 |
# If the branch is private, and can be public, show the field.
|
|
1037 |
show_private_field = policy.canBranchesBePublic() |
|
13760.3.5
by Ian Booth
Add story tests and implementation for branch edit page |
1038 |
|
1039 |
# If this branch is public but is deemed private because it is
|
|
1040 |
# stacked on a private branch, disable the field.
|
|
1041 |
if not branch.explicitly_private: |
|
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
1042 |
show_private_field = False |
13760.3.5
by Ian Booth
Add story tests and implementation for branch edit page |
1043 |
private_info = Bool( |
1044 |
__name__="private", |
|
1045 |
title=_("Branch is confidential"), |
|
1046 |
description=_( |
|
1047 |
"This branch is confidential because it is stacked "
|
|
1048 |
"on a private branch.")) |
|
1049 |
private_info_field = form.Fields( |
|
1050 |
private_info, render_context=self.render_context) |
|
1051 |
self.form_fields = self.form_fields.omit('private') |
|
1052 |
self.form_fields = private_info_field + self.form_fields |
|
1053 |
self.form_fields['private'].custom_widget = ( |
|
1054 |
CustomWidgetFactory( |
|
1055 |
CheckBoxWidget, extra='disabled="disabled"')) |
|
4333.6.1
by Tim Penhey
Allow the user to toggle branch privacy if the should be allowed to. |
1056 |
else: |
8137.17.24
by Barry Warsaw
thread merge |
1057 |
# If the branch is public, and can be made private, show the
|
9941.1.4
by Tim Penhey
Update the view class to pass through the user and update the story. |
1058 |
# field. Users with special access rights to branches can set
|
1059 |
# public branches as private.
|
|
1060 |
show_private_field = ( |
|
1061 |
policy.canBranchesBePrivate() or |
|
1062 |
user_has_special_branch_access(self.user)) |
|
4333.6.1
by Tim Penhey
Allow the user to toggle branch privacy if the should be allowed to. |
1063 |
|
8137.17.24
by Barry Warsaw
thread merge |
1064 |
if not show_private_field: |
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
1065 |
self.form_fields = self.form_fields.omit('explicitly_private') |
4333.6.1
by Tim Penhey
Allow the user to toggle branch privacy if the should be allowed to. |
1066 |
|
6096.6.3
by Tim Penhey
Make Bazaar Experts and Launchpad administrators able to reassign a branch to anyone. |
1067 |
# If the user can administer branches, then they should be able to
|
1068 |
# assign the ownership of the branch to any valid person or team.
|
|
1069 |
if check_permission('launchpad.Admin', branch): |
|
1070 |
owner_field = self.schema['owner'] |
|
1071 |
any_owner_choice = Choice( |
|
1072 |
__name__='owner', title=owner_field.title, |
|
13314.12.2
by Ian Booth
Lint |
1073 |
description=_("As an administrator you are able to reassign" |
6096.6.3
by Tim Penhey
Make Bazaar Experts and Launchpad administrators able to reassign a branch to anyone. |
1074 |
" this branch to any person or team."), |
1075 |
required=True, vocabulary='ValidPersonOrTeam') |
|
1076 |
any_owner_field = form.Fields( |
|
1077 |
any_owner_choice, render_context=self.render_context) |
|
1078 |
# Replace the normal owner field with a more permissive vocab.
|
|
1079 |
self.form_fields = self.form_fields.omit('owner') |
|
1080 |
self.form_fields = any_owner_field + self.form_fields |
|
10843.3.7
by Tim Penhey
If we are in the situation where the branch editor isn't in the team of the branch owner (as we get in the situation where an official package branch is being edited by an uploader), add the owner to the vocabulary used for the owner field.~ |
1081 |
else: |
1082 |
# For normal users, there is an edge case with package branches
|
|
1083 |
# where the editor may not be in the team of the branch owner. In
|
|
1084 |
# these cases we need to extend the vocabulary connected to the
|
|
1085 |
# owner field.
|
|
1086 |
if not self.user.inTeam(self.context.owner): |
|
1087 |
vocab = UserTeamsParticipationPlusSelfVocabulary() |
|
1088 |
owner = self.context.owner |
|
1089 |
terms = [SimpleTerm( |
|
13314.13.1
by Ian Booth
Fix implementation - use custom vocab |
1090 |
owner, owner.name, owner.unique_displayname)] |
10843.3.7
by Tim Penhey
If we are in the situation where the branch editor isn't in the team of the branch owner (as we get in the situation where an official package branch is being edited by an uploader), add the owner to the vocabulary used for the owner field.~ |
1091 |
terms.extend([term for term in vocab]) |
1092 |
owner_field = self.schema['owner'] |
|
1093 |
owner_choice = Choice( |
|
1094 |
__name__='owner', title=owner_field.title, |
|
13314.12.2
by Ian Booth
Lint |
1095 |
description=owner_field.description, |
10843.3.7
by Tim Penhey
If we are in the situation where the branch editor isn't in the team of the branch owner (as we get in the situation where an official package branch is being edited by an uploader), add the owner to the vocabulary used for the owner field.~ |
1096 |
required=True, vocabulary=SimpleVocabulary(terms)) |
1097 |
new_owner_field = form.Fields( |
|
1098 |
owner_choice, render_context=self.render_context) |
|
1099 |
# Replace the normal owner field with a more permissive vocab.
|
|
1100 |
self.form_fields = self.form_fields.omit('owner') |
|
1101 |
self.form_fields = new_owner_field + self.form_fields |
|
6096.6.3
by Tim Penhey
Make Bazaar Experts and Launchpad administrators able to reassign a branch to anyone. |
1102 |
|
3691.112.6
by David Allouche
properly validate branch name in branch/+edit |
1103 |
def validate(self, data): |
4673.7.1
by Michael Hudson
prevent reassignment of +junk branches to teams, test, and a couple more |
1104 |
# Check that we're not moving a team branch to the +junk
|
1105 |
# pseudo project.
|
|
6096.6.4
by Tim Penhey
Update the pagetests. |
1106 |
owner = data['owner'] |
8418.1.1
by Jonathan Lange
Remove a stack of code that lets you move branches. |
1107 |
if 'name' in data: |
8418.1.7
by Jonathan Lange
Remove any references to product in the branch edit form. |
1108 |
# Only validate if the name has changed or the owner has changed.
|
8418.1.1
by Jonathan Lange
Remove a stack of code that lets you move branches. |
1109 |
if ((data['name'] != self.context.name) or |
6194.1.1
by Tim Penhey
Back out the change that required branches names to be unique across a product, but keep the good error messages. |
1110 |
(owner != self.context.owner)): |
8418.1.8
by Jonathan Lange
Clean up the code, improve test coverage. |
1111 |
# We only allow moving within the same branch target for now.
|
1112 |
namespace = self.context.target.getNamespace(owner) |
|
8418.1.7
by Jonathan Lange
Remove any references to product in the branch edit form. |
1113 |
try: |
1114 |
namespace.validateMove( |
|
1115 |
self.context, self.user, name=data['name']) |
|
13025.3.1
by William Grant
Display an error when attempting to change the owner of a branch to a value forbidden by the visibility policy. |
1116 |
except BranchCreationForbidden: |
1117 |
self.addError( |
|
1118 |
"%s is not allowed to own branches in %s." % ( |
|
1119 |
owner.displayname, self.context.target.displayname)) |
|
8418.1.7
by Jonathan Lange
Remove any references to product in the branch edit form. |
1120 |
except BranchExists, e: |
1121 |
self._setBranchExists(e.existing_branch) |
|
4953.6.1
by Tim Penhey
Removed unhelpful or obsolete help, and corrected URL validation |
1122 |
|
1123 |
# If the branch is a MIRRORED branch, then the url
|
|
1124 |
# must be supplied, and if HOSTED the url must *not*
|
|
1125 |
# be supplied.
|
|
1126 |
url = data.get('url') |
|
4693.1.1
by Tim Penhey
First part of remote branches. |
1127 |
if self.context.branch_type == BranchType.MIRRORED: |
4953.6.1
by Tim Penhey
Removed unhelpful or obsolete help, and corrected URL validation |
1128 |
if url is None: |
1129 |
# If the url is not set due to url validation errors,
|
|
1130 |
# there will be an error set for it.
|
|
5243.1.1
by Jonathan Knowles
Renaming method getWidgetError (in LaunchpadFormView) to getFieldError. |
1131 |
error = self.getFieldError('url') |
4953.6.1
by Tim Penhey
Removed unhelpful or obsolete help, and corrected URL validation |
1132 |
if not error: |
1133 |
self.setFieldError( |
|
1134 |
'url', |
|
1135 |
'Branch URLs are required for Mirrored branches.') |
|
1136 |
else: |
|
4953.6.2
by Tim Penhey
Updates following review comments. |
1137 |
# We don't care about whether the URL is set for REMOTE branches,
|
1138 |
# and the URL field is not shown for IMPORT or HOSTED branches.
|
|
4953.6.1
by Tim Penhey
Removed unhelpful or obsolete help, and corrected URL validation |
1139 |
pass
|
3691.112.9
by David Allouche
review fixes, convert xx-team-branches.txt to testbrowser |
1140 |
|
1141 |
||
9041.5.1
by Tim Penhey
Mid change when I realise I need trunk. |
1142 |
class BranchReviewerEditView(BranchEditFormView): |
7211.1.4
by Tim Penhey
Changed view names and added test. |
1143 |
"""The view to set the review team."""
|
1144 |
||
9041.5.1
by Tim Penhey
Mid change when I realise I need trunk. |
1145 |
field_names = ['reviewer'] |
7211.1.4
by Tim Penhey
Changed view names and added test. |
1146 |
|
1147 |
@property
|
|
1148 |
def initial_values(self): |
|
1149 |
return {'reviewer': self.context.code_reviewer} |
|
7211.1.2
by Tim Penhey
Added the views. |
1150 |
|
1151 |
||
3691.112.6
by David Allouche
properly validate branch name in branch/+edit |
1152 |
class BranchAddView(LaunchpadFormView, BranchNameValidationMixin): |
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1153 |
|
12924.3.3
by Tim Penhey
Fix up the branch_type vocabulary, and remove some XXX comments that are not worthy. |
1154 |
class schema(Interface): |
1155 |
use_template( |
|
13756.5.1
by Jelmer Vernooij
Reimport bzr code import support UI patch. |
1156 |
IBranch, include=['owner', 'name', 'lifecycle_status']) |
12924.3.3
by Tim Penhey
Fix up the branch_type vocabulary, and remove some XXX comments that are not worthy. |
1157 |
|
6954.3.3
by Tim Penhey
Make the read only fields available for initial creation. |
1158 |
for_input = True |
13756.5.1
by Jelmer Vernooij
Reimport bzr code import support UI patch. |
1159 |
field_names = ['owner', 'name', 'lifecycle_status'] |
3691.112.1
by David Allouche
Fixing $branch/+edit, day one |
1160 |
|
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1161 |
branch = None |
5430.5.1
by Tim Penhey
Hacking the radio widget to show vocab descriptions |
1162 |
custom_widget('lifecycle_status', LaunchpadRadioWidgetWithDescription) |
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1163 |
|
8120.2.12
by Jonathan Lange
Fix up the initial focus -- lost in combining the two views. |
1164 |
initial_focus_widget = 'name' |
1165 |
||
4693.1.1
by Tim Penhey
First part of remote branches. |
1166 |
@property
|
9084.3.2
by Tim Penhey
Update branch-add.pt. |
1167 |
def page_title(self): |
1168 |
return 'Register a branch' |
|
1169 |
||
1170 |
@property
|
|
4693.1.1
by Tim Penhey
First part of remote branches. |
1171 |
def initial_values(self): |
8120.2.11
by Jonathan Lange
Delete PersonBranchAddView and ProductBranchAddView, since the only |
1172 |
return { |
1173 |
'owner': self.default_owner, |
|
1174 |
'branch_type': UICreatableBranchType.MIRRORED} |
|
1175 |
||
1176 |
@property
|
|
8120.2.13
by Jonathan Lange
Make the unique name javascript work by making it use the name of the |
1177 |
def target(self): |
1178 |
"""The branch target for the context."""
|
|
1179 |
return IBranchTarget(self.context) |
|
1180 |
||
1181 |
@property
|
|
8120.2.11
by Jonathan Lange
Delete PersonBranchAddView and ProductBranchAddView, since the only |
1182 |
def default_owner(self): |
1183 |
"""The default owner of branches in this context.
|
|
1184 |
||
1185 |
If the context is a person, then it's the context. If the context is
|
|
1186 |
not a person, then the default owner is the currently logged-in user.
|
|
1187 |
"""
|
|
1188 |
return IPerson(self.context, self.user) |
|
4693.1.1
by Tim Penhey
First part of remote branches. |
1189 |
|
5543.5.10
by Tim Penhey
Updates following review. |
1190 |
@action('Register Branch', name='add') |
3691.68.12
by James Henstridge
convert branch edit and add views to LaunchpadFormView |
1191 |
def add_action(self, action, data): |
1192 |
"""Handle a request to create a new branch for this product."""
|
|
4333.5.5
by Tim Penhey
Updating the views for creating branches, and the XMLRPC views |
1193 |
try: |
8120.2.14
by Jonathan Lange
Minor cleanup |
1194 |
namespace = self.target.getNamespace(data['owner']) |
7959.1.10
by Tim Penhey
Kill IBranchSet.new. |
1195 |
self.branch = namespace.createBranch( |
13756.5.1
by Jelmer Vernooij
Reimport bzr code import support UI patch. |
1196 |
branch_type=BranchType.HOSTED, |
4333.5.5
by Tim Penhey
Updating the views for creating branches, and the XMLRPC views |
1197 |
name=data['name'], |
6043.1.20
by Jonathan Lange
Uses of the creator kwarg that I missed. |
1198 |
registrant=self.user, |
13756.5.1
by Jelmer Vernooij
Reimport bzr code import support UI patch. |
1199 |
url=None, |
8137.17.24
by Barry Warsaw
thread merge |
1200 |
lifecycle_status=data['lifecycle_status']) |
4333.5.13
by Tim Penhey
Updates following review comments. |
1201 |
except BranchCreationForbidden: |
8120.2.10
by Jonathan Lange
Many classes of error go away when you are only allowed to create branches |
1202 |
self.addError( |
1203 |
"You are not allowed to create branches in %s." % |
|
1204 |
self.context.displayname) |
|
7362.3.6
by Jonathan Lange
Don't look before you leap. |
1205 |
except BranchExists, e: |
1206 |
self._setBranchExists(e.existing_branch) |
|
4333.5.13
by Tim Penhey
Updates following review comments. |
1207 |
else: |
4333.5.5
by Tim Penhey
Updating the views for creating branches, and the XMLRPC views |
1208 |
self.next_url = canonical_url(self.branch) |
1209 |
||
3691.112.5
by David Allouche
properly validate branch name in +addbranch |
1210 |
def validate(self, data): |
6194.1.1
by Tim Penhey
Back out the change that required branches names to be unique across a product, but keep the good error messages. |
1211 |
owner = data['owner'] |
5543.5.1
by Tim Penhey
Refactoring the +addbranch forms |
1212 |
|
1213 |
if not self.user.inTeam(owner): |
|
1214 |
self.setFieldError( |
|
1215 |
'owner', |
|
5543.5.6
by Tim Penhey
Tidying up |
1216 |
'You are not a member of %s' % owner.displayname) |
5543.5.1
by Tim Penhey
Refactoring the +addbranch forms |
1217 |
|
8120.2.17
by Jonathan Lange
Restore the cancel URL link, lost when combining the view classes. |
1218 |
@property
|
1219 |
def cancel_url(self): |
|
1220 |
return canonical_url(self.context) |
|
1221 |
||
3691.112.5
by David Allouche
properly validate branch name in +addbranch |
1222 |
|
4333.2.2
by Tim Penhey
linked, albiet weirdly |
1223 |
class BranchSubscriptionsView(LaunchpadView): |
4333.2.10
by Tim Penhey
yet more review updates |
1224 |
"""The view for the branch subscriptions portlet.
|
4333.2.9
by Tim Penhey
more updates following review |
1225 |
|
1226 |
The view is used to provide a decorated list of branch subscriptions
|
|
1227 |
in order to provide links to be able to edit the subscriptions
|
|
1228 |
based on whether or not the user is able to edit the subscription.
|
|
1229 |
"""
|
|
4333.2.2
by Tim Penhey
linked, albiet weirdly |
1230 |
|
6699.2.4
by Paul Hummer
Adds the new subscription portlet |
1231 |
def owner_is_registrant(self): |
1232 |
"""Return whether or not owner is the same as the registrant"""
|
|
1233 |
return self.context.owner == self.context.registrant |
|
6735.1.1
by Paul Hummer
Adds merge proposal stuffs |
1234 |
|
4414.5.4
by Tim Penhey
First cut at getting a page to register a merge proposal |
1235 |
|
5579.2.1
by Tim Penhey
Some queue management |
1236 |
class BranchMergeQueueView(LaunchpadView): |
5579.2.7
by Tim Penhey
Update the existing pagetest for new actions. |
1237 |
"""The view used to render the merge queue for a branch."""
|
5579.2.11
by Tim Penhey
Updates following review. |
1238 |
|
5579.2.1
by Tim Penhey
Some queue management |
1239 |
@cachedproperty
|
1240 |
def merge_queue(self): |
|
1241 |
"""Get the merge queue and check visibility."""
|
|
1242 |
result = [] |
|
5579.2.11
by Tim Penhey
Updates following review. |
1243 |
for proposal in self.context.getMergeQueue(): |
1244 |
# If the logged in user cannot view the proposal then we
|
|
1245 |
# show a "place holder" in the queue position.
|
|
5579.2.1
by Tim Penhey
Some queue management |
1246 |
if check_permission('launchpad.View', proposal): |
5579.2.11
by Tim Penhey
Updates following review. |
1247 |
result.append(proposal) |
5579.2.1
by Tim Penhey
Some queue management |
1248 |
else: |
5579.2.11
by Tim Penhey
Updates following review. |
1249 |
result.append(None) |
5579.2.1
by Tim Penhey
Some queue management |
1250 |
return result |
1251 |
||
1252 |
||
6623.3.1
by Tim Penhey
Add an option on proposing a merge to choose needs review or work in progress. |
1253 |
class RegisterProposalStatus(EnumeratedType): |
1254 |
"""A restricted status enum for the register proposal form."""
|
|
1255 |
||
6623.3.3
by Tim Penhey
Updates following review. |
1256 |
# The text in this enum is different from the general proposal status
|
1257 |
# enum as we want the help text that is shown in the form to be more
|
|
1258 |
# relevant to the registration of the proposal.
|
|
1259 |
||
6623.3.1
by Tim Penhey
Add an option on proposing a merge to choose needs review or work in progress. |
1260 |
NEEDS_REVIEW = Item(""" |
1261 |
Needs review
|
|
1262 |
||
1263 |
The changes are ready for review.
|
|
1264 |
""") |
|
1265 |
||
1266 |
WORK_IN_PROGRESS = Item(""" |
|
1267 |
Work in progress
|
|
1268 |
||
1269 |
The changes are still being actively worked on, and are not
|
|
1270 |
yet ready for review.
|
|
1271 |
""") |
|
1272 |
||
1273 |
||
1274 |
class RegisterProposalSchema(Interface): |
|
1275 |
"""The schema to define the form for registering a new merge proposal."""
|
|
7325.8.4
by Paul Hummer
Added source branch attribute to bmp api |
1276 |
target_branch = Choice( |
1277 |
title=_('Target Branch'), |
|
8377.8.25
by Tim Penhey
Add a pagetest for merging between packages and products. |
1278 |
vocabulary='Branch', required=True, readonly=True, |
7325.8.4
by Paul Hummer
Added source branch attribute to bmp api |
1279 |
description=_( |
1280 |
"The branch that the source branch will be merged into.")) |
|
1281 |
||
9773.1.9
by Aaron Bentley
Allow setting and viewing prerequisite branch. |
1282 |
prerequisite_branch = Choice( |
1283 |
title=_('Prerequisite Branch'), |
|
1284 |
vocabulary='Branch', required=False, readonly=False, |
|
1285 |
description=_( |
|
9773.1.15
by Aaron Bentley
Clarify text. |
1286 |
'A branch that should be merged before this one. (Its changes'
|
9773.1.16
by Aaron Bentley
Fix syntax in RegisterProposalSchema. |
1287 |
' will not be shown in the diff.)')) |
9773.1.9
by Aaron Bentley
Allow setting and viewing prerequisite branch. |
1288 |
|
7074.2.3
by Tim Penhey
Test the date_review_requested, and other reviewer comments. |
1289 |
comment = Text( |
7675.548.2
by Tim Penhey
Update for the description field. |
1290 |
title=_('Description of the Change'), required=False, |
1291 |
description=_('Describe what changes your branch introduces, ' |
|
1292 |
'what bugs it fixes, or what features it implements. '
|
|
1293 |
'Ideally include rationale and how to test.')) |
|
7074.2.1
by Tim Penhey
Change the register a merge proposal to be a form where the user can specify an initial comment and request a reviewer. |
1294 |
|
7055.6.16
by Tim Penhey
vote tag and field name fixes. |
1295 |
reviewer = copy_field( |
1296 |
ICodeReviewVoteReference['reviewer'], required=False) |
|
7074.2.1
by Tim Penhey
Change the register a merge proposal to be a form where the user can specify an initial comment and request a reviewer. |
1297 |
|
9656.1.4
by Nathan Handler
Wrap lines to resolve some make lint warnings |
1298 |
review_type = copy_field( |
1299 |
ICodeReviewVoteReference['review_type'], |
|
1300 |
description=u'Lowercase keywords describing the type of review you ' |
|
1301 |
'would like to be performed.') |
|
6623.3.1
by Tim Penhey
Add an option on proposing a merge to choose needs review or work in progress. |
1302 |
|
10155.5.1
by Tim Penhey
Make the less used fields on register merge proposal extra options. |
1303 |
commit_message = IBranchMergeProposal['commit_message'] |
1304 |
||
1305 |
needs_review = Bool( |
|
1306 |
title=_("Needs review"), required=True, default=True, |
|
1307 |
description=_( |
|
1308 |
"Is the proposal ready for review now?")) |
|
1309 |
||
6623.3.1
by Tim Penhey
Add an option on proposing a merge to choose needs review or work in progress. |
1310 |
|
4414.5.4
by Tim Penhey
First cut at getting a page to register a merge proposal |
1311 |
class RegisterBranchMergeProposalView(LaunchpadFormView): |
1312 |
"""The view to register new branch merge proposals."""
|
|
6623.3.1
by Tim Penhey
Add an option on proposing a merge to choose needs review or work in progress. |
1313 |
schema = RegisterProposalSchema |
5121.5.10
by Tim Penhey
lint fixes |
1314 |
for_input = True |
4414.5.6
by Tim Penhey
Limiting fields |
1315 |
|
5121.5.1
by Tim Penhey
Initial work with new widget. |
1316 |
custom_widget('target_branch', TargetBranchWidget) |
7573.2.10
by Paul Hummer
Made the merge proposal creation form use a fixed width font |
1317 |
custom_widget('comment', TextAreaWidget, cssClass='codereviewcomment') |
7074.2.1
by Tim Penhey
Change the register a merge proposal to be a form where the user can specify an initial comment and request a reviewer. |
1318 |
|
9209.1.2
by Tim Penhey
Use generic edit to propose for merging. |
1319 |
page_title = label = 'Propose branch for merging' |
1320 |
||
7074.2.1
by Tim Penhey
Change the register a merge proposal to be a form where the user can specify an initial comment and request a reviewer. |
1321 |
@property
|
6618.2.1
by Paul Hummer
Adds cancel_url, fixes tests |
1322 |
def cancel_url(self): |
5280.4.19
by Tim Penhey
merge poposal page test now passes. |
1323 |
return canonical_url(self.context) |
1324 |
||
5430.1.1
by Tim Penhey
Remove the ability for junk branches to traverse to +register-merge. |
1325 |
def initialize(self): |
8377.8.4
by Tim Penhey
Ask the branch target if it supports merge proposals. |
1326 |
"""Show a 404 if the branch target doesn't support proposals."""
|
1327 |
if not self.context.target.supports_merge_proposals: |
|
5430.1.1
by Tim Penhey
Remove the ability for junk branches to traverse to +register-merge. |
1328 |
raise NotFound(self.context, '+register-merge') |
1329 |
LaunchpadFormView.initialize(self) |
|
1330 |
||
7074.2.1
by Tim Penhey
Change the register a merge proposal to be a form where the user can specify an initial comment and request a reviewer. |
1331 |
@action('Propose Merge', name='register') |
4414.5.8
by Tim Penhey
Changing fields and getting it working. |
1332 |
def register_action(self, action, data): |
1333 |
"""Register the new branch merge proposal."""
|
|
1334 |
||
1335 |
registrant = self.user |
|
1336 |
source_branch = self.context |
|
4414.5.25
by Tim Penhey
Updates following review |
1337 |
target_branch = data['target_branch'] |
9773.1.12
by Aaron Bentley
Make prerequisite_branch optional. |
1338 |
prerequisite_branch = data.get('prerequisite_branch') |
4414.5.13
by Tim Penhey
Still work in progress |
1339 |
|
7334.4.18
by Tim Penhey
Updates following review comments. |
1340 |
review_requests = [] |
11542.3.3
by Ian Booth
Refactor initial changes |
1341 |
reviewer = data.get('reviewer') |
1342 |
review_type = data.get('review_type') |
|
11542.3.20
by Ian Booth
Test refactoring as per code review |
1343 |
if reviewer is None: |
1344 |
reviewer = target_branch.code_reviewer |
|
11542.3.3
by Ian Booth
Refactor initial changes |
1345 |
if reviewer is not None: |
1346 |
review_requests.append((reviewer, review_type)) |
|
7334.4.18
by Tim Penhey
Updates following review comments. |
1347 |
|
4414.5.13
by Tim Penhey
Still work in progress |
1348 |
try: |
6618.2.1
by Paul Hummer
Adds cancel_url, fixes tests |
1349 |
proposal = source_branch.addLandingTarget( |
4414.5.13
by Tim Penhey
Still work in progress |
1350 |
registrant=registrant, target_branch=target_branch, |
10155.5.1
by Tim Penhey
Make the less used fields on register merge proposal extra options. |
1351 |
prerequisite_branch=prerequisite_branch, |
1352 |
needs_review=data['needs_review'], |
|
7675.548.9
by Tim Penhey
Stop pretending it is an initial comment. |
1353 |
description=data.get('comment'), |
10155.5.1
by Tim Penhey
Make the less used fields on register merge proposal extra options. |
1354 |
review_requests=review_requests, |
11542.3.20
by Ian Booth
Test refactoring as per code review |
1355 |
commit_message=data.get('commit_message')) |
6618.2.1
by Paul Hummer
Adds cancel_url, fixes tests |
1356 |
self.next_url = canonical_url(proposal) |
4414.5.13
by Tim Penhey
Still work in progress |
1357 |
except InvalidBranchMergeProposal, error: |
1358 |
self.addError(str(error)) |
|
5280.4.19
by Tim Penhey
merge poposal page test now passes. |
1359 |
|
4414.5.13
by Tim Penhey
Still work in progress |
1360 |
def validate(self, data): |
1361 |
source_branch = self.context |
|
1362 |
target_branch = data.get('target_branch') |
|
4414.5.12
by Tim Penhey
work in progress |
1363 |
|
4414.5.8
by Tim Penhey
Changing fields and getting it working. |
1364 |
# Make sure that the target branch is different from the context.
|
4414.5.13
by Tim Penhey
Still work in progress |
1365 |
if target_branch is None: |
1366 |
# Skip the following tests.
|
|
1367 |
# The existance of the target_branch is handled by the form
|
|
1368 |
# machinery.
|
|
1369 |
pass
|
|
1370 |
elif source_branch == target_branch: |
|
4414.5.8
by Tim Penhey
Changing fields and getting it working. |
1371 |
self.setFieldError( |
1372 |
'target_branch', |
|
1373 |
"The target branch cannot be the same as the source branch.") |
|
1374 |
else: |
|
1375 |
# Make sure that the target_branch is in the same project.
|
|
8377.8.7
by Tim Penhey
Fix the view to not check .product. |
1376 |
if not target_branch.isBranchMergeable(source_branch): |
4414.5.8
by Tim Penhey
Changing fields and getting it working. |
1377 |
self.setFieldError( |
1378 |
'target_branch', |
|
8377.8.7
by Tim Penhey
Fix the view to not check .product. |
1379 |
"This branch is not mergeable into %s." % |
1380 |
target_branch.bzr_identity) |
|
4414.5.8
by Tim Penhey
Changing fields and getting it working. |
1381 |
|
6233.6.1
by Michael Hudson
stuff |
1382 |
|
1383 |
class BranchRequestImportView(LaunchpadFormView): |
|
6233.6.10
by Michael Hudson
a docstring |
1384 |
"""The view to provide an 'Import now' button on the branch index page.
|
1385 |
||
1386 |
This only appears on the page of a branch with an associated code import
|
|
1387 |
that is being actively imported and where there is a import scheduled at
|
|
1388 |
some point in the future.
|
|
1389 |
"""
|
|
6233.6.1
by Michael Hudson
stuff |
1390 |
|
1391 |
schema = IBranch |
|
1392 |
field_names = [] |
|
1393 |
||
6233.6.9
by Michael Hudson
review comments |
1394 |
form_style = "display: inline" |
6233.6.1
by Michael Hudson
stuff |
1395 |
|
1396 |
@property
|
|
1397 |
def next_url(self): |
|
1398 |
return canonical_url(self.context) |
|
1399 |
||
1400 |
@action('Import Now', name='request') |
|
1401 |
def request_import_action(self, action, data): |
|
10454.12.4
by James Westby
Use the new method from the existing browser code. |
1402 |
try: |
1403 |
self.context.code_import.requestImport( |
|
1404 |
self.user, error_if_already_requested=True) |
|
1405 |
self.request.response.addNotification( |
|
1406 |
"Import will run as soon as possible.") |
|
1407 |
except CodeImportNotInReviewedState: |
|
6233.6.2
by Michael Hudson
tests and stuff |
1408 |
self.request.response.addNotification( |
6233.6.9
by Michael Hudson
review comments |
1409 |
"This import is no longer being updated automatically.") |
10454.12.4
by James Westby
Use the new method from the existing browser code. |
1410 |
except CodeImportAlreadyRunning: |
6233.6.2
by Michael Hudson
tests and stuff |
1411 |
self.request.response.addNotification( |
1412 |
"The import is already running.") |
|
10454.12.4
by James Westby
Use the new method from the existing browser code. |
1413 |
except CodeImportAlreadyRequested, e: |
1414 |
user = e.requesting_user |
|
6233.6.2
by Michael Hudson
tests and stuff |
1415 |
adapter = queryAdapter(user, IPathAdapter, 'fmt') |
1416 |
self.request.response.addNotification( |
|
6233.6.5
by Michael Hudson
Much better tests. Shame they don't work. |
1417 |
structured("The import has already been requested by %s." % |
7119.1.5
by Guilherme Salgado
Fix a couple tests |
1418 |
adapter.link(None))) |
6233.6.1
by Michael Hudson
stuff |
1419 |
|
1420 |
@property
|
|
1421 |
def prefix(self): |
|
1422 |
return "request%s" % self.context.id |
|
1423 |
||
1424 |
@property
|
|
1425 |
def action_url(self): |
|
1426 |
return "%s/@@+request-import" % canonical_url(self.context) |
|
8137.17.24
by Barry Warsaw
thread merge |
1427 |
|
1428 |
||
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
1429 |
class TryImportAgainView(LaunchpadFormView): |
8377.9.4
by Michael Hudson
minor progress |
1430 |
"""The view to provide an 'Try again' button on the branch index page.
|
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
1431 |
|
1432 |
This only appears on the page of a branch with an associated code import
|
|
8377.9.4
by Michael Hudson
minor progress |
1433 |
that is marked as failing.
|
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
1434 |
"""
|
1435 |
||
1436 |
schema = IBranch |
|
1437 |
field_names = [] |
|
1438 |
||
1439 |
@property
|
|
1440 |
def next_url(self): |
|
1441 |
return canonical_url(self.context) |
|
1442 |
||
1443 |
@action('Try Again', name='tryagain') |
|
1444 |
def request_try_again(self, action, data): |
|
8377.9.17
by Michael Hudson
review comments |
1445 |
if (self.context.code_import.review_status != |
1446 |
CodeImportReviewStatus.FAILING): |
|
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
1447 |
self.request.response.addNotification( |
8377.9.4
by Michael Hudson
minor progress |
1448 |
"The import is now %s." |
1449 |
% self.context.code_import.review_status.name) |
|
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
1450 |
else: |
8377.9.14
by Michael Hudson
test passes now |
1451 |
self.context.code_import.tryFailingImportAgain(self.user) |
8377.9.2
by Michael Hudson
allow retrying FAILING builds |
1452 |
self.request.response.addNotification( |
1453 |
"Import will be tried again as soon as possible.") |
|
1454 |
||
1455 |
@property
|
|
1456 |
def prefix(self): |
|
8377.9.22
by Michael Hudson
ui review part 2 |
1457 |
return "tryagain" |