/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing 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
121
121
    global _QUOTE_RE
122
122
    if _QUOTE_RE is None:
123
123
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
124
 
        
 
124
 
125
125
    if _QUOTE_RE.search(f):
126
126
        return '"' + f + '"'
127
127
    else:
171
171
 
172
172
def fancy_rename(old, new, rename_func, unlink_func):
173
173
    """A fancy rename, when you don't have atomic rename.
174
 
    
 
174
 
175
175
    :param old: The old path, to rename from
176
176
    :param new: The new path, to rename to
177
177
    :param rename_func: The potentially non-atomic rename function
317
317
    """We expect to be able to atomically replace 'new' with old.
318
318
 
319
319
    On win32, if new exists, it must be moved out of the way first,
320
 
    and then deleted. 
 
320
    and then deleted.
321
321
    """
322
322
    try:
323
323
        fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
324
324
    except OSError, e:
325
325
        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 
 
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
328
328
            # if the old path doesn't exist, sometimes we get EACCES
329
329
            # On Linux, we seem to get EBUSY, on Mac we get EINVAL
330
330
            os.lstat(old)
470
470
 
471
471
def is_inside(dir, fname):
472
472
    """True if fname is inside dir.
473
 
    
 
473
 
474
474
    The parameters should typically be passed to osutils.normpath first, so
475
475
    that . and .. and repeated slashes are eliminated, and the separators
476
476
    are canonical for the platform.
477
 
    
478
 
    The empty string as a dir name is taken as top-of-tree and matches 
 
477
 
 
478
    The empty string as a dir name is taken as top-of-tree and matches
479
479
    everything.
480
480
    """
481
 
    # XXX: Most callers of this can actually do something smarter by 
 
481
    # XXX: Most callers of this can actually do something smarter by
482
482
    # looking at the inventory
483
483
    if dir == fname:
484
484
        return True
485
 
    
 
485
 
486
486
    if dir == '':
487
487
        return True
488
488
 
597
597
    return s.hexdigest()
598
598
 
599
599
 
 
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
 
600
618
def sha_file_by_name(fname):
601
619
    """Calculate the SHA1 of a file by reading the full text"""
602
620
    s = sha()
648
666
    return offset.days * 86400 + offset.seconds
649
667
 
650
668
weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
651
 
    
 
669
 
652
670
def format_date(t, offset=0, timezone='original', date_fmt=None,
653
671
                show_offset=True):
654
672
    """Return a formatted date string.
710
728
 
711
729
def compact_date(when):
712
730
    return time.strftime('%Y%m%d%H%M%S', time.gmtime(when))
713
 
    
 
731
 
714
732
 
715
733
def format_delta(delta):
716
734
    """Get a nice looking string for a time delta.
792
810
ALNUM = '0123456789abcdefghijklmnopqrstuvwxyz'
793
811
def rand_chars(num):
794
812
    """Return a random string of num alphanumeric characters
795
 
    
796
 
    The result only contains lowercase chars because it may be used on 
 
813
 
 
814
    The result only contains lowercase chars because it may be used on
797
815
    case-insensitive filesystems.
798
816
    """
799
817
    s = ''
1033
1051
    """Coerce unicode_or_utf8_string into unicode.
1034
1052
 
1035
1053
    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.
 
1054
    Otherwise it is decoded from utf-8. If decoding fails, the exception is
 
1055
    wrapped in a BzrBadParameterNotUnicode exception.
1039
1056
    """
1040
1057
    if isinstance(unicode_or_utf8_string, unicode):
1041
1058
        return unicode_or_utf8_string
1128
1145
 
1129
1146
    On platforms where the system normalizes filenames (Mac OSX),
1130
1147
    you can access a file by any path which will normalize correctly.
1131
 
    On platforms where the system does not normalize filenames 
 
1148
    On platforms where the system does not normalize filenames
1132
1149
    (Windows, Linux), you have to access a file by its exact path.
1133
1150
 
1134
 
    Internally, bzr only supports NFC normalization, since that is 
 
1151
    Internally, bzr only supports NFC normalization, since that is
1135
1152
    the standard for XML documents.
1136
1153
 
1137
1154
    So return the normalized path, and a flag indicating if the file
1217
1234
 
1218
1235
 
1219
1236
def check_legal_path(path):
1220
 
    """Check whether the supplied path is legal.  
 
1237
    """Check whether the supplied path is legal.
1221
1238
    This is only required on Windows, so we don't test on other platforms
1222
1239
    right now.
1223
1240
    """
