~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Robert Collins
  • Date: 2005-09-28 05:25:54 UTC
  • mfrom: (1185.1.42)
  • mto: (1092.2.18)
  • mto: This revision was merged to the branch mainline in revision 1397.
  • Revision ID: robertc@robertcollins.net-20050928052554-beb985505f77ea6a
update symlink branch to integration

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Bazaar-NG -- distributed version control
2
 
 
 
2
#
3
3
# Copyright (C) 2005 by Canonical Ltd
4
 
 
 
4
#
5
5
# This program is free software; you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
7
7
# the Free Software Foundation; either version 2 of the License, or
8
8
# (at your option) any later version.
9
 
 
 
9
#
10
10
# This program is distributed in the hope that it will be useful,
11
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
13
# GNU General Public License for more details.
14
 
 
 
14
#
15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 
19
 
import os, types, re, time, errno, sys
20
 
from stat import S_ISREG, S_ISDIR, S_ISLNK, ST_MODE, ST_SIZE
 
19
from stat import (S_ISREG, S_ISDIR, S_ISLNK, ST_MODE, ST_SIZE,
 
20
                  S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
 
21
import errno
 
22
import os
 
23
import re
 
24
import sha
 
25
import sys
 
26
import time
 
27
import types
21
28
 
 
29
import bzrlib
22
30
from bzrlib.errors import BzrError
23
31
from bzrlib.trace import mutter
24
 
import bzrlib
 
32
 
25
33
 
26
34
def make_readonly(filename):
27
35
    """Make a filename read-only."""
28
 
    # TODO: probably needs to be fixed for windows
29
36
    mod = os.stat(filename).st_mode
30
37
    mod = mod & 0777555
31
38
    os.chmod(filename, mod)
48
55
    # TODO: I'm not really sure this is the best format either.x
49
56
    global _QUOTE_RE
50
57
    if _QUOTE_RE == None:
51
 
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/_~-])')
 
58
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/\\_~-])')
52
59
        
53
60
    if _QUOTE_RE.search(f):
54
61
        return '"' + f + '"'
64
71
        return 'directory'
65
72
    elif S_ISLNK(mode):
66
73
        return 'symlink'
 
74
    elif S_ISCHR(mode):
 
75
        return 'chardev'
 
76
    elif S_ISBLK(mode):
 
77
        return 'block'
 
78
    elif S_ISFIFO(mode):
 
79
        return 'fifo'
 
80
    elif S_ISSOCK(mode):
 
81
        return 'socket'
67
82
    else:
68
 
        raise BzrError("can't handle file kind with mode %o of %r" % (mode, f))
 
83
        return 'unknown'
69
84
 
70
85
 
71
86
def kind_marker(kind):
110
125
 
111
126
    If the file is already a backup, it's not copied.
