Merge lp:~mwhudson/launchpad/code-import-optimizations into lp:launchpad

Proposed by Michael Hudson-Doyle
Status: Merged
Approved by: Tim Penhey
Approved revision: 10680
Merged at revision: not available
Proposed branch: lp:~mwhudson/launchpad/code-import-optimizations
Merge into: lp:launchpad
Diff against target: 555 lines (+176/-126)
2 files modified
lib/lp/codehosting/codeimport/tests/test_worker.py (+87/-52)
lib/lp/codehosting/codeimport/worker.py (+89/-74)
To merge this branch: bzr merge lp:~mwhudson/launchpad/code-import-optimizations
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Review via email: mp+23206@code.launchpad.net

Commit message

Improve logging during code imports and don't build a working tree if not needed, both of which will help with large imports timing out on startup

Description of the change

Hi,

This branch should fix some very large foreign branch imports timing out in two ways:

1) There was no progress reporting during fetching the branch from the store or building the tree, so I moved the initial fetch into the block that has our custom ui factory installed.

2) Building the working tree was a waste of time anyway for foreign branch imports, so we no longer do that. This required the bulk of the changes from a textual point of view, to talk about branches where previously we talked about trees, but I think the result is better even if it wasn't faster.

I also add a few logging calls as suggested in bug 559808.

Cheers,
mwh

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

The change looks fine.

It does get me wondering a bit why we didn't seem to get any logging when it was pushing the branch to the central store before. Thanks for adding the job started and finished logging bits too.

I agree that it makes more sense to use branch rather than working tree in the workers.

review: Approve
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

On 12/04/10 14:16, Tim Penhey wrote:
> Review: Approve
> The change looks fine.

Thanks.

> It does get me wondering a bit why we didn't seem to get any logging when it was pushing the branch to the central store before. Thanks for adding the job started and finished logging bits too.

I think we do actually get logging when pushing to the central store,
but the new log lines should let us see what comes from where :-)

> I agree that it makes more sense to use branch rather than working tree in the workers.

Cool.

