Rev 2979: (robertc) Fix WorkingTree.walkdirs to support walking an empty directory. (Marius Kruger) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Mon Nov 12 19:54:33 GMT 2007


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

------------------------------------------------------------
revno: 2979
revision-id: pqm at pqm.ubuntu.com-20071112195430-0xgqswqpc1j2pk2m
parent: pqm at pqm.ubuntu.com-20071109195036-5o5bwu0a01uniqwg
parent: amanic at gmail.com-20071027214542-xmp0swkwzwvivd0v
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2007-11-12 19:54:30 +0000
message:
  (robertc) Fix WorkingTree.walkdirs to support walking an empty directory. (Marius Kruger)
modified:
  bzrlib/tests/workingtree_implementations/test_walkdirs.py test_walkdirs.py-20060731045042-ch366w6dve2m7ro9-1
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
    ------------------------------------------------------------
    revno: 2457.2.7
    merged: amanic at gmail.com-20071027214542-xmp0swkwzwvivd0v
    parent: amanic at gmail.com-20071027202558-fenj4xffah1icef2
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Sat 2007-10-27 23:45:42 +0200
    message:
      extract method as per review request
    ------------------------------------------------------------
    revno: 2457.2.6
    merged: amanic at gmail.com-20071027202558-fenj4xffah1icef2
    parent: amanic at gmail.com-20071027202258-lne296tnecc7ihcg
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Sat 2007-10-27 22:25:58 +0200
    message:
      add DirBlock comment
    ------------------------------------------------------------
    revno: 2457.2.5
    merged: amanic at gmail.com-20071027202258-lne296tnecc7ihcg
    parent: amanic at gmail.com-20071027195529-oy291e5h03koi1j6
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Sat 2007-10-27 22:22:58 +0200
    message:
      move DirBlock out of TestWalkdirs as per review comment
    ------------------------------------------------------------
    revno: 2457.2.4
    merged: amanic at gmail.com-20071027195529-oy291e5h03koi1j6
    parent: amanic at gmail.com-20071027195346-kll2vxgdza8io5ry
    parent: pqm at pqm.ubuntu.com-20071025022746-ftudwmzir8v2lccc
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Sat 2007-10-27 21:55:29 +0200
    message:
      merge with bzr.dev
    ------------------------------------------------------------
    revno: 2457.2.3
    merged: amanic at gmail.com-20071027195346-kll2vxgdza8io5ry
    parent: amanic at gmail.com-20070812081515-vgekipfhohcuj6rn
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Sat 2007-10-27 21:53:46 +0200
    message:
      factor out tuples into better readable variables
    ------------------------------------------------------------
    revno: 2457.2.2
    merged: amanic at gmail.com-20070812081515-vgekipfhohcuj6rn
    parent: amanic at gmail.com-20070427190445-2xp5a3g4mvu8jpdh
    parent: pqm at pqm.ubuntu.com-20070810230629-bcp0rgmbhp0z35e1
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Sun 2007-08-12 10:15:15 +0200
    message:
      merge with bzr.dev
    ------------------------------------------------------------
    revno: 2457.2.1
    merged: amanic at gmail.com-20070427190445-2xp5a3g4mvu8jpdh
    parent: pqm at pqm.ubuntu.com-20070426021942-eutaiob3qgh6kln8
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.workingtree.walk_empty_dir
    timestamp: Fri 2007-04-27 21:04:45 +0200
    message:
      * Fix workingtree.walkdirs to support getting a prefix which specifies an empty directory.
      * tests/workingtree_implementations/test_walkdirs
        - Add tests for walking empty directories.
        - Combine get_tree_with_unknowns and get_tree_with_missings into
          get_tree which is a little more flexible.
        - Add nested class DirBlock which simplifies working with the
          dirblocks a little.
=== modified file 'bzrlib/tests/workingtree_implementations/test_walkdirs.py'
--- a/bzrlib/tests/workingtree_implementations/test_walkdirs.py	2007-11-01 09:52:45 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_walkdirs.py	2007-11-12 19:54:30 +0000
@@ -25,116 +25,142 @@
 # tests to write:
 # type mismatches - file to link, dir, dir to file, link, link to file, dir
 
