~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-03-16 14:01:20 UTC
  • mfrom: (3280.2.5 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080316140120-i3yq8yr1l66m11h7
Start 1.4 development

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2009 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
 
17
from cStringIO import StringIO
17
18
import os
18
19
import re
19
20
import stat
34
35
                    splitdrive as _nt_splitdrive,
35
36
                    )
36
37
import posixpath
 
38
import sha
37
39
import shutil
38
40
from shutil import (
39
41
    rmtree,
51
53
    )
52
54
""")
53
55
 
54
 
# sha and md5 modules are deprecated in python2.6 but hashlib is available as
55
 
# of 2.5
56
 
if sys.version_info < (2, 5):
57
 
    import md5 as _mod_md5
58
 
    md5 = _mod_md5.new
59
 
    import sha as _mod_sha
60
 
    sha = _mod_sha.new
61
 
else:
62
 
    from hashlib import (
63
 
        md5,
64
 
        sha1 as sha,
65
 
        )
66
 
 
67
 
 
68
56
import bzrlib
69
57
from bzrlib import symbol_versioning
 
58
from bzrlib.symbol_versioning import (
 
59
    deprecated_function,
 
60
    one_zero,
 
61
    )
 
62
from bzrlib.trace import mutter
70
63
 
71
64
 
72
65
# On win32, O_BINARY is used to indicate the file should
121
114
    global _QUOTE_RE
122
115
    if _QUOTE_RE is None:
123
116
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
124
 
 
 
117
        
125
118
    if _QUOTE_RE.search(f):
126
119
        return '"' + f + '"'
127
120
    else:
130
123
 
131
124
_directory_kind = 'directory'
132
125
 
 
126
_formats = {
 
127
    stat.S_IFDIR:_directory_kind,
 
128
    stat.S_IFCHR:'chardev',
 
129
    stat.S_IFBLK:'block',
 
130
    stat.S_IFREG:'file',
 
131
    stat.S_IFIFO:'fifo',
 
132
    stat.S_IFLNK:'symlink',
 
133
    stat.S_IFSOCK:'socket',
 
134
}
 
135
 
 
136
 
 
137
def file_kind_from_stat_mode(stat_mode, _formats=_formats, _unknown='unknown'):
 
138
    """Generate a file kind from a stat mode. This is used in walkdirs.
 
139
 
 
140
    Its performance is critical: Do not mutate without careful benchmarking.
 
141
    """
 
142
    try:
 
143
        return _formats[stat_mode & 0170000]
 
144
    except KeyError:
 
145
        return _unknown
 
146
 
 
147
 
 
148
def file_kind(f, _lstat=os.lstat, _mapper=file_kind_from_stat_mode):
 
149
    try:
 
150
        return _mapper(_lstat(f).st_mode)
 
151
    except OSError, e:
 
152
        if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
 
153
            raise errors.NoSuchFile(f)
 
154
        raise
 
155
 
 
156
 
133
157
def get_umask():
134
158
    """Return the current umask"""
135
159
    # Assume that people aren't messing with the umask while running
171
195
 
172
196
def fancy_rename(old, new, rename_func, unlink_func):
173
197
    """A fancy rename, when you don't have atomic rename.
174
 
 
 
198
    
175
199
    :param old: The old path, to rename from
176
200
    :param new: The new path, to rename to
177
201
    :param rename_func: The potentially non-atomic rename function
179
203
    """
180
204
 
181
205
    # sftp rename doesn't allow overwriting, so play tricks:
 
206
    import random
182
207
    base = os.path.basename(new)
183
208
    dirname = os.path.dirname(new)
184
209
    tmp_name = u'tmp.%s.%.9f.%d.%s' % (base, time.time(), os.getpid(), rand_chars(10))
291
316
        path = cwd + '\\' + path
292
317
    return _win32_fixdrive(_nt_normpath(path).replace('\\', '/'))
293
318
 
 
319
if win32utils.winver == 'Windows 98':
 
320
    _win32_abspath = _win98_abspath
 
321
 
294
322
 
295
323
def _win32_realpath(path):
296
324
    # Real _nt_realpath doesn't have a problem with a unicode cwd
317
345
    """We expect to be able to atomically replace 'new' with old.
318
346
 
319
347
    On win32, if new exists, it must be moved out of the way first,
320
 
    and then deleted.
 
348
    and then deleted. 
321
349
    """
322
350
    try:
323
351
        fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
324
352
    except OSError, e:
325
353
        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
 
354
            # If we try to rename a non-existant file onto cwd, we get 
 
355
            # EPERM or EACCES instead of ENOENT, this will raise ENOENT 
328
356
            # if the old path doesn't exist, sometimes we get EACCES
329
357
            # On Linux, we seem to get EBUSY, on Mac we get EINVAL
330
358
            os.lstat(old)
355
383
 
356
384
 
357
385
if sys.platform == 'win32':
358
 
    if win32utils.winver == 'Windows 98':
359
 
        abspath = _win98_abspath
360
 
    else:
361
 
        abspath = _win32_abspath
 
386
    abspath = _win32_abspath
362
387
    realpath = _win32_realpath
363
388
    pathjoin = _win32_pathjoin
364
389
    normpath = _win32_normpath
393
418
 
394
419
    This attempts to check both sys.stdout and sys.stdin to see
395
420
    what encoding they are in, and if that fails it falls back to
396
 
    osutils.get_user_encoding().
 
421
    bzrlib.user_encoding.
397
422
    The problem is that on Windows, locale.getpreferredencoding()
398
423
    is not the same encoding as that used by the console:
399
424
    http://mail.python.org/pipermail/python-list/2003-May/162357.html
401
426
    On my standard US Windows XP, the preferred encoding is
402
427
    cp1252, but the console is cp437
403
428
    """
404
 
    from bzrlib.trace import mutter
