~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Martin Pool
  • Date: 2005-06-22 06:37:43 UTC
  • Revision ID: mbp@sourcefrog.net-20050622063743-e395f04c4db8977f
- move old blackbox code from testbzr into bzrlib.selftest.blackbox

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
    os.chmod(filename, mod)
38
38
 
39
39
 
40
 
_QUOTE_RE = None
41
 
 
42
 
 
 
40
_QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/_~-])')
43
41
def quotefn(f):
44
 
    """Return a quoted filename filename
45
 
 
46
 
    This previously used backslash quoting, but that works poorly on
47
 
    Windows."""
48
 
    # TODO: I'm not really sure this is the best format either.x
49
 
    global _QUOTE_RE
50
 
    if _QUOTE_RE == None:
51
 
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/_~-])')
52
 
        
53
 
    if _QUOTE_RE.search(f):
54
 
        return '"' + f + '"'
55
 
    else:
56
 
        return f
 
42
    """Return shell-quoted filename"""
 
43
    ## We could be a bit more terse by using double-quotes etc
 
44
    f = _QUOTE_RE.sub(r'\\\1', f)
 
45
    if f[0] == '~':
 
46
        f[0:1] = r'\~' 
 
47
    return f
57
48
 
58
49
 
59
50
def file_kind(f):
80
71
 
81
72
 
82
73
 
83
 
def backup_file(fn):
84
 
    """Copy a file to a backup.
85
 
 
86
 
    Backups are named in GNU-style, with a ~ suffix.
87
 
 
88
 
    If the file is already a backup, it's not copied.
89
 
    """
90
 
    import os
91
 
    if fn[-1] == '~':
92
 
        return
93
 
    bfn = fn + '~'
94
 
 
95
 
    inf = file(fn, 'rb')
96
 
    try:
97
 
        content = inf.read()
98
 
    finally:
99
 
        inf.close()
100
 
    
101
 
    outf = file(bfn, 'wb')
102
 
    try:
103
 
        outf.write(content)
104
 
    finally:
105
 
        outf.close()
106
 
 
107
 
def rename(path_from, path_to):
108
 
    """Basically the same as os.rename() just special for win32"""
109
 
    if sys.platform == 'win32':
110
 
        try:
111
 
            os.remove(path_to)
112
 
        except OSError, e:
113
 
            if e.errno != e.ENOENT:
114
 
                raise
115
 
    os.rename(path_from, path_to)
116
 
 
117
 
 
118
 
 
119
 
 
120
 
 
121
74
def isdir(f):
122
75
    """True if f is an accessible directory."""
123
76
    try:
137
90
 
138
91
def is_inside(dir, fname):
139
92
    """True if fname is inside dir.
140
 
    
141
 
    The parameters should typically be passed to os.path.normpath first, so
142
 
    that . and .. and repeated slashes are eliminated, and the separators
143
 
    are canonical for the platform.
144
 
    
145
 
    The empty string as a dir name is taken as top-of-tree and matches 
146
 
    everything.
147
 
    
148
 
    >>> is_inside('src', 'src/foo.c')
149
 
    True
150
 
    >>> is_inside('src', 'srccontrol')
151
 
    False
152
 
    >>> is_inside('src', 'src/a/a/a/foo.c')
153
 
    True
154
 
    >>> is_inside('foo.c', 'foo.c')
155
 
    True
156
 
    >>> is_inside('foo.c', '')
157
 
    False
158
 
    >>> is_inside('', 'foo.c')
159
 
    True
160
93
    """
161
 
    # XXX: Most callers of this can actually do something smarter by 
162
 
    # looking at the inventory
163
 
    if dir == fname:
164
 
        return True
165
 
    
166
 
    if dir == '':
167
 
        return True
168
 
    
169
 
    if dir[-1] != os.sep:
170
 
        dir += os.sep
171
 
    
172
 
    return fname.startswith(dir)
 