+class DirBlock:
+    """Object representation of the tuples returned by dirstate."""
+
+    def __init__(self, tree, file_path, file_name=None, id=None,
+                 inventory_kind=None, stat=None, disk_kind='unknown'):
+        self.file_path = file_path
+        self.abspath = tree.abspath(file_path)
+        self.relpath = tree.relpath(file_path)
+        if file_name == None:
+           file_name = os.path.split(file_path)[-1]
+           if len(file_name) == 0:
+               file_name = os.path.split(file_path)[-2]
+        self.file_name = file_name
+        self.id = id
+        self.inventory_kind = inventory_kind
+        self.stat = stat
+        self.disk_kind = disk_kind
+
+    def as_tuple(self):
+         return (self.relpath, self.file_name, self.disk_kind,
+                 self.stat, self.id, self.inventory_kind)
+
+    def as_dir_tuple(self):
+         return (self.relpath, self.id)
+
+    def __str__(self):
+        return """
+file_path      = %r
+abspath        = %r
+relpath        = %r
+file_name      = %r
+id             = %r
+inventory_kind = %r
+stat           = %r
+disk_kind      = %r""" % (self.file_path, self.abspath, self.relpath,
+        self.file_name, self.id, self.inventory_kind, self.stat,
+        self.disk_kind)
+
+
 class TestWalkdirs(TestCaseWithWorkingTree):
 
-    def get_tree_with_unknowns(self):
+    added='added'
+    missing='missing'
+    unknown='unknown'
+
+    def get_tree(self, file_status, prefix=None):
         tree = self.make_branch_and_tree('.')
-        self.build_tree([
-            'unknown file',
-            'unknown dir/',
-            'unknown dir/a file',
-            ])
-        u_f_stat = os.lstat('unknown file')
-        u_d_stat = os.lstat('unknown dir')
-        u_d_f_stat = os.lstat('unknown dir/a file')
+        dirblocks = []
+        paths = [
+            file_status + ' file',
+            file_status + ' dir/',
+            file_status + ' dir/a file',
+            file_status + ' empty dir/',
+            ]
+        self.build_tree(paths)
+
+        def add_dirblock(path, kind):
+            dirblock = DirBlock(tree, path)
+            if file_status != self.unknown:
+                dirblock.id = 'a ' + str(path).replace('/','-') + '-id'
+                dirblock.inventory_kind = kind
+            if file_status != self.missing:
+                dirblock.disk_kind = kind
+                dirblock.stat = os.lstat(dirblock.relpath)
+            dirblocks.append(dirblock)
+
+        add_dirblock(paths[0], 'file')
+        add_dirblock(paths[1], 'directory')
+        add_dirblock(paths[2], 'file')
+        add_dirblock(paths[3], 'directory')
+
+        if file_status != self.unknown:
+            tree.add(paths, [db.id for db in dirblocks])
+
+        if file_status == self.missing:
+            # now make the files be missing
+            tree.bzrdir.root_transport.delete(dirblocks[0].relpath)
+            tree.bzrdir.root_transport.delete_tree(dirblocks[1].relpath)
+            tree.bzrdir.root_transport.delete_tree(dirblocks[3].relpath)
+
         expected_dirblocks = [
             (('', tree.path2id('')),
-             [
-              ('unknown dir', 'unknown dir', 'directory', u_d_stat, None, None),
-              ('unknown file', 'unknown file', 'file', u_f_stat, None, None),
-             ]
-            ),
-            (('unknown dir', None),
-             [('unknown dir/a file', 'a file', 'file', u_d_f_stat, None, None),
-             ]
+             [dirblocks[1].as_tuple(), dirblocks[3].as_tuple(),
+              dirblocks[0].as_tuple()]
+            ),
+            (dirblocks[1].as_dir_tuple(),
+             [dirblocks[2].as_tuple()]
+            ),
+            (dirblocks[3].as_dir_tuple(),
+             []
             ),
             ]
