Rev 3697: Refactor bzrlib.osutils._walkdirs_utf8 to aid API migration in future. in http://people.ubuntu.com/~robertc/baz2.0/readdir

Robert Collins robertc at robertcollins.net
Tue Sep 9 02:53:11 BST 2008


At http://people.ubuntu.com/~robertc/baz2.0/readdir

------------------------------------------------------------
revno: 3697
revision-id: robertc at robertcollins.net-20080909015303-183ct6bgha6e8tg7
parent: pqm at pqm.ubuntu.com-20080908061835-nz7hj7o0pms1nf9p
committer: Robert Collins <robertc at robertcollins.net>
branch nick: readdir
timestamp: Tue 2008-09-09 11:53:03 +1000
message:
  Refactor bzrlib.osutils._walkdirs_utf8 to aid API migration in future.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/tests/test__walkdirs_win32.py test__walkdirs_win32-20080716220454-kweh3tgxez5dvw2l-3
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
=== modified file 'NEWS'
--- a/NEWS	2008-09-06 10:25:39 +0000
+++ b/NEWS	2008-09-09 01:53:03 +0000
@@ -166,6 +166,10 @@
       is unknown in both source and target.
       (Robert Collins, Aaron Bentley)
 
+    * ``bzrlib.osutils._walkdirs_utf8`` has been refactored into common
+      tree walking, and modular directory listing code to aid future
+      performance optimisations and refactoring. (Robert Collins)
+
     * ``GraphIndexBuilder.add_node`` and ``BTreeBuilder`` have been
       streamlined a bit. This should make creating large indexes faster.
       (In benchmarking, it now takes less time to create a BTree index than

=== modified file 'bzrlib/_walkdirs_win32.pyx'
--- a/bzrlib/_walkdirs_win32.pyx	2008-07-17 20:23:45 +0000
+++ b/bzrlib/_walkdirs_win32.pyx	2008-09-09 01:53:03 +0000
@@ -151,30 +151,19 @@
     return 0
 
 
-cdef class Win32Finder:
-    """A class which encapsulates the search of files in a given directory"""
-
-    cdef object _top
-    cdef object _prefix
+cdef class Win32ReadDir:
+    """Read directories on win32."""
 
     cdef object _directory_kind
     cdef object _file_kind
 
-    cdef object _pending
-    cdef object _last_dirblock
-
-    def __init__(self, top, prefix=""):
-        self._top = top
-        self._prefix = prefix
-
+    def __init__(self):
         self._directory_kind = osutils._directory_kind
         self._file_kind = osutils._formats[stat.S_IFREG]
 
-        self._pending = [(osutils.safe_utf8(prefix), osutils.safe_unicode(top))]
-        self._last_dirblock = None
-
-    def __iter__(self):
-        return self
+    def top_prefix_to_starting_dir(self, top, prefix=""):
+        """See DirReader.top_prefix_to_starting_dir."""
+        return (osutils.safe_utf8(prefix), osutils.safe_unicode(top))
 
     cdef object _get_kind(self, WIN32_FIND_DATAW *data):
         if data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY:
@@ -195,16 +184,10 @@
         statvalue.st_dev = 0
         return statvalue
 
-    def _get_files_in(self, directory, relprefix):
-        """Return the dirblock for all files in the given directory.
+    def read_dir(self, prefix, top):
+        """Win32 implementation of DirReader.read_dir.
 
-        :param directory: A path that can directly access the files on disk.
-            Should be a Unicode object.
-        :param relprefix: A psuedo path for these files (as inherited from the
-            original 'prefix=XXX' when instantiating this class.)
-            It should be a UTF-8 string.
-        :return: A dirblock for all the files of the form
-            [(utf8_relpath, utf8_fname, kind, _Win32Stat, unicode_abspath)]
+        :seealso: DirReader.read_dir
         """
         cdef WIN32_FIND_DATAW search_data
         cdef HANDLE hFindFile
@@ -212,7 +195,13 @@
         cdef WCHAR *query
         cdef int result
 
-        top_star = directory + '*'
+        if prefix:
+            relprefix = prefix + '/'
+        else:
+            relprefix = ''
+        top_slash = top + '/'
+
+        top_star = top + '*'
 
         dirblock = []
 
@@ -235,7 +224,7 @@
                     (relprefix + name_utf8, name_utf8, 
                      self._get_kind(&search_data),
                      self._get_stat_value(&search_data),
-                     directory + name_unicode))
+                     top + name_unicode))
 
                 result = FindNextFileW(hFindFile, &search_data)
             # FindNextFileW sets GetLastError() == ERROR_NO_MORE_FILES when it
@@ -251,43 +240,5 @@
                 # TODO: We should probably raise an exception if FindClose
                 #       returns an error, however, I don't want to supress an
                 #       earlier Exception, so for now, I'm ignoring this
+        dirblock.sort(key=operator.itemgetter(1))
         return dirblock
-
-    cdef _update_pending(self):
-        """If we had a result before, add the subdirs to pending."""
-        if self._last_dirblock is not None:
-            # push the entries left in the dirblock onto the pending queue
-            # we do this here, because we allow the user to modified the
-            # queue before the next iteration
-            for d in reversed(self._last_dirblock):
-                if d[2] == self._directory_kind:
-                    self._pending.append((d[0], d[-1]))
-            self._last_dirblock = None
-        
-    def __next__(self):
-        self._update_pending()
-        if not self._pending:
-            raise StopIteration()
-        relroot, top = self._pending.pop()
-        # NB: At the moment Pyrex doesn't support Unicode literals, which means
-        # that all of these string literals are going to be upcasted to Unicode
-        # at runtime... :(
-        # Maybe we could use unicode(x) during __init__?
-        if relroot:
-            relprefix = relroot + '/'
-        else:
-            relprefix = ''
-        top_slash = top + '/'
-
-        dirblock = self._get_files_in(top_slash, relprefix)
-        dirblock.sort(key=operator.itemgetter(1))
-        self._last_dirblock = dirblock
-        return (relroot, top), dirblock
-
-
-def _walkdirs_utf8_win32_find_file(top, prefix=""):
-    """Implement a version of walkdirs_utf8 for win32.
-
-    This uses the find files api to both list the files and to stat them.
-    """
-    return Win32Finder(top, prefix=prefix)

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2008-09-03 20:00:51 +0000
+++ b/bzrlib/osutils.py	2008-09-09 01:53:03 +0000
@@ -1231,7 +1231,33 @@
         pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
 
 
-_real_walkdirs_utf8 = None
+class DirReader(object):
+    """An interface for reading directories."""
+
+    def top_prefix_to_starting_dir(self, top, prefix=""):
+        """Converts top and prefix to a starting dir entry
+
+        :param top: A utf8 path
+        :param prefix: An optional utf8 path to prefix output relative paths
+            with.
+        :return: A tuple starting with prefix, and ending with the native
+            encoding of top.
+        """
+        raise NotImplementedError(self.top_prefix_to_starting_dir)
+
+    def read_dir(self, prefix, top):
+        """Read a specific dir.
+
+        :param prefix: A utf8 prefix to be preprended to the path basenames.
+        :param top: A natively encoded path to read.
+        :return: A sorted list of the directories contents. Each item contains:
+            (utf8_relpath, utf8_name, kind, lstatvalue, native_abspath)
+        """
+        raise NotImplementedError(self.read_dir)
+
+
+_selected_dir_reader = None
+
 
 def _walkdirs_utf8(top, prefix=""):
     """Yield data about all the directories in a tree.
@@ -1247,8 +1273,8 @@
         path-from-top might be unicode or utf8, but it is the correct path to
         pass to os functions to affect the file in question. (such as os.lstat)
     """
-    global _real_walkdirs_utf8
-    if _real_walkdirs_utf8 is None:
+    global _selected_dir_reader
+    if _selected_dir_reader is None:
         fs_encoding = _fs_enc.upper()
         if win32utils.winver == 'Windows NT':
             # Win98 doesn't have unicode apis like FindFirstFileW
@@ -1257,38 +1283,53 @@
             #       but that gets a bit tricky, and requires custom compiling
             #       for win98 anyway.
             try:
-                from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+                from bzrlib._walkdirs_win32 import Win32ReadDir
             except ImportError:
-                _real_walkdirs_utf8 = _walkdirs_unicode_to_utf8
+                _selected_dir_reader = UnicodeDirReader()
             else:
-                _real_walkdirs_utf8 = _walkdirs_utf8_win32_find_file
+                _selected_dir_reader = Win32ReadDir()
         elif fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
             # ANSI_X3.4-1968 is a form of ASCII
-            _real_walkdirs_utf8 = _walkdirs_unicode_to_utf8
+            _selected_dir_reader = UnicodeDirReader()
         else:
-            _real_walkdirs_utf8 = _walkdirs_fs_utf8
-    return _real_walkdirs_utf8(top, prefix=prefix)
-
-
-def _walkdirs_fs_utf8(top, prefix=""):
-    """See _walkdirs_utf8.
-
-    This sub-function is called when we know the filesystem is already in utf8
-    encoding. So we don't need to transcode filenames.
-    """
-    _lstat = os.lstat
-    _directory = _directory_kind
-    # Use C accelerated directory listing.
-    _listdir = _read_dir
-    _kind_from_mode = _formats.get
-
+            _selected_dir_reader = UTF8DirReader()
     # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
     # But we don't actually uses 1-3 in pending, so set them to None
-    pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
+    pending = [_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]
+    read_dir = _selected_dir_reader.read_dir
+    _directory = _directory_kind
     while pending:
         relroot, _, _, _, top = pending.pop()
-        if relroot:
-            relprefix = relroot + '/'
+        dirblock = read_dir(relroot, top)
+        yield (relroot, top), dirblock
+        # push the user specified dirs from dirblock
+        pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
+
+
+class UTF8DirReader(DirReader):
+    """A dir reader for utf8 file systems."""
+
+    def top_prefix_to_starting_dir(self, top, prefix=""):
+        """See DirReader.top_prefix_to_starting_dir."""
+        return (safe_utf8(prefix), None, None, None, safe_utf8(top))
+
+    def read_dir(self, prefix, top):
+        """Read a single directory from a utf8 file system.
+
+        All paths in and out are utf8.
+
+        This sub-function is called when we know the filesystem is already in utf8
+        encoding. So we don't need to transcode filenames.
+
+        See DirReader.read_dir for details.
+        """
+        _lstat = os.lstat
+        # Use C accelerated directory listing.
+        _listdir = _read_dir
+        _kind_from_mode = _formats.get
+
+        if prefix:
+            relprefix = prefix + '/'
         else:
             relprefix = ''
         top_slash = top + '/'
@@ -1302,33 +1343,41 @@
             kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
             append((relprefix + name, name, kind, statvalue, abspath))
         dirblock.sort()
-        yield (relroot, top), dirblock
-
-        # push the user specified dirs from dirblock
-        pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
-
-
-def _walkdirs_unicode_to_utf8(top, prefix=""):
-    """See _walkdirs_utf8
-
-    Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
-    Unicode paths.
-    This is currently the fallback code path when the filesystem encoding is
-    not UTF-8. It may be better to implement an alternative so that we can
-    safely handle paths that are not properly decodable in the current
-    encoding.
-    """
-    _utf8_encode = codecs.getencoder('utf8')
-    _lstat = os.lstat
-    _directory = _directory_kind
-    _listdir = os.listdir
-    _kind_from_mode = _formats.get
-
-    pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
-    while pending:
-        relroot, _, _, _, top = pending.pop()
-        if relroot:
-            relprefix = relroot + '/'
+        return dirblock
+
+
+class UnicodeDirReader(DirReader):
+    """A dir reader for non-utf8 file systems, which transcodes."""
+
+    __slots__ = ['_utf8_encode']
+
+    def __init__(self):
+        self._utf8_encode = codecs.getencoder('utf8')
+
+    def top_prefix_to_starting_dir(self, top, prefix=""):
+        """See DirReader.top_prefix_to_starting_dir."""
+        return (safe_utf8(prefix), None, None, None, safe_unicode(top))
+
+    def read_dir(self, prefix, top):
+        """Read a single directory from a non-utf8 file system.
+
+        top, and the abspath element in the output are unicode, all other paths
+        are utf8. Local disk IO is done via unicode calls to listdir etc.
+
+        This is currently the fallback code path when the filesystem encoding is
+        not UTF-8. It may be better to implement an alternative so that we can
+        safely handle paths that are not properly decodable in the current
+        encoding.
+
+        See DirReader.read_dir for details.
+        """
+        _utf8_encode = self._utf8_encode
+        _lstat = os.lstat
+        _listdir = os.listdir
+        _kind_from_mode = _formats.get
+
+        if prefix:
+            relprefix = prefix + '/'
         else:
             relprefix = ''
         top_slash = top + u'/'
@@ -1341,10 +1390,7 @@
             statvalue = _lstat(abspath)
             kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
             append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
-        yield (relroot, top), dirblock
-
-        # push the user specified dirs from dirblock
-        pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
+        return dirblock
 
 
 def copy_tree(from_path, to_path, handlers={}):

=== modified file 'bzrlib/tests/test__walkdirs_win32.py'
--- a/bzrlib/tests/test__walkdirs_win32.py	2008-07-17 03:46:13 +0000
+++ b/bzrlib/tests/test__walkdirs_win32.py	2008-09-09 01:53:03 +0000
@@ -21,7 +21,7 @@
 from bzrlib import tests
 
 
-class _WalkdirsWin32Feature(tests.Feature):
+class _Win32ReadDirFeature(tests.Feature):
 
     def _probe(self):
         try:
@@ -32,21 +32,21 @@
             return True
 
     def feature_name(self):
-        return 'bzrlib._walkdirs_win32'
+        return 'bzrlib._Win32ReadDir'
 
-WalkdirsWin32Feature = _WalkdirsWin32Feature()
+Win32ReadDirFeature = _Win32ReadDirFeature()
 
 
 class TestWin32Finder(tests.TestCaseInTempDir):
 
-    _test_needs_features = [WalkdirsWin32Feature]
+    _test_needs_features = [Win32ReadDirFeature]
 
     def setUp(self):
         super(TestWin32Finder, self).setUp()
         from bzrlib._walkdirs_win32 import (
-            _walkdirs_utf8_win32_find_file
+            Win32ReadDir,
             )
-        self.walkdirs_utf8 = _walkdirs_utf8_win32_find_file
+        self.reader = Win32ReadDir()
 
     def _remove_stat_from_dirblock(self, dirblock):
         return [info[:3] + info[4:] for info in dirblock]
@@ -58,65 +58,42 @@
             result.append((dirname, self._remove_stat_from_dirblock(dirblock)))
         self.assertEqual(expected, result)
 
+    def assertReadDir(self, expected, prefix, top_unicode):
+        result = self._remove_stat_from_dirblock(
+            self.reader.read_dir(prefix, top_unicode))
+        self.assertEqual(expected, result)
+
+    def test_top_prefix_to_starting_dir(self):
+        # preparing an iteration should create a unicode native path.
+        self.assertEqual(('prefix', None, None, None, u'\x12'),
+            self.reader.top_prefix_to_starting_dir('prefix',
+                u'\x12'.encode('utf8')))
+
     def test_empty_directory(self):
+        self.assertReadDir([], 'prefix', u'.')
         self.assertWalkdirs([(('', u'.'), [])], u'.')
 
-    def test_file_in_dir(self):
+    def test_file(self):
         self.build_tree(['foo'])
-        self.assertWalkdirs([
-            (('', u'.'), [('foo', 'foo', 'file', u'./foo')])
-            ], u'.')
-
-    def test_subdir(self):
-        self.build_tree(['foo', 'bar/', 'bar/baz'])
-        self.assertWalkdirs([
-            (('', u'.'), [('bar', 'bar', 'directory', u'./bar'),
-                          ('foo', 'foo', 'file', u'./foo'),
-                         ]),
-            (('bar', u'./bar'), [('bar/baz', 'baz', 'file', u'./bar/baz')]),
-            ], '.')
-        self.assertWalkdirs([
-            (('xxx', u'.'), [('xxx/bar', 'bar', 'directory', u'./bar'),
-                             ('xxx/foo', 'foo', 'file', u'./foo'),
-                            ]),
-            (('xxx/bar', u'./bar'), [('xxx/bar/baz', 'baz', 'file', u'./bar/baz')]),
-            ], '.', prefix='xxx')
-        self.assertWalkdirs([
-            (('', u'bar'), [('baz', 'baz', 'file', u'bar/baz')]),
-            ], 'bar')
-
-    def test_skip_subdir(self): 
-        self.build_tree(['a/', 'b/', 'c/', 'a/aa', 'b/bb', 'c/cc'])
-        base_dirblock = [('a', 'a', 'directory', u'./a'),
-                          ('b', 'b', 'directory', u'./b'),
-                          ('c', 'c', 'directory', u'./c'),
-                         ]
-        self.assertWalkdirs([
-            (('', u'.'), base_dirblock),
-            (('a', u'./a'), [('a/aa', 'aa', 'file', u'./a/aa')]),
-            (('b', u'./b'), [('b/bb', 'bb', 'file', u'./b/bb')]),
-            (('c', u'./c'), [('c/cc', 'cc', 'file', u'./c/cc')]),
-            ], '.')
-
-        walker = self.walkdirs_utf8('.')
-        dir_info, first_dirblock = walker.next()
-        self.assertEqual(('', u'.'), dir_info)
-        self.assertEqual(base_dirblock,
-                         self._remove_stat_from_dirblock(first_dirblock))
-        # Now, remove 'b' and it should be skipped on the next round
-        del first_dirblock[1]
-        dir_info, second_dirblock = walker.next()
-        second_dirblock = self._remove_stat_from_dirblock(second_dirblock)
-        self.assertEqual(('a', u'./a'), dir_info)
-        self.assertEqual([('a/aa', 'aa', 'file', u'./a/aa')], second_dirblock)
-        dir_info, third_dirblock = walker.next()
-        third_dirblock = self._remove_stat_from_dirblock(third_dirblock)
-        self.assertEqual(('c', u'./c'), dir_info)
-        self.assertEqual([('c/cc', 'cc', 'file', u'./c/cc')], third_dirblock)
+        self.assertReadDir([('foo', 'foo', 'file', u'./foo')],
+            '', u'.')
+
+    def test_dir(self):
+        self.build_tree(['bar/'])
+        self.assertReadDir([('bar', 'bar', 'directory', u'./bar')],
+            '', u'.')
+
+    def test_prefix(self):
+        self.build_tree(['bar/', 'baf'])
+        self.assertReadDir([
+            ('xxx/baf', 'baf', 'file', u'./baf'),
+            ('xxx/bar', 'bar', 'directory', u'./bar'),
+            ],
+            'xxx', u'.')
 
     def test_missing_dir(self):
         e = self.assertRaises(WindowsError, list,
-                                self.walkdirs_utf8(u'no_such_dir'))
+            self.reader.read_dir('prefix', u'no_such_dir'))
         self.assertEqual(errno.ENOENT, e.errno)
         self.assertEqual(3, e.winerror)
         self.assertEqual((3, u'no_such_dir/*'), e.args)

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2008-09-03 08:32:49 +0000
+++ b/bzrlib/tests/test_osutils.py	2008-09-09 01:53:03 +0000
@@ -54,7 +54,7 @@
 from bzrlib.tests.file_utils import (
     FakeReadFile,
     )
-from bzrlib.tests.test__walkdirs_win32 import WalkdirsWin32Feature
+from bzrlib.tests.test__walkdirs_win32 import Win32ReadDirFeature
 
 
 def load_tests(standard_tests, module, loader):
@@ -912,79 +912,61 @@
                 new_dirblock.append((info[0], info[1], info[2], info[4]))
             dirblock[:] = new_dirblock
 
-    def test__walkdirs_utf8_selection(self):
-        # Just trigger the function once, to make sure it has selected a real
-        # implementation.
-        list(osutils._walkdirs_utf8('.'))
-        if WalkdirsWin32Feature.available():
-            # If the compiled form is available, make sure it is used
-            from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
-            self.assertIs(_walkdirs_utf8_win32_find_file,
-                          osutils._real_walkdirs_utf8)
-        elif sys.platform == 'win32':
-            self.assertIs(osutils._walkdirs_unicode_to_utf8,
-                          osutils._real_walkdirs_utf8)
-        elif osutils._fs_enc.upper() in ('UTF-8', 'ASCII', 'ANSI_X3.4-1968'): # ascii
-            self.assertIs(osutils._walkdirs_fs_utf8,
-                          osutils._real_walkdirs_utf8)
-        else:
-            self.assertIs(osutils._walkdirs_unicode_to_utf8,
-                          osutils._real_walkdirs_utf8)
-
     def _save_platform_info(self):
         cur_winver = win32utils.winver
         cur_fs_enc = osutils._fs_enc
-        cur_real_walkdirs_utf8 = osutils._real_walkdirs_utf8
+        cur_dir_reader = osutils._selected_dir_reader
         def restore():
             win32utils.winver = cur_winver
             osutils._fs_enc = cur_fs_enc
-            osutils._real_walkdirs_utf8 = cur_real_walkdirs_utf8
+            osutils._selected_dir_reader = cur_dir_reader
         self.addCleanup(restore)
 
-    def assertWalkdirsUtf8Is(self, expected):
+    def assertReadFSDirIs(self, expected):
         """Assert the right implementation for _walkdirs_utf8 is chosen."""
         # Force it to redetect
-        osutils._real_walkdirs_utf8 = None
+        osutils._selected_dir_reader = None
         # Nothing to list, but should still trigger the selection logic
         self.assertEqual([(('', '.'), [])], list(osutils._walkdirs_utf8('.')))
-        self.assertIs(expected, osutils._real_walkdirs_utf8)
+        self.assertIsInstance(osutils._selected_dir_reader, expected)
 
     def test_force_walkdirs_utf8_fs_utf8(self):
         self._save_platform_info()
         win32utils.winver = None # Avoid the win32 detection code
         osutils._fs_enc = 'UTF-8'
-        self.assertWalkdirsUtf8Is(osutils._walkdirs_fs_utf8)
+        self.assertReadFSDirIs(osutils.UTF8DirReader)
 
     def test_force_walkdirs_utf8_fs_ascii(self):
         self._save_platform_info()
         win32utils.winver = None # Avoid the win32 detection code
         osutils._fs_enc = 'US-ASCII'
-        self.assertWalkdirsUtf8Is(osutils._walkdirs_fs_utf8)
+        self.assertReadFSDirIs(osutils.UTF8DirReader)
 
     def test_force_walkdirs_utf8_fs_ANSI(self):
         self._save_platform_info()
         win32utils.winver = None # Avoid the win32 detection code
         osutils._fs_enc = 'ANSI_X3.4-1968'
-        self.assertWalkdirsUtf8Is(osutils._walkdirs_fs_utf8)
+        self.assertReadFSDirIs(osutils.UTF8DirReader)
 
     def test_force_walkdirs_utf8_fs_latin1(self):
         self._save_platform_info()
         win32utils.winver = None # Avoid the win32 detection code
         osutils._fs_enc = 'latin1'
-        self.assertWalkdirsUtf8Is(osutils._walkdirs_unicode_to_utf8)
+        self.assertReadFSDirIs(osutils.UnicodeDirReader)
 
     def test_force_walkdirs_utf8_nt(self):
-        self.requireFeature(WalkdirsWin32Feature)
+        # Disabled because the thunk of the whole walkdirs api is disabled.
+        self.requireFeature(Win32ReadDirFeature)
         self._save_platform_info()
         win32utils.winver = 'Windows NT'
-        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
-        self.assertWalkdirsUtf8Is(_walkdirs_utf8_win32_find_file)
+        from bzrlib._walkdirs_win32 import Win32ReadDir
+        self.assertReadFSDirIs(Win32ReadDir)
 
-    def test_force_walkdirs_utf8_nt(self):
-        self.requireFeature(WalkdirsWin32Feature)
+    def test_force_walkdirs_utf8_98(self):
+        self.requireFeature(Win32ReadDirFeature)
         self._save_platform_info()
         win32utils.winver = 'Windows 98'
-        self.assertWalkdirsUtf8Is(osutils._walkdirs_unicode_to_utf8)
+        self.assertReadFSDirIs(osutils.UnicodeDirReader)
 
     def test_unicode_walkdirs(self):
         """Walkdirs should always return unicode paths."""
@@ -1093,11 +1075,15 @@
             result.append((dirdetail, new_dirblock))
         self.assertEqual(expected_dirblocks, result)
 
-    def test_unicode__walkdirs_unicode_to_utf8(self):
-        """walkdirs_unicode_to_utf8 should be a safe fallback everywhere
+    def test__walkdirs_utf8_with_unicode_fs(self):
+        """UnicodeDirReader should be a safe fallback everywhere
 
         The abspath portion should be in unicode
         """
+        # Use the unicode reader. TODO: split into driver-and-driven unit
+        # tests.
+        self._save_platform_info()
+        osutils._selected_dir_reader = osutils.UnicodeDirReader()
         name0u = u'0file-\xb6'
         name1u = u'1dir-\u062c\u0648'
         name2u = u'2file-\u0633'
@@ -1138,14 +1124,16 @@
                  ]
                 ),
             ]
