~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Andrew Bennetts
  • Date: 2010-03-11 04:33:41 UTC
  • mfrom: (4797.33.4 2.1)
  • mto: This revision was merged to the branch mainline in revision 5082.
  • Revision ID: andrew.bennetts@canonical.com-20100311043341-rzdik83fnactjsxs
Merge lp:bzr/2.1, including fixes for #496813, #526211, #526353.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
21
21
                  S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
22
22
import sys
23
23
import time
 
24
import codecs
 
25
import warnings
24
26
 
25
27
from bzrlib.lazy_import import lazy_import
26
28
lazy_import(globals(), """
27
 
import codecs
28
29
from datetime import datetime
29
30
import errno
30
31
from ntpath import (abspath as _nt_abspath,
38
39
from shutil import (
39
40
    rmtree,
40
41
    )
 
42
import signal
 
43
import subprocess
41
44
import tempfile
42
45
from tempfile import (
43
46
    mkdtemp,
69
72
from bzrlib import symbol_versioning
70
73
 
71
74
 
 
75
# Cross platform wall-clock time functionality with decent resolution.
 
76
# On Linux ``time.clock`` returns only CPU time. On Windows, ``time.time()``
 
77
# only has a resolution of ~15ms. Note that ``time.clock()`` is not
 
78
# synchronized with ``time.time()``, this is only meant to be used to find
 
79
# delta times by subtracting from another call to this function.
 
80
timer_func = time.time
 
81
if sys.platform == 'win32':
 
82
    timer_func = time.clock
 
83
 
72
84
# On win32, O_BINARY is used to indicate the file should
73
85
# be opened in binary mode, rather than text mode.
74
86
# On other platforms, O_BINARY doesn't exist, because
75
87
# they always open in binary mode, so it is okay to
76
 
# OR with 0 on those platforms
 
88
# OR with 0 on those platforms.
 
89
# O_NOINHERIT and O_TEXT exists only on win32 too.
77
90
O_BINARY = getattr(os, 'O_BINARY', 0)
 
91
O_TEXT = getattr(os, 'O_TEXT', 0)
 
92
O_NOINHERIT = getattr(os, 'O_NOINHERIT', 0)
 
93
 
 
94
 
 
95
def get_unicode_argv():
 
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(("Parameter '%r' is unsupported by the current "
 
101
                                                            "encoding." % a))
78
102
 
79
103
 
80
104
def make_readonly(filename):
97
121
 
98
122
    :param paths: A container (and hence not None) of paths.
99
123
    :return: A set of paths sufficient to include everything in paths via
100
 
        is_inside_any, drawn from the paths parameter.
 
124
        is_inside, drawn from the paths parameter.
101
125
    """
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
    if len(paths) < 2:
 
127
        return set(paths)
 
128
 
 
129
    def sort_key(path):
 
130
        return path.split('/')
 
131
    sorted_paths = sorted(list(paths), key=sort_key)
 
132
 
 
133
    search_paths = [sorted_paths[0]]
 
134
    for path in sorted_paths[1:]:
 
135
        if not is_inside(search_paths[-1], path):
 
136
            # This path is unique, add it
 
137
            search_paths.append(path)
 
138
 
 
139
    return set(search_paths)
110
140
 
111
141
 
112
142
_QUOTE_RE = None
121
151
    global _QUOTE_RE
122
152
    if _QUOTE_RE is None:
123
153
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
124
 
        
 
154
 
125
155
    if _QUOTE_RE.search(f):
126
156
        return '"' + f + '"'
127
157
    else:
152
182
    try:
153
183
        return _kind_marker_map[kind]
154
184
    except KeyError:
155
 
        raise errors.BzrError('invalid file kind %r' % kind)
 
185
        # Slightly faster than using .get(, '') when the common case is that
 
186
        # kind will be found
 
187
        return ''
156
188
 
157
189
 
158
190
lexists = getattr(os.path, 'lexists', None)
171
203
 
172
204
def fancy_rename(old, new, rename_func, unlink_func):
173
205
    """A fancy rename, when you don't have atomic rename.
174
 
    
 
206
 
175
207
    :param old: The old path, to rename from
176
208
    :param new: The new path, to rename to
177
209
    :param rename_func: The potentially non-atomic rename function
178
 
    :param unlink_func: A way to delete the target file if the full rename succeeds
 
210
    :param unlink_func: A way to delete the target file if the full rename
 
211
        succeeds
179
212
    """
180
 
 
181
213
    # sftp rename doesn't allow overwriting, so play tricks:
182
214
    base = os.path.basename(new)
183
215
    dirname = os.path.dirname(new)
184
 
    tmp_name = u'tmp.%s.%.9f.%d.%s' % (base, time.time(), os.getpid(), rand_chars(10))
 
216
    # callers use different encodings for the paths so the following MUST
 
217
    # respect that. We rely on python upcasting to unicode if new is unicode
 
218
    # and keeping a str if not.
 
219
    tmp_name = 'tmp.%s.%.9f.%d.%s' % (base, time.time(),
 
220
                                      os.getpid(), rand_chars(10))
185
221
    tmp_name = pathjoin(dirname, tmp_name)
186
222
 
187
223
    # Rename the file out of the way, but keep track if it didn't exist
207
243
    else:
208
244
        file_existed = True
209
245
 
 
246
    failure_exc = None
210
247
    success = False
211
248
    try:
212
249
        try:
218
255
            # source and target may be aliases of each other (e.g. on a
219
256
            # case-insensitive filesystem), so we may have accidentally renamed
220
257
            # source by when we tried to rename target
221
 
            if not (file_existed and e.errno in (None, errno.ENOENT)):
222
 
                raise
 
258
            failure_exc = sys.exc_info()
 
259
            if (file_existed and e.errno in (None, errno.ENOENT)
 
260
                and old.lower() == new.lower()):
 
261
                # source and target are the same file on a case-insensitive
 
262
                # filesystem, so we don't generate an exception
 
263
                failure_exc = None
223
264
    finally:
224
265
        if file_existed:
225
266
            # If the file used to exist, rename it back into place
228
269
                unlink_func(tmp_name)
229
270
            else:
230
271
                rename_func(tmp_name, new)
 
272
    if failure_exc is not None:
 
273
        raise failure_exc[0], failure_exc[1], failure_exc[2]
231
274
 
232
275
 
233
276
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
317
360
    """We expect to be able to atomically replace 'new' with old.
318
361
 
319
362
    On win32, if new exists, it must be moved out of the way first,
320
 
    and then deleted. 
 
363
    and then deleted.
321
364
    """
322
365
    try:
323
366
        fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
324
367
    except OSError, e:
325
368
        if e.errno in (errno.EPERM, errno.EACCES, errno.EBUSY, errno.EINVAL):
326
 
            # If we try to rename a non-existant file onto cwd, we get 
327
 
            # EPERM or EACCES instead of ENOENT, this will raise ENOENT 
 
369
            # If we try to rename a non-existant file onto cwd, we get
 
370
            # EPERM or EACCES instead of ENOENT, this will raise ENOENT
328
371
            # if the old path doesn't exist, sometimes we get EACCES
329
372
            # On Linux, we seem to get EBUSY, on Mac we get EINVAL
330
373
            os.lstat(old)
384
427
    def rmtree(path, ignore_errors=False, onerror=_win32_delete_readonly):
385
428
        """Replacer for shutil.rmtree: could remove readonly dirs/files"""
386
429
        return shutil.rmtree(path, ignore_errors, onerror)
 
430
 
 
431
    f = win32utils.get_unicode_argv     # special function or None
 
432
    if f is not None:
 
433
        get_unicode_argv = f
 
434
 
387
435
elif sys.platform == 'darwin':
388
436
    getcwd = _mac_getcwd
389
437
 
470
518
 
471
519
def is_inside(dir, fname):
472
520
    """True if fname is inside dir.
473
 
    
 
521
 
474
522
    The parameters should typically be passed to osutils.normpath first, so
475
523
    that . and .. and repeated slashes are eliminated, and the separators
476
524
    are canonical for the platform.
477
 
    
478
 
    The empty string as a dir name is taken as top-of-tree and matches 
 
525
 
 
526
    The empty string as a dir name is taken as top-of-tree and matches
479
527
    everything.
480
528
    """
481
 
    # XXX: Most callers of this can actually do something smarter by 
 
529
    # XXX: Most callers of this can actually do something smarter by
482
530
    # looking at the inventory
483
531
    if dir == fname:
484
532
        return True
485
 
    
 
533
 
486
534
    if dir == '':
487
535
        return True
488
536
 
597
645
    return s.hexdigest()
598
646
 
599
647
 
 
648
def size_sha_file(f):
 
649
    """Calculate the size and hexdigest of an open file.
 
650
 
 
651
    The file cursor should be already at the start and
 
652
    the caller is responsible for closing the file afterwards.
 
653
    """
 
654
    size = 0
 
655
    s = sha()
 
656
    BUFSIZE = 128<<10
 
657
    while True:
 
658
        b = f.read(BUFSIZE)
 
659
        if not b:
 
660
            break
 
661
        size += len(b)
 
662
        s.update(b)
 
663
    return size, s.hexdigest()
 
664
 
 
665
 
600
666
def sha_file_by_name(fname):
601
667
    """Calculate the SHA1 of a file by reading the full text"""
602
668
    s = sha()
603
 
    f = os.open(fname, os.O_RDONLY | O_BINARY)
 
669
    f = os.open(fname, os.O_RDONLY | O_BINARY | O_NOINHERIT)
604
670
    try:
605
671
        while True:
606
672
            b = os.read(f, 1<<16)
648
714
    return offset.days * 86400 + offset.seconds
649
715
 
650
716
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
651
 
    
 
717
_default_format_by_weekday_num = [wd + " %Y-%m-%d %H:%M:%S" for wd in weekdays]
 
718
 
 
719
 
652
720
def format_date(t, offset=0, timezone='original', date_fmt=None,
653
721
                show_offset=True):
654
722
    """Return a formatted date string.
667
735
    date_str = time.strftime(date_fmt, tt)
668
736
    return date_str + offset_str
669
737
 
 
738
 
 
739
# Cache of formatted offset strings
 
740
_offset_cache = {}
 
741
 
 
742
 
 
743
def format_date_with_offset_in_original_timezone(t, offset=0,
 
744
    _cache=_offset_cache):
 
745
    """Return a formatted date string in the original timezone.
 
746
 
 
747
    This routine may be faster then format_date.
 
748
 
 
749
    :param t: Seconds since the epoch.
 
750
    :param offset: Timezone offset in seconds east of utc.
 
751
    """
 
752
    if offset is None:
 
753
        offset = 0
 
754
    tt = time.gmtime(t + offset)
 
755
    date_fmt = _default_format_by_weekday_num[tt[6]]
 
756
    date_str = time.strftime(date_fmt, tt)
 
757
    offset_str = _cache.get(offset, None)
 
758
    if offset_str is None:
 
759
        offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
 
760
        _cache[offset] = offset_str
 
761
    return date_str + offset_str
 
762
 
 
763
 
670
764
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
671
765
                      show_offset=True):
672
766
    """Return an unicode date string formatted according to the current locale.
683
777
               _format_date(t, offset, timezone, date_fmt, show_offset)
684
778
    date_str = time.strftime(date_fmt, tt)
685
779
    if not isinstance(date_str, unicode):
686
 
        date_str = date_str.decode(bzrlib.user_encoding, 'replace')
 
780
        date_str = date_str.decode(get_user_encoding(), 'replace')
687
781
    return date_str + offset_str
688
782
 
 
783
 
689
784
def _format_date(t, offset, timezone, date_fmt, show_offset):
690
785
    if timezone == 'utc':
691
786
        tt = time.gmtime(t)
710
805
 
711
806
def compact_date(when):
712
807
    return time.strftime('%Y%m%d%H%M%S', time.gmtime(when))
713
 
    
 
808
 
714
809
 
715
810
def format_delta(delta):
716
811
    """Get a nice looking string for a time delta.
792
887
ALNUM = '0123456789abcdefghijklmnopqrstuvwxyz'
793
888
def rand_chars(num):
794
889
    """Return a random string of num alphanumeric characters
795
 
    
796
 
    The result only contains lowercase chars because it may be used on 
 
890
 
 
891
    The result only contains lowercase chars because it may be used on
797
892
    case-insensitive filesystems.
798
893
    """
799
894
    s = ''
829
924
    return pathjoin(*p)
830
925
 
831
926
 
 
927
def parent_directories(filename):
 
928
    """Return the list of parent directories, deepest first.
 
929
    
 
930
    For example, parent_directories("a/b/c") -> ["a/b", "a"].
 
931
    """
 
932
    parents = []
 
933
    parts = splitpath(dirname(filename))
 
934
    while parts:
 
935
        parents.append(joinpath(parts))
 
936
        parts.pop()
 
937
    return parents
 
938
 
 
939
 
 
940
_extension_load_failures = []
 
941
 
 
942
 
 
943
def failed_to_load_extension(exception):
 
944
    """Handle failing to load a binary extension.
 
945
 
 
946
    This should be called from the ImportError block guarding the attempt to
 
947
    import the native extension.  If this function returns, the pure-Python
 
948
    implementation should be loaded instead::
 
949
 
 
950
    >>> try:
 
951
    >>>     import bzrlib._fictional_extension_pyx
 
952
    >>> except ImportError, e:
 
953
    >>>     bzrlib.osutils.failed_to_load_extension(e)
 
954
    >>>     import bzrlib._fictional_extension_py
 
955
    """
 
956
    # NB: This docstring is just an example, not a doctest, because doctest
 
957
    # currently can't cope with the use of lazy imports in this namespace --
 
958
    # mbp 20090729
 
959
    
 
960
    # This currently doesn't report the failure at the time it occurs, because
 
961
    # they tend to happen very early in startup when we can't check config
 
962
    # files etc, and also we want to report all failures but not spam the user
 
963
    # with 10 warnings.
 
964
    from bzrlib import trace
 
965
    exception_str = str(exception)
 
966
    if exception_str not in _extension_load_failures:
 
967
        trace.mutter("failed to load compiled extension: %s" % exception_str)
 
968
        _extension_load_failures.append(exception_str)
 
969
 
 
970
 
 
971
def report_extension_load_failures():
 
972
    if not _extension_load_failures:
 
973
        return
 
974
    from bzrlib.config import GlobalConfig
 
975
    if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
 
976
        return
 
977
    # the warnings framework should by default show this only once
 
978
    from bzrlib.trace import warning
 
979
    warning(
 
980
        "bzr: warning: some compiled extensions could not be loaded; "
 
981
        "see <https://answers.launchpad.net/bzr/+faq/703>")
 
982
    # we no longer show the specific missing extensions here, because it makes
 
983
    # the message too long and scary - see
 
984
    # https://bugs.launchpad.net/bzr/+bug/430529
 
985
 
 
986
 
832
987
try:
833
988
    from bzrlib._chunks_to_lines_pyx import chunks_to_lines
834
 
except ImportError:
 
989
except ImportError, e:
 
990
    failed_to_load_extension(e)
835
991
    from bzrlib._chunks_to_lines_py import chunks_to_lines
836
992
 
837
993
 
875
1031
        shutil.copyfile(src, dest)
876
1032
 
877
1033
 
878
 
# Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
879
 
# Forgiveness than Permission (EAFP) because:
880
 
# - root can damage a solaris file system by using unlink,
881
 
# - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
882
 
#   EACCES, OSX: EPERM) when invoked on a directory.
883
1034
def delete_any(path):
884
 
    """Delete a file or directory."""
 
1035
    """Delete a file, symlink or directory.  
 
1036
    
 
1037
    Will delete even if readonly.
 
1038
    """
 
1039
    try:
 
1040
       _delete_file_or_dir(path)
 
1041
    except (OSError, IOError), e:
 
1042
        if e.errno in (errno.EPERM, errno.EACCES):
 
1043
            # make writable and try again
 
1044
            try:
 
1045
                make_writable(path)
 
1046
            except (OSError, IOError):
 
1047
                pass
 
1048
            _delete_file_or_dir(path)
 
1049
        else:
 
1050
            raise
 
1051
 
 
1052
 
 
1053
def _delete_file_or_dir(path):
 
1054
    # Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
 
1055
    # Forgiveness than Permission (EAFP) because:
 
1056
    # - root can damage a solaris file system by using unlink,
 
1057
    # - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
 
1058
    #   EACCES, OSX: EPERM) when invoked on a directory.
885
1059
    if isdir(path): # Takes care of symlinks
886
1060
        os.rmdir(path)
887
1061
    else:
907
1081
            and sys.platform not in ('cygwin', 'win32'))
908
1082
 
909
1083
 
 
1084
def readlink(abspath):
 
1085
    """Return a string representing the path to which the symbolic link points.
 
1086
 
 
1087
    :param abspath: The link absolute unicode path.
 
1088
 
 
1089
    This his guaranteed to return the symbolic link in unicode in all python
 
1090
    versions.
 
1091
    """
 
1092
    link = abspath.encode(_fs_enc)
 
1093
    target = os.readlink(link)
 
1094
    target = target.decode(_fs_enc)
 
1095
    return target
 
1096
 
 
1097
 
910
1098
def contains_whitespace(s):
911
1099
    """True if there are any whitespace characters in s."""
912
1100
    # string.whitespace can include '\xa0' in certain locales, because it is
956
1144
 
957
1145
    s = []
958
1146
    head = rp
959
 
    while len(head) >= len(base):
 
1147
    while True:
 
1148
        if len(head) <= len(base) and head != base:
 
1149
            raise errors.PathNotChild(rp, base)
960
1150
        if head == base:
961
1151
            break
962
 
        head, tail = os.path.split(head)
 
1152
        head, tail = split(head)
963
1153
        if tail:
964
 
            s.insert(0, tail)
965
 
    else:
966
 
        raise errors.PathNotChild(rp, base)
 
1154
            s.append(tail)
967
1155
 
968
1156
    if s:
969
 
        return pathjoin(*s)
 
1157
        return pathjoin(*reversed(s))
970
1158
    else:
971
1159
        return ''
972
1160
 
999
1187
    bit_iter = iter(rel.split('/'))
1000
1188
    for bit in bit_iter:
1001
1189
        lbit = bit.lower()
1002
 
        for look in _listdir(current):
 
1190
        try:
 
1191
            next_entries = _listdir(current)
 
1192
        except OSError: # enoent, eperm, etc
 
1193
            # We can't find this in the filesystem, so just append the
 
1194
            # remaining bits.
 
1195
            current = pathjoin(current, bit, *list(bit_iter))
 
1196
            break
 
1197
        for look in next_entries:
1003
1198
            if lbit == look.lower():
1004
1199
                current = pathjoin(current, look)
1005
1200
                break
1009
1204
            # the target of a move, for example).
1010
1205
            current = pathjoin(current, bit, *list(bit_iter))
1011
1206
            break
1012
 
    return current[len(abs_base)+1:]
 
1207
    return current[len(abs_base):].lstrip('/')
1013
1208
 
1014
1209
# 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":
 
1210
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
 
1211
# filesystems), for example, so could probably benefit from the same basic
 
1212
# support there.  For now though, only Windows and OSX get that support, and
 
1213
# they get it for *all* file-systems!
 
1214
if sys.platform in ('win32', 'darwin'):
1019
1215
    canonical_relpath = _cicp_canonical_relpath
1020
1216
else:
1021
1217
    canonical_relpath = relpath
1033
1229
    """Coerce unicode_or_utf8_string into unicode.
1034
1230
 
1035
1231
    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.
 
1232
    Otherwise it is decoded from utf-8. If decoding fails, the exception is
 
1233
    wrapped in a BzrBadParameterNotUnicode exception.
1039
1234
    """
1040
1235
    if isinstance(unicode_or_utf8_string, unicode):
1041
1236
        return unicode_or_utf8_string
1128
1323
 
1129
1324
    On platforms where the system normalizes filenames (Mac OSX),
1130
1325
    you can access a file by any path which will normalize correctly.
1131
 
    On platforms where the system does not normalize filenames 
 
1326
    On platforms where the system does not normalize filenames
1132
1327
    (Windows, Linux), you have to access a file by its exact path.
1133
1328
 
1134
 
    Internally, bzr only supports NFC normalization, since that is 
 
1329
    Internally, bzr only supports NFC normalization, since that is
1135
1330
    the standard for XML documents.
1136
1331
 
1137
1332
    So return the normalized path, and a flag indicating if the file
1154
1349
    normalized_filename = _inaccessible_normalized_filename
1155
1350
 
1156
1351
 
 
1352
def set_signal_handler(signum, handler, restart_syscall=True):
 
1353
    """A wrapper for signal.signal that also calls siginterrupt(signum, False)
 
1354
    on platforms that support that.
 
1355
 
 
1356
    :param restart_syscall: if set, allow syscalls interrupted by a signal to
 
1357
        automatically restart (by calling `signal.siginterrupt(signum,
 
1358
        False)`).  May be ignored if the feature is not available on this
 
1359
        platform or Python version.
 
1360
    """
 
1361
    old_handler = signal.signal(signum, handler)
 
1362
    if restart_syscall:
 
1363
        try:
 
1364
            siginterrupt = signal.siginterrupt
 
1365
        except AttributeError: # siginterrupt doesn't exist on this platform, or for this version of
 
1366
            # Python.
 
1367
            pass
 
1368
        else:
 
1369
            siginterrupt(signum, False)
 
1370
    return old_handler
 
1371
 
 
1372
 
 
1373
default_terminal_width = 80
 
1374
"""The default terminal width for ttys.
 
1375
 
 
1376
This is defined so that higher levels can share a common fallback value when
 
1377
terminal_width() returns None.
 
1378
"""
 
1379
 
 
1380
 
1157
1381
def terminal_width():
1158
 
    """Return estimated terminal width."""
1159
 
    if sys.platform == 'win32':
1160
 
        return win32utils.get_console_size()[0]
1161
 
    width = 0
 
1382
    """Return terminal width.
 
1383
 
 
1384
    None is returned if the width can't established precisely.
 
1385
 
 
1386
    The rules are:
 
1387
    - if BZR_COLUMNS is set, returns its value
 
1388
    - if there is no controlling terminal, returns None
 
1389
    - if COLUMNS is set, returns its value,
 
1390
 
 
1391
    From there, we need to query the OS to get the size of the controlling
 
1392
    terminal.
 
1393
 
 
1394
    Unices:
 
1395
    - get termios.TIOCGWINSZ
 
1396
    - if an error occurs or a negative value is obtained, returns None
 
1397
 
 
1398
    Windows:
 
1399
    
 
1400
    - win32utils.get_console_size() decides,
 
1401
    - returns None on error (provided default value)
 
1402
    """
 
1403
 
 
1404
    # If BZR_COLUMNS is set, take it, user is always right
 
1405
    try:
 
1406
        return int(os.environ['BZR_COLUMNS'])
 
1407
    except (KeyError, ValueError):
 
1408
        pass
 
1409
 
 
1410
    isatty = getattr(sys.stdout, 'isatty', None)
 
1411
    if  isatty is None or not isatty():
 
1412
        # Don't guess, setting BZR_COLUMNS is the recommended way to override.
 
1413
        return None
 
1414
 
 
1415
    # If COLUMNS is set, take it, the terminal knows better (even inside a
 
1416
    # given terminal, the application can decide to set COLUMNS to a lower
 
1417
    # value (splitted screen) or a bigger value (scroll bars))
 
1418
    try:
 
1419
        return int(os.environ['COLUMNS'])
 
1420
    except (KeyError, ValueError):
 
1421
        pass
 
1422
 
 
1423
    width, height = _terminal_size(None, None)
 
1424
    if width <= 0:
 
1425
        # Consider invalid values as meaning no width
 
1426
        return None
 
1427
 
 
1428
    return width
 
1429
 
 
1430
 
 
1431
def _win32_terminal_size(width, height):
 
1432
    width, height = win32utils.get_console_size(defaultx=width, defaulty=height)
 
1433
    return width, height
 
1434
 
 
1435
 
 
1436
def _ioctl_terminal_size(width, height):
1162
1437
    try:
1163
1438
        import struct, fcntl, termios
1164
1439
        s = struct.pack('HHHH', 0, 0, 0, 0)
1165
1440
        x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
1166
 
        width = struct.unpack('HHHH', x)[1]
1167
 
    except IOError:
 
1441
        height, width = struct.unpack('HHHH', x)[0:2]
 
1442
    except (IOError, AttributeError):
1168
1443
        pass
1169
 
    if width <= 0:
1170
 
        try:
1171
 
            width = int(os.environ['COLUMNS'])
1172
 
        except:
 
1444
    return width, height
 
1445
 
 
1446
_terminal_size = None
 
1447
"""Returns the terminal size as (width, height).
 
1448
 
 
1449
:param width: Default value for width.
 
1450
:param height: Default value for height.
 
1451
 
 
1452
This is defined specifically for each OS and query the size of the controlling
 
1453
terminal. If any error occurs, the provided default values should be returned.
 
1454
"""
 
1455
if sys.platform == 'win32':
 
1456
    _terminal_size = _win32_terminal_size
 
1457
else:
 
1458
    _terminal_size = _ioctl_terminal_size
 
1459
 
 
1460
 
 
1461
def _terminal_size_changed(signum, frame):
 
1462
    """Set COLUMNS upon receiving a SIGnal for WINdow size CHange."""
 
1463
    width, height = _terminal_size(None, None)
 
1464
    if width is not None:
 
1465
        os.environ['COLUMNS'] = str(width)
 
1466
 
 
1467
 
 
1468
_registered_sigwinch = False
 
1469
 
 
1470
def watch_sigwinch():
 
1471
    """Register for SIGWINCH, once and only once."""
 
1472
    global _registered_sigwinch
 
1473
    if not _registered_sigwinch:
 
1474
        if sys.platform == 'win32':
 
1475
            # Martin (gz) mentioned WINDOW_BUFFER_SIZE_RECORD from
 
1476
            # ReadConsoleInput but I've no idea how to plug that in
 
1477
            # the current design -- vila 20091216
1173
1478
            pass
1174
 
    if width <= 0:
1175
 
        width = 80
1176
 
 
1177
 
    return width
 
1479
        else:
 
1480
            set_signal_handler(signal.SIGWINCH, _terminal_size_changed)
 
1481
        _registered_sigwinch = True
1178
1482
 
1179
1483
 
1180
1484
def supports_executable():
1217
1521
 
1218
1522
 
1219
1523
def check_legal_path(path):
1220
 
    """Check whether the supplied path is legal.  
 
1524
    """Check whether the supplied path is legal.
1221
1525
    This is only required on Windows, so we don't test on other platforms
1222
1526
    right now.
1223
1527
    """
1257
1561
 
1258
1562
def walkdirs(top, prefix=""):
1259
1563
    """Yield data about all the directories in a tree.
1260
 
    
 
1564
 
1261
1565
    This yields all the data about the contents of a directory at a time.
1262
1566
    After each directory has been yielded, if the caller has mutated the list
1263
1567
    to exclude some directories, they are then not descended into.
1264
 
    
 
1568
 
1265
1569
    The data yielded is of the form:
1266
1570
    ((directory-relpath, directory-path-from-top),
1267
1571
    [(relpath, basename, kind, lstat, path-from-top), ...]),
1268
1572
     - directory-relpath is the relative path of the directory being returned
1269
1573
       with respect to top. prefix is prepended to this.
1270
 
     - directory-path-from-root is the path including top for this directory. 
 
1574
     - directory-path-from-root is the path including top for this directory.
1271
1575
       It is suitable for use with os functions.
1272
1576
     - relpath is the relative path within the subtree being walked.
1273
1577
     - basename is the basename of the path
1275
1579
       present within the tree - but it may be recorded as versioned. See
1276
1580
       versioned_kind.
1277
1581
     - lstat is the stat data *if* the file was statted.
1278
 
     - planned, not implemented: 
 
1582
     - planned, not implemented:
1279
1583
       path_from_tree_root is the path from the root of the tree.
1280
1584
 
1281
 
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This 
 
1585
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1282
1586
        allows one to walk a subtree but get paths that are relative to a tree
1283
1587
        rooted higher up.
1284
1588
    :return: an iterator over the dirs.
1285
1589
    """
1286
1590
    #TODO there is a bit of a smell where the results of the directory-
1287
 
    # summary in this, and the path from the root, may not agree 
 
1591
    # summary in this, and the path from the root, may not agree
1288
1592
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
1289
1593
    # potentially confusing output. We should make this more robust - but
1290
1594
    # not at a speed cost. RBC 20060731
1374
1678
            #       for win98 anyway.
1375
1679
            try:
1376
1680
                from bzrlib._walkdirs_win32 import Win32ReadDir
1377
 
            except ImportError:
1378
 
                _selected_dir_reader = UnicodeDirReader()
1379
 
            else:
1380
1681
                _selected_dir_reader = Win32ReadDir()
1381
 
        elif fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
 
1682
            except ImportError:
 
1683
                pass
 
1684
        elif fs_encoding in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
1382
1685
            # ANSI_X3.4-1968 is a form of ASCII
1383
 
            _selected_dir_reader = UnicodeDirReader()
1384
 
        else:
1385
1686
            try:
1386
1687
                from bzrlib._readdir_pyx import UTF8DirReader
1387
 
            except ImportError:
1388
 
                # No optimised code path
1389
 
                _selected_dir_reader = UnicodeDirReader()
1390
 
            else:
1391
1688
                _selected_dir_reader = UTF8DirReader()
 
1689
            except ImportError, e:
 
1690
                failed_to_load_extension(e)
 
1691
                pass
 
1692
 
 
1693
    if _selected_dir_reader is None:
 
1694
        # Fallback to the python version
 
1695
        _selected_dir_reader = UnicodeDirReader()
 
1696
 
1392
1697
    # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1393
1698
    # But we don't actually uses 1-3 in pending, so set them to None
1394
1699
    pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]]