405
429
    output_encoding = getattr(sys.stdout, 'encoding', None)
406
430
    if not output_encoding:
407
431
        input_encoding = getattr(sys.stdin, 'encoding', None)
408
432
        if not input_encoding:
409
 
            output_encoding = get_user_encoding()
410
 
            mutter('encoding stdout as osutils.get_user_encoding() %r',
411
 
                   output_encoding)
 
433
            output_encoding = bzrlib.user_encoding
 
434
            mutter('encoding stdout as bzrlib.user_encoding %r', output_encoding)
412
435
        else:
413
436
            output_encoding = input_encoding
414
437
            mutter('encoding stdout as sys.stdin encoding %r', output_encoding)
416
439
        mutter('encoding stdout as sys.stdout encoding %r', output_encoding)
417
440
    if output_encoding == 'cp0':
418
441
        # invalid encoding (cp0 means 'no codepage' on Windows)
419
 
        output_encoding = get_user_encoding()
 
442
        output_encoding = bzrlib.user_encoding
420
443
        mutter('cp0 is invalid encoding.'
421
 
               ' encoding stdout as osutils.get_user_encoding() %r',
422
 
               output_encoding)
 
444
               ' encoding stdout as bzrlib.user_encoding %r', output_encoding)
423
445
    # check encoding
424
446
    try:
425
447
        codecs.lookup(output_encoding)
427
449
        sys.stderr.write('bzr: warning:'
428
450
                         ' unknown terminal encoding %s.\n'
429
451
                         '  Using encoding %s instead.\n'
430
 
                         % (output_encoding, get_user_encoding())
 
452
                         % (output_encoding, bzrlib.user_encoding)
431
453
                        )
432
 
        output_encoding = get_user_encoding()
 
454
        output_encoding = bzrlib.user_encoding
433
455
 
434
456
    return output_encoding
435
457
 
446
468
        return pathjoin(F(p), e)
447
469
 
448
470
 
 
471
@deprecated_function(one_zero)
 
472
def backup_file(fn):
 
473
    """Copy a file to a backup.
 
474
 
 
475
    Backups are named in GNU-style, with a ~ suffix.
 
476
 
 
477
    If the file is already a backup, it's not copied.
 
478
    """
 
479
    if fn[-1] == '~':
 
480
        return
 
481
    bfn = fn + '~'
 
482
 
 
483
    if has_symlinks() and os.path.islink(fn):
 
484
        target = os.readlink(fn)
 
485
        os.symlink(target, bfn)
 
486
        return
 
487
    inf = file(fn, 'rb')
 
488
    try:
 
489
        content = inf.read()
 
490
    finally:
 
491
        inf.close()
 
492
    
 
493
    outf = file(bfn, 'wb')
 
494
    try:
 
495
        outf.write(content)
 
496
    finally:
 
497
        outf.close()
 
498
 
 
499
 
449
500
def isdir(f):
450
501
    """True if f is an accessible directory."""
451
502
    try:
470
521
 
471
522
def is_inside(dir, fname):
472
523
    """True if fname is inside dir.
473
 
 
 
524
    
474
525
    The parameters should typically be passed to osutils.normpath first, so
475
526
    that . and .. and repeated slashes are eliminated, and the separators
476
527
    are canonical for the platform.
477
 
 
478
 
    The empty string as a dir name is taken as top-of-tree and matches
 
528
    
 
529
    The empty string as a dir name is taken as top-of-tree and matches 
479
530
    everything.
480
531
    """
481
 
    # XXX: Most callers of this can actually do something smarter by
 
532
    # XXX: Most callers of this can actually do something smarter by 
482
533
    # looking at the inventory
483
534
    if dir == fname:
484
535
        return True
485
 
 
 
536
    
486
537
    if dir == '':
487
538
        return True
488
539
 
508
559
    return False
509
560
 
510
561
 
511
 
def pumpfile(from_file, to_file, read_length=-1, buff_size=32768,
512
 
             report_activity=None, direction='read'):
 
562
def pumpfile(fromfile, tofile):
513
563
    """Copy contents of one file to another.
514
 
 
515
 
    The read_length can either be -1 to read to end-of-file (EOF) or
516
 
    it can specify the maximum number of bytes to read.
517
 
 
518
 
    The buff_size represents the maximum size for each read operation
519
 
    performed on from_file.
520
 
 
521
 
    :param report_activity: Call this as bytes are read, see
522
 
        Transport._report_activity
523
 
    :param direction: Will be passed to report_activity
524
 
 
 
564
    
525
565
    :return: The number of bytes copied.
526
566
    """
 
567
    BUFSIZE = 32768
527
568
    length = 0
528
 
    if read_length >= 0:
529
 
        # read specified number of bytes
530
 
 
531
 
        while read_length > 0:
532
 
            num_bytes_to_read = min(read_length, buff_size)
533
 
 
534
 
            block = from_file.read(num_bytes_to_read)
535
 
            if not block:
536
 
                # EOF reached
537
 
                break
538
 
            if report_activity is not None:
539
 
                report_activity(len(block), direction)
540
 
            to_file.write(block)
541
 
 
542
 
            actual_bytes_read = len(block)
543
 
            read_length -= actual_bytes_read
544
 
            length += actual_bytes_read
545
 
    else:
546
 
        # read to EOF
547
 
        while True:
548
 
            block = from_file.read(buff_size)
549
 
            if not block:
550
 
                # EOF reached
551
 
                break
552
 
            if report_activity is not None:
553
 
                report_activity(len(block), direction)
554
 
            to_file.write(block)
555
 
            length += len(block)
 
569
    while True:
 
570
        b = fromfile.read(BUFSIZE)
 
571
        if not b:
 
572
            break
 
573
        tofile.write(b)
 
574
        length += len(b)
