~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-31 16:12:57 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060731161257-91a231523255332c
new official bzr.ico

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
from bzrlib.trace import mutter
54
54
 
55
55
 
56
 
# On win32, O_BINARY is used to indicate the file should
57
 
# be opened in binary mode, rather than text mode.
58
 
# On other platforms, O_BINARY doesn't exist, because
59
 
# they always open in binary mode, so it is okay to
60
 
# OR with 0 on those platforms
61
 
O_BINARY = getattr(os, 'O_BINARY', 0)
62
 
 
63
 
 
64
56
def make_readonly(filename):
65
57
    """Make a filename read-only."""
66
58
    mod = os.stat(filename).st_mode
84
76
    Windows."""
85
77
    # TODO: I'm not really sure this is the best format either.x
86
78
    global _QUOTE_RE
87
 
    if _QUOTE_RE is None:
 
79
    if _QUOTE_RE == None:
88
80
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
89
81
        
90
82
    if _QUOTE_RE.search(f):
126
118
        raise
127
119
 
128
120
 
129
 
def get_umask():
130
 
    """Return the current umask"""
131
 
    # Assume that people aren't messing with the umask while running
132
 
    # XXX: This is not thread safe, but there is no way to get the
133
 
    #      umask without setting it
134
 
    umask = os.umask(0)
135
 
    os.umask(umask)
136
 
    return umask
137
 
 
138
 
 
139
121
def kind_marker(kind):
140
122
    if kind == 'file':
141
123
        return ''
150
132
if lexists is None:
151
133
    def lexists(f):
152
134
        try:
153
 
            if getattr(os, 'lstat') is not None:
 
135
            if hasattr(os, 'lstat'):
154
136
                os.lstat(f)
155
137
            else:
156
138
                os.stat(f)
190
172
        pass
191
173
    except IOError, e:
192
174
        # RBC 20060103 abstraction leakage: the paramiko SFTP clients rename
193
 
        # function raises an IOError with errno is None when a rename fails.
 
175
        # function raises an IOError with errno == None when a rename fails.
194
176
        # This then gets caught here.
195
177
        if e.errno not in (None, errno.ENOENT, errno.ENOTDIR):
196
178
            raise
197
179
    except Exception, e:
198
 
        if (getattr(e, 'errno', None) is None
 
180
        if (not hasattr(e, 'errno') 
199
181
            or e.errno not in (errno.ENOENT, errno.ENOTDIR)):
200
182
            raise
201
183
    else:
370
352
 
371
353
 
372
354
def normalizepath(f):
373
 
    if getattr(os.path, 'realpath', None) is not None:
 
355
    if hasattr(os.path, 'realpath'):
374
356
        F = realpath
375
357
    else:
376
358
        F = abspath
505
487
 
506
488
 
507
489
def sha_file(f):
508
 
    if getattr(f, 'tell', None) is not None:
 
490
    if hasattr(f, 'tell'):
509
491
        assert f.tell() == 0
510
492
    s = sha.new()
511
493
    BUFSIZE = 128<<10
555
537
def local_time_offset(t=None):
556
538
    """Return offset of local zone from GMT, either at present or at time t."""
557
539
    # python2.3 localtime() can't take None
558
 
    if t is None:
 
540
    if t == None:
559
541
        t = time.time()
560
542
        
561
543
    if time.localtime(t).tm_isdst and time.daylight:
574
556
        tt = time.gmtime(t)
575
557
        offset = 0
576
558
    elif timezone == 'original':
577
 
        if offset is None:
 
559
        if offset == None:
578
560
            offset = 0
579
561
        tt = time.gmtime(t + offset)
580
562
    elif timezone == 'local':
676
658
def joinpath(p):
677
659
    assert isinstance(p, list)
678
660
    for f in p:
679
 
        if (f == '..') or (f is None) or (f == ''):
 
661
        if (f == '..') or (f == None) or (f == ''):
680
662
            raise BzrError("sorry, %r not allowed in path" % f)
681
663
    return pathjoin(*p)
682
664
 
726
708
 
727
709
 
728
710
def has_symlinks():
729
 
    if getattr(os, 'symlink', None) is not None:
 
711
    if hasattr(os, 'symlink'):
730
712
        return True
731
713
    else:
732
714
        return False
867
849
 
868
850
    return width
869
851
 
870
 
 
871
852
def supports_executable():
872
853
    return sys.platform != "win32"
873
854
 
874
855
 
875
 
def set_or_unset_env(env_variable, value):
876
 
    """Modify the environment, setting or removing the env_variable.
877
 
 
878
 
    :param env_variable: The environment variable in question
879
 
    :param value: The value to set the environment to. If None, then
880
 
        the variable will be removed.
881
 
    :return: The original value of the environment variable.
882
 
    """
883
 
    orig_val = os.environ.get(env_variable)
884
 
    if value is None:
885
 
        if orig_val is not None:
886
 
            del os.environ[env_variable]
887
 
    else:
888
 
        if isinstance(value, unicode):
889
 
            value = value.encode(bzrlib.user_encoding)
890
 
        os.environ[env_variable] = value
891
 
    return orig_val
892
 
 
893
 
 
894
856
_validWin32PathRE = re.compile(r'^([A-Za-z]:[/\\])?[^:<>*"?\|]*$')
895
857
 
896
858
 
913
875
    to exclude some directories, they are then not descended into.
914
876
    
915
877
    The data yielded is of the form:
916
 
    ((directory-relpath, directory-path-from-top),
917
 
    [(relpath, basename, kind, lstat), ...]),
918
 
     - directory-relpath is the relative path of the directory being returned
919
 
       with respect to top. prefix is prepended to this.
920
 
     - directory-path-from-root is the path including top for this directory. 
921
 
       It is suitable for use with os functions.
922
 
     - relpath is the relative path within the subtree being walked.
923
 
     - basename is the basename of the path
924
 
     - kind is the kind of the file now. If unknown then the file is not
925
 
       present within the tree - but it may be recorded as versioned. See
926
 
       versioned_kind.
927
 
     - lstat is the stat data *if* the file was statted.
928
 
     - planned, not implemented: 
929
 
       path_from_tree_root is the path from the root of the tree.
 
878
    [(relpath, basename, kind, lstat, path_from_top), ...]
930
879
 
931
880
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This 
932
881
        allows one to walk a subtree but get paths that are relative to a tree
933
882
        rooted higher up.
934
883
    :return: an iterator over the dirs.
935
884
    """