1460
1765
def copy_tree(from_path, to_path, handlers={}):
1461
1766
    """Copy all of the entries in from_path into to_path.
1462
1767
 
1463
 
    :param from_path: The base directory to copy. 
 
1768
    :param from_path: The base directory to copy.
1464
1769
    :param to_path: The target directory. If it does not exist, it will
1465
1770
        be created.
1466
1771
    :param handlers: A dictionary of functions, which takes a source and
1623
1928
    return b
1624
1929
 
1625
1930
 
1626
 
def send_all(socket, bytes):
 
1931
def send_all(socket, bytes, report_activity=None):
1627
1932
    """Send all bytes on a socket.
1628
1933
 
1629
1934
    Regular socket.sendall() can give socket error 10053 on Windows.  This
1630
1935
    implementation sends no more than 64k at a time, which avoids this problem.
 
1936
 
 
1937
    :param report_activity: Call this as bytes are read, see
 
1938
        Transport._report_activity
1631
1939
    """
1632
1940
    chunk_size = 2**16
1633
1941
    for pos in xrange(0, len(bytes), chunk_size):
1634
 
        until_no_eintr(socket.sendall, bytes[pos:pos+chunk_size])
 
1942
        block = bytes[pos:pos+chunk_size]
 
1943
        if report_activity is not None:
 
1944
            report_activity(len(block), 'write')
 
1945
        until_no_eintr(socket.sendall, block)
1635
1946
 
1636
1947
 
1637
1948
def dereference_path(path):
1688
1999
        try:
1689
2000
            from bzrlib._readdir_pyx import UTF8DirReader
1690
2001
            file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1691
 
        except ImportError:
 
2002
        except ImportError, e:
 
2003
            # This is one time where we won't warn that an extension failed to
 
2004
            # load. The extension is never available on Windows anyway.
1692
2005
            from bzrlib._readdir_py import (
1693
2006
                _kind_from_mode as file_kind_from_stat_mode
1694
2007
                )
1716
2029
                continue
1717
2030
            raise
1718
2031
 
 
2032
def re_compile_checked(re_string, flags=0, where=""):
 
2033
    """Return a compiled re, or raise a sensible error.
 
