/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/osutils.py

  • Committer: Jelmer Vernooij
  • Date: 2020-08-10 15:00:17 UTC
  • mfrom: (7490.40.99 work)
  • mto: This revision was merged to the branch mainline in revision 7521.
  • Revision ID: jelmer@jelmer.uk-20200810150017-vs7xnrd1vat4iktg
Merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
 
 
19
17
import errno
20
18
import os
21
19
import re
52
50
from breezy.i18n import gettext
53
51
""")
54
52
 
55
 
from .sixish import (
56
 
    PY3,
57
 
    text_type,
58
 
    )
59
 
 
60
53
from hashlib import (
61
54
    md5,
62
55
    sha1 as sha,
90
83
        self.timezone = timezone
91
84
 
92
85
 
93
 
def get_unicode_argv():
94
 
    if PY3:
95
 
        return sys.argv[1:]
96
 
    try:
97
 
        user_encoding = get_user_encoding()
98
 
        return [a.decode(user_encoding) for a in sys.argv[1:]]
99
 
    except UnicodeDecodeError:
100
 
        raise errors.BzrError(gettext("Parameter {0!r} encoding is unsupported by {1} "
101
 
                                      "application locale.").format(a, user_encoding))
102
 
 
103
 
 
104
86
def make_readonly(filename):
105
87
    """Make a filename read-only."""
106
88
    mod = os.lstat(filename).st_mode
325
307
    return path
326
308
 
327
309
 
328
 
def _posix_path_from_environ(key):
329
 
    """Get unicode path from `key` in environment or None if not present
330
 
 
331
 
    Note that posix systems use arbitrary byte strings for filesystem objects,
332
 
    so a path that raises BadFilenameEncoding here may still be accessible.
333
 
    """
334
 
    val = os.environ.get(key, None)
335
 
    if PY3 or val is None:
336
 
        return val
337
 
    try:
338
 
        return val.decode(_fs_enc)
339
 
    except UnicodeDecodeError:
340
 
        # GZ 2011-12-12:Ideally want to include `key` in the exception message
341
 
        raise errors.BadFilenameEncoding(val, _fs_enc)
342
 
 
343
 
 
344
310
def _posix_get_home_dir():
345
311
    """Get the home directory of the current user as a unicode path"""
346
312
    path = posixpath.expanduser("~")
354
320
 
355
321
def _posix_getuser_unicode():
356
322
    """Get username from environment or password database as unicode"""
357
 
    name = getpass.getuser()
358
 
    if PY3:
359
 
        return name
360
 
    user_encoding = get_user_encoding()
361
 
    try:
362
 
        return name.decode(user_encoding)
363
 
    except UnicodeDecodeError:
364
 
        raise errors.BzrError("Encoding of username %r is unsupported by %s "
365
 
                              "application locale." % (name, user_encoding))
 
323
    return getpass.getuser()
366
324
 
367
325
 
368
326
def _win32_fixdrive(path):
447
405
    return _rename_wrapper
448
406
 
449
407
 
450
 
if sys.version_info > (3,):
451
 
    _getcwd = os.getcwd
452
 
else:
453
 
    _getcwd = os.getcwdu
 
408
_getcwd = os.getcwd
454
409
 
455
410
 
456
411
# Default rename wraps os.rename()
462
417
realpath = _posix_realpath
463
418
pathjoin = os.path.join
464
419
normpath = _posix_normpath
465
 
path_from_environ = _posix_path_from_environ
466
420
_get_home_dir = _posix_get_home_dir
467
421
getuser_unicode = _posix_getuser_unicode
468
422
getcwd = _getcwd
520
474
        """Replacer for shutil.rmtree: could remove readonly dirs/files"""
521
475
        return shutil.rmtree(path, ignore_errors, onerror)
522
476
 
523
 
    get_unicode_argv = getattr(win32utils, 'get_unicode_argv', get_unicode_argv)
524
 
    path_from_environ = win32utils.get_environ_unicode
525
477
    _get_home_dir = win32utils.get_home_location
526
478
    getuser_unicode = win32utils.get_user_name
527
479
 
738
690
 
739
691
# GZ 2017-09-16: Makes sense in general for hexdigest() result to be text, but
740
692
# used as bytes through most interfaces so encode with this wrapper.
741
 
if PY3:
742
 
    def _hexdigest(hashobj):
743
 
        return hashobj.hexdigest().encode()
744
 
else:
745
 
    def _hexdigest(hashobj):
746
 
        return hashobj.hexdigest()
 
693
def _hexdigest(hashobj):
 
694
    return hashobj.hexdigest().encode()
747
695
 
748
696
 
749
697
def sha_file(f):
895
843
    (date_fmt, tt, offset_str) = \
896
844
        _format_date(t, offset, timezone, date_fmt, show_offset)
897
845
    date_str = time.strftime(date_fmt, tt)
898
 
    if not isinstance(date_str, text_type):
 
846
    if not isinstance(date_str, str):
899
847
        date_str = date_str.decode(get_user_encoding(), 'replace')
900
848
    return date_str + offset_str
901
849
 
1012
960
    """