936
 
    #TODO there is a bit of a smell where the results of the directory-
937
 
    # summary in this, and the path from the root, may not agree 
938
 
    # depending on top and prefix - i.e. ./foo and foo as a pair leads to
939
 
    # potentially confusing output. We should make this more robust - but
940
 
    # not at a speed cost. RBC 20060731
941
885
    lstat = os.lstat
942
886
    pending = []
943
887
    _directory = _directory_kind
955
899
        for name in sorted(_listdir(top)):
956
900
            abspath = top + '/' + name
957
901
            statvalue = lstat(abspath)
958
 
            dirblock.append((relroot + name, name,
959
 
                file_kind_from_stat_mode(statvalue.st_mode),
960
 
                statvalue, abspath))
961
 
        yield (currentdir[0], top), dirblock
 
902
            dirblock.append ((relroot + name, name, file_kind_from_stat_mode(statvalue.st_mode), statvalue, abspath))
 
903
        yield dirblock
962
904
        # push the user specified dirs from dirblock
963
905
        for dir in reversed(dirblock):
964
906
            if dir[2] == _directory:
965
907
                pending.append(dir)
966
908
 
967
909
 
968
 
def copy_tree(from_path, to_path, handlers={}):
969
 
    """Copy all of the entries in from_path into to_path.
970
 
 
971
 
    :param from_path: The base directory to copy. 
972
 
    :param to_path: The target directory. If it does not exist, it will
973
 
        be created.
974
 
    :param handlers: A dictionary of functions, which takes a source and
975
 
        destinations for files, directories, etc.
976
 
        It is keyed on the file kind, such as 'directory', 'symlink', or 'file'
977
 
        'file', 'directory', and 'symlink' should always exist.
978
 
        If they are missing, they will be replaced with 'os.mkdir()',
979
 
        'os.readlink() + os.symlink()', and 'shutil.copy2()', respectively.
980
 
    """
981
 
    # Now, just copy the existing cached tree to the new location
982
 
    # We use a cheap trick here.
983
 
    # Absolute paths are prefixed with the first parameter
984
 
    # relative paths are prefixed with the second.
985
 
    # So we can get both the source and target returned
986
 
    # without any extra work.
987
 
 
988
 
    def copy_dir(source, dest):
989
 
        os.mkdir(dest)
990
 
 
991
 
    def copy_link(source, dest):
992
 
        """Copy the contents of a symlink"""
993
 
        link_to = os.readlink(source)
994
 
        os.symlink(link_to, dest)
995
 
 
996
 
    real_handlers = {'file':shutil.copy2,
997
 
                     'symlink':copy_link,
998
 
                     'directory':copy_dir,
999
 
                    }
1000
 
    real_handlers.update(handlers)
1001
 
 
1002
 
    if not os.path.exists(to_path):
1003
 
        real_handlers['directory'](from_path, to_path)
1004
 
 
1005
 
    for dir_info, entries in walkdirs(from_path, prefix=to_path):
1006
 
        for relpath, name, kind, st, abspath in entries:
1007
 
            real_handlers[kind](abspath, relpath)
1008
 
 
1009
 
 
1010
910
def path_prefix_key(path):
1011
911
    """Generate a prefix-order path key for path.
1012
912
 
1020
920
    key_a = path_prefix_key(path_a)
1021
921
    key_b = path_prefix_key(path_b)
1022
922
    return cmp(key_a, key_b)
1023
 
 
1024
 
 
1025
 
_cached_user_encoding = None
1026
 
 
1027
 
 
1028
 
def get_user_encoding():
1029
 
    """Find out what the preferred user encoding is.
1030
 
 
1031
 
    This is generally the encoding that is used for command line parameters
1032
 
    and file contents. This may be different from the terminal encoding
1033
 
    or the filesystem encoding.
1034
 
 
1035
 
    :return: A string defining the preferred user encoding
1036
 
    """
1037
 
    global _cached_user_encoding
1038
 
    if _cached_user_encoding is not None:
1039
 
        return _cached_user_encoding
1040
 
 
1041
 
    if sys.platform == 'darwin':
1042
 
        # work around egregious python 2.4 bug
1043
 
        sys.platform = 'posix'
1044
 
        try:
1045
 
            import locale
1046
 
        finally:
1047
 
            sys.platform = 'darwin'
1048
 
    else:
1049
 
        import locale
1050
 
 
1051
 
    try:
1052
 
        _cached_user_encoding = locale.getpreferredencoding()
1053
 
    except locale.Error, e:
1054
 
        sys.stderr.write('bzr: warning: %s\n'
1055
 
                         '  Could not determine what text encoding to use.\n'
1056
 
                         '  This error usually means your Python interpreter\n'
1057
 
                         '  doesn\'t support the locale set by $LANG (%s)\n'
1058
 
                         "  Continuing with ascii encoding.\n"
1059
 
                         % (e, os.environ.get('LANG')))
1060
 
 
1061
 
    if _cached_user_encoding is None:
1062
 
        _cached_user_encoding = 'ascii'
1063
 
    return _cached_user_encoding