Merge lp:~cjwatson/launchpad/codeimport-worker-refactor into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18231
Proposed branch: lp:~cjwatson/launchpad/codeimport-worker-refactor
Merge into: lp:launchpad
Prerequisite: lp:~cjwatson/launchpad/codeimport-source-details-refactor
Diff against target: 547 lines (+114/-96)
7 files modified
lib/lp/code/xmlrpc/codeimportscheduler.py (+4/-4)
lib/lp/code/xmlrpc/tests/test_codeimportscheduler.py (+5/-5)
lib/lp/codehosting/codeimport/tests/test_worker.py (+16/-16)
lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+6/-6)
lib/lp/codehosting/codeimport/worker.py (+74/-56)
lib/lp/codehosting/codeimport/workermonitor.py (+5/-5)
lib/lp/testing/factory.py (+4/-4)
To merge this branch: bzr merge lp:~cjwatson/launchpad/codeimport-worker-refactor
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+308122@code.launchpad.net

Commit message

Refactor various bits of the code import worker to be less Bazaar-specific.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/xmlrpc/codeimportscheduler.py'
--- lib/lp/code/xmlrpc/codeimportscheduler.py 2016-10-11 13:46:57 +0000
+++ lib/lp/code/xmlrpc/codeimportscheduler.py 2016-10-11 13:46:57 +0000
@@ -69,10 +69,10 @@
69 job = self._getJob(job_id)69 job = self._getJob(job_id)
70 arguments = CodeImportSourceDetails.fromCodeImportJob(70 arguments = CodeImportSourceDetails.fromCodeImportJob(
71 job).asArguments()71 job).asArguments()
72 branch = job.code_import.branch72 target = job.code_import.target
73 branch_url = canonical_url(branch)73 target_url = canonical_url(target)
74 log_file_name = '%s.log' % branch.unique_name[1:].replace('/', '-')74 log_file_name = '%s.log' % target.unique_name[1:].replace('/', '-')
75 return (arguments, branch_url, log_file_name)75 return (arguments, target_url, log_file_name)
7676
77 @return_fault77 @return_fault
78 def _updateHeartbeat(self, job_id, log_tail):78 def _updateHeartbeat(self, job_id, log_tail):
7979
=== modified file 'lib/lp/code/xmlrpc/tests/test_codeimportscheduler.py'
--- lib/lp/code/xmlrpc/tests/test_codeimportscheduler.py 2016-10-11 13:46:57 +0000
+++ lib/lp/code/xmlrpc/tests/test_codeimportscheduler.py 2016-10-11 13:46:57 +0000
@@ -57,20 +57,20 @@
57 self.assertEqual(code_import_job.id, job_id)57 self.assertEqual(code_import_job.id, job_id)
5858
59 def test_getImportDataForJobID(self):59 def test_getImportDataForJobID(self):
60 # getImportDataForJobID returns the worker arguments, branch url and60 # getImportDataForJobID returns the worker arguments, target url and
61 # log file name for an import corresponding to a particular job.61 # log file name for an import corresponding to a particular job.
62 code_import_job = self.makeCodeImportJob(running=True)62 code_import_job = self.makeCodeImportJob(running=True)
63 code_import = removeSecurityProxy(code_import_job).code_import63 code_import = removeSecurityProxy(code_import_job).code_import
64 code_import_arguments, branch_url, log_file_name = \64 code_import_arguments, target_url, log_file_name = \
65 self.api.getImportDataForJobID(code_import_job.id)65 self.api.getImportDataForJobID(code_import_job.id)
66 import_as_arguments = CodeImportSourceDetails.fromCodeImportJob(66 import_as_arguments = CodeImportSourceDetails.fromCodeImportJob(
67 code_import_job).asArguments()67 code_import_job).asArguments()
68 expected_log_file_name = '%s.log' % (68 expected_log_file_name = '%s.log' % (
69 code_import.branch.unique_name[1:].replace('/', '-'))69 code_import.target.unique_name[1:].replace('/', '-'))
70 self.assertEqual(70 self.assertEqual(
71 (import_as_arguments, canonical_url(code_import.branch),71 (import_as_arguments, canonical_url(code_import.target),
72 expected_log_file_name),72 expected_log_file_name),
73 (code_import_arguments, branch_url, log_file_name))73 (code_import_arguments, target_url, log_file_name))
7474
75 def test_getImportDataForJobID_not_found(self):75 def test_getImportDataForJobID_not_found(self):
76 # getImportDataForJobID returns a NoSuchCodeImportJob fault when there76 # getImportDataForJobID returns a NoSuchCodeImportJob fault when there
7777
=== modified file 'lib/lp/codehosting/codeimport/tests/test_worker.py'
--- lib/lp/codehosting/codeimport/tests/test_worker.py 2016-10-11 13:46:57 +0000
+++ lib/lp/codehosting/codeimport/tests/test_worker.py 2016-10-11 13:46:57 +0000
@@ -78,7 +78,7 @@
78 get_default_bazaar_branch_store,78 get_default_bazaar_branch_store,
79 GitImportWorker,79 GitImportWorker,
80 ImportDataStore,80 ImportDataStore,
81 ImportWorker,81 ToBzrImportWorker,
82 )82 )
83from lp.codehosting.safe_open import (83from lp.codehosting.safe_open import (
84 AcceptAnythingPolicy,84 AcceptAnythingPolicy,
@@ -428,7 +428,7 @@
428 source_details = self.factory.makeCodeImportSourceDetails()428 source_details = self.factory.makeCodeImportSourceDetails()
429 # That the remote name is like this is part of the interface of429 # That the remote name is like this is part of the interface of
430 # ImportDataStore.430 # ImportDataStore.
431 remote_name = '%08x.tar.gz' % (source_details.branch_id,)431 remote_name = '%08x.tar.gz' % (source_details.target_id,)
432 local_name = '%s.tar.gz' % (self.factory.getUniqueString(),)432 local_name = '%s.tar.gz' % (self.factory.getUniqueString(),)
433 transport = self.get_transport()433 transport = self.get_transport()
434 transport.put_bytes(remote_name, '')434 transport.put_bytes(remote_name, '')
@@ -442,7 +442,7 @@
442 source_details = self.factory.makeCodeImportSourceDetails()442 source_details = self.factory.makeCodeImportSourceDetails()
443 # That the remote name is like this is part of the interface of443 # That the remote name is like this is part of the interface of
444 # ImportDataStore.444 # ImportDataStore.
445 remote_name = '%08x.tar.gz' % (source_details.branch_id,)445 remote_name = '%08x.tar.gz' % (source_details.target_id,)
446 content = self.factory.getUniqueString()446 content = self.factory.getUniqueString()
447 transport = self.get_transport()447 transport = self.get_transport()
448 transport.put_bytes(remote_name, content)448 transport.put_bytes(remote_name, content)
@@ -457,7 +457,7 @@
457 source_details = self.factory.makeCodeImportSourceDetails()457 source_details = self.factory.makeCodeImportSourceDetails()
458 # That the remote name is like this is part of the interface of458 # That the remote name is like this is part of the interface of
459 # ImportDataStore.459 # ImportDataStore.
460 remote_name = '%08x.tar.gz' % (source_details.branch_id,)460 remote_name = '%08x.tar.gz' % (source_details.target_id,)
461 content = self.factory.getUniqueString()461 content = self.factory.getUniqueString()
462 transport = self.get_transport()462 transport = self.get_transport()
463 transport.put_bytes(remote_name, content)463 transport.put_bytes(remote_name, content)
@@ -481,7 +481,7 @@
481 store.put(local_name)481 store.put(local_name)
482 # That the remote name is like this is part of the interface of482 # That the remote name is like this is part of the interface of
483 # ImportDataStore.483 # ImportDataStore.
484 remote_name = '%08x.tar.gz' % (source_details.branch_id,)484 remote_name = '%08x.tar.gz' % (source_details.target_id,)
485 self.assertEquals(content, transport.get_bytes(remote_name))485 self.assertEquals(content, transport.get_bytes(remote_name))
486486
487 def test_put_ensures_base(self):487 def test_put_ensures_base(self):
@@ -509,7 +509,7 @@
509 store.put(local_name, self.get_transport(local_prefix))509 store.put(local_name, self.get_transport(local_prefix))
510 # That the remote name is like this is part of the interface of510 # That the remote name is like this is part of the interface of
511 # ImportDataStore.511 # ImportDataStore.
512 remote_name = '%08x.tar.gz' % (source_details.branch_id,)512 remote_name = '%08x.tar.gz' % (source_details.target_id,)
513 self.assertEquals(content, transport.get_bytes(remote_name))513 self.assertEquals(content, transport.get_bytes(remote_name))
514514
515515
@@ -585,8 +585,8 @@
585 transport = store.import_data_store._transport585 transport = store.import_data_store._transport
586 source_details = store.import_data_store.source_details586 source_details = store.import_data_store.source_details
587 self.assertTrue(587 self.assertTrue(
588 transport.has('%08x.tar.gz' % source_details.branch_id),588 transport.has('%08x.tar.gz' % source_details.target_id),
589 "Couldn't find '%08x.tar.gz'" % source_details.branch_id)589 "Couldn't find '%08x.tar.gz'" % source_details.target_id)
590590
591 def test_fetchFromArchiveFailure(self):591 def test_fetchFromArchiveFailure(self):
592 # If a tree has not been archived yet, but we try to retrieve it from592 # If a tree has not been archived yet, but we try to retrieve it from
@@ -631,7 +631,7 @@
631631
632 def makeImportWorker(self):632 def makeImportWorker(self):
633 """Make an ImportWorker."""633 """Make an ImportWorker."""
634 return ImportWorker(634 return ToBzrImportWorker(
635 self.source_details, self.get_transport('import_data'),635 self.source_details, self.get_transport('import_data'),
636 self.makeBazaarBranchStore(), logging.getLogger("silent"),636 self.makeBazaarBranchStore(), logging.getLogger("silent"),
637 AcceptAnythingPolicy())637 AcceptAnythingPolicy())
@@ -728,7 +728,7 @@
728 import_worker.import_data_store.put('git.db')728 import_worker.import_data_store.put('git.db')
729 # Make sure there's a Bazaar branch in the branch store.729 # Make sure there's a Bazaar branch in the branch store.
730 branch = self.make_branch('branch')730 branch = self.make_branch('branch')
731 ImportWorker.pushBazaarBranch(import_worker, branch)731 ToBzrImportWorker.pushBazaarBranch(import_worker, branch)
732 # Finally, fetching the tree gets the git.db file too.732 # Finally, fetching the tree gets the git.db file too.
733 branch = import_worker.getBazaarBranch()733 branch = import_worker.getBazaarBranch()
734 self.assertEqual(734 self.assertEqual(
@@ -747,7 +747,7 @@
747 import_worker.import_data_store.put('git-cache.tar.gz')747 import_worker.import_data_store.put('git-cache.tar.gz')
748 # Make sure there's a Bazaar branch in the branch store.748 # Make sure there's a Bazaar branch in the branch store.
749 branch = self.make_branch('branch')749 branch = self.make_branch('branch')
750 ImportWorker.pushBazaarBranch(import_worker, branch)750 ToBzrImportWorker.pushBazaarBranch(import_worker, branch)
751 # Finally, fetching the tree gets the git.db file too.751 # Finally, fetching the tree gets the git.db file too.
752 new_branch = import_worker.getBazaarBranch()752 new_branch = import_worker.getBazaarBranch()
753 self.assertEqual(753 self.assertEqual(
@@ -767,13 +767,13 @@
767 :source_details: A `CodeImportSourceDetails` describing the import.767 :source_details: A `CodeImportSourceDetails` describing the import.
768 """768 """
769 tree_transport = get_transport(config.codeimport.foreign_tree_store)769 tree_transport = get_transport(config.codeimport.foreign_tree_store)
770 prefix = '%08x' % source_details.branch_id770 prefix = '%08x' % source_details.target_id
771 if tree_transport.has('.'):771 if tree_transport.has('.'):
772 for filename in tree_transport.list_dir('.'):772 for filename in tree_transport.list_dir('.'):
773 if filename.startswith(prefix):773 if filename.startswith(prefix):
774 tree_transport.delete(filename)774 tree_transport.delete(filename)
775 branchstore = get_default_bazaar_branch_store()775 branchstore = get_default_bazaar_branch_store()
776 branch_name = '%08x' % source_details.branch_id776 branch_name = '%08x' % source_details.target_id
777 if branchstore.transport.has(branch_name):777 if branchstore.transport.has(branch_name):
778 branchstore.transport.delete_tree(branch_name)778 branchstore.transport.delete_tree(branch_name)
779779
@@ -822,7 +822,7 @@
822 """Get the Bazaar branch 'worker' stored into its BazaarBranchStore.822 """Get the Bazaar branch 'worker' stored into its BazaarBranchStore.
823 """823 """
824 branch_url = worker.bazaar_branch_store._getMirrorURL(824 branch_url = worker.bazaar_branch_store._getMirrorURL(
825 worker.source_details.branch_id)825 worker.source_details.target_id)
826 return Branch.open(branch_url)826 return Branch.open(branch_url)
827827
828 def test_import(self):828 def test_import(self):
@@ -885,7 +885,7 @@
885 self.addCleanup(lambda: shutil.rmtree(tree_path))885 self.addCleanup(lambda: shutil.rmtree(tree_path))
886886
887 branch_url = get_default_bazaar_branch_store()._getMirrorURL(887 branch_url = get_default_bazaar_branch_store()._getMirrorURL(
888 source_details.branch_id)888 source_details.target_id)
889 branch = Branch.open(branch_url)889 branch = Branch.open(branch_url)
890890
891 self.assertEqual(self.foreign_commit_count, branch.revno())891 self.assertEqual(self.foreign_commit_count, branch.revno())
@@ -1345,7 +1345,7 @@
1345 self.assertEqual(1345 self.assertEqual(
1346 CodeImportWorkerExitCode.SUCCESS, worker.run())1346 CodeImportWorkerExitCode.SUCCESS, worker.run())
1347 branch_url = self.bazaar_store._getMirrorURL(1347 branch_url = self.bazaar_store._getMirrorURL(
1348 worker.source_details.branch_id)1348 worker.source_details.target_id)
1349 branch = Branch.open(branch_url)1349 branch = Branch.open(branch_url)
1350 self.assertEquals(self.revid, branch.last_revision())1350 self.assertEquals(self.revid, branch.last_revision())
13511351
13521352
=== modified file 'lib/lp/codehosting/codeimport/tests/test_workermonitor.py'
--- lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2016-10-11 13:46:57 +0000
+++ lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2016-10-11 13:46:57 +0000
@@ -241,21 +241,21 @@
241 return worker_monitor.getWorkerArguments().addCallback(241 return worker_monitor.getWorkerArguments().addCallback(
242 self.assertEqual, args)242 self.assertEqual, args)
243243
244 def test_getWorkerArguments_sets_branch_url_and_logfilename(self):244 def test_getWorkerArguments_sets_target_url_and_logfilename(self):
245 # getWorkerArguments sets the _branch_url (for use in oops reports)245 # getWorkerArguments sets the _target_url (for use in oops reports)
246 # and _log_file_name (for upload to the librarian) attributes on the246 # and _log_file_name (for upload to the librarian) attributes on the
247 # WorkerMonitor from the data returned by getImportDataForJobID.247 # WorkerMonitor from the data returned by getImportDataForJobID.
248 branch_url = self.factory.getUniqueString()248 target_url = self.factory.getUniqueString()
249 log_file_name = self.factory.getUniqueString()249 log_file_name = self.factory.getUniqueString()
250 worker_monitor = self.makeWorkerMonitorWithJob(250 worker_monitor = self.makeWorkerMonitorWithJob(
251 1, (['a'], branch_url, log_file_name))251 1, (['a'], target_url, log_file_name))
252252
253 def check_branch_log(ignored):253 def check_branch_log(ignored):
254 # Looking at the _ attributes here is in slightly poor taste, but254 # Looking at the _ attributes here is in slightly poor taste, but
255 # much much easier than them by logging and parsing an oops, etc.255 # much much easier than them by logging and parsing an oops, etc.
256 self.assertEqual(256 self.assertEqual(
257 (branch_url, log_file_name),257 (target_url, log_file_name),
258 (worker_monitor._branch_url, worker_monitor._log_file_name))258 (worker_monitor._target_url, worker_monitor._log_file_name))
259259
260 return worker_monitor.getWorkerArguments().addCallback(260 return worker_monitor.getWorkerArguments().addCallback(
261 check_branch_log)261 check_branch_log)
262262
=== modified file 'lib/lp/codehosting/codeimport/worker.py'
--- lib/lp/codehosting/codeimport/worker.py 2016-10-11 13:46:57 +0000
+++ lib/lp/codehosting/codeimport/worker.py 2016-10-11 13:46:57 +0000
@@ -15,6 +15,7 @@
15 'ForeignTreeStore',15 'ForeignTreeStore',
16 'GitImportWorker',16 'GitImportWorker',
17 'ImportWorker',17 'ImportWorker',
18 'ToBzrImportWorker',
18 'get_default_bazaar_branch_store',19 'get_default_bazaar_branch_store',
19 ]20 ]
2021
@@ -268,18 +269,20 @@
268 of the information suitable for passing around on executables' command269 of the information suitable for passing around on executables' command
269 lines.270 lines.
270271
271 :ivar branch_id: The id of the branch associated to this code import, used272 :ivar target_id: The id of the Bazaar branch associated with this code
272 for locating the existing import and the foreign tree.273 import, used for locating the existing import and the foreign tree.
273 :ivar rcstype: 'cvs', 'git', 'bzr-svn', 'bzr' as appropriate.274 :ivar rcstype: 'cvs', 'git', 'bzr-svn', 'bzr' as appropriate.
274 :ivar url: The branch URL if rcstype in ['bzr-svn', 'git', 'bzr'], None275 :ivar url: The branch URL if rcstype in ['bzr-svn', 'git', 'bzr'], None
275 otherwise.276 otherwise.
276 :ivar cvs_root: The $CVSROOT if rcstype == 'cvs', None otherwise.277 :ivar cvs_root: The $CVSROOT if rcstype == 'cvs', None otherwise.
277 :ivar cvs_module: The CVS module if rcstype == 'cvs', None otherwise.278 :ivar cvs_module: The CVS module if rcstype == 'cvs', None otherwise.
279 :ivar stacked_on_url: The URL of the branch that the associated branch
280 is stacked on, if any.
278 """281 """
279282
280 def __init__(self, branch_id, rcstype, url=None, cvs_root=None,283 def __init__(self, target_id, rcstype, url=None, cvs_root=None,
281 cvs_module=None, stacked_on_url=None):284 cvs_module=None, stacked_on_url=None):
282 self.branch_id = branch_id285 self.target_id = target_id
283 self.rcstype = rcstype286 self.rcstype = rcstype
284 self.url = url287 self.url = url
285 self.cvs_root = cvs_root288 self.cvs_root = cvs_root
@@ -289,7 +292,7 @@
289 @classmethod292 @classmethod
290 def fromArguments(cls, arguments):293 def fromArguments(cls, arguments):
291 """Convert command line-style arguments to an instance."""294 """Convert command line-style arguments to an instance."""
292 branch_id = int(arguments.pop(0))295 target_id = int(arguments.pop(0))
293 rcstype = arguments.pop(0)296 rcstype = arguments.pop(0)
294 if rcstype in ['bzr-svn', 'git', 'bzr']:297 if rcstype in ['bzr-svn', 'git', 'bzr']:
295 url = arguments.pop(0)298 url = arguments.pop(0)
@@ -305,34 +308,34 @@
305 else:308 else:
306 raise AssertionError("Unknown rcstype %r." % rcstype)309 raise AssertionError("Unknown rcstype %r." % rcstype)
307 return cls(310 return cls(
308 branch_id, rcstype, url, cvs_root, cvs_module, stacked_on_url)311 target_id, rcstype, url, cvs_root, cvs_module, stacked_on_url)
309312
310 @classmethod313 @classmethod
311 def fromCodeImportJob(cls, job):314 def fromCodeImportJob(cls, job):
312 """Convert a `CodeImportJob` to an instance."""315 """Convert a `CodeImportJob` to an instance."""
313 code_import = job.code_import316 code_import = job.code_import
314 branch = code_import.branch317 target = code_import.target
315 if branch.stacked_on is not None and not branch.stacked_on.private:318 if target.stacked_on is not None and not target.stacked_on.private:
316 stacked_path = branch_id_alias(branch.stacked_on)319 stacked_path = branch_id_alias(target.stacked_on)
317 stacked_on_url = compose_public_url('http', stacked_path)320 stacked_on_url = compose_public_url('http', stacked_path)
318 else:321 else:
319 stacked_on_url = None322 stacked_on_url = None
320 if code_import.rcs_type == RevisionControlSystems.BZR_SVN:323 if code_import.rcs_type == RevisionControlSystems.BZR_SVN:
321 return cls(324 return cls(
322 branch.id, 'bzr-svn', str(code_import.url),325 target.id, 'bzr-svn', str(code_import.url),
323 stacked_on_url=stacked_on_url)326 stacked_on_url=stacked_on_url)
324 elif code_import.rcs_type == RevisionControlSystems.CVS:327 elif code_import.rcs_type == RevisionControlSystems.CVS:
325 return cls(328 return cls(
326 branch.id, 'cvs',329 target.id, 'cvs',
327 cvs_root=str(code_import.cvs_root),330 cvs_root=str(code_import.cvs_root),
328 cvs_module=str(code_import.cvs_module))331 cvs_module=str(code_import.cvs_module))
329 elif code_import.rcs_type == RevisionControlSystems.GIT:332 elif code_import.rcs_type == RevisionControlSystems.GIT:
330 return cls(333 return cls(
331 branch.id, 'git', str(code_import.url),334 target.id, 'git', str(code_import.url),
332 stacked_on_url=stacked_on_url)335 stacked_on_url=stacked_on_url)
333 elif code_import.rcs_type == RevisionControlSystems.BZR:336 elif code_import.rcs_type == RevisionControlSystems.BZR:
334 return cls(337 return cls(
335 branch.id, 'bzr', str(code_import.url),338 target.id, 'bzr', str(code_import.url),
336 stacked_on_url=stacked_on_url)339 stacked_on_url=stacked_on_url)
337 else:340 else:
338 raise AssertionError("Unknown rcstype %r." % code_import.rcs_type)341 raise AssertionError("Unknown rcstype %r." % code_import.rcs_type)
@@ -340,7 +343,7 @@
340 def asArguments(self):343 def asArguments(self):
341 """Return a list of arguments suitable for passing to a child process.344 """Return a list of arguments suitable for passing to a child process.
342 """345 """
343 result = [str(self.branch_id), self.rcstype]346 result = [str(self.target_id), self.rcstype]
344 if self.rcstype in ['bzr-svn', 'git', 'bzr']:347 if self.rcstype in ['bzr-svn', 'git', 'bzr']:
345 result.append(self.url)348 result.append(self.url)
346 if self.stacked_on_url is not None:349 if self.stacked_on_url is not None:
@@ -374,7 +377,7 @@
374 """377 """
375 self.source_details = source_details378 self.source_details = source_details
376 self._transport = transport379 self._transport = transport
377 self._branch_id = source_details.branch_id380 self._target_id = source_details.target_id
378381
379 def _getRemoteName(self, local_name):382 def _getRemoteName(self, local_name):
380 """Convert `local_name` to the name used to store a file.383 """Convert `local_name` to the name used to store a file.
@@ -394,7 +397,7 @@
394 if dot_index < 0:397 if dot_index < 0:
395 raise AssertionError("local_name must have an extension.")398 raise AssertionError("local_name must have an extension.")
396 ext = local_name[dot_index:]399 ext = local_name[dot_index:]
397 return '%08x%s' % (self._branch_id, ext)400 return '%08x%s' % (self._target_id, ext)
398401
399 def fetch(self, filename, dest_transport=None):402 def fetch(self, filename, dest_transport=None):
400 """Retrieve `filename` from the store.403 """Retrieve `filename` from the store.
@@ -505,57 +508,23 @@
505class ImportWorker:508class ImportWorker:
506 """Oversees the actual work of a code import."""509 """Oversees the actual work of a code import."""
507510
508 # Where the Bazaar working tree will be stored.511 def __init__(self, source_details, logger, opener_policy):
509 BZR_BRANCH_PATH = 'bzr_branch'
510
511 # Should `getBazaarBranch` create a working tree?
512 needs_bzr_tree = True
513
514 required_format = BzrDirFormat.get_default_format()
515
516 def __init__(self, source_details, import_data_transport,
517 bazaar_branch_store, logger, opener_policy):
518 """Construct an `ImportWorker`.512 """Construct an `ImportWorker`.
519513
520 :param source_details: A `CodeImportSourceDetails` object.514 :param source_details: A `CodeImportSourceDetails` object.
521 :param bazaar_branch_store: A `BazaarBranchStore`. The import worker
522 uses this to fetch and store the Bazaar branches that are created
523 and updated during the import process.
524 :param logger: A `Logger` to pass to cscvs.515 :param logger: A `Logger` to pass to cscvs.
525 :param opener_policy: Policy object that decides what branches can516 :param opener_policy: Policy object that decides what branches can
526 be imported517 be imported
527 """518 """
528 self.source_details = source_details519 self.source_details = source_details
529 self.bazaar_branch_store = bazaar_branch_store
530 self.import_data_store = ImportDataStore(
531 import_data_transport, self.source_details)
532 self._logger = logger520 self._logger = logger
533 self._opener_policy = opener_policy521 self._opener_policy = opener_policy
534522
535 def getBazaarBranch(self):
536 """Return the Bazaar `Branch` that we are importing into."""
537 if os.path.isdir(self.BZR_BRANCH_PATH):
538 shutil.rmtree(self.BZR_BRANCH_PATH)
539 return self.bazaar_branch_store.pull(
540 self.source_details.branch_id, self.BZR_BRANCH_PATH,
541 self.required_format, self.needs_bzr_tree,
542 stacked_on_url=self.source_details.stacked_on_url)
543
544 def pushBazaarBranch(self, bazaar_branch):
545 """Push the updated Bazaar branch to the server.
546
547 :return: True if revisions were transferred.
548 """
549 return self.bazaar_branch_store.push(
550 self.source_details.branch_id, bazaar_branch,
551 self.required_format,
552 stacked_on_url=self.source_details.stacked_on_url)
553
554 def getWorkingDirectory(self):523 def getWorkingDirectory(self):
555 """The directory we should change to and store all scratch files in.524 """The directory we should change to and store all scratch files in.
556 """525 """
557 base = config.codeimportworker.working_directory_root526 base = config.codeimportworker.working_directory_root
558 dirname = 'worker-for-branch-%s' % self.source_details.branch_id527 dirname = 'worker-for-branch-%s' % self.source_details.target_id
559 return os.path.join(base, dirname)528 return os.path.join(base, dirname)
560529
561 def run(self):530 def run(self):
@@ -594,7 +563,56 @@
594 raise NotImplementedError()563 raise NotImplementedError()
595564
596565
597class CSCVSImportWorker(ImportWorker):566class ToBzrImportWorker(ImportWorker):
567 """Oversees the actual work of a code import to Bazaar."""
568
569 # Where the Bazaar working tree will be stored.
570 BZR_BRANCH_PATH = 'bzr_branch'
571
572 # Should `getBazaarBranch` create a working tree?
573 needs_bzr_tree = True
574
575 required_format = BzrDirFormat.get_default_format()
576
577 def __init__(self, source_details, import_data_transport,
578 bazaar_branch_store, logger, opener_policy):
579 """Construct a `ToBzrImportWorker`.
580
581 :param source_details: A `CodeImportSourceDetails` object.
582 :param bazaar_branch_store: A `BazaarBranchStore`. The import worker
583 uses this to fetch and store the Bazaar branches that are created
584 and updated during the import process.
585 :param logger: A `Logger` to pass to cscvs.
586 :param opener_policy: Policy object that decides what branches can
587 be imported
588 """
589 super(ToBzrImportWorker, self).__init__(
590 source_details, logger, opener_policy)
591 self.bazaar_branch_store = bazaar_branch_store
592 self.import_data_store = ImportDataStore(
593 import_data_transport, self.source_details)
594
595 def getBazaarBranch(self):
596 """Return the Bazaar `Branch` that we are importing into."""
597 if os.path.isdir(self.BZR_BRANCH_PATH):
598 shutil.rmtree(self.BZR_BRANCH_PATH)
599 return self.bazaar_branch_store.pull(
600 self.source_details.target_id, self.BZR_BRANCH_PATH,
601 self.required_format, self.needs_bzr_tree,
602 stacked_on_url=self.source_details.stacked_on_url)
603
604 def pushBazaarBranch(self, bazaar_branch):
605 """Push the updated Bazaar branch to the server.
606
607 :return: True if revisions were transferred.
608 """
609 return self.bazaar_branch_store.push(
610 self.source_details.target_id, bazaar_branch,
611 self.required_format,
612 stacked_on_url=self.source_details.stacked_on_url)
613
614
615class CSCVSImportWorker(ToBzrImportWorker):
598 """An ImportWorker for imports that use CSCVS.616 """An ImportWorker for imports that use CSCVS.
599617
600 As well as invoking cscvs to do the import, this class also needs to618 As well as invoking cscvs to do the import, this class also needs to
@@ -674,7 +692,7 @@
674 return CodeImportWorkerExitCode.SUCCESS_NOCHANGE692 return CodeImportWorkerExitCode.SUCCESS_NOCHANGE
675693
676694
677class PullingImportWorker(ImportWorker):695class PullingImportWorker(ToBzrImportWorker):
678 """An import worker for imports that can be done by a bzr plugin.696 """An import worker for imports that can be done by a bzr plugin.
679697
680 Subclasses need to implement `probers`.698 Subclasses need to implement `probers`.
@@ -806,7 +824,7 @@
806 return config.codeimport.git_revisions_import_limit824 return config.codeimport.git_revisions_import_limit
807825
808 def getBazaarBranch(self):826 def getBazaarBranch(self):
809 """See `ImportWorker.getBazaarBranch`.827 """See `ToBzrImportWorker.getBazaarBranch`.
810828
811 In addition to the superclass' behaviour, we retrieve bzr-git's829 In addition to the superclass' behaviour, we retrieve bzr-git's
812 caches, both legacy and modern, from the import data store and put830 caches, both legacy and modern, from the import data store and put
@@ -828,7 +846,7 @@
828 return branch846 return branch
829847
830 def pushBazaarBranch(self, bazaar_branch):848 def pushBazaarBranch(self, bazaar_branch):
831 """See `ImportWorker.pushBazaarBranch`.849 """See `ToBzrImportWorker.pushBazaarBranch`.
832850
833 In addition to the superclass' behaviour, we store bzr-git's cache851 In addition to the superclass' behaviour, we store bzr-git's cache
834 directory at .bzr/repository/git in the import data store.852 directory at .bzr/repository/git in the import data store.
835853
=== modified file 'lib/lp/codehosting/codeimport/workermonitor.py'
--- lib/lp/codehosting/codeimport/workermonitor.py 2013-01-07 02:40:55 +0000
+++ lib/lp/codehosting/codeimport/workermonitor.py 2016-10-11 13:46:57 +0000
@@ -134,7 +134,7 @@
134 self.codeimport_endpoint = codeimport_endpoint134 self.codeimport_endpoint = codeimport_endpoint
135 self._call_finish_job = True135 self._call_finish_job = True
136 self._log_file = tempfile.TemporaryFile()136 self._log_file = tempfile.TemporaryFile()
137 self._branch_url = None137 self._target_url = None
138 self._log_file_name = 'no-name-set.txt'138 self._log_file_name = 'no-name-set.txt'
139 self._access_policy = access_policy139 self._access_policy = access_policy
140140
@@ -143,7 +143,7 @@
143 context = {143 context = {
144 'twisted_failure': failure,144 'twisted_failure': failure,
145 'http_request': errorlog.ScriptRequest(145 'http_request': errorlog.ScriptRequest(
146 [('code_import_job_id', self._job_id)], self._branch_url),146 [('code_import_job_id', self._job_id)], self._target_url),
147 }147 }
148 report = config.create(context)148 report = config.create(context)
149149
@@ -169,15 +169,15 @@
169 def getWorkerArguments(self):169 def getWorkerArguments(self):
170 """Get arguments for the worker for the import we are working on.170 """Get arguments for the worker for the import we are working on.
171171
172 This also sets the _branch_url and _log_file_name attributes for use172 This also sets the _target_url and _log_file_name attributes for use
173 in the _logOopsFromFailure and finishJob methods respectively.173 in the _logOopsFromFailure and finishJob methods respectively.
174 """174 """
175 deferred = self.codeimport_endpoint.callRemote(175 deferred = self.codeimport_endpoint.callRemote(
176 'getImportDataForJobID', self._job_id)176 'getImportDataForJobID', self._job_id)
177177
178 def _processResult(result):178 def _processResult(result):
179 code_import_arguments, branch_url, log_file_name = result179 code_import_arguments, target_url, log_file_name = result
180 self._branch_url = branch_url180 self._target_url = target_url
181 self._log_file_name = log_file_name181 self._log_file_name = log_file_name
182 self._logger.info(182 self._logger.info(
183 'Found source details: %s', code_import_arguments)183 'Found source details: %s', code_import_arguments)
184184
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2016-10-03 17:00:56 +0000
+++ lib/lp/testing/factory.py 2016-10-11 13:46:57 +0000
@@ -492,11 +492,11 @@
492 epoch = datetime(2009, 1, 1, tzinfo=pytz.UTC)492 epoch = datetime(2009, 1, 1, tzinfo=pytz.UTC)
493 return epoch + timedelta(minutes=self.getUniqueInteger())493 return epoch + timedelta(minutes=self.getUniqueInteger())
494494
495 def makeCodeImportSourceDetails(self, branch_id=None, rcstype=None,495 def makeCodeImportSourceDetails(self, target_id=None, rcstype=None,
496 url=None, cvs_root=None, cvs_module=None,496 url=None, cvs_root=None, cvs_module=None,
497 stacked_on_url=None):497 stacked_on_url=None):
498 if branch_id is None:498 if target_id is None:
499 branch_id = self.getUniqueInteger()499 target_id = self.getUniqueInteger()
500 if rcstype is None:500 if rcstype is None:
501 rcstype = 'bzr-svn'501 rcstype = 'bzr-svn'
502 if rcstype in ['bzr-svn', 'bzr']:502 if rcstype in ['bzr-svn', 'bzr']:
@@ -516,7 +516,7 @@
516 else:516 else:
517 raise AssertionError("Unknown rcstype %r." % rcstype)517 raise AssertionError("Unknown rcstype %r." % rcstype)
518 return CodeImportSourceDetails(518 return CodeImportSourceDetails(
519 branch_id, rcstype, url, cvs_root, cvs_module,519 target_id, rcstype, url, cvs_root, cvs_module,
520 stacked_on_url=stacked_on_url)520 stacked_on_url=stacked_on_url)
521521
522522