Rev 3483: Improve build_tree performance (igc, abentley) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Sun Jun 8 01:21:30 BST 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3483
revision-id:pqm at pqm.ubuntu.com-20080608002120-r3kcq0kxq24lhnak
parent: pqm at pqm.ubuntu.com-20080606135624-1ambbf8pct52xfh8
parent: aaron at aaronbentley.com-20080607193326-eyxo0nvfowppii2c
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Sun 2008-06-08 01:21:20 +0100
message:
Improve build_tree performance (igc, abentley)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 3453.2.11
revision-id:aaron at aaronbentley.com-20080607193326-eyxo0nvfowppii2c
parent: aaron at aaronbentley.com-20080606191036-7uctnxi5ozdiiss8
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Sat 2008-06-07 15:33:26 -0400
message:
Updates from review
modified:
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
------------------------------------------------------------
revno: 3453.2.10
revision-id:aaron at aaronbentley.com-20080606191036-7uctnxi5ozdiiss8
parent: aaron at aaronbentley.com-20080606190750-f6064uc2u1ea05dk
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 15:10:36 -0400
message:
Fix long lines
modified:
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
------------------------------------------------------------
revno: 3453.2.9
revision-id:aaron at aaronbentley.com-20080606190750-f6064uc2u1ea05dk
parent: aaron at aaronbentley.com-20080606164046-ghbxplxuhtpcb9iz
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 15:07:50 -0400
message:
Update NEWS
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 3453.2.8
revision-id:aaron at aaronbentley.com-20080606164046-ghbxplxuhtpcb9iz
parent: abentley at bruiser-20080606163615-8ceq4an8jxjcmnu1
parent: pqm at pqm.ubuntu.com-20080606135624-1ambbf8pct52xfh8
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 12:40:46 -0400
message:
Merge with bzr.dev
added:
bzrlib/tests/blackbox/test_alias.py test_alias.py-20080425112253-fbt0yz1c1834jriz-1
bzrlib/tests/blackbox/test_modified.py test_modified.py-20080424085848-nwqjenan4dq2vq3w-1
bzrlib/tests/per_repository_reference/ repository_external_-20080220025549-nnm2s80it1lvcwnc-1
bzrlib/tests/per_repository_reference/__init__.py __init__.py-20080220025549-nnm2s80it1lvcwnc-2
bzrlib/tests/per_repository_reference/test_add_inventory.py test_add_inventory.p-20080220025549-nnm2s80it1lvcwnc-3
bzrlib/tests/per_repository_reference/test_add_revision.py test_add_revision.py-20080220034108-ao1u8qgakqbo5a08-1
bzrlib/tests/per_repository_reference/test_add_signature_text.py test_add_signature_t-20080220041905-1j2g4lyz3c6h34v4-1
bzrlib/tests/per_repository_reference/test_all_revision_ids.py test_all_revision_id-20080220041905-1j2g4lyz3c6h34v4-2
bzrlib/tests/per_repository_reference/test_break_lock.py test_break_lock.py-20080220042825-1f48qmpnuqqp5wg2-1
bzrlib/tests/per_repository_reference/test_check.py test_check.py-20080220044229-sxxe747gzi6q8fyv-1
renamed:
doc/en/user-guide/revnos.txt => doc/en/user-guide/zen.txt revnos.txt-20080111231928-pbntxea0ynh9ww1t-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/__init__.py __init__.py-20050309040759-33e65acf91bbcd5d
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/check.py check.py-20050309040759-f3a679400c06bcc1
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/config.py config.py-20051011043216-070c74f4e9e338e8
bzrlib/counted_lock.py counted_lock.py-20070502135927-7dk86io3ok7ctx6k-1
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/graph.py graph_walker.py-20070525030359-y852guab65d4wtn0-1
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/lockdir.py lockdir.py-20060220222025-98258adf27fbdda3
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/merge_directive.py merge_directive.py-20070228184838-ja62280spt1g7f4x-1
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repofmt/knitrepo.py knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/revisionspec.py revisionspec.py-20050907152633-17567659fd5c0ddb
bzrlib/smart/client.py client.py-20061116014825-2k6ada6xgulslami-1
bzrlib/smart/message.py message.py-20080222013625-ncqmh3nrxjkxab87-1
bzrlib/symbol_versioning.py symbol_versioning.py-20060105104851-9ecf8af605d15a80
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/__init__.py __init__.py-20051128053524-eba30d8255e08dc3
bzrlib/tests/blackbox/test_added.py test_added.py-20060119085008-6b8b90369d42a26c
bzrlib/tests/blackbox/test_non_ascii.py test_non_ascii.py-20060105214030-68010be784a5d854
bzrlib/tests/blackbox/test_uncommit.py test_uncommit.py-20051027212835-84944b63adae51be
bzrlib/tests/blackbox/test_unknowns.py test_unknowns.py-20070905015344-74tg6s1synijo2oe-1
bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
bzrlib/tests/branch_implementations/test_update.py test_update.py-20060305010612-e68efbcbb1baa69f
bzrlib/tests/http_server.py httpserver.py-20061012142527-m1yxdj1xazsf8d7s-1
bzrlib/tests/repository_implementations/__init__.py __init__.py-20060131092037-9564957a7d4a841b
bzrlib/tests/test_branch.py test_branch.py-20060116013032-97819aa07b8ab3b5
bzrlib/tests/test_config.py testconfig.py-20051011041908-742d0c15d8d8c8eb
bzrlib/tests/test_counted_lock.py test_counted_lock.py-20070502135927-7dk86io3ok7ctx6k-2
bzrlib/tests/test_diff.py testdiff.py-20050727164403-d1a3496ebb12e339
bzrlib/tests/test_errors.py test_errors.py-20060210110251-41aba2deddf936a8
bzrlib/tests/test_graph.py test_graph_walker.py-20070525030405-enq4r60hhi9xrujc-1
bzrlib/tests/test_lockable_files.py test_lockable_files.py-20051225183927-365c7fd99591caf1
bzrlib/tests/test_lockdir.py test_lockdir.py-20060220222025-33d4221569a3d600
bzrlib/tests/test_merge.py testmerge.py-20050905070950-c1b5aa49ff911024
bzrlib/tests/test_merge_directive.py test_merge_directive-20070228184838-ja62280spt1g7f4x-2
bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
bzrlib/tests/test_revisionspec.py testrevisionnamespaces.py-20050711050225-8b4af89e6b1efe84
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
bzrlib/tests/test_smart_transport.py test_ssh_transport.py-20060608202016-c25gvf1ob7ypbus6-2
bzrlib/tests/test_switch.py test_switch.py-20071116011000-v5lnw7d2wkng9eux-2
bzrlib/tests/test_symbol_versioning.py test_symbol_versioning.py-20060105104851-51d7722c2018d42b
bzrlib/tests/test_transport_implementations.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
bzrlib/tests/test_versionedfile.py test_versionedfile.py-20060222045249-db45c9ed14a1c2e5
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tests/workingtree_implementations/test_parents.py test_set_parents.py-20060807231740-yicmnlci1mj8smu1-1
bzrlib/uncommit.py uncommit.py-20050626215513-5ec509fa425b305c
bzrlib/workingtree.py workingtree.py-20050511021032-29b6ec0a681e02e3
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
doc/developers/HACKING.txt HACKING-20050805200004-2a5dc975d870f78c
doc/developers/index.txt index.txt-20070508041241-qznziunkg0nffhiw-1
doc/developers/releasing.txt releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
doc/en/user-guide/branching_a_project.txt branching_a_project.-20071122141511-0knao2lklsdsvb1q-2
doc/en/user-guide/core_concepts.txt core_concepts.txt-20071114035000-q36a9h57ps06uvnl-2
doc/en/user-guide/index.txt index.txt-20060622101119-tgwtdci8z769bjb9-2
doc/en/user-guide/partner_intro.txt partner_workflow.txt-20071122141511-0knao2lklsdsvb1q-4
doc/en/user-guide/releasing_a_project.txt releasing_a_project.-20071121073725-0corxykv5irjal00-5
doc/en/user-guide/svn_plugin.txt svn_plugin.txt-20080509065016-cjc90f46407vi9a0-2
doc/en/user-guide/undoing_mistakes.txt undoing_mistakes.txt-20071121092300-8fyacngt1w98e5mp-1
doc/en/user-guide/zen.txt revnos.txt-20080111231928-pbntxea0ynh9ww1t-1
------------------------------------------------------------
revno: 3453.2.7
revision-id:abentley at bruiser-20080606163615-8ceq4an8jxjcmnu1
parent: aaron at aaronbentley.com-20080606161445-b7ii90zduprtigkb
committer: Aaron Bentley <abentley at bruiser>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 12:36:15 -0400
message:
Remove test kipple
modified:
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
------------------------------------------------------------
revno: 3453.2.6
revision-id:aaron at aaronbentley.com-20080606161445-b7ii90zduprtigkb
parent: aaron at aaronbentley.com-20080606152106-145ajhf9pw31fu7p
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 12:14:45 -0400
message:
Rename mutate_tree to delta_from_tree, add comment
modified:
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 3453.2.5
revision-id:aaron at aaronbentley.com-20080606152106-145ajhf9pw31fu7p
parent: aaron at aaronbentley.com-20080606134221-54emmgm6eagq1szs
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 11:21:06 -0400
message:
Avoid statting tons of non-existant files when building from scratch
modified:
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
------------------------------------------------------------
revno: 3453.2.4
revision-id:aaron at aaronbentley.com-20080606134221-54emmgm6eagq1szs
parent: aaron at aaronbentley.com-20080606025405-l7e8qeh6spaym69x
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Fri 2008-06-06 09:42:21 -0400
message:
Disable fast-path when conflicts are encountered
modified:
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
------------------------------------------------------------
revno: 3453.2.3
revision-id:aaron at aaronbentley.com-20080606025405-l7e8qeh6spaym69x
parent: aaron at aaronbentley.com-20080605193053-v21g2jieqihlz1oz
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Thu 2008-06-05 22:54:05 -0400
message:
Enable using a precomputed inventory delta for build_tree.
modified:
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 3453.2.2
revision-id:aaron at aaronbentley.com-20080605193053-v21g2jieqihlz1oz
parent: aaron at aaronbentley.com-20080602190332-6bfet6syo8wpl3jc
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Thu 2008-06-05 15:30:53 -0400
message:
Avoid unnecessary file_id lookups
modified:
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
------------------------------------------------------------
revno: 3453.2.1
revision-id:aaron at aaronbentley.com-20080602190332-6bfet6syo8wpl3jc
parent: pqm at pqm.ubuntu.com-20080527013230-8qjaju10duxpy3e2
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: fast-checkout2
timestamp: Mon 2008-06-02 15:03:32 -0400
message:
Speed up apply_insertions using iter_entries_by_dir instead of id2path
modified:
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
=== modified file 'NEWS'
--- a/NEWS 2008-06-06 12:02:48 +0000
+++ b/NEWS 2008-06-06 19:07:50 +0000
@@ -31,6 +31,9 @@
``modified`` (for null-separated unknowns, use ``ls --unknown --null``)
(Adrian Wilkins)
+ * Faster branching (1.09x) and lightweight checkouts (1.06x) on large trees.
+ (Ian Clatworthy, Aaron Bentley)
+
BUGFIXES:
* ``bzr status`` was breaking if you merged the same revision twice.
=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py 2008-05-12 02:48:08 +0000
+++ b/bzrlib/tests/test_transform.py 2008-06-06 16:36:15 +0000
@@ -64,7 +64,7 @@
def get_transform(self):
transform = TreeTransform(self.wt)
- #self.addCleanup(transform.finalize)
+ self.addCleanup(transform.finalize)
return transform, transform.root
def test_existing_limbo(self):
@@ -1704,6 +1704,19 @@
self.assertEqual([], list(target.iter_changes(revision_tree)))
self.assertTrue(source.is_executable('file1-id'))
+ def test_case_insensitive_build_tree_inventory(self):
+ source = self.make_branch_and_tree('source')
+ self.build_tree(['source/file', 'source/FILE'])
+ source.add(['file', 'FILE'], ['lower-id', 'upper-id'])
+ source.commit('added files')
+ # Don't try this at home, kids!
+ # Force the tree to report that it is case insensitive
+ target = self.make_branch_and_tree('target')
+ target.case_sensitive = False
+ build_tree(source.basis_tree(), target, source, delta_from_tree=True)
+ self.assertEqual('file.moved', target.id2path('lower-id'))
+ self.assertEqual('FILE', target.id2path('upper-id'))
+
class MockTransform(object):
=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py 2008-05-12 02:48:08 +0000
+++ b/bzrlib/transform.py 2008-06-07 19:33:26 +0000
@@ -450,16 +450,21 @@
del self._new_id[trans_id]
del self._r_new_id[file_id]
- def new_paths(self):
- """Determine the paths of all new and changed files"""
+ def new_paths(self, filesystem_only=False):
+ """Determine the paths of all new and changed files.
+
+ :param filesystem_only: if True, only calculate values for files
+ that require renames or execute bit changes.
+ """
new_ids = set()
- fp = FinalPaths(self)
- for id_set in (self._new_name, self._new_parent, self._new_contents,
- self._new_id, self._new_executability):
+ if filesystem_only:
+ id_sets = (self._needs_rename, self._new_executability)
+ else:
+ id_sets = (self._new_name, self._new_parent, self._new_contents,
+ self._new_id, self._new_executability)
+ for id_set in id_sets:
new_ids.update(id_set)
- new_paths = [(fp.get_path(t), t) for t in new_ids]
- new_paths.sort()
- return new_paths
+ return sorted(FinalPaths(self).get_paths(new_ids))
def tree_kind(self, trans_id):
"""Determine the file kind in the working tree.
@@ -856,7 +861,8 @@
def _set_executability(self, path, entry, trans_id):
"""Set the executability of versioned files """
new_executability = self._new_executability[trans_id]
- entry.executable = new_executability
+ if entry is not None:
+ entry.executable = new_executability
if supports_executable():
abspath = self._tree.abspath(path)
current_mode = os.stat(abspath).st_mode
@@ -1167,7 +1173,7 @@
tree.case_sensitive)
self._deletiondir = deletiondir
- def apply(self, no_conflicts=False, _mover=None):
+ def apply(self, no_conflicts=False, precomputed_delta=None, _mover=None):
"""Apply all changes to the inventory and filesystem.
If filesystem or inventory conflicts are present, MalformedTransform
@@ -1177,13 +1183,20 @@
:param no_conflicts: if True, the caller guarantees there are no
conflicts, so no check is made.
+ :param precomputed_delta: An inventory delta to use instead of
+ calculating one.
:param _mover: Supply an alternate FileMover, for testing
"""
if not no_conflicts:
conflicts = self.find_conflicts()
if len(conflicts) != 0:
raise MalformedTransform(conflicts=conflicts)
- inventory_delta = []
+ if precomputed_delta is None:
+ new_inventory_delta = []
+ inventory_delta = new_inventory_delta
+ else:
+ new_inventory_delta = None
+ inventory_delta = precomputed_delta
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
try:
if _mover is None:
@@ -1192,9 +1205,10 @@
mover = _mover
try:
child_pb.update('Apply phase', 0, 2)
- self._apply_removals(inventory_delta, mover)
+ self._apply_removals(new_inventory_delta, mover)
child_pb.update('Apply phase', 1, 2)
- modified_paths = self._apply_insertions(inventory_delta, mover)
+ modified_paths = self._apply_insertions(new_inventory_delta,
+ mover)
except:
mover.rollback()
raise
@@ -1213,6 +1227,8 @@
That is, delete files that are to be deleted, and put any files that
need renaming into limbo. This must be done in strict child-to-parent
order.
+
+ If inventory_delta is None, no inventory delta generation is performed.
"""
tree_paths = list(self._tree_path_ids.iteritems())
tree_paths.sort(reverse=True)
@@ -1234,7 +1250,8 @@
raise
else:
self.rename_count += 1
- if trans_id in self._removed_id:
+ if (trans_id in self._removed_id
+ and inventory_delta is not None):
if trans_id == self._new_root:
file_id = self._tree.get_root_id()
else:
@@ -1252,62 +1269,78 @@
That is, create any files that need to be created, and restore from
limbo any files that needed renaming. This must be done in strict
parent-to-child order.
+
+ If inventory_delta is None, no inventory delta is calculated, and
+ no list of modified paths is returned.
"""
- new_paths = self.new_paths()
+ new_paths = self.new_paths(filesystem_only=(inventory_delta is None))
modified_paths = []
- child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
completed_new = []
+ new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
+ new_paths)
+ if inventory_delta is not None:
+ entries = self._tree.iter_entries_by_dir(
+ new_path_file_ids.values())
+ old_paths = dict((e.file_id, p) for p, e in entries)
+ child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
try:
for num, (path, trans_id) in enumerate(new_paths):
new_entry = None
- child_pb.update('adding file', num, len(new_paths))
- if trans_id in self._new_contents or \
- self.path_changed(trans_id):
- full_path = self._tree.abspath(path)
- if trans_id in self._needs_rename:
+ if (num % 10) == 0:
+ child_pb.update('adding file', num, len(new_paths))
+ full_path = self._tree.abspath(path)
+ if trans_id in self._needs_rename:
+ try:
+ mover.rename(self._limbo_name(trans_id), full_path)
+ except OSError, e:
+ # We may be renaming a dangling inventory id
+ if e.errno != errno.ENOENT:
+ raise
+ else:
+ self.rename_count += 1
+ if inventory_delta is not None:
+ if (trans_id in self._new_contents or
+ self.path_changed(trans_id)):
+ if trans_id in self._new_contents:
+ modified_paths.append(full_path)
+ completed_new.append(trans_id)
+ file_id = new_path_file_ids[trans_id]
+ if file_id is not None and (trans_id in self._new_id or
+ trans_id in self._new_name or
+ trans_id in self._new_parent
+ or trans_id in self._new_executability):
try:
- mover.rename(self._limbo_name(trans_id), full_path)
- except OSError, e:
- # We may be renaming a dangling inventory id
- if e.errno != errno.ENOENT:
- raise
+ kind = self.final_kind(trans_id)
+ except NoSuchFile:
+ kind = self._tree.stored_kind(file_id)
+ parent_trans_id = self.final_parent(trans_id)
+ parent_file_id = new_path_file_ids.get(parent_trans_id)
+ if parent_file_id is None:
+ parent_file_id = self.final_file_id(
+ parent_trans_id)
+ if trans_id in self._new_reference_revision:
+ new_entry = inventory.TreeReference(
+ file_id,
+ self._new_name[trans_id],
+ self.final_file_id(self._new_parent[trans_id]),
+ None, self._new_reference_revision[trans_id])
else:
- self.rename_count += 1
- if trans_id in self._new_contents:
- modified_paths.append(full_path)
- completed_new.append(trans_id)
- file_id = self.final_file_id(trans_id)
- if file_id is not None and (trans_id in self._new_id or
- trans_id in self._new_name or trans_id in self._new_parent
- or trans_id in self._new_executability):
- try:
- kind = self.final_kind(trans_id)
- except NoSuchFile:
- kind = self._tree.stored_kind(file_id)
- if trans_id in self._new_reference_revision:
- new_entry = inventory.TreeReference(
- self.final_file_id(trans_id),
- self._new_name[trans_id],
- self.final_file_id(self._new_parent[trans_id]),
- None, self._new_reference_revision[trans_id])
- else:
- new_entry = inventory.make_entry(kind,
- self.final_name(trans_id),
- self.final_file_id(self.final_parent(trans_id)),
- self.final_file_id(trans_id))
- try:
- old_path = self._tree.id2path(new_entry.file_id)
- except errors.NoSuchId:
- old_path = None
- inventory_delta.append((old_path, path, new_entry.file_id,
- new_entry))
+ new_entry = inventory.make_entry(kind,
+ self.final_name(trans_id),
+ parent_file_id, file_id)
+ old_path = old_paths.get(new_entry.file_id)
+ inventory_delta.append(
+ (old_path, path, new_entry.file_id, new_entry))
if trans_id in self._new_executability:
self._set_executability(path, new_entry, trans_id)
finally:
child_pb.finished()
- for trans_id in completed_new:
- del self._new_contents[trans_id]
+ if inventory_delta is None:
+ self._new_contents.clear()
+ else:
+ for trans_id in completed_new:
+ del self._new_contents[trans_id]
return modified_paths
@@ -1554,6 +1587,10 @@
self._known_paths[trans_id] = self._determine_path(trans_id)
return self._known_paths[trans_id]
+ def get_paths(self, trans_ids):
+ return [(self.get_path(t), t) for t in trans_ids]
+
+
def topology_sorted_ids(tree):
"""Determine the topological order of the ids in a tree"""
@@ -1562,7 +1599,8 @@
return file_ids
-def build_tree(tree, wt, accelerator_tree=None, hardlink=False):
+def build_tree(tree, wt, accelerator_tree=None, hardlink=False,
+ delta_from_tree=False):
"""Create working tree for a branch, using a TreeTransform.
This function should be used on empty trees, having a tree root at most.
@@ -1584,6 +1622,8 @@
:param hardlink: If true, hard-link files to accelerator_tree, where
possible. accelerator_tree must implement abspath, i.e. be a
working tree.
+ :param delta_from_tree: If true, build_tree may use the input Tree to
+ generate the inventory delta.
"""
wt.lock_tree_write()
try:
@@ -1592,7 +1632,8 @@
if accelerator_tree is not None:
accelerator_tree.lock_read()
try:
- return _build_tree(tree, wt, accelerator_tree, hardlink)
+ return _build_tree(tree, wt, accelerator_tree, hardlink,
+ delta_from_tree)
finally:
if accelerator_tree is not None:
accelerator_tree.unlock()
@@ -1602,11 +1643,14 @@
wt.unlock()
-def _build_tree(tree, wt, accelerator_tree, hardlink):
+def _build_tree(tree, wt, accelerator_tree, hardlink, delta_from_tree):
"""See build_tree."""
for num, _unused in enumerate(wt.all_file_ids()):
if num > 0: # more than just a root
raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
+ existing_files = set()
+ for dir, files in wt.walkdirs():
+ existing_files.update(f[0] for f in files)
file_trans_id = {}
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
pp = ProgressPhase("Build phase", 2, top_pb)
@@ -1631,6 +1675,10 @@
try:
deferred_contents = []
num = 0
+ if delta_from_tree:
+ precomputed_delta = []
+ else:
+ precomputed_delta = None
for num, (tree_path, entry) in \
enumerate(tree.inventory.iter_entries_by_dir()):
pb.update("Building tree", num - len(deferred_contents),
@@ -1639,12 +1687,11 @@
continue
reparent = False
file_id = entry.file_id
- target_path = wt.abspath(tree_path)
- try:
+ if delta_from_tree:
+ precomputed_delta.append((None, tree_path, file_id, entry))
+ if tree_path in existing_files:
+ target_path = wt.abspath(tree_path)
kind = file_kind(target_path)
- except NoSuchFile:
- pass
- else:
if kind == "directory":
try:
bzrdir.BzrDir.open(target_path)
@@ -1670,7 +1717,7 @@
file_trans_id[file_id] = trans_id
tt.version_file(entry.file_id, trans_id)
executable = tree.is_executable(entry.file_id, tree_path)
- if executable is not None:
+ if executable:
tt.set_executability(executable, trans_id)
deferred_contents.append((entry.file_id, trans_id))
else:
@@ -1689,6 +1736,8 @@
divert_trans = set(file_trans_id[f] for f in divert)
resolver = lambda t, c: resolve_checkout(t, c, divert_trans)
raw_conflicts = resolve_conflicts(tt, pass_func=resolver)
+ if len(raw_conflicts) > 0:
+ precomputed_delta = None
conflicts = cook_conflicts(raw_conflicts, tt)
for conflict in conflicts:
warning(conflict)
@@ -1696,7 +1745,8 @@
wt.add_conflicts(conflicts)
except errors.UnsupportedOperation:
pass
- result = tt.apply(no_conflicts=True)
+ result = tt.apply(no_conflicts=True,
+ precomputed_delta=precomputed_delta)
finally:
tt.finalize()
top_pb.finished()
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2008-06-04 17:54:52 +0000
+++ b/bzrlib/workingtree_4.py 2008-06-06 16:40:46 +0000
@@ -1373,8 +1373,11 @@
if basis_root_id is not None:
wt._set_root_id(basis_root_id)
wt.flush()
+ # delta_from_tree is safe even for DirStateRevisionTrees,
+ # because wt4.apply_inventory_delta does not mutate the input
+ # inventory entries.
transform.build_tree(basis, wt, accelerator_tree,
- hardlink=hardlink)
+ hardlink=hardlink, delta_from_tree=True)
finally:
basis.unlock()
finally:
More information about the bazaar-commits
mailing list