556
575
    return length
557
576
 
558
577
 
559
 
def pump_string_file(bytes, file_handle, segment_size=None):
560
 
    """Write bytes to file_handle in many smaller writes.
561
 
 
562
 
    :param bytes: The string to write.
563
 
    :param file_handle: The file to write to.
564
 
    """
565
 
    # Write data in chunks rather than all at once, because very large
566
 
    # writes fail on some platforms (e.g. Windows with SMB  mounted
567
 
    # drives).
568
 
    if not segment_size:
569
 
        segment_size = 5242880 # 5MB
570
 
    segments = range(len(bytes) / segment_size + 1)
571
 
    write = file_handle.write
572
 
    for segment_index in segments:
573
 
        segment = buffer(bytes, segment_index * segment_size, segment_size)
574
 
        write(segment)
575
 
 
576
 
 
577
578
def file_iterator(input_file, readsize=32768):
578
579
    while True:
579
580
        b = input_file.read(readsize)
583
584
 
584
585
 
585
586
def sha_file(f):
586
 
    """Calculate the hexdigest of an open file.
587
 
 
588
 
    The file cursor should be already at the start.
589
 
    """
590
 
    s = sha()
 
587
    if getattr(f, 'tell', None) is not None:
 
588
        assert f.tell() == 0
 
589
    s = sha.new()
591
590
    BUFSIZE = 128<<10
592
591
    while True:
593
592
        b = f.read(BUFSIZE)
597
596
    return s.hexdigest()
598
597
 
599
598
 
600
 
def size_sha_file(f):
601
 
    """Calculate the size and hexdigest of an open file.
602
 
 
603
 
    The file cursor should be already at the start and
604
 
    the caller is responsible for closing the file afterwards.
605
 
    """
606
 
    size = 0
607
 
    s = sha()
608
 
    BUFSIZE = 128<<10
609
 
    while True:
610
 
        b = f.read(BUFSIZE)
611
 
        if not b:
612
 
            break
613
 
        size += len(b)
614
 
        s.update(b)
615
 
    return size, s.hexdigest()
616
 
 
617
 
 
618
599
def sha_file_by_name(fname):
619
600
    """Calculate the SHA1 of a file by reading the full text"""
620
 
    s = sha()
 
601
    s = sha.new()
621
602
    f = os.open(fname, os.O_RDONLY | O_BINARY)
622
603
    try:
623
604
        while True:
629
610
        os.close(f)
630
611
 
631
612
 
632
 
def sha_strings(strings, _factory=sha):
 
613
def sha_strings(strings, _factory=sha.new):
633
614
    """Return the sha-1 of concatenation of strings"""
634
615
    s = _factory()
635
616
    map(s.update, strings)
636
617
    return s.hexdigest()
637
618
 
638
619
 
639
 
def sha_string(f, _factory=sha):
 
620
def sha_string(f, _factory=sha.new):
640
621
    return _factory(f).hexdigest()
641
622
 
642
623
 
643
624
def fingerprint_file(f):
644
625
    b = f.read()
645
626
    return {'size': len(b),
646
 
            'sha1': sha(b).hexdigest()}
 
627
            'sha1': sha.new(b).hexdigest()}
647
628
 
648
629
 
649
630
def compare_files(a, b):
665
646
    offset = datetime.fromtimestamp(t) - datetime.utcfromtimestamp(t)
666
647
    return offset.days * 86400 + offset.seconds
667
648
 
668
 
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
669
 
 
 
649
    
670
650
def format_date(t, offset=0, timezone='original', date_fmt=None,
671
651
                show_offset=True):
672
652
    """Return a formatted date string.
676
656
    :param timezone: How to display the time: 'utc', 'original' for the
677
657
         timezone specified by offset, or 'local' for the process's current
678
658
         timezone.
679
 
    :param date_fmt: strftime format.
680
 
    :param show_offset: Whether to append the timezone.
681
 
    """
682
 
    (date_fmt, tt, offset_str) = \
683
 
               _format_date(t, offset, timezone, date_fmt, show_offset)
684
 
    date_fmt = date_fmt.replace('%a', weekdays[tt[6]])
685
 
    date_str = time.strftime(date_fmt, tt)
686
 
    return date_str + offset_str
687
 
 
688
 
def format_local_date(t, offset=0, timezone='original', date_fmt=None,
689
 
                      show_offset=True):
690
 
    """Return an unicode date string formatted according to the current locale.
691
 
 
692
 
    :param t: Seconds since the epoch.
693
 
    :param offset: Timezone offset in seconds east of utc.
694
 
    :param timezone: How to display the time: 'utc', 'original' for the
695
 
         timezone specified by offset, or 'local' for the process's current
696
 
         timezone.
697
 
    :param date_fmt: strftime format.
698
 
    :param show_offset: Whether to append the timezone.
699
 
    """
700
 
    (date_fmt, tt, offset_str) = \
701
 
               _format_date(t, offset, timezone, date_fmt, show_offset)
702
 
    date_str = time.strftime(date_fmt, tt)
703
 
    if not isinstance(date_str, unicode):
704
 
        date_str = date_str.decode(bzrlib.user_encoding, 'replace')
705
 
    return date_str + offset_str
706
 
 
707
 
def _format_date(t, offset, timezone, date_fmt, show_offset):
 
659
    :param show_offset: Whether to append the timezone.
 
660
    :param date_fmt: strftime format.
 
661
    """
708
662
    if timezone == 'utc':
709
663
        tt = time.gmtime(t)
710
664
        offset = 0
723
677
        offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
724
678
    else:
725
679
        offset_str = ''
726
 
    return (date_fmt, tt, offset_str)
 
680
    return (time.strftime(date_fmt, tt) +  offset_str)
727
681
 
728
682
 
729
683
def compact_date(when):
730
684
    return time.strftime('%Y%m%d%H%M%S', time.gmtime(when))
731
 
 
 
685
    
732
686
 
733
687
def format_delta(delta):
734
688
    """Get a nice looking string for a time delta.
