Merge lp:~mwhudson/launchpad/bzr-svn-imports into lp:launchpad

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-imports
Merge into: lp:launchpad
Diff against target: 577 lines (+133/-85)
8 files modified
lib/lp/codehosting/codeimport/tests/servers.py (+3/-16)
lib/lp/codehosting/codeimport/tests/test_dispatcher.py (+2/-4)
lib/lp/codehosting/codeimport/tests/test_worker.py (+76/-44)
lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+5/-6)
lib/lp/codehosting/codeimport/worker.py (+40/-10)
lib/lp/testing/factory.py (+1/-1)
scripts/code-import-worker.py (+5/-3)
sourcecode/Makefile (+1/-1)
To merge this branch: bzr merge lp:~mwhudson/launchpad/bzr-svn-imports
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Review via email: mp+15027@code.launchpad.net

Commit message

Add support for bzr-svn to the code import worker

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

This branch adds support for bzr-svn to the code import worker, the lowest level of the code import system.

Revision history for this message
Tim Penhey (thumper) wrote :

Looks pretty good to me.

Will be happy to see bzr-svn working.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/codehosting/codeimport/tests/servers.py'
2--- lib/lp/codehosting/codeimport/tests/servers.py 2009-06-30 16:56:07 +0000
3+++ lib/lp/codehosting/codeimport/tests/servers.py 2009-11-23 21:24:23 +0000
4@@ -11,7 +11,6 @@
5
6 __metaclass__ = type
7
8-import logging
9 import os
10 import shutil
11 import tempfile
12@@ -24,6 +23,7 @@
13 from bzrlib.transport import Server
14 from bzrlib.tests.treeshape import build_tree_contents
15
16+from canonical.launchpad.scripts.logger import QuietFakeLogger
17
18 def local_path_to_url(local_path):
19 """Return a file:// URL to `local_path`.
20@@ -35,19 +35,6 @@
21 os.path.normpath(os.path.abspath(local_path)))
22
23
24-def _make_silent_logger():
25- """Create a logger that prints nothing."""
26-
27- class SilentLogHandler(logging.Handler):
28- def emit(self, record):
29- pass
30-
31- logger = logging.Logger("collector")
32- handler = SilentLogHandler()
33- logger.addHandler(handler)
34- return logger
35-
36-
37 def run_in_temporary_directory(function):
38 """Decorate `function` to be run in a temporary directory.
39
40@@ -79,7 +66,7 @@
41
42 def createRepository(self, path):
43 """Create a Subversion repository at `path`."""
44- svn_oo.Repository.Create(path, _make_silent_logger())
45+ svn_oo.Repository.Create(path, QuietFakeLogger())
46
47 def get_url(self):
48 """Return a URL to the Subversion repository."""
49@@ -139,7 +126,7 @@
50 :param path: The local path to create a repository in.
51 :return: A CVS.Repository`.
52 """
53- return CVS.init(path, _make_silent_logger())
54+ return CVS.init(path, QuietFakeLogger())
55
56 def getRoot(self):
57 """Return the CVS root for this server."""
58
59=== modified file 'lib/lp/codehosting/codeimport/tests/test_dispatcher.py'
60--- lib/lp/codehosting/codeimport/tests/test_dispatcher.py 2009-06-25 04:06:00 +0000
61+++ lib/lp/codehosting/codeimport/tests/test_dispatcher.py 2009-11-23 21:24:23 +0000
62@@ -10,7 +10,6 @@
63 import os
64 import shutil
65 import socket
66-import sys
67 import tempfile
68 from textwrap import dedent
69 from unittest import TestLoader
70@@ -19,9 +18,8 @@
71
72 from canonical.config import config
73 from lp.codehosting.codeimport.dispatcher import CodeImportDispatcher
74-from lp.codehosting.codeimport.tests.servers import (
75- _make_silent_logger)
76 from canonical.launchpad import scripts
77+from canonical.launchpad.scripts.logger import QuietFakeLogger
78 from canonical.testing.layers import TwistedLaunchpadZopelessLayer
79
80
81@@ -43,7 +41,7 @@
82 def setUp(self):
83 self.config_count = 0
84 self.pushConfig(forced_hostname='none')
85- self.dispatcher = CodeImportDispatcher(_make_silent_logger())
86+ self.dispatcher = CodeImportDispatcher(QuietFakeLogger())
87
88 def pushConfig(self, **args):
89 """Push some key-value pairs into the codeimportdispatcher config.
90
91=== modified file 'lib/lp/codehosting/codeimport/tests/test_worker.py'
92--- lib/lp/codehosting/codeimport/tests/test_worker.py 2009-11-21 00:28:10 +0000
93+++ lib/lp/codehosting/codeimport/tests/test_worker.py 2009-11-23 21:24:23 +0000
94@@ -9,6 +9,7 @@
95 import os
96 import shutil
97 import subprocess
98+import sys
99 import tempfile
100 import time
101 import unittest
102@@ -21,18 +22,23 @@
103 from bzrlib.upgrade import upgrade
104 from bzrlib.urlutils import join as urljoin
105
106+from CVS import Repository, tree
107+
108 from canonical.cachedproperty import cachedproperty
109+from canonical.config import config
110+from canonical.launchpad.scripts.logger import QuietFakeLogger
111+from canonical.testing import BaseLayer
112+
113 from lp.codehosting import load_optional_plugin
114 from lp.codehosting.codeimport.worker import (
115- BazaarBranchStore, CSCVSImportWorker, ForeignTreeStore, GitImportWorker,
116- ImportDataStore, ImportWorker, get_default_bazaar_branch_store)
117+ BazaarBranchStore, BzrSvnImportWorker, CSCVSImportWorker,
118+ ForeignTreeStore, GitImportWorker, ImportDataStore, ImportWorker,
119+ get_default_bazaar_branch_store)
120 from lp.codehosting.codeimport.tests.servers import (
121 CVSServer, GitServer, SubversionServer)
122 from lp.codehosting.tests.helpers import (
123 create_branch_with_one_revision)
124-from canonical.config import config
125 from lp.testing.factory import LaunchpadObjectFactory
126-from canonical.testing import BaseLayer
127
128 import pysvn
129
130@@ -120,7 +126,7 @@
131 store = self.makeBranchStore()
132 target_url = store._getMirrorURL(self.arbitrary_branch_id)
133 knit_format = format_registry.get('knit')()
134- tree = create_branch_with_one_revision(target_url, format=knit_format)
135+ create_branch_with_one_revision(target_url, format=knit_format)
136 default_format = BzrDirFormat.get_default_format()
137
138 # The fetched branch is in the default format.
139@@ -142,7 +148,7 @@
140 store = self.makeBranchStore()
141 target_url = store._getMirrorURL(self.arbitrary_branch_id)
142 knit_format = format_registry.get('knit')()
143- tree = create_branch_with_one_revision(target_url, format=knit_format)
144+ create_branch_with_one_revision(target_url, format=knit_format)
145 upgrade(target_url, format_registry.get('dirstate-tags')())
146 self.failUnless(get_transport(target_url).has('backup.bzr'))
147 default_format = BzrDirFormat.get_default_format()
148@@ -587,7 +593,6 @@
149 if filename.startswith(prefix):
150 tree_transport.delete(filename)
151 branchstore = get_default_bazaar_branch_store()
152- branch_transport = branchstore.transport
153 branch_name = '%08x' % source_details.branch_id
154 if branchstore.transport.has(branch_name):
155 branchstore.transport.delete_tree(branch_name)
156@@ -615,8 +620,10 @@
157 raise NotImplementedError(
158 "Override this with a VCS-specific implementation.")
159
160- def commitInForeignTree(self, foreign_tree):
161- """Commit a single revision to `foreign_tree`.
162+ def makeForeignCommit(self):
163+ """Commit a revision to the repo described by `self.source_details`.
164+
165+ Increment `self.foreign_commit_count` as appropriate.
166
167 Override this in your subclass.
168 """
169@@ -626,6 +633,8 @@
170 def makeSourceDetails(self, module_name, files):
171 """Make a `CodeImportSourceDetails` that points to a real repository.
172
173+ This should set `self.foreign_commit_count` to an appropriate value.
174+
175 Override this in your subclass.
176 """
177 raise NotImplementedError(
178@@ -656,18 +665,7 @@
179 self.foreign_commit_count, len(branch.revision_history()))
180
181 # Change the remote branch.
182-
183- tree_dir = self.makeTemporaryDirectory()
184- # This is pretty gross, but it works: the call to worker.run() will
185- # chdir() again to the worker's scratch directory, and in any case the
186- # tests subclass bzrlib's TestCaseInTempdir, so the directory will be
187- # restored at the end of the test.
188- os.chdir(tree_dir)
189- if isinstance(worker, CSCVSImportWorker):
190- foreign_tree = worker.foreign_tree_store.fetch(tree_dir)
191- else:
192- foreign_tree = None
193- self.commitInForeignTree(foreign_tree)
194+ self.makeForeignCommit()
195
196 # Run the same worker again.
197 worker.run()
198@@ -736,15 +734,17 @@
199 super(TestCVSImport, self).setUp()
200 self.setUpImport()
201
202- def commitInForeignTree(self, foreign_tree):
203+ def makeForeignCommit(self):
204 # If you write to a file in the same second as the previous commit,
205 # CVS will not think that it has changed.
206 time.sleep(1)
207- self.build_tree_contents(
208- [(os.path.join(foreign_tree.local_path, 'README'),
209- 'New content')])
210- foreign_tree.commit()
211+ repo = Repository(self.source_details.cvs_root, QuietFakeLogger())
212+ repo.get(self.source_details.cvs_module, 'working_dir')
213+ wt = tree('working_dir')
214+ self.build_tree_contents([('working_dir/README', 'New content')])
215+ wt.commit(log='Log message')
216 self.foreign_commit_count += 1
217+ shutil.rmtree('working_dir')
218
219 def makeSourceDetails(self, module_name, files):
220 """Make a CVS `CodeImportSourceDetails` pointing at a real CVS repo.
221@@ -761,18 +761,14 @@
222 rcstype='cvs', cvs_root=cvs_server.getRoot(), cvs_module='trunk')
223
224
225-class TestSubversionImport(WorkerTest, CSCVSActualImportMixin):
226- """Tests for the worker importing and syncing a Subversion branch."""
227-
228- def setUp(self):
229- WorkerTest.setUp(self)
230- self.setUpImport()
231-
232- def commitInForeignTree(self, foreign_tree):
233- """Change the foreign tree, generating exactly one commit."""
234- svn_url = foreign_tree.remote_url
235+class SubversionImportHelpers:
236+ """Implementations of `makeForeignCommit` and `makeSourceDetails` for svn.
237+ """
238+
239+ def makeForeignCommit(self):
240+ """Change the foreign tree."""
241 client = pysvn.Client()
242- client.checkout(svn_url, 'working_tree')
243+ client.checkout(self.source_details.svn_branch_url, 'working_tree')
244 file = open('working_tree/newfile', 'w')
245 file.write('No real content\n')
246 file.close()
247@@ -789,10 +785,21 @@
248 self.addCleanup(svn_server.tearDown)
249
250 svn_branch_url = svn_server.makeBranch(branch_name, files)
251+ svn_branch_url = svn_branch_url.replace('://localhost/', ':///')
252 self.foreign_commit_count = 2
253-
254 return self.factory.makeCodeImportSourceDetails(
255- rcstype='svn', svn_branch_url=svn_branch_url)
256+ rcstype=self.rcstype, svn_branch_url=svn_branch_url)
257+
258+
259+class TestSubversionImport(WorkerTest, SubversionImportHelpers,
260+ CSCVSActualImportMixin):
261+ """Tests for the worker importing and syncing a Subversion branch."""
262+
263+ rcstype = 'svn'
264+
265+ def setUp(self):
266+ WorkerTest.setUp(self)
267+ self.setUpImport()
268
269
270 class TestGitImport(WorkerTest, TestActualImportMixin):
271@@ -820,11 +827,11 @@
272 self.source_details, self.get_transport('import_data'),
273 self.bazaar_store, logging.getLogger())
274
275- def commitInForeignTree(self, foreign_tree):
276+ def makeForeignCommit(self):
277 """Change the foreign tree, generating exactly one commit."""
278 from bzrlib.plugins.git.tests import run_git
279 wd = os.getcwd()
280- os.chdir(self.repository_path)
281+ os.chdir(self.source_details.git_repo_url)
282 try:
283 run_git('config', 'user.name', 'Joe Random Hacker')
284 run_git('commit', '-m', 'dsadas')
285@@ -835,8 +842,8 @@
286 def makeSourceDetails(self, branch_name, files):
287 """Make a Git `CodeImportSourceDetails` pointing at a real Git repo.
288 """
289- self.repository_path = self.makeTemporaryDirectory()
290- git_server = GitServer(self.repository_path)
291+ repository_path = self.makeTemporaryDirectory()
292+ git_server = GitServer(repository_path)
293 git_server.setUp()
294 self.addCleanup(git_server.tearDown)
295
296@@ -844,7 +851,32 @@
297 self.foreign_commit_count = 1
298
299 return self.factory.makeCodeImportSourceDetails(
300- rcstype='git', git_repo_url=self.repository_path)
301+ rcstype='git', git_repo_url=repository_path)
302+
303+
304+class TestBzrSvnImport(WorkerTest, SubversionImportHelpers,
305+ TestActualImportMixin):
306+
307+ rcstype = 'bzr-svn'
308+
309+ def setUp(self):
310+ super(TestBzrSvnImport, self).setUp()
311+ load_optional_plugin('svn')
312+ self.setUpImport()
313+ # XXX MichaelHudson, 2009-11-24, bug=464174:
314+ # TestCaseWithMemoryTransport likes to set these environment variables
315+ # to unicode strings and bzr-svn hits an assertion failure in this
316+ # case.
317+ os.environ['BZR_HOME'] = os.environ['BZR_HOME'].encode(
318+ sys.getfilesystemencoding())
319+ os.environ['HOME'] = os.environ['HOME'].encode(
320+ sys.getfilesystemencoding())
321+
322+ def makeImportWorker(self):
323+ """Make a new `ImportWorker`."""
324+ return BzrSvnImportWorker(
325+ self.source_details, self.get_transport('import_data'),
326+ self.bazaar_store, logging.getLogger())
327
328
329 def test_suite():
330
331=== modified file 'lib/lp/codehosting/codeimport/tests/test_workermonitor.py'
332--- lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2009-11-21 01:08:05 +0000
333+++ lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2009-11-23 21:24:23 +0000
334@@ -24,6 +24,7 @@
335 from zope.security.proxy import removeSecurityProxy
336
337 from canonical.config import config
338+from canonical.launchpad.scripts.logger import QuietFakeLogger
339 from canonical.testing.layers import (
340 TwistedLayer, TwistedLaunchpadZopelessLayer)
341 from canonical.twistedsupport.tests.test_processmonitor import (
342@@ -41,7 +42,7 @@
343 CodeImportWorkerMonitor, CodeImportWorkerMonitorProtocol, ExitQuietly,
344 read_only_transaction)
345 from lp.codehosting.codeimport.tests.servers import (
346- CVSServer, GitServer, SubversionServer, _make_silent_logger)
347+ CVSServer, GitServer, SubversionServer)
348 from lp.codehosting.codeimport.tests.test_worker import (
349 clean_up_default_stores_for_import)
350 from lp.testing import login, logout
351@@ -173,8 +174,7 @@
352 getUtility(ICodeImportJobWorkflow).startJob(
353 job, self.factory.makeCodeImportMachine(set_online=True))
354 self.job_id = job.id
355- self.worker_monitor = self.WorkerMonitor(
356- job.id, _make_silent_logger())
357+ self.worker_monitor = self.WorkerMonitor(job.id, QuietFakeLogger())
358 self.worker_monitor._failures = []
359 self.layer.txn.commit()
360 self.layer.switchDbUser('codeimportworker')
361@@ -349,8 +349,7 @@
362 getUtility(ICodeImportJobWorkflow).startJob(
363 job, self.factory.makeCodeImportMachine(set_online=True))
364 self.job_id = job.id
365- self.worker_monitor = self.WorkerMonitor(
366- job.id, _make_silent_logger())
367+ self.worker_monitor = self.WorkerMonitor(job.id, QuietFakeLogger())
368 self.worker_monitor.result_status = None
369 self.layer.txn.commit()
370 self.layer.switchDbUser('codeimportworker')
371@@ -540,7 +539,7 @@
372 This implementation does it in-process.
373 """
374 self.layer.switchDbUser('codeimportworker')
375- monitor = CIWorkerMonitorForTesting(job_id, _make_silent_logger())
376+ monitor = CIWorkerMonitorForTesting(job_id, QuietFakeLogger())
377 deferred = monitor.run()
378 def save_protocol_object(result):
379 """Save the process protocol object.
380
381=== modified file 'lib/lp/codehosting/codeimport/worker.py'
382--- lib/lp/codehosting/codeimport/worker.py 2009-09-18 01:36:48 +0000
383+++ lib/lp/codehosting/codeimport/worker.py 2009-11-23 21:24:23 +0000
384@@ -6,18 +6,21 @@
385 __metaclass__ = type
386 __all__ = [
387 'BazaarBranchStore',
388+ 'BzrSvnImportWorker',
389 'CSCVSImportWorker',
390 'CodeImportSourceDetails',
391 'ForeignTreeStore',
392+ 'GitImportWorker',
393 'ImportWorker',
394- 'get_default_bazaar_branch_store']
395+ 'get_default_bazaar_branch_store',
396+ ]
397
398
399 import os
400 import shutil
401
402 from bzrlib.branch import Branch
403-from bzrlib.bzrdir import BzrDir, BzrDirFormat, format_registry
404+from bzrlib.bzrdir import BzrDir, BzrDirFormat
405 from bzrlib.transport import get_transport
406 from bzrlib.errors import NoSuchFile, NotBranchError
407 import bzrlib.ui
408@@ -105,9 +108,12 @@
409 :ivar branch_id: The id of the branch associated to this code import, used
410 for locating the existing import and the foreign tree.
411 :ivar rcstype: 'svn' or 'cvs' as appropriate.
412- :ivar svn_branch_url: The branch URL if rcstype == 'svn', None otherwise.
413+ :ivar svn_branch_url: The branch URL if rcstype in ['svn', 'bzr-svn'],
414+ None otherwise.
415 :ivar cvs_root: The $CVSROOT if rcstype == 'cvs', None otherwise.
416 :ivar cvs_module: The CVS module if rcstype == 'cvs', None otherwise.
417+ :ivar git_repo_url: The URL of the git repo, if rcstype == 'git', None,
418+ otherwise.
419 """
420
421 def __init__(self, branch_id, rcstype, svn_branch_url=None, cvs_root=None,
422@@ -124,7 +130,7 @@
423 """Convert command line-style arguments to an instance."""
424 branch_id = int(arguments.pop(0))
425 rcstype = arguments.pop(0)
426- if rcstype == 'svn':
427+ if rcstype in ['svn', 'bzr-svn']:
428 [svn_branch_url] = arguments
429 cvs_root = cvs_module = git_repo_url = None
430 elif rcstype == 'cvs':
431@@ -165,7 +171,7 @@
432 """Return a list of arguments suitable for passing to a child process.
433 """
434 result = [str(self.branch_id), self.rcstype]
435- if self.rcstype == 'svn':
436+ if self.rcstype in ['svn', 'bzr-svn']:
437 result.append(self.svn_branch_url)
438 elif self.rcstype == 'cvs':
439 result.append(self.cvs_root)
440@@ -209,8 +215,8 @@
441 characters. For example 'tree.tar.gz' might become '0000a23d.tar.gz'
442 or 'git.db' might become '00003e4.db'.
443
444- :param local_name: The local name of the file to be stored. :return:
445- The name to store the file as on the remote transport.
446+ :param local_name: The local name of the file to be stored.
447+ :return: The name to store the file as on the remote transport.
448 """
449 if '/' in local_name:
450 raise AssertionError("local_name must be a name, not a path")
451@@ -393,11 +399,13 @@
452 if os.path.exists(working_directory):
453 shutil.rmtree(working_directory)
454 os.makedirs(working_directory)
455+ saved_pwd = os.getcwd()
456 os.chdir(working_directory)
457 try:
458 self._doImport()
459 finally:
460 shutil.rmtree(working_directory)
461+ os.chdir(saved_pwd)
462
463 def _doImport(self):
464 raise NotImplementedError()
465@@ -479,17 +487,25 @@
466
467
468 class PullingImportWorker(ImportWorker):
469- """An import worker for imports that can be done by a bzr plugin."""
470+ """An import worker for imports that can be done by a bzr plugin.
471+
472+ Subclasses need to implement `pull_url`.
473+ """
474+ @property
475+ def pull_url(self):
476+ """Return the URL that should be pulled from."""
477+ raise NotImplementedError
478
479 def _doImport(self):
480 bazaar_tree = self.getBazaarWorkingTree()
481+ self.bazaar_branch_store.push(
482+ self.source_details.branch_id, bazaar_tree, self.required_format)
483 saved_factory = bzrlib.ui.ui_factory
484 bzrlib.ui.ui_factory = LoggingUIFactory(
485 writer=lambda m: self._logger.info('%s', m))
486 try:
487 bazaar_tree.branch.pull(
488- Branch.open(self.source_details.git_repo_url),
489- overwrite=True)
490+ Branch.open(self.pull_url), overwrite=True)
491 finally:
492 bzrlib.ui.ui_factory = saved_factory
493 self.pushBazaarWorkingTree(bazaar_tree)
494@@ -501,6 +517,11 @@
495 The only behaviour we add is preserving the 'git.db' shamap between runs.
496 """
497
498+ @property
499+ def pull_url(self):
500+ """See `PullingImportWorker.pull_url`."""
501+ return self.source_details.git_repo_url
502+
503 def getBazaarWorkingTree(self):
504 """See `ImportWorker.getBazaarWorkingTree`.
505
506@@ -523,3 +544,12 @@
507 PullingImportWorker.pushBazaarWorkingTree(self, bazaar_tree)
508 self.import_data_store.put(
509 'git.db', bazaar_tree.branch.repository._transport)
510+
511+
512+class BzrSvnImportWorker(PullingImportWorker):
513+ """An import worker for importing Subversion via bzr-svn."""
514+
515+ @property
516+ def pull_url(self):
517+ """See `PullingImportWorker.pull_url`."""
518+ return self.source_details.svn_branch_url
519
520=== modified file 'lib/lp/testing/factory.py'
521--- lib/lp/testing/factory.py 2009-11-20 15:42:50 +0000
522+++ lib/lp/testing/factory.py 2009-11-23 21:24:23 +0000
523@@ -1311,7 +1311,7 @@
524 branch_id = self.getUniqueInteger()
525 if rcstype is None:
526 rcstype = 'svn'
527- if rcstype == 'svn':
528+ if rcstype in ['svn', 'bzr-svn']:
529 assert cvs_root is cvs_module is git_repo_url is None
530 if svn_branch_url is None:
531 svn_branch_url = self.getUniqueURL()
532
533=== added symlink 'lib/subvertpy'
534=== target is u'../sourcecode/subvertpy/subvertpy'
535=== added symlink 'optionalbzrplugins/svn'
536=== target is u'../sourcecode/bzr-svn'
537=== modified file 'scripts/code-import-worker.py'
538--- scripts/code-import-worker.py 2009-10-13 14:38:07 +0000
539+++ scripts/code-import-worker.py 2009-11-23 21:24:23 +0000
540@@ -25,12 +25,11 @@
541 from canonical.config import config
542 from lp.codehosting import load_optional_plugin
543 from lp.codehosting.codeimport.worker import (
544- CSCVSImportWorker, CodeImportSourceDetails, GitImportWorker,
545- get_default_bazaar_branch_store)
546+ BzrSvnImportWorker, CSCVSImportWorker, CodeImportSourceDetails,
547+ GitImportWorker, get_default_bazaar_branch_store)
548 from canonical.launchpad import scripts
549
550
551-
552 class CodeImportWorker:
553
554 def __init__(self):
555@@ -44,6 +43,9 @@
556 if source_details.rcstype == 'git':
557 load_optional_plugin('git')
558 import_worker_cls = GitImportWorker
559+ elif source_details.rcstype == 'bzr-svn':
560+ load_optional_plugin('svn')
561+ import_worker_cls = BzrSvnImportWorker
562 else:
563 if source_details.rcstype not in ['cvs', 'svn']:
564 raise AssertionError(
565
566=== modified file 'sourcecode/Makefile'
567--- sourcecode/Makefile 2009-11-18 15:09:01 +0000
568+++ sourcecode/Makefile 2009-11-23 21:24:23 +0000
569@@ -4,7 +4,7 @@
570 # the ones we test. If we fix them all to have EITHER a good makefile
571 # (build and check targets work), or no makefile we can reenable auto
572 # detection.
573-build_dirs:=cscvs dulwich pygettextpo pygpgme twisted
574+build_dirs:=cscvs dulwich pygettextpo pygpgme twisted subvertpy
575 test_dirs:=cscvs pygettextpo twisted
576
577 TEST_ENV_VARS = \