1013
961
    s = ''
1014
962
    for raw_byte in rand_bytes(num):
1015
 
        if not PY3:
1016
 
            s += ALNUM[ord(raw_byte) % 36]
1017
 
        else:
1018
 
            s += ALNUM[raw_byte % 36]
 
963
        s += ALNUM[raw_byte % 36]
1019
964
    return s
1020
965
 
1021
966
 
1322
1267
 
1323
1268
    abs_base = abspath(base)
1324
1269
    current = abs_base
1325
 
    _listdir = os.listdir
1326
1270
 
1327
1271
    # use an explicit iterator so we can easily consume the rest on early exit.
1328
1272
    bit_iter = iter(rel.split('/'))
1329
1273
    for bit in bit_iter:
1330
1274
        lbit = bit.lower()
1331
1275
        try:
1332
 
            next_entries = _listdir(current)
 
1276
            next_entries = scandir(current)
1333
1277
        except OSError:  # enoent, eperm, etc
1334
1278
            # We can't find this in the filesystem, so just append the
1335
1279
            # remaining bits.
1336
1280
            current = pathjoin(current, bit, *list(bit_iter))
1337
1281
            break
1338
 
        for look in next_entries:
1339
 
            if lbit == look.lower():
1340
 
                current = pathjoin(current, look)
 
1282
        for entry in next_entries:
 
1283
            if lbit == entry.name.lower():
 
1284
                current = entry.path
1341
1285
                break
1342
1286
        else:
1343
1287
            # got to the end, nothing matched, so we just return the
1376
1320
    Otherwise it is decoded from the the filesystem's encoding. If decoding
1377
1321
    fails, a errors.BadFilenameEncoding exception is raised.
1378
1322
    """
1379
 
    if isinstance(filename, text_type):
 
1323
    if isinstance(filename, str):
1380
1324
        return filename
1381
1325
    try:
1382
1326
        return filename.decode(_fs_enc)
1391
1335
    Otherwise it is decoded from utf-8. If decoding fails, the exception is
1392
1336
    wrapped in a BzrBadParameterNotUnicode exception.
1393
1337
    """
1394
 
    if isinstance(unicode_or_utf8_string, text_type):
 
1338
    if isinstance(unicode_or_utf8_string, str):
1395
1339
        return unicode_or_utf8_string
1396
1340
    try:
1397
1341
        return unicode_or_utf8_string.decode('utf8')
1698
1642
        if orig_val is not None:
1699
1643
            del os.environ[env_variable]
1700
1644
    else:
1701
 
        if not PY3 and isinstance(value, text_type):
1702
 
            value = value.encode(get_user_encoding())
1703
1645
        os.environ[env_variable] = value
1704
1646
    return orig_val
1705
1647
 
1721
1663
_WIN32_ERROR_DIRECTORY = 267  # Similar to errno.ENOTDIR
1722
1664
 
1723
1665
 
 
1666
try:
 
1667
    scandir = os.scandir
 
1668
except AttributeError:  # Python < 3
 
1669
    lazy_import(globals(), """\
 
1670
from scandir import scandir
 
1671
""")
 
1672
 
 
1673
 