1257
1274
 
1258
1275
def walkdirs(top, prefix=""):
1259
1276
    """Yield data about all the directories in a tree.
1260
 
    
 
1277
 
1261
1278
    This yields all the data about the contents of a directory at a time.
1262
1279
    After each directory has been yielded, if the caller has mutated the list
1263
1280
    to exclude some directories, they are then not descended into.
1264
 
    
 
1281
 
1265
1282
    The data yielded is of the form:
1266
1283
    ((directory-relpath, directory-path-from-top),
1267
1284
    [(relpath, basename, kind, lstat, path-from-top), ...]),
1268
1285
     - directory-relpath is the relative path of the directory being returned
1269
1286
       with respect to top. prefix is prepended to this.
1270
 
     - directory-path-from-root is the path including top for this directory. 
 
1287
     - directory-path-from-root is the path including top for this directory.
1271
1288
       It is suitable for use with os functions.
1272
1289
     - relpath is the relative path within the subtree being walked.
1273
1290
     - basename is the basename of the path
1275
1292
       present within the tree - but it may be recorded as versioned. See
1276
1293
       versioned_kind.
1277
1294
     - lstat is the stat data *if* the file was statted.
1278
 
     - planned, not implemented: 
 
1295
     - planned, not implemented:
1279
1296
       path_from_tree_root is the path from the root of the tree.
1280
1297
 
1281
 
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This 
 
1298
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This
1282
1299
        allows one to walk a subtree but get paths that are relative to a tree
1283
1300
        rooted higher up.
1284
1301
    :return: an iterator over the dirs.
1285
1302
    """
1286
1303
    #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 
 
1304
    # summary in this, and the path from the root, may not agree
1288
1305
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
1289
1306
    # potentially confusing output. We should make this more robust - but
1290
1307
    # not at a speed cost. RBC 20060731
1460
1477
def copy_tree(from_path, to_path, handlers={}):
1461
1478
    """Copy all of the entries in from_path into to_path.
1462
1479
 
1463
 
    :param from_path: The base directory to copy. 
 
1480
    :param from_path: The base directory to copy.
1464
1481
    :param to_path: The target directory. If it does not exist, it will
1465
1482
        be created.
1466
1483
    :param handlers: A dictionary of functions, which takes a source and
1623
1640
    return b
1624
1641
 
1625
1642
 
1626
 
def send_all(socket, bytes):
 
1643
def send_all(socket, bytes, report_activity=None):
1627
1644
    """Send all bytes on a socket.
1628
1645
 
1629
1646
    Regular socket.sendall() can give socket error 10053 on Windows.  This
1630
1647
    implementation sends no more than 64k at a time, which avoids this problem.
 
1648
 
 
1649
    :param report_activity: Call this as bytes are read, see
 
1650
        Transport._report_activity
1631
1651
    """
1632
1652
    chunk_size = 2**16
1633
1653
    for pos in xrange(0, len(bytes), chunk_size):
1634
 
        until_no_eintr(socket.sendall, bytes[pos:pos+chunk_size])
 
1654
        block = bytes[pos:pos+chunk_size]
 
1655
        if report_activity is not None:
 
1656
            report_activity(len(block), 'write')
 
1657
        until_no_eintr(socket.sendall, block)
1635
1658
 
1636
1659
 
1637
1660
def dereference_path(path):
1716
1739
                continue
1717
1740
            raise
1718
1741
 
 
1742
def re_compile_checked(re_string, flags=0, where=""):
 
1743
    """Return a compiled re, or raise a sensible error.
 
1744
    
 
1745
    This should only be used when compiling user-supplied REs.
 
1746
 
 
1747
    :param re_string: Text form of regular expression.
 
1748
    :param flags: eg re.IGNORECASE
 
1749
    :param where: Message explaining to the user the context where 
 
1750
        it occurred, eg 'log search filter'.
 
1751
    """
 
1752
    # from https://bugs.launchpad.net/bzr/+bug/251352
 
1753
    try:
 
1754
        re_obj = re.compile(re_string, flags)
 
1755
        re_obj.search("")
 
1756
        return re_obj
 
1757
    except re.error, e:
 
1758
        if where:
 
1759
            where = ' in ' + where
 
1760
        # despite the name 'error' is a type
 
1761
        raise errors.BzrCommandError('Invalid regular expression%s: %r: %s'
 
1762
            % (where, re_string, e))
 
1763
 
1719
1764
 
1720
1765
if sys.platform == "win32":
1721
1766
    import msvcrt