~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Vincent Ladeuil
  • Date: 2010-02-10 15:46:03 UTC
  • mfrom: (4985.3.21 update)
  • mto: This revision was merged to the branch mainline in revision 5021.
  • Revision ID: v.ladeuil+lp@free.fr-20100210154603-k4no1gvfuqpzrw7p
Update performs two merges in a more logical order but stop on conflicts

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
21
21
                  S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
22
22
import sys
23
23
import time
 
24
import warnings
24
25
 
25
26
from bzrlib.lazy_import import lazy_import
26
27
lazy_import(globals(), """
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
77
89
O_BINARY = getattr(os, 'O_BINARY', 0)
78
90
 
79
91
 
 
92
def get_unicode_argv():
 
93
    try:
 
94
        user_encoding = get_user_encoding()
 
95
        return [a.decode(user_encoding) for a in sys.argv[1:]]
 
96
    except UnicodeDecodeError:
 
97
        raise errors.BzrError(("Parameter '%r' is unsupported by the current "
 
98
                                                            "encoding." % a))
 
99
 
 
100
 
80
101
def make_readonly(filename):
81
102
    """Make a filename read-only."""
82
103
    mod = os.lstat(filename).st_mode
97
118
 
98
119
    :param paths: A container (and hence not None) of paths.
99
120
    :return: A set of paths sufficient to include everything in paths via
100
 
        is_inside_any, drawn from the paths parameter.
 
121
        is_inside, drawn from the paths parameter.
101
122
    """
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
 
123
    if len(paths) < 2:
 
124
        return set(paths)
 
125
 
 
126
    def sort_key(path):
 
127
        return path.split('/')
 
128
    sorted_paths = sorted(list(paths), key=sort_key)
 
129
 
 
130
    search_paths = [sorted_paths[0]]
 
131
    for path in sorted_paths[1:]:
 
132
        if not is_inside(search_paths[-1], path):
 
133
            # This path is unique, add it
 
134
            search_paths.append(path)
 
135
 
 
136
    return set(search_paths)
110
137
 
111
138
 
112
139
_QUOTE_RE = None
121
148
    global _QUOTE_RE
122
149
    if _QUOTE_RE is None:
123
150
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
124
 
        
 
151
 
125
152
    if _QUOTE_RE.search(f):
126
153
        return '"' + f + '"'
127
154
    else:
171
198
 
172
199
def fancy_rename(old, new, rename_func, unlink_func):
173
200
    """A fancy rename, when you don't have atomic rename.
174
 
    
 
201
 
175
202
    :param old: The old path, to rename from
176
203
    :param new: The new path, to rename to
177
204
    :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
 
205
    :param unlink_func: A way to delete the target file if the full rename
 
206
        succeeds
179
207
    """
180
 
 
181
208
    # sftp rename doesn't allow overwriting, so play tricks:
182
209
    base = os.path.basename(new)
183
210
    dirname = os.path.dirname(new)
184
 
    tmp_name = u'tmp.%s.%.9f.%d.%s' % (base, time.time(), os.getpid(), rand_chars(10))
 
211
    # callers use different encodings for the paths so the following MUST
 
212
    # respect that. We rely on python upcasting to unicode if new is unicode
 
213
    # and keeping a str if not.
 
214
    tmp_name = 'tmp.%s.%.9f.%d.%s' % (base, time.time(),
 
215
                                      os.getpid(), rand_chars(10))
185
216
    tmp_name = pathjoin(dirname, tmp_name)
186
217
 
187
218
    # Rename the file out of the way, but keep track if it didn't exist
207
238
    else:
208
239
        file_existed = True
209
240
 
 
241
    failure_exc = None
210
242
    success = False
211
243
    try:
212
244
        try:
218
250
            # source and target may be aliases of each other (e.g. on a
219
251
            # case-insensitive filesystem), so we may have accidentally renamed
220
252
            # source by when we tried to rename target
221
 
            if not (file_existed and e.errno in (None, errno.ENOENT)):
222
 
                raise
 
253
            failure_exc = sys.exc_info()
 
254
            if (file_existed and e.errno in (None, errno.ENOENT)
 
255
                and old.lower() == new.lower()):
 
256
                # source and target are the same file on a case-insensitive
 
257
                # filesystem, so we don't generate an exception
 
258
                failure_exc = None
223
259
    finally:
224
260
        if file_existed:
225
261
            # If the file used to exist, rename it back into place
228
264
                unlink_func(tmp_name)
229
265
            else:
230
266
                rename_func(tmp_name, new)
 
267
    if failure_exc is not None:
 
268
        raise failure_exc[0], failure_exc[1], failure_exc[2]
231
269
 
232
270
 
233
271
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
317
355
    """We expect to be able to atomically replace 'new' with old.
318
356
 
319
357
    On win32, if new exists, it must be moved out of the way first,
320
 
    and then deleted. 
 
358
    and then deleted.
321
359
    """
322
360
    try:
323
361
        fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
324
362
    except OSError, e:
325
363
        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 
 
364
            # If we try to rename a non-existant file onto cwd, we get
 
365
            # EPERM or EACCES instead of ENOENT, this will raise ENOENT
328
366
            # if the old path doesn't exist, sometimes we get EACCES
329
367
            # On Linux, we seem to get EBUSY, on Mac we get EINVAL
330
368
            os.lstat(old)
384
422
    def rmtree(path, ignore_errors=False, onerror=_win32_delete_readonly):
385
423
        """Replacer for shutil.rmtree: could remove readonly dirs/files"""
386
424
        return shutil.rmtree(path, ignore_errors, onerror)
 
425
 
 
426
    f = win32utils.get_unicode_argv     # special function or None
 
427
    if f is not None:
 
428
        get_unicode_argv = f
 
429
 
387
430
elif sys.platform == 'darwin':
388
431
    getcwd = _mac_getcwd
389
432
 
470
513
 
471
514
def is_inside(dir, fname):
472
515
    """True if fname is inside dir.
473
 
    
 
516
 
474
517
    The parameters should typically be passed to osutils.normpath first, so
475
518
    that . and .. and repeated slashes are eliminated, and the separators
476
519
    are canonical for the platform.
477
 
    
478
 
    The empty string as a dir name is taken as top-of-tree and matches 
 
520
 
 
521
    The empty string as a dir name is taken as top-of-tree and matches
479
522
    everything.
480
523
    """
481
 
    # XXX: Most callers of this can actually do something smarter by 
 
524
    # XXX: Most callers of this can actually do something smarter by
482
525
    # looking at the inventory
483
526
    if dir == fname:
484
527
        return True
485
 
    
 
528
 
486
529
    if dir == '':
487
530
        return True
488
531
 
597
640
    return s.hexdigest()
598
641
 
599
642
 
 
643
def size_sha_file(f):
 
644
    """Calculate the size and hexdigest of an open file.
 
645
 
 
646
    The file cursor should be already at the start and
 
647
    the caller is responsible for closing the file afterwards.
 
648
    """
 
649
    size = 0
 
650
    s = sha()
 
651
    BUFSIZE = 128<<10
 
652
    while True:
 
653
        b = f.read(BUFSIZE)
 
654
        if not b:
 
655
            break
 
656
        size += len(b)
 
657
        s.update(b)
 
658
    return size, s.hexdigest()
 
659
 
 
660
 
600
661
def sha_file_by_name(fname):
601
662
    """Calculate the SHA1 of a file by reading the full text"""
602
663
    s = sha()
648
709
    return offset.days * 86400 + offset.seconds
649
710
 
650
711
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
651
 
    
 
712
_default_format_by_weekday_num = [wd + " %Y-%m-%d %H:%M:%S" for wd in weekdays]
 
713
 
 
714
 
652
715
def format_date(t, offset=0, timezone='original', date_fmt=None,
653
716
                show_offset=True):
654
717
    """Return a formatted date string.
667
730
    date_str = time.strftime(date_fmt, tt)
668
731
    return date_str + offset_str
669
732
 
 
733
 
 
734
# Cache of formatted offset strings
 
735
_offset_cache = {}
 
736
 
 
737
 
 
738
def format_date_with_offset_in_original_timezone(t, offset=0,
 
739
    _cache=_offset_cache):
 
740
    """Return a formatted date string in the original timezone.
 
741
 
 
742
    This routine may be faster then format_date.
 
743
 
 
744
    :param t: Seconds since the epoch.
 
745
    :param offset: Timezone offset in seconds east of utc.
 
746
    """
 
747
    if offset is None:
 
748
        offset = 0
 
749
    tt = time.gmtime(t + offset)
 
750
    date_fmt = _default_format_by_weekday_num[tt[6]]
 
751
    date_str = time.strftime(date_fmt, tt)
 
752
    offset_str = _cache.get(offset, None)
 
753
    if offset_str is None:
 
754
        offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
 
755
        _cache[offset] = offset_str
 
756
    return date_str + offset_str
 
757
 
 
758
 
670
759
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
671
760
                      show_offset=True):
672
761
    """Return an unicode date string formatted according to the current locale.
683
772
               _format_date(t, offset, timezone, date_fmt, show_offset)
684
773
    date_str = time.strftime(date_fmt, tt)
685
774
    if not isinstance(date_str, unicode):
686
 
        date_str = date_str.decode(bzrlib.user_encoding, 'replace')
 
775
        date_str = date_str.decode(get_user_encoding(), 'replace')
687
776
    return date_str + offset_str
688
777
 
 
778
 
689
779
def _format_date(t, offset, timezone, date_fmt, show_offset):
690
780
    if timezone == 'utc':
691
781
        tt = time.gmtime(t)
710
800
 
711
801
def compact_date(when):
712
802
    return time.strftime('%Y%m%d%H%M%S', time.gmtime(when))
713
 
    
 
803
 
714
804
 
715
805
def format_delta(delta):
716
806
    """Get a nice looking string for a time delta.
792
882
ALNUM = '0123456789abcdefghijklmnopqrstuvwxyz'
793
883
def rand_chars(num):
794
884
    """Return a random string of num alphanumeric characters
795
 
    
796
 
    The result only contains lowercase chars because it may be used on 
 
885
 
 
886
    The result only contains lowercase chars because it may be used on
797
887
    case-insensitive filesystems.
798
888
    """
799
889
    s = ''
829
919
    return pathjoin(*p)
830
920
 
831
921
 
 
922
def parent_directories(filename):
 
923
    """Return the list of parent directories, deepest first.
 
924
    
 
925
    For example, parent_directories("a/b/c") -> ["a/b", "a"].
 
926
    """
 
927
    parents = []
 
928
    parts = splitpath(dirname(filename))
 
929
    while parts:
 
930
        parents.append(joinpath(parts))
 
931
        parts.pop()
 
932
    return parents
 
933
 
 
934
 
 
935
_extension_load_failures = []
 
936
 
 
937
 
 
938
def failed_to_load_extension(exception):
 
939
    """Handle failing to load a binary extension.
 
940
 
 
941
    This should be called from the ImportError block guarding the attempt to
 
942
    import the native extension.  If this function returns, the pure-Python
 
943
    implementation should be loaded instead::
 
944
 
 
945
    >>> try:
 
946
    >>>     import bzrlib._fictional_extension_pyx
 
947
    >>> except ImportError, e:
 
948
    >>>     bzrlib.osutils.failed_to_load_extension(e)
 
949
    >>>     import bzrlib._fictional_extension_py
 
950
    """
 
951
    # NB: This docstring is just an example, not a doctest, because doctest
 
952
    # currently can't cope with the use of lazy imports in this namespace --
 
953
    # mbp 20090729
 
954
    
 
955
    # This currently doesn't report the failure at the time it occurs, because
 
956
    # they tend to happen very early in startup when we can't check config
 
957
    # files etc, and also we want to report all failures but not spam the user
 
958
    # with 10 warnings.
 
959
    from bzrlib import trace
 
960
    exception_str = str(exception)
 
961
    if exception_str not in _extension_load_failures:
 
962
        trace.mutter("failed to load compiled extension: %s" % exception_str)
 
963
        _extension_load_failures.append(exception_str)
 
964
 
 
965
 
 
966
def report_extension_load_failures():
 
967
    if not _extension_load_failures:
 
968
        return
 
969
    from bzrlib.config import GlobalConfig
 
970
    if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
 
971
        return
 
972
    # the warnings framework should by default show this only once
 
973
    from bzrlib.trace import warning
 
974
    warning(
 
975
        "bzr: warning: some compiled extensions could not be loaded; "
 
976
        "see <https://answers.launchpad.net/bzr/+faq/703>")
 
977
    # we no longer show the specific missing extensions here, because it makes
 
978
    # the message too long and scary - see
 
979
    # https://bugs.launchpad.net/bzr/+bug/430529
 
980
 
 
981
 
832
982
try:
833
983
    from bzrlib._chunks_to_lines_pyx import chunks_to_lines
834
 
except ImportError:
 
984
except ImportError, e:
 
985
    failed_to_load_extension(e)
835
986
    from bzrlib._chunks_to_lines_py import chunks_to_lines
836
987
 
837
988
 
875
1026
        shutil.copyfile(src, dest)
876
1027
 
877
1028
 
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
1029
def delete_any(path):
884
 
    """Delete a file or directory."""
 
1030
    """Delete a file, symlink or directory.  
 
1031
    
 
1032
    Will delete even if readonly.
 
1033
    """
 
1034
    try:
 
1035
       _delete_file_or_dir(path)
 
1036
    except (OSError, IOError), e:
 
1037
        if e.errno in (errno.EPERM, errno.EACCES):
 
1038
            # make writable and try again
 
1039
            try:
 
1040
                make_writable(path)
 
1041
            except (OSError, IOError):
 
1042
                pass
 
1043
            _delete_file_or_dir(path)
 
1044
        else:
 
1045
            raise
 
1046
 
 
1047
 
 
1048
def _delete_file_or_dir(path):
 
1049
    # Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
 
1050
    # Forgiveness than Permission (EAFP) because:
 
1051
    # - root can damage a solaris file system by using unlink,
 
1052
    # - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
 
1053
    #   EACCES, OSX: EPERM) when invoked on a directory.
885
1054
    if isdir(path): # Takes care of symlinks
886
1055
        os.rmdir(path)
887
1056
    else:
907
1076
            and sys.platform not in ('cygwin', 'win32'))
908
1077
 
909
1078
 
 
1079
def readlink(abspath):
 
1080
    """Return a string representing the path to which the symbolic link points.
 
1081
 
 
1082
    :param abspath: The link absolute unicode path.
 
1083
 
 
1084
    This his guaranteed to return the symbolic link in unicode in all python
 
1085
    versions.
 
1086
    """
 
1087
    link = abspath.encode(_fs_enc)
 
1088
    target = os.readlink(link)
 
1089
    target = target.decode(_fs_enc)
 
1090
    return target
 
1091
 
 
1092
 
910
1093
def contains_whitespace(s):
911
1094
    """True if there are any whitespace characters in s."""
912
1095
    # string.whitespace can include '\xa0' in certain locales, because it is
956
1139
 
957
1140
    s = []
958
1141
    head = rp
959
 
    while len(head) >= len(base):
 
1142
    while True:
 
1143
        if len(head) <= len(base) and head != base:
 
1144
            raise errors.PathNotChild(rp, base)
960
1145
        if head == base:
961
1146
            break
962
 
        head, tail = os.path.split(head)
 
1147
        head, tail = split(head)
963
1148
        if tail:
964
 
            s.insert(0, tail)
965
 
    else:
966
 
        raise errors.PathNotChild(rp, base)
 
1149
            s.append(tail)
967
1150
 
968
1151
    if s:
969
 
        return pathjoin(*s)
 
1152
        return pathjoin(*reversed(s))
970
1153
    else:
971
1154
        return ''
972
1155
 
999
1182
    bit_iter = iter(rel.split('/'))
1000
1183
    for bit in bit_iter:
1001
1184
        lbit = bit.lower()
1002
 
        for look in _listdir(current):
 
1185
        try:
 
1186
            next_entries = _listdir(current)
 
1187
        except OSError: # enoent, eperm, etc
 
1188
            # We can't find this in the filesystem, so just append the
 
1189
            # remaining bits.
 
1190
            current = pathjoin(current, bit, *list(bit_iter))
 
1191
            break
 
1192
        for look in next_entries:
1003
1193
            if lbit == look.lower():
1004
1194
                current = pathjoin(current, look)
1005
1195
                break
1009
1199
            # the target of a move, for example).
1010
1200
            current = pathjoin(current, bit, *list(bit_iter))
1011
1201
            break
1012
 
    return current[len(abs_base)+1:]
 
1202
    return current[len(abs_base):].lstrip('/')
1013
1203
 
1014
1204
# 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":
 
1205
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
 
1206
# filesystems), for example, so could probably benefit from the same basic
 
1207
# support there.  For now though, only Windows and OSX get that support, and
 
1208
# they get it for *all* file-systems!
 
1209
if sys.platform in ('win32', 'darwin'):
1019
1210
    canonical_relpath = _cicp_canonical_relpath
1020
1211
else:
1021
1212
    canonical_relpath = relpath
1033
1224
    """Coerce unicode_or_utf8_string into unicode.
1034
1225
 
1035
1226
    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.
 
1227
    Otherwise it is decoded from utf-8. If decoding fails, the exception is
 
1228
    wrapped in a BzrBadParameterNotUnicode exception.
1039
1229
    """
1040
1230
    if isinstance(unicode_or_utf8_string, unicode):
1041
1231
        return unicode_or_utf8_string
1128
1318
 
1129
1319
    On platforms where the system normalizes filenames (Mac OSX),
1130
1320
    you can access a file by any path which will normalize correctly.
1131
 
    On platforms where the system does not normalize filenames 
 
1321
    On platforms where the system does not normalize filenames
1132
1322
    (Windows, Linux), you have to access a file by its exact path.
1133
1323
 
1134
 
    Internally, bzr only supports NFC normalization, since that is 
 
1324
    Internally, bzr only supports NFC normalization, since that is
1135
1325
    the standard for XML documents.
1136
1326
 
1137
1327
    So return the normalized path, and a flag indicating if the file
1154
1344
    normalized_filename = _inaccessible_normalized_filename
1155
1345
 
1156
1346
 
 
1347
default_terminal_width = 80
 
1348
"""The default terminal width for ttys.
 
1349
 
 
1350
This is defined so that higher levels can share a common fallback value when
 
1351
terminal_width() returns None.
 
1352
"""
 
1353
 
 
1354
 
1157
1355
def terminal_width():
1158
 
    """Return estimated terminal width."""
1159
 
    if sys.platform == 'win32':
1160
 
        return win32utils.get_console_size()[0]
1161
 
    width = 0
 
1356
    """Return terminal width.
 
1357
 
 
1358
    None is returned if the width can't established precisely.
 
1359
 
 
1360
    The rules are:
 
1361
    - if BZR_COLUMNS is set, returns its value
 
1362
    - if there is no controlling terminal, returns None
 
1363
    - if COLUMNS is set, returns its value,
 
1364
 
 
1365
    From there, we need to query the OS to get the size of the controlling
 
1366
    terminal.
 
1367
 
 
1368
    Unices:
 
1369
    - get termios.TIOCGWINSZ
 
1370
    - if an error occurs or a negative value is obtained, returns None
 
1371
 
 
1372
    Windows:
 
1373
    
 
1374
    - win32utils.get_console_size() decides,
 
1375
    - returns None on error (provided default value)
 
1376
    """
 
1377
 
 
1378
    # If BZR_COLUMNS is set, take it, user is always right
 
1379
    try:
 
1380
        return int(os.environ['BZR_COLUMNS'])
 
1381
    except (KeyError, ValueError):
 
1382
        pass
 
1383
 
 
1384
    isatty = getattr(sys.stdout, 'isatty', None)
 
1385
    if  isatty is None or not isatty():
 
1386
        # Don't guess, setting BZR_COLUMNS is the recommended way to override.
 
1387
        return None
 
1388
 
 
1389
    # If COLUMNS is set, take it, the terminal knows better (even inside a
 
1390
    # given terminal, the application can decide to set COLUMNS to a lower
 
1391
    # value (splitted screen) or a bigger value (scroll bars))
 
1392
    try:
 
1393
        return int(os.environ['COLUMNS'])
 
1394
    except (KeyError, ValueError):
 
1395
        pass
 
1396
 
 
1397
    width, height = _terminal_size(None, None)
 
1398
    if width <= 0:
 
1399
        # Consider invalid values as meaning no width
 
1400
        return None
 
1401
 
 
1402
    return width
 
1403
 
 
1404
 
 
1405
def _win32_terminal_size(width, height):
 
1406
    width, height = win32utils.get_console_size(defaultx=width, defaulty=height)
 
1407
    return width, height
 
1408
 
 
1409
 
 
1410
def _ioctl_terminal_size(width, height):
1162
1411
    try:
1163
1412
        import struct, fcntl, termios
1164
1413
        s = struct.pack('HHHH', 0, 0, 0, 0)
1165
1414
        x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
1166
 
        width = struct.unpack('HHHH', x)[1]
1167
 
    except IOError:
 
1415
        height, width = struct.unpack('HHHH', x)[0:2]
 
1416
    except (IOError, AttributeError):
1168
1417
        pass
1169
 
    if width <= 0:
1170
 
        try:
1171
 
            width = int(os.environ['COLUMNS'])
1172
 
        except:
1173
 
            pass
1174
 
    if width <= 0:
1175
 
        width = 80
1176
 
 
1177
 
    return width
 
1418
    return width, height
 
1419
 
 
1420
_terminal_size = None
 
1421
"""Returns the terminal size as (width, height).
 
1422
 
 
1423
:param width: Default value for width.
 
1424
:param height: Default value for height.
 
1425
 
 
1426
This is defined specifically for each OS and query the size of the controlling
 
1427
terminal. If any error occurs, the provided default values should be returned.
 
1428
"""
 
1429
if sys.platform == 'win32':
 
1430
    _terminal_size = _win32_terminal_size
 
1431
else:
 
1432
    _terminal_size = _ioctl_terminal_size
 
1433
 
 
1434
 
 
1435
def _terminal_size_changed(signum, frame):
 
1436
    """Set COLUMNS upon receiving a SIGnal for WINdow size CHange."""
 
1437
    width, height = _terminal_size(None, None)
 
1438
    if width is not None:
 
1439
        os.environ['COLUMNS'] = str(width)
 
1440
 
 
1441
if sys.platform == 'win32':
 
1442
    # Martin (gz) mentioned WINDOW_BUFFER_SIZE_RECORD from ReadConsoleInput but
 
1443
    # I've no idea how to plug that in the current design -- vila 20091216
 
1444
    pass
 
1445
else:
 
1446
    signal.signal(signal.SIGWINCH, _terminal_size_changed)
1178
1447
 
1179
1448
 
1180
1449
def supports_executable():
1217
1486
 
1218
1487
 
1219
1488
def check_legal_path(path):
1220
 
    """Check whether the supplied path is legal.  
 
1489
    """Check whether the supplied path is legal.
1221
1490
    This is only required on Windows, so we don't test on other platforms
1222
1491
    right now.
1223
1492
    """
1257
1526
 
1258
1527
def walkdirs(top, prefix=""):
1259
1528
    """Yield data about all the directories in a tree.
1260
 
    
 
1529
 
1261
1530
    This yields all the data about the contents of a directory at a time.
1262
1531
    After each directory has been yielded, if the caller has mutated the list
1263
1532
    to exclude some directories, they are then not descended into.
1264
 
    
 
1533
 
1265
1534
    The data yielded is of the form:
1266
1535
    ((directory-relpath, directory-path-from-top),
1267
1536
    [(relpath, basename, kind, lstat, path-from-top), ...]),
1268
1537
     - directory-relpath is the relative path of the directory being returned
1269
1538
       with respect to top. prefix is prepended to this.
1270
 
     - directory-path-from-root is the path including top for this directory. 
 
1539
     - directory-path-from-root is the path including top for this directory.
1271
1540
       It is suitable for use with os functions.
1272
1541
     - relpath is the relative path within the subtree being walked.
1273
1542
     - basename is the basename of the path
1275
1544
       present within the tree - but it may be recorded as versioned. See
1276
1545
       versioned_kind.
1277
1546
     - lstat is the stat data *if* the file was statted.
1278
 
     - planned, not implemented: 
 
1547
     - planned, not implemented:
1279
1548
       path_from_tree_root is the path from the root of the tree.
1280
1549
 
1281
 
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This 
 
1550
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1282
1551
        allows one to walk a subtree but get paths that are relative to a tree
1283
1552
        rooted higher up.
1284
1553
    :return: an iterator over the dirs.
1285
1554
    """
1286
1555
    #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 
 
1556
    # summary in this, and the path from the root, may not agree
1288
1557
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
1289
1558
    # potentially confusing output. We should make this more robust - but
1290
1559
    # not at a speed cost. RBC 20060731
1374
1643
            #       for win98 anyway.
1375
1644
            try:
1376
1645
                from bzrlib._walkdirs_win32 import Win32ReadDir
1377
 
            except ImportError:
1378
 
                _selected_dir_reader = UnicodeDirReader()
1379
 
            else:
1380
1646
                _selected_dir_reader = Win32ReadDir()
1381
 
        elif fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
 
1647
            except ImportError:
 
1648
                pass
 
1649
        elif fs_encoding in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
1382
1650
            # ANSI_X3.4-1968 is a form of ASCII
1383
 
            _selected_dir_reader = UnicodeDirReader()
1384
 
        else:
1385
1651
            try:
1386
1652
                from bzrlib._readdir_pyx import UTF8DirReader
1387
 
            except ImportError:
1388
 
                # No optimised code path
1389
 
                _selected_dir_reader = UnicodeDirReader()
1390
 
            else:
1391
1653
                _selected_dir_reader = UTF8DirReader()
 
1654
            except ImportError, e:
 
1655
                failed_to_load_extension(e)
 
1656
                pass
 
1657
 
 
1658
    if _selected_dir_reader is None:
 
1659
        # Fallback to the python version
 
1660
        _selected_dir_reader = UnicodeDirReader()
 
1661
 
1392
1662
    # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1393
1663
    # But we don't actually uses 1-3 in pending, so set them to None
1394
1664
    pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]]