Cheers,
mwh

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/codehosting/codeimport/tests/test_worker.py'
--- lib/lp/codehosting/codeimport/tests/test_worker.py 2010-04-09 04:39:38 +0000
+++ lib/lp/codehosting/codeimport/tests/test_worker.py 2010-04-12 01:54:17 +0000
@@ -19,7 +19,7 @@
19from bzrlib.tests import TestCaseWithTransport19from bzrlib.tests import TestCaseWithTransport
20from bzrlib.transport import get_transport20from bzrlib.transport import get_transport
21from bzrlib.upgrade import upgrade21from bzrlib.upgrade import upgrade
22from bzrlib.urlutils import join as urljoin22from bzrlib.urlutils import join as urljoin, local_path_from_url
2323
24from CVS import Repository, tree as CVSTree24from CVS import Repository, tree as CVSTree
2525
@@ -120,22 +120,57 @@
120120
121 def test_getNewBranch(self):121 def test_getNewBranch(self):
122 # If there's no Bazaar branch of this id, then pull creates a new122 # If there's no Bazaar branch of this id, then pull creates a new
123 # Bazaar working tree.123 # Bazaar branch.
124 store = self.makeBranchStore()124 store = self.makeBranchStore()
125 bzr_working_tree = store.pull(125 bzr_branch = store.pull(
126 self.arbitrary_branch_id, self.temp_dir, default_format)126 self.arbitrary_branch_id, self.temp_dir, default_format)
127 self.assertEqual([], bzr_working_tree.branch.revision_history())127 self.assertEqual([], bzr_branch.revision_history())
128
129 def test_getNewBranch_without_tree(self):
130 # If pull() with needs_tree=False creates a new branch, it doesn't
131 # create a working tree.
132 store = self.makeBranchStore()
133 bzr_branch = store.pull(
134 self.arbitrary_branch_id, self.temp_dir, default_format, False)
135 self.assertFalse(bzr_branch.bzrdir.has_workingtree())
136
137 def test_getNewBranch_with_tree(self):
138 # If pull() with needs_tree=True creates a new branch, it creates a
139 # working tree.
140 store = self.makeBranchStore()
141 bzr_branch = store.pull(
142 self.arbitrary_branch_id, self.temp_dir, default_format, True)
143 self.assertTrue(bzr_branch.bzrdir.has_workingtree())
128144
129 def test_pushBranchThenPull(self):145 def test_pushBranchThenPull(self):
130 # After we've pushed up a branch to the store, we can then pull it146 # After we've pushed up a branch to the store, we can then pull it
131 # from the store.147 # from the store.
132 store = self.makeBranchStore()148 store = self.makeBranchStore()
133 tree = create_branch_with_one_revision('original')149 tree = create_branch_with_one_revision('original')
134 store.push(self.arbitrary_branch_id, tree, default_format)150 store.push(self.arbitrary_branch_id, tree.branch, default_format)
135 new_tree = store.pull(151 new_branch = store.pull(
136 self.arbitrary_branch_id, self.temp_dir, default_format)152 self.arbitrary_branch_id, self.temp_dir, default_format)
137 self.assertEqual(153 self.assertEqual(
138 tree.branch.last_revision(), new_tree.branch.last_revision())154 tree.branch.last_revision(), new_branch.last_revision())
155
156 def test_pull_without_needs_tree_doesnt_create_tree(self):
157 # pull with needs_tree=False doesn't spend the time to create a
158 # working tree.
159 store = self.makeBranchStore()
160 tree = create_branch_with_one_revision('original')
161 store.push(self.arbitrary_branch_id, tree.branch, default_format)
162 new_branch = store.pull(
163 self.arbitrary_branch_id, self.temp_dir, default_format, False)
164 self.assertFalse(new_branch.bzrdir.has_workingtree())
165
166 def test_pull_needs_tree_creates_tree(self):
167 # pull with needs_tree=True creates a working tree.
168 store = self.makeBranchStore()
169 tree = create_branch_with_one_revision('original')
170 store.push(self.arbitrary_branch_id, tree.branch, default_format)
171 new_branch = store.pull(
172 self.arbitrary_branch_id, self.temp_dir, default_format, True)
173 self.assertTrue(new_branch.bzrdir.has_workingtree())
139174
140 # XXX Tim Penhey 2009-09-18 bug 432217 Automatic upgrade of import175 # XXX Tim Penhey 2009-09-18 bug 432217 Automatic upgrade of import
141 # branches disabled. Need an orderly upgrade process.176 # branches disabled. Need an orderly upgrade process.
@@ -188,21 +223,21 @@
188 # store.223 # store.
189 store = self.makeBranchStore()224 store = self.makeBranchStore()
190 tree = create_branch_with_one_revision('original')225 tree = create_branch_with_one_revision('original')
191 store.push(self.arbitrary_branch_id, tree, default_format)226 store.push(self.arbitrary_branch_id, tree.branch, default_format)
192 store.push(self.arbitrary_branch_id, tree, default_format)227 store.push(self.arbitrary_branch_id, tree.branch, default_format)
193 new_tree = store.pull(228 new_branch = store.pull(
194 self.arbitrary_branch_id, self.temp_dir, default_format)229 self.arbitrary_branch_id, self.temp_dir, default_format)
195 self.assertEqual(230 self.assertEqual(
196 tree.branch.last_revision(), new_tree.branch.last_revision())231 tree.branch.last_revision(), new_branch.last_revision())
197232
198 def test_push_divergant_branches(self):233 def test_push_divergant_branches(self):
199 # push() uses overwrite=True, so divergent branches (rebased) can be234 # push() uses overwrite=True, so divergent branches (rebased) can be
200 # pushed.235 # pushed.
201 store = self.makeBranchStore()236 store = self.makeBranchStore()
202 tree = create_branch_with_one_revision('original')237 tree = create_branch_with_one_revision('original')
203 store.push(self.arbitrary_branch_id, tree, default_format)238 store.push(self.arbitrary_branch_id, tree.branch, default_format)
204 tree = create_branch_with_one_revision('divergant')239 tree = create_branch_with_one_revision('divergant')
205 store.push(self.arbitrary_branch_id, tree, default_format)240 store.push(self.arbitrary_branch_id, tree.branch, default_format)
206241
207 def fetchBranch(self, from_url, target_path):242 def fetchBranch(self, from_url, target_path):
208 """Pull a branch from `from_url` to `target_path`.243 """Pull a branch from `from_url` to `target_path`.
@@ -221,7 +256,7 @@
221 # doesn't already exist.256 # doesn't already exist.
222 store = BazaarBranchStore(self.get_transport('doesntexist'))257 store = BazaarBranchStore(self.get_transport('doesntexist'))
223 tree = create_branch_with_one_revision('original')258 tree = create_branch_with_one_revision('original')
224 store.push(self.arbitrary_branch_id, tree, default_format)259 store.push(self.arbitrary_branch_id, tree.branch, default_format)
225 self.assertIsDirectory('doesntexist', self.get_transport())260 self.assertIsDirectory('doesntexist', self.get_transport())
226261
227 def test_storedLocation(self):262 def test_storedLocation(self):
@@ -229,12 +264,12 @@
229 # the BazaarBranchStore's transport.264 # the BazaarBranchStore's transport.
230 store = self.makeBranchStore()265 store = self.makeBranchStore()
231 tree = create_branch_with_one_revision('original')266 tree = create_branch_with_one_revision('original')
232 store.push(self.arbitrary_branch_id, tree, default_format)267 store.push(self.arbitrary_branch_id, tree.branch, default_format)
233 new_tree = self.fetchBranch(268 new_branch = self.fetchBranch(
234 urljoin(store.transport.base, '%08x' % self.arbitrary_branch_id),269 urljoin(store.transport.base, '%08x' % self.arbitrary_branch_id),
235 'new_tree')270 'new_tree')
236 self.assertEqual(271 self.assertEqual(
237 tree.branch.last_revision(), new_tree.branch.last_revision())272 tree.branch.last_revision(), new_branch.last_revision())
238273
239 def test_sftpPrefix(self):274 def test_sftpPrefix(self):
240 # Since branches are mirrored by importd via sftp, _getMirrorURL must275 # Since branches are mirrored by importd via sftp, _getMirrorURL must
@@ -270,15 +305,14 @@
270 None, None, [('add', ('', 'root-id', 'directory', ''))])305 None, None, [('add', ('', 'root-id', 'directory', ''))])
271 revid1 = builder.build_snapshot(None, [revid], [])306 revid1 = builder.build_snapshot(None, [revid], [])
272 revid2 = builder.build_snapshot(None, [revid], [])307 revid2 = builder.build_snapshot(None, [revid], [])
273 branch = builder.get_branch()
274 source_tree = branch.bzrdir.create_workingtree()
275 store = self.makeBranchStore()308 store = self.makeBranchStore()
276 store.push(self.arbitrary_branch_id, source_tree, default_format)309 store.push(
277 retrieved_tree = store.pull(310 self.arbitrary_branch_id, builder.get_branch(), default_format)
311 retrieved_branch = store.pull(
278 self.arbitrary_branch_id, 'pulled', default_format)312 self.arbitrary_branch_id, 'pulled', default_format)
279 self.assertEqual(313 self.assertEqual(
280 set([revid, revid1, revid2]),314 set([revid, revid1, revid2]),
281 set(retrieved_tree.branch.repository.all_revision_ids()))315 set(retrieved_branch.repository.all_revision_ids()))
282316
283317
284class TestImportDataStore(WorkerTest):318class TestImportDataStore(WorkerTest):
@@ -532,21 +566,21 @@
532 worker = self.makeImportWorker()566 worker = self.makeImportWorker()
533 self.assertEqual(self.source_details, worker.source_details)567 self.assertEqual(self.source_details, worker.source_details)
534568
535 def test_getBazaarWorkingTreeMakesEmptyTree(self):569 def test_getBazaarWorkingBranchMakesEmptyBranch(self):
536 # getBazaarWorkingTree returns a brand-new working tree for an initial570 # getBazaarBranch returns a brand-new working tree for an initial
537 # import.571 # import.
538 worker = self.makeImportWorker()572 worker = self.makeImportWorker()
539 bzr_working_tree = worker.getBazaarWorkingTree()573 bzr_branch = worker.getBazaarBranch()
540 self.assertEqual([], bzr_working_tree.branch.revision_history())574 self.assertEqual([], bzr_branch.revision_history())
541575
542 def test_bazaarWorkingTreeLocation(self):576 def test_bazaarBranchLocation(self):
543 # getBazaarWorkingTree makes the working tree under the current577 # getBazaarBranch makes the working tree under the current working
544 # working directory.578 # directory.
545 worker = self.makeImportWorker()579 worker = self.makeImportWorker()
546 bzr_working_tree = worker.getBazaarWorkingTree()580 bzr_branch = worker.getBazaarBranch()
547 self.assertIsSameRealPath(581 self.assertIsSameRealPath(
548 os.path.abspath(worker.BZR_WORKING_TREE_PATH),582 os.path.abspath(worker.BZR_BRANCH_PATH),
549 os.path.abspath(bzr_working_tree.basedir))583 os.path.abspath(local_path_from_url(bzr_branch.base)))
550584
551585
552class TestCSCVSWorker(WorkerTest):586class TestCSCVSWorker(WorkerTest):
@@ -591,22 +625,22 @@
591 source_details, self.get_transport('import_data'),625 source_details, self.get_transport('import_data'),
592 self.makeBazaarBranchStore(), logging.getLogger("silent"))626 self.makeBazaarBranchStore(), logging.getLogger("silent"))
593627
594 def test_pushBazaarWorkingTree_saves_git_cache(self):628 def test_pushBazaarBranch_saves_git_cache(self):
595 # GitImportWorker.pushBazaarWorkingTree saves a tarball of the git629 # GitImportWorker.pushBazaarBranch saves a tarball of the git cache
596 # cache from the tree's repository in the worker's ImportDataStore.630 # from the tree's repository in the worker's ImportDataStore.
597 content = self.factory.getUniqueString()631 content = self.factory.getUniqueString()
598 tree = self.make_branch_and_tree('.')632 branch = self.make_branch('.')
599 tree.branch.repository._transport.mkdir('git')633 branch.repository._transport.mkdir('git')
600 tree.branch.repository._transport.put_bytes('git/cache', content)634 branch.repository._transport.put_bytes('git/cache', content)
601 import_worker = self.makeImportWorker()635 import_worker = self.makeImportWorker()
602 import_worker.pushBazaarWorkingTree(tree)636 import_worker.pushBazaarBranch(branch)
603 import_worker.import_data_store.fetch('git-cache.tar.gz')637 import_worker.import_data_store.fetch('git-cache.tar.gz')
604 extract_tarball('git-cache.tar.gz', '.')638 extract_tarball('git-cache.tar.gz', '.')
605 self.assertEqual(content, open('cache').read())639 self.assertEqual(content, open('cache').read())
606640
607 def test_getBazaarWorkingTree_fetches_legacy_git_db(self):641 def test_getBazaarBranch_fetches_legacy_git_db(self):
608 # GitImportWorker.getBazaarWorkingTree fetches the legacy git.db file,642 # GitImportWorker.getBazaarBranch fetches the legacy git.db file, if
609 # if present, from the worker's ImportDataStore into the tree's643 # present, from the worker's ImportDataStore into the tree's
610 # repository.644 # repository.
611 import_worker = self.makeImportWorker()645 import_worker = self.makeImportWorker()
612 # Store the git.db file in the store.646 # Store the git.db file in the store.
@@ -614,15 +648,15 @@
614 open('git.db', 'w').write(content)648 open('git.db', 'w').write(content)
615 import_worker.import_data_store.put('git.db')649 import_worker.import_data_store.put('git.db')
616 # Make sure there's a Bazaar branch in the branch store.650 # Make sure there's a Bazaar branch in the branch store.
617 tree = self.make_branch_and_tree('tree')651 branch = self.make_branch('branch')
618 ImportWorker.pushBazaarWorkingTree(import_worker, tree)652 ImportWorker.pushBazaarBranch(import_worker, branch)
619 # Finally, fetching the tree gets the git.db file too.653 # Finally, fetching the tree gets the git.db file too.
620 tree = import_worker.getBazaarWorkingTree()654 branch = import_worker.getBazaarBranch()
621 self.assertEqual(655 self.assertEqual(
622 content, tree.branch.repository._transport.get('git.db').read())656 content, branch.repository._transport.get('git.db').read())
623657
624 def test_getBazaarWorkingTree_fetches_git_cache(self):658 def test_getBazaarBranch_fetches_git_cache(self):
625 # GitImportWorker.getBazaarWorkingTree fetches the tarball of the git659 # GitImportWorker.getBazaarBranch fetches the tarball of the git
626 # cache from the worker's ImportDataStore and expands it into the660 # cache from the worker's ImportDataStore and expands it into the
627 # tree's repository.661 # tree's repository.
628 import_worker = self.makeImportWorker()662 import_worker = self.makeImportWorker()
@@ -633,12 +667,13 @@
633 create_tarball('cache', 'git-cache.tar.gz')667 create_tarball('cache', 'git-cache.tar.gz')
634 import_worker.import_data_store.put('git-cache.tar.gz')668 import_worker.import_data_store.put('git-cache.tar.gz')
635 # Make sure there's a Bazaar branch in the branch store.669 # Make sure there's a Bazaar branch in the branch store.
636 tree = self.make_branch_and_tree('tree')670 branch = self.make_branch('branch')
637 ImportWorker.pushBazaarWorkingTree(import_worker, tree)671 ImportWorker.pushBazaarBranch(import_worker, branch)
638 # Finally, fetching the tree gets the git.db file too.672 # Finally, fetching the tree gets the git.db file too.
639 tree = import_worker.getBazaarWorkingTree()673 new_branch = import_worker.getBazaarBranch()
640 self.assertEqual(674 self.assertEqual(
641 content, tree.branch.repository._transport.get('git/git-cache').read())675 content,
676 new_branch.repository._transport.get('git/git-cache').read())
642677
643678
644def clean_up_default_stores_for_import(source_details):679def clean_up_default_stores_for_import(source_details):
645680
=== modified file 'lib/lp/codehosting/codeimport/worker.py'
--- lib/lp/codehosting/codeimport/worker.py 2010-04-09 04:39:38 +0000
+++ lib/lp/codehosting/codeimport/worker.py 2010-04-12 01:54:17 +0000
@@ -64,17 +64,22 @@
64 """Return the URL that `db_branch` is stored at."""64 """Return the URL that `db_branch` is stored at."""
65 return urljoin(self.transport.base, '%08x' % db_branch_id)65 return urljoin(self.transport.base, '%08x' % db_branch_id)
6666
67 def pull(self, db_branch_id, target_path, required_format):67 def pull(self, db_branch_id, target_path, required_format,
68 """Pull down the Bazaar branch for `code_import` to `target_path`.68 needs_tree=False):
69 """Pull down the Bazaar branch of an import to `target_path`.
6970
70 :return: A Bazaar working tree for the branch of `code_import`.71 :return: A Bazaar branch for the code import corresponding to the
72 database branch with id `db_branch_id`.
71 """73 """
72 remote_url = self._getMirrorURL(db_branch_id)74 remote_url = self._getMirrorURL(db_branch_id)
73 try:75 try:
74 remote_bzr_dir = BzrDir.open(remote_url)76 remote_bzr_dir = BzrDir.open(remote_url)
75 except NotBranchError:77 except NotBranchError:
76 return BzrDir.create_standalone_workingtree(78 local_branch = BzrDir.create_branch_and_repo(
77 target_path, required_format)79 target_path, format=required_format)
80 if needs_tree:
81 local_branch.bzrdir.create_workingtree()
82 return local_branch
78 # XXX Tim Penhey 2009-09-18 bug 432217 Automatic upgrade of import83 # XXX Tim Penhey 2009-09-18 bug 432217 Automatic upgrade of import
79 # branches disabled. Need an orderly upgrade process.84 # branches disabled. Need an orderly upgrade process.
80 if False and remote_bzr_dir.needs_format_conversion(85 if False and remote_bzr_dir.needs_format_conversion(
@@ -84,33 +89,33 @@
84 except NoSuchFile:89 except NoSuchFile:
85 pass90 pass
86 upgrade(remote_url, required_format)91 upgrade(remote_url, required_format)
87 local_bzr_dir = remote_bzr_dir.sprout(target_path)92 local_branch = remote_bzr_dir.sprout(
93 target_path, create_tree_if_local=needs_tree).open_branch()
88 # Because of the way we do incremental imports, there may be revisions94 # Because of the way we do incremental imports, there may be revisions
89 # in the branch's repo that are not in the ancestry of the branch tip.95 # in the branch's repo that are not in the ancestry of the branch tip.
90 # We need to transfer them too.96 # We need to transfer them too.
91 local_bzr_dir.open_repository().fetch(97 local_branch.repository.fetch(
92 remote_bzr_dir.open_repository())98 remote_bzr_dir.open_repository())
93 return local_bzr_dir.open_workingtree()99 return local_branch
94100
95 def push(self, db_branch_id, bzr_tree, required_format):101 def push(self, db_branch_id, bzr_branch, required_format):
96 """Push up `bzr_tree` as the Bazaar branch for `code_import`.102 """Push up `bzr_branch` as the Bazaar branch for `code_import`.
97103
98 :return: A boolean that is true if the push was non-trivial104 :return: A boolean that is true if the push was non-trivial
99 (i.e. actually transferred revisions).105 (i.e. actually transferred revisions).
100 """106 """
101 self.transport.create_prefix()107 self.transport.create_prefix()
102 branch_from = bzr_tree.branch
103 target_url = self._getMirrorURL(db_branch_id)108 target_url = self._getMirrorURL(db_branch_id)
104 try:109 try:
105 branch_to = Branch.open(target_url)110 remote_branch = Branch.open(target_url)
106 except NotBranchError:111 except NotBranchError:
107 branch_to = BzrDir.create_branch_and_repo(112 remote_branch = BzrDir.create_branch_and_repo(
108 target_url, format=required_format)113 target_url, format=required_format)
109 pull_result = branch_to.pull(branch_from, overwrite=True)114 pull_result = remote_branch.pull(bzr_branch, overwrite=True)
110 # Because of the way we do incremental imports, there may be revisions115 # Because of the way we do incremental imports, there may be revisions
111 # in the branch's repo that are not in the ancestry of the branch tip.116 # in the branch's repo that are not in the ancestry of the branch tip.
112 # We need to transfer them too.117 # We need to transfer them too.
113 branch_to.repository.fetch(branch_from.repository)118 remote_branch.repository.fetch(bzr_branch.repository)
114 return pull_result.old_revid != pull_result.new_revid119 return pull_result.old_revid != pull_result.new_revid
115120
116121
@@ -352,7 +357,10 @@
352 """Oversees the actual work of a code import."""357 """Oversees the actual work of a code import."""
353358
354 # Where the Bazaar working tree will be stored.359 # Where the Bazaar working tree will be stored.
355 BZR_WORKING_TREE_PATH = 'bzr_working_tree'360 BZR_BRANCH_PATH = 'bzr_branch'
361
362 # Should `getBazaarBranch` create a working tree?
363 needs_bzr_tree = True
356364
357 required_format = BzrDirFormat.get_default_format()365 required_format = BzrDirFormat.get_default_format()
358366
@@ -372,21 +380,22 @@
372 import_data_transport, self.source_details)380 import_data_transport, self.source_details)
373 self._logger = logger381 self._logger = logger
374382
375 def getBazaarWorkingTree(self):383 def getBazaarBranch(self):
376 """Return the Bazaar `WorkingTree` that we are importing into."""384 """Return the Bazaar `Branch` that we are importing into."""
377 if os.path.isdir(self.BZR_WORKING_TREE_PATH):385 if os.path.isdir(self.BZR_BRANCH_PATH):
378 shutil.rmtree(self.BZR_WORKING_TREE_PATH)386 shutil.rmtree(self.BZR_BRANCH_PATH)
379 return self.bazaar_branch_store.pull(387 return self.bazaar_branch_store.pull(
380 self.source_details.branch_id, self.BZR_WORKING_TREE_PATH,388 self.source_details.branch_id, self.BZR_BRANCH_PATH,
381 self.required_format)389 self.required_format, self.needs_bzr_tree)
382390
383 def pushBazaarWorkingTree(self, bazaar_tree):391 def pushBazaarBranch(self, bazaar_branch):
384 """Push the updated Bazaar working tree to the server.392 """Push the updated Bazaar branch to the server.
385393
386 :return: True if revisions were transferred.394 :return: True if revisions were transferred.
387 """395 """
388 return self.bazaar_branch_store.push(396 return self.bazaar_branch_store.push(
389 self.source_details.branch_id, bazaar_tree, self.required_format)397 self.source_details.branch_id, bazaar_branch,
398 self.required_format)
390399
391 def getWorkingDirectory(self):400 def getWorkingDirectory(self):
392 """The directory we should change to and store all scratch files in.401 """The directory we should change to and store all scratch files in.
@@ -455,14 +464,15 @@
455 os.mkdir(self.FOREIGN_WORKING_TREE_PATH)464 os.mkdir(self.FOREIGN_WORKING_TREE_PATH)
456 return self.foreign_tree_store.fetch(self.FOREIGN_WORKING_TREE_PATH)465 return self.foreign_tree_store.fetch(self.FOREIGN_WORKING_TREE_PATH)
457466
458 def importToBazaar(self, foreign_tree, bazaar_tree):467 def importToBazaar(self, foreign_tree, bazaar_branch):
459 """Actually import `foreign_tree` into `bazaar_tree`.468 """Actually import `foreign_tree` into `bazaar_branch`.
460469
461 :param foreign_tree: A `SubversionWorkingTree` or a `CVSWorkingTree`.470 :param foreign_tree: A `SubversionWorkingTree` or a `CVSWorkingTree`.
462 :param bazaar_tree: A `bzrlib.workingtree.WorkingTree`.471 :param bazaar_tree: A `bzrlib.branch.Branch`, which must have a
472 colocated working tree.
463 """473 """
464 foreign_directory = foreign_tree.local_path474 foreign_directory = foreign_tree.local_path
465 bzr_directory = str(bazaar_tree.basedir)475 bzr_directory = str(bazaar_branch.bzrdir.open_workingtree().basedir)
466476
467 scm_branch = SCM.branch(bzr_directory)477 scm_branch = SCM.branch(bzr_directory)
468 last_commit = cscvs.findLastCscvsCommit(scm_branch)478 last_commit = cscvs.findLastCscvsCommit(scm_branch)
@@ -500,9 +510,9 @@
500510
501 def _doImport(self):511 def _doImport(self):
502 foreign_tree = self.getForeignTree()512 foreign_tree = self.getForeignTree()
503 bazaar_tree = self.getBazaarWorkingTree()513 bazaar_branch = self.getBazaarBranch()
504 self.importToBazaar(foreign_tree, bazaar_tree)514 self.importToBazaar(foreign_tree, bazaar_branch)
505 non_trivial = self.pushBazaarWorkingTree(bazaar_tree)515 non_trivial = self.pushBazaarBranch(bazaar_branch)
506 self.foreign_tree_store.archive(foreign_tree)516 self.foreign_tree_store.archive(foreign_tree)
507 if non_trivial:517 if non_trivial:
508 return CodeImportWorkerExitCode.SUCCESS518 return CodeImportWorkerExitCode.SUCCESS
@@ -516,6 +526,8 @@
516 Subclasses need to implement `format_classes`.526 Subclasses need to implement `format_classes`.
517 """527 """
518528
529 needs_bzr_tree = False
530
519 @property531 @property
520 def format_classes(self):532 def format_classes(self):
521 """The format classes that should be tried for this import."""533 """The format classes that should be tried for this import."""
@@ -531,13 +543,14 @@
531 return {}543 return {}
532544
533 def _doImport(self):545 def _doImport(self):
534 bazaar_tree = self.getBazaarWorkingTree()546 self._logger.info("Starting job.")
535 self.bazaar_branch_store.push(
536 self.source_details.branch_id, bazaar_tree, self.required_format)
537 saved_factory = bzrlib.ui.ui_factory547 saved_factory = bzrlib.ui.ui_factory
538 bzrlib.ui.ui_factory = LoggingUIFactory(548 bzrlib.ui.ui_factory = LoggingUIFactory(
539 writer=lambda m: self._logger.info('%s', m))549 writer=lambda m: self._logger.info('%s', m))
540 try:550 try:
551 self._logger.info(
552 "Getting exising bzr branch from central store.")
553 bazaar_branch = self.getBazaarBranch()
541 transport = get_transport(self.source_details.url)554 transport = get_transport(self.source_details.url)
542 for format_class in self.format_classes:555 for format_class in self.format_classes:
543 try:556 try:
@@ -549,11 +562,14 @@
549 raise NotBranchError(self.source_details.url)562 raise NotBranchError(self.source_details.url)
550 foreign_branch = format.open(transport).open_branch()563 foreign_branch = format.open(transport).open_branch()
551 foreign_branch_tip = foreign_branch.last_revision()564 foreign_branch_tip = foreign_branch.last_revision()
552 inter_branch = InterBranch.get(foreign_branch, bazaar_tree.branch)565 inter_branch = InterBranch.get(foreign_branch, bazaar_branch)
566 self._logger.info("Importing foreign branch.")
553 pull_result = inter_branch.pull(567 pull_result = inter_branch.pull(
554 overwrite=True, **self.getExtraPullArgs())568 overwrite=True, **self.getExtraPullArgs())
555 self.pushBazaarWorkingTree(bazaar_tree)569 self._logger.info("Pushing foreign branch to central store.")
556 last_imported_revison = bazaar_tree.branch.last_revision()570 self.pushBazaarBranch(bazaar_branch)
571 last_imported_revison = bazaar_branch.last_revision()
572 self._logger.info("Job complete.")
557 if last_imported_revison == foreign_branch_tip:573 if last_imported_revison == foreign_branch_tip:
558 if pull_result.old_revid != pull_result.new_revid:574 if pull_result.old_revid != pull_result.new_revid:
559 return CodeImportWorkerExitCode.SUCCESS575 return CodeImportWorkerExitCode.SUCCESS
@@ -583,39 +599,38 @@
583 """See `PullingImportWorker.getExtraPullArgs`."""599 """See `PullingImportWorker.getExtraPullArgs`."""
584 return {'limit': config.codeimport.git_revisions_import_limit}600 return {'limit': config.codeimport.git_revisions_import_limit}
585601
586 def getBazaarWorkingTree(self):602 def getBazaarBranch(self):
587 """See `ImportWorker.getBazaarWorkingTree`.603 """See `ImportWorker.getBazaarBranch`.
588604
589 In addition to the superclass' behaviour, we retrieve the 'git.db'605 In addition to the superclass' behaviour, we retrieve bzr-git's
590 shamap from the import data store and put it where bzr-git will find606 caches, both legacy and modern, from the import data store and put
591 it in the Bazaar tree, that is at '.bzr/repository/git.db'.607 them where bzr-git will find them in the Bazaar tree, that is at
608 '.bzr/repository/git.db' and '.bzr/repository/git'.
592 """609 """
593 tree = PullingImportWorker.getBazaarWorkingTree(self)610 branch = PullingImportWorker.getBazaarBranch(self)
594 # Fetch the legacy cache from the store, if present.611 # Fetch the legacy cache from the store, if present.
595 self.import_data_store.fetch(612 self.import_data_store.fetch(
596 'git.db', tree.branch.repository._transport)613 'git.db', branch.repository._transport)
597 # The cache dir from newer bzr-gits is stored as a tarball.614 # The cache dir from newer bzr-gits is stored as a tarball.
598 local_name = 'git-cache.tar.gz'615 local_name = 'git-cache.tar.gz'
599 if self.import_data_store.fetch(local_name):616 if self.import_data_store.fetch(local_name):
600 repo_transport = tree.branch.repository._transport617 repo_transport = branch.repository._transport
601 repo_transport.mkdir('git')618 repo_transport.mkdir('git')
602 git_db_dir = os.path.join(619 git_db_dir = os.path.join(
603 local_path_from_url(repo_transport.base), 'git')620 local_path_from_url(repo_transport.base), 'git')
604 extract_tarball(local_name, git_db_dir)621 extract_tarball(local_name, git_db_dir)
605 return tree622 return branch
606623
607 def pushBazaarWorkingTree(self, bazaar_tree):624 def pushBazaarBranch(self, bazaar_branch):
608 """See `ImportWorker.pushBazaarWorkingTree`.625 """See `ImportWorker.pushBazaarBranch`.
609626
610 In addition to the superclass' behaviour, we store the 'git.db' shamap627 In addition to the superclass' behaviour, we store bzr-git's cache
611 that bzr-git will have created at .bzr/repository/bzr.git into the628 directory at .bzr/repository/git in the import data store.
612 import data store.
613 """629 """
614 non_trivial = PullingImportWorker.pushBazaarWorkingTree(630 non_trivial = PullingImportWorker.pushBazaarBranch(
615 self, bazaar_tree)631 self, bazaar_branch)
616 repo_transport = bazaar_tree.branch.repository._transport632 repo_base = bazaar_branch.repository._transport.base
617 git_db_dir = os.path.join(633 git_db_dir = os.path.join(local_path_from_url(repo_base), 'git')
618 local_path_from_url(repo_transport.base), 'git')
619 local_name = 'git-cache.tar.gz'634 local_name = 'git-cache.tar.gz'
620 create_tarball(git_db_dir, local_name)635 create_tarball(git_db_dir, local_name)
621 self.import_data_store.put(local_name)636 self.import_data_store.put(local_name)
@@ -637,29 +652,29 @@
637 from bzrlib.plugins.hg import HgBzrDirFormat652 from bzrlib.plugins.hg import HgBzrDirFormat
638 return [HgBzrDirFormat]653 return [HgBzrDirFormat]
639654
640 def getBazaarWorkingTree(self):655 def getBazaarBranch(self):
641 """See `ImportWorker.getBazaarWorkingTree`.656 """See `ImportWorker.getBazaarBranch`.
642657
643 In addition to the superclass' behaviour, we retrieve the 'hg-v2.db'658 In addition to the superclass' behaviour, we retrieve the 'hg-v2.db'
644 map from the import data store and put it where bzr-hg will find659 map from the import data store and put it where bzr-hg will find
645 it in the Bazaar tree, that is at '.bzr/repository/hg-v2.db'.660 it in the Bazaar tree, that is at '.bzr/repository/hg-v2.db'.
646 """661 """
647 tree = PullingImportWorker.getBazaarWorkingTree(self)662 branch = PullingImportWorker.getBazaarBranch(self)
648 self.import_data_store.fetch(663 self.import_data_store.fetch(
649 self.db_file, tree.branch.repository._transport)664 self.db_file, branch.repository._transport)
650 return tree665 return branch
651666
652 def pushBazaarWorkingTree(self, bazaar_tree):667 def pushBazaarBranch(self, bazaar_branch):
653 """See `ImportWorker.pushBazaarWorkingTree`.668 """See `ImportWorker.pushBazaarBranch`.
654669
655 In addition to the superclass' behaviour, we store the 'hg-v2.db' shamap670 In addition to the superclass' behaviour, we store the 'hg-v2.db'
656 that bzr-hg will have created at .bzr/repository/hg-v2.db into the671 shamap that bzr-hg will have created at .bzr/repository/hg-v2.db into
657 import data store.672 the import data store.
658 """673 """
659 non_trivial = PullingImportWorker.pushBazaarWorkingTree(674 non_trivial = PullingImportWorker.pushBazaarBranch(
660 self, bazaar_tree)675 self, bazaar_branch)
661 self.import_data_store.put(676 self.import_data_store.put(
662 self.db_file, bazaar_tree.branch.repository._transport)677 self.db_file, bazaar_branch.repository._transport)
663 return non_trivial678 return non_trivial
664679
665680