Merge lp:~mwhudson/launchpad/bzr-svn-monitor into lp:launchpad
- bzr-svn-monitor
- Merge into devel
Proposed by
Michael Hudson-Doyle
Status: | Merged |
---|---|
Approved by: | Tim Penhey |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~mwhudson/launchpad/bzr-svn-monitor |
Merge into: | lp:launchpad |
Diff against target: |
428 lines (+153/-22) 8 files modified
lib/lp/code/doc/codeimport.txt (+65/-12) lib/lp/code/mail/codeimport.py (+2/-1) lib/lp/code/model/codeimport.py (+4/-1) lib/lp/code/model/codeimportevent.py (+2/-1) lib/lp/codehosting/codeimport/tests/servers.py (+40/-2) lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+26/-1) lib/lp/codehosting/codeimport/worker.py (+5/-1) lib/lp/testing/factory.py (+9/-3) |
To merge this branch: | bzr merge lp:~mwhudson/launchpad/bzr-svn-monitor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Penhey (community) | Approve | ||
Review via email: mp+15264@code.launchpad.net |
Commit message
A test for bzr-svn at the worker-monitor level and enough to make it pass.
Description of the change
To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote : | # |
Revision history for this message
Tim Penhey (thumper) wrote : | # |
As much as it hurts me to say it, but can you please ReSTify the codeimport doc test titles? The current feeling is that as you touch the old files they get converted.
Other than that, looks good.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/doc/codeimport.txt' |
2 | --- lib/lp/code/doc/codeimport.txt 2009-10-03 17:10:28 +0000 |
3 | +++ lib/lp/code/doc/codeimport.txt 2009-12-07 03:01:12 +0000 |
4 | @@ -1,4 +1,5 @@ |
5 | -= Code Imports = |
6 | +Code Imports |
7 | +============ |
8 | |
9 | CodeImport objects model the process surrounding the code import |
10 | service of Launchpad. A CodeImport object is created by a user |
11 | @@ -14,7 +15,8 @@ |
12 | >>> login('david.allouche@canonical.com') |
13 | |
14 | |
15 | -== Code import set utility == |
16 | +Code import set utility |
17 | +----------------------- |
18 | |
19 | CodeImports are created and found using the ICodeImportSet interface, |
20 | which is registered as a utility. |
21 | @@ -34,7 +36,8 @@ |
22 | >>> nopriv = getUtility(IPersonSet).getByName('no-priv') |
23 | |
24 | |
25 | -== CodeImport events == |
26 | +CodeImport events |
27 | +----------------- |
28 | |
29 | Most mutating operations affecting code imports should create |
30 | CodeImportEvent objects in the database to provide an audit trail. |
31 | @@ -43,7 +46,8 @@ |
32 | >>> event_set = getUtility(ICodeImportEventSet) |
33 | |
34 | |
35 | -== Supported source systems == |
36 | +Supported source systems |
37 | +------------------------ |
38 | |
39 | The rcs_type field, which indicates whether the import is from CVS or |
40 | Subversion, takes values from the 'RevisionControlSystems' vocabulary. |
41 | @@ -57,7 +61,8 @@ |
42 | Git |
43 | |
44 | |
45 | -=== Import from CVS === |
46 | +Import from CVS |
47 | ++++++++++++++++ |
48 | |
49 | Code imports from CVS specify the CVSROOT value, and the path to import |
50 | in the repository, known as the "module". |
51 | @@ -113,7 +118,8 @@ |
52 | True |
53 | |
54 | |
55 | -=== Import from Subversion === |
56 | +Import from Subversion |
57 | +++++++++++++++++++++++ |
58 | |
59 | Code imports from Subversion specify the URL used with "svn checkout" to |
60 | retrieve the tree to import. |
61 | @@ -140,7 +146,33 @@ |
62 | >>> svn_import == existing_import |
63 | True |
64 | |
65 | -=== Import from Git === |
66 | + |
67 | +Import from Subversion via bzr-svn |
68 | +++++++++++++++++++++++++++++++++++ |
69 | + |
70 | +Code imports from Subversion can also specify that they should be |
71 | +imported with 'bzr-svn' rather than cscvs. In most respects these |
72 | +imports are similar to the Subversion via cscvs imports. |
73 | + |
74 | + >>> bzr_svn = RevisionControlSystems.BZR_SVN |
75 | + >>> bzr_svn_url = 'svn://svn.example.com/for-bzr-svn/trunk' |
76 | + >>> bzr_svn_import = code_import_set.new( |
77 | + ... registrant=nopriv, product=product, branch_name='trunk-bzr-svn', |
78 | + ... rcs_type=bzr_svn, svn_branch_url=bzr_svn_url) |
79 | + >>> verifyObject(ICodeImport, removeSecurityProxy(svn_import)) |
80 | + True |
81 | + |
82 | +The CodeImportSet.getBySVNDetails is also able to find bzr-svn |
83 | +imports. |
84 | + |
85 | + >>> existing_bzr_svn_import = code_import_set.getBySVNDetails( |
86 | + ... svn_branch_url=bzr_svn_url) |
87 | + >>> bzr_svn_import == existing_bzr_svn_import |
88 | + True |
89 | + |
90 | + |
91 | +Import from Git |
92 | ++++++++++++++++ |
93 | |
94 | Code imports from Git specify the URL used with "git clone" to |
95 | retrieve the branch to import. |
96 | @@ -167,7 +199,9 @@ |
97 | >>> git_import == existing_import |
98 | True |
99 | |
100 | -== Updating code import details == |
101 | + |
102 | +Updating code import details |
103 | +---------------------------- |
104 | |
105 | Members of the VCS Imports team (import operators), or Launchpad |
106 | administrators can update the details of the code import, including |
107 | @@ -267,7 +301,8 @@ |
108 | ... |
109 | |
110 | |
111 | -== Update intervals == |
112 | +Update intervals |
113 | +---------------- |
114 | |
115 | After an import is initially completed, it must be updated regularly. Each |
116 | code import can specify a custom update interval, or use a default value. |
117 | @@ -304,6 +339,8 @@ |
118 | datetime.timedelta(0, 21600) |
119 | >>> svn_import.effective_update_interval |
120 | datetime.timedelta(0, 21600) |
121 | + >>> bzr_svn_import.effective_update_interval |
122 | + datetime.timedelta(0, 21600) |
123 | |
124 | >>> default_interval_git |
125 | datetime.timedelta(0, 21600) |
126 | @@ -325,7 +362,9 @@ |
127 | >>> svn_import.effective_update_interval |
128 | datetime.timedelta(0, 3600) |
129 | |
130 | -== Retreiving CodeImports == |
131 | + |
132 | +Retrieving CodeImports |
133 | +---------------------- |
134 | |
135 | You can retrieve all imports with the `getAll` method of ICodeImport. |
136 | |
137 | @@ -361,7 +400,8 @@ |
138 | NotFoundError: -10 |
139 | |
140 | |
141 | -== Canonical URLs == |
142 | +Canonical URLs |
143 | +-------------- |
144 | |
145 | We've registered the ICodeImportSet utility on the 'code' part of the |
146 | site: |
147 | @@ -380,7 +420,8 @@ |
148 | NoCanonicalUrl: ... |
149 | |
150 | |
151 | -== Modifying CodeImports == |
152 | +Modifying CodeImports |
153 | +--------------------- |
154 | |
155 | Modifications to CodeImport objects must be done using setter methods |
156 | that create CodeImportEvent objects when appropriate. This is enforced |
157 | @@ -449,6 +490,18 @@ |
158 | instead of: |
159 | git://git.example.com/hello.git |
160 | |
161 | +Imports via bzr-svn are also similar. |
162 | + |
163 | + >>> data = {'svn_branch_url': 'http://svn.example.com/for-bzr-svn/trunk'} |
164 | + >>> modify_event = bzr_svn_import.updateFromData(data, nopriv) |
165 | + >>> print make_email_body_for_code_import_update( |
166 | + ... bzr_svn_import, modify_event, None) |
167 | + ~no-priv/firefox/trunk-bzr-svn is now being imported from: |
168 | + http://svn.example.com/for-bzr-svn/trunk |
169 | + instead of: |
170 | + svn://svn.example.com/for-bzr-svn/trunk |
171 | + |
172 | + |
173 | In addition, updateFromData can be used to set the branch whiteboard, |
174 | which is also described in the email that is sent. |
175 | |
176 | |
177 | === modified file 'lib/lp/code/mail/codeimport.py' |
178 | --- lib/lp/code/mail/codeimport.py 2009-10-13 14:00:24 +0000 |
179 | +++ lib/lp/code/mail/codeimport.py 2009-12-07 03:01:12 +0000 |
180 | @@ -95,7 +95,8 @@ |
181 | body.append( |
182 | details_change_prefix + '\n' + new_details + |
183 | "\ninstead of:\n" + old_details) |
184 | - elif code_import.rcs_type == RevisionControlSystems.SVN: |
185 | + elif code_import.rcs_type in (RevisionControlSystems.SVN, |
186 | + RevisionControlSystems.BZR_SVN): |
187 | if CodeImportEventDataType.OLD_SVN_BRANCH_URL in event_data: |
188 | old_url = event_data[CodeImportEventDataType.OLD_SVN_BRANCH_URL] |
189 | body.append( |
190 | |
191 | === modified file 'lib/lp/code/model/codeimport.py' |
192 | --- lib/lp/code/model/codeimport.py 2009-10-03 17:10:28 +0000 |
193 | +++ lib/lp/code/model/codeimport.py 2009-12-07 03:01:12 +0000 |
194 | @@ -105,6 +105,8 @@ |
195 | config.codeimport.default_interval_cvs, |
196 | RevisionControlSystems.SVN: |
197 | config.codeimport.default_interval_subversion, |
198 | + RevisionControlSystems.BZR_SVN: |
199 | + config.codeimport.default_interval_subversion, |
200 | RevisionControlSystems.GIT: |
201 | config.codeimport.default_interval_git, |
202 | } |
203 | @@ -218,7 +220,8 @@ |
204 | assert cvs_root is not None and cvs_module is not None |
205 | assert svn_branch_url is None |
206 | assert git_repo_url is None |
207 | - elif rcs_type == RevisionControlSystems.SVN: |
208 | + elif rcs_type in (RevisionControlSystems.SVN, |
209 | + RevisionControlSystems.BZR_SVN): |
210 | assert cvs_root is None and cvs_module is None |
211 | assert svn_branch_url is not None |
212 | assert git_repo_url is None |
213 | |
214 | === modified file 'lib/lp/code/model/codeimportevent.py' |
215 | --- lib/lp/code/model/codeimportevent.py 2009-07-17 00:26:05 +0000 |
216 | +++ lib/lp/code/model/codeimportevent.py 2009-12-07 03:01:12 +0000 |
217 | @@ -256,7 +256,8 @@ |
218 | |
219 | def _iterSourceDetails(self, code_import): |
220 | """Yield key-value tuples describing the source of the import.""" |
221 | - if code_import.rcs_type == RevisionControlSystems.SVN: |
222 | + if code_import.rcs_type in (RevisionControlSystems.SVN, |
223 | + RevisionControlSystems.BZR_SVN): |
224 | yield 'SVN_BRANCH_URL', code_import.svn_branch_url |
225 | elif code_import.rcs_type == RevisionControlSystems.CVS: |
226 | yield 'CVS_ROOT', code_import.cvs_root |
227 | |
228 | === modified file 'lib/lp/codehosting/codeimport/tests/servers.py' |
229 | --- lib/lp/codehosting/codeimport/tests/servers.py 2009-11-19 04:33:06 +0000 |
230 | +++ lib/lp/codehosting/codeimport/tests/servers.py 2009-12-07 03:01:12 +0000 |
231 | @@ -3,6 +3,8 @@ |
232 | |
233 | """Server classes that know how to create various kinds of foreign archive.""" |
234 | |
235 | +from __future__ import with_statement |
236 | + |
237 | __all__ = [ |
238 | 'CVSServer', |
239 | 'GitServer', |
240 | @@ -13,7 +15,10 @@ |
241 | |
242 | import os |
243 | import shutil |
244 | +import signal |
245 | +import subprocess |
246 | import tempfile |
247 | +import time |
248 | |
249 | import CVS |
250 | import pysvn |
251 | @@ -60,9 +65,10 @@ |
252 | class SubversionServer(Server): |
253 | """A controller for an Subversion repository, used for testing.""" |
254 | |
255 | - def __init__(self, repository_path): |
256 | + def __init__(self, repository_path, use_svn_serve=False): |
257 | super(SubversionServer, self).__init__() |
258 | self.repository_path = os.path.abspath(repository_path) |
259 | + self._use_svn_serve = use_svn_serve |
260 | |
261 | def createRepository(self, path): |
262 | """Create a Subversion repository at `path`.""" |
263 | @@ -70,11 +76,43 @@ |
264 | |
265 | def get_url(self): |
266 | """Return a URL to the Subversion repository.""" |
267 | - return local_path_to_url(self.repository_path) |
268 | + if self._use_svn_serve: |
269 | + return 'svn://localhost/' |
270 | + else: |
271 | + return local_path_to_url(self.repository_path) |
272 | |
273 | def setUp(self): |
274 | super(SubversionServer, self).setUp() |
275 | self.createRepository(self.repository_path) |
276 | + if self._use_svn_serve: |
277 | + conf_path = os.path.join( |
278 | + self.repository_path, 'conf/svnserve.conf') |
279 | + with open(conf_path , 'w') as conf_file: |
280 | + conf_file.write('[general]\nanon-access = write\n') |
281 | + self._svnserve = subprocess.Popen( |
282 | + ['svnserve', '--daemon', '--foreground', '--root', |
283 | + self.repository_path]) |
284 | + delay = 0.1 |
285 | + for i in range(10): |
286 | + try: |
287 | + client = pysvn.Client() |
288 | + client.ls(self.get_url()) |
289 | + except pysvn.ClientError, e: |
290 | + if 'Connection refused' in str(e): |
291 | + time.sleep(delay) |
292 | + delay *= 1.5 |
293 | + continue |
294 | + else: |
295 | + break |
296 | + else: |
297 | + raise AssertionError( |
298 | + "svnserve didn't start accepting connections") |
299 | + |
300 | + def tearDown(self): |
301 | + super(SubversionServer, self).tearDown() |
302 | + if self._use_svn_serve: |
303 | + os.kill(self._svnserve.pid, signal.SIGINT) |
304 | + self._svnserve.communicate() |
305 | |
306 | @run_in_temporary_directory |
307 | def makeBranch(self, branch_name, tree_contents): |
308 | |
309 | === modified file 'lib/lp/codehosting/codeimport/tests/test_workermonitor.py' |
310 | --- lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2009-11-25 07:00:06 +0000 |
311 | +++ lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2009-12-07 03:01:12 +0000 |
312 | @@ -29,7 +29,8 @@ |
313 | TwistedLayer, TwistedLaunchpadZopelessLayer) |
314 | from canonical.twistedsupport.tests.test_processmonitor import ( |
315 | makeFailure, ProcessTestsMixin) |
316 | -from lp.code.enums import CodeImportResultStatus, CodeImportReviewStatus |
317 | +from lp.code.enums import ( |
318 | + CodeImportResultStatus, CodeImportReviewStatus, RevisionControlSystems) |
319 | from lp.code.interfaces.codeimport import ICodeImportSet |
320 | from lp.code.interfaces.codeimportjob import ( |
321 | ICodeImportJobSet, ICodeImportJobWorkflow) |
322 | @@ -476,6 +477,20 @@ |
323 | return self.factory.makeCodeImport( |
324 | svn_branch_url=svn_branch_url) |
325 | |
326 | + def makeBzrSvnCodeImport(self): |
327 | + """Make a `CodeImport` that points to a real Subversion repository.""" |
328 | + self.subversion_server = SubversionServer( |
329 | + self.repo_path, use_svn_serve=True) |
330 | + self.subversion_server.setUp() |
331 | + self.addCleanup(self.subversion_server.tearDown) |
332 | + svn_branch_url = self.subversion_server.makeBranch( |
333 | + 'trunk', [('README', 'contents')]) |
334 | + self.foreign_commit_count = 2 |
335 | + |
336 | + return self.factory.makeCodeImport( |
337 | + svn_branch_url=svn_branch_url, |
338 | + rcs_type=RevisionControlSystems.BZR_SVN) |
339 | + |
340 | def makeGitCodeImport(self): |
341 | """Make a `CodeImport` that points to a real Git repository.""" |
342 | load_optional_plugin('git') |
343 | @@ -579,6 +594,15 @@ |
344 | result = self.performImport(job_id) |
345 | return result.addCallback(self.assertImported, code_import_id) |
346 | |
347 | + def test_import_bzrsvn(self): |
348 | + # Create a Subversion-via-bzr-svn CodeImport and import it. |
349 | + job = self.getStartedJobForImport(self.makeBzrSvnCodeImport()) |
350 | + code_import_id = job.code_import.id |
351 | + job_id = job.id |
352 | + self.layer.txn.commit() |
353 | + result = self.performImport(job_id) |
354 | + return result.addCallback(self.assertImported, code_import_id) |
355 | + |
356 | |
357 | class DeferredOnExit(protocol.ProcessProtocol): |
358 | |
359 | @@ -591,6 +615,7 @@ |
360 | else: |
361 | self._deferred.errback(reason) |
362 | |
363 | + |
364 | class TestWorkerMonitorIntegrationScript(TestWorkerMonitorIntegration): |
365 | """Tests for CodeImportWorkerMonitor that execute a child process.""" |
366 | |
367 | |
368 | === modified file 'lib/lp/codehosting/codeimport/worker.py' |
369 | --- lib/lp/codehosting/codeimport/worker.py 2009-12-06 23:01:26 +0000 |
370 | +++ lib/lp/codehosting/codeimport/worker.py 2009-12-07 03:01:12 +0000 |
371 | @@ -152,6 +152,10 @@ |
372 | rcstype = 'svn' |
373 | svn_branch_url = str(code_import.svn_branch_url) |
374 | cvs_root = cvs_module = git_repo_url = None |
375 | + elif code_import.rcs_type == RevisionControlSystems.BZR_SVN: |
376 | + rcstype = 'bzr-svn' |
377 | + svn_branch_url = str(code_import.svn_branch_url) |
378 | + cvs_root = cvs_module = git_repo_url = None |
379 | elif code_import.rcs_type == RevisionControlSystems.CVS: |
380 | rcstype = 'cvs' |
381 | svn_branch_url = git_repo_url = None |
382 | @@ -162,7 +166,7 @@ |
383 | svn_branch_url = cvs_root = cvs_module = None |
384 | git_repo_url = str(code_import.git_repo_url) |
385 | else: |
386 | - raise AssertionError("Unknown rcstype %r." % rcstype) |
387 | + raise AssertionError("Unknown rcstype %r." % code_import.rcs_type) |
388 | return cls( |
389 | code_import.branch.id, rcstype, svn_branch_url, |
390 | cvs_root, cvs_module, git_repo_url) |
391 | |
392 | === modified file 'lib/lp/testing/factory.py' |
393 | --- lib/lp/testing/factory.py 2009-11-27 12:50:16 +0000 |
394 | +++ lib/lp/testing/factory.py 2009-12-07 03:01:12 +0000 |
395 | @@ -1210,7 +1210,7 @@ |
396 | |
397 | def makeCodeImport(self, svn_branch_url=None, cvs_root=None, |
398 | cvs_module=None, product=None, branch_name=None, |
399 | - git_repo_url=None, registrant=None): |
400 | + git_repo_url=None, registrant=None, rcs_type=None): |
401 | """Create and return a new, arbitrary code import. |
402 | |
403 | The type of code import will be inferred from the source details |
404 | @@ -1229,16 +1229,22 @@ |
405 | |
406 | code_import_set = getUtility(ICodeImportSet) |
407 | if svn_branch_url is not None: |
408 | + if rcs_type is None: |
409 | + rcs_type = RevisionControlSystems.SVN |
410 | + else: |
411 | + assert rcs_type in (RevisionControlSystems.SVN, |
412 | + RevisionControlSystems.BZR_SVN) |
413 | return code_import_set.new( |
414 | - registrant, product, branch_name, |
415 | - rcs_type=RevisionControlSystems.SVN, |
416 | + registrant, product, branch_name, rcs_type=rcs_type, |
417 | svn_branch_url=svn_branch_url) |
418 | elif git_repo_url is not None: |
419 | + assert rcs_type in (None, RevisionControlSystems.GIT) |
420 | return code_import_set.new( |
421 | registrant, product, branch_name, |
422 | rcs_type=RevisionControlSystems.GIT, |
423 | git_repo_url=git_repo_url) |
424 | else: |
425 | + assert rcs_type in (None, RevisionControlSystems.CVS) |
426 | return code_import_set.new( |
427 | registrant, product, branch_name, |
428 | rcs_type=RevisionControlSystems.CVS, |
Hi,
This branch adds a test for bzr-svn at the worker-monitor level and makes it pass. It also tests some very basic stuff in codeimport.txt.
Cheers,
mwh