112
127
    """
113
 
    import os
114
128
    if fn[-1] == '~':
115
129
        return
116
130
    bfn = fn + '~'
127
141
    finally:
128
142
        outf.close()
129
143
 
130
 
def rename(path_from, path_to):
131
 
    """Basically the same as os.rename() just special for win32"""
132
 
    if sys.platform == 'win32':
133
 
        try:
134
 
            os.remove(path_to)
135
 
        except OSError, e:
136
 
            if e.errno != e.ENOENT:
137
 
                raise
138
 
    os.rename(path_from, path_to)
139
 
 
140
 
 
141
 
 
 
144
if os.name == 'nt':
 
145
    import shutil
 
146
    rename = shutil.move
 
147
else:
 
148
    rename = os.rename
142
149
 
143
150
 
144
151
def isdir(f):
149
156
        return False
150
157
 
151
158
 
152
 
 
153
159
def isfile(f):
154
160
    """True if f is a regular file."""
155
161
    try:
174
180
    The empty string as a dir name is taken as top-of-tree and matches 
175
181
    everything.
176
182
    
177
 
    >>> is_inside('src', 'src/foo.c')
 
183
    >>> is_inside('src', os.path.join('src', 'foo.c'))
178
184
    True
179
185
    >>> is_inside('src', 'srccontrol')
180
186
    False
181
 
    >>> is_inside('src', 'src/a/a/a/foo.c')
 
187
    >>> is_inside('src', os.path.join('src', 'a', 'a', 'a', 'foo.c'))
182
188
    True
183
189
    >>> is_inside('foo.c', 'foo.c')
184
190
    True
194
200
    
195
201
    if dir == '':
196
202
        return True
197
 
    
 
203
 
198
204
    if dir[-1] != os.sep:
199
205
        dir += os.sep
200
 
    
 
206
 
201
207
    return fname.startswith(dir)
202
208
 
203
209
 
215
221
    tofile.write(fromfile.read())
216
222
 
217
223
 
218
 
def uuid():
219
 
    """Return a new UUID"""
220
 
    try:
221
 
        return file('/proc/sys/kernel/random/uuid').readline().rstrip('\n')
222
 
    except IOError:
223
 
        return chomp(os.popen('uuidgen').readline())
224
 
 
225
 
 
226
224
def sha_file(f):
227
 
    import sha
228
225
    if hasattr(f, 'tell'):
229
226
        assert f.tell() == 0
230
227
    s = sha.new()
238
235
 
239
236
 
240
237
def sha_string(f):
241
 
    import sha
242
238
    s = sha.new()
243
239
    s.update(f)
244
240
    return s.hexdigest()
245
241
 
246
242
 
247
 
 
248
243
def fingerprint_file(f):
249
 
    import sha
250
244
    s = sha.new()
251
245
    b = f.read()
252
246
    s.update(b)
262
256
    
263
257
    TODO: Global option --config-dir to override this.
264
258
    """
265
 
    return os.path.expanduser("~/.bzr.conf")
 
259
    return os.path.join(os.path.expanduser("~"), ".bzr.conf")
266
260
 
267
261
 
268
262
def _auto_user_id():
372
366
    if e:
373
367
        m = re.search(r'[\w+.-]+@[\w+.-]+', e)
374
368
        if not m:
375
 
            raise BzrError("%r doesn't seem to contain a reasonable email address" % e)
 
369
            raise BzrError("%r doesn't seem to contain "
 
370
                           "a reasonable email address" % e)
376
371
        return m.group(0)
377
372
 
378
373
    return _auto_user_id()[1]
379
 
    
380
374
 
381
375
 
382
376
def compare_files(a, b):
391
385
            return True
392
386
 
393
387
 
394
 
 
395
388
def local_time_offset(t=None):
396
389
    """Return offset of local zone from GMT, either at present or at time t."""
397
390
    # python2.3 localtime() can't take None
436
429
    """Return size of given open file."""
437
430
    return os.fstat(f.fileno())[ST_SIZE]
438
431
 
439
 
 
440
 
if hasattr(os, 'urandom'): # python 2.4 and later
 
432
# Define rand_bytes based on platform.
 
433
try:
 
434
    # Python 2.4 and later have os.urandom,
 
435
    # but it doesn't work on some arches
 
436
    os.urandom(1)
441
437
    rand_bytes = os.urandom
442
 
elif sys.platform == 'linux2':
443
 
    rand_bytes = file('/dev/urandom', 'rb').read
444
 
else:
445
 
    # not well seeded, but better than nothing
446
 
    def rand_bytes(n):
447
 
        import random
448
 
        s = ''
449
 
        while n:
450
 
            s += chr(random.randint(0, 255))
451
 
            n -= 1
452
 
        return s
453
 
 
 
438
except (NotImplementedError, AttributeError):
 
439
    # If python doesn't have os.urandom, or it doesn't work,
 
440
    # then try to first pull random data from /dev/urandom
 
441
    if os.path.exists("/dev/urandom"):
 
442
        rand_bytes = file('/dev/urandom', 'rb').read
 
443
    # Otherwise, use this hack as a last resort
 
444
    else:
 
445
        # not well seeded, but better than nothing
 
446
        def rand_bytes(n):
 
447
            import random
 
448
            s = ''
 
449
            while n:
 
450
                s += chr(random.randint(0, 255))
 
451
                n -= 1
 
452
            return s
454
453
 
455
454
## TODO: We could later have path objects that remember their list
456
455
## decomposition (might be too tricksy though.)
519
518
        if e.errno == errno.ENOENT:
520
519
            return None
521
520
        raise
522
 
 
523