2034
 
 
2035
    This should only be used when compiling user-supplied REs.
 
2036
 
 
2037
    :param re_string: Text form of regular expression.
 
2038
    :param flags: eg re.IGNORECASE
 
2039
    :param where: Message explaining to the user the context where
 
2040
        it occurred, eg 'log search filter'.
 
2041
    """
 
2042
    # from https://bugs.launchpad.net/bzr/+bug/251352
 
2043
    try:
 
2044
        re_obj = re.compile(re_string, flags)
 
2045
        re_obj.search("")
 
2046
        return re_obj
 
2047
    except re.error, e:
 
2048
        if where:
 
2049
            where = ' in ' + where
 
2050
        # despite the name 'error' is a type
 
2051
        raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
 
2052
            % (where, re_string, e))
 
2053
 
1719
2054
 
1720
2055
if sys.platform == "win32":
1721
2056
    import msvcrt
1733
2068
        finally:
1734
2069
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
1735
2070
        return ch
 
2071
 
 
2072
 
 
2073
if sys.platform == 'linux2':
 
2074
    def _local_concurrency():
 
2075
        concurrency = None
 
2076
        prefix = 'processor'
 
2077
        for line in file('/proc/cpuinfo', 'rb'):
 
2078
            if line.startswith(prefix):
 
2079
                concurrency = int(line[line.find(':')+1:]) + 1
 
2080
        return concurrency
 
2081
elif sys.platform == 'darwin':
 
2082
    def _local_concurrency():
 
2083
        return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
 
2084
                                stdout=subprocess.PIPE).communicate()[0]
 
2085
elif sys.platform[0:7] == 'freebsd':
 
2086
    def _local_concurrency():
 
2087
        return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
 
2088
                                stdout=subprocess.PIPE).communicate()[0]
 
2089
elif sys.platform == 'sunos5':
 
2090
    def _local_concurrency():
 
2091
        return subprocess.Popen(['psrinfo', '-p',],
 
2092
                                stdout=subprocess.PIPE).communicate()[0]
 
2093
elif sys.platform == "win32":
 
2094
    def _local_concurrency():
 
2095
        # This appears to return the number of cores.
 
2096
        return os.environ.get('NUMBER_OF_PROCESSORS')
 
2097
else:
 
2098
    def _local_concurrency():
 
2099
        # Who knows ?
 
2100
        return None
 
2101
 
 
2102
 
 
2103
_cached_local_concurrency = None
 
2104
 
 
2105
def local_concurrency(use_cache=True):
 
2106
    """Return how many processes can be run concurrently.
 
