~jelmer/brz/byov-trunk

« back to all changes in this revision

Viewing changes to breezy/osutils.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2020-02-21 04:58:46 UTC
  • mfrom: (7489.5.5 scandir)
  • Revision ID: breezy.the.bot@gmail.com-20200221045846-q69cgqyvb7bd1jiu
Use os.scandir.

Merged from https://code.launchpad.net/~jelmer/brz/scandir2/+merge/379604

Show diffs side-by-side

added added

removed removed

Lines of Context:
1283
1283
 
1284
1284
    abs_base = abspath(base)
1285
1285
    current = abs_base
1286
 
    _listdir = os.listdir
1287
1286
 
1288
1287
    # use an explicit iterator so we can easily consume the rest on early exit.
1289
1288
    bit_iter = iter(rel.split('/'))
1290
1289
    for bit in bit_iter:
1291
1290
        lbit = bit.lower()
1292
1291
        try:
1293
 
            next_entries = _listdir(current)
 
1292
            next_entries = scandir(current)
1294
1293
        except OSError:  # enoent, eperm, etc
1295
1294
            # We can't find this in the filesystem, so just append the
1296
1295
            # remaining bits.
1297
1296
            current = pathjoin(current, bit, *list(bit_iter))
1298
1297
            break
1299
 
        for look in next_entries:
1300
 
            if lbit == look.lower():
1301
 
                current = pathjoin(current, look)
 
1298
        for entry in next_entries:
 
1299
            if lbit == entry.name.lower():
 
1300
                current = entry.path
1302
1301
                break
1303
1302
        else:
1304
1303
            # got to the end, nothing matched, so we just return the
1712
1711
_WIN32_ERROR_DIRECTORY = 267  # Similar to errno.ENOTDIR
1713
1712
 
1714
1713
 
 
1714
try:
 
1715
    scandir = os.scandir
 
1716
except AttributeError:  # Python < 3
 
1717
    lazy_import(globals(), """\
 
1718
from scandir import scandir
 
1719
""")
 
1720
 
 
1721
 
1715
1722
def _is_error_enotdir(e):
1716
1723
    """Check if this exception represents ENOTDIR.
1717
1724
 
1771
1778
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
1772
1779
    # potentially confusing output. We should make this more robust - but
1773
1780
    # not at a speed cost. RBC 20060731
1774
 
    _lstat = os.lstat
1775
1781
    _directory = _directory_kind
1776
 
    _listdir = os.listdir
1777
 
    _kind_from_mode = file_kind_from_stat_mode
1778
1782
    pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1779
1783
    while pending:
1780
1784
        # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1786
1790
        top_slash = top + u'/'
1787
1791
 
1788
1792
        dirblock = []
1789
 
        append = dirblock.append
1790
1793
        try:
1791
 
            names = sorted(map(decode_filename, _listdir(top)))
 
1794
            for entry in scandir(top):
 
1795
                name = decode_filename(entry.name)
 
1796
                statvalue = entry.stat(follow_symlinks=False)
 
1797
                kind = file_kind_from_stat_mode(statvalue.st_mode)
 
1798
                dirblock.append((relprefix + name, name, kind, statvalue, entry.path))
1792
1799
        except OSError as e:
1793
1800
            if not _is_error_enotdir(e):
1794
1801
                raise
1795
 
        else:
1796
 
            for name in names:
1797
 
                abspath = top_slash + name
1798
 
                statvalue = _lstat(abspath)
1799
 
                kind = _kind_from_mode(statvalue.st_mode)
1800
 
                append((relprefix + name, name, kind, statvalue, abspath))
 
1802
        except UnicodeDecodeError as e:
 
1803
            raise errors.BadFilenameEncoding(e.object, _fs_enc)
 
1804
        dirblock.sort()
1801
1805
        yield (relroot, top), dirblock
1802
1806
 
1803
1807
        # push the user specified dirs from dirblock
1913
1917
        def _fs_decode(s): return s.decode(_fs_enc)
1914
1918
 
1915
1919
        def _fs_encode(s): return s.encode(_fs_enc)
1916
 
        _lstat = os.lstat
1917
 
        _listdir = os.listdir
1918
 
        _kind_from_mode = file_kind_from_stat_mode
1919
1920
 
1920
1921
        if prefix:
1921
1922
            relprefix = prefix + b'/'
1925
1926
 
1926
1927
        dirblock = []
1927
1928
        append = dirblock.append
1928
 
        for name_native in _listdir(top.encode('utf-8')):
 
1929
        for entry in scandir(safe_utf8(top)):
1929
1930
            try:
1930
 
                name = _fs_decode(name_native)
 
1931
                name = _fs_decode(entry.name)
1931
1932
            except UnicodeDecodeError:
1932
1933
                raise errors.BadFilenameEncoding(
1933
 
                    relprefix + name_native, _fs_enc)
 
1934
                    relprefix + entry.name, _fs_enc)
 
1935
            abspath = top_slash + name
1934
1936
            name_utf8 = _utf8_encode(name)[0]
1935
 
            abspath = top_slash + name
1936
 
            statvalue = _lstat(abspath)
1937
 
            kind = _kind_from_mode(statvalue.st_mode)
 
1937
            statvalue = entry.stat(follow_symlinks=False)
 
1938
            kind = file_kind_from_stat_mode(statvalue.st_mode)
1938
1939
            append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1939
1940
        return sorted(dirblock)
1940
1941