~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Robert Collins
  • Date: 2009-05-11 01:59:06 UTC
  • mto: This revision was merged to the branch mainline in revision 4593.
  • Revision ID: robertc@robertcollins.net-20090511015906-6zi6a9b8tuuhipc8
Less lock thrashing in check.py.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
from shutil import (
39
39
    rmtree,
40
40
    )
41
 
import subprocess
42
41
import tempfile
43
42
from tempfile import (
44
43
    mkdtemp,
78
77
O_BINARY = getattr(os, 'O_BINARY', 0)
79
78
 
80
79
 
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
 
 
90
80
def make_readonly(filename):
91
81
    """Make a filename read-only."""
92
82
    mod = os.lstat(filename).st_mode
107
97
 
108
98
    :param paths: A container (and hence not None) of paths.
109
99
    :return: A set of paths sufficient to include everything in paths via
110
 
        is_inside, drawn from the paths parameter.
 
100
        is_inside_any, drawn from the paths parameter.
111
101
    """
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)
 
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
126
110
 
127
111
 
128
112
_QUOTE_RE = None
400
384
    def rmtree(path, ignore_errors=False, onerror=_win32_delete_readonly):
401
385
        """Replacer for shutil.rmtree: could remove readonly dirs/files"""
402
386
        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
 
 
408
387
elif sys.platform == 'darwin':
409
388
    getcwd = _mac_getcwd
410
389
 
722
701
               _format_date(t, offset, timezone, date_fmt, show_offset)
723
702
    date_str = time.strftime(date_fmt, tt)
724
703
    if not isinstance(date_str, unicode):
725
 
        date_str = date_str.decode(get_user_encoding(), 'replace')
 
704
        date_str = date_str.decode(bzrlib.user_encoding, 'replace')
726
705
    return date_str + offset_str
727
706
 
728
707
def _format_date(t, offset, timezone, date_fmt, show_offset):
868
847
    return pathjoin(*p)
869
848
 
870
849
 
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
 
 
884
850
try:
885
851
    from bzrlib._chunks_to_lines_pyx import chunks_to_lines
886
852
except ImportError:
927
893
        shutil.copyfile(src, dest)
928
894
 
929
895
 
 
896
# Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
 
897
# Forgiveness than Permission (EAFP) because:
 
898
# - root can damage a solaris file system by using unlink,
 
899
# - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
 
900
#   EACCES, OSX: EPERM) when invoked on a directory.
930
901
def delete_any(path):
931
 
    """Delete a file, symlink or directory.  
932
 
    
933
 
    Will delete even if readonly.
934
 
    """
935
 
    try:
936
 
       _delete_file_or_dir(path)
937
 
    except (OSError, IOError), e:
938
 
        if e.errno in (errno.EPERM, errno.EACCES):
939
 
            # make writable and try again
940
 
            try:
941
 
                make_writable(path)
942
 
            except (OSError, IOError):
943
 
                pass
944
 
            _delete_file_or_dir(path)
945
 
        else:
946
 
            raise
947
 
 
948
 
 
949
 
def _delete_file_or_dir(path):
950
 
    # Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
951
 
    # Forgiveness than Permission (EAFP) because:
952
 
    # - root can damage a solaris file system by using unlink,
953
 
    # - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
954
 
    #   EACCES, OSX: EPERM) when invoked on a directory.
 
902
    """Delete a file or directory."""
955
903
    if isdir(path): # Takes care of symlinks
956
904
        os.rmdir(path)
957
905
    else:
1040
988
 
1041
989
    s = []
1042
990
    head = rp
1043
 
    while True:
1044
 
        if len(head) <= len(base) and head != base:
1045
 
            raise errors.PathNotChild(rp, base)
 
991
    while len(head) >= len(base):
1046
992
        if head == base:
1047
993
            break
1048
 
        head, tail = split(head)
 
994
        head, tail = os.path.split(head)
1049
995
        if tail:
1050
 
            s.append(tail)
 
996
            s.insert(0, tail)
 
997
    else:
 
998
        raise errors.PathNotChild(rp, base)
1051
999
 
1052
1000
    if s:
1053
 
        return pathjoin(*reversed(s))
 
1001
        return pathjoin(*s)
1054
1002
    else:
1055
1003
        return ''
1056
1004
 
1808
1756
 
1809
1757
def re_compile_checked(re_string, flags=0, where=""):
1810
1758
    """Return a compiled re, or raise a sensible error.
1811
 
 
 
1759
    
1812
1760
    This should only be used when compiling user-supplied REs.
1813
1761
 
1814
1762
    :param re_string: Text form of regular expression.
1815
1763
    :param flags: eg re.IGNORECASE
1816
 
    :param where: Message explaining to the user the context where
 
1764
    :param where: Message explaining to the user the context where 
1817
1765
        it occurred, eg 'log search filter'.
1818
1766
    """
1819
1767
    # from https://bugs.launchpad.net/bzr/+bug/251352
1845
1793
        finally:
1846
1794
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
1847
1795
        return ch
1848
 
 
1849
 
 
1850
 
if sys.platform == 'linux2':
1851
 
    def _local_concurrency():
1852
 
        concurrency = None
1853
 
        prefix = 'processor'
1854
 
        for line in file('/proc/cpuinfo', 'rb'):
1855
 
            if line.startswith(prefix):
1856
 
                concurrency = int(line[line.find(':')+1:]) + 1
1857
 
        return concurrency
1858
 
elif sys.platform == 'darwin':
1859
 
    def _local_concurrency():
1860
 
        return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
1861
 
                                stdout=subprocess.PIPE).communicate()[0]
1862
 
elif sys.platform[0:7] == 'freebsd':
1863
 
    def _local_concurrency():
1864
 
        return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
1865
 
                                stdout=subprocess.PIPE).communicate()[0]
1866
 
elif sys.platform == 'sunos5':
1867
 
    def _local_concurrency():
1868
 
        return subprocess.Popen(['psrinfo', '-p',],
1869
 
                                stdout=subprocess.PIPE).communicate()[0]
1870
 
elif sys.platform == "win32":
1871
 
    def _local_concurrency():
1872
 
        # This appears to return the number of cores.
1873
 
        return os.environ.get('NUMBER_OF_PROCESSORS')
1874
 
else:
1875
 
    def _local_concurrency():
1876
 
        # Who knows ?
1877
 
        return None
1878
 
 
1879
 
 
1880
 
_cached_local_concurrency = None
1881
 
 
1882
 
def local_concurrency(use_cache=True):
1883
 
    """Return how many processes can be run concurrently.
1884
 
 
1885
 
    Rely on platform specific implementations and default to 1 (one) if
1886
 
    anything goes wrong.
1887
 
    """
1888
 
    global _cached_local_concurrency
1889
 
    if _cached_local_concurrency is not None and use_cache:
1890
 
        return _cached_local_concurrency
1891
 
 
1892
 
    try:
1893
 
        concurrency = _local_concurrency()
1894
 
    except (OSError, IOError):
1895
 
        concurrency = None
1896
 
    try:
1897
 
        concurrency = int(concurrency)
1898
 
    except (TypeError, ValueError):
1899
 
        concurrency = 1
1900
 
    if use_cache:
1901
 
        _cached_concurrency = concurrency
1902
 
    return concurrency