2107
 
 
2108
    Rely on platform specific implementations and default to 1 (one) if
 
2109
    anything goes wrong.
 
2110
    """
 
2111
    global _cached_local_concurrency
 
2112
 
 
2113
    if _cached_local_concurrency is not None and use_cache:
 
2114
        return _cached_local_concurrency
 
2115
 
 
2116
    concurrency = os.environ.get('BZR_CONCURRENCY', None)
 
2117
    if concurrency is None:
 
2118
        try:
 
2119
            concurrency = _local_concurrency()
 
2120
        except (OSError, IOError):
 
2121
            pass
 
2122
    try:
 
2123
        concurrency = int(concurrency)
 
2124
    except (TypeError, ValueError):
 
2125
        concurrency = 1
 
2126
    if use_cache:
 
2127
        _cached_concurrency = concurrency
 
2128
    return concurrency
 
2129
 
 
2130
 
 
2131
class UnicodeOrBytesToBytesWriter(codecs.StreamWriter):
 
2132
    """A stream writer that doesn't decode str arguments."""
 
2133
 
 
2134
    def __init__(self, encode, stream, errors='strict'):
 
2135
        codecs.StreamWriter.__init__(self, stream, errors)
 
2136
        self.encode = encode
 
2137
 
 
2138
    def write(self, object):
 
