~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: John Arbash Meinel
  • Date: 2006-09-12 22:16:38 UTC
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20060912221638-bf11ba3e3f498106
lazy_import diff.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Bazaar-NG -- distributed version control
 
1
# Bazaar -- distributed version control
2
2
#
3
3
# Copyright (C) 2005 by Canonical Ltd
4
4
#
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
 
56
64
def make_readonly(filename):
57
65
    """Make a filename read-only."""
58
66
    mod = os.stat(filename).st_mode
76
84
    Windows."""
77
85
    # TODO: I'm not really sure this is the best format either.x
78
86
    global _QUOTE_RE
79
 
    if _QUOTE_RE == None:
 
87
    if _QUOTE_RE is None:
80
88
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
81
89
        
82
90
    if _QUOTE_RE.search(f):
118
126
        raise
119
127
 
120
128
 
 
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
 
121
139
def kind_marker(kind):
122
140
    if kind == 'file':
123
141
        return ''
132
150
if lexists is None:
133
151
    def lexists(f):
134
152
        try:
135
 
            if hasattr(os, 'lstat'):
 
153
            if getattr(os, 'lstat') is not None:
136
154
                os.lstat(f)
137
155
            else:
138
156
                os.stat(f)
172
190
        pass
173
191
    except IOError, e:
174
192
        # RBC 20060103 abstraction leakage: the paramiko SFTP clients rename
175
 
        # function raises an IOError with errno == None when a rename fails.
 
193
        # function raises an IOError with errno is None when a rename fails.
176
194
        # This then gets caught here.
177
195
        if e.errno not in (None, errno.ENOENT, errno.ENOTDIR):
178
196
            raise
179
197
    except Exception, e:
180
 
        if (not hasattr(e, 'errno') 
 
198
        if (getattr(e, 'errno', None) is None
181
199
            or e.errno not in (errno.ENOENT, errno.ENOTDIR)):
182
200
            raise
183
201
    else:
352
370
 
353
371
 
354
372
def normalizepath(f):
355
 
    if hasattr(os.path, 'realpath'):
 
373
    if getattr(os.path, 'realpath', None) is not None:
356
374
        F = realpath
357
375
    else:
358
376
        F = abspath
487
505
 
488
506
 
489
507
def sha_file(f):
490
 
    if hasattr(f, 'tell'):
 
508
    if getattr(f, 'tell', None) is not None:
491
509
        assert f.tell() == 0
492
510
    s = sha.new()
493
511
    BUFSIZE = 128<<10
537
555
def local_time_offset(t=None):
538
556
    """Return offset of local zone from GMT, either at present or at time t."""
539
557
    # python2.3 localtime() can't take None
540
 
    if t == None:
 
558
    if t is None:
541
559
        t = time.time()
542
560
        
543
561
    if time.localtime(t).tm_isdst and time.daylight:
556
574
        tt = time.gmtime(t)
557
575
        offset = 0
558
576
    elif timezone == 'original':
559
 
        if offset == None:
 
577
        if offset is None:
560
578
            offset = 0
561
579
        tt = time.gmtime(t + offset)
562
580
    elif timezone == 'local':
658
676
def joinpath(p):
659
677
    assert isinstance(p, list)
660
678
    for f in p:
661
 
        if (f == '..') or (f == None) or (f == ''):
 
679
        if (f == '..') or (f is None) or (f == ''):
662
680
            raise BzrError("sorry, %r not allowed in path" % f)
663
681
    return pathjoin(*p)
664
682
 
708
726
 
709
727
 
710
728
def has_symlinks():
711
 
    if hasattr(os, 'symlink'):
 
729
    if getattr(os, 'symlink', None) is not None:
712
730
        return True
713
731
    else:
714
732
        return False
849
867
 
850
868
    return width
851
869
 
 
870
 
852
871
def supports_executable():
853
872
    return sys.platform != "win32"
854
873
 
855
874
 
 
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
 
856
894
_validWin32PathRE = re.compile(r'^([A-Za-z]:[/\\])?[^:<>*"?\|]*$')
857
895
 
858
896
 
875
913
    to exclude some directories, they are then not descended into.
876
914
    
877
915
    The data yielded is of the form:
878
 
    [(relpath, basename, kind, lstat, path_from_top), ...]
 
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.
879
930
 
880
931
    :param prefix: Prefix the relpaths that are yielded with 'prefix'. This 
881
932
        allows one to walk a subtree but get paths that are relative to a tree
882
933
        rooted higher up.
883
934
    :return: an iterator over the dirs.
884
935
    """
 
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
885
941
    lstat = os.lstat
886
942
    pending = []
887
943
    _directory = _directory_kind
899
955
        for name in sorted(_listdir(top)):
900
956
            abspath = top + '/' + name
901
957
            statvalue = lstat(abspath)
902
 
            dirblock.append ((relroot + name, name, file_kind_from_stat_mode(statvalue.st_mode), statvalue, abspath))
903
 
        yield dirblock
 
958
            dirblock.append((relroot + name, name,
 
959
                file_kind_from_stat_mode(statvalue.st_mode),
 
960
                statvalue, abspath))
 
961
        yield (currentdir[0], top), dirblock
904
962
        # push the user specified dirs from dirblock
905
963
        for dir in reversed(dirblock):
906
964
            if dir[2] == _directory:
907
965
                pending.append(dir)
908
966
 
909
967
 
 
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
 
910
1010
def path_prefix_key(path):
911
1011
    """Generate a prefix-order path key for path.
912
1012
 
920
1020
    key_a = path_prefix_key(path_a)
921
1021
    key_b = path_prefix_key(path_b)
922
1022
    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 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