810
764
ALNUM = '0123456789abcdefghijklmnopqrstuvwxyz'
811
765
def rand_chars(num):
812
766
    """Return a random string of num alphanumeric characters
813
 
 
814
 
    The result only contains lowercase chars because it may be used on
 
767
    
 
768
    The result only contains lowercase chars because it may be used on 
815
769
    case-insensitive filesystems.
816
770
    """
817
771
    s = ''
825
779
 
826
780
def splitpath(p):
827
781
    """Turn string into list of parts."""
 
782
    assert isinstance(p, basestring)
 
783
 
828
784
    # split on either delimiter because people might use either on
829
785
    # Windows
830
786
    ps = re.split(r'[\\/]', p)
839
795
            rps.append(f)
840
796
    return rps
841
797
 
842
 
 
843
798
def joinpath(p):
 
799
    assert isinstance(p, (list, tuple))
844
800
    for f in p:
845
801
        if (f == '..') or (f is None) or (f == ''):
846
802
            raise errors.BzrError("sorry, %r not allowed in path" % f)
847
803
    return pathjoin(*p)
848
804
 
849
805
 
850
 
try:
851
 
    from bzrlib._chunks_to_lines_pyx import chunks_to_lines
852
 
except ImportError:
853
 
    from bzrlib._chunks_to_lines_py import chunks_to_lines
854
 
 
855
 
 
856
806
def split_lines(s):
857
807
    """Split s into lines, but without removing the newline characters."""
858
 
    # Trivially convert a fulltext into a 'chunked' representation, and let
859
 
    # chunks_to_lines do the heavy lifting.
860
 
    if isinstance(s, str):
861
 
        # chunks_to_lines only supports 8-bit strings
862
 
        return chunks_to_lines([s])
863
 
    else:
864
 
        return _split_lines(s)
865
 
 
866
 
 
867
 
def _split_lines(s):
868
 
    """Split s into lines, but without removing the newline characters.
869
 
 
870
 
    This supports Unicode or plain string objects.
871
 
    """
872
808
    lines = s.split('\n')
873
809
    result = [line + '\n' for line in lines[:-1]]
874
810
    if lines[-1]:
920
856
        return False
921
857
 
922
858
 
923
 
def host_os_dereferences_symlinks():
924
 
    return (has_symlinks()
925
 
            and sys.platform not in ('cygwin', 'win32'))
926
 
 
927
 
 
928
859
def contains_whitespace(s):
929
860
    """True if there are any whitespace characters in s."""
930
861
    # string.whitespace can include '\xa0' in certain locales, because it is
965
896
    avoids that problem.
966
897
    """
967
898
 
968
 
    if len(base) < MIN_ABS_PATHLENGTH:
969
 
        # must have space for e.g. a drive letter
970
 
        raise ValueError('%r is too short to calculate a relative path'
971
 
            % (base,))
 
899
    assert len(base) >= MIN_ABS_PATHLENGTH, ('Length of base must be equal or'
 
900
        ' exceed the platform minimum length (which is %d)' % 
 
901
        MIN_ABS_PATHLENGTH)
972
902
 
973
903
    rp = abspath(path)
974
904
 
989
919
        return ''
990
920
 
991
921
 
992
 
def _cicp_canonical_relpath(base, path):
993
 
    """Return the canonical path relative to base.
994
 
 
995
 
    Like relpath, but on case-insensitive-case-preserving file-systems, this
996
 
    will return the relpath as stored on the file-system rather than in the
997
 
    case specified in the input string, for all existing portions of the path.
998
 
 
999
 
    This will cause O(N) behaviour if called for every path in a tree; if you
1000
 
    have a number of paths to convert, you should use canonical_relpaths().
1001
 
    """
1002
 
    # TODO: it should be possible to optimize this for Windows by using the
1003
 
    # win32 API FindFiles function to look for the specified name - but using
1004
 
    # os.listdir() still gives us the correct, platform agnostic semantics in
1005
 
    # the short term.
1006
 
 
1007
 
    rel = relpath(base, path)
1008
 
    # '.' will have been turned into ''
1009
 
    if not rel:
1010
 
        return rel
1011
 
 
1012
 
    abs_base = abspath(base)
1013
 
    current = abs_base
1014
 
    _listdir = os.listdir
1015
 
 
1016
 
    # use an explicit iterator so we can easily consume the rest on early exit.
1017
 
    bit_iter = iter(rel.split('/'))
1018
 
    for bit in bit_iter:
1019
 
        lbit = bit.lower()
1020
 
        for look in _listdir(current):
1021
 
            if lbit == look.lower():
1022
 
                current = pathjoin(current, look)
1023
 
                break
1024
 
        else:
1025
 
            # got to the end, nothing matched, so we just return the
1026
 
            # non-existing bits as they were specified (the filename may be
1027
 
            # the target of a move, for example).
1028
 
            current = pathjoin(current, bit, *list(bit_iter))
1029
 
            break
1030
 
    return current[len(abs_base)+1:]
1031
 
 
1032
 
# XXX - TODO - we need better detection/integration of case-insensitive
1033
 
# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
1034
 
# filesystems), for example, so could probably benefit from the same basic
1035
 
# support there.  For now though, only Windows and OSX get that support, and
1036
 
# they get it for *all* file-systems!
1037
 
if sys.platform in ('win32', 'darwin'):
1038
 
    canonical_relpath = _cicp_canonical_relpath
1039
 
else:
1040
 
    canonical_relpath = relpath
1041
 
 
1042
 
def canonical_relpaths(base, paths):
1043
 
    """Create an iterable to canonicalize a sequence of relative paths.
