Rev 6119: (jelmer) Support repository formats without explicitly versioned directories in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Sep 1 10:55:29 UTC 2011


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 6119 [merge]
revision-id: pqm at pqm.ubuntu.com-20110901105526-jnqnr84fhdriyjee
parent: pqm at pqm.ubuntu.com-20110901084618-j9ajgwuc0q3ka4zu
parent: jelmer at samba.org-20110831231741-328lh2ipzqq4v3m3
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2011-09-01 10:55:26 +0000
message:
  (jelmer) Support repository formats without explicitly versioned directories
   in HasLayout. (Jelmer Vernooij)
modified:
  bzrlib/revisiontree.py         revisiontree.py-20060724012533-bg8xyryhxd0o0i0h-1
  bzrlib/tests/matchers.py       matchers.py-20100506074820-iiipsgdue8dhvidy-1
  bzrlib/tests/per_tree/test_tree.py test_tree.py-20061215160206-usu7lwcj8aq2n3br-1
  bzrlib/tests/per_workingtree/test_add.py test_add.py-20070226165239-4vo178spkrnhavc7-1
  bzrlib/tests/per_workingtree/test_move.py test_move.py-20070225171927-mohn2vqj5fx7edc6-1
  bzrlib/tests/per_workingtree/test_rename_one.py test_rename_one.py-20070226161242-2d8ibdedl700jgio-1
  bzrlib/tests/test_matchers.py  test_matchers.py-20100506074820-iiipsgdue8dhvidy-2
  bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
=== modified file 'bzrlib/revisiontree.py'
--- a/bzrlib/revisiontree.py	2011-06-16 11:58:04 +0000
+++ b/bzrlib/revisiontree.py	2011-08-29 19:06:57 +0000
@@ -36,6 +36,10 @@
         self._revision_id = revision_id
         self._rules_searcher = None
 
+    def has_versioned_directories(self):
+        """See `Tree.has_versioned_directories`."""
+        return self._repository._format.supports_versioned_directories
+
     def supports_tree_reference(self):
         return getattr(self._repository._format, "supports_tree_reference",
             False)

=== modified file 'bzrlib/tests/matchers.py'
--- a/bzrlib/tests/matchers.py	2011-08-16 13:26:27 +0000
+++ b/bzrlib/tests/matchers.py	2011-08-31 23:17:41 +0000
@@ -33,6 +33,7 @@
     ]
 
 from bzrlib import (
+    osutils,
     revision as _mod_revision,
     )
 
@@ -54,7 +55,7 @@
         self.lockable_thing = lockable_thing
 
     def __str__(self):