+        if prefix:
+            expected_dirblocks = [e for e in expected_dirblocks
+                if len(e) > 0 and len(e[0]) > 0 and e[0][0] == prefix]
         return tree, expected_dirblocks
-    
+
+    def _test_walkdir(self, file_status, prefix=""):
+        result = []
+        tree, expected_dirblocks = self.get_tree(file_status, prefix)
+        tree.lock_read()
+        for dirinfo, dirblock in tree.walkdirs(prefix):
+            result.append((dirinfo, list(dirblock)))
+        tree.unlock()
+
+        # check each return value for debugging ease.
+        for pos, item in enumerate(expected_dirblocks):
+            result_pos = []
+            if len(result) > pos:
+                result_pos = result[pos]
+            self.assertEqual(item, result_pos)
+        self.assertEqual(expected_dirblocks, result)
+
     def test_walkdir_unknowns(self):
         """unknown files and directories should be reported by walkdirs."""
-        # test that its iterable by iterating:
-        result = []
-        tree, expected_dirblocks = self.get_tree_with_unknowns()
-        tree.lock_read()
-        for dirinfo, dirblock in tree.walkdirs():
-            result.append((dirinfo, list(dirblock)))
-        tree.unlock()
-        # check each return value for debugging ease.
-        for pos, item in enumerate(expected_dirblocks):
-            self.assertEqual(item, result[pos])
-        self.assertEqual(len(expected_dirblocks), len(result))
+        self._test_walkdir(self.unknown)
 
     def test_walkdir_from_unknown_dir(self):
         """Doing a walkdir when the requested prefix is unknown but on disk."""
-        result = []
-        tree, expected_dirblocks = self.get_tree_with_unknowns()
-        tree.lock_read()
-        for dirinfo, dirblock in tree.walkdirs('unknown dir'):
-            result.append((dirinfo, list(dirblock)))
-        tree.unlock()
-        # check each return value for debugging ease.
-        for pos, item in enumerate(expected_dirblocks[1:]):
-            self.assertEqual(item, result[pos])
-        self.assertEqual(len(expected_dirblocks) - 1, len(result))
+        self._test_walkdir(self.unknown, 'unknown dir')
 
-    def get_tree_with_missings(self):
-        tree = self.make_branch_and_tree('.')
-        paths = [
-            'missing file',
-            'missing dir/',
-            'missing dir/a file',
-            ]
-        ids = [
-            'a file',
-            'a dir',
-            'a dir-a file',
-            ]
-        self.build_tree(paths)
-        tree.add(paths, ids)
-        # now make the files be missing
-        tree.bzrdir.root_transport.delete_tree('missing dir')
-        tree.bzrdir.root_transport.delete('missing file')
-        expected_dirblocks = [
-            (('', tree.path2id('')),
-             [
-              ('missing dir', 'missing dir', 'unknown', None, 'a dir', 'directory'),
-              ('missing file', 'missing file', 'unknown', None, 'a file', 'file'),
-             ]
-            ),
-            (('missing dir', 'a dir'),
-             [('missing dir/a file', 'a file', 'unknown', None, 'a dir-a file', 'file'),
-             ]
-            ),
-            ]
-        return tree, expected_dirblocks
-    
     def test_walkdir_missings(self):
         """missing files and directories should be reported by walkdirs."""
-        # test that its iterable by iterating:
-        result = []
-        tree, expected_dirblocks = self.get_tree_with_missings()
-        tree.lock_read()
-        for dirinfo, dirblock in tree.walkdirs():
-            result.append((dirinfo, list(dirblock)))
-        tree.unlock()
-        # check each return value for debugging ease.
-        for pos, item in enumerate(expected_dirblocks):
-            self.assertEqual(item, result[pos])
-        self.assertEqual(len(expected_dirblocks), len(result))
+        self._test_walkdir(self.missing)
+
+    def test_walkdir_from_dir(self):
+        """Doing a walkdir when the requested prefix is known and on disk."""
+        self._test_walkdir(self.added, 'added dir')
+
+    def test_walkdir_from_empty_dir(self):
+        """Doing a walkdir when the requested prefix is empty dir."""
+        self._test_walkdir(self.added, 'added empty dir')
 
     def test_walkdir_from_missing_dir(self):
         """Doing a walkdir when the requested prefix is missing but on disk."""