1044
 
 
1045
 
    The intent is for this implementation to use a cache, vastly speeding
1046
 
    up multiple transformations in the same directory.
1047
 
    """
1048
 
    # but for now, we haven't optimized...
1049
 
    return [canonical_relpath(base, p) for p in paths]
1050
 
 
1051
922
def safe_unicode(unicode_or_utf8_string):
1052
923
    """Coerce unicode_or_utf8_string into unicode.
1053
924
 
1054
925
    If it is unicode, it is returned.
1055
 
    Otherwise it is decoded from utf-8. If decoding fails, the exception is
1056
 
    wrapped in a BzrBadParameterNotUnicode exception.
 
926
    Otherwise it is decoded from utf-8. If a decoding error
 
927
    occurs, it is wrapped as a If the decoding fails, the exception is wrapped 
 
928
    as a BzrBadParameter exception.
1057
929
    """
1058
930
    if isinstance(unicode_or_utf8_string, unicode):
1059
931
        return unicode_or_utf8_string
1146
1018
 
1147
1019
    On platforms where the system normalizes filenames (Mac OSX),
1148
1020
    you can access a file by any path which will normalize correctly.
1149
 
    On platforms where the system does not normalize filenames
 
1021
    On platforms where the system does not normalize filenames 
1150
1022
    (Windows, Linux), you have to access a file by its exact path.
1151
1023
 
1152
 
    Internally, bzr only supports NFC normalization, since that is
 
1024
    Internally, bzr only supports NFC normalization, since that is 
1153
1025
    the standard for XML documents.
1154
1026
 
1155
1027
    So return the normalized path, and a flag indicating if the file
1226
1098
            del os.environ[env_variable]
1227
1099
    else:
1228
1100
        if isinstance(value, unicode):
1229
 
            value = value.encode(get_user_encoding())
 
1101
            value = value.encode(bzrlib.user_encoding)
1230
1102
        os.environ[env_variable] = value
1231
1103
    return orig_val
1232
1104
 
1235
1107
 
1236
1108
 
1237
1109
def check_legal_path(path):
1238
 
    """Check whether the supplied path is legal.
 
1110
    """Check whether the supplied path is legal.  
1239
1111
    This is only required on Windows, so we don't test on other platforms
1240
1112
    right now.
1241
1113
    """
1245
1117
        raise errors.IllegalPath(path)
1246
1118
 
1247
1119
 
1248
 
_WIN32_ERROR_DIRECTORY = 267 # Similar to errno.ENOTDIR
1249
 
 
1250
 
def _is_error_enotdir(e):
1251
 
    """Check if this exception represents ENOTDIR.
1252
 
 
1253
 
    Unfortunately, python is very inconsistent about the exception
1254
 
    here. The cases are:
1255
 
      1) Linux, Mac OSX all versions seem to set errno == ENOTDIR
1256
 
      2) Windows, Python2.4, uses errno == ERROR_DIRECTORY (267)
1257
 
         which is the windows error code.
1258
 
      3) Windows, Python2.5 uses errno == EINVAL and
1259
 
         winerror == ERROR_DIRECTORY
1260
 
 
1261
 
    :param e: An Exception object (expected to be OSError with an errno
1262
 
        attribute, but we should be able to cope with anything)
1263
 
    :return: True if this represents an ENOTDIR error. False otherwise.
1264
 
    """
1265
 
    en = getattr(e, 'errno', None)
1266
 
    if (en == errno.ENOTDIR
1267
 
        or (sys.platform == 'win32'
1268
 
            and (en == _WIN32_ERROR_DIRECTORY
1269
 
                 or (en == errno.EINVAL
1270
 
                     and getattr(e, 'winerror', None) == _WIN32_ERROR_DIRECTORY)
1271
 
        ))):
1272
 
        return True
1273
 
    return False
1274
 
 
1275
 
 
1276
1120
def walkdirs(top, prefix=""):
1277
1121
    """Yield data about all the directories in a tree.
1278
 
 
 
1122
    
1279
1123
    This yields all the data about the contents of a directory at a time.
1280
1124
    After each directory has been yielded, if the caller has mutated the list
1281
1125
    to exclude some directories, they are then not descended into.
1282
 
 
 
1126
    
1283
1127
    The data yielded is of the form:
1284
1128
    ((directory-relpath, directory-path-from-top),
1285
1129
    [(relpath, basename, kind, lstat, path-from-top), ...]),
1286
1130
     - directory-relpath is the relative path of the directory being returned
1287
1131
       with respect to top. prefix is prepended to this.
1288
 
     - directory-path-from-root is the path including top for this directory.
 
1132
     - directory-path-from-root is the path including top for this directory. 
1289
1133
       It is suitable for use with os functions.
1290
1134
     - relpath is the relative path within the subtree being walked.
1291
1135
     - basename is the basename of the path
1293
1137
       present within the tree - but it may be recorded as versioned. See
1294
1138
       versioned_kind.
1295
1139
     - lstat is the stat data *if* the file was statted.
1296
 
     - planned, not implemented:
 
1140
     - planned, not implemented: 
1297
1141
       path_from_tree_root is the path from the root of the tree.
1298
1142
 
1299
 
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This
 
1143
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This 
1300
1144
        allows one to walk a subtree but get paths that are relative to a tree
1301
1145
        rooted higher up.
1302
1146
    :return: an iterator over the dirs.
1303
1147
    """
1304
1148
    #TODO there is a bit of a smell where the results of the directory-
1305
 
    # summary in this, and the path from the root, may not agree
 
1149
    # summary in this, and the path from the root, may not agree 
1306
1150
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
1307
1151
    # potentially confusing output. We should make this more robust - but
1308
1152
    # not at a speed cost. RBC 20060731
1309
1153
    _lstat = os.lstat
