Rev 5755: (jam) Merge 2.3 into bzr.dev, resolving some conflicts in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Apr 5 11:54:00 UTC 2011
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5755 [merge]
revision-id: pqm at pqm.ubuntu.com-20110405115356-5d6k2moisuap7bi6
parent: pqm at pqm.ubuntu.com-20110405103130-b8da764vupjyqpb0
parent: john at arbash-meinel.com-20110405104136-5efh3us2o4csleng
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2011-04-05 11:53:56 +0000
message:
(jam) Merge 2.3 into bzr.dev, resolving some conflicts
modified:
bzrlib/config.py config.py-20051011043216-070c74f4e9e338e8
bzrlib/crash.py crash.py-20090812083334-d6volool4lktdjcx-1
bzrlib/lockdir.py lockdir.py-20060220222025-98258adf27fbdda3
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/tests/test_config.py testconfig.py-20051011041908-742d0c15d8d8c8eb
bzrlib/tests/test_crash.py test_crash.py-20090820042958-jglgza3wrn03ha9e-2
doc/developers/testing.txt testing.txt-20080812140359-i70zzh6v2z7grqex-1
doc/en/release-notes/bzr-2.3.txt NEWS-20050323055033-4e00b5db738777ff
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py 2011-03-31 13:35:54 +0000
+++ b/bzrlib/config.py 2011-04-05 10:41:36 +0000
@@ -63,6 +63,7 @@
"""
import os
+import string
import sys
from bzrlib import commands
@@ -441,21 +442,21 @@
the concrete policy type is checked, and finally
$EMAIL is examined.
If no username can be found, errors.NoWhoami exception is raised.
-
- TODO: Check it's reasonably well-formed.
"""
v = os.environ.get('BZR_EMAIL')
if v:
return v.decode(osutils.get_user_encoding())
-
v = self._get_user_id()
if v:
return v
-
v = os.environ.get('EMAIL')
if v:
return v.decode(osutils.get_user_encoding())
-
+ name, email = _auto_user_id()
+ if name and email:
+ return '%s <%s>' % (name, email)
+ elif email:
+ return email
raise errors.NoWhoami()
def ensure_username(self):
@@ -1407,6 +1408,86 @@
return os.path.expanduser('~/.cache')
+def _get_default_mail_domain():
+ """If possible, return the assumed default email domain.
+
+ :returns: string mail domain, or None.
+ """
+ if sys.platform == 'win32':
+ # No implementation yet; patches welcome
+ return None
+ try:
+ f = open('/etc/mailname')
+ except (IOError, OSError), e:
+ return None
+ try:
+ domain = f.read().strip()
+ return domain
+ finally:
+ f.close()
+
+
+def _auto_user_id():
+ """Calculate automatic user identification.
+
+ :returns: (realname, email), either of which may be None if they can't be
+ determined.
+
+ Only used when none is set in the environment or the id file.
+
+ This only returns an email address if we can be fairly sure the
+ address is reasonable, ie if /etc/mailname is set on unix.
+
+ This doesn't use the FQDN as the default domain because that may be
+ slow, and it doesn't use the hostname alone because that's not normally
+ a reasonable address.
+ """
+ if sys.platform == 'win32':
+ # No implementation to reliably determine Windows default mail
+ # address; please add one.
+ return None, None
+
+ default_mail_domain = _get_default_mail_domain()
+ if not default_mail_domain:
+ return None, None
+
+ import pwd
+ uid = os.getuid()
+ try:
+ w = pwd.getpwuid(uid)
+ except KeyError:
+ mutter('no passwd entry for uid %d?' % uid)
+ return None, None
+
+ # we try utf-8 first, because on many variants (like Linux),
+ # /etc/passwd "should" be in utf-8, and because it's unlikely to give
+ # false positives. (many users will have their user encoding set to
+ # latin-1, which cannot raise UnicodeError.)
+ try:
+ gecos = w.pw_gecos.decode('utf-8')
+ encoding = 'utf-8'
+ except UnicodeError:
+ try:
+ encoding = osutils.get_user_encoding()
+ gecos = w.pw_gecos.decode(encoding)
+ except UnicodeError, e:
+ mutter("cannot decode passwd entry %s" % w)
+ return None, None
+ try:
+ username = w.pw_name.decode(encoding)
+ except UnicodeError, e:
+ mutter("cannot decode passwd entry %s" % w)
+ return None, None
+
+ comma = gecos.find(',')
+ if comma == -1:
+ realname = gecos
+ else:
+ realname = gecos[:comma]
+
+ return realname, (username + '@' + default_mail_domain)
+
+
def parse_username(username):
"""Parse e-mail username and return a (name, address) tuple."""
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
=== modified file 'bzrlib/crash.py'
--- a/bzrlib/crash.py 2011-01-20 23:07:25 +0000
+++ b/bzrlib/crash.py 2011-04-05 10:41:36 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2009, 2010, 2011 Canonical Ltd
+# Copyright (C) 2009-2011 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -84,19 +84,27 @@
"""Report a bug by just printing a message to the user."""
trace.print_exception(exc_info, err_file)
err_file.write('\n')
- err_file.write('bzr %s on python %s (%s)\n' % \
- (bzrlib.__version__,
- bzrlib._format_version_tuple(sys.version_info),
- platform.platform(aliased=1)))
- err_file.write('arguments: %r\n' % sys.argv)
- err_file.write(
+ import textwrap
+ def print_wrapped(l):
+ err_file.write(textwrap.fill(l,
+ width=78, subsequent_indent=' ') + '\n')
+ print_wrapped('bzr %s on python %s (%s)\n' % \
+ (bzrlib.__version__,
+ bzrlib._format_version_tuple(sys.version_info),
+ platform.platform(aliased=1)))
+ print_wrapped('arguments: %r\n' % sys.argv)
+ print_wrapped(textwrap.fill(
+ 'plugins: ' + plugin.format_concise_plugin_list(),
+ width=78,
+ subsequent_indent=' ',
+ ) + '\n')
+ print_wrapped(
'encoding: %r, fsenc: %r, lang: %r\n' % (
osutils.get_user_encoding(), sys.getfilesystemencoding(),
os.environ.get('LANG')))
- err_file.write("plugins:\n")
- err_file.write(_format_plugin_list())
+ # We used to show all the plugins here, but it's too verbose.
err_file.write(
- "\n\n"
+ "\n"
"*** Bazaar has encountered an internal error. This probably indicates a\n"
" bug in Bazaar. You can help us fix it by filing a bug report at\n"
" https://bugs.launchpad.net/bzr/+filebug\n"
=== modified file 'bzrlib/lockdir.py'
--- a/bzrlib/lockdir.py 2011-01-12 20:31:15 +0000
+++ b/bzrlib/lockdir.py 2011-03-31 09:01:27 +0000
@@ -537,6 +537,17 @@
hook(hook_result)
return result
+ def lock_url_for_display(self):
+ """Give a nicely-printable representation of the URL of this lock."""
+ # As local lock urls are correct we display them.
+ # We avoid displaying remote lock urls.
+ lock_url = self.transport.abspath(self.path)
+ if lock_url.startswith('file://'):
+ lock_url = lock_url.split('.bzr/')[0]
+ else:
+ lock_url = ''
+ return lock_url
+
def wait_lock(self, timeout=None, poll=None, max_attempts=None):
"""Wait a certain period for a lock.
@@ -566,6 +577,7 @@
deadline_str = None
last_info = None
attempt_count = 0
+ lock_url = self.lock_url_for_display()
while True:
attempt_count += 1
try:
@@ -590,13 +602,6 @@
if deadline_str is None:
deadline_str = time.strftime('%H:%M:%S',
time.localtime(deadline))
- # As local lock urls are correct we display them.
- # We avoid displaying remote lock urls.
- lock_url = self.transport.abspath(self.path)
- if lock_url.startswith('file://'):
- lock_url = lock_url.split('.bzr/')[0]
- else:
- lock_url = ''
user, hostname, pid, time_ago = formatted_info
msg = ('%s lock %s ' # lock_url
'held by ' # start
=== modified file 'bzrlib/plugin.py'
--- a/bzrlib/plugin.py 2011-01-20 01:02:34 +0000
+++ b/bzrlib/plugin.py 2011-04-05 10:41:36 +0000
@@ -451,6 +451,17 @@
return result
+def format_concise_plugin_list():
+ """Return a string holding a concise list of plugins and their version.
+ """
+ items = []
+ for name, a_plugin in sorted(plugins().items()):
+ items.append("%s[%s]" %
+ (name, a_plugin.__version__))
+ return ', '.join(items)
+
+
+
class PluginsHelpIndex(object):
"""A help index that returns help topics for plugins."""
=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py 2011-02-25 12:12:39 +0000
+++ b/bzrlib/tests/test_config.py 2011-04-05 10:41:36 +0000
@@ -42,6 +42,7 @@
)
from bzrlib.tests import (
features,
+ TestSkipped,
scenarios,
)
from bzrlib.util.configobj import configobj
@@ -2469,3 +2470,25 @@
# test_user_prompted ?
class TestAuthenticationRing(tests.TestCaseWithTransport):
pass
+
+
+class TestAutoUserId(tests.TestCase):
+ """Test inferring an automatic user name."""
+
+ def test_auto_user_id(self):
+ """Automatic inference of user name.
+
+ This is a bit hard to test in an isolated way, because it depends on
+ system functions that go direct to /etc or perhaps somewhere else.
+ But it's reasonable to say that on Unix, with an /etc/mailname, we ought
+ to be able to choose a user name with no configuration.
+ """
+ if sys.platform == 'win32':
+ raise TestSkipped("User name inference not implemented on win32")
+ realname, address = config._auto_user_id()
+ if os.path.exists('/etc/mailname'):
+ self.assertTrue(realname)
+ self.assertTrue(address)
+ else:
+ self.assertEquals((None, None), (realname, address))
+
=== modified file 'bzrlib/tests/test_crash.py'
--- a/bzrlib/tests/test_crash.py 2011-01-18 00:41:29 +0000
+++ b/bzrlib/tests/test_crash.py 2011-04-05 10:41:36 +0000
@@ -15,12 +15,12 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+import doctest
+import os
from StringIO import StringIO
import sys
-
-import os
-
+from testtools.matchers import DocTestMatches
from bzrlib import (
config,
@@ -80,3 +80,45 @@
self.assertContainsRe(
report,
'Failed to load plugin foo')
+
+
+class TestNonApportReporting(tests.TestCase):
+ """Reporting of crash-type bugs without apport.
+
+ This should work in all environments.
+ """
+
+ def setup_fake_plugins(self):
+ def fake_plugins():
+ fake = plugin.PlugIn('fake_plugin', plugin)
+ fake.version_info = lambda: (1, 2, 3)
+ return {"fake_plugin": fake}
+ self.overrideAttr(plugin, 'plugins', fake_plugins)
+
+ def test_report_bug_legacy(self):
+ self.setup_fake_plugins()
+ err_file = StringIO()
+ try:
+ raise AssertionError("my error")
+ except AssertionError, e:
+ pass
+ crash.report_bug_legacy(sys.exc_info(), err_file)
+ self.assertThat(
+ err_file.getvalue(),
+ DocTestMatches("""\
+bzr: ERROR: exceptions.AssertionError: my error
+
+Traceback (most recent call last):
+ ...
+AssertionError: my error
+
+bzr ... on python ...
+arguments: ...
+plugins: fake_plugin[1.2.3]
+encoding: ...
+
+*** Bazaar has encountered an internal error. This probably indicates a
+ bug in Bazaar. You can help us fix it by filing a bug report at
+ https://bugs.launchpad.net/bzr/+filebug
+ including this traceback and a description of the problem.
+""", flags=doctest.ELLIPSIS|doctest.REPORT_UDIFF))
=== modified file 'doc/developers/testing.txt'
--- a/doc/developers/testing.txt 2011-02-03 00:39:52 +0000
+++ b/doc/developers/testing.txt 2011-04-05 10:41:36 +0000
@@ -339,6 +339,11 @@
__ http://docs.python.org/lib/module-doctest.html
+There is an `assertDoctestExampleMatches` method in
+`bzrlib.tests.TestCase` that allows you to match against doctest-style
+string templates (including ``...`` to skip sections) from regular Python
+tests.
+
Shell-like tests
----------------
=== modified file 'doc/en/release-notes/bzr-2.3.txt'
--- a/doc/en/release-notes/bzr-2.3.txt 2011-03-24 11:41:42 +0000
+++ b/doc/en/release-notes/bzr-2.3.txt 2011-04-05 10:41:36 +0000
@@ -39,11 +39,25 @@
.. Fixes for situations where bzr would previously crash or give incorrect
or undesirable results.
+* Bazaar now infers the default user email address on Unix from the local
+ account name plus the contents of ``/etc/mailname`` if that file exists.
+ In particular, this means that committing as root through etckeeper will
+ normally not require running ``bzr whoami`` first.
+ (Martin Pool, #616878)
+
+* When reporting a crash without apport, don't print the full list of
+ plugins because it's often too long.
+ (Martin Pool, #716389)
+
* ``bzr push`` into a repository (that doesn't have a branch), will no
longer copy all revisions in the repository. Only the ones in the
ancestry of the source branch, like it does in all other cases.
(John Arbash Meinel, #465517)
+* Fix ``UnboundLocalError: local variable 'lock_url' in wait_lock`` error,
+ especially while trying to save configuration from QBzr.
+ (Martin Pool, #733136)
+
* Fix "Unable to obtain lock" error when pushing to a bound branch if tags
had changed. Bazaar was attempting to open and lock the master branch
twice in this case. (Andrew Bennetts, #733350)
@@ -79,7 +93,6 @@
(<http://psf.upfronthosting.co.za/roundup/tracker/issue8194> should be fixed
in python > 2.7.1). (Vincent Ladeuil, #654733)
-
bzr 2.3.1
#########
More information about the bazaar-commits
mailing list