Rev 3866: (jam) Re-order pack files during fetch. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Nov 27 09:35:10 GMT 2008


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

------------------------------------------------------------
revno: 3866
revision-id: pqm at pqm.ubuntu.com-20081127093507-qn31zeicepc4g6li
parent: pqm at pqm.ubuntu.com-20081127082650-adzra5ok5apue0gl
parent: andrew.bennetts at canonical.com-20081127090045-qxatg46jzwrbh2lg
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2008-11-27 09:35:07 +0000
message:
  (jam) Re-order pack files during fetch.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
  bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
    ------------------------------------------------------------
    revno: 3824.2.8
    revision-id: andrew.bennetts at canonical.com-20081127090045-qxatg46jzwrbh2lg
    parent: andrew.bennetts at canonical.com-20081127071700-st1cn64rvo5784t4
    parent: pqm at pqm.ubuntu.com-20081127082650-adzra5ok5apue0gl
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: pack_ordering
    timestamp: Thu 2008-11-27 20:00:45 +1100
    message:
      Merge bzr.dev, resolving NEWS conflict.  (And improve the wording of the new NEWS entry too.)
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
      bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
      bzrlib/mutabletree.py          mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/tests/branch_implementations/test_sprout.py test_sprout.py-20070521151739-b8t8p7axw1h966ws-1
      bzrlib/tests/commands/test_commit.py test_commit.py-20070913161801-ydrx2k5gmv7k7eiu-1
      bzrlib/tests/test_fetch.py     testfetch.py-20050825090644-f73e07e7dfb1765a
      bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
      bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
      bzrlib/tests/workingtree_implementations/test_parents.py test_set_parents.py-20060807231740-yicmnlci1mj8smu1-1
    ------------------------------------------------------------
    revno: 3824.2.7
    revision-id: andrew.bennetts at canonical.com-20081127071700-st1cn64rvo5784t4
    parent: andrew.bennetts at canonical.com-20081127071343-evmtit8agpher2ga
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: pack_ordering
    timestamp: Thu 2008-11-27 18:17:00 +1100
    message:
      Add NEWS entry.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3824.2.6
    revision-id: andrew.bennetts at canonical.com-20081127071343-evmtit8agpher2ga
    parent: andrew.bennetts at canonical.com-20081127071255-23b0p350ti1nfwrd
    parent: pqm at pqm.ubuntu.com-20081127052415-9hb2n5pppt7imsb3
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: pack_ordering
    timestamp: Thu 2008-11-27 18:13:43 +1100
    message:
      Merge bzr.dev.
    added:
      bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
      bzrlib/tests/test_foreign.py   test_foreign.py-20081125004048-ywb901edgp9lluxo-1
      contrib/convert_to_1.9.py      convert_to_dev2.py-20081014130524-z1ydl3mq9b4ehlvv-1
      tools/win32/build_release.py   build_release.py-20081105204355-2ghh5cv01v1x4rzz-1
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
      bzrlib/_readdir_pyx.pyx        readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/branchbuilder.py        branchbuilder.py-20070427022007-zlxpqz2lannhk6y8-1
      bzrlib/btree_index.py          index.py-20080624222253-p0x5f92uyh5hw734-7
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/commit.py               commit.py-20050511101309-79ec1a0168e0e825
      bzrlib/config.py               config.py-20051011043216-070c74f4e9e338e8
      bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
      bzrlib/help_topics/__init__.py help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
      bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
      bzrlib/lockable_files.py       control_files.py-20051111201905-bb88546e799d669f
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/msgeditor.py            msgeditor.py-20050901111708-ef6d8de98f5d8f2f
      bzrlib/option.py               option.py-20051014052914-661fb36e76e7362f
      bzrlib/plugin.py               plugin.py-20050622060424-829b654519533d69
      bzrlib/plugins/launchpad/account.py account.py-20071011033320-50y6vfftywf4yllw-1
      bzrlib/plugins/launchpad/lp_directory.py lp_indirect.py-20070126012204-de5rugwlt22c7u7e-1
      bzrlib/plugins/launchpad/test_account.py test_account.py-20071011033320-50y6vfftywf4yllw-2
      bzrlib/python-compat.h         pythoncompat.h-20080924041409-9kvi0fgtuuqp743j-1
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/repofmt/weaverepo.py    presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/shelf_ui.py             shelver.py-20081005210102-33worgzwrtdw0yrm-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/test_commit.py test_commit.py-20060212094538-ae88fc861d969db0
      bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
      bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
      bzrlib/tests/interrepository_implementations/test_fetch.py test_fetch.py-20080425213627-j60cjh782ufm83ry-1
      bzrlib/tests/per_repository/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
      bzrlib/tests/per_repository/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/per_repository/test_revision.py testrevprops.py-20051013073044-92bc3c68302ce1bf
      bzrlib/tests/per_repository/test_write_group.py test_write_group.py-20070716105516-89n34xtogq5frn0m-1
      bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
      bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
      bzrlib/tests/test_log.py       testlog.py-20050728115707-1a514809d7d49309
      bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
      bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
      bzrlib/tests/test_permissions.py test_permissions.py-20051215004520-ccf475789c80e80c
      bzrlib/tests/test_plugins.py   plugins.py-20050622075746-32002b55e5e943e9
      bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_revision.py  testrevision.py-20050804210559-46f5e1eb67b01289
      bzrlib/tests/test_sftp_transport.py testsftp.py-20051027032739-247570325fec7e7e
      bzrlib/tests/test_shelf_ui.py  test_shelf_ui.py-20081027155203-wtcuazg85wp9u4fv-1
      bzrlib/tests/test_transport_implementations.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
      bzrlib/trace.py                trace.py-20050309040759-c8ed824bdcd4748a
      bzrlib/transport/__init__.py   transport.py-20050711165921-4978aa7ce1285ad5
      bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
      bzrlib/transport/remote.py     ssh.py-20060608202016-c25gvf1ob7ypbus6-1
      bzrlib/transport/sftp.py       sftp.py-20051019050329-ab48ce71b7e32dfe
      bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 3824.2.5
    revision-id: andrew.bennetts at canonical.com-20081127071255-23b0p350ti1nfwrd
    parent: john at arbash-meinel.com-20081110014549-fz0659nun3ex2bav
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: pack_ordering
    timestamp: Thu 2008-11-27 18:12:55 +1100
    message:
      Minor tweaks to comments etc.
    modified:
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
    ------------------------------------------------------------
    revno: 3824.2.4
    revision-id: john at arbash-meinel.com-20081110014549-fz0659nun3ex2bav
    parent: john at arbash-meinel.com-20081110001740-w1fd7io9lld9cvzf
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: pack_ordering
    timestamp: Sun 2008-11-09 19:45:49 -0600
    message:
      Add a test that ensures the pack ordering changes as part of calling .pack()
    modified:
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
    ------------------------------------------------------------
    revno: 3824.2.3
    revision-id: john at arbash-meinel.com-20081110001740-w1fd7io9lld9cvzf
    parent: john at arbash-meinel.com-20081109225137-idgt37y6jqlruykl
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: pack_ordering
    timestamp: Sun 2008-11-09 18:17:40 -0600
    message:
      Reorder the packs list after determining what packs
      have the revisions we care about.
      
      This saves us from reading text and inventory indexes that aren't
      likely to have what we need.
    modified:
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
    ------------------------------------------------------------
    revno: 3824.2.2
    revision-id: john at arbash-meinel.com-20081109225137-idgt37y6jqlruykl
    parent: john at arbash-meinel.com-20081109224938-tyh8vgnnsr8j1n0w
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: pack_ordering
    timestamp: Sun 2008-11-09 16:51:37 -0600
    message:
      Switch to using using pack.access_tuple()
    modified:
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
    ------------------------------------------------------------
    revno: 3824.2.1
    revision-id: john at arbash-meinel.com-20081109224938-tyh8vgnnsr8j1n0w
    parent: pqm at pqm.ubuntu.com-20081107151945-hwdojxj8yafpk350
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: pack_ordering
    timestamp: Sun 2008-11-09 16:49:38 -0600
    message:
      Clean up some pack object functions.
      Nobody was using _make_index_map, get rid of it
      Only Packer was using PackCollection._packs_list_to_index_map and
      _index_contents, so make them attributes of Packer instead of
      PackCollection.
    modified:
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
=== modified file 'NEWS'
--- a/NEWS	2008-11-27 08:26:50 +0000
+++ b/NEWS	2008-11-27 09:00:45 +0000
@@ -24,6 +24,12 @@
       history just to set the last revision info.
       (Andrew Bennetts, John Arbash Meinel)
 