1724
1674
def _is_error_enotdir(e):
1725
1675
    """Check if this exception represents ENOTDIR.
1726
1676
 
1780
1730
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
1781
1731
    # potentially confusing output. We should make this more robust - but
1782
1732
    # not at a speed cost. RBC 20060731
1783
 
    _lstat = os.lstat
1784
1733
    _directory = _directory_kind
1785
 
    _listdir = os.listdir
1786
 
    _kind_from_mode = file_kind_from_stat_mode
1787
1734
    pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1788
1735
    while pending:
1789
1736
        # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1795
1742
        top_slash = top + u'/'
1796
1743
 
1797
1744
        dirblock = []
1798
 
        append = dirblock.append
1799
1745
        try:
1800
 
            names = sorted(map(decode_filename, _listdir(top)))
 
1746
            for entry in scandir(top):
 
1747
                name = decode_filename(entry.name)
 
1748
                statvalue = entry.stat(follow_symlinks=False)
 
1749
                kind = file_kind_from_stat_mode(statvalue.st_mode)
 
1750
                dirblock.append((relprefix + name, name, kind, statvalue, entry.path))
1801
1751
        except OSError as e:
1802
1752
            if not _is_error_enotdir(e):
1803
1753
                raise
1804
 
        else:
1805
 
            for name in names:
1806
 
                abspath = top_slash + name
1807
 
                statvalue = _lstat(abspath)
1808
 
                kind = _kind_from_mode(statvalue.st_mode)
1809
 
                append((relprefix + name, name, kind, statvalue, abspath))
 
1754
        except UnicodeDecodeError as e:
 
1755
            raise errors.BadFilenameEncoding(e.object, _fs_enc)
 
1756
        dirblock.sort()
1810
1757
        yield (relroot, top), dirblock
1811
1758
 
1812
1759
        # push the user specified dirs from dirblock
1922
1869
        def _fs_decode(s): return s.decode(_fs_enc)
1923
1870
 
1924
1871
        def _fs_encode(s): return s.encode(_fs_enc)
1925
 
        _lstat = os.lstat
1926
 
        _listdir = os.listdir
1927
 
        _kind_from_mode = file_kind_from_stat_mode
1928
1872
 
1929
1873
        if prefix:
1930
1874
            relprefix = prefix + b'/'
1934
1878
 
1935
1879
        dirblock = []
1936
1880
        append = dirblock.append
1937
 
        for name_native in _listdir(top.encode('utf-8')):
 
1881
        for entry in scandir(safe_utf8(top)):
1938
1882
            try:
1939
 
                name = _fs_decode(name_native)
 
1883
                name = _fs_decode(entry.name)
1940
1884
            except UnicodeDecodeError:
1941
1885
                raise errors.BadFilenameEncoding(
1942
 
                    relprefix + name_native, _fs_enc)
 
1886
                    relprefix + entry.name, _fs_enc)
 
1887
            abspath = top_slash + name
1943
1888
            name_utf8 = _utf8_encode(name)[0]
1944
 
            abspath = top_slash + name
1945
 
            statvalue = _lstat(abspath)
1946
 
            kind = _kind_from_mode(statvalue.st_mode)
 
1889
            statvalue = entry.stat(follow_symlinks=False)
 
1890
            kind = file_kind_from_stat_mode(statvalue.st_mode)
1947
1891
            append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1948
1892
        return sorted(dirblock)
1949
1893
 
2094
2038
        return win32utils.get_host_name()
2095
2039
    else:
2096
2040
        import socket
2097
 
        if PY3:
2098
 
            return socket.gethostname()
2099
 
        return socket.gethostname().decode(get_user_encoding())
 
2041
        return socket.gethostname()
2100
2042
 
2101
2043
 
2102
2044
# We must not read/write any more than 64k at a time from/to a socket so we
2595
2537
            raise exception_class(path)
2596
2538
 
2597
2539
 
2598
 
def is_environment_error(evalue):
2599
 
    """True if exception instance is due to a process environment issue
2600
 
 
2601
 
    This includes OSError and IOError, but also other errors that come from
2602
 
    the operating system or core libraries but are not subclasses of those.
2603
 
    """
2604
 
    if isinstance(evalue, (EnvironmentError, select.error)):
2605
 
        return True
2606
 
    if sys.platform == "win32" and win32utils._is_pywintypes_error(evalue):
2607
 
        return True
2608
 
    return False
2609
 
 
2610
 
 
2611
2540
def read_mtab(path):
2612
2541
    """Read an fstab-style file and extract mountpoint+filesystem information.
2613
2542
 
2681
2610
    return _FILESYSTEM_FINDER.find(path)
2682
2611
 
2683
2612
 
2684
 
if PY3:
2685
 
    perf_counter = time.perf_counter
2686
 
else:
2687
 
    perf_counter = time.clock
 
2613
perf_counter = time.perf_counter