1460
1730
def copy_tree(from_path, to_path, handlers={}):
1461
1731
    """Copy all of the entries in from_path into to_path.
1462
1732
 
1463
 
    :param from_path: The base directory to copy. 
 
1733
    :param from_path: The base directory to copy.
1464
1734
    :param to_path: The target directory. If it does not exist, it will
1465
1735
        be created.
1466
1736
    :param handlers: A dictionary of functions, which takes a source and
1623
1893
    return b
1624
1894
 
1625
1895
 
1626
 
def send_all(socket, bytes):
 
1896
def send_all(socket, bytes, report_activity=None):
1627
1897
    """Send all bytes on a socket.
1628
1898
 
1629
1899
    Regular socket.sendall() can give socket error 10053 on Windows.  This
1630
1900
    implementation sends no more than 64k at a time, which avoids this problem.
 
1901
 
 
1902
    :param report_activity: Call this as bytes are read, see
 
1903
        Transport._report_activity
1631
1904
    """
1632
1905
    chunk_size = 2**16
1633
1906
    for pos in xrange(0, len(bytes), chunk_size):
1634
 
        until_no_eintr(socket.sendall, bytes[pos:pos+chunk_size])
 
1907
        block = bytes[pos:pos+chunk_size]
 
1908
        if report_activity is not None:
 
1909
            report_activity(len(block), 'write')
 
1910
        until_no_eintr(socket.sendall, block)
1635
1911
 
1636
1912
 
1637
1913
def dereference_path(path):
1688
1964
        try:
1689
1965
            from bzrlib._readdir_pyx import UTF8DirReader
1690
1966
            file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1691
 
        except ImportError:
 
1967
        except ImportError, e:
 
1968
            # This is one time where we won't warn that an extension failed to
 
1969
            # load. The extension is never available on Windows anyway.
1692
1970
            from bzrlib._readdir_py import (
1693
1971
                _kind_from_mode as file_kind_from_stat_mode
1694
1972
                )
1716
1994
                continue
1717
1995
            raise
1718
1996
 
 
1997
def re_compile_checked(re_string, flags=0, where=""):
 
1998
    """Return a compiled re, or raise a sensible error.
 
