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