1310
1154
    _directory = _directory_kind
1311
1155
    _listdir = os.listdir
1312
 
    _kind_from_mode = file_kind_from_stat_mode
 
1156
    _kind_from_mode = _formats.get
1313
1157
    pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1314
1158
    while pending:
1315
1159
        # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1322
1166
 
1323
1167
        dirblock = []
1324
1168
        append = dirblock.append
1325
 
        try:
1326
 
            names = sorted(_listdir(top))
1327
 
        except OSError, e:
1328
 
            if not _is_error_enotdir(e):
1329
 
                raise
1330
 
        else:
1331
 
            for name in names:
1332
 
                abspath = top_slash + name
1333
 
                statvalue = _lstat(abspath)
1334
 
                kind = _kind_from_mode(statvalue.st_mode)
1335
 
                append((relprefix + name, name, kind, statvalue, abspath))
 
1169
        for name in sorted(_listdir(top)):
 
1170
            abspath = top_slash + name
 
1171
            statvalue = _lstat(abspath)
 
1172
            kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
 
1173
            append((relprefix + name, name, kind, statvalue, abspath))
1336
1174
        yield (relroot, top), dirblock
1337
1175
 
1338
1176
        # push the user specified dirs from dirblock
1339
1177
        pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1340
1178
 
1341
1179
 
1342
 
class DirReader(object):
1343
 
    """An interface for reading directories."""
1344
 
 
1345
 
    def top_prefix_to_starting_dir(self, top, prefix=""):
1346
 
        """Converts top and prefix to a starting dir entry
1347
 
 
1348
 
        :param top: A utf8 path
1349
 
        :param prefix: An optional utf8 path to prefix output relative paths
1350
 
            with.
1351
 
        :return: A tuple starting with prefix, and ending with the native
1352
 
            encoding of top.
1353
 
        """
1354
 
        raise NotImplementedError(self.top_prefix_to_starting_dir)
1355
 
 
1356
 
    def read_dir(self, prefix, top):
1357
 
        """Read a specific dir.
1358
 
 
1359
 
        :param prefix: A utf8 prefix to be preprended to the path basenames.
1360
 
        :param top: A natively encoded path to read.
1361
 
        :return: A list of the directories contents. Each item contains:
1362
 
            (utf8_relpath, utf8_name, kind, lstatvalue, native_abspath)
1363
 
        """
1364
 
        raise NotImplementedError(self.read_dir)
1365
 
 
1366
 
 
1367
 
_selected_dir_reader = None
1368
 
 
1369
 
 
1370
1180
def _walkdirs_utf8(top, prefix=""):
1371
1181
    """Yield data about all the directories in a tree.
1372
1182
 
1381
1191
        path-from-top might be unicode or utf8, but it is the correct path to
1382
1192
        pass to os functions to affect the file in question. (such as os.lstat)
1383
1193
    """
1384
 
    global _selected_dir_reader
1385
 
    if _selected_dir_reader is None:
1386
 
        fs_encoding = _fs_enc.upper()
1387
 
        if sys.platform == "win32" and win32utils.winver == 'Windows NT':
1388
 
            # Win98 doesn't have unicode apis like FindFirstFileW
1389
 
            # TODO: We possibly could support Win98 by falling back to the
1390
 
            #       original FindFirstFile, and using TCHAR instead of WCHAR,
1391
 
            #       but that gets a bit tricky, and requires custom compiling
1392
 
            #       for win98 anyway.
1393
 
            try:
1394
 
                from bzrlib._walkdirs_win32 import Win32ReadDir
1395
 
            except ImportError:
1396
 
                _selected_dir_reader = UnicodeDirReader()
1397
 
            else:
1398
 
                _selected_dir_reader = Win32ReadDir()
1399
 
        elif fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'):
1400
 
            # ANSI_X3.4-1968 is a form of ASCII
1401
 
            _selected_dir_reader = UnicodeDirReader()
1402
 
        else:
1403
 
            try:
1404
 
                from bzrlib._readdir_pyx import UTF8DirReader
1405
 
            except ImportError:
1406
 
                # No optimised code path
1407
 
                _selected_dir_reader = UnicodeDirReader()
1408
 
            else:
1409
 
                _selected_dir_reader = UTF8DirReader()
 
1194
    fs_encoding = _fs_enc.upper()
 
1195
    if (sys.platform == 'win32' or
 
1196
        fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
 
1197
        return _walkdirs_unicode_to_utf8(top, prefix=prefix)
 
1198
    else:
 
1199
        return _walkdirs_fs_utf8(top, prefix=prefix)
 
1200
 
 
1201
 
 
1202
def _walkdirs_fs_utf8(top, prefix=""):
 
1203
    """See _walkdirs_utf8.
 
1204
 
 
1205
    This sub-function is called when we know the filesystem is already in utf8
 
1206
    encoding. So we don't need to transcode filenames.
 
1207
    """
 
1208
    _lstat = os.lstat
 
1209
    _directory = _directory_kind
 
1210
    _listdir = os.listdir
 
1211
    _kind_from_mode = _formats.get
 
1212
 
1410
1213
    # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1411
1214
    # But we don't actually uses 1-3 in pending, so set them to None
1412
 
    pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]]
1413
 
    read_dir = _selected_dir_reader.read_dir
1414
 
    _directory = _directory_kind
 
1215
    pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
1415
1216
    while pending:
1416
 
        relroot, _, _, _, top = pending[-1].pop()
1417
 
        if not pending[-1]:
1418
 
            pending.pop()
1419
 
        dirblock = sorted(read_dir(relroot, top))
 
1217
        relroot, _, _, _, top = pending.pop()
 
1218
        if relroot:
 
1219
            relprefix = relroot + '/'
 
1220
        else:
 
1221
            relprefix = ''
 