1999
 
 
2000
    This should only be used when compiling user-supplied REs.
 
2001
 
 
2002
    :param re_string: Text form of regular expression.
 
2003
    :param flags: eg re.IGNORECASE
 
2004
    :param where: Message explaining to the user the context where
 
2005
        it occurred, eg 'log search filter'.
 
2006
    """
 
2007
    # from https://bugs.launchpad.net/bzr/+bug/251352
 
2008
    try:
 
2009
        re_obj = re.compile(re_string, flags)
 
2010
        re_obj.search("")
 
2011
        return re_obj
 
2012
    except re.error, e:
 
2013
        if where:
 
2014
            where = ' in ' + where
 
2015
        # despite the name 'error' is a type
 
2016
        raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
 
2017
            % (where, re_string, e))
 
2018
 
1719
2019
 
1720
2020
if sys.platform == "win32":
1721
2021
    import msvcrt
1733
2033
        finally:
1734
2034
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
1735
2035
        return ch
 
2036
 
 
2037
 
 
2038
if sys.platform == 'linux2':
 
2039
    def _local_concurrency():
 
2040
        concurrency = None
 
2041
        prefix = 'processor'
 
2042
        for line in file('/proc/cpuinfo', 'rb'):
 
2043
            if line.startswith(prefix):
 
2044
                concurrency = int(line[line.find(':')+1:]) + 1
 
2045
        return concurrency
 
2046
elif sys.platform == 'darwin':
 
2047
    def _local_concurrency():
 
2048
        return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
 
2049
                                stdout=subprocess.PIPE).communicate()[0]
 
2050
elif sys.platform[0:7] == 'freebsd':
 
2051
    def _local_concurrency():
 
2052
        return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
 
2053
                                stdout=subprocess.PIPE).communicate()[0]
 
2054
elif sys.platform == 'sunos5':
 
2055
    def _local_concurrency():
 
2056
        return subprocess.Popen(['psrinfo', '-p',],
 
2057
                                stdout=subprocess.PIPE).communicate()[0]
 
2058
elif sys.platform == "win32":
 
2059
    def _local_concurrency():
 
2060
        # This appears to return the number of cores.
 
2061
        return os.environ.get('NUMBER_OF_PROCESSORS')
 
2062
else:
 
2063
    def _local_concurrency():
 
2064
        # Who knows ?
 
2065
        return None
 
2066
 
 
2067
 
 
2068
_cached_local_concurrency = None
 
2069
 
 
2070
def local_concurrency(use_cache=True):
 
2071
    """Return how many processes can be run concurrently.
 