-        result = []
-        tree, expected_dirblocks = self.get_tree_with_missings()
-        tree.lock_read()
-        for dirinfo, dirblock in tree.walkdirs('missing dir'):
-            result.append((dirinfo, list(dirblock)))
-        tree.unlock()
-        # check each return value for debugging ease.
-        for pos, item in enumerate(expected_dirblocks[1:]):
-            self.assertEqual(item, result[pos])
-        self.assertEqual(len(expected_dirblocks[1:]), len(result))
+        self._test_walkdir(self.missing, 'missing dir')
 
     def test_walkdirs_type_changes(self):
         """Walkdir shows the actual kinds on disk and the recorded kinds."""

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2007-11-03 09:39:11 +0000
+++ b/bzrlib/workingtree.py	2007-11-12 19:54:30 +0000
@@ -2302,16 +2302,24 @@
             current_inv = None
             inv_finished = True
         while not inv_finished or not disk_finished:
+            if current_disk:
+                ((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
+                    cur_disk_dir_content) = current_disk
+            else:
+                ((cur_disk_dir_relpath, cur_disk_dir_path_from_top),
+                    cur_disk_dir_content) = ((None, None), None)
             if not disk_finished:
                 # strip out .bzr dirs
-                if current_disk[0][1][top_strip_len:] == '':
-                    # osutils.walkdirs can be made nicer - 
+                if (cur_disk_dir_path_from_top[top_strip_len:] == '' and
+                    len(cur_disk_dir_content) > 0):
+                    # osutils.walkdirs can be made nicer -
                     # yield the path-from-prefix rather than the pathjoined
                     # value.
-                    bzrdir_loc = bisect_left(current_disk[1], ('.bzr', '.bzr'))
-                    if current_disk[1][bzrdir_loc][0] == '.bzr':
+                    bzrdir_loc = bisect_left(cur_disk_dir_content,
+                        ('.bzr', '.bzr'))
+                    if cur_disk_dir_content[bzrdir_loc][0] == '.bzr':
                         # we dont yield the contents of, or, .bzr itself.
-                        del current_disk[1][bzrdir_loc]
+                        del cur_disk_dir_content[bzrdir_loc]
             if inv_finished:
                 # everything is unknown
                 direction = 1
@@ -2319,12 +2327,13 @@
                 # everything is missing
                 direction = -1
             else:
-                direction = cmp(current_inv[0][0], current_disk[0][0])
+                direction = cmp(current_inv[0][0], cur_disk_dir_relpath)
             if direction > 0:
                 # disk is before inventory - unknown
                 dirblock = [(relpath, basename, kind, stat, None, None) for
-                    relpath, basename, kind, stat, top_path in current_disk[1]]
-                yield (current_disk[0][0], None), dirblock
+                    relpath, basename, kind, stat, top_path in
+                    cur_disk_dir_content]
+                yield (cur_disk_dir_relpath, None), dirblock
                 try:
                     current_disk = disk_iterator.next()
                 except StopIteration:
@@ -2332,7 +2341,7 @@
             elif direction < 0:
                 # inventory is before disk - missing.
                 dirblock = [(relpath, basename, 'unknown', None, fileid, kind)
-                    for relpath, basename, dkind, stat, fileid, kind in 
+                    for relpath, basename, dkind, stat, fileid, kind in
                     current_inv[1]]
                 yield (current_inv[0][0], current_inv[0][1]), dirblock
                 try:
@@ -2344,7 +2353,8 @@
                 # merge the inventory and disk data together
                 dirblock = []
                 for relpath, subiterator in itertools.groupby(sorted(
-                    current_inv[1] + current_disk[1], key=operator.itemgetter(0)), operator.itemgetter(1)):
+                    current_inv[1] + cur_disk_dir_content,
+                    key=operator.itemgetter(0)), operator.itemgetter(1)):
                     path_elements = list(subiterator)
                     if len(path_elements) == 2:
                         inv_row, disk_row = path_elements




More information about the bazaar-commits mailing list