Rev 2423: merge robert, debugging in http://sourcefrog.net/bzr/dirstate-plus-subtree
Martin Pool
mbp at sourcefrog.net
Thu Mar 1 10:14:05 GMT 2007
At http://sourcefrog.net/bzr/dirstate-plus-subtree
------------------------------------------------------------
revno: 2423
revision-id: mbp at sourcefrog.net-20070301101403-v2ey2v53rhzprmds
parent: mbp at sourcefrog.net-20070301090216-vhh2444yosrvw6ll
parent: robertc at robertcollins.net-20070301085003-1k4kx7hxz8ce5x8p
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: dirstate-plus-subtree
timestamp: Thu 2007-03-01 21:14:03 +1100
message:
merge robert, debugging
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/mutabletree.py mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_add.py test_add.py-20060518072250-857e4f86f54a30b2
bzrlib/tests/blackbox/test_break_lock.py test_break_lock.py-20060303014503-a90e07d38d042d1d
bzrlib/tests/blackbox/test_cat.py test_cat.py-20051201162916-f0937e4e19ea24b3
bzrlib/tests/blackbox/test_status.py teststatus.py-20050712014354-508855eb9f29f7dc
bzrlib/tests/blackbox/test_update.py test_update.py-20060212125639-c4dad1a5c56d5919
bzrlib/tests/repository_implementations/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
bzrlib/tests/test_inv.py testinv.py-20050722220913-1dc326138d1a5892
bzrlib/tests/test_smart_add.py test_smart_add.py-20050824235919-c60dcdb0c8e999ce
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/tests/workingtree_implementations/test_workingtree.py test_workingtree.py-20060203003124-817757d3e31444fb
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
bzrlib/workingtree.py workingtree.py-20050511021032-29b6ec0a681e02e3
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 2406.1.70
merged: robertc at robertcollins.net-20070301085003-1k4kx7hxz8ce5x8p
parent: robertc at robertcollins.net-20070301084414-h302pw7vt7wllqb6
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 19:50:03 +1100
message:
Workaround WorkingTree4 not having a native remove() in test_cat.
------------------------------------------------------------
revno: 2406.1.69
merged: robertc at robertcollins.net-20070301084414-h302pw7vt7wllqb6
parent: mbp at sourcefrog.net-20070301083325-e87nhnnpx3i18nea
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 19:44:14 +1100
message:
Fix all blackbox add tests, and the add --from-ids case in the UI.
------------------------------------------------------------
revno: 2406.1.68
merged: mbp at sourcefrog.net-20070301083325-e87nhnnpx3i18nea
parent: robertc at robertcollins.net-20070301080114-dt6xpp7v0envbati
committer: Martin Pool <mbp at sourcefrog.net>
branch nick: dirstate-robert
timestamp: Thu 2007-03-01 19:33:25 +1100
message:
Add a test for setting the root id in a dirstate with parent trees
------------------------------------------------------------
revno: 2406.1.67
merged: robertc at robertcollins.net-20070301080114-dt6xpp7v0envbati
parent: robertc at robertcollins.net-20070301074339-34mc7tfym7o4uugf
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 19:01:14 +1100
message:
Fix test_inv - make setting WorkingTree4._dirty use a helper to reduce code duplication, and reset the inventory when we dont manually update it, if it exists.
------------------------------------------------------------
revno: 2406.1.66
merged: robertc at robertcollins.net-20070301074339-34mc7tfym7o4uugf
parent: robertc at robertcollins.net-20070301072736-dc00wtcb7py592re
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 18:43:39 +1100
message:
MutableTree.add only needs a tree write lock.
------------------------------------------------------------
revno: 2406.1.65
merged: robertc at robertcollins.net-20070301072736-dc00wtcb7py592re
parent: robertc at robertcollins.net-20070301071122-yhy7vchlazynnb8y
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 18:27:36 +1100
message:
Split test_root_revision_entry into tree and repository portions.
------------------------------------------------------------
revno: 2406.1.64
merged: robertc at robertcollins.net-20070301071122-yhy7vchlazynnb8y
parent: robertc at robertcollins.net-20070301065052-d08k4x37bchwo48e
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 18:11:22 +1100
message:
Disabled test_repository.test_create_basis_inventory, a test that tests tree behaviour in the wrong place - its future is being discussed.
------------------------------------------------------------
revno: 2406.1.63
merged: robertc at robertcollins.net-20070301065052-d08k4x37bchwo48e
parent: robertc at robertcollins.net-20070301061944-y1jw05ufqdpw4yx5
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 17:50:52 +1100
message:
Fix cmd_renames to lock around inventory access.
------------------------------------------------------------
revno: 2406.1.62
merged: robertc at robertcollins.net-20070301061944-y1jw05ufqdpw4yx5
parent: robertc at robertcollins.net-20070301054630-ff4zf6s3odxfic71
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 17:19:44 +1100
message:
Update the Tree.filter_unversioned_files docstring to reflect what the existing implementations actually do, and change the WorkingTree4 implementation to match a newly created test for it.
------------------------------------------------------------
revno: 2406.1.61
merged: robertc at robertcollins.net-20070301054630-ff4zf6s3odxfic71
parent: robertc at robertcollins.net-20070301053439-rf8mkppoqutiy7fa
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:46:30 +1100
message:
Remove exploratory cruft.
------------------------------------------------------------
revno: 2406.1.60
merged: robertc at robertcollins.net-20070301053439-rf8mkppoqutiy7fa
parent: robertc at robertcollins.net-20070301052802-zwbocbr7z5vyptad
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:34:39 +1100
message:
Make the assertStatus blackbox helper clearer.
------------------------------------------------------------
revno: 2406.1.59
merged: robertc at robertcollins.net-20070301052802-zwbocbr7z5vyptad
parent: robertc at robertcollins.net-20070301052607-x77gnbfssigedky4
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:28:02 +1100
message:
Remove a break-lock test that was duplicating lower level testing without adding value.
------------------------------------------------------------
revno: 2406.1.58
merged: robertc at robertcollins.net-20070301052607-x77gnbfssigedky4
parent: robertc at robertcollins.net-20070301052056-h3byz7nuk38la3os
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:26:07 +1100
message:
Fix a blackbox test to not use inventory to determine tree size.
------------------------------------------------------------
revno: 2406.1.57
merged: robertc at robertcollins.net-20070301052056-h3byz7nuk38la3os
parent: robertc at robertcollins.net-20070301051807-3qz6wj0jtjsieyj2
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:20:56 +1100
message:
Fix test_smart_add tests for dirstate - mainly inventory outside locks issues.
------------------------------------------------------------
revno: 2406.1.56
merged: robertc at robertcollins.net-20070301051807-3qz6wj0jtjsieyj2
parent: robertc at robertcollins.net-20070301050247-ufh99m2ze45d7mol
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:18:07 +1100
message:
Document behaviour of tree.path2id("path/").
------------------------------------------------------------
revno: 2406.1.55
merged: robertc at robertcollins.net-20070301050247-ufh99m2ze45d7mol
parent: robertc at robertcollins.net-20070301050153-9wdn7gdori263v9e
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:02:47 +1100
message:
Whitespace fix.
------------------------------------------------------------
revno: 2406.1.54
merged: robertc at robertcollins.net-20070301050153-9wdn7gdori263v9e
parent: robertc at robertcollins.net-20070301050053-u0ac7vavyzplbjz1
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:01:53 +1100
message:
in test_inv, stop abusing the inventory interface to get tree alterations to occur.
------------------------------------------------------------
revno: 2406.1.53
merged: robertc at robertcollins.net-20070301050053-u0ac7vavyzplbjz1
parent: robertc at robertcollins.net-20070301042839-hgs5fy98vuws6iau
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 16:00:53 +1100
message:
Make the dirstate API changes be prominently documented for upgraders.
------------------------------------------------------------
revno: 2406.1.52
merged: robertc at robertcollins.net-20070301042839-hgs5fy98vuws6iau
parent: robertc at robertcollins.net-20070301042042-vmcypp3mjnvuwft5
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 15:28:39 +1100
message:
Lock trees in Merge3Merger correctly.
------------------------------------------------------------
revno: 2406.1.51
merged: robertc at robertcollins.net-20070301042042-vmcypp3mjnvuwft5
parent: robertc at robertcollins.net-20070301041307-yendz2ijpubqmfgq
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 15:20:42 +1100
message:
Lock build_tree trees in write-first order, to support older formats that dont do lock_tree_write nicely.
------------------------------------------------------------
revno: 2406.1.50
merged: robertc at robertcollins.net-20070301041307-yendz2ijpubqmfgq
parent: robertc at robertcollins.net-20070301040645-1ky0urtukkb9gdxa
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 15:13:07 +1100
message:
Remove unguarded call to find_interesting in test_find_interesting - its tested by the actual code that does the work.
------------------------------------------------------------
revno: 2406.1.49
merged: robertc at robertcollins.net-20070301040645-1ky0urtukkb9gdxa
parent: robertc at robertcollins.net-20070301035615-apsvyiyqk6pqext2
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 15:06:45 +1100
message:
Lock trees passed in to build_tree.
------------------------------------------------------------
revno: 2406.1.48
merged: robertc at robertcollins.net-20070301035615-apsvyiyqk6pqext2
parent: robertc at robertcollins.net-20070301035205-lfdthhpjoudb07b8
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 14:56:15 +1100
message:
Deprecated and make work with DirState trees 'transform.find_interesting'.
------------------------------------------------------------
revno: 2406.1.47
merged: robertc at robertcollins.net-20070301035205-lfdthhpjoudb07b8
parent: robertc at robertcollins.net-20070301032019-s9lbs2lv8xa6zqxk
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate
timestamp: Thu 2007-03-01 14:52:05 +1100
message:
Improve applyDeprecated warning message.
=== modified file 'NEWS'
--- a/NEWS 2007-02-22 15:04:35 +0000
+++ b/NEWS 2007-03-01 05:00:53 +0000
@@ -1,5 +1,23 @@
IN DEVELOPMENT
+ SURPRISES:
+
+ * For users of bzrlib: Two major changes have been made to the working tree
+ api in bzrlib. The first is that many methods and attributes, including
+ the inventory attribute, are no longer valid for use until one of
+ lock_read/lock_write/lock_tree_write has been called, and become invalid
+ again after unlock is called. This has been done to improve performance
+ and correctness as part of the dirstate development. (Robert Collins,
+ John A Meinel, Martin Pool, and others).
+ * For users of bzrlib: The attribute 'tree.inventory' should be considered
+ readonly. Previously it was possible to directly alter this attribute, or
+ its contents, and have the tree notice this. This has been made
+ unsupported - it may work in some tree formats, but in the newer dirstate
+ format such actions will have no effect and will be ignored, or even
+ cause assertions. All operations possible can still be carried out by a
+ combination of the tree API, and the bzrlib.transform API. (Robert
+ Collins, John A Meinel, Martin Pool, and others).
+
IMPROVEMENTS:
* Support for OS Windows 98. Also .bzr.log on any windows system
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2007-03-01 04:07:42 +0000
+++ b/bzrlib/builtins.py 2007-03-01 10:14:03 +0000
@@ -342,6 +342,7 @@
file_ids_from=None):
import bzrlib.add
+ base_tree = None
if file_ids_from is not None:
try:
base_tree, base_path = WorkingTree.open_containing(
@@ -357,8 +358,14 @@
action = bzrlib.add.AddAction(to_file=self.outf,
should_print=(not is_quiet()))
- added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
- action=action, save=not dry_run)
+ if base_tree:
+ base_tree.lock_read()
+ try:
+ added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
+ action=action, save=not dry_run)
+ finally:
+ if base_tree is not None:
+ base_tree.unlock()
if len(ignored) > 0:
if verbose:
for glob in sorted(ignored.keys()):
@@ -977,12 +984,21 @@
@display_command
def run(self, dir=u'.'):
tree = WorkingTree.open_containing(dir)[0]
- old_inv = tree.basis_tree().inventory
- new_inv = tree.read_working_inventory()
- renames = list(_mod_tree.find_renames(old_inv, new_inv))
- renames.sort()
- for old_name, new_name in renames:
- self.outf.write("%s => %s\n" % (old_name, new_name))
+ tree.lock_read()
+ try:
+ new_inv = tree.inventory
+ old_tree = tree.basis_tree()
+ old_tree.lock_read()
+ try:
+ old_inv = old_tree.inventory
+ renames = list(_mod_tree.find_renames(old_inv, new_inv))
+ renames.sort()
+ for old_name, new_name in renames:
+ self.outf.write("%s => %s\n" % (old_name, new_name))
+ finally:
+ old_tree.unlock()
+ finally:
+ tree.unlock()
class cmd_update(Command):
@@ -1467,17 +1483,26 @@
@display_command
def run(self):
wt = WorkingTree.open_containing(u'.')[0]
- basis_inv = wt.basis_tree().inventory
- inv = wt.inventory
- for file_id in inv:
- if file_id in basis_inv:
- continue
- if inv.is_root(file_id) and len(basis_inv) == 0:
- continue
- path = inv.id2path(file_id)
- if not os.access(osutils.abspath(path), os.F_OK):
- continue
- self.outf.write(path + '\n')
+ wt.lock_read()
+ try:
+ basis = wt.basis_tree()
+ basis.lock_read()
+ try:
+ basis_inv = basis.inventory
+ inv = wt.inventory
+ for file_id in inv:
+ if file_id in basis_inv:
+ continue
+ if inv.is_root(file_id) and len(basis_inv) == 0:
+ continue
+ path = inv.id2path(file_id)
+ if not os.access(osutils.abspath(path), os.F_OK):
+ continue
+ self.outf.write(path + '\n')
+ finally:
+ basis.unlock()
+ finally:
+ wt.unlock()
class cmd_root(Command):
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2007-03-01 07:56:56 +0000
+++ b/bzrlib/dirstate.py 2007-03-01 10:14:03 +0000
@@ -1963,6 +1963,31 @@
self._dirblock_state = DirState.IN_MEMORY_MODIFIED
+ def _validate(self):
+ """Check that invariants on the dirblock are correct.
+
+ This can be useful in debugging; it shouldn't be necessary in
+ normal code.
+ """
+ from pprint import pformat
+ if len(self._dirblocks) > 0:
+ assert self._dirblocks[0][0] == '', \
+ "dirblocks don't start with root block:\n" + \
+ pformat(dirblocks)
+ if len(self._dirblocks) > 1:
+ assert self._dirblocks[1][0] == '', \
+ "dirblocks missing root directory:\n" + \
+ pformat(dirblocks)
+ assert self._dirblocks[0][0] == '', \
+ "dirblocks don't start with root block:\n" + \
+ pformat(dirblocks)
+ assert self._dirblocks[1:] == sorted(self._dirblocks[1:]), \
+ "dirblocks are not in sorted order:\n" + \
+ pformat(self._dirblocks)
+ for dirblock in self._dirblocks:
+ assert dirblock[1] == sorted(dirblock[1]), \
+ "dirblock for %r is not sorted:\n%s" % \
+ (dirblock[0], pformat(dirblock))
def _wipe_state(self):
"""Forget all state information about the dirstate."""
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2007-02-27 05:51:36 +0000
+++ b/bzrlib/merge.py 2007-03-01 10:14:03 +0000
@@ -415,8 +415,11 @@
"""Initialize the merger object and perform the merge."""
object.__init__(self)
self.this_tree = working_tree
+ self.this_tree.lock_tree_write()
self.base_tree = base_tree
+ self.base_tree.lock_read()
self.other_tree = other_tree
+ self.other_tree.lock_read()
self._raw_conflicts = []
self.cooked_conflicts = []
self.reprocess = reprocess
@@ -432,7 +435,6 @@
else:
all_ids = set(base_tree)
all_ids.update(other_tree)
- working_tree.lock_tree_write()
self.tt = TreeTransform(working_tree, self.pb)
try:
self.pp.next_phase()
@@ -467,7 +469,9 @@
pass
finally:
self.tt.finalize()
- working_tree.unlock()
+ self.other_tree.unlock()
+ self.base_tree.unlock()
+ self.this_tree.unlock()
self.pb.clear()
def fix_root(self):
=== modified file 'bzrlib/mutabletree.py'
--- a/bzrlib/mutabletree.py 2007-02-26 14:24:46 +0000
+++ b/bzrlib/mutabletree.py 2007-03-01 10:14:03 +0000
@@ -62,7 +62,7 @@
branch and bzrdir attributes.
"""
- @needs_write_lock
+ @needs_tree_write_lock
def add(self, files, ids=None, kinds=None):
"""Add paths to the set of versioned paths.
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2007-02-23 05:47:26 +0000
+++ b/bzrlib/tests/__init__.py 2007-03-01 10:14:03 +0000
@@ -741,7 +741,7 @@
expected_first_warning = symbol_versioning.deprecation_string(
a_callable, deprecation_format)
if len(call_warnings) == 0:
- self.fail("No assertion generated by call to %s" %
+ self.fail("No deprecation warning generated by call to %s" %
a_callable)
self.assertEqual(expected_first_warning, call_warnings[0])
return result
=== modified file 'bzrlib/tests/blackbox/test_add.py'
--- a/bzrlib/tests/blackbox/test_add.py 2007-02-15 22:24:48 +0000
+++ b/bzrlib/tests/blackbox/test_add.py 2007-03-01 08:44:14 +0000
@@ -115,7 +115,7 @@
self.run_bzr('add')
self.assertEquals(self.capture('unknowns'), 'README\n')
- eq(len(t.read_working_inventory()), 3)
+ eq(len(list(t)), 3)
chdir('..')
self.run_bzr('add')
@@ -144,7 +144,6 @@
'added b/c w/ file id from b/c\n',
out)
- new_tree.read_working_inventory()
self.assertEqual(base_tree.path2id('a'), new_tree.path2id('a'))
self.assertEqual(base_tree.path2id('b'), new_tree.path2id('b'))
self.assertEqual(base_tree.path2id('b/c'), new_tree.path2id('b/c'))
@@ -165,7 +164,6 @@
'added d w/ file id from b/d\n',
out)
- new_tree.read_working_inventory()
self.assertEqual(base_tree.path2id('b/c'), new_tree.path2id('c'))
self.assertEqual(base_tree.path2id('b/d'), new_tree.path2id('d'))
=== modified file 'bzrlib/tests/blackbox/test_break_lock.py'
--- a/bzrlib/tests/blackbox/test_break_lock.py 2007-02-25 21:52:19 +0000
+++ b/bzrlib/tests/blackbox/test_break_lock.py 2007-03-01 05:28:02 +0000
@@ -92,37 +92,6 @@
self.assertRaises(errors.LockBroken, self.wt.unlock)
self.assertRaises(errors.LockBroken, self.master_branch.unlock)
- def test_saying_no_leaves_it_locked(self):
- ### if 'no' is answered, objects should remain locked.
- self.wt.lock_write()
- try:
- self.master_branch.lock_write()
- try:
- # run the break-lock
- # we need 5 yes's - wt, branch, repo, bound branch, bound repo.
- self.run_bzr('break-lock', 'checkout', stdin="n\nn\nn\nn\nn\n")
-
- # The default timeout to wait for LockContention is 5 minutes.
- # we need to override this temporarily.
- # TODO: jam 20060927 When we have per repository/branch/tree
- # timeouts set the value of the repository,
- # rather than setting the global default.
- orig_default = lockdir._DEFAULT_TIMEOUT_SECONDS
- try:
- lockdir._DEFAULT_TIMEOUT_SECONDS = 1
- # a new tree instance should not be lockable
- wt = bzrlib.workingtree.WorkingTree.open('checkout')
- self.assertRaises(errors.LockContention, wt.lock_write)
- # and a new instance of the master branch
- mb = wt.branch.get_master_branch()
- self.assertRaises(errors.LockContention, mb.lock_write)
- finally:
- lockdir._DEFAULT_TIMEOUT_SECONDS = orig_default
- # unlock our branches normally.
- finally:
- self.master_branch.unlock()
- finally:
- self.wt.unlock()
class TestBreakLockOldBranch(ExternalBase):
=== modified file 'bzrlib/tests/blackbox/test_cat.py'
--- a/bzrlib/tests/blackbox/test_cat.py 2006-12-13 08:15:54 +0000
+++ b/bzrlib/tests/blackbox/test_cat.py 2007-03-01 08:50:03 +0000
@@ -73,6 +73,9 @@
try:
tree.add(['a-rev-tree', 'c-rev', 'd-rev'])
tree.commit('add test files')
+ # remove currently uses self._write_inventory -
+ # work around that for now.
+ tree.flush()
tree.remove(['d-rev'])
tree.rename_one('a-rev-tree', 'b-tree')
tree.rename_one('c-rev', 'a-rev-tree')
=== modified file 'bzrlib/tests/blackbox/test_status.py'
--- a/bzrlib/tests/blackbox/test_status.py 2007-02-21 07:59:17 +0000
+++ b/bzrlib/tests/blackbox/test_status.py 2007-03-01 05:34:39 +0000
@@ -40,15 +40,15 @@
class BranchStatus(TestCaseWithTransport):
- def assertStatus(self, output_lines, working_tree,
+ def assertStatus(self, expected_lines, working_tree,
revision=None, short=False):
"""Run status in working_tree and look for output.
- :param output_lines: The lines to look for.
+ :param expected_lines: The lines to look for.
:param working_tree: The tree to run status in.
"""
output_string = self.status_string(working_tree, revision, short)
- self.assertEqual(output_lines, output_string.splitlines(True))
+ self.assertEqual(expected_lines, output_string.splitlines(True))
def status_string(self, wt, revision=None, short=False):
# use a real file rather than StringIO because it doesn't handle
=== modified file 'bzrlib/tests/blackbox/test_update.py'
--- a/bzrlib/tests/blackbox/test_update.py 2006-10-18 02:26:35 +0000
+++ b/bzrlib/tests/blackbox/test_update.py 2007-03-01 05:02:47 +0000
@@ -202,7 +202,7 @@
"""Update a light checkout of a readonly branch"""
tree = self.make_branch_and_tree('branch')
readonly_branch = branch.Branch.open(self.get_readonly_url('branch'))
- checkout = readonly_branch.create_checkout('checkout',
+ checkout = readonly_branch.create_checkout('checkout',
lightweight=True)
tree.commit('empty commit')
self.runbzr(['update', 'checkout'])
=== modified file 'bzrlib/tests/repository_implementations/test_commit_builder.py'
--- a/bzrlib/tests/repository_implementations/test_commit_builder.py 2007-02-26 15:27:17 +0000
+++ b/bzrlib/tests/repository_implementations/test_commit_builder.py 2007-03-01 07:27:36 +0000
@@ -126,3 +126,14 @@
# the RevisionTree api.
self.assertEqual(rev_id, rev_tree.get_revision_id())
self.assertEqual([], rev_tree.get_parent_ids())
+
+ def test_root_entry_has_revision(self):
+ # test the root revision created and put in the basis
+ # has the right rev id.
+ tree = self.make_branch_and_tree('.')
+ rev_id = tree.commit('message')
+ basis_tree = tree.basis_tree()
+ basis_tree.lock_read()
+ self.addCleanup(basis_tree.unlock)
+ self.assertEqual(rev_id, basis_tree.inventory.root.revision)
+
=== modified file 'bzrlib/tests/repository_implementations/test_repository.py'
--- a/bzrlib/tests/repository_implementations/test_repository.py 2007-02-16 07:02:19 +0000
+++ b/bzrlib/tests/repository_implementations/test_repository.py 2007-03-01 10:14:03 +0000
@@ -365,11 +365,10 @@
def test_root_entry_has_revision(self):
tree = self.make_branch_and_tree('.')
tree.commit('message', rev_id='rev_id')
- self.assertEqual('rev_id', tree.basis_tree().inventory.root.revision)
- rev_tree = tree.branch.repository.revision_tree(tree.get_parent_ids()[0])
+ rev_tree = tree.branch.repository.revision_tree(tree.last_revision())
self.assertEqual('rev_id', rev_tree.inventory.root.revision)
- def test_create_basis_inventory(self):
+ def DISABLED_DELETE_OR_FIX_BEFORE_MERGE_test_create_basis_inventory(self):
# Needs testing here because differences between repo and working tree
# basis inventory formats can lead to bugs.
t = self.make_branch_and_tree('.')
=== modified file 'bzrlib/tests/test_dirstate.py'
--- a/bzrlib/tests/test_dirstate.py 2007-02-27 21:32:16 +0000
+++ b/bzrlib/tests/test_dirstate.py 2007-03-01 08:33:25 +0000
@@ -424,6 +424,41 @@
finally:
state.unlock()
+ def test_set_path_id_with_parents(self):
+ """Set the root file id in a dirstate with parents"""
+ mt = self.make_branch_and_tree('mt')
+ # may need to set the root when the default format is one where it's
+ # not TREE_ROOT
+ mt.commit('foo', rev_id='parent-revid')
+ rt = mt.branch.repository.revision_tree('parent-revid')
+ state = dirstate.DirState.initialize('dirstate')
+ try:
+ state.set_parent_trees([('parent-revid', rt)], ghosts=[])
+ state.set_path_id('', 'foobarbaz')
+ # now see that it is what we expected
+ expected_rows = [
+ (('', '', 'TREE_ROOT'),
+ [('a', '', 0, False, ''),
+ ('d', '', 0, False, 'parent-revid'),
+ ]),
+ (('', '', 'foobarbaz'),
+ [('d', '', 0, False, ''),
+ ('a', '', 0, False, ''),
+ ]),
+ ]
+ self.assertEqual(expected_rows, list(state._iter_entries()))
+ # should work across save too
+ state.save()
+ finally:
+ state.unlock()
+ # now flush & check we get the same
+ state = dirstate.DirState.on_file('dirstate')
+ state.lock_read()
+ try:
+ self.assertEqual(expected_rows, list(state._iter_entries()))
+ finally:
+ state.unlock()
+
def test_set_parent_trees_no_content(self):
# set_parent_trees is a slow but important api to support.
tree1 = self.make_branch_and_memory_tree('tree1')
=== modified file 'bzrlib/tests/test_inv.py'
--- a/bzrlib/tests/test_inv.py 2007-02-22 05:51:57 +0000
+++ b/bzrlib/tests/test_inv.py 2007-03-01 10:14:03 +0000
@@ -312,6 +312,8 @@
self.file_1 = self.inv_1['fileid']
self.file_1b = self.inv_1['binfileid']
self.tree_2 = self.wt
+ self.tree_2.lock_read()
+ self.addCleanup(self.tree_2.unlock)
self.inv_2 = self.tree_2.read_working_inventory()
self.file_2 = self.inv_2['fileid']
self.file_2b = self.inv_2['binfileid']
@@ -419,6 +421,8 @@
self.tree_1 = self.branch.repository.revision_tree('1')
self.inv_1 = self.branch.repository.get_inventory('1')
self.file_1 = self.inv_1['fileid']
+ self.wt.lock_write()
+ self.addCleanup(self.wt.unlock)
self.file_active = self.wt.inventory['fileid']
self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
@@ -473,8 +477,8 @@
def test_snapshot_changed(self):
# This tests that a commit with one different parent results in a new
# revision id in the entry.
- self.file_active.name='newname'
- rename('subdir/file', 'subdir/newname')
+ self.wt.rename_one('subdir/file', 'subdir/newname')
+ self.file_active = self.wt.inventory['fileid']
self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1},
self.wt, self.builder)
# expected outcome - file_1 has a revision id of '2'
@@ -508,6 +512,8 @@
self.wt.add_parent_tree_id('B')
self.wt.commit('merge in B', rev_id='D')
self.inv_D = self.branch.repository.get_inventory('D')
+ self.wt.lock_read()
+ self.addCleanup(self.wt.unlock)
self.file_active = self.wt.inventory['fileid']
self.weave = self.branch.repository.weave_store.get_weave('fileid',
self.branch.repository.get_transaction())
@@ -608,10 +614,13 @@
def test_dangling_id(self):
wt = self.make_branch_and_tree('b1')
+ wt.lock_tree_write()
+ self.addCleanup(wt.unlock)
self.assertEqual(len(wt.inventory), 1)
open('b1/a', 'wb').write('a test\n')
wt.add('a')
self.assertEqual(len(wt.inventory), 2)
+ wt.flush() # workaround revert doing wt._write_inventory for now.
os.unlink('b1/a')
wt.revert([])
self.assertEqual(len(wt.inventory), 1)
=== modified file 'bzrlib/tests/test_smart_add.py'
--- a/bzrlib/tests/test_smart_add.py 2006-09-10 19:04:48 +0000
+++ b/bzrlib/tests/test_smart_add.py 2007-03-01 05:20:56 +0000
@@ -114,8 +114,6 @@
wt = self.make_branch_and_tree('.')
self.build_tree(['file'])
smart_add_tree(wt, ['file'], save=False)
- self.assertNotEqual(wt.path2id('file'), None, "No id added for 'file'")
- wt.read_working_inventory()
self.assertEqual(wt.path2id('file'), None)
def test_add_dry_run(self):
@@ -258,7 +256,9 @@
'added dir1/file2 with id file-dir1%file2\n',
'added file1 with id file-file1\n',
], lines)
- self.assertEqual([('', wt.inventory.root.file_id),
+ wt.lock_read()
+ self.addCleanup(wt.unlock)
+ self.assertEqual([('', wt.path2id('')),
('dir1', 'directory-dir1'),
('dir1/file2', 'file-dir1%file2'),
('file1', 'file-file1'),
@@ -341,6 +341,8 @@
# These should get newly generated ids
c_id = new_tree.path2id('c')
self.assertNotEqual(None, c_id)
+ self.base_tree.lock_read()
+ self.addCleanup(self.base_tree.unlock)
self.failIf(c_id in self.base_tree)
d_id = new_tree.path2id('subdir/d')
@@ -364,6 +366,8 @@
# matching path or child of 'subby'.
a_id = new_tree.path2id('subby/a')
self.assertNotEqual(None, a_id)
+ self.base_tree.lock_read()
+ self.addCleanup(self.base_tree.unlock)
self.failIf(a_id in self.base_tree)
@@ -383,6 +387,8 @@
osutils.normalized_filename = osutils._accessible_normalized_filename
try:
smart_add_tree(self.wt, [u'a\u030a'])
+ self.wt.lock_read()
+ self.addCleanup(self.wt.unlock)
self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
[(path, ie.kind) for path,ie in
self.wt.inventory.iter_entries()])
@@ -395,6 +401,8 @@
osutils.normalized_filename = osutils._accessible_normalized_filename
try:
smart_add_tree(self.wt, [])
+ self.wt.lock_read()
+ self.addCleanup(self.wt.unlock)
self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
[(path, ie.kind) for path,ie in
self.wt.inventory.iter_entries()])
=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py 2007-02-17 20:21:42 +0000
+++ b/bzrlib/tests/test_transform.py 2007-03-01 10:14:03 +0000
@@ -21,6 +21,7 @@
from bzrlib import (
errors,
generate_ids,
+ symbol_versioning,
tests,
urlutils,
)
@@ -525,10 +526,9 @@
create.new_file('vfile', root, 'myfile-text', 'myfile-id')
create.new_file('uvfile', root, 'othertext')
create.apply()
- self.assertEqual(find_interesting(wt, wt, ['vfile']),
- set(['myfile-id']))
- self.assertRaises(PathsNotVersionedError, find_interesting, wt, wt,
- ['uvfile'])
+ result = self.applyDeprecated(symbol_versioning.zero_fifteen,
+ find_interesting, wt, wt, ['vfile'])
+ self.assertEqual(result, set(['myfile-id']))
def test_set_executability_order(self):
"""Ensure that executability behaves the same, no matter what order.
=== modified file 'bzrlib/tests/workingtree_implementations/test_workingtree.py'
--- a/bzrlib/tests/workingtree_implementations/test_workingtree.py 2007-02-26 04:44:45 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_workingtree.py 2007-03-01 10:14:03 +0000
@@ -758,3 +758,28 @@
self.assertEqual(expected_results, list(tree.walkdirs()))
finally:
tree.unlock()
+
+ def test_path2id(self):
+ # smoke test for path2id
+ tree = self.make_branch_and_tree('.')
+ self.build_tree(['foo'])
+ tree.add(['foo'], ['foo-id'])
+ self.assertEqual('foo-id', tree.path2id('foo'))
+ # the next assertion is for backwards compatability with WorkingTree3,
+ # though its probably a bad idea, it makes things work. Perhaps
+ # it should raise a deprecation warning?
+ self.assertEqual('foo-id', tree.path2id('foo/'))
+
+ def test_filter_unversioned_files(self):
+ # smoke test for filter_unversioned_files
+ tree = self.make_branch_and_tree('.')
+ paths = ['here-and-versioned', 'here-and-not-versioned',
+ 'not-here-and-versioned', 'not-here-and-not-versioned']
+ tree.add(['here-and-versioned', 'not-here-and-versioned'],
+ kinds=['file', 'file'])
+ self.build_tree(['here-and-versioned', 'here-and-not-versioned'])
+ tree.lock_read()
+ self.addCleanup(tree.unlock)
+ self.assertEqual(
+ set(['not-here-and-not-versioned', 'here-and-not-versioned']),
+ tree.filter_unversioned_files(paths))
=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py 2007-02-26 02:56:24 +0000
+++ b/bzrlib/transform.py 2007-03-01 10:14:03 +0000
@@ -34,6 +34,7 @@
from bzrlib.osutils import (file_kind, supports_executable, pathjoin, lexists,
delete_any)
from bzrlib.progress import DummyProgress, ProgressPhase
+from bzrlib.symbol_versioning import deprecated_function, zero_fifteen
from bzrlib.trace import mutter, warning
from bzrlib import tree
import bzrlib.ui
@@ -1112,6 +1113,18 @@
it is silently replaced.
- Otherwise, conflict resolution will move the old file to 'oldname.moved'.
"""
+ wt.lock_tree_write()
+ try:
+ tree.lock_read()
+ try:
+ return _build_tree(tree, wt)
+ finally:
+ tree.unlock()
+ finally:
+ wt.unlock()
+
+def _build_tree(tree, wt):
+ """See build_tree."""
if len(wt.inventory) > 1: # more than just a root
raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
file_trans_id = {}
@@ -1266,10 +1279,21 @@
tt.set_executability(entry.executable, trans_id)
+ at deprecated_function(zero_fifteen)
def find_interesting(working_tree, target_tree, filenames):
- """Find the ids corresponding to specified filenames."""
- trees = (working_tree, target_tree)
- return tree.find_ids_across_trees(filenames, trees)
+ """Find the ids corresponding to specified filenames.
+
+ Deprecated: Please use tree1.paths2ids(filenames, [tree2]).
+ """
+ working_tree.lock_read()
+ try:
+ target_tree.lock_read()
+ try:
+ return working_tree.paths2ids(filenames, [target_tree])
+ finally:
+ target_tree.unlock()
+ finally:
+ working_tree.unlock()
def change_entry(tt, file_id, working_tree, target_tree,
=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py 2007-03-01 04:07:42 +0000
+++ b/bzrlib/tree.py 2007-03-01 10:14:03 +0000
@@ -304,7 +304,7 @@
pass
def filter_unversioned_files(self, paths):
- """Filter out paths that are not versioned.
+ """Filter out paths that are versioned.
:return: set of paths.
"""
@@ -464,58 +464,6 @@
specified_path_ids = _find_ids_across_trees(filenames, trees,
require_versioned)
return _find_children_across_trees(specified_path_ids, trees)
-# specified_ids = [id for path, id in _find_path_ids_across_trees(filenames, trees, require_versioned)]
-# return _find_children_across_trees(specified_ids, trees)
-
-def find_path_ids_across_trees(filenames, trees, require_versioned=True):
- """Find the paths and ids corresponding to specified filenames.
-
- All matches in all trees will be used, and all children of matched
- directories will be included
-
- :param filenames: The filenames to find file_ids for
- :param trees: The trees to find file_ids within
- :param require_versioned: if true, all specified filenames must occur in
- at least one tree.
- :return: a set of (path, file ids) for the specified filenames and their
- children. The returned path is the path of the id in the first tree
- that contains it. This matters when files have been moved
- """
- if not filenames:
- return set()
- # This function needs to know the ids for filenames in all trees, then
- # search for those same files and children in all the other trees.
- # it is complicated by the same path in two trees being able to have
- # different ids, which might both be present in both trees.
- # consider two trees, which have had 'mv foo bar' and 'mv baz foo' done
- # in this case, a diff of 'foo' should should changes to both the current
- # 'bar' and the current 'foo' which was baz. Its arguable that if
- # the situation is 'mv parent/foo bar' and 'mv baz parent/foo', that
- # we should return the current bar and the current parent/foo' - at the
- # moment we do, but we loop around all ids and all trees: I*T checks.
-
- # Updating this algorithm to be fast in the common case:
- # nothing has moved, all files have the same id in parent, child and there
- # are only two trees (or one is working tree and the others are parents).
- # walk the dirstate. as we find each path, gather the paths of that
- # id in all trees. add a mapping from the id to the path in those trees.
- # now lookup children by id, again in all trees; for these trees that
- # nothing has moved in, the id->path mapping will allow us to find the
- # parent trivially. To answer 'has anything been moved' in one of the
- # dirstate parent trees though, we will need to stare harder at it.
-
- # Now, given a path index, that is trivial for any one tree, and given
- # that we can ask for additional data from a dirstate tree, its a single
- # pass, though it will require scanning the entire tree to find paths
- # that were at the current location.
- # ideal results?: There are three things: tree, path, id. Pathologically
- # we can have completely disjoint ids for each tree; but we cannot have
- # disjoin paths for each tree, except if we scan each tree for the
- # different ids from other trees.
-
- specified_path_ids = _find_ids_across_trees(filenames, trees,
- require_versioned)
- return _find_path_id_children_across_trees(specified_path_ids, trees)
def _find_ids_across_trees(filenames, trees, require_versioned):
=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py 2007-03-01 04:07:42 +0000
+++ b/bzrlib/workingtree.py 2007-03-01 10:14:03 +0000
@@ -620,7 +620,7 @@
mode = os.lstat(self.abspath(path)).st_mode
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
- @needs_write_lock
+ @needs_tree_write_lock
def _add(self, files, ids, kinds):
"""See MutableTree._add."""
# TODO: Re-adding a file that is removed in the working copy
@@ -2706,9 +2706,11 @@
# formats which have no format string are not discoverable
# and not independently creatable, so are not registered.
__default_format = WorkingTreeFormat3()
+## __default_format = WorkingTreeFormat4()
WorkingTreeFormat.register_format(__default_format)
WorkingTreeFormat.register_format(WorkingTreeFormat4())
WorkingTreeFormat.register_format(WorkingTreeFormatAB1())
+## WorkingTreeFormat.register_format(WorkingTreeFormat3())
WorkingTreeFormat.set_default_format(__default_format)
# formats which have no format string are not discoverable
# and not independently creatable, so are not registered.
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-03-01 09:02:16 +0000
+++ b/bzrlib/workingtree_4.py 2007-03-01 10:14:03 +0000
@@ -174,7 +174,17 @@
# - on the first access it will be gathered, and we can
# always change this once tests are all passing.
state.add(f, file_id, kind, None, '')
+ self._make_dirty(reset_inventory=True)
+
+ def _make_dirty(self, reset_inventory):
+ """Make the tree state dirty.
+
+ :param reset_inventory: True if the cached inventory should be removed
+ (presuming there is one).
+ """
self._dirty = True
+ if reset_inventory and self._inventory is not None:
+ self._inventory = None
@needs_tree_write_lock
def add_reference(self, sub_tree):
@@ -253,7 +263,7 @@
return self._dirstate
def filter_unversioned_files(self, paths):
- """Filter out paths that are not versioned.
+ """Filter out paths that are versioned.
:return: set of paths.
"""
@@ -262,13 +272,13 @@
# results of each bisect in further still
paths = sorted(paths)
result = set()
- state = self.current_dirstate()
+ STate = self.current_dirstate()
# TODO we want a paths_to_dirblocks helper I think
for path in paths:
dirname, basename = os.path.split(path.encode('utf8'))
_, _, _, path_is_versioned = state._get_block_entry_index(
dirname, basename, 0)
- if path_is_versioned:
+ if not path_is_versioned:
result.add(path)
return result
@@ -692,7 +702,7 @@
raise
result.append((from_rel, to_rel))
state._dirblock_state = dirstate.DirState.IN_MEMORY_MODIFIED
- self._dirty = True
+ self._make_dirty(reset_inventory=False)
return result
@@ -707,6 +717,7 @@
@needs_read_lock
def path2id(self, path):
"""Return the id for path in this tree."""
+ path = path.strip('/')
entry = self._get_entry(path=path)
if entry == (None, None):
return None
@@ -946,13 +957,14 @@
self.branch.repository.revision_tree(None)))
ghosts.append(rev_id)
dirstate.set_parent_trees(real_trees, ghosts=ghosts)
- self._dirty = True
+ self._make_dirty(reset_inventory=False)
def _set_root_id(self, file_id):
"""See WorkingTree.set_root_id."""
state = self.current_dirstate()
state.set_path_id('', file_id)
- self._dirty = state._dirblock_state == dirstate.DirState.IN_MEMORY_MODIFIED
+ if state._dirblock_state == dirstate.DirState.IN_MEMORY_MODIFIED:
+ self._make_dirty(reset_inventory=True)
def unlock(self):
"""Unlock in format 4 trees needs to write the entire dirstate."""
@@ -1048,7 +1060,7 @@
block_index += 1
if ids_to_unversion:
raise errors.NoSuchId(self, iter(ids_to_unversion).next())
- self._dirty = True
+ self._make_dirty(reset_inventory=False)
# have to change the legacy inventory too.
if self._inventory is not None:
for file_id in file_ids:
@@ -1059,10 +1071,13 @@
"""Write inventory as the current inventory."""
assert not self._dirty, "attempting to write an inventory when the dirstate is dirty will cause data loss"
self.current_dirstate().set_state_from_inventory(inv)
- self._dirty = True
+ self._make_dirty(reset_inventory=False)
+ if self._inventory is not None:
+ self._inventory = inv
self.flush()
+
class WorkingTreeFormat4(WorkingTreeFormat3):
"""The first consolidated dirstate working tree format.
@@ -1115,20 +1130,24 @@
_control_files=control_files)
wt._new_tree()
wt.lock_tree_write()
+ state._validate()
try:
if revision_id in (None, NULL_REVISION):
wt._set_root_id(generate_ids.gen_root_id())
wt.flush()
+ wt.current_dirstate()._validate()
else:
wt.set_last_revision(revision_id)
wt.flush()
basis = wt.basis_tree()
basis.lock_read()
state = wt.current_dirstate()
+ state._validate()
# if the basis has a root id we have to use that; otherwise we use
# a new random one
basis_root_id = basis.get_root_id()
if basis_root_id is not None:
+ state._validate()
wt._set_root_id(basis_root_id)
wt.flush()
transform.build_tree(basis, wt)
@@ -1566,7 +1585,7 @@
all_versioned = False
break
if not all_versioned:
- raise errors.PathsNotVersionedError(paths)
+ raise errors.PathsNotVersionedError(specific_files)
# -- remove redundancy in supplied specific_files to prevent over-scanning --
search_specific_files = set()
for path in specific_files:
@@ -1943,12 +1962,15 @@
new_executable = bool(
stat.S_ISREG(current_path_info[3].st_mode)
and stat.S_IEXEC & current_path_info[3].st_mode)
- yield (None, current_path_info[0], True,
- (False, False),
- (None, None),
- (None, current_path_info[1]),
- (None, current_path_info[2]),
- (None, new_executable))
+ pass # unversioned file support not added to the
+ # _iter_changes api yet - breaks status amongst other
+ # things.
+# yield (None, current_path_info[0], True,
+# (False, False),
+# (None, None),
+# (None, current_path_info[1]),
+# (None, current_path_info[2]),
+# (None, new_executable))
elif current_path_info is None:
# no path is fine: the per entry code will handle it.
for result in _process_entry(current_entry, current_path_info):
More information about the bazaar-commits
mailing list