2139
        if type(object) is str:
 
2140
            self.stream.write(object)
 
2141
        else:
 
2142
            data, _ = self.encode(object, self.errors)
 
2143
            self.stream.write(data)
 
2144
 
 
2145
if sys.platform == 'win32':
 
2146
    def open_file(filename, mode='r', bufsize=-1):
 
2147
        """This function is used to override the ``open`` builtin.
 
2148
        
 
2149
        But it uses O_NOINHERIT flag so the file handle is not inherited by
 
2150
        child processes.  Deleting or renaming a closed file opened with this
 
2151
        function is not blocking child processes.
 
2152
        """
 
2153
        writing = 'w' in mode
 
2154
        appending = 'a' in mode
 
2155
        updating = '+' in mode
 
2156
        binary = 'b' in mode
 
2157
 
 
2158
        flags = O_NOINHERIT
 
2159
        # see http://msdn.microsoft.com/en-us/library/yeby3zcb%28VS.71%29.aspx
 
2160
        # for flags for each modes.
 
2161
        if binary:
 
2162
            flags |= O_BINARY
 
2163
        else:
 
2164
            flags |= O_TEXT
 
2165
 
 
2166
        if writing:
 
2167
            if updating:
 
2168
                flags |= os.O_RDWR
 
2169
            else:
 
2170
                flags |= os.O_WRONLY
 
2171
            flags |= os.O_CREAT | os.O_TRUNC
 
2172
        elif appending:
 
2173
            if updating:
 
2174
                flags |= os.O_RDWR
 
2175
            else:
 
2176
                flags |= os.O_WRONLY
 
2177
            flags |= os.O_CREAT | os.O_APPEND
 
2178
        else: #reading
 
2179
            if updating:
 
2180
                flags |= os.O_RDWR
 
2181
            else:
 
2182
                flags |= os.O_RDONLY
 
2183
 
 
2184
        return os.fdopen(os.open(filename, flags), mode, bufsize)
 
2185
else:
 
2186
    open_file = open