1222
        top_slash = top + '/'
 
1223
 
 
1224
        dirblock = []
 
1225
        append = dirblock.append
 
1226
        for name in sorted(_listdir(top)):
 
1227
            abspath = top_slash + name
 
1228
            statvalue = _lstat(abspath)
 
1229
            kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
 
1230
            append((relprefix + name, name, kind, statvalue, abspath))
1420
1231
        yield (relroot, top), dirblock
 
1232
 
1421
1233
        # push the user specified dirs from dirblock
1422
 
        next = [d for d in reversed(dirblock) if d[2] == _directory]
1423
 
        if next:
1424
 
            pending.append(next)
1425
 
 
1426
 
 
1427
 
class UnicodeDirReader(DirReader):
1428
 
    """A dir reader for non-utf8 file systems, which transcodes."""
1429
 
 
1430
 
    __slots__ = ['_utf8_encode']
1431
 
 
1432
 
    def __init__(self):
1433
 
        self._utf8_encode = codecs.getencoder('utf8')
1434
 
 
1435
 
    def top_prefix_to_starting_dir(self, top, prefix=""):
1436
 
        """See DirReader.top_prefix_to_starting_dir."""
1437
 
        return (safe_utf8(prefix), None, None, None, safe_unicode(top))
1438
 
 
1439
 
    def read_dir(self, prefix, top):
1440
 
        """Read a single directory from a non-utf8 file system.
1441
 
 
1442
 
        top, and the abspath element in the output are unicode, all other paths
1443
 
        are utf8. Local disk IO is done via unicode calls to listdir etc.
1444
 
 
1445
 
        This is currently the fallback code path when the filesystem encoding is
1446
 
        not UTF-8. It may be better to implement an alternative so that we can
1447
 
        safely handle paths that are not properly decodable in the current
1448
 
        encoding.
1449
 
 
1450
 
        See DirReader.read_dir for details.
1451
 
        """
1452
 
        _utf8_encode = self._utf8_encode
1453
 
        _lstat = os.lstat
1454
 
        _listdir = os.listdir
1455
 
        _kind_from_mode = file_kind_from_stat_mode
1456
 
 
1457
 
        if prefix:
1458
 
            relprefix = prefix + '/'
 
1234
        pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
 
1235
 
 
1236
 
 
1237
def _walkdirs_unicode_to_utf8(top, prefix=""):
 
1238
    """See _walkdirs_utf8
 
1239
 
 
1240
    Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
 
1241
    Unicode paths.
 
1242
    This is currently the fallback code path when the filesystem encoding is
 
1243
    not UTF-8. It may be better to implement an alternative so that we can
 
1244
    safely handle paths that are not properly decodable in the current
 
1245
    encoding.
 
1246
    """
 
1247
    _utf8_encode = codecs.getencoder('utf8')
 
1248
    _lstat = os.lstat
 
1249
    _directory = _directory_kind
 
1250
    _listdir = os.listdir
 
1251
    _kind_from_mode = _formats.get
 
1252
 
 
1253
    pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
 
1254
    while pending:
 
1255
        relroot, _, _, _, top = pending.pop()
 
1256
        if relroot:
 
1257
            relprefix = relroot + '/'
1459
1258
        else:
1460
1259
            relprefix = ''
1461
1260
        top_slash = top + u'/'
1463
1262
        dirblock = []
1464
1263
        append = dirblock.append
1465
1264
        for name in sorted(_listdir(top)):
1466
 
            try:
1467
 
                name_utf8 = _utf8_encode(name)[0]
1468
 
            except UnicodeDecodeError:
1469
 
                raise errors.BadFilenameEncoding(
1470
 
                    _utf8_encode(relprefix)[0] + name, _fs_enc)
 
1265
            name_utf8 = _utf8_encode(name)[0]
1471
1266
            abspath = top_slash + name
1472
1267
            statvalue = _lstat(abspath)
1473
 
            kind = _kind_from_mode(statvalue.st_mode)
 
1268
            kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1474
1269
            append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1475
 
        return dirblock
 
1270
        yield (relroot, top), dirblock
 
1271
 
 
1272
        # push the user specified dirs from dirblock
 
1273
        pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1476
1274
 
1477
1275
 
1478
1276
def copy_tree(from_path, to_path, handlers={}):
1479
1277
    """Copy all of the entries in from_path into to_path.
1480
1278
 
1481
 
    :param from_path: The base directory to copy.
 
1279
    :param from_path: The base directory to copy. 
1482
1280
    :param to_path: The target directory. If it does not exist, it will
1483
1281
        be created.
1484
1282
    :param handlers: A dictionary of functions, which takes a source and
1553
1351
        return _cached_user_encoding
1554
1352
 
1555
1353
    if sys.platform == 'darwin':
1556
 
        # python locale.getpreferredencoding() always return
1557
 
        # 'mac-roman' on darwin. That's a lie.
 
1354
        # work around egregious python 2.4 bug
1558
1355
        sys.platform = 'posix'
1559
1356
        try:
1560
 
            if os.environ.get('LANG', None) is None:
1561
 
                # If LANG is not set, we end up with 'ascii', which is bad
1562
 
                # ('mac-roman' is more than ascii), so we set a default which
1563
 
                # will give us UTF-8 (which appears to work in all cases on
1564
 
                # OSX). Users are still free to override LANG of course, as
1565
 
                # long as it give us something meaningful. This work-around
1566
 
                # *may* not be needed with python 3k and/or OSX 10.5, but will
1567
 
                # work with them too -- vila 20080908
1568
 
                os.environ['LANG'] = 'en_US.UTF-8'
1569
1357
            import locale
1570
1358
        finally:
1571
1359
            sys.platform = 'darwin'
1586
1374
    # Windows returns 'cp0' to indicate there is no code page. So we'll just
1587
1375
    # treat that as ASCII, and not support printing unicode characters to the
1588
1376
    # console.
1589
 
    #
1590
 
    # For python scripts run under vim, we get '', so also treat that as ASCII
1591
 
    if user_encoding in (None, 'cp0', ''):
 
1377
    if user_encoding in (None, 'cp0'):
1592
1378
        user_encoding = 'ascii'
1593
1379
    else:
1594
1380
        # check encoding
1608
1394
    return user_encoding
1609
1395
 
1610
1396
 
1611
 
def get_host_name():
1612
 
    """Return the current unicode host name.