2072
 
 
2073
    Rely on platform specific implementations and default to 1 (one) if
 
2074
    anything goes wrong.
 
2075
    """
 
2076
    global _cached_local_concurrency
 
2077
 
 
2078
    if _cached_local_concurrency is not None and use_cache:
 
2079
        return _cached_local_concurrency
 
2080
 
 
2081
    concurrency = os.environ.get('BZR_CONCURRENCY', None)
 
2082
    if concurrency is None:
 
2083
        try:
 
2084
            concurrency = _local_concurrency()
 
2085
        except (OSError, IOError):
 
2086
            pass
 
2087
    try:
 
2088
        concurrency = int(concurrency)
 
2089
    except (TypeError, ValueError):
 
2090
        concurrency = 1
 
2091
    if use_cache:
 
2092
        _cached_concurrency = concurrency
 
2093
    return concurrency
 
2094
 
 
2095
 
 
2096
class UnicodeOrBytesToBytesWriter(codecs.StreamWriter):
 
2097
    """A stream writer that doesn't decode str arguments."""
 
2098
 
 
2099
    def __init__(self, encode, stream, errors='strict'):
 
2100
        codecs.StreamWriter.__init__(self, stream, errors)
 
2101
        self.encode = encode
 
2102
 
 
2103
    def write(self, object):
 
2104
        if type(object) is str:
 
2105
            self.stream.write(object)
 
2106
        else:
 
2107
            data, _ = self.encode(object, self.errors)
 
2108
            self.stream.write(data)