94
    return os.path.commonprefix([dir, fname]) == dir
173
95
 
174
96
 
175
97
def is_inside_any(dir_list, fname):
176
98
    """True if fname is inside any of given dirs."""
 
99
    # quick scan for perfect match
 
100
    if fname in dir_list:
 
101
        return True
 
102
    
177
103
    for dirname in dir_list:
178
104
        if is_inside(dirname, fname):
179
105
            return True
272
198
    return realname, (username + '@' + socket.gethostname())
273
199
 
274
200
 
275
 
def _get_user_id(branch):
 
201
def _get_user_id():
276
202
    """Return the full user id from a file or environment variable.
277
203
 
278
 
    e.g. "John Hacker <jhacker@foo.org>"
279
 
 
280
 
    branch
281
 
        A branch to use for a per-branch configuration, or None.
282
 
 
283
 
    The following are searched in order:
284
 
 
285
 
    1. $BZREMAIL
286
 
    2. .bzr/email for this branch.
287
 
    3. ~/.bzr.conf/email
288
 
    4. $EMAIL
289
 
    """
 
204
    TODO: Allow taking this from a file in the branch directory too
 
205
    for per-branch ids."""
290
206
    v = os.environ.get('BZREMAIL')
291
207
    if v:
292
208
        return v.decode(bzrlib.user_encoding)
293
 
 
294
 
    if branch:
295
 
        try:
296
 
            return (branch.controlfile("email", "r") 
297
 
                    .read()
298
 
                    .decode(bzrlib.user_encoding)
299
 
                    .rstrip("\r\n"))
300
 
        except IOError, e:
301
 
            if e.errno != errno.ENOENT:
302
 
                raise
303
 
        except BzrError, e:
304
 
            pass
305
209
    
306
210
    try:
307
211
        return (open(os.path.join(config_dir(), "email"))
319
223
        return None
320
224
 
321
225
 
322
 
def username(branch):
 
226
def username():
323
227
    """Return email-style username.
324
228
 
325
229
    Something similar to 'Martin Pool <mbp@sourcefrog.net>'
326
230
 
327
231
    TODO: Check it's reasonably well-formed.
328
232
    """
329
 
    v = _get_user_id(branch)
 
233
    v = _get_user_id()
330
234
    if v:
331
235
        return v
332
236
    
337
241
        return email
338
242
 
339
243
 
340
 
def user_email(branch):
 
244
_EMAIL_RE = re.compile(r'[\w+.-]+@[\w+.-]+')
 
245
def user_email():
341
246
    """Return just the email component of a username."""
342
 
    e = _get_user_id(branch)
 
247
    e = _get_user_id()
343
248
    if e:
344
 
        m = re.search(r'[\w+.-]+@[\w+.-]+', e)
 
249
        m = _EMAIL_RE.search(e)
345
250
        if not m:
346
251
            raise BzrError("%r doesn't seem to contain a reasonable email address" % e)
347
252
        return m.group(0)
391
296
        tt = time.localtime(t)
392
297
        offset = local_time_offset(t)
393
298
    else:
394
 
        raise BzrError("unsupported timezone format %r" % timezone,
395
 
                       ['options are "utc", "original", "local"'])
 
299
        raise BzrError("unsupported timezone format %r",
 
300
                ['options are "utc", "original", "local"'])
396
301
 
397
302
    return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
398
303
            + ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
479
384
        if not ignore_errors:
480
385
            raise BzrError('command failed')
481
386
 
482
 
 
483
 
def _read_config_value(name):
484
 
    """Read a config value from the file ~/.bzr.conf/<name>
485
 
    Return None if the file does not exist"""
486
 
    try:
487
 
        f = file(os.path.join(config_dir(), name), "r")
488
 
        return f.read().decode(bzrlib.user_encoding).rstrip("\r\n")
489
 
    except IOError, e:
490
 
        if e.errno == errno.ENOENT:
491
 
            return None
492
 
        raise
493
 
 
494