1613
 
 
1614
 
    This is meant to be used in place of socket.gethostname() because that
1615
 
    behaves inconsistently on different platforms.
1616
 
    """
1617
 
    if sys.platform == "win32":
1618
 
        import win32utils
1619
 
        return win32utils.get_host_name()
1620
 
    else:
1621
 
        import socket
1622
 
        return socket.gethostname().decode(get_user_encoding())
1623
 
 
1624
 
 
1625
1397
def recv_all(socket, bytes):
1626
1398
    """Receive an exact number of bytes.
1627
1399
 
1634
1406
    """
1635
1407
    b = ''
1636
1408
    while len(b) < bytes:
1637
 
        new = until_no_eintr(socket.recv, bytes - len(b))
 
1409
        new = socket.recv(bytes - len(b))
1638
1410
        if new == '':
1639
1411
            break # eof
1640
1412
        b += new
1641
1413
    return b
1642
1414
 
1643
1415
 
1644
 
def send_all(socket, bytes, report_activity=None):
 
1416
def send_all(socket, bytes):
1645
1417
    """Send all bytes on a socket.
1646
1418
 
1647
1419
    Regular socket.sendall() can give socket error 10053 on Windows.  This
1648
1420
    implementation sends no more than 64k at a time, which avoids this problem.
1649
 
 
1650
 
    :param report_activity: Call this as bytes are read, see
1651
 
        Transport._report_activity
1652
1421
    """
1653
1422
    chunk_size = 2**16
1654
1423
    for pos in xrange(0, len(bytes), chunk_size):
1655
 
        block = bytes[pos:pos+chunk_size]
1656
 
        if report_activity is not None:
1657
 
            report_activity(len(block), 'write')
1658
 
        until_no_eintr(socket.sendall, block)
 
1424
        socket.sendall(bytes[pos:pos+chunk_size])
1659
1425
 
1660
1426
 
1661
1427
def dereference_path(path):
1704
1470
        base = abspath(pathjoin(base, '..', '..'))
1705
1471
    filename = pathjoin(base, resource_relpath)
1706
1472
    return open(filename, 'rU').read()
1707
 
 
1708
 
 
1709
 
def file_kind_from_stat_mode_thunk(mode):
1710
 
    global file_kind_from_stat_mode
1711
 
    if file_kind_from_stat_mode is file_kind_from_stat_mode_thunk:
1712
 
        try:
1713
 
            from bzrlib._readdir_pyx import UTF8DirReader
1714
 
            file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1715
 
        except ImportError:
1716
 
            from bzrlib._readdir_py import (
1717
 
                _kind_from_mode as file_kind_from_stat_mode
1718
 
                )
1719
 
    return file_kind_from_stat_mode(mode)
1720
 
file_kind_from_stat_mode = file_kind_from_stat_mode_thunk
1721
 
 
1722
 
 
1723
 
def file_kind(f, _lstat=os.lstat):
1724
 
    try:
1725
 
        return file_kind_from_stat_mode(_lstat(f).st_mode)
1726
 
    except OSError, e:
1727
 
        if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
1728
 
            raise errors.NoSuchFile(f)
1729
 
        raise
1730
 
 
1731
 
 
1732
 
def until_no_eintr(f, *a, **kw):
1733
 
    """Run f(*a, **kw), retrying if an EINTR error occurs."""
1734
 
    # Borrowed from Twisted's twisted.python.util.untilConcludes function.
1735
 
    while True:
1736
 
        try:
1737
 
            return f(*a, **kw)
1738
 
        except (IOError, OSError), e:
1739
 
            if e.errno == errno.EINTR:
1740
 
                continue
1741
 
            raise
1742
 
 
1743
 
def re_compile_checked(re_string, flags=0, where=""):
1744
 
    """Return a compiled re, or raise a sensible error.
1745
 
    
1746
 
    This should only be used when compiling user-supplied REs.
1747
 
 
1748
 
    :param re_string: Text form of regular expression.
1749
 
    :param flags: eg re.IGNORECASE
1750
 
    :param where: Message explaining to the user the context where 
1751
 
        it occurred, eg 'log search filter'.
1752
 
    """
1753
 
    # from https://bugs.launchpad.net/bzr/+bug/251352
1754
 
    try:
1755
 
        re_obj = re.compile(re_string, flags)
1756
 
        re_obj.search("")
1757
 
        return re_obj
1758
 
    except re.error, e:
1759
 
        if where:
1760
 
            where = ' in ' + where
1761
 
        # despite the name 'error' is a type
1762
 
        raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
1763
 
            % (where, re_string, e))
1764
 
 
1765
 
 
1766
 
if sys.platform == "win32":
1767
 
    import msvcrt
1768
 
    def getchar():
1769
 
        return msvcrt.getch()
1770
 
else:
1771
 
    import tty
1772
 
    import termios
1773
 
    def getchar():
1774
 
        fd = sys.stdin.fileno()
1775
 
        settings = termios.tcgetattr(fd)
1776
 
        try:
1777
 
            tty.setraw(fd)
1778
 
            ch = sys.stdin.read(1)
1779
 
        finally:
1780
 
            termios.tcsetattr(fd, termios.TCSADRAIN, settings)
1781
 
        return ch