Rev 4738: (andrew) Merge lp:bzr/2.0 into lp:bzr, including fixes for #322807, in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Oct 13 07:08:55 BST 2009


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 4738 [merge]
revision-id: pqm at pqm.ubuntu.com-20091013060853-erk2aaj80fnkrv25
parent: pqm at pqm.ubuntu.com-20091012223642-0seiqhjw7sa587dm
parent: andrew.bennetts at canonical.com-20091013052050-u1w6tv0z7kqhn8d0
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2009-10-13 07:08:53 +0100
message:
  (andrew) Merge lp:bzr/2.0 into lp:bzr, including fixes for #322807,
  	#389413, #402623 and documentation improvements.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  README                         README-20050309040720-8f368abf9f346b9d
  bzrlib/btree_index.py          index.py-20080624222253-p0x5f92uyh5hw734-7
  bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
  bzrlib/tests/per_repository_chk/test_supported.py test_supported.py-20080925063728-k65ry0n2rhta6t34-1
  bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
  bzrlib/tests/test_index.py     test_index.py-20070712131115-lolkarso50vjr64s-2
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
  bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
  doc/developers/releasing.txt   releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
  doc/en/upgrade-guide/data_migration.txt data_migration.txt-20090702082510-q2pocf7uhntljqnl-2
=== modified file 'NEWS'
--- a/NEWS	2009-10-12 18:14:21 +0000
+++ b/NEWS	2009-10-13 05:20:50 +0000
@@ -108,17 +108,31 @@
   with some combinations of remote and local formats.  This was causing
   "unknown object type identifier 60" errors.  (Andrew Bennetts, #427736)
 
+* Fixed ``ObjectNotLocked`` errors when doing some log and diff operations
+  on branches via a smart server.  (Andrew Bennetts, #389413)
+
 * ftp transports were built differently when the kerberos python module was
   present leading to obscure failures related to ASCII/BINARY modes.
   (Vincent Ladeuil, #443041)
 
-* Network streams now decode adjacent records of the same type into a
-  single stream, reducing layering churn. (Robert Collins)
+* Handle things like ``bzr add foo`` and ``bzr rm foo`` when the tree is
+  at the root of a drive. ``osutils._cicp_canonical_relpath`` always
+  assumed that ``abspath()`` returned a path that did not have a trailing
+  ``/``, but that is not true when working at the root of the filesystem.
+  (John Arbash Meinel, Jason Spashett, #322807)
+
+* Improve the time for ``bzr log DIR`` for 2a format repositories.
+  We had been using the same code path as for <2a formats, which required
+  iterating over all objects in all revisions.
+  (John Arbash Meinel, #374730)
 
 * Make sure that we unlock the tree if we fail to create a TreeTransform
   object when doing a merge, and there is limbo, or pending-deletions
   directory.  (Gary van der Merwe, #427773)
 
+* Network streams now decode adjacent records of the same type into a
+  single stream, reducing layering churn. (Robert Collins)
+
 * Occasional IndexError on renamed files have been fixed. Operations that
   set a full inventory in the working tree will now go via the
   apply_inventory_delta code path which is simpler and easier to
@@ -138,6 +152,14 @@
 * Registry objects should not use iteritems() when asked to use items().
   (Vincent Ladeuil, #430510)
 
+* Retrieving file text or mtime from a _PreviewTree has good performance when
+  there are many changes.  (Aaron Bentley)
+
+* The CHK index pages now use an unlimited cache size. With a limited
+  cache and a large project, the random access of chk pages could cause us
+  to download the entire cix file many times.
+  (John Arbash Meinel, #402623)
+
 * Weave based repositories couldn't be cloned when committers were using
   domains or user ids embedding '.sig'. Now they can.
   (Matthew Fuller, Vincent Ladeuil, #430868)
@@ -172,6 +194,12 @@
 * Help on hooks no longer says 'Not deprecated' for hooks that are
   currently supported. (Ian Clatworthy, #422415)
 
+* Improved README. (Ian Clatworthy)
+
+* Improved upgrade documentation for Launchpad branches.
+  (Barry Warsaw)
+
+
 API Changes
 ***********
 
@@ -285,6 +313,15 @@
   with some combinations of remote and local formats.  This was causing
   "unknown object type identifier 60" errors.  (Andrew Bennetts, #427736)
 
+* Fixed ``ObjectNotLocked`` errors when doing some log and diff operations
+  on branches via a smart server.  (Andrew Bennetts, #389413)
+
+* Handle things like ``bzr add foo`` and ``bzr rm foo`` when the tree is
+  at the root of a drive. ``osutils._cicp_canonical_relpath`` always
+  assumed that ``abspath()`` returned a path that did not have a trailing
+  ``/``, but that is not true when working at the root of the filesystem.
+  (John Arbash Meinel, Jason Spashett, #322807)
+
 * Improve the time for ``bzr log DIR`` for 2a format repositories.
   We had been using the same code path as for <2a formats, which required
   iterating over all objects in all revisions.
@@ -302,11 +339,25 @@
   but such operations are already doing full tree scans, so no radical
   performance change should be observed. (Robert Collins, #403322)
 
+* Retrieving file text or mtime from a _PreviewTree has good performance when
+  there are many changes.  (Aaron Bentley)
+
+* The CHK index pages now use an unlimited cache size. With a limited
+  cache and a large project, the random access of chk pages could cause us
+  to download the entire cix file many times.
+  (John Arbash Meinel, #402623)
+
 * When a file kind becomes unversionable after being added, a sensible
   error will be shown instead of a traceback. (Robert Collins, #438569)
 
-* Retrieving file text or mtime from a _PreviewTree has good performance when
-  there are many changes.  (Aaron Bentley)
+
+Documentation
+*************
+
+* Improved README. (Ian Clatworthy)
+
+* Improved upgrade documentation for Launchpad branches.
+  (Barry Warsaw)
 
 
 bzr 2.0.0

=== modified file 'README'
--- a/README	2008-03-16 14:01:20 +0000
+++ b/README	2009-10-06 07:41:02 +0000
@@ -3,72 +3,44 @@
 =================
 
 Bazaar (``bzr``) is a decentralized revision control system, designed to be
-easy for developers and end users alike.  Bazaar is part of the GNU project to
-develop a complete free operating system.
-
-To install Bazaar from source, follow the instructions in the INSTALL
-file. Otherwise, you may want to check your distribution package manager
-for ready-to-install packages, or http://bazaar-vcs.org/DistroDownloads.
-
-To learn how to use Bazaar, check the documentation in the doc/ directory.
-Once installed, you can also run 'bzr help'. An always up-to-date and more
-complete set of documents can be found in the Bazaar website, at:
-
-    http://bazaar-vcs.org/Documentation
+easy for developers and end users alike.  Bazaar is part of the GNU project
+to develop a complete free operating system.
+
+To install Bazaar, follow the instructions given at
+http://bazaar-vcs.org/Download. Ready-to-install packages are available
+for most popular operating systems or you can install from source.
+
+To learn how to use Bazaar, see the official documentation at:
+
+    http://doc.bazaar-vcs.org/en/
+
+For additional training materials including screencasts and slides,
+visit our community wiki documentation page at:
+
+    http://bazaar-vcs.org/Documentation/
 
 Bazaar is written in Python, and is sponsored by Canonical Limited, the
 founders of Ubuntu and Launchpad. Bazaar is Free Software, and is released
 under the GNU General Public License.
 
-Bazaar was formerly known as Bazaar-NG.  It's the successor to ``baz``, a fork
-of GNU arch, but shares no code.  (To upgrade from Baz, use the ``baz-import``
-command in the bzrtools plugin.)
-
 Bazaar highlights
 =================
 
-* Easy to use and intuitive.
-
-  Only five commands are needed to do all basic operations, and all
-  commands have documentation accessible via 'bzr help command'.
-  Bazaar's interface is also easy to learn for CVS and Subversion users.
-
-* Robust and reliable.
-
-  Bazaar is developed under an extensive test suite. Branches can be
-  checked and verified for integrity at any time, and revisions can be
-  signed with PGP/GnuPG.
-
-* Publish branches with HTTP.
-
-  Branches can be hosted on an HTTP server with no need for special
-  software on the server side. Branches can be uploaded by bzr itself
-  over SSH (SFTP), or with rsync.
-
-* Adapts to multiple environments.
-
-  Bazaar runs on Linux and Windows, fully supports Unicode filenames,
-  and suits different development models, including centralized.
-
-* Easily extended and customized.
-
-  A rich Python interface is provided for extending and embedding,
-  including a plugin interface. There are already many available plugins,
-  most of them registered at http://bazaar-vcs.org/PluginRegistry.
-
-* Smart merging.
-
-  Changes will never be merged more than once, conflicts will be
-  minimized, and identical changes are dealt with well.
-
-* Vibrant and active community.
-
-  Help with Bazaar is obtained easily, via the mailing list, or the IRC
-  channel.
-
-
-Registration and Feedback
-=========================
+Bazaar directly supports both central version control (like cvs/svn) and
+distributed version control (like git/hg). Developers can organize their
+workspace in whichever way they want on a per project basis including:
+
+* checkouts (like svn)
+* feature branches (like hg)
+* shared working tree (like git).
+
+It also directly supports and encourages a large number of development best
+practices like refactoring and pre-commit regression testing. Users can
+choose between our command line tool and our cross-platform GUI application.
+For further details, see our website at http://bazaar-vcs.org/en.
+
+Feedback
+========
 
 If you encounter any problems with Bazaar, need help understanding it, or would
 like to offer suggestions or feedback, please get in touch with us:
@@ -76,7 +48,7 @@
 * Ask a question through our web support interface, at 
   https://answers.launchpad.net/bzr/
 
-* Report bugs at https://bugs.edge.launchpad.net/bzr/+filebug
+* Report bugs at https://bugs.launchpad.net/bzr/+filebug
 
 * Write to us at bazaar at lists.canonical.com 
   You can join the list at <https://lists.ubuntu.com/mailman/listinfo/bazaar>.
@@ -85,12 +57,8 @@
 
 * Talk to us in irc://irc.ubuntu.com/bzr
 
-* And see http://bazaar-vcs.org/BzrSupport for more.
-
-If you would like to help us improve Bazaar by telling us about yourself and
-what we could do better, please register and complete the online survey here:
-http://www.surveymonkey.com/s.aspx?sm=L94RvLswhKdktrxiHWiX3g_3d_3d.  
-Registration is completely optional. 
-
-Enjoy,
+Our mission is to make a version control tool that developers LOVE to use
+and that casual contributors feel confident with. Please let us know how
+we're going.
+
 The Bazaar Team

=== modified file 'bzrlib/btree_index.py'
--- a/bzrlib/btree_index.py	2009-09-22 02:18:24 +0000
+++ b/bzrlib/btree_index.py	2009-10-13 05:20:50 +0000
@@ -636,7 +636,7 @@
     memory except when very large walks are done.
     """
 
-    def __init__(self, transport, name, size):
+    def __init__(self, transport, name, size, unlimited_cache=False):
         """Create a B+Tree index object on the index name.
 
         :param transport: The transport to read data for the index from.
@@ -646,6 +646,9 @@
             the initial read (to read the root node header) can be done
             without over-reading even on empty indices, and on small indices
             allows single-IO to read the entire index.
+        :param unlimited_cache: If set to True, then instead of using an
+            LRUCache with size _NODE_CACHE_SIZE, we will use a dict and always
+            cache all leaf nodes.
         """
         self._transport = transport
         self._name = name
@@ -655,12 +658,15 @@
         self._root_node = None
         # Default max size is 100,000 leave values
         self._leaf_value_cache = None # lru_cache.LRUCache(100*1000)
-        self._leaf_node_cache = lru_cache.LRUCache(_NODE_CACHE_SIZE)
-        # We could limit this, but even a 300k record btree has only 3k leaf
-        # nodes, and only 20 internal nodes. So the default of 100 nodes in an
-        # LRU would mean we always cache everything anyway, no need to pay the
-        # overhead of LRU
-        self._internal_node_cache = fifo_cache.FIFOCache(100)
+        if unlimited_cache:
+            self._leaf_node_cache = {}
+            self._internal_node_cache = {}
+        else:
+            self._leaf_node_cache = lru_cache.LRUCache(_NODE_CACHE_SIZE)
+            # We use a FIFO here just to prevent possible blowout. However, a
+            # 300k record btree has only 3k leaf nodes, and only 20 internal
+            # nodes. A value of 100 scales to ~100*100*100 = 1M records.
+            self._internal_node_cache = fifo_cache.FIFOCache(100)
         self._key_count = None
         self._row_lengths = None
         self._row_offsets = None # Start of each row, [-1] is the end
@@ -698,9 +704,9 @@
                 if start_of_leaves is None:
                     start_of_leaves = self._row_offsets[-2]
                 if node_pos < start_of_leaves:
-                    self._internal_node_cache.add(node_pos, node)
+                    self._internal_node_cache[node_pos] = node
                 else:
-                    self._leaf_node_cache.add(node_pos, node)
+                    self._leaf_node_cache[node_pos] = node
             found[node_pos] = node
         return found
 

=== modified file 'bzrlib/index.py'
--- a/bzrlib/index.py	2009-10-08 04:35:01 +0000
+++ b/bzrlib/index.py	2009-10-13 05:20:50 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008 Canonical Ltd
+# Copyright (C) 2007, 2008, 2009 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
@@ -368,7 +368,7 @@
     suitable for production use. :XXX
     """
 
-    def __init__(self, transport, name, size):
+    def __init__(self, transport, name, size, unlimited_cache=False):
         """Open an index called name on transport.
 
         :param transport: A bzrlib.transport.Transport.

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2009-09-19 01:33:10 +0000
+++ b/bzrlib/osutils.py	2009-10-13 05:20:50 +0000
@@ -1132,7 +1132,14 @@
     bit_iter = iter(rel.split('/'))
     for bit in bit_iter:
         lbit = bit.lower()
-        for look in _listdir(current):
+        try:
+            next_entries = _listdir(current)
+        except OSError: # enoent, eperm, etc
+            # We can't find this in the filesystem, so just append the
+            # remaining bits.
+            current = pathjoin(current, bit, *list(bit_iter))
+            break
+        for look in next_entries:
             if lbit == look.lower():
                 current = pathjoin(current, look)
                 break
@@ -1142,7 +1149,7 @@
             # the target of a move, for example).
             current = pathjoin(current, bit, *list(bit_iter))
             break
-    return current[len(abs_base)+1:]
+    return current[len(abs_base):].lstrip('/')
 
 # XXX - TODO - we need better detection/integration of case-insensitive
 # file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2009-10-08 08:16:35 +0000
+++ b/bzrlib/remote.py	2009-10-13 05:20:50 +0000
@@ -2434,6 +2434,7 @@
             raise NotImplementedError(self.dont_leave_lock_in_place)
         self._leave_lock = False
 
+    @needs_read_lock
     def get_rev_id(self, revno, history=None):
         if revno == 0:
             return _mod_revision.NULL_REVISION

=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2009-10-08 08:16:35 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2009-10-13 05:20:50 +0000
@@ -225,10 +225,14 @@
         return self.index_name('text', name)
 
     def _replace_index_with_readonly(self, index_type):
+        unlimited_cache = False
+        if index_type == 'chk':
+            unlimited_cache = True
         setattr(self, index_type + '_index',
             self.index_class(self.index_transport,
                 self.index_name(index_type, self.name),
-                self.index_sizes[self.index_offset(index_type)]))
+                self.index_sizes[self.index_offset(index_type)],
+                unlimited_cache=unlimited_cache))
 
 
 class ExistingPack(Pack):
@@ -1675,7 +1679,7 @@
             txt_index = self._make_index(name, '.tix')
             sig_index = self._make_index(name, '.six')
             if self.chk_index is not None:
-                chk_index = self._make_index(name, '.cix')
+                chk_index = self._make_index(name, '.cix', unlimited_cache=True)
             else:
                 chk_index = None
             result = ExistingPack(self._pack_transport, name, rev_index,
@@ -1700,7 +1704,8 @@
             txt_index = self._make_index(name, '.tix', resume=True)
             sig_index = self._make_index(name, '.six', resume=True)
             if self.chk_index is not None:
-                chk_index = self._make_index(name, '.cix', resume=True)
+                chk_index = self._make_index(name, '.cix', resume=True,
+                                             unlimited_cache=True)
             else:
                 chk_index = None
             result = self.resumed_pack_factory(name, rev_index, inv_index,
@@ -1736,7 +1741,7 @@
         return self._index_class(self.transport, 'pack-names', None
                 ).iter_all_entries()
 
-    def _make_index(self, name, suffix, resume=False):
+    def _make_index(self, name, suffix, resume=False, unlimited_cache=False):
         size_offset = self._suffix_offsets[suffix]
         index_name = name + suffix
         if resume:
@@ -1745,7 +1750,8 @@
         else:
             transport = self._index_transport
             index_size = self._names[name][size_offset]
-        return self._index_class(transport, index_name, index_size)
+        return self._index_class(transport, index_name, index_size,
+                                 unlimited_cache=unlimited_cache)
 
     def _max_pack_count(self, total_revisions):
         """Return the maximum number of packs to use for total revisions.

=== modified file 'bzrlib/tests/per_repository_chk/test_supported.py'
--- a/bzrlib/tests/per_repository_chk/test_supported.py	2009-09-08 06:25:26 +0000
+++ b/bzrlib/tests/per_repository_chk/test_supported.py	2009-09-09 18:52:56 +0000
@@ -17,8 +17,10 @@
 """Tests for repositories that support CHK indices."""
 
 from bzrlib import (
+    btree_index,
     errors,
     osutils,
+    repository,
     )
 from bzrlib.versionedfile import VersionedFiles
 from bzrlib.tests.per_repository_chk import TestCaseWithRepositoryCHK
@@ -108,6 +110,39 @@
         finally:
             repo.unlock()
 
+    def test_chk_bytes_are_fully_buffered(self):
+        repo = self.make_repository('.')
+        repo.lock_write()
+        self.addCleanup(repo.unlock)
+        repo.start_write_group()
+        try:
+            sha1, len, _ = repo.chk_bytes.add_lines((None,),
+                None, ["foo\n", "bar\n"], random_id=True)
+            self.assertEqual('4e48e2c9a3d2ca8a708cb0cc545700544efb5021',
+                sha1)
+            self.assertEqual(
+                set([('sha1:4e48e2c9a3d2ca8a708cb0cc545700544efb5021',)]),
+                repo.chk_bytes.keys())
+        except:
+            repo.abort_write_group()
+            raise
+        else:
+            repo.commit_write_group()
+        # This may not always be correct if we change away from BTreeGraphIndex
+        # in the future. But for now, lets check that chk_bytes are fully
+        # buffered
+        index = repo.chk_bytes._index._graph_index._indices[0]
+        self.assertIsInstance(index, btree_index.BTreeGraphIndex)
+        self.assertIs(type(index._leaf_node_cache), dict)
+        # Re-opening the repository should also have a repo with everything
+        # fully buffered
+        repo2 = repository.Repository.open(self.get_url())
+        repo2.lock_read()
+        self.addCleanup(repo2.unlock)
+        index = repo2.chk_bytes._index._graph_index._indices[0]
+        self.assertIsInstance(index, btree_index.BTreeGraphIndex)
+        self.assertIs(type(index._leaf_node_cache), dict)
+
 
 class TestCommitWriteGroupIntegrityCheck(TestCaseWithRepositoryCHK):
     """Tests that commit_write_group prevents various kinds of invalid data

=== modified file 'bzrlib/tests/test_btree_index.py'
--- a/bzrlib/tests/test_btree_index.py	2009-08-13 19:56:26 +0000
+++ b/bzrlib/tests/test_btree_index.py	2009-10-09 15:02:19 +0000
@@ -23,6 +23,8 @@
 from bzrlib import (
     btree_index,
     errors,
+    fifo_cache,
+    lru_cache,
     osutils,
     tests,
     )
@@ -1115,6 +1117,43 @@
         self.assertEqual({}, parent_map)
         self.assertEqual(set([('one',), ('two',)]), missing_keys)
 
+    def test_supports_unlimited_cache(self):
+        builder = btree_index.BTreeBuilder(reference_lists=0, key_elements=1)
+        # We need enough nodes to cause a page split (so we have both an
+        # internal node and a couple leaf nodes. 500 seems to be enough.)
+        nodes = self.make_nodes(500, 1, 0)
+        for node in nodes:
+            builder.add_node(*node)
+        stream = builder.finish()
+        trans = get_transport(self.get_url())
+        size = trans.put_file('index', stream)
+        index = btree_index.BTreeGraphIndex(trans, 'index', size)
+        self.assertEqual(500, index.key_count())
+        # We have an internal node
+        self.assertEqual(2, len(index._row_lengths))
+        # We have at least 2 leaf nodes
+        self.assertTrue(index._row_lengths[-1] >= 2)
+        self.assertIsInstance(index._leaf_node_cache, lru_cache.LRUCache)
+        self.assertEqual(btree_index._NODE_CACHE_SIZE,
+                         index._leaf_node_cache._max_cache)
+        self.assertIsInstance(index._internal_node_cache, fifo_cache.FIFOCache)
+        self.assertEqual(100, index._internal_node_cache._max_cache)
+        # No change if unlimited_cache=False is passed
+        index = btree_index.BTreeGraphIndex(trans, 'index', size,
+                                            unlimited_cache=False)
+        self.assertIsInstance(index._leaf_node_cache, lru_cache.LRUCache)
+        self.assertEqual(btree_index._NODE_CACHE_SIZE,
+                         index._leaf_node_cache._max_cache)
+        self.assertIsInstance(index._internal_node_cache, fifo_cache.FIFOCache)
+        self.assertEqual(100, index._internal_node_cache._max_cache)
+        index = btree_index.BTreeGraphIndex(trans, 'index', size,
+                                            unlimited_cache=True)
+        self.assertIsInstance(index._leaf_node_cache, dict)
+        self.assertIs(type(index._internal_node_cache), dict)
+        # Exercise the lookup code
+        entries = set(index.iter_entries([n[0] for n in nodes]))
+        self.assertEqual(500, len(entries))
+
 
 class TestBTreeNodes(BTreeTestCase):
 

=== modified file 'bzrlib/tests/test_index.py'
--- a/bzrlib/tests/test_index.py	2009-08-13 19:56:26 +0000
+++ b/bzrlib/tests/test_index.py	2009-09-09 18:52:56 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007, 2009 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
@@ -1006,6 +1006,15 @@
         self.assertEqual(set(), missing_keys)
         self.assertEqual(set(), search_keys)
 
+    def test_supports_unlimited_cache(self):
+        builder = GraphIndexBuilder(0, key_elements=1)
+        stream = builder.finish()
+        trans = get_transport(self.get_url())
+        size = trans.put_file('index', stream)
+        # It doesn't matter what unlimited_cache does here, just that it can be
+        # passed
+        index = GraphIndex(trans, 'index', size, unlimited_cache=True)
+
 
 class TestCombinedGraphIndex(TestCaseWithMemoryTransport):
 

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2009-09-19 16:14:10 +0000
+++ b/bzrlib/tests/test_osutils.py	2009-10-13 05:20:50 +0000
@@ -457,6 +457,49 @@
         self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
 
 
+class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
+
+    def assertRelpath(self, expected, base, path):
+        actual = osutils._cicp_canonical_relpath(base, path)
+        self.assertEqual(expected, actual)
+
+    def test_simple(self):
+        self.build_tree(['MixedCaseName'])
+        base = osutils.realpath(self.get_transport('.').local_abspath('.'))
+        self.assertRelpath('MixedCaseName', base, 'mixedcAsename')
+
+    def test_subdir_missing_tail(self):
+        self.build_tree(['MixedCaseParent/', 'MixedCaseParent/a_child'])
+        base = osutils.realpath(self.get_transport('.').local_abspath('.'))
+        self.assertRelpath('MixedCaseParent/a_child', base,
+                           'MixedCaseParent/a_child')
+        self.assertRelpath('MixedCaseParent/a_child', base,
+                           'MixedCaseParent/A_Child')
+        self.assertRelpath('MixedCaseParent/not_child', base,
+                           'MixedCaseParent/not_child')
+
+    def test_at_root_slash(self):
+        # We can't test this on Windows, because it has a 'MIN_ABS_PATHLENGTH'
+        # check...
+        if osutils.MIN_ABS_PATHLENGTH > 1:
+            raise tests.TestSkipped('relpath requires %d chars'
+                                    % osutils.MIN_ABS_PATHLENGTH)
+        self.assertRelpath('foo', '/', '/foo')
+
+    def test_at_root_drive(self):
+        if sys.platform != 'win32':
+            raise tests.TestNotApplicable('we can only test drive-letter relative'
+                                          ' paths on Windows where we have drive'
+                                          ' letters.')
+        # see bug #322807
+        # The specific issue is that when at the root of a drive, 'abspath'
+        # returns "C:/" or just "/". However, the code assumes that abspath
+        # always returns something like "C:/foo" or "/foo" (no trailing slash).
+        self.assertRelpath('foo', 'C:/', 'C:/foo')
+        self.assertRelpath('foo', 'X:/', 'X:/foo')
+        self.assertRelpath('foo', 'X:/', 'X://foo')
+
+
 class TestPumpFile(tests.TestCase):
     """Test pumpfile method."""
 

=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py	2009-09-24 05:31:23 +0000
+++ b/bzrlib/tests/test_remote.py	2009-10-13 05:20:50 +0000
@@ -2201,6 +2201,26 @@
             repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
         self.assertFinished(client)
 
+    def test_branch_fallback_locking(self):
+        """RemoteBranch.get_rev_id takes a read lock, and tries to call the
+        get_rev_id_for_revno verb.  If the verb is unknown the VFS fallback
+        will be invoked, which will fail if the repo is unlocked.
+        """
+        self.setup_smart_server_with_call_log()
+        tree = self.make_branch_and_memory_tree('.')
+        tree.lock_write()
+        rev1 = tree.commit('First')
+        rev2 = tree.commit('Second')
+        tree.unlock()
+        branch = tree.branch
+        self.assertFalse(branch.is_locked())
+        self.reset_smart_call_log()
+        verb = 'Repository.get_rev_id_for_revno'
+        self.disable_verb(verb)
+        self.assertEqual(rev1, branch.get_rev_id(1))
+        self.assertLength(1, [call for call in self.hpss_calls if
+                              call.call.method == verb])
+
 
 class TestRepositoryIsShared(TestRemoteRepository):
 

=== modified file 'doc/developers/releasing.txt'
--- a/doc/developers/releasing.txt	2009-09-16 08:59:26 +0000
+++ b/doc/developers/releasing.txt	2009-10-13 05:20:50 +0000
@@ -212,9 +212,20 @@
 we have a releasable product.  The next step is to make it generally
 available to the world.
 
-#. Link from http://bazaar-vcs.org/Download to the tarball and signature.
-
-#. Announce on the `Bazaar home page <http://bazaar-vcs.org/>`_.
+go to the release
+
+#. Within that release, upload the source tarball and zipfile and the GPG
+   signature.  Or, if you prefer, use the
+   ``tools/packaging/lp-upload-release`` script to do this.
+
+#. Link from http://bazaar-vcs.org/SourceDownloads to the tarball and
+   signature.
+
+#. Announce on the `Bazaar website <http://bazaar-vcs.org/>`_.
+   This page is edited via the lp:bzr-website branch. (Changes
+   pushed to this branch are refreshed by a cron job on escudero.)
+
+#. Announce on the `Bazaar wiki <http://bazaar-vcs.org/Welcome>`_.
 
 #. Check that the documentation for this release is available in
    <http://doc.bazaar-vcs.org>.  It should be automatically build when the

=== modified file 'doc/en/upgrade-guide/data_migration.txt'
--- a/doc/en/upgrade-guide/data_migration.txt	2009-09-09 13:34:08 +0000
+++ b/doc/en/upgrade-guide/data_migration.txt	2009-10-02 18:12:29 +0000
@@ -30,7 +30,7 @@
 * **upgrade** - migrate data to a different format.
 
 **reconcile** is rarely needed but it's good practice to run **check**
-before and after runing **upgrade**.
+before and after running **upgrade**.
 
 For detailed help on these commands, see the `Bazaar User Reference`_.
 
@@ -40,7 +40,7 @@
 Communicating with your community
 ---------------------------------
 
-To enable a smooth transistion to the new format, you should:
+To enable a smooth transition to the new format, you should:
 
 1. Make one person responsible for migrating the trunk.
 
@@ -97,22 +97,54 @@
 Migrating branches on Launchpad
 -------------------------------
 
+You have two options for upgrading your Launchpad branches.  You can either
+upgrade them remotely or you can upgrade them locally and push the migrated
+branch to Launchpad.  We recommend the latter.  Upgrading remotely currently
+requires a fast, rock solid network connection to the Launchpad servers, and
+any interruption in that connection can leave you with a partially upgraded
+branch.  The instructions below are the safest and often fastest way to
+upgrade your Launchpad branches.
+
 To allow isolation between public and private branches, Launchpad
 uses stacked branches rather than shared repositories as the core
 technology for efficient branch storage. The process for migrating
 to a new format for projects using Launchpad code hosting is therefore
 different to migrating a personal or in-house project.
 
+In Launchpad, a project can define a *development series* and associate a
+branch with that series.  The branch then becomes the *focus of development*
+and gets special treatment and a shortcut url.  By default, if anybody
+branches your project's focus of development and pushes changes back to
+Launchpad, their branch will be stacked on your development focus branch.
+Also, branches can be associated with other Launchpad artifacts such as bugs
+and merge proposals.  All of these things mean that upgrading your focus of
+development branch is trickier.
+
 Here are the steps to follow:
 
-1. The nominated person grabs a copy of trunk and does the migration.
+1. The nominated person grabs a copy of trunk and does the migration locally.
 
 2. On Launchpad, unset the current trunk from being the development focus.
    (This *must* be done or the following step won't work as expected.)
 
-3. Push the migrated trunk to Launchpad.
-
-4. Set it as the development focus.
+   1. Go to your project's home page on Launchpad
+
+   2. Look for "XXX is the current focus of development"
+
+   3. Click on the edit (pencil) icon
+
+   4. Click on "Change details" in the portlet on the right
+
+   5. Scroll down to where it says "Branch: (Optional)"
+
+   6. Blank out this input field and click "Change"
+
+3. Push the migrated trunk to Launchpad.  See below if you want your
+   new migrated development focus branch to have the same name as your old
+   pre-migration development focus branch.
+
+4. Set it as the development focus.  Follow the instructions above but at step
+   5, enter the name of the newly migrated branch you just pushed.
 
 5. Ask users subscribed to the old trunk to subscribe to the new one.
 
@@ -124,6 +156,20 @@
 You are now ready to tell your community that the new trunk is available
 and to give them instructions on migrating any local branches they have.
 
+If you want your new migrated development focus branch to have the same name
+as your old pre-migration branch, you need to do a few extra things before you
+establish the new development focus.
+
+1. Rename your old pre-migration branch; use something like
+   **foo-obsolete-do-not-use**.  You will really not want to delete this
+   because there will be artifacts (bugs, merge proposals, etc.) associated
+   with it.
+
+2. Rename the new migrated branch to the pre-migration branch's old name.
+
+3. Re-establish the development focus branch using the new migrated branch's
+   new name (i.e. the old pre-migration branch's original name).
+
 
 Migrating local branches after a central trunk has migrated
 -----------------------------------------------------------




More information about the bazaar-commits mailing list