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.
279
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]
282
386
def compare_files(a, b):
283
387
"""Returns true if equal in contents"""
303
407
return -time.timezone
306
def format_date(t, offset=0, timezone='original', date_fmt=None,
410
def format_date(t, offset=0, timezone='original'):
308
411
## TODO: Perhaps a global option to use either universal or local time?
309
412
## Or perhaps just let people set $TZ?
310
413
assert isinstance(t, float)
323
426
raise BzrError("unsupported timezone format %r" % timezone,
324
427
['options are "utc", "original", "local"'])
326
date_fmt = "%a %Y-%m-%d %H:%M:%S"
328
offset_str = ' %+03d%02d' % (offset / 3600, (offset / 60) % 60)
331
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))
334
433
def compact_date(when):
412
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:
415
526
def split_lines(s):
416
527
"""Split s into lines, but without removing the newline characters."""
417
528
return StringIO(s).readlines()
432
543
if e.errno != errno.EXDEV:
434
545
copyfile(src, dest)
438
if hasattr(os, 'symlink'):
444
def contains_whitespace(s):
445
"""True if there are any whitespace characters in s."""
446
for ch in string.whitespace:
453
def contains_linebreaks(s):
454
"""True if there is any vertical whitespace in s."""
462
def relpath(base, path):
463
"""Return path relative to base, or raise exception.
465
The path may be either an absolute path or a path relative to the
466
current working directory.
468
os.path.commonprefix (python2.4) has a bad bug that it works just
469
on string prefixes, assuming that '/u' is a prefix of '/u2'. This
470
avoids that problem."""
475
while len(head) >= len(base):
478
head, tail = os.path.split(head)
482
# XXX This should raise a NotChildPath exception, as its not tied
484
raise NotBranchError("path %r is not within branch %r" % (rp, base))
486
return os.sep.join(s)