~lifeless/ubuntu/lucid/bzr/2.1.2-sru

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2009-06-27 15:23:34 UTC
  • mfrom: (1.3.1 upstream) (3.1.78 karmic)
  • Revision ID: james.westby@ubuntu.com-20090627152334-u3smexjpaolh96qd
* New upstream release.
* Bump standards version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
18
18
import re
38
38
from shutil import (
39
39
    rmtree,
40
40
    )
 
41
import subprocess
41
42
import tempfile
42
43
from tempfile import (
43
44
    mkdtemp,
77
78
O_BINARY = getattr(os, 'O_BINARY', 0)
78
79
 
79
80
 
 
81
def get_unicode_argv():
 
82
    try:
 
83
        user_encoding = get_user_encoding()
 
84
        return [a.decode(user_encoding) for a in sys.argv[1:]]
 
85
    except UnicodeDecodeError:
 
86
        raise errors.BzrError(("Parameter '%r' is unsupported by the current "
 
87
                                                            "encoding." % a))
 
88
 
 
89
 
80
90
def make_readonly(filename):
81
91
    """Make a filename read-only."""
82
92
    mod = os.lstat(filename).st_mode
97
107
 
98
108
    :param paths: A container (and hence not None) of paths.
99
109
    :return: A set of paths sufficient to include everything in paths via
100
 
        is_inside_any, drawn from the paths parameter.
 
110
        is_inside, drawn from the paths parameter.
101
111
    """
102
 
    search_paths = set()
103
 
    paths = set(paths)
104
 
    for path in paths:
105
 
        other_paths = paths.difference([path])
106
 
        if not is_inside_any(other_paths, path):
107
 
            # this is a top level path, we must check it.
108
 
            search_paths.add(path)
109
 
    return search_paths
 
112
    if len(paths) < 2:
 
113
        return set(paths)
 
114
 
 
115
    def sort_key(path):
 
116
        return path.split('/')
 
117
    sorted_paths = sorted(list(paths), key=sort_key)
 
118
 
 
119
    search_paths = [sorted_paths[0]]
 
120
    for path in sorted_paths[1:]:
 
121
        if not is_inside(search_paths[-1], path):
 
122
            # This path is unique, add it
 
123
            search_paths.append(path)
 
124
 
 
125
    return set(search_paths)
110
126
 
111
127
 
112
128
_QUOTE_RE = None
384
400
    def rmtree(path, ignore_errors=False, onerror=_win32_delete_readonly):
385
401
        """Replacer for shutil.rmtree: could remove readonly dirs/files"""
386
402
        return shutil.rmtree(path, ignore_errors, onerror)
 
403
 
 
404
    f = win32utils.get_unicode_argv     # special function or None
 
405
    if f is not None:
 
406
        get_unicode_argv = f
 
407
 
387
408
elif sys.platform == 'darwin':
388
409
    getcwd = _mac_getcwd
389
410
 
597
618
    return s.hexdigest()
598
619
 
599
620
 
 
621
def size_sha_file(f):
 
622
    """Calculate the size and hexdigest of an open file.
 
623
 
 
624
    The file cursor should be already at the start and
 
625
    the caller is responsible for closing the file afterwards.
 
626
    """
 
627
    size = 0
 
628
    s = sha()
 
629
    BUFSIZE = 128<<10
 
630
    while True:
 
631
        b = f.read(BUFSIZE)
 
632
        if not b:
 
633
            break
 
634
        size += len(b)
 
635
        s.update(b)
 
636
    return size, s.hexdigest()
 
637
 
 
638
 
600
639
def sha_file_by_name(fname):
601
640
    """Calculate the SHA1 of a file by reading the full text"""
602
641
    s = sha()
683
722
               _format_date(t, offset, timezone, date_fmt, show_offset)
684
723
    date_str = time.strftime(date_fmt, tt)
685
724
    if not isinstance(date_str, unicode):
686
 
        date_str = date_str.decode(bzrlib.user_encoding, 'replace')
 
725
        date_str = date_str.decode(get_user_encoding(), 'replace')
687
726
    return date_str + offset_str
688
727
 
689
728
def _format_date(t, offset, timezone, date_fmt, show_offset):
829
868
    return pathjoin(*p)
830
869
 
831
870
 
 
871
def parent_directories(filename):
 
872
    """Return the list of parent directories, deepest first.
 
873
    
 
874
    For example, parent_directories("a/b/c") -> ["a/b", "a"].
 
875
    """
 
876
    parents = []
 
877
    parts = splitpath(dirname(filename))
 
878
    while parts:
 
879
        parents.append(joinpath(parts))
 
880
        parts.pop()
 
881
    return parents
 
882
 
 
883
 
832
884
try:
833
885
    from bzrlib._chunks_to_lines_pyx import chunks_to_lines
834
886
except ImportError:
907
959
            and sys.platform not in ('cygwin', 'win32'))
908
960
 
909
961
 
 
962
def readlink(abspath):
 
963
    """Return a string representing the path to which the symbolic link points.
 
964
 
 
965
    :param abspath: The link absolute unicode path.
 
966
 
 
967
    This his guaranteed to return the symbolic link in unicode in all python
 
968
    versions.
 
969
    """
 
970
    link = abspath.encode(_fs_enc)
 
971
    target = os.readlink(link)
 
972
    target = target.decode(_fs_enc)
 
973
    return target
 
974
 
 
975
 
910
976
def contains_whitespace(s):
911
977
    """True if there are any whitespace characters in s."""
912
978
    # string.whitespace can include '\xa0' in certain locales, because it is
1012
1078
    return current[len(abs_base)+1:]
1013
1079
 
1014
1080
# XXX - TODO - we need better detection/integration of case-insensitive
1015
 
# file-systems; Linux often sees FAT32 devices, for example, so could
1016
 
# probably benefit from the same basic support there.  For now though, only
1017
 
# Windows gets that support, and it gets it for *all* file-systems!
1018
 
if sys.platform == "win32":
 
1081
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
 
1082
# filesystems), for example, so could probably benefit from the same basic
 
1083
# support there.  For now though, only Windows and OSX get that support, and
 
1084
# they get it for *all* file-systems!
 
1085
if sys.platform in ('win32', 'darwin'):
1019
1086
    canonical_relpath = _cicp_canonical_relpath
1020
1087
else:
1021
1088
    canonical_relpath = relpath
1033
1100
    """Coerce unicode_or_utf8_string into unicode.
1034
1101
 
1035
1102
    If it is unicode, it is returned.
1036
 
    Otherwise it is decoded from utf-8. If a decoding error
1037
 
    occurs, it is wrapped as a If the decoding fails, the exception is wrapped
1038
 
    as a BzrBadParameter exception.
 
1103
    Otherwise it is decoded from utf-8. If decoding fails, the exception is
 
1104
    wrapped in a BzrBadParameterNotUnicode exception.
1039
1105
    """
1040
1106
    if isinstance(unicode_or_utf8_string, unicode):
1041
1107
        return unicode_or_utf8_string
1374
1440
            #       for win98 anyway.
1375
1441
            try:
1376
1442
                from bzrlib._walkdirs_win32 import Win32ReadDir
1377
 
            except ImportError:
1378
 
                _selected_dir_reader = UnicodeDirReader()
1379
 
            else:
1380
1443
                _selected_dir_reader = Win32ReadDir()
1381
 
        elif fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
 
1444
            except ImportError:
 
1445
                pass
 
1446
        elif fs_encoding in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
1382
1447
            # ANSI_X3.4-1968 is a form of ASCII
1383
 
            _selected_dir_reader = UnicodeDirReader()
1384
 
        else:
1385
1448
            try:
1386
1449
                from bzrlib._readdir_pyx import UTF8DirReader
1387
 
            except ImportError:
1388
 
                # No optimised code path
1389
 
                _selected_dir_reader = UnicodeDirReader()
1390
 
            else:
1391
1450
                _selected_dir_reader = UTF8DirReader()
 
1451
            except ImportError:
 
1452
                pass
 
1453
 
 
1454
    if _selected_dir_reader is None:
 
1455
        # Fallback to the python version
 
1456
        _selected_dir_reader = UnicodeDirReader()
 
1457
 
1392
1458
    # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1393
1459
    # But we don't actually uses 1-3 in pending, so set them to None
1394
1460
    pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]]
1722
1788
                continue
1723
1789
            raise
1724
1790
 
 
1791
def re_compile_checked(re_string, flags=0, where=""):
 
1792
    """Return a compiled re, or raise a sensible error.
 
1793
 
 
1794
    This should only be used when compiling user-supplied REs.
 
1795
 
 
1796
    :param re_string: Text form of regular expression.
 
1797
    :param flags: eg re.IGNORECASE
 
1798
    :param where: Message explaining to the user the context where
 
1799
        it occurred, eg 'log search filter'.
 
1800
    """
 
1801
    # from https://bugs.launchpad.net/bzr/+bug/251352
 
1802
    try:
 
1803
        re_obj = re.compile(re_string, flags)
 
1804
        re_obj.search("")
 
1805
        return re_obj
 
1806
    except re.error, e:
 
1807
        if where:
 
1808
            where = ' in ' + where
 
1809
        # despite the name 'error' is a type
 
1810
        raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
 
1811
            % (where, re_string, e))
 
1812
 
1725
1813
 
1726
1814
if sys.platform == "win32":
1727
1815
    import msvcrt
1739
1827
        finally:
1740
1828
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
1741
1829
        return ch
 
1830
 
 
1831
 
 
1832
if sys.platform == 'linux2':
 
1833
    def _local_concurrency():
 
1834
        concurrency = None
 
1835
        prefix = 'processor'
 
1836
        for line in file('/proc/cpuinfo', 'rb'):
 
1837
            if line.startswith(prefix):
 
1838
                concurrency = int(line[line.find(':')+1:]) + 1
 
1839
        return concurrency
 
1840
elif sys.platform == 'darwin':
 
1841
    def _local_concurrency():
 
1842
        return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
 
1843
                                stdout=subprocess.PIPE).communicate()[0]
 
1844
elif sys.platform[0:7] == 'freebsd':
 
1845
    def _local_concurrency():
 
1846
        return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
 
1847
                                stdout=subprocess.PIPE).communicate()[0]
 
1848
elif sys.platform == 'sunos5':
 
1849
    def _local_concurrency():
 
1850
        return subprocess.Popen(['psrinfo', '-p',],
 
1851
                                stdout=subprocess.PIPE).communicate()[0]
 
1852
elif sys.platform == "win32":
 
1853
    def _local_concurrency():
 
1854
        # This appears to return the number of cores.
 
1855
        return os.environ.get('NUMBER_OF_PROCESSORS')
 
1856
else:
 
1857
    def _local_concurrency():
 
1858
        # Who knows ?
 
1859
        return None
 
1860
 
 
1861
 
 
1862
_cached_local_concurrency = None
 
1863
 
 
1864
def local_concurrency(use_cache=True):
 
1865
    """Return how many processes can be run concurrently.
 
1866
 
 
1867
    Rely on platform specific implementations and default to 1 (one) if
 
1868
    anything goes wrong.
 
1869
    """
 
1870
    global _cached_local_concurrency
 
1871
    if _cached_local_concurrency is not None and use_cache:
 
1872
        return _cached_local_concurrency
 
1873
 
 
1874
    try:
 
1875
        concurrency = _local_concurrency()
 
1876
    except (OSError, IOError):
 
1877
        concurrency = None
 
1878
    try:
 
1879
        concurrency = int(concurrency)
 
1880
    except (TypeError, ValueError):
 
1881
        concurrency = 1
 
1882
    if use_cache:
 
1883
        _cached_concurrency = concurrency
 
1884
    return concurrency