Rev 5403: Merge bzr.dev 5404 in http://bazaar.launchpad.net/~jameinel/bzr/2.3-bzr-connect-ssh

John Arbash Meinel john at arbash-meinel.com
Wed Sep 1 19:43:23 BST 2010


At http://bazaar.launchpad.net/~jameinel/bzr/2.3-bzr-connect-ssh

------------------------------------------------------------
revno: 5403 [merge]
revision-id: john at arbash-meinel.com-20100901184313-c9g2gxkmfqq7ofco
parent: john at arbash-meinel.com-20100901184131-nlr61r0wroe8qrko
parent: pqm at pqm.ubuntu.com-20100901180619-u0q01om0gjzxxy2i
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.3-bzr-connect-ssh
timestamp: Wed 2010-09-01 13:43:13 -0500
message:
  Merge bzr.dev 5404
modified:
  Makefile                       Makefile-20050805140406-d96e3498bb61c5bb
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
  bzrlib/merge.py                merge.py-20050513021216-953b65a438527106
  bzrlib/repofmt/groupcompress_repo.py repofmt.py-20080715094215-wp1qfvoo7093c8qr-1
  bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/strace.py               strace.py-20070323001526-6zquhhw8leb9m6j8-1
  bzrlib/symbol_versioning.py    symbol_versioning.py-20060105104851-9ecf8af605d15a80
  bzrlib/tests/test_config.py    testconfig.py-20051011041908-742d0c15d8d8c8eb
  bzrlib/tests/test_server.py    test_server.py-20100209163834-im1ozfuenfmqaa2m-1
  bzrlib/tests/test_strace.py    test_strace.py-20070323001526-6zquhhw8leb9m6j8-2
  bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
  bzrlib/tests/test_transport.py testtransport.py-20050718175618-e5cdb99f4555ddce
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
  bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
  bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
  doc/en/whats-new/whats-new-in-2.3.txt whatsnewin2.3.txt-20100818072501-x2h25r7jbnknvy30-1
-------------- next part --------------
=== modified file 'Makefile'
--- a/Makefile	2010-04-06 06:59:03 +0000
+++ b/Makefile	2010-08-30 21:23:49 +0000
@@ -39,8 +39,14 @@
 check: docs check-nodocs
 
 check-nodocs: extensions
+	set -e
 	# Generate a stream for PQM to watch.
+	-$(RM) -f selftest.log
 	$(PYTHON) -Werror -O ./bzr selftest --subunit $(tests) | tee selftest.log
+	# An empty log file should catch errors in the $(PYTHON)
+	# command above (the '|' swallow any errors since 'make'
+	# sees the 'tee' exit code for the whole line
+	if [ ! -s selftest.log ] ; then exit 1 ; fi
 	# Check that there were no errors reported.
 	subunit-stats < selftest.log
 

=== modified file 'NEWS'
--- a/NEWS	2010-08-30 07:47:38 +0000
+++ b/NEWS	2010-09-01 18:06:19 +0000
@@ -20,6 +20,11 @@
   is now named "msg" instead of earlier "message".
   (Parth Malwankar, #603461)
 
+* ``bzrlib.transform.TreeTransformBase.final_kind``,
+  ``bzrlib.transform.TreeTransform.tree_kind`` and
+  ``bzrlib.transform.TransformPreview.tree_kind`` now return None instead
+  of raising NoSuchFile.  (Vincent Ladeuil)
+
 * `decode` parameter to get() method in FtpTransport and GioTransport classes
   is deprecated. (Alexander Belchenko)
 
@@ -73,6 +78,9 @@
   ``bzr launchpad-login user && bzr push lp:~/project/branch`` will now
   push to ``lp:~user/project/branch``.  (John Arbash Meinel)
 
+* New development format ``development8-subtree`` which is similar to the 
+  ``2a`` format and adds subtree support. (Jelmer Vernooij)
+
 Bug Fixes
 *********
 
@@ -111,6 +119,9 @@
 * Don't print internal object name when print an invalid revision spec
   error.  (Neil Martinsen-Burrell, #598701)
 
+* ``EPIPE`` can be raised during test server shutdown. This happened on
+  gentoo only so far. (Vincent Ladeuil, #627277)
+
 * Errors occurring during http(s) test server starts should now be
   handled cleanly. (Vincent Ladeuil, #392402)
 
@@ -118,6 +129,9 @@
   directory that was a symlink in the previous commit.
   (Martin Pool, #192859)
 
+* Fix spurious paramiko warning on hardy by ensuring that ``selftest``
+  properly remove its warning filter. (Vincent Ladeuil, #625686)
+
 * ``HTTP/1.1`` test servers now set a ``Content-Length`` header to comply
   with pedantic ``HTTP/1.1`` clients. (Vincent Ladeuil, #568421)
 
@@ -128,11 +142,18 @@
 * `PathNotChild` should not give a traceback.
   (Martin Pool, #98735)
 
+* ``PQM`` will no longer ignore syntax errors in submissions.
+  (Vincent Ladeuil, #626667)
+
 * Prevent ``CHKMap.apply_delta`` from generating non-canonical CHK maps,
   which can result in "missing referenced chk root keys" errors when
   fetching from repositories with affected revisions.
   (Andrew Bennetts, #522637)
 
+* strace test-helper tests cope with the new Ubuntu policy of not allowing
+  users to attach to their own processes by default.
+  (Martin Pool, #626679)
+
 * ``Transport.stat`` on a symlink, including a transport pointing directly
   to a symlink, now returns information about the symlink.
   (Martin Pool)
@@ -146,6 +167,10 @@
   will be backed up (adding an extention of the form .~#~).
   (Marius Kruger, #400554)
 
+* ``bzr revert`` and ``bzr status`` are up to 15% faster on large trees
+  with many changes by not repeatedly building a list of all file-ids.
+  (Andrew Bennetts)
+
 * Decrease memory consumption when many chk index pages are loaded. (Such
   as during ``bzr co`` or ``bzr ls -R`` of a large tree.) Often we need to
   read many chk pages because the individual chk map nodes will be spread

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2010-08-30 07:47:38 +0000
+++ b/bzrlib/builtins.py	2010-08-31 08:57:28 +0000
@@ -3572,9 +3572,6 @@
             parallel=None, lsprof_tests=False):
         from bzrlib import tests
 
-        # Make deprecation warnings visible, unless -Werror is set
-        symbol_versioning.activate_deprecation_warnings(override=False)
-
         if testspecs_list is not None:
             pattern = '|'.join(testspecs_list)
         else:
@@ -3620,7 +3617,14 @@
                           "starting_with": starting_with
                           }
         selftest_kwargs.update(self.additional_selftest_args)
-        result = tests.selftest(**selftest_kwargs)
+
+        # Make deprecation warnings visible, unless -Werror is set
+        cleanup = symbol_versioning.activate_deprecation_warnings(
+            override=False)
+        try:
+            result = tests.selftest(**selftest_kwargs)
+        finally:
+            cleanup()
         return int(not result)
 
 

=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2010-08-23 20:37:18 +0000
+++ b/bzrlib/bzrdir.py	2010-08-25 02:16:31 +0000
@@ -3290,8 +3290,24 @@
     alias=True,
     hidden=True,
     )
+register_metadir(controldir.format_registry, 'development5-subtree',
+    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
+    help='Development format, subtree variant. Can convert data to and '
+        'from pack-0.92-subtree (and anything compatible with '
+        'pack-0.92-subtree) format repositories. Repositories and branches in '
+        'this format can only be read by bzr.dev. Please read '
+        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
+        'before use.',
+    branch_format='bzrlib.branch.BzrBranchFormat7',
+    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
+    experimental=True,
+    hidden=True,
+    alias=False,
+    )
+
+
 register_metadir(controldir.format_registry, 'development-subtree',
-    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
+    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2aSubtree',
     help='Current development format, subtree variant. Can convert data to and '
         'from pack-0.92-subtree (and anything compatible with '
         'pack-0.92-subtree) format repositories. Repositories and branches in '
@@ -3341,7 +3357,7 @@
         # 'rich roots. Supported by bzr 1.16 and later.',
     branch_format='bzrlib.branch.BzrBranchFormat7',
     tree_format='bzrlib.workingtree.WorkingTreeFormat6',
-    experimental=True,
+    experimental=False,
     )
 
 # The following format should be an alias for the rich root equivalent 

=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py	2010-07-29 03:56:54 +0000
+++ b/bzrlib/merge.py	2010-08-25 13:02:32 +0000
@@ -1085,9 +1085,7 @@
         return result
 
     def fix_root(self):
-        try:
-            self.tt.final_kind(self.tt.root)
-        except errors.NoSuchFile:
+        if self.tt.final_kind(self.tt.root) is None:
             self.tt.cancel_deletion(self.tt.root)
         if self.tt.final_file_id(self.tt.root) is None:
             self.tt.version_file(self.tt.tree_file_id(self.tt.root),
@@ -1102,10 +1100,9 @@
             # the other tree's root is a non-root in the current tree (as when
             # a previously unrelated branch is merged into another)
             return
-        try:
-            self.tt.final_kind(other_root)
+        if self.tt.final_kind(other_root) is not None:
             other_root_is_present = True
-        except errors.NoSuchFile:
+        else:
             # other_root doesn't have a physical representation. We still need
             # to move any references to the actual root of the tree.
             other_root_is_present = False
@@ -1115,15 +1112,10 @@
         for thing, child in self.other_tree.inventory.root.children.iteritems():
             trans_id = self.tt.trans_id_file_id(child.file_id)
             if not other_root_is_present:
-                # FIXME: Make final_kind returns None instead of raising
-                # NoSuchFile to avoid the ugly construct below -- vila 20100402
-                try:
-                    self.tt.final_kind(trans_id)
+                if self.tt.final_kind(trans_id) is not None:
                     # The item exist in the final tree and has a defined place
                     # to go already.
                     continue
-                except errors.NoSuchFile, e:
-                    pass
             # Move the item into the root
             self.tt.adjust_path(self.tt.final_name(trans_id),
                                 self.tt.root, trans_id)
@@ -1405,10 +1397,7 @@
             self.tt.version_file(file_id, trans_id)
         # The merge has been performed, so the old contents should not be
         # retained.
-        try:
-            self.tt.delete_contents(trans_id)
-        except errors.NoSuchFile:
-            pass
+        self.tt.delete_contents(trans_id)
         return result
 
     def _default_other_winner_merge(self, merge_hook_params):
@@ -1586,10 +1575,7 @@
         if winner == 'this' and file_status != "modified":
             return
         trans_id = self.tt.trans_id_file_id(file_id)
-        try:
-            if self.tt.final_kind(trans_id) != "file":
-                return
-        except errors.NoSuchFile:
+        if self.tt.final_kind(trans_id) != "file":
             return
         if winner == "this":
             executability = this_executable

=== modified file 'bzrlib/repofmt/groupcompress_repo.py'
--- a/bzrlib/repofmt/groupcompress_repo.py	2010-08-23 17:54:07 +0000
+++ b/bzrlib/repofmt/groupcompress_repo.py	2010-09-01 11:27:40 +0000
@@ -1428,3 +1428,28 @@
         """See RepositoryFormat.get_format_description()."""
         return ("Repository format 2a - rich roots, group compression"
             " and chk inventories")
+
+
+class RepositoryFormat2aSubtree(RepositoryFormat2a):
+    """A 2a repository format that supports nested trees.
+
+    """
+
+    def _get_matching_bzrdir(self):
+        return bzrdir.format_registry.make_bzrdir('development-subtree')
+
+    def _ignore_setting_bzrdir(self, format):
+        pass
+
+    _matchingbzrdir = property(_get_matching_bzrdir, _ignore_setting_bzrdir)
+
+    def get_format_string(self):
+        return ('Bazaar development format 8\n')
+
+    def get_format_description(self):
+        """See RepositoryFormat.get_format_description()."""
+        return ("Development repository format 8 - nested trees, "
+                "group compression and chk inventories")
+
+    experimental = True
+    supports_tree_reference = True

=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2010-08-05 19:25:52 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2010-09-01 11:27:40 +0000
@@ -2918,7 +2918,7 @@
 
     def _get_matching_bzrdir(self):
         return bzrdir.format_registry.make_bzrdir(
-            'development-subtree')
+            'development5-subtree')
 
     def _ignore_setting_bzrdir(self, format):
         pass

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2010-08-17 22:24:01 +0000
+++ b/bzrlib/repository.py	2010-08-25 02:16:31 +0000
@@ -3389,6 +3389,11 @@
     'bzrlib.repofmt.groupcompress_repo',
     'RepositoryFormat2a',
     )
+format_registry.register_lazy(
+    'Bazaar development format 8\n',
+    'bzrlib.repofmt.groupcompress_repo',
+    'RepositoryFormat2aSubtree',
+    )
 
 
 class InterRepository(InterObject):

=== modified file 'bzrlib/strace.py'
--- a/bzrlib/strace.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/strace.py	2010-09-01 18:43:13 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
 #   Authors: Robert Collins <robert.collins at canonical.com>
 #
 # This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,9 @@
 import subprocess
 import tempfile
 
+from bzrlib import errors
+
+
 # this is currently test-focused, so importing bzrlib.tests is ok. We might
 # want to move feature to its own module though.
 from bzrlib.tests import Feature
@@ -46,14 +49,17 @@
     # capture strace output to a file
     log_file = tempfile.NamedTemporaryFile()
     log_file_fd = log_file.fileno()
+    err_file = tempfile.NamedTemporaryFile()
     pid = os.getpid()
     # start strace
     strace_cmd = ['strace', '-r', '-tt', '-p', str(pid), '-o', log_file.name]
     if follow_children:
         strace_args.append('-f')
+    # need to catch both stdout and stderr to work around
+    # bug 627208
     proc = subprocess.Popen(strace_cmd,
                             stdout=subprocess.PIPE,
-                            stderr=subprocess.STDOUT)
+                            stderr=err_file.fileno())
     # Wait for strace to attach
     attached_notice = proc.stdout.readline()
     # Run the function to strace
@@ -65,18 +71,31 @@
     log_file.seek(0)
     log = log_file.read()
     log_file.close()
-    return result, StraceResult(log)
+    # and stderr
+    err_file.seek(0)
+    err_messages = err_file.read()
+    err_file.close()
+    # and read any errors
+    if err_messages.startswith("attach: ptrace(PTRACE_ATTACH,"):
+        raise StraceError(err_messages=err_messages)
+    return result, StraceResult(log, err_messages)
+
+
+class StraceError(errors.BzrError):
+    
+    _fmt = "strace failed: %(err_messages)s"
 
 
 class StraceResult(object):
     """The result of stracing a function."""
 
-    def __init__(self, raw_log):
+    def __init__(self, raw_log, err_messages):
         """Create a StraceResult.
 
         :param raw_log: The output that strace created.
         """
         self.raw_log = raw_log
+        self.err_messages = err_messages
 
 
 class _StraceFeature(Feature):

=== modified file 'bzrlib/symbol_versioning.py'
--- a/bzrlib/symbol_versioning.py	2010-06-29 16:21:13 +0000
+++ b/bzrlib/symbol_versioning.py	2010-08-28 15:34:24 +0000
@@ -29,6 +29,9 @@
            'warn',
            ]
 
+
+import warnings
+# Import the 'warn' symbol so bzrlib can call it even if we redefine it
 from warnings import warn
 
 import bzrlib
@@ -296,7 +299,6 @@
     :param error_only: Only match an 'error' filter
     :return: True if a filter is found, False otherwise
     """
-    import warnings
     for filter in warnings.filters:
         if issubclass(DeprecationWarning, filter[2]):
             # This filter will effect DeprecationWarning
@@ -305,6 +307,19 @@
     return False
 
 
+def _remove_filter_callable(filter):
+    """Build and returns a callable removing filter from the warnings.
+
+    :param filter: The filter to remove (can be None).
+
+    :return: A callable that will remove filter from warnings.filters.
+    """
+    def cleanup():
+        if filter:
+            warnings.filters.remove(filter)
+    return cleanup
+
+
 def suppress_deprecation_warnings(override=True):
     """Call this function to suppress all deprecation warnings.
 
@@ -314,18 +329,17 @@
 
     :param override: If True, always set the ignore, if False, only set the
         ignore if there isn't already a filter.
+
     :return: A callable to remove the new warnings this added.
     """
-    import warnings
     if not override and _check_for_filter(error_only=False):
         # If there is already a filter effecting suppress_deprecation_warnings,
         # then skip it.
-        return
-    warnings.filterwarnings('ignore', category=DeprecationWarning)
-    filter = warnings.filters[0]
-    def cleanup():
-        warnings.filters.remove(filter)
-    return cleanup
+        filter = None
+    else:
+        warnings.filterwarnings('ignore', category=DeprecationWarning)
+        filter = warnings.filters[0]
+    return _remove_filter_callable(filter)
 
 
 def activate_deprecation_warnings(override=True):
@@ -342,10 +356,14 @@
     :param override: If False, only add a filter if there isn't an error filter
         already. (This slightly differs from suppress_deprecation_warnings, in
         because it always overrides everything but -Werror).
+
+    :return: A callable to remove the new warnings this added.
     """
-    import warnings
     if not override and _check_for_filter(error_only=True):
         # DeprecationWarnings are already turned into errors, don't downgrade
         # them to 'default'.
-        return
-    warnings.filterwarnings('default', category=DeprecationWarning)
+        filter = None
+    else:
+        warnings.filterwarnings('default', category=DeprecationWarning)
+        filter = warnings.filters[0]
+    return _remove_filter_callable(filter)

=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py	2010-08-29 14:32:45 +0000
+++ b/bzrlib/tests/test_config.py	2010-08-30 08:26:45 +0000
@@ -491,7 +491,8 @@
         return self.config_class(*self.config_args)
 
     def create_config(self, content):
-        c = self.config_class.from_string(content, *self.config_args, save=True)
+        kwargs = dict(save=True)
+        c = self.config_class.from_string(content, *self.config_args, **kwargs)
         return c
 
     def test_simple_read_access(self):

=== modified file 'bzrlib/tests/test_server.py'
--- a/bzrlib/tests/test_server.py	2010-08-24 16:07:33 +0000
+++ b/bzrlib/tests/test_server.py	2010-08-31 08:24:17 +0000
@@ -424,10 +424,19 @@
 
     def ignored_exceptions_during_shutdown(self, e):
         if sys.platform == 'win32':
-            accepted_errnos = [errno.EBADF, errno.WSAEBADF, errno.WSAENOTCONN,
-                               errno.WSAECONNRESET, errno.WSAESHUTDOWN]
+            accepted_errnos = [errno.EBADF,
+                               errno.EPIPE,
+                               errno.WSAEBADF,
+                               errno.WSAECONNRESET,
+                               errno.WSAENOTCONN,
+                               errno.WSAESHUTDOWN,
+                               ]
         else:
-            accepted_errnos = [errno.EBADF, errno.ENOTCONN, errno.ECONNRESET]
+            accepted_errnos = [errno.EBADF,
+                               errno.ECONNRESET,
+                               errno.ENOTCONN,
+                               errno.EPIPE,
+                               ]
         if isinstance(e, socket.error) and e[0] in accepted_errnos:
             return True
         return False

=== modified file 'bzrlib/tests/test_strace.py'
--- a/bzrlib/tests/test_strace.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/test_strace.py	2010-09-01 18:43:13 +0000
@@ -1,5 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
-#   Authors: Robert Collins <robert.collins at canonical.com>
+# Copyright (C) 2007-2010 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
@@ -22,34 +21,26 @@
 import threading
 
 from bzrlib import (
+    strace,
     tests,
     )
 from bzrlib.strace import StraceFeature, strace_detailed, StraceResult
 
 
-class TestStraceFeature(tests.TestCaseWithTransport):
-
-    def test_strace_detection(self):
-        """Strace is available if its runnable."""
-        try:
-            proc = subprocess.Popen(['strace'],
-                stderr=subprocess.PIPE,
-                stdout=subprocess.PIPE)
-            proc.communicate()
-            found_strace = True
-        except OSError, e:
-            if e.errno == errno.ENOENT:
-                # strace is not installed
-                found_strace = False
-            else:
-                raise
-        self.assertEqual(found_strace, StraceFeature.available())
-
-
 class TestStrace(tests.TestCaseWithTransport):
 
     _test_needs_features = [StraceFeature]
 
+    def setUp(self):
+        # NB: see http://pad.lv/626679 and
+        # <https://code.launchpad.net/~mbp/bzr/626679-strace/+merge/34157>:
+        # testing strace by connecting to ourselves has repeatedly caused
+        # hangs in running the test suite; these are fixable given enough
+        # determination but given that strace is not used by any other tests
+        # at the moment and that it's only test-support code, we just leave it
+        # untested -- mbp 20100901
+        raise tests.TestSkipped("strace selftests are broken and disabled")
+
     def _check_threads(self):
         # For bug #226769, it was decided that the strace tests should not be
         # run when more than one thread is active. A lot of tests are currently
@@ -61,14 +52,26 @@
             raise tests.KnownFailure(
                 '%d active threads, bug #103133 needs to be fixed.' % active)
 
+    def strace_detailed_or_skip(self, *args, **kwargs):
+        """Run strace, but cope if it's not allowed"""
+        try:
+            return strace_detailed(*args, **kwargs)
+        except strace.StraceError, e:
+            if e.err_messages.startswith(
+                    "attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted"):
+                raise tests.TestSkipped("ptrace not permitted")
+            else:
+                raise
+
     def test_strace_callable_is_called(self):
         self._check_threads()
 
         output = []
         def function(positional, *args, **kwargs):
             output.append((positional, args, kwargs))
-        strace_detailed(function, ["a", "b"], {"c": "c"},
-                        follow_children=False)
+        self.strace_detailed_or_skip(
+            function, ["a", "b"], {"c": "c"},
+            follow_children=False)
         self.assertEqual([("a", ("b",), {"c":"c"})], output)
 
     def test_strace_callable_result(self):
@@ -76,7 +79,7 @@
 
         def function():
             return "foo"
-        result, strace_result = strace_detailed(function,[], {},
+        result, strace_result = self.strace_detailed_or_skip(function,[], {},
                                                 follow_children=False)
         self.assertEqual("foo", result)
         self.assertIsInstance(strace_result, StraceResult)
@@ -87,6 +90,6 @@
 
         def function():
             self.build_tree(['myfile'])
-        unused, result = strace_detailed(function, [], {},
+        unused, result = self.strace_detailed_or_skip(function, [], {},
                                          follow_children=False)
         self.assertContainsRe(result.raw_log, 'myfile')

=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2010-07-21 10:38:31 +0000
+++ b/bzrlib/tests/test_transform.py	2010-08-25 10:20:41 +0000
@@ -123,12 +123,12 @@
         imaginary_id = transform.trans_id_tree_path('imaginary')
         imaginary_id2 = transform.trans_id_tree_path('imaginary/')
         self.assertEqual(imaginary_id, imaginary_id2)
-        self.assertEqual(transform.get_tree_parent(imaginary_id), root)
-        self.assertEqual(transform.final_kind(root), 'directory')
-        self.assertEqual(transform.final_file_id(root), self.wt.get_root_id())
+        self.assertEqual(root, transform.get_tree_parent(imaginary_id))
+        self.assertEqual('directory', transform.final_kind(root))
+        self.assertEqual(self.wt.get_root_id(), transform.final_file_id(root))
         trans_id = transform.create_path('name', root)
         self.assertIs(transform.final_file_id(trans_id), None)
-        self.assertRaises(NoSuchFile, transform.final_kind, trans_id)
+        self.assertIs(None, transform.final_kind(trans_id))
         transform.create_file('contents', trans_id)
         transform.set_executability(True, trans_id)
         transform.version_file('my_pretties', trans_id)

=== modified file 'bzrlib/tests/test_transport.py'
--- a/bzrlib/tests/test_transport.py	2010-09-01 18:18:28 +0000
+++ b/bzrlib/tests/test_transport.py	2010-09-01 18:43:13 +0000
@@ -900,6 +900,8 @@
 
         bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.
         """
+        raise tests.TestSkipped('this test was recently broken,'
+                                ' see bug #626876')
         # This test actually causes a bzr instance to be invoked, which is very
         # expensive: it should be the only such test in the test suite.
         # A reasonable evolution for this would be to simply check inside

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2010-08-06 19:54:45 +0000
+++ b/bzrlib/transform.py	2010-08-27 07:54:21 +0000
@@ -315,10 +315,9 @@
 
     def delete_contents(self, trans_id):
         """Schedule the contents of a path entry for deletion"""
-        # Ensure that the object exists in the WorkingTree, this will raise an
-        # exception if there is a problem
-        self.tree_kind(trans_id)
-        self._removed_contents.add(trans_id)
+        kind = self.tree_kind(trans_id)
+        if kind is not None:
+            self._removed_contents.add(trans_id)
 
     def cancel_deletion(self, trans_id):
         """Cancel a scheduled deletion"""
@@ -389,22 +388,22 @@
         changed_kind = set(self._removed_contents)
         changed_kind.intersection_update(self._new_contents)
         changed_kind.difference_update(new_ids)
-        changed_kind = (t for t in changed_kind if self.tree_kind(t) !=
-                        self.final_kind(t))
+        changed_kind = (t for t in changed_kind
+                        if self.tree_kind(t) != self.final_kind(t))
         new_ids.update(changed_kind)
         return sorted(FinalPaths(self).get_paths(new_ids))
 
     def final_kind(self, trans_id):
         """Determine the final file kind, after any changes applied.
 
-        Raises NoSuchFile if the file does not exist/has no contents.
-        (It is conceivable that a path would be created without the
-        corresponding contents insertion command)
+        :return: None if the file does not exist/has no contents.  (It is
+            conceivable that a path would be created without the corresponding
+            contents insertion command)
         """
         if trans_id in self._new_contents:
             return self._new_contents[trans_id]
         elif trans_id in self._removed_contents:
-            raise NoSuchFile(None)
+            return None
         else:
             return self.tree_kind(trans_id)
 
@@ -596,9 +595,8 @@
         """
         conflicts = []
         for trans_id in self._new_id.iterkeys():
-            try:
-                kind = self.final_kind(trans_id)
-            except NoSuchFile:
+            kind = self.final_kind(trans_id)
+            if kind is None:
                 conflicts.append(('versioning no contents', trans_id))
                 continue
             if not InventoryEntry.versionable_kind(kind):
@@ -618,11 +616,7 @@
             if self.final_file_id(trans_id) is None:
                 conflicts.append(('unversioned executability', trans_id))
             else:
-                try:
-                    non_file = self.final_kind(trans_id) != "file"
-                except NoSuchFile:
-                    non_file = True
-                if non_file is True:
+                if self.final_kind(trans_id) != "file":
                     conflicts.append(('non-file executability', trans_id))
         return conflicts
 
@@ -630,9 +624,7 @@
         """Check for overwrites (not permitted on Win32)"""
         conflicts = []
         for trans_id in self._new_contents:
-            try:
-                self.tree_kind(trans_id)
-            except NoSuchFile:
+            if self.tree_kind(trans_id) is None:
                 continue
             if trans_id not in self._removed_contents:
                 conflicts.append(('overwrite', trans_id,
@@ -652,10 +644,7 @@
             last_name = None
             last_trans_id = None
             for name, trans_id in name_ids:
-                try:
-                    kind = self.final_kind(trans_id)
-                except NoSuchFile:
-                    kind = None
+                kind = self.final_kind(trans_id)
                 file_id = self.final_file_id(trans_id)
                 if kind is None and file_id is None:
                     continue
@@ -687,15 +676,7 @@
                 continue
             if not self._any_contents(children):
                 continue
-            for child in children:
-                try:
-                    self.final_kind(child)
-                except NoSuchFile:
-                    continue
-            try:
-                kind = self.final_kind(parent_id)
-            except NoSuchFile:
-                kind = None
+            kind = self.final_kind(parent_id)
             if kind is None:
                 conflicts.append(('missing parent', parent_id))
             elif kind != "directory":
@@ -705,11 +686,8 @@
     def _any_contents(self, trans_ids):
         """Return true if any of the trans_ids, will have contents."""
         for trans_id in trans_ids:
-            try:
-                kind = self.final_kind(trans_id)
-            except NoSuchFile:
-                continue
-            return True
+            if self.final_kind(trans_id) is not None:
+                return True
         return False
 
     def _set_executability(self, path, trans_id):
@@ -845,10 +823,7 @@
         Return a (name, parent, kind, executable) tuple
         """
         to_name = self.final_name(to_trans_id)
-        try:
-            to_kind = self.final_kind(to_trans_id)
-        except NoSuchFile:
-            to_kind = None
+        to_kind = self.final_kind(to_trans_id)
         to_parent = self.final_file_id(self.final_parent(to_trans_id))
         if to_trans_id in self._new_executability:
             to_executable = self._new_executability[to_trans_id]
@@ -1419,18 +1394,15 @@
     def tree_kind(self, trans_id):
         """Determine the file kind in the working tree.
 
-        Raises NoSuchFile if the file does not exist
+        :returns: The file kind or None if the file does not exist
         """
         path = self._tree_id_paths.get(trans_id)
         if path is None:
-            raise NoSuchFile(None)
+            return None
         try:
             return file_kind(self._tree.abspath(path))
-        except OSError, e:
-            if e.errno != errno.ENOENT:
-                raise
-            else:
-                raise NoSuchFile(path)
+        except errors.NoSuchFile:
+            return None
 
     def _set_mode(self, trans_id, mode_id, typefunc):
         """Set the mode of new file contents.
@@ -1605,9 +1577,8 @@
                 if file_id is None:
                     continue
                 needs_entry = False
-                try:
-                    kind = self.final_kind(trans_id)
-                except NoSuchFile:
+                kind = self.final_kind(trans_id)
+                if kind is None:
                     kind = self._tree.stored_kind(file_id)
                 parent_trans_id = self.final_parent(trans_id)
                 parent_file_id = new_path_file_ids.get(parent_trans_id)
@@ -1725,9 +1696,12 @@
     def tree_kind(self, trans_id):
         path = self._tree_id_paths.get(trans_id)
         if path is None:
-            raise NoSuchFile(None)
+            return None
         file_id = self._tree.path2id(path)
-        return self._tree.kind(file_id)
+        try:
+            return self._tree.kind(file_id)
+        except errors.NoSuchFile:
+            return None
 
     def _set_mode(self, trans_id, mode_id, typefunc):
         """Set the mode of new file contents.
@@ -1929,9 +1903,8 @@
             if (specific_file_ids is not None
                 and file_id not in specific_file_ids):
                 continue
-            try:
-                kind = self._transform.final_kind(trans_id)
-            except NoSuchFile:
+            kind = self._transform.final_kind(trans_id)
+            if kind is None:
                 kind = self._transform._tree.stored_kind(file_id)
             new_entry = inventory.make_entry(
                 kind,
@@ -2169,10 +2142,10 @@
                 path_from_root = self._final_paths.get_path(child_id)
                 basename = self._transform.final_name(child_id)
                 file_id = self._transform.final_file_id(child_id)
-                try:
-                    kind = self._transform.final_kind(child_id)
+                kind  = self._transform.final_kind(child_id)
+                if kind is not None:
                     versioned_kind = kind
-                except NoSuchFile:
+                else:
                     kind = 'unknown'
                     versioned_kind = self._transform._tree.stored_kind(file_id)
                 if versioned_kind == 'directory':

=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py	2010-05-25 17:27:52 +0000
+++ b/bzrlib/tree.py	2010-08-31 07:12:18 +0000
@@ -1130,7 +1130,7 @@
             if file_id in to_paths:
                 # already returned
                 continue
-            if file_id not in self.target.all_file_ids():
+            if not self.target.has_id(file_id):
                 # common case - paths we have not emitted are not present in
                 # target.
                 to_path = None

=== modified file 'bzrlib/versionedfile.py'
--- a/bzrlib/versionedfile.py	2010-08-16 06:46:17 +0000
+++ b/bzrlib/versionedfile.py	2010-08-28 15:34:24 +0000
@@ -46,7 +46,6 @@
 from bzrlib.transport.memory import MemoryTransport
 """)
 from bzrlib.registry import Registry
-from bzrlib.symbol_versioning import *
 from bzrlib.textmerge import TextMerge
 from bzrlib import bencode
 

=== modified file 'doc/en/whats-new/whats-new-in-2.3.txt'
--- a/doc/en/whats-new/whats-new-in-2.3.txt	2010-08-23 18:59:22 +0000
+++ b/doc/en/whats-new/whats-new-in-2.3.txt	2010-08-31 07:12:18 +0000
@@ -8,12 +8,12 @@
 :doc:`../release-notes/index` for a full list.
 
 Users are encouraged to upgrade from the other stable series.  This
-document outlines the improvements in Bazaar 2.2 vs Bazaar 2.1. As well as
+document outlines the improvements in Bazaar 2.3 vs Bazaar 2.2. As well as
 summarizing improvements made to the core product, it highlights
 enhancements within the broader Bazaar world of potential interest to
 those upgrading.
 
-Bazaar 2.2.0 is fully compatible both locally and on the network with 2.0
+Bazaar 2.3.0 is fully compatible both locally and on the network with 2.0
 2.1, and 2.2, and can read and write repositories generated by all
 previous versions.
 
@@ -28,6 +28,10 @@
 Performance improvements
 ************************
 
+* ``bzr revert`` and ``bzr status`` are up to 15% faster on large trees
+  with many changes by not repeatedly building a list of all file-ids.
+  (Andrew Bennetts)
+
 * ``bzr send`` uses less memory.  
   (John Arbash Meinel, #614576)
 



More information about the bazaar-commits mailing list