120
121
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
123
139
def backup_file(fn):
124
140
"""Copy a file to a backup.
259
279
'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]
386
282
def compare_files(a, b):
387
283
"""Returns true if equal in contents"""
407
303
return -time.timezone
410
def format_date(t, offset=0, timezone='original'):
306
def format_date(t, offset=0, timezone='original', date_fmt=None,
411
308
## TODO: Perhaps a global option to use either universal or local time?
412
309
## Or perhaps just let people set $TZ?
413
310
assert isinstance(t, float)
426
323
raise BzrError("unsupported timezone format %r" % timezone,
427
324
['options are "utc", "original", "local"'])
429
return (time.strftime("%a %Y-%m-%d %H:%M:%S", tt)
430
+ ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
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)
433
334
def compact_date(when):
511
412
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:
526
415
def split_lines(s):
527
416
"""Split s into lines, but without removing the newline characters."""
528
417
return StringIO(s).readlines()
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)