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).
|
4236.3.1
by Michael Hudson
create a page at code.launchpad.dev/code-imports |
3 |
|
4236.3.54
by Michael Hudson
respond to review comments |
4 |
"""Browser views for CodeImports."""
|
4236.3.1
by Michael Hudson
create a page at code.launchpad.dev/code-imports |
5 |
|
6 |
__metaclass__ = type |
|
7 |
||
4236.3.11
by Michael Hudson
add a very simple page view for ICodeImport |
8 |
__all__ = [ |
5895.4.1
by Tim Penhey
Initial methods and email notification. |
9 |
'CodeImportEditView', |
5763.6.1
by Tim Penhey
Machine view |
10 |
'CodeImportMachineView', |
5763.4.12
by Tim Penhey
New pagetest to show creation. |
11 |
'CodeImportNewView', |
9209.4.5
by Guilherme Salgado
Update all existing breadcrumb adapters to use Breadcrumb rather than BreadcrumbBuilder. Also rename them all |
12 |
'CodeImportSetBreadcrumb', |
6233.5.2
by Tim Penhey
Get the page working. |
13 |
'CodeImportSetNavigation', |
4236.3.11
by Michael Hudson
add a very simple page view for ICodeImport |
14 |
'CodeImportSetView', |
4236.3.46
by Michael Hudson
improvements to tests, and removal of a strange hack |
15 |
'CodeImportView', |
4236.3.11
by Michael Hudson
add a very simple page view for ICodeImport |
16 |
]
|
4236.3.1
by Michael Hudson
create a page at code.launchpad.dev/code-imports |
17 |
|
4236.3.4
by Michael Hudson
beef up test to create a code import, and check that it affects the code import |
18 |
|
5763.4.2
by Tim Penhey
Initial work. |
19 |
from BeautifulSoup import BeautifulSoup |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
20 |
from lazr.restful.interface import ( |
21 |
copy_field, |
|
22 |
use_template, |
|
23 |
)
|
|
5763.4.2
by Tim Penhey
Initial work. |
24 |
from zope.app.form import CustomWidgetFactory |
25 |
from zope.app.form.interfaces import IInputWidget |
|
26 |
from zope.app.form.utility import setUpWidget |
|
27 |
from zope.component import getUtility |
|
28 |
from zope.formlib import form |
|
6650.1.2
by Michael Hudson
less hacking, no more working |
29 |
from zope.interface import Interface |
10454.5.2
by James Westby
Import Choice. |
30 |
from zope.schema import Choice |
5763.4.2
by Tim Penhey
Initial work. |
31 |
|
4236.3.48
by Michael Hudson
after what felt like heroic Z3 hacking, a fairly small amount of code to allow |
32 |
from canonical.launchpad import _ |
8138.1.2
by Jonathan Lange
Run migrater over lp.code. Many tests broken and imports failing. |
33 |
from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
34 |
from canonical.launchpad.webapp import ( |
35 |
canonical_url, |
|
36 |
LaunchpadView, |
|
37 |
Navigation, |
|
38 |
stepto, |
|
39 |
)
|
|
40 |
from canonical.launchpad.webapp.batching import BatchNavigator |
|
41 |
from canonical.launchpad.webapp.breadcrumb import Breadcrumb |
|
42 |
from canonical.launchpad.webapp.menu import structured |
|
12293.1.10
by Curtis Hovey
Formatted imports. |
43 |
from lp.app.browser.launchpadform import ( |
44 |
action, |
|
45 |
custom_widget, |
|
46 |
LaunchpadFormView, |
|
47 |
)
|
|
48 |
from lp.app.errors import NotFoundError |
|
12293.1.9
by Curtis Hovey
Deglobbed widget imports. |
49 |
from lp.app.widgets.itemswidgets import ( |
50 |
LaunchpadDropdownWidget, |
|
51 |
LaunchpadRadioWidget, |
|
52 |
)
|
|
12293.1.3
by Curtis Hovey
Migrated all the canonical.widgets to app.widgets. |
53 |
from lp.app.widgets.textwidgets import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
54 |
StrippedTextWidget, |
55 |
URIWidget, |
|
56 |
)
|
|
8555.2.5
by Tim Penhey
Move the branch subscription enums. |
57 |
from lp.code.enums import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
58 |
BranchSubscriptionDiffSize, |
59 |
BranchSubscriptionNotificationLevel, |
|
60 |
CodeImportReviewStatus, |
|
61 |
CodeReviewNotificationLevel, |
|
62 |
RevisionControlSystems, |
|
63 |
)
|
|
11270.2.5
by Tim Penhey
Last import change. |
64 |
from lp.code.errors import BranchExists |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
65 |
from lp.code.interfaces.branch import ( |
66 |
IBranch, |
|
67 |
user_has_special_branch_access, |
|
68 |
)
|
|
8615.1.1
by Tim Penhey
Fix the oops when trying to import a branch for a private project. |
69 |
from lp.code.interfaces.branchnamespace import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
70 |
get_branch_namespace, |
71 |
IBranchNamespacePolicy, |
|
72 |
)
|
|
73 |
from lp.code.interfaces.branchtarget import IBranchTarget |
|
8138.1.2
by Jonathan Lange
Run migrater over lp.code. Many tests broken and imports failing. |
74 |
from lp.code.interfaces.codeimport import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
75 |
ICodeImport, |
76 |
ICodeImportSet, |
|
77 |
)
|
|
8138.1.2
by Jonathan Lange
Run migrater over lp.code. Many tests broken and imports failing. |
78 |
from lp.code.interfaces.codeimportmachine import ICodeImportMachineSet |
10155.4.1
by Tim Penhey
Provide the new code import view for products directly so the user doesn't need to specify it. |
79 |
from lp.registry.interfaces.product import IProduct |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
80 |
from lp.services.fields import URIField |
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
81 |
from lp.services.propertycache import cachedproperty |
4236.3.49
by Michael Hudson
whitespace, ensure that the code imports are listed in id order, test cleanups |
82 |
|
5763.4.20
by Tim Penhey
Last updates from review. |
83 |
|
6233.5.2
by Tim Penhey
Get the page working. |
84 |
class CodeImportSetNavigation(Navigation): |
85 |
"""Navigation methods for IBuilder."""
|
|
86 |
usedfor = ICodeImportSet |
|
87 |
||
88 |
@stepto('+machines') |
|
89 |
def bugs(self): |
|
90 |
return getUtility(ICodeImportMachineSet) |
|
91 |
||
6767.6.17
by Maris Fogels
Migrated the CodeImport breadcrumb to the new system interface. |
92 |
|
9209.4.5
by Guilherme Salgado
Update all existing breadcrumb adapters to use Breadcrumb rather than BreadcrumbBuilder. Also rename them all |
93 |
class CodeImportSetBreadcrumb(Breadcrumb): |
6767.6.26
by Maris Fogels
Rework based on reviewer feedback. |
94 |
"""Builds a breadcrumb for an `ICodeImportSet`."""
|
6767.6.17
by Maris Fogels
Migrated the CodeImport breadcrumb to the new system interface. |
95 |
text = u'Code Import System' |
6233.5.2
by Tim Penhey
Get the page working. |
96 |
|
97 |
||
10427.14.1
by Michael Hudson
browser code changes |
98 |
class DropdownWidgetWithAny(LaunchpadDropdownWidget): |
4236.3.54
by Michael Hudson
respond to review comments |
99 |
"""A <select> widget with a more appropriate 'no value' message.
|
100 |
||
101 |
By default `LaunchpadDropdownWidget` displays 'no value' when the
|
|
102 |
associated value is None or not supplied, which is not what we want on
|
|
103 |
this page.
|
|
104 |
"""
|
|
4236.3.51
by Michael Hudson
consistency-with-other-code changes |
105 |
_messageNoValue = _('Any') |
106 |
||
107 |
||
4236.3.1
by Michael Hudson
create a page at code.launchpad.dev/code-imports |
108 |
class CodeImportSetView(LaunchpadView): |
4236.3.54
by Michael Hudson
respond to review comments |
109 |
"""The default view for `ICodeImportSet`.
|
110 |
||
111 |
We present the CodeImportSet as a list of all imports.
|
|
112 |
"""
|
|
113 |
||
4236.3.29
by Michael Hudson
make the codeimportsetview batched |
114 |
def initialize(self): |
4236.3.54
by Michael Hudson
respond to review comments |
115 |
"""See `LaunchpadView.initialize`."""
|
10427.14.6
by Michael Hudson
address review comments |
116 |
review_status_field = copy_field( |
117 |
ICodeImport['review_status'], required=False, default=None) |
|
118 |
self.review_status_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
|
119 |
setUpWidget(self, 'review_status', review_status_field, IInputWidget) |
|
4236.3.48
by Michael Hudson
after what felt like heroic Z3 hacking, a fairly small amount of code to allow |
120 |
|
10427.14.6
by Michael Hudson
address review comments |
121 |
rcs_type_field = copy_field( |
122 |
ICodeImport['rcs_type'], required=False, default=None) |
|
123 |
self.rcs_type_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
|
124 |
setUpWidget(self, 'rcs_type', rcs_type_field, IInputWidget) |
|
10427.14.1
by Michael Hudson
browser code changes |
125 |
|
4236.3.56
by Michael Hudson
preparations for merging |
126 |
# status should be None if either (a) there were no query arguments
|
127 |
# supplied, i.e. the user browsed directly to this page (this is when
|
|
128 |
# hasValidInput returns False) or (b) the user chose 'Any' in the
|
|
129 |
# status widget (this is when hasValidInput returns True but
|
|
130 |
# getInputValue returns None).
|
|
10427.14.6
by Michael Hudson
address review comments |
131 |
review_status = None |
132 |
if self.review_status_widget.hasValidInput(): |
|
133 |
review_status = self.review_status_widget.getInputValue() |
|
10427.14.1
by Michael Hudson
browser code changes |
134 |
# Similar for 'type'
|
135 |
rcs_type = None |
|
10427.14.6
by Michael Hudson
address review comments |
136 |
if self.rcs_type_widget.hasValidInput(): |
137 |
rcs_type = self.rcs_type_widget.getInputValue() |
|
4236.3.48
by Michael Hudson
after what felt like heroic Z3 hacking, a fairly small amount of code to allow |
138 |
|
10427.14.6
by Michael Hudson
address review comments |
139 |
imports = self.context.search( |
140 |
review_status=review_status, rcs_type=rcs_type) |
|
4236.3.48
by Michael Hudson
after what felt like heroic Z3 hacking, a fairly small amount of code to allow |
141 |
|
4236.3.53
by Michael Hudson
so it turns out that the default batch size is 5 (ridiculously small) only for |
142 |
self.batchnav = BatchNavigator(imports, self.request) |
4236.3.46
by Michael Hudson
improvements to tests, and removal of a strange hack |
143 |
|
4236.3.49
by Michael Hudson
whitespace, ensure that the code imports are listed in id order, test cleanups |
144 |
|
4236.3.46
by Michael Hudson
improvements to tests, and removal of a strange hack |
145 |
class CodeImportView(LaunchpadView): |
4236.3.54
by Michael Hudson
respond to review comments |
146 |
"""The default view for `ICodeImport`.
|
147 |
||
148 |
We present the CodeImport as a simple page listing all the details of the
|
|
10454.4.9
by James Westby
Use BranchTarget in a couple of places when requesting an import. |
149 |
import such as target and branch, who requested the import,
|
4236.3.54
by Michael Hudson
respond to review comments |
150 |
and so on.
|
151 |
"""
|
|
152 |
||
4236.3.46
by Michael Hudson
improvements to tests, and removal of a strange hack |
153 |
def initialize(self): |
4236.3.54
by Michael Hudson
respond to review comments |
154 |
"""See `LaunchpadView.initialize`."""
|
10454.4.15
by James Westby
Fix another instance of accessing code_import.target, rather than branch.target. |
155 |
self.title = "Code Import for %s" % (self.context.branch.target.name,) |
5763.4.1
by Tim Penhey
Initial work |
156 |
|
5763.4.2
by Tim Penhey
Initial work. |
157 |
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
158 |
class CodeImportBaseView(LaunchpadFormView): |
159 |
"""A base view for both new and edit code import views."""
|
|
160 |
||
161 |
schema = ICodeImport |
|
162 |
||
163 |
custom_widget('cvs_root', StrippedTextWidget, displayWidth=50) |
|
164 |
custom_widget('cvs_module', StrippedTextWidget, displayWidth=20) |
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
165 |
custom_widget('url', URIWidget, displayWidth=50) |
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
166 |
|
167 |
@cachedproperty
|
|
168 |
def _super_user(self): |
|
169 |
"""Is the user an admin or member of vcs-imports?"""
|
|
170 |
celebs = getUtility(ILaunchpadCelebrities) |
|
171 |
return (self.user.inTeam(celebs.admin) or |
|
172 |
self.user.inTeam(celebs.vcs_imports)) |
|
173 |
||
174 |
def showOptionalMarker(self, field_name): |
|
175 |
"""Don't show the optional marker for rcs locations."""
|
|
5763.5.11
by Tim Penhey
OMG, the test passes, quick, commit! |
176 |
# No field in either the new or edit view needs an optional marker,
|
177 |
# so we can be simple here.
|
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
178 |
return False |
179 |
||
180 |
def setSecondaryFieldError(self, field, error): |
|
181 |
"""Set the field error only if there isn't an error already."""
|
|
182 |
if self.getFieldError(field): |
|
183 |
# Leave this one as it is often required or a validator error.
|
|
184 |
pass
|
|
185 |
else: |
|
186 |
self.setFieldError(field, error) |
|
187 |
||
5763.5.9
by Tim Penhey
Fix validation. |
188 |
def _validateCVS(self, cvs_root, cvs_module, existing_import=None): |
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
189 |
"""If the user has specified cvs, then we need to make
|
190 |
sure that there isn't already an import with those values."""
|
|
191 |
if cvs_root is None: |
|
192 |
self.setSecondaryFieldError( |
|
193 |
'cvs_root', 'Enter a CVS root.') |
|
194 |
if cvs_module is None: |
|
195 |
self.setSecondaryFieldError( |
|
196 |
'cvs_module', 'Enter a CVS module.') |
|
197 |
||
198 |
if cvs_root and cvs_module: |
|
199 |
code_import = getUtility(ICodeImportSet).getByCVSDetails( |
|
200 |
cvs_root, cvs_module) |
|
5763.5.9
by Tim Penhey
Fix validation. |
201 |
if (code_import is not None and |
202 |
code_import != existing_import): |
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
203 |
self.addError(structured(""" |
204 |
Those CVS details are already specified for
|
|
205 |
the imported branch <a href="%s">%s</a>.""", |
|
206 |
canonical_url(code_import.branch), |
|
207 |
code_import.branch.unique_name)) |
|
208 |
||
10129.6.9
by Tim Penhey
Yet more test fixes. |
209 |
def _validateURL(self, url, existing_import=None, field_name='url'): |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
210 |
"""If the user has specified a url, we need to make sure that there
|
211 |
isn't already an import with that url."""
|
|
212 |
if url is None: |
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
213 |
self.setSecondaryFieldError( |
10129.6.9
by Tim Penhey
Yet more test fixes. |
214 |
field_name, 'Enter the URL of a foreign VCS branch.') |
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
215 |
else: |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
216 |
code_import = getUtility(ICodeImportSet).getByURL(url) |
5763.5.9
by Tim Penhey
Fix validation. |
217 |
if (code_import is not None and |
218 |
code_import != existing_import): |
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
219 |
self.setFieldError( |
10129.6.9
by Tim Penhey
Yet more test fixes. |
220 |
field_name, |
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
221 |
structured(""" |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
222 |
This foreign branch URL is already specified for
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
223 |
the imported branch <a href="%s">%s</a>.""", |
224 |
canonical_url(code_import.branch), |
|
225 |
code_import.branch.unique_name)) |
|
226 |
||
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
227 |
|
228 |
||
229 |
class NewCodeImportForm(Interface): |
|
230 |
"""The fields presented on the form for editing a code import."""
|
|
231 |
||
10762.1.1
by Tim Penhey
Allow the users to specify the owner for a new import. |
232 |
use_template(IBranch, ['owner']) |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
233 |
use_template( |
234 |
ICodeImport, |
|
10454.4.3
by James Westby
Hack product out of NewCodeImportForm. |
235 |
['rcs_type', 'cvs_root', 'cvs_module']) |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
236 |
|
237 |
svn_branch_url = URIField( |
|
238 |
title=_("Branch URL"), required=False, |
|
239 |
description=_( |
|
10635.5.4
by Michael Hudson
thumper approved wording |
240 |
"The URL of a Subversion branch, starting with svn:// or "
|
241 |
"http(s)://. You can include a username and password as part "
|
|
242 |
"of the url, but this will be displayed on the branch page."), |
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
243 |
allowed_schemes=["http", "https", "svn"], |
10635.5.2
by Michael Hudson
starting steps |
244 |
allow_userinfo=True, |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
245 |
allow_port=True, |
246 |
allow_query=False, |
|
247 |
allow_fragment=False, |
|
248 |
trailing_slash=False) |
|
249 |
||
250 |
git_repo_url = URIField( |
|
251 |
title=_("Repo URL"), required=False, |
|
252 |
description=_( |
|
10129.6.21
by Tim Penhey
Correct the wording on the git and hg import strings. |
253 |
"The URL of the git repository. The HEAD branch will be "
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
254 |
"imported."), |
10427.9.1
by Michael Hudson
allow http and https for git imports |
255 |
allowed_schemes=["git", "http", "https"], |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
256 |
allow_userinfo=False, # Only anonymous access is supported. |
257 |
allow_port=True, |
|
10129.7.1
by Tim Penhey
Minor tweaks mentioned in review. |
258 |
allow_query=False, |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
259 |
allow_fragment=False, |
260 |
trailing_slash=False) |
|
261 |
||
10129.6.13
by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts. |
262 |
hg_repo_url = URIField( |
263 |
title=_("Repo URL"), required=False, |
|
10129.6.21
by Tim Penhey
Correct the wording on the git and hg import strings. |
264 |
description=_( |
265 |
"The URL of the Mercurial repository. The tip branch will be "
|
|
266 |
"imported."), |
|
10129.6.13
by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts. |
267 |
allowed_schemes=["http", "https"], |
268 |
allow_userinfo=False, # Only anonymous access is supported. |
|
269 |
allow_port=True, |
|
270 |
allow_query=False, # Query makes no sense in Mercurial |
|
271 |
allow_fragment=False, # Fragment makes no sense in Mercurial |
|
272 |
trailing_slash=False) # See http://launchpad.net/bugs/56357. |
|
273 |
||
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
274 |
branch_name = copy_field( |
275 |
IBranch['name'], |
|
10129.6.9
by Tim Penhey
Yet more test fixes. |
276 |
__name__='branch_name', |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
277 |
title=_('Branch Name'), |
278 |
description=_( |
|
279 |
"This will be used in the branch URL to identify the "
|
|
280 |
"imported branch. Examples: main, trunk."), |
|
281 |
)
|
|
9905.7.6
by Jelmer Vernooij
More tests. |
282 |
|
10454.4.10
by James Westby
Define product on the new codeimport form again. |
283 |
product = Choice( |
10454.4.14
by James Westby
Products are called projects in the UI. |
284 |
title=_('Project'), |
285 |
description=_("The Project to associate the code import with."), |
|
10454.4.10
by James Westby
Define product on the new codeimport form again. |
286 |
vocabulary="Product", |
287 |
)
|
|
288 |
||
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
289 |
|
290 |
class CodeImportNewView(CodeImportBaseView): |
|
5763.4.1
by Tim Penhey
Initial work |
291 |
"""The view to request a new code import."""
|
292 |
||
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
293 |
schema = NewCodeImportForm |
5763.4.2
by Tim Penhey
Initial work. |
294 |
for_input = True |
5763.4.1
by Tim Penhey
Initial work |
295 |
|
5763.4.2
by Tim Penhey
Initial work. |
296 |
custom_widget('rcs_type', LaunchpadRadioWidget) |
297 |
||
10762.1.1
by Tim Penhey
Allow the users to specify the owner for a new import. |
298 |
@property
|
299 |
def initial_values(self): |
|
300 |
return { |
|
301 |
'owner': self.user, |
|
302 |
'rcs_type': RevisionControlSystems.BZR_SVN, |
|
303 |
'branch_name': 'trunk', |
|
304 |
}
|
|
5763.4.2
by Tim Penhey
Initial work. |
305 |
|
5763.4.16
by Tim Penhey
Updates following review. |
306 |
@property
|
10155.4.1
by Tim Penhey
Provide the new code import view for products directly so the user doesn't need to specify it. |
307 |
def context_is_product(self): |
308 |
return IProduct.providedBy(self.context) |
|
309 |
||
310 |
@property
|
|
311 |
def label(self): |
|
312 |
if self.context_is_product: |
|
313 |
return 'Request a code import for %s' % self.context.displayname |
|
314 |
else: |
|
315 |
return 'Request a code import' |
|
316 |
||
317 |
@property
|
|
5763.4.16
by Tim Penhey
Updates following review. |
318 |
def cancel_url(self): |
319 |
"""Cancel should take the user back to the root site."""
|
|
320 |
return '/' |
|
321 |
||
5763.4.2
by Tim Penhey
Initial work. |
322 |
def setUpFields(self): |
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
323 |
CodeImportBaseView.setUpFields(self) |
10155.4.1
by Tim Penhey
Provide the new code import view for products directly so the user doesn't need to specify it. |
324 |
if self.context_is_product: |
325 |
self.form_fields = self.form_fields.omit('product') |
|
326 |
||
10762.1.1
by Tim Penhey
Allow the users to specify the owner for a new import. |
327 |
# If the user can administer branches, then they should be able to
|
328 |
# assign the ownership of the branch to any valid person or team.
|
|
329 |
if user_has_special_branch_access(self.user): |
|
330 |
owner_field = self.schema['owner'] |
|
331 |
any_owner_choice = Choice( |
|
332 |
__name__='owner', title=owner_field.title, |
|
333 |
description = _("As an administrator you are able to reassign" |
|
334 |
" this branch to any person or team."), |
|
335 |
required=True, vocabulary='ValidPersonOrTeam') |
|
336 |
any_owner_field = form.Fields( |
|
337 |
any_owner_choice, render_context=self.render_context) |
|
338 |
# Replace the normal owner field with a more permissive vocab.
|
|
339 |
self.form_fields = self.form_fields.omit('owner') |
|
340 |
self.form_fields = any_owner_field + self.form_fields |
|
341 |
||
5763.4.2
by Tim Penhey
Initial work. |
342 |
def setUpWidgets(self): |
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
343 |
CodeImportBaseView.setUpWidgets(self) |
5763.4.2
by Tim Penhey
Initial work. |
344 |
|
5763.4.16
by Tim Penhey
Updates following review. |
345 |
# Extract the radio buttons from the rcs_type widget, so we can
|
5763.4.2
by Tim Penhey
Initial work. |
346 |
# display them separately in the form.
|
347 |
soup = BeautifulSoup(self.widgets['rcs_type']()) |
|
7675.85.2
by Jonathan Lange
Undo revision generated by step 2 of process. |
348 |
fields = soup.findAll('input') |
9905.7.6
by Jelmer Vernooij
More tests. |
349 |
[cvs_button, svn_button, git_button, hg_button, empty_marker] = [ |
7675.85.2
by Jonathan Lange
Undo revision generated by step 2 of process. |
350 |
field for field in fields |
9905.7.13
by Jelmer Vernooij
Merge devel. |
351 |
if field.get('value') in ['CVS', 'BZR_SVN', 'GIT', 'HG', '1']] |
5763.4.2
by Tim Penhey
Initial work. |
352 |
cvs_button['onclick'] = 'updateWidgets()' |
353 |
svn_button['onclick'] = 'updateWidgets()' |
|
8245.3.2
by Paul Hummer
Fixed the javascript for new imports |
354 |
git_button['onclick'] = 'updateWidgets()' |
9905.7.6
by Jelmer Vernooij
More tests. |
355 |
hg_button['onclick'] = 'updateWidgets()' |
5763.4.16
by Tim Penhey
Updates following review. |
356 |
# The following attributes are used only in the page template.
|
5763.4.2
by Tim Penhey
Initial work. |
357 |
self.rcs_type_cvs = str(cvs_button) |
358 |
self.rcs_type_svn = str(svn_button) |
|
8245.3.1
by Paul Hummer
Added git fields to the new import page |
359 |
self.rcs_type_git = str(git_button) |
9905.7.6
by Jelmer Vernooij
More tests. |
360 |
self.rcs_type_hg = str(hg_button) |
5763.4.2
by Tim Penhey
Initial work. |
361 |
self.rcs_type_emptymarker = str(empty_marker) |
362 |
||
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
363 |
def _getImportLocation(self, data): |
364 |
"""Return the import location based on type."""
|
|
365 |
rcs_type = data['rcs_type'] |
|
366 |
if rcs_type == RevisionControlSystems.CVS: |
|
367 |
return data.get('cvs_root'), data.get('cvs_module'), None |
|
368 |
elif rcs_type == RevisionControlSystems.BZR_SVN: |
|
369 |
return None, None, data.get('svn_branch_url') |
|
370 |
elif rcs_type == RevisionControlSystems.GIT: |
|
371 |
return None, None, data.get('git_repo_url') |
|
10129.6.13
by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts. |
372 |
elif rcs_type == RevisionControlSystems.HG: |
373 |
return None, None, data.get('hg_repo_url') |
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
374 |
else: |
375 |
raise AssertionError( |
|
376 |
'Unexpected revision control type %r.' % rcs_type) |
|
377 |
||
5763.4.16
by Tim Penhey
Updates following review. |
378 |
def _create_import(self, data, status): |
379 |
"""Create the code import."""
|
|
10155.4.1
by Tim Penhey
Provide the new code import view for products directly so the user doesn't need to specify it. |
380 |
product = self.getProduct(data) |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
381 |
cvs_root, cvs_module, url = self._getImportLocation(data) |
5763.4.16
by Tim Penhey
Updates following review. |
382 |
return getUtility(ICodeImportSet).new( |
5763.4.2
by Tim Penhey
Initial work. |
383 |
registrant=self.user, |
10762.1.1
by Tim Penhey
Allow the users to specify the owner for a new import. |
384 |
owner=data['owner'], |
10454.4.16
by James Westby
Make ICodeImportSet.new act on IBranchTargets. |
385 |
target=IBranchTarget(product), |
5763.4.17
by Tim Penhey
Merge RF. |
386 |
branch_name=data['branch_name'], |
5763.4.2
by Tim Penhey
Initial work. |
387 |
rcs_type=data['rcs_type'], |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
388 |
url=url, |
389 |
cvs_root=cvs_root, |
|
390 |
cvs_module=cvs_module, |
|
391 |
review_status=status) |
|
5763.4.16
by Tim Penhey
Updates following review. |
392 |
|
7362.3.3
by Jonathan Lange
Use the richer errors from BranchSet.new to remove look-before-you-leap |
393 |
def _setBranchExists(self, existing_branch): |
394 |
"""Set a field error indicating that the branch already exists."""
|
|
395 |
self.setFieldError( |
|
396 |
'branch_name', |
|
397 |
structured(""" |
|
398 |
There is already an existing import for
|
|
399 |
<a href="%(product_url)s">%(product_name)s</a> |
|
400 |
with the name of
|
|
401 |
<a href="%(branch_url)s">%(branch_name)s</a>.""", |
|
10454.4.9
by James Westby
Use BranchTarget in a couple of places when requesting an import. |
402 |
product_url=canonical_url(existing_branch.target), |
403 |
product_name=existing_branch.target.name, |
|
7362.3.3
by Jonathan Lange
Use the richer errors from BranchSet.new to remove look-before-you-leap |
404 |
branch_url=canonical_url(existing_branch), |
405 |
branch_name=existing_branch.name)) |
|
406 |
||
5763.4.20
by Tim Penhey
Last updates from review. |
407 |
@action(_('Request Import'), name='request_import') |
408 |
def request_import_action(self, action, data): |
|
5763.4.16
by Tim Penhey
Updates following review. |
409 |
"""Create the code_import, and subscribe the user to the branch."""
|
7362.3.3
by Jonathan Lange
Use the richer errors from BranchSet.new to remove look-before-you-leap |
410 |
try: |
411 |
code_import = self._create_import(data, None) |
|
412 |
except BranchExists, e: |
|
413 |
self._setBranchExists(e.existing_branch) |
|
414 |
return
|
|
5763.4.16
by Tim Penhey
Updates following review. |
415 |
|
416 |
# Subscribe the user.
|
|
5763.4.8
by Tim Penhey
Subscribe the user to the newly created imported branch. |
417 |
code_import.branch.subscribe( |
418 |
self.user, |
|
419 |
BranchSubscriptionNotificationLevel.FULL, |
|
5608.5.40
by Aaron Bentley
Fix failing tests |
420 |
BranchSubscriptionDiffSize.NODIFF, |
7675.708.3
by Tim Penhey
Add subscribed_by and unsubscribed_by to the subscribe and unsubscribe branch methods. |
421 |
CodeReviewNotificationLevel.NOEMAIL, |
422 |
self.user) |
|
5763.4.8
by Tim Penhey
Subscribe the user to the newly created imported branch. |
423 |
|
5763.4.4
by Tim Penhey
Make the CodeImport stuff a little more permissive. |
424 |
self.next_url = canonical_url(code_import.branch) |
5763.4.1
by Tim Penhey
Initial work |
425 |
|
5763.4.16
by Tim Penhey
Updates following review. |
426 |
self.request.response.addNotification(""" |
5763.4.20
by Tim Penhey
Last updates from review. |
427 |
New code import created. The code import operators
|
5763.4.16
by Tim Penhey
Updates following review. |
428 |
have been notified and the request will be reviewed shortly.""") |
429 |
||
430 |
def _showApprove(self, ignored): |
|
431 |
"""Is the user an admin or member of vcs-imports?"""
|
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
432 |
return self._super_user |
5763.4.16
by Tim Penhey
Updates following review. |
433 |
|
434 |
@action(_('Create Approved Import'), name='approve', |
|
435 |
condition=_showApprove) |
|
436 |
def approve_action(self, action, data): |
|
437 |
"""Create the code_import, and subscribe the user to the branch."""
|
|
7362.3.3
by Jonathan Lange
Use the richer errors from BranchSet.new to remove look-before-you-leap |
438 |
try: |
439 |
code_import = self._create_import( |
|
440 |
data, CodeImportReviewStatus.REVIEWED) |
|
441 |
except BranchExists, e: |
|
442 |
self._setBranchExists(e.existing_branch) |
|
443 |
return
|
|
5763.4.16
by Tim Penhey
Updates following review. |
444 |
|
445 |
# Don't subscribe the requester as they are an import operator.
|
|
446 |
self.next_url = canonical_url(code_import.branch) |
|
447 |
||
448 |
self.request.response.addNotification( |
|
449 |
"New reviewed code import created.") |
|
450 |
||
10155.4.1
by Tim Penhey
Provide the new code import view for products directly so the user doesn't need to specify it. |
451 |
def getProduct(self, data): |
452 |
"""If the context is a product, use that, otherwise get from data."""
|
|
453 |
if self.context_is_product: |
|
454 |
return self.context |
|
455 |
else: |
|
456 |
return data.get('product') |
|
457 |
||
5763.4.1
by Tim Penhey
Initial work |
458 |
def validate(self, data): |
5763.4.16
by Tim Penhey
Updates following review. |
459 |
"""See `LaunchpadFormView`."""
|
8615.1.1
by Tim Penhey
Fix the oops when trying to import a branch for a private project. |
460 |
# Make sure that the user is able to create branches for the specified
|
461 |
# namespace.
|
|
10155.4.1
by Tim Penhey
Provide the new code import view for products directly so the user doesn't need to specify it. |
462 |
product = self.getProduct(data) |
10762.1.1
by Tim Penhey
Allow the users to specify the owner for a new import. |
463 |
# 'owner' in data may be None if it failed validation.
|
464 |
owner = data.get('owner') |
|
465 |
if product is not None and owner is not None: |
|
466 |
namespace = get_branch_namespace(owner, product) |
|
8615.1.1
by Tim Penhey
Fix the oops when trying to import a branch for a private project. |
467 |
policy = IBranchNamespacePolicy(namespace) |
10762.1.1
by Tim Penhey
Allow the users to specify the owner for a new import. |
468 |
if not policy.canCreateBranches(self.user): |
8615.1.1
by Tim Penhey
Fix the oops when trying to import a branch for a private project. |
469 |
self.setFieldError( |
470 |
'product', |
|
471 |
"You are not allowed to register imports for %s." |
|
472 |
% product.displayname) |
|
473 |
||
5763.4.2
by Tim Penhey
Initial work. |
474 |
rcs_type = data['rcs_type'] |
475 |
# Make sure fields for unselected revision control systems
|
|
476 |
# are blanked out:
|
|
477 |
if rcs_type == RevisionControlSystems.CVS: |
|
478 |
self._validateCVS(data.get('cvs_root'), data.get('cvs_module')) |
|
9946.1.13
by Michael Hudson
more tests, create bzr-svn imports by default |
479 |
elif rcs_type == RevisionControlSystems.BZR_SVN: |
10129.6.9
by Tim Penhey
Yet more test fixes. |
480 |
self._validateURL( |
481 |
data.get('svn_branch_url'), field_name='svn_branch_url') |
|
8245.3.3
by Paul Hummer
Completed full registration of git import creation (minus the database constraint issue. |
482 |
elif rcs_type == RevisionControlSystems.GIT: |
10129.6.9
by Tim Penhey
Yet more test fixes. |
483 |
self._validateURL( |
484 |
data.get('git_repo_url'), field_name='git_repo_url') |
|
9905.7.6
by Jelmer Vernooij
More tests. |
485 |
elif rcs_type == RevisionControlSystems.HG: |
10129.6.13
by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts. |
486 |
self._validateURL( |
487 |
data.get('hg_repo_url'), field_name='hg_repo_url') |
|
5763.4.2
by Tim Penhey
Initial work. |
488 |
else: |
9946.1.13
by Michael Hudson
more tests, create bzr-svn imports by default |
489 |
raise AssertionError( |
490 |
'Unexpected revision control type %r.' % rcs_type) |
|
5763.4.12
by Tim Penhey
New pagetest to show creation. |
491 |
|
5895.4.3
by Tim Penhey
Added edit view. |
492 |
|
6650.1.2
by Michael Hudson
less hacking, no more working |
493 |
class EditCodeImportForm(Interface): |
494 |
"""The fields presented on the form for editing a code import."""
|
|
495 |
||
10454.3.4
by James Westby
Fix other tests from fallout. |
496 |
url = copy_field(ICodeImport['url'], readonly=False) |
497 |
cvs_root = copy_field(ICodeImport['cvs_root'], readonly=False) |
|
498 |
cvs_module = copy_field(ICodeImport['cvs_module'], readonly=False) |
|
6650.1.1
by Michael Hudson
some hacking |
499 |
whiteboard = copy_field(IBranch['whiteboard']) |
500 |
||
501 |
||
6650.1.13
by Michael Hudson
some kind of progress |
502 |
def _makeEditAction(label, status, text): |
503 |
"""Make an Action to call a particular code import method.
|
|
504 |
||
505 |
:param label: The label for the action, which will end up as the
|
|
506 |
button title.
|
|
507 |
:param status: If the code import has this as its review_status, don't
|
|
508 |
show the button (always show the button if it is None).
|
|
509 |
:param text: The text to go after 'The code import has been' in a
|
|
510 |
notifcation, if a change was made.
|
|
511 |
"""
|
|
512 |
if status is not None: |
|
513 |
def condition(self, ignored): |
|
514 |
return self._showButtonForStatus(status) |
|
515 |
else: |
|
516 |
condition = None |
|
517 |
def success(self, action, data): |
|
518 |
"""Make the requested status change."""
|
|
519 |
if status is not None: |
|
520 |
data['review_status'] = status |
|
521 |
event = self.code_import.updateFromData(data, self.user) |
|
522 |
if event is not None: |
|
523 |
self.request.response.addNotification( |
|
524 |
'The code import has been ' + text + '.') |
|
525 |
else: |
|
526 |
self.request.response.addNotification('No changes made.') |
|
527 |
name = label.lower().replace(' ', '_') |
|
528 |
return form.Action( |
|
529 |
label, name=name, success=success, condition=condition) |
|
530 |
||
531 |
||
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
532 |
class CodeImportEditView(CodeImportBaseView): |
5895.4.3
by Tim Penhey
Added edit view. |
533 |
"""View for editing code imports.
|
534 |
||
6650.1.2
by Michael Hudson
less hacking, no more working |
535 |
This view is registered against the branch, but mostly edits the code
|
536 |
import for that branch -- the exception being that it also allows the
|
|
537 |
editing of the branch whiteboard. If the branch has no associated code
|
|
538 |
import, then the result is a 404. If the branch does have a code import,
|
|
539 |
then the adapters property allows the form internals to do the associated
|
|
540 |
mappings.
|
|
5895.4.3
by Tim Penhey
Added edit view. |
541 |
"""
|
542 |
||
6650.1.2
by Michael Hudson
less hacking, no more working |
543 |
schema = EditCodeImportForm |
544 |
||
5763.5.11
by Tim Penhey
OMG, the test passes, quick, commit! |
545 |
# Need this to render the context to prepopulate the form fields.
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
546 |
# Added here as the base class isn't LaunchpadEditFormView.
|
547 |
render_context = True |
|
9129.2.4
by Tim Penhey
Remove codeimport-edit.pt in favour of generic-edit.pt. |
548 |
page_title = 'Edit import details' |
549 |
label = page_title |
|
6650.1.1
by Michael Hudson
some hacking |
550 |
|
551 |
@property
|
|
552 |
def initial_values(self): |
|
6650.1.19
by Michael Hudson
review stuff |
553 |
return {'whiteboard': self.context.whiteboard} |
5895.4.3
by Tim Penhey
Added edit view. |
554 |
|
555 |
def initialize(self): |
|
556 |
"""Show a 404 if the branch has no code import."""
|
|
557 |
self.code_import = self.context.code_import |
|
558 |
if self.code_import is None: |
|
559 |
raise NotFoundError |
|
5763.5.7
by Tim Penhey
Add new pagetest. |
560 |
# The next and cancel location is the branch details page.
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
561 |
self.cancel_url = self.next_url = canonical_url(self.context) |
562 |
CodeImportBaseView.initialize(self) |
|
5895.4.3
by Tim Penhey
Added edit view. |
563 |
|
564 |
@property
|
|
565 |
def adapters(self): |
|
5763.5.11
by Tim Penhey
OMG, the test passes, quick, commit! |
566 |
"""See `LaunchpadFormView`."""
|
6650.1.2
by Michael Hudson
less hacking, no more working |
567 |
return {EditCodeImportForm: self.code_import} |
5895.4.3
by Tim Penhey
Added edit view. |
568 |
|
569 |
def setUpFields(self): |
|
5895.4.6
by Tim Penhey
Added unittest around code import approval et al, and got the pages working. |
570 |
CodeImportBaseView.setUpFields(self) |
5895.4.3
by Tim Penhey
Added edit view. |
571 |
|
572 |
# If the import is a Subversion import, then omit the CVS
|
|
573 |
# fields, and vice versa.
|
|
574 |
if self.code_import.rcs_type == RevisionControlSystems.CVS: |
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
575 |
self.form_fields = self.form_fields.omit('url') |
9946.1.7
by Michael Hudson
make test actually test what it was intended to, fix it |
576 |
elif self.code_import.rcs_type in (RevisionControlSystems.SVN, |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
577 |
RevisionControlSystems.BZR_SVN, |
10129.6.13
by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts. |
578 |
RevisionControlSystems.GIT, |
579 |
RevisionControlSystems.HG): |
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
580 |
self.form_fields = self.form_fields.omit( |
581 |
'cvs_root', 'cvs_module') |
|
5895.4.3
by Tim Penhey
Added edit view. |
582 |
else: |
583 |
raise AssertionError('Unknown rcs_type for code import.') |
|
584 |
||
585 |
def _showButtonForStatus(self, status): |
|
586 |
"""If the status is different, and the user is super, show button."""
|
|
587 |
return self._super_user and self.code_import.review_status != status |
|
588 |
||
6650.1.3
by Michael Hudson
refactor so that I only have to change once place to do stuff with the new |
589 |
actions = form.Actions( |
6650.1.13
by Michael Hudson
some kind of progress |
590 |
_makeEditAction(_('Update'), None, 'updated'), |
6650.1.10
by Michael Hudson
renames, docstrings |
591 |
_makeEditAction( |
6650.1.13
by Michael Hudson
some kind of progress |
592 |
_('Approve'), CodeImportReviewStatus.REVIEWED, |
6650.1.3
by Michael Hudson
refactor so that I only have to change once place to do stuff with the new |
593 |
'approved'), |
6650.1.10
by Michael Hudson
renames, docstrings |
594 |
_makeEditAction( |
6650.1.13
by Michael Hudson
some kind of progress |
595 |
_('Mark Invalid'), CodeImportReviewStatus.INVALID, |
6650.1.3
by Michael Hudson
refactor so that I only have to change once place to do stuff with the new |
596 |
'set as invalid'), |
6650.1.10
by Michael Hudson
renames, docstrings |
597 |
_makeEditAction( |
6650.1.13
by Michael Hudson
some kind of progress |
598 |
_('Suspend'), CodeImportReviewStatus.SUSPENDED, |
6650.1.3
by Michael Hudson
refactor so that I only have to change once place to do stuff with the new |
599 |
'suspended'), |
6650.1.10
by Michael Hudson
renames, docstrings |
600 |
_makeEditAction( |
6650.1.13
by Michael Hudson
some kind of progress |
601 |
_('Mark Failing'), CodeImportReviewStatus.FAILING, |
6650.1.3
by Michael Hudson
refactor so that I only have to change once place to do stuff with the new |
602 |
'marked as failing'), |
603 |
)
|
|
6505.2.1
by Michael Hudson
cargo culting ftw |
604 |
|
5763.5.8
by Tim Penhey
Add validate method. |
605 |
def validate(self, data): |
606 |
"""See `LaunchpadFormView`."""
|
|
607 |
if self.code_import.rcs_type == RevisionControlSystems.CVS: |
|
5763.5.9
by Tim Penhey
Fix validation. |
608 |
self._validateCVS( |
609 |
data.get('cvs_root'), data.get('cvs_module'), |
|
610 |
self.code_import) |
|
9946.1.7
by Michael Hudson
make test actually test what it was intended to, fix it |
611 |
elif self.code_import.rcs_type in (RevisionControlSystems.SVN, |
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
612 |
RevisionControlSystems.BZR_SVN, |
10129.6.13
by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts. |
613 |
RevisionControlSystems.GIT, |
614 |
RevisionControlSystems.HG): |
|
10129.6.3
by Tim Penhey
Starting to unify the urls for code imports, particularly in the browser code. |
615 |
self._validateURL(data.get('url'), self.code_import) |
5763.5.11
by Tim Penhey
OMG, the test passes, quick, commit! |
616 |
else: |
617 |
raise AssertionError('Unknown rcs_type for code import.') |
|
5763.6.1
by Tim Penhey
Machine view |
618 |
|
619 |
||
620 |
class CodeImportMachineView(LaunchpadView): |
|
621 |
"""The view for the page that shows all the import machines."""
|
|
622 |
||
623 |
label = "Import machines for Launchpad" |
|
624 |
||
625 |
@property
|
|
626 |
def machines(self): |
|
627 |
"""Get the machines, sorted alphabetically by hostname."""
|
|
628 |
return getUtility(ICodeImportMachineSet).getAll() |