121
120
return os.path.join(F(p), e)
123
if os.name == "posix":
124
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
125
# choke on a Unicode string containing a relative path if
126
# os.getcwd() returns a non-sys.getdefaultencoding()-encoded
128
_fs_enc = sys.getfilesystemencoding()
130
return os.path.abspath(path.encode(_fs_enc)).decode(_fs_enc)
132
return os.path.realpath(path.encode(_fs_enc)).decode(_fs_enc)
134
# We need to use the Unicode-aware os.path.abspath and
135
# os.path.realpath on Windows systems.
136
abspath = os.path.abspath
137
realpath = os.path.realpath
139
123
def backup_file(fn):
140
124
"""Copy a file to a backup.
284
259
'sha1': s.hexdigest()}
263
"""Return per-user configuration directory.
265
By default this is ~/.bzr.conf/
267
TODO: Global option --config-dir to override this.
269
return os.path.join(os.path.expanduser("~"), ".bzr.conf")
273
"""Calculate automatic user identification.
275
Returns (realname, email).
277
Only used when none is set in the environment or the id file.
279
This previously used the FQDN as the default domain, but that can
280
be very slow on machines where DNS is broken. So now we simply
285
# XXX: Any good way to get real user name on win32?
290
w = pwd.getpwuid(uid)
291
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
292
username = w.pw_name.decode(bzrlib.user_encoding)
293
comma = gecos.find(',')
297
realname = gecos[:comma]
303
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
305
return realname, (username + '@' + socket.gethostname())
308
def _get_user_id(branch):
309
"""Return the full user id from a file or environment variable.
311
e.g. "John Hacker <jhacker@foo.org>"
314
A branch to use for a per-branch configuration, or None.
316
The following are searched in order:
319
2. .bzr/email for this branch.
323
v = os.environ.get('BZREMAIL')
325
return v.decode(bzrlib.user_encoding)
329
return (branch.controlfile("email", "r")
331
.decode(bzrlib.user_encoding)
334
if e.errno != errno.ENOENT:
340
return (open(os.path.join(config_dir(), "email"))
342
.decode(bzrlib.user_encoding)
345
if e.errno != errno.ENOENT:
348
v = os.environ.get('EMAIL')
350
return v.decode(bzrlib.user_encoding)
355
def username(branch):
356
"""Return email-style username.
358
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
360
TODO: Check it's reasonably well-formed.
362
v = _get_user_id(branch)
366
name, email = _auto_user_id()
368
return '%s <%s>' % (name, email)
373
def user_email(branch):
374
"""Return just the email component of a username."""
375
e = _get_user_id(branch)
377
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
379
raise BzrError("%r doesn't seem to contain "
380
"a reasonable email address" % e)
383
return _auto_user_id()[1]
287
386
def compare_files(a, b):
288
387
"""Returns true if equal in contents"""
308
407
return -time.timezone
311
def format_date(t, offset=0, timezone='original', date_fmt=None,
410
def format_date(t, offset=0, timezone='original'):
313
411
## TODO: Perhaps a global option to use either universal or local time?
314
412
## Or perhaps just let people set $TZ?
315
413
assert isinstance(t, float)
328
426
raise BzrError("unsupported timezone format %r" % timezone,
329
427
['options are "utc", "original", "local"'])
331
date_fmt = "%a %Y-%m-%d %H:%M:%S"
333
offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
336
return (time.strftime(date_fmt, tt) + offset_str)
429
return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
430
+ ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
339
433
def compact_date(when):
417
511
return os.path.join(p1, p2)
514
def _read_config_value(name):
515
"""Read a config value from the file ~/.bzr.conf/<name>
516
Return None if the file does not exist"""
518
f = file(os.path.join(config_dir(), name), "r")
519
return f.read().decode(bzrlib.user_encoding).rstrip("\r\n")
521
if e.errno == errno.ENOENT:
420
526
def split_lines(s):
421
527
"""Split s into lines, but without removing the newline characters."""
422
528
return StringIO(s).readlines()
437
543
if e.errno != errno.EXDEV:
439
545
copyfile(src, dest)
443
if hasattr(os, 'symlink'):
449
def contains_whitespace(s):
450
"""True if there are any whitespace characters in s."""
451
for ch in string.whitespace:
458
def contains_linebreaks(s):
459
"""True if there is any vertical whitespace in s."""
467
def relpath(base, path):
468
"""Return path relative to base, or raise exception.
470
The path may be either an absolute path or a path relative to the
471
current working directory.
473
os.path.commonprefix (python2.4) has a bad bug that it works just
474
on string prefixes, assuming that '/u' is a prefix of '/u2'. This
475
avoids that problem."""
480
while len(head) >= len(base):
483
head, tail = os.path.split(head)
487
# XXX This should raise a NotChildPath exception, as its not tied
489
raise NotBranchError("path %r is not within branch %r" % (rp, base))
491
return os.sep.join(s)
495
def terminal_width():
496
"""Return estimated terminal width."""
498
# TODO: Do something smart on Windows?
500
# TODO: Is there anything that gets a better update when the window
501
# is resized while the program is running? We could use the Python termcap
504
return int(os.environ['COLUMNS'])
505
except (IndexError, KeyError, ValueError):