示例#1
0
 def test_tree_reference(self):
     s_v5 = bzrlib.xml5.serializer_v5
     s_v6 = bzrlib.xml6.serializer_v6
     s_v7 = xml7.serializer_v7
     inv = Inventory('tree-root-321', revision_id='rev-outer')
     inv.root.revision = 'root-rev'
     inv.add(
         inventory.TreeReference('nested-id', 'nested', 'tree-root-321',
                                 'rev-outer', 'rev-inner'))
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v5.write_inventory_to_string, inv)
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v6.write_inventory_to_string, inv)
     txt = s_v7.write_inventory_to_string(inv)
     lines = s_v7.write_inventory_to_lines(inv)
     self.assertEqual(bzrlib.osutils.split_lines(txt), lines)
     inv2 = s_v7.read_inventory_from_string(txt)
     self.assertEqual('tree-root-321', inv2['nested-id'].parent_id)
     self.assertEqual('rev-outer', inv2['nested-id'].revision)
     self.assertEqual('rev-inner', inv2['nested-id'].reference_revision)
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v6.read_inventory_from_string,
                       txt.replace('format="7"', 'format="6"'))
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v5.read_inventory_from_string,
                       txt.replace('format="7"', 'format="5"'))
示例#2
0
 def test_roundtrip_inventory_v7(self):
     inv = self.get_sample_inventory()
     inv.add(
         inventory.TreeReference('nested-id', 'nested', 'tree-root-321',
                                 'rev_outer', 'rev_inner'))
     txt = xml7.serializer_v7.write_inventory_to_string(inv)
     lines = xml7.serializer_v7.write_inventory_to_lines(inv)
     self.assertEqual(bzrlib.osutils.split_lines(txt), lines)
     self.assertEqualDiff(_expected_inv_v7, txt)
     inv2 = xml7.serializer_v7.read_inventory_from_string(txt)
     self.assertEqual(5, len(inv2))
     for path, ie in inv.iter_entries():
         self.assertEqual(ie, inv2[ie.file_id])
示例#3
0
 def _unpack_entry(self, elt):
     kind = elt.tag
     if not kind in self.supported_kinds:
         raise AssertionError('unsupported entry kind %s' % kind)
     if kind == 'tree-reference':
         file_id = elt.attrib['file_id']
         name = elt.attrib['name']
         parent_id = elt.attrib['parent_id']
         revision = elt.get('revision')
         reference_revision = elt.get('reference_revision')
         return inventory.TreeReference(file_id, name, parent_id, revision,
                                        reference_revision)
     else:
         return xml6.Serializer_v6._unpack_entry(self, elt)
示例#4
0
def unpack_inventory_entry(elt, entry_cache=None, return_from_cache=False):
    elt_get = elt.get
    file_id = elt_get('file_id')
    revision = elt_get('revision')
    # Check and see if we have already unpacked this exact entry
    # Some timings for "repo.revision_trees(last_100_revs)"
    #               bzr     mysql
    #   unmodified  4.1s    40.8s
    #   using lru   3.5s
    #   using fifo  2.83s   29.1s
    #   lru._cache  2.8s
    #   dict        2.75s   26.8s
    #   inv.add     2.5s    26.0s
    #   no_copy     2.00s   20.5s
    #   no_c,dict   1.95s   18.0s
    # Note that a cache of 10k nodes is more than sufficient to hold all of
    # the inventory for the last 100 revs for bzr, but not for mysql (20k
    # is enough for mysql, which saves the same 2s as using a dict)

    # Breakdown of mysql using time.clock()
    #   4.1s    2 calls to element.get for file_id, revision_id
    #   4.5s    cache_hit lookup
    #   7.1s    InventoryFile.copy()
    #   2.4s    InventoryDirectory.copy()
    #   0.4s    decoding unique entries
    #   1.6s    decoding entries after FIFO fills up
    #   0.8s    Adding nodes to FIFO (including flushes)
    #   0.1s    cache miss lookups
    # Using an LRU cache
    #   4.1s    2 calls to element.get for file_id, revision_id
    #   9.9s    cache_hit lookup
    #   10.8s   InventoryEntry.copy()
    #   0.3s    cache miss lookus
    #   1.2s    decoding entries
    #   1.0s    adding nodes to LRU
    if entry_cache is not None and revision is not None:
        key = (file_id, revision)
        try:
            # We copy it, because some operations may mutate it
            cached_ie = entry_cache[key]
        except KeyError:
            pass
        else:
            # Only copying directory entries drops us 2.85s => 2.35s
            if return_from_cache:
                if cached_ie.kind == 'directory':
                    return cached_ie.copy()
                return cached_ie
            return cached_ie.copy()

    kind = elt.tag
    if not inventory.InventoryEntry.versionable_kind(kind):
        raise AssertionError('unsupported entry kind %s' % kind)

    file_id = get_utf8_or_ascii(file_id)
    if revision is not None:
        revision = get_utf8_or_ascii(revision)
    parent_id = elt_get('parent_id')
    if parent_id is not None:
        parent_id = get_utf8_or_ascii(parent_id)

    if kind == 'directory':
        ie = inventory.InventoryDirectory(file_id, elt_get('name'), parent_id)
    elif kind == 'file':
        ie = inventory.InventoryFile(file_id, elt_get('name'), parent_id)
        ie.text_sha1 = elt_get('text_sha1')
        if elt_get('executable') == 'yes':
            ie.executable = True
        v = elt_get('text_size')
        ie.text_size = v and int(v)
    elif kind == 'symlink':
        ie = inventory.InventoryLink(file_id, elt_get('name'), parent_id)
        ie.symlink_target = elt_get('symlink_target')
    elif kind == 'tree-reference':
        file_id = elt.attrib['file_id']
        name = elt.attrib['name']
        parent_id = elt.attrib['parent_id']
        revision = elt.get('revision')
        reference_revision = elt.get('reference_revision')
        ie = inventory.TreeReference(file_id, name, parent_id, revision,
                                     reference_revision)
    else:
        raise errors.UnsupportedInventoryKind(kind)
    ie.revision = revision
    if revision is not None and entry_cache is not None:
        # We cache a copy() because callers like to mutate objects, and
        # that would cause the item in cache to mutate as well.
        # This has a small effect on many-inventory performance, because
        # the majority fraction is spent in cache hits, not misses.
        entry_cache[key] = ie.copy()

    return ie