-        result = list(osutils._walkdirs_unicode_to_utf8('.'))
+        result = list(osutils._walkdirs_utf8('.'))
         self._filter_out_stat(result)
         self.assertEqual(expected_dirblocks, result)
 
     def test__walkdirs_utf_win32_find_file(self):
-        self.requireFeature(WalkdirsWin32Feature)
+        self.requireFeature(Win32ReadDirFeature)
         self.requireFeature(tests.UnicodeFilenameFeature)
-        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        from bzrlib._walkdirs_win32 import Win32ReadDir
+        self._save_platform_info()
+        osutils._selected_dir_reader = osutils.Win32ReadDir()
         name0u = u'0file-\xb6'
         name1u = u'1dir-\u062c\u0648'
         name2u = u'2file-\u0633'
@@ -1182,7 +1170,7 @@
                  ]
                 ),
             ]
-        result = list(_walkdirs_utf8_win32_find_file(u'.'))
+        result = list(_walkdirs_utf8(u'.'))
         self._filter_out_stat(result)
         self.assertEqual(expected_dirblocks, result)
 
@@ -1198,9 +1186,9 @@
 
     def test__walkdirs_utf_win32_find_file_stat_file(self):
         """make sure our Stat values are valid"""
-        self.requireFeature(WalkdirsWin32Feature)
+        self.requireFeature(Win32ReadDirFeature)
         self.requireFeature(tests.UnicodeFilenameFeature)
-        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        from bzrlib._walkdirs_win32 import Win32ReadDir
         name0u = u'0file-\xb6'
         name0 = name0u.encode('utf8')
         self.build_tree([name0u])
@@ -1213,8 +1201,8 @@
         finally:
             f.close()
 
-        result = list(_walkdirs_utf8_win32_find_file(u'.'))
-        entry = result[0][1][0]
+        result = Win32ReadDir().read_dir('', u'.')
+        entry = result[0]
         self.assertEqual((name0, name0, 'file'), entry[:3])
         self.assertEqual(u'./' + name0u, entry[4])
         self.assertStatIsCorrect(entry[4], entry[3])
@@ -1222,15 +1210,15 @@
 
     def test__walkdirs_utf_win32_find_file_stat_directory(self):
         """make sure our Stat values are valid"""
-        self.requireFeature(WalkdirsWin32Feature)
+        self.requireFeature(Win32ReadDirFeature)
         self.requireFeature(tests.UnicodeFilenameFeature)
-        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        from bzrlib._walkdirs_win32 import Win32ReadDir
         name0u = u'0dir-\u062c\u0648'
         name0 = name0u.encode('utf8')
         self.build_tree([name0u + '/'])
 
-        result = list(_walkdirs_utf8_win32_find_file(u'.'))
-        entry = result[0][1][0]
+        result = Win32ReadDir().read_dir('', u'.')
+        entry = result[0]
         self.assertEqual((name0, name0, 'directory'), entry[:3])
         self.assertEqual(u'./' + name0u, entry[4])
         self.assertStatIsCorrect(entry[4], entry[3])




More information about the bazaar-commits mailing list