-        return ('ReturnsUnlockable(lockable_thing=%s)' % 
+        return ('ReturnsUnlockable(lockable_thing=%s)' %
             self.lockable_thing)
 
     def match(self, lock_method):
@@ -131,16 +132,46 @@
         """Get the (path, file_id) pairs for the current tree."""
         tree.lock_read()
         try:
-            return [(path, ie.file_id) for path, ie
-                    in tree.iter_entries_by_dir()]
+            for path, ie in tree.iter_entries_by_dir():
+                if ie.parent_id is None:
+                    yield (u"", ie.file_id)
+                else:
+                    yield (path+ie.kind_character(), ie.file_id)
         finally:
             tree.unlock()
 
+    @staticmethod
+    def _strip_unreferenced_directories(entries):
+        """Strip all directories that don't (in)directly contain any files.
+
+        :param entries: List of path strings or (path, ie) tuples to process
+        """
+        directories = []
+        for entry in entries:
+            if isinstance(entry, basestring):
+                path = entry
+            else:
+                path = entry[0]
+            if not path or path[-1] == "/":
+                # directory
+                directories.append((path, entry))
+            else:
+                # Yield the referenced parent directories
+                for dirpath, direntry in directories:
+                    if osutils.is_inside(dirpath, path):
+                        yield direntry
+                directories = []
+                yield entry
+
     def __str__(self):
-        return ('HasLayout(%r)' % self.entries)
+        return 'HasLayout(%r)' % self.entries
 
     def match(self, tree):
-        actual = self.get_tree_layout(tree)
+        actual = list(self.get_tree_layout(tree))
         if self.entries and isinstance(self.entries[0], basestring):
             actual = [path for (path, fileid) in actual]
-        return Equals(actual).match(self.entries)
+        if not tree.has_versioned_directories():
+            entries = list(self._strip_unreferenced_directories(self.entries))
+        else:
+            entries = self.entries
+        return Equals(entries).match(actual)

=== modified file 'bzrlib/tests/per_tree/test_tree.py'
--- a/bzrlib/tests/per_tree/test_tree.py	2011-08-05 13:34:40 +0000
+++ b/bzrlib/tests/per_tree/test_tree.py	2011-08-29 19:06:57 +0000
@@ -323,3 +323,11 @@
         if kind == "SHA1":
             expected = osutils.sha_strings('file content')
             self.assertEqual(expected, data)
+
+
+class TestHasVersionedDirectories(TestCaseWithTree):
+
+    def test_has_versioned_directories(self):
+        work_tree = self.make_branch_and_tree('tree')
+        tree = self._convert_tree(work_tree)
+        self.assertSubset([tree.has_versioned_directories()], (True, False))

=== modified file 'bzrlib/tests/per_workingtree/test_add.py'
--- a/bzrlib/tests/per_workingtree/test_add.py	2011-08-16 13:15:28 +0000
+++ b/bzrlib/tests/per_workingtree/test_add.py	2011-08-29 21:53:33 +0000
@@ -101,8 +101,8 @@
         tree.add(['dir/subdir/foo'], ['foo-id'])
         root_id = tree.get_root_id()
 
-        self.assertTreeLayout([('', root_id), ('dir', 'dir-id'),
-                               ('dir/subdir', 'subdir-id'),
+        self.assertTreeLayout([('', root_id), ('dir/', 'dir-id'),
+                               ('dir/subdir/', 'subdir-id'),
                                ('dir/subdir/foo', 'foo-id')], tree)
 
     def test_add_multiple(self):
@@ -113,7 +113,7 @@
         root_id = tree.get_root_id()
 
         self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
-                               ('dir', 'dir-id'), ('dir/subdir', 'subdir-id'),
+                               ('dir/', 'dir-id'), ('dir/subdir/', 'subdir-id'),
                                ('dir/subdir/foo', 'foo-id')], tree)
 
     def test_add_invalid(self):

=== modified file 'bzrlib/tests/per_workingtree/test_move.py'
--- a/bzrlib/tests/per_workingtree/test_move.py	2011-08-16 13:15:28 +0000
+++ b/bzrlib/tests/per_workingtree/test_move.py	2011-08-29 21:53:33 +0000
@@ -126,12 +126,12 @@
                           tree.move, ['d', 'c', 'b'], 'a')
         if osutils.lexists('a/c'):
             # If 'c' was actually moved, then 'd' should have also been moved
-            self.assertTreeLayout([('', root_id), ('a', 'a-id'),
+            self.assertTreeLayout([('', root_id), ('a/', 'a-id'),
                                    ('a/c', 'c-id'),  ('a/d', 'd-id')], tree)
         else:
-            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+            self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c', 'c-id'),
                                    ('d', 'd-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c', 'c-id'),
                                ('d', 'd-id')], tree.basis_tree())
         tree._validate()
 
@@ -145,7 +145,7 @@
         tree.remove(['a/b'], keep_files=False)
         self.assertEqual([('b', 'a/b')], tree.move(['b'], 'a'))
         self.assertTreeLayout([('', root_id),
-                               ('a', 'a-id'),
+                               ('a/', 'a-id'),
                                ('a/b', 'b-id'),
                               ], tree)
         tree._validate()
@@ -156,16 +156,16 @@
         tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
         tree.commit('initial', rev_id='rev-1')
         root_id = tree.get_root_id()
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree.basis_tree())
         a_contents = tree.get_file_text('a-id')
         self.assertEqual([('a', 'b/a')],
             tree.move(['a'], 'b'))
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id'),
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id'),
                                ('b/c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree.basis_tree())
         self.assertPathDoesNotExist('a')
         self.assertFileEqual(a_contents, 'b/a')
@@ -180,9 +180,9 @@
         c_contents = tree.get_file_text('c-id')
         self.assertEqual([('b/c', 'c')],
             tree.move(['b/c'], ''))
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree.basis_tree())
         self.assertPathDoesNotExist('b/c')
         self.assertFileEqual(c_contents, 'c')
@@ -200,13 +200,13 @@
         # 'c' may or may not have been moved, but either way the tree should
         # maintain a consistent state.
         if osutils.lexists('c'):
-            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                    ('c', 'c-id')], tree)
         else:
             self.assertPathExists('b/c')
-            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                    ('b/c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('c', 'c-id')], tree.basis_tree())
         tree._validate()
 
@@ -238,15 +238,15 @@
         root_id = tree.get_root_id()
         os.rename('a', 'b/a')
 
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         # We don't need after=True as long as source is missing and target
         # exists.
         self.assertEqual([('a', 'b/a')],
             tree.move(['a'], 'b'))
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id')],
                               tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         tree._validate()
 
@@ -258,14 +258,14 @@
         root_id = tree.get_root_id()
         os.rename('a', 'b/a')
 
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         # Passing after=True should work as well
         self.assertEqual([('a', 'b/a')],
             tree.move(['a'], 'b', after=True))
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id')],
                               tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         tree._validate()
 
@@ -279,7 +279,7 @@
         # Passing after when the file hasn't been move raises an exception
         self.assertRaises(errors.BzrMoveFailedError,
                           tree.move, ['a'], 'b', after=True)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         tree._validate()
 
@@ -303,20 +303,20 @@
         finally:
             ba_file.close()
 
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         self.assertRaises(errors.RenameFailedFilesExist,
                           tree.move, ['a'], 'b', after=False)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         self.assertFileEqual(a_text, 'a')
         self.assertFileEqual(ba_text, 'b/a')
         # But you can pass after=True
         self.assertEqual([('a', 'b/a')],
             tree.move(['a'], 'b', after=True))
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id')],
                               tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         # But it shouldn't actually move anything
         self.assertFileEqual(a_text, 'a')
@@ -333,11 +333,11 @@
 
         self.assertEqual([('a', 'e/a')],
             tree.move(['a'], 'e'))
-        self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/a', 'a-id'),
-                               ('e/a/b', 'b-id'), ('e/a/c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('e/', 'e-id'), ('e/a/', 'a-id'),
+                               ('e/a/b', 'b-id'), ('e/a/c/', 'c-id'),
                                ('e/a/c/d', 'd-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
-                               ('a/b', 'b-id'), ('a/c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('e/', 'e-id'),
+                               ('a/b', 'b-id'), ('a/c/', 'c-id'),
                                ('a/c/d', 'd-id')], tree.basis_tree())
         tree._validate()
 
@@ -355,9 +355,9 @@
         self.assertEqual([('c/b', 'b')],
                          tree.move(['c/b'], ''))
         self.assertTreeLayout([('', root_id),
-                               ('b', 'b-id'),
-                               ('c', 'c-id'),
-                               ('b/d', 'd-id'),
+                               ('b/', 'b-id'),
+                               ('c/', 'c-id'),
+                               ('b/d/', 'd-id'),
                               ], tree)
         tree._validate()
 
@@ -370,25 +370,18 @@
         root_id = tree.get_root_id()
 
         tree.rename_one('a/b', 'a/c/b')
-        if self.workingtree_format.supports_versioned_directories:
-            self.assertTreeLayout([('', root_id),
-                                   ('a', 'a-id'),
-                                   ('d', 'd-id'),
-                                   ('a/c', 'c-id'),
-                                   ('a/c/b', 'b-id'),
-                                  ], tree)
-        else:
-            self.assertTreeLayout([('', root_id),
-                                   ('a', 'a-id'),
-                                   ('a/c', 'c-id'),
-                                   ('a/c/b', 'b-id'),
-                                  ], tree)
+        self.assertTreeLayout([('', root_id),
+                               ('a/', 'a-id'),
+                               ('d/', 'd-id'),
+                               ('a/c/', 'c-id'),
+                               ('a/c/b', 'b-id'),
+                              ], tree)
         self.assertEqual([('a', 'd/a')],
                          tree.move(['a'], 'd'))
         self.assertTreeLayout([('', root_id),
-                               ('d', 'd-id'),
-                               ('d/a', 'a-id'),
-                               ('d/a/c', 'c-id'),
+                               ('d/', 'd-id'),
+                               ('d/a/', 'a-id'),
+                               ('d/a/c/', 'c-id'),
                                ('d/a/c/b', 'b-id'),
                               ], tree)
         tree._validate()
@@ -406,8 +399,8 @@
         self.assertEqual([('a', 'b/a')],
                          tree.move(['a'], 'b'))
         self.assertTreeLayout([('', root_id),
-                               ('b', 'b-id'),
-                               ('b/a', 'a-id'),
+                               ('b/', 'b-id'),
+                               ('b/a/', 'a-id'),
                                ('b/a/c', 'ac-id'),
                               ], tree)
         tree._validate()
@@ -425,8 +418,8 @@
         self.assertEqual([('a', 'b/a')],
                          tree.move(['a'], 'b'))
         self.assertTreeLayout([('', root_id),
-                               ('b', 'b-id'),
-                               ('b/a', 'a-id'),
+                               ('b/', 'b-id'),
+                               ('b/a/', 'a-id'),
                                ('b/a/b', 'ab-id'),
                                ('b/a/c', 'ac-id'),
                                ('b/a/d', 'ad-id'),
@@ -444,18 +437,18 @@
         self.assertEqual([('a/b', 'b')],
                          tree.move(['a/b'], ''))
         self.assertTreeLayout([('', root_id),
-                               ('a', 'a-id'),
+                               ('a/', 'a-id'),
                                ('b', 'b-id'),
                                ('d', 'd-id'),
-                               ('e', 'e-id'),
+                               ('e/', 'e-id'),
                                ('a/c', 'c-id'),
                               ], tree)
         self.assertEqual([('d', 'a/d')],
                          tree.move(['d'], 'a'))
         self.assertTreeLayout([('', root_id),
-                               ('a', 'a-id'),
+                               ('a/', 'a-id'),
                                ('b', 'b-id'),
-                               ('e', 'e-id'),
+                               ('e/', 'e-id'),
                                ('a/c', 'c-id'),
                                ('a/d', 'd-id'),
                               ], tree)
@@ -463,8 +456,8 @@
                          tree.move(['a'], 'e'))
         self.assertTreeLayout([('', root_id),
                                ('b', 'b-id'),
-                               ('e', 'e-id'),
-                               ('e/a', 'a-id'),
+                               ('e/', 'e-id'),
+                               ('e/a/', 'a-id'),
                                ('e/a/c', 'c-id'),
                                ('e/a/d', 'd-id'),
                               ], tree)
@@ -480,16 +473,16 @@
 
         tree.rename_one('a/b', 'a/d')
         self.assertTreeLayout([('', root_id),
-                               ('a', 'a-id'),
-                               ('d', 'd-id'),
+                               ('a/', 'a-id'),
+                               ('d/', 'd-id'),
                                ('a/c', 'c-id'),
                                ('a/d', 'b-id'),
                               ], tree)
         self.assertEqual([('a', 'd/a')],
                          tree.move(['a'], 'd'))
         self.assertTreeLayout([('', root_id),
-                               ('d', 'd-id'),
-                               ('d/a', 'a-id'),
+                               ('d/', 'd-id'),
+                               ('d/a/', 'a-id'),
                                ('d/a/c', 'c-id'),
                                ('d/a/d', 'b-id'),
                               ], tree)
@@ -507,8 +500,8 @@
         tree.rename_one('a/d', 'a/b')
         tree.rename_one('a/bb', 'a/d')
         self.assertTreeLayout([('', root_id),
-                               ('a', 'a-id'),
-                               ('e', 'e-id'),
+                               ('a/', 'a-id'),
+                               ('e/', 'e-id'),
                                ('a/b', 'd-id'),
                                ('a/c', 'c-id'),
                                ('a/d', 'b-id'),
@@ -516,8 +509,8 @@
         self.assertEqual([('a', 'e/a')],
                          tree.move(['a'], 'e'))
         self.assertTreeLayout([('', root_id),
-                               ('e', 'e-id'),
-                               ('e/a', 'a-id'),
+                               ('e/', 'e-id'),
+                               ('e/a/', 'a-id'),
                                ('e/a/b', 'd-id'),
                                ('e/a/c', 'c-id'),
                                ('e/a/d', 'b-id'),
@@ -534,16 +527,16 @@
 
         self.assertEqual([('a/b', 'c/b')],
             tree.move(['a/b'], 'c'))
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
                                ('c/b', 'b-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
                                ('a/b', 'b-id')], tree.basis_tree())
 
         self.assertEqual([('c/b', 'b')],
             tree.move(['c/b'], ''))
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
-                               ('c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('b', 'b-id'),
+                               ('c/', 'c-id')], tree)
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
                                ('a/b', 'b-id')], tree.basis_tree())
         tree._validate()
 

=== modified file 'bzrlib/tests/per_workingtree/test_rename_one.py'
--- a/bzrlib/tests/per_workingtree/test_rename_one.py	2011-08-16 13:15:28 +0000
+++ b/bzrlib/tests/per_workingtree/test_rename_one.py	2011-08-29 21:53:33 +0000
@@ -81,9 +81,9 @@
 
         a_contents = tree.get_file_text('a-id')
         tree.rename_one('a', 'foo')
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('foo', 'a-id')],
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('foo', 'a-id')],
                               tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         self.assertPathDoesNotExist('a')
         self.assertFileEqual(a_contents, 'foo')
@@ -97,9 +97,9 @@
 
         a_contents = tree.get_file_text('a-id')
         tree.rename_one('a', 'b/foo')
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/foo', 'a-id')],
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/foo', 'a-id')],
                               tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         self.assertPathDoesNotExist('tree/a')
         self.assertFileEqual(a_contents, 'tree/b/foo')
@@ -110,15 +110,15 @@
         tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
         tree.commit('initial', rev_id='rev-1')
         root_id = tree.get_root_id()
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree.basis_tree())
         a_contents = tree.get_file_text('a-id')
         tree.rename_one('a', 'b/d')
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/c', 'c-id'),
                                ('b/d', 'a-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree.basis_tree())
         self.assertPathDoesNotExist('a')
         self.assertFileEqual(a_contents, 'b/d')
@@ -131,9 +131,9 @@
         root_id = tree.get_root_id()
         c_contents = tree.get_file_text('c-id')
         tree.rename_one('b/c', 'd')
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('d', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('b/c', 'c-id')], tree.basis_tree())
         self.assertPathDoesNotExist('b/c')
         self.assertFileEqual(c_contents, 'd')
@@ -147,9 +147,9 @@
         # Target already exists
         self.assertRaises(errors.RenameFailedFilesExist,
                           tree.rename_one, 'a', 'b/a')
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
                                ('c', 'c-id')], tree.basis_tree())
 
     def test_rename_one_onto_existing(self):
@@ -187,14 +187,14 @@
         root_id = tree.get_root_id()
         os.rename('a', 'b/foo')
 
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         # We don't need after=True as long as source is missing and target
         # exists.
         tree.rename_one('a', 'b/foo')
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
                                ('b/foo', 'a-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
 
     def test_rename_one_after_with_after(self):
@@ -205,13 +205,13 @@
         root_id = tree.get_root_id()
         os.rename('a', 'b/foo')
 
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         # Passing after=True should work as well
         tree.rename_one('a', 'b/foo', after=True)
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
                                ('b/foo', 'a-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
 
     def test_rename_one_after_dest_versioned(self):
@@ -269,13 +269,13 @@
         os.rename('a', 'b/foo')
         tree.remove(['a'])
 
-        self.assertTreeLayout([('', root_id), ('b', 'b-id')], tree)
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id')], tree)
         # We don't need after=True as long as source is missing and target
         # exists.
         tree.rename_one('a', 'b/foo')
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
                                ('b/foo', 'a-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
 
     def test_rename_one_after_no_target(self):
@@ -288,9 +288,9 @@
         # Passing after when the file hasn't been rename_one raises an exception
         self.assertRaises(errors.BzrMoveFailedError,
                           tree.rename_one, 'a', 'b/foo', after=True)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
 
     def test_rename_one_after_source_and_dest(self):
@@ -313,19 +313,19 @@
         finally:
             foo_file.close()
 
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         self.assertRaises(errors.RenameFailedFilesExist,
                           tree.rename_one, 'a', 'b/foo', after=False)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree)
         self.assertFileEqual(a_text, 'a')
         self.assertFileEqual(foo_text, 'b/foo')
         # But you can pass after=True
         tree.rename_one('a', 'b/foo', after=True)
-        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
+        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
                                ('b/foo', 'a-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
+        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
                               tree.basis_tree())
         # But it shouldn't actually move anything
         self.assertFileEqual(a_text, 'a')
@@ -340,11 +340,11 @@
         root_id = tree.get_root_id()
 
         tree.rename_one('a', 'e/f')
-        self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/f', 'a-id'),
-                               ('e/f/b', 'b-id'), ('e/f/c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('e/', 'e-id'), ('e/f/', 'a-id'),
+                               ('e/f/b', 'b-id'), ('e/f/c/', 'c-id'),
                                ('e/f/c/d', 'd-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
-                               ('a/b', 'b-id'), ('a/c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('e/', 'e-id'),
+                               ('a/b', 'b-id'), ('a/c/', 'c-id'),
                                ('a/c/d', 'd-id')], tree.basis_tree())
 
     def test_rename_one_moved(self):
@@ -356,15 +356,15 @@
         root_id = tree.get_root_id()
 
         tree.rename_one('a/b', 'c/foo')
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
                                ('c/foo', 'b-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
                                ('a/b', 'b-id')], tree.basis_tree())
 
         tree.rename_one('c/foo', 'bar')
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('bar', 'b-id'),
-                               ('c', 'c-id')], tree)
-        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('bar', 'b-id'),
+                               ('c/', 'c-id')], tree)
+        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
                                ('a/b', 'b-id')], tree.basis_tree())
 
     def test_rename_to_denormalised_fails(self):

=== modified file 'bzrlib/tests/test_matchers.py'
--- a/bzrlib/tests/test_matchers.py	2011-08-16 13:26:27 +0000
+++ b/bzrlib/tests/test_matchers.py	2011-08-31 23:17:41 +0000
@@ -116,11 +116,11 @@
         t = self.make_branch_and_tree('.')
         self.build_tree(['a', 'b/', 'b/c'])
         t.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
-        self.assertThat(t, HasLayout(['', 'a', 'b', 'b/c']))
+        self.assertThat(t, HasLayout(['', 'a', 'b/', 'b/c']))
         self.assertThat(t, HasLayout(
             [('', t.get_root_id()),
              ('a', 'a-id'),
-             ('b', 'b-id'),
+             ('b/', 'b-id'),
              ('b/c', 'c-id')]))
 
     def test_mismatch(self):
@@ -130,5 +130,19 @@
         mismatch = HasLayout(['a']).match(t)
         self.assertIsNot(None, mismatch)
         self.assertEquals(
-            "[u'', u'a', u'b', u'b/c'] != ['a']",
+            "['a'] != [u'', u'a', u'b/', u'b/c']",
+            mismatch.describe())
+
+    def test_no_dirs(self):
+        # Some tree/repository formats do not support versioned directories
+        t = self.make_branch_and_tree('.')
+        t.has_versioned_directories = lambda: False
+        self.build_tree(['a', 'b/', 'b/c'])
+        t.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
+        self.assertIs(None, HasLayout(['', 'a', 'b/', 'b/c']).match(t))
+        self.assertIs(None, HasLayout(['', 'a', 'b/', 'b/c', 'd/']).match(t))
+        mismatch = HasLayout([u'', u'a', u'd/']).match(t)
+        self.assertIsNot(None, mismatch)
+        self.assertEquals(
+            "[u'', u'a'] != [u'', u'a', u'b/', u'b/c']",
             mismatch.describe())

=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py	2011-08-05 13:34:40 +0000
+++ b/bzrlib/tree.py	2011-08-29 19:06:57 +0000
@@ -58,6 +58,14 @@
     trees or versioned trees.
     """
 
+    def has_versioned_directories(self):
+        """Whether this tree can contain explicitly versioned directories.
+
+        This defaults to True, but some implementations may want to override
+        it.
+        """
+        return True
+
     def changes_from(self, other, want_unchanged=False, specific_files=None,
         extra_trees=None, require_versioned=False, include_root=False,
         want_unversioned=False):

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2011-08-30 09:29:03 +0000
+++ b/bzrlib/workingtree.py	2011-09-01 10:55:26 +0000
@@ -224,6 +224,10 @@
             the working tree has been constructed from.
             """)
 
+    def has_versioned_directories(self):
+        """See `Tree.has_versioned_directories`."""
+        return self._format.supports_versioned_directories
+
     def break_lock(self):
         """Break a lock if one is present from another instance.
 




More information about the bazaar-commits mailing list