+    * Search index files corresponding to pack files we've already used
+      before searching others, because they are more likely to have the
+      keys we're looking for.  This reduces the number of iix and tix
+      files accessed when pushing 1 new revision, for instance.
+      (John Arbash Meinel)
+
     * The generic fetch code can once again copy revisions and signatures
       without extracting them completely to fulltexts and then serializing
       them back down into byte strings. This is a significant performance

=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2008-11-27 07:25:52 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2008-11-27 09:00:45 +0000
@@ -581,6 +581,35 @@
     def _extra_init(self):
         """A template hook to allow extending the constructor trivially."""
 
+    def _pack_map_and_index_list(self, index_attribute):
+        """Convert a list of packs to an index pack map and index list.
+
+        :param index_attribute: The attribute that the desired index is found
+            on.
+        :return: A tuple (map, list) where map contains the dict from
+            index:pack_tuple, and list contains the indices in the preferred
+            access order.
+        """
+        indices = []
+        pack_map = {}
+        for pack_obj in self.packs:
+            index = getattr(pack_obj, index_attribute)
+            indices.append(index)
+            pack_map[index] = pack_obj
+        return pack_map, indices
+
+    def _index_contents(self, indices, key_filter=None):
+        """Get an iterable of the index contents from a pack_map.
+
+        :param indices: The list of indices to query
+        :param key_filter: An optional filter to limit the keys returned.
+        """
+        all_index = CombinedGraphIndex(indices)
+        if key_filter is None:
+            return all_index.iter_all_entries()
+        else:
+            return all_index.iter_entries(key_filter)
+
     def pack(self, pb=None):
         """Create a new pack by reading data from other packs.
 
@@ -625,6 +654,40 @@
         return NewPack(self._pack_collection, upload_suffix=self.suffix,
                 file_mode=self._pack_collection.repo.bzrdir._get_file_mode())
 
+    def _update_pack_order(self, entries, index_to_pack_map):
+        """Determine how we want our packs to be ordered.
+
+        This changes the sort order of the self.packs list so that packs unused
+        by 'entries' will be at the end of the list, so that future requests
+        can avoid probing them.  Used packs will be at the front of the
+        self.packs list, in the order of their first use in 'entries'.
+
+        :param entries: A list of (index, ...) tuples
+        :param index_to_pack_map: A mapping from index objects to pack objects.
+        """
+        packs = []
+        seen_indexes = set()
+        for entry in entries:
+            index = entry[0]
+            if index not in seen_indexes:
+                packs.append(index_to_pack_map[index])
+                seen_indexes.add(index)
+        if len(packs) == len(self.packs):
+            if 'pack' in debug.debug_flags:
+                mutter('Not changing pack list, all packs used.')
+            return
+        seen_packs = set(packs)
+        for pack in self.packs:
+            if pack not in seen_packs:
+                packs.append(pack)
+                seen_packs.add(pack)
+        if 'pack' in debug.debug_flags:
+            old_names = [p.access_tuple()[1] for p in self.packs]
+            new_names = [p.access_tuple()[1] for p in packs]
+            mutter('Reordering packs\nfrom: %s\n  to: %s',
+                   old_names, new_names)
+        self.packs = packs
+
     def _copy_revision_texts(self):
         """Copy revision data to the new pack."""
         # select revisions
@@ -633,9 +696,11 @@
         else:
             revision_keys = None
         # select revision keys
-        revision_index_map = self._pack_collection._packs_list_to_pack_map_and_index_list(
-            self.packs, 'revision_index')[0]
-        revision_nodes = self._pack_collection._index_contents(revision_index_map, revision_keys)
+        revision_index_map, revision_indices = self._pack_map_and_index_list(
+            'revision_index')
+        revision_nodes = self._index_contents(revision_indices, revision_keys)
+        revision_nodes = list(revision_nodes)
+        self._update_pack_order(revision_nodes, revision_index_map)
         # copy revision keys and adjust values
         self.pb.update("Copying revision texts", 1)
         total_items, readv_group_iter = self._revision_node_readv(revision_nodes)
@@ -661,9 +726,9 @@
         # querying for keys here could introduce a bug where an inventory item
         # is missed, so do not change it to query separately without cross
         # checking like the text key check below.
-        inventory_index_map = self._pack_collection._packs_list_to_pack_map_and_index_list(
-            self.packs, 'inventory_index')[0]
-        inv_nodes = self._pack_collection._index_contents(inventory_index_map, inv_keys)
+        inventory_index_map, inventory_indices = self._pack_map_and_index_list(
+            'inventory_index')
+        inv_nodes = self._index_contents(inventory_indices, inv_keys)
         # copy inventory keys and adjust values
         # XXX: Should be a helper function to allow different inv representation
         # at this point.
@@ -736,9 +801,9 @@
         self._copy_text_texts()
         # select signature keys
         signature_filter = self._revision_keys # same keyspace
-        signature_index_map = self._pack_collection._packs_list_to_pack_map_and_index_list(
-            self.packs, 'signature_index')[0]
-        signature_nodes = self._pack_collection._index_contents(signature_index_map,
+        signature_index_map, signature_indices = self._pack_map_and_index_list(
+            'signature_index')
+        signature_nodes = self._index_contents(signature_indices,
             signature_filter)
         # copy signature keys and adjust values
         self.pb.update("Copying signature texts", 4)
@@ -794,7 +859,8 @@
             # linear scan up the pack
             pack_readv_requests.sort()
             # copy the data
-            transport, path = index_map[index]
+            pack_obj = index_map[index]
+            transport, path = pack_obj.access_tuple()
             reader = pack.make_readv_reader(transport, path,
                 [offset[0:2] for offset in pack_readv_requests])
             for (names, read_func), (_1, _2, (key, eol_flag)) in \
@@ -838,7 +904,8 @@
         pb.update("Copied record", record_index, total_items)
         for index, readv_vector, node_vector in readv_group_iter:
             # copy the data
-            transport, path = index_map[index]
+            pack_obj = index_map[index]
+            transport, path = pack_obj.access_tuple()
             reader = pack.make_readv_reader(transport, path, readv_vector)
             for (names, read_func), (key, eol_flag, references) in \
                 izip(reader.iter_records(), node_vector):
@@ -862,9 +929,9 @@
                 record_index += 1
 
     def _get_text_nodes(self):
-        text_index_map = self._pack_collection._packs_list_to_pack_map_and_index_list(
-            self.packs, 'text_index')[0]
-        return text_index_map, self._pack_collection._index_contents(text_index_map,
+        text_index_map, text_indices = self._pack_map_and_index_list(
+            'text_index')
+        return text_index_map, self._index_contents(text_indices,
             self._text_filter)
 
     def _least_readv_node_readv(self, nodes):
@@ -1215,9 +1282,6 @@
             return False
         # XXX: the following may want to be a class, to pack with a given
         # policy.
-        mutter('Auto-packing repository %s, which has %d pack files, '
-            'containing %d revisions into %d packs.', self, total_packs,
-            total_revisions, self._max_pack_count(total_revisions))
         # determine which packs need changing
         pack_distribution = self.pack_distribution(total_revisions)
         existing_packs = []
@@ -1238,6 +1302,13 @@
             existing_packs.append((revision_count, pack))
         pack_operations = self.plan_autopack_combinations(
             existing_packs, pack_distribution)
+        num_new_packs = len(pack_operations)
+        num_old_packs = sum([len(po[1]) for po in pack_operations])
+        num_revs_affected = sum([po[0] for po in pack_operations])
+        mutter('Auto-packing repository %s, which has %d pack files, '
+            'containing %d revisions. Packing %d files into %d affecting %d'
+            ' revisions', self, total_packs, total_revisions, num_old_packs,
+            num_new_packs, num_revs_affected)
         self._execute_pack_operations(pack_operations)
         return True
 
@@ -1511,57 +1582,6 @@
         self._packs_by_name = {}
         self._packs_at_load = None
 
-    def _make_index_map(self, index_suffix):
-        """Return information on existing indices.
-
-        :param suffix: Index suffix added to pack name.
-
-        :returns: (pack_map, indices) where indices is a list of GraphIndex 
-        objects, and pack_map is a mapping from those objects to the 
-        pack tuple they describe.
-        """
-        # TODO: stop using this; it creates new indices unnecessarily.
-        self.ensure_loaded()
-        suffix_map = {'.rix': 'revision_index',
-            '.six': 'signature_index',
-            '.iix': 'inventory_index',
-            '.tix': 'text_index',
-        }
-        return self._packs_list_to_pack_map_and_index_list(self.all_packs(),
-            suffix_map[index_suffix])
-
-    def _packs_list_to_pack_map_and_index_list(self, packs, index_attribute):
-        """Convert a list of packs to an index pack map and index list.
-
-        :param packs: The packs list to process.
-        :param index_attribute: The attribute that the desired index is found
-            on.
-        :return: A tuple (map, list) where map contains the dict from
-            index:pack_tuple, and lsit contains the indices in the same order
-            as the packs list.
-        """
-        indices = []
-        pack_map = {}
-        for pack in packs:
-            index = getattr(pack, index_attribute)
-            indices.append(index)
-            pack_map[index] = (pack.pack_transport, pack.file_name())
-        return pack_map, indices
-
-    def _index_contents(self, pack_map, key_filter=None):
-        """Get an iterable of the index contents from a pack_map.
-
-        :param pack_map: A map from indices to pack details.
-        :param key_filter: An optional filter to limit the
-            keys returned.
-        """
-        indices = [index for index in pack_map.iterkeys()]
-        all_index = CombinedGraphIndex(indices)
-        if key_filter is None:
-            return all_index.iter_all_entries()
-        else:
-            return all_index.iter_entries(key_filter)
-
     def _unlock_names(self):
         """Release the mutex around the pack-names index."""
         self.repo.control_files.unlock()

=== modified file 'bzrlib/tests/test_repository.py'
--- a/bzrlib/tests/test_repository.py	2008-11-27 07:25:52 +0000
+++ b/bzrlib/tests/test_repository.py	2008-11-27 09:00:45 +0000
@@ -1055,8 +1055,36 @@
 class TestPacker(TestCaseWithTransport):
     """Tests for the packs repository Packer class."""
 
-    # To date, this class has been factored out and nothing new added to it;
-    # thus there are not yet any tests.
+    def test_pack_optimizes_pack_order(self):
+        builder = self.make_branch_builder('.')
+        builder.start_series()
+        builder.build_snapshot('A', None, [
+            ('add', ('', 'root-id', 'directory', None)),
+            ('add', ('f', 'f-id', 'file', 'content\n'))])
+        builder.build_snapshot('B', ['A'],
+            [('modify', ('f-id', 'new-content\n'))])
+        builder.build_snapshot('C', ['B'],
+            [('modify', ('f-id', 'third-content\n'))])
+        builder.build_snapshot('D', ['C'],
+            [('modify', ('f-id', 'fourth-content\n'))])
+        b = builder.get_branch()
+        b.lock_read()
+        builder.finish_series()
+        self.addCleanup(b.unlock)
+        # At this point, we should have 4 pack files available
+        # Because of how they were built, they correspond to
+        # ['D', 'C', 'B', 'A']
+        packs = b.repository._pack_collection.packs
+        packer = pack_repo.Packer(b.repository._pack_collection,
+                                  packs, 'testing',
+                                  revision_ids=['B', 'C'])
+        # Now, when we are copying the B & C revisions, their pack files should
+        # be moved to the front of the stack
+        # The new ordering moves B & C to the front of the .packs attribute,
+        # and leaves the others in the original order.
+        new_packs = [packs[1], packs[2], packs[0], packs[3]]
+        new_pack = packer.pack()
+        self.assertEqual(new_packs, packer.packs)
 
 
 class TestOptimisingPacker(TestCaseWithTransport):




More information about the bazaar-commits mailing list