~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: John Arbash Meinel
  • Date: 2009-07-08 14:37:25 UTC
  • mfrom: (4516 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4517.
  • Revision ID: john@arbash-meinel.com-20090708143725-sc9sjy3mz4cxwxzz
Merge bzr.dev 4516

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
# created, but it's not for now.
28
28
ROOT_ID = "TREE_ROOT"
29
29
 
30
 
from copy import deepcopy
31
 
 
32
30
from bzrlib.lazy_import import lazy_import
33
31
lazy_import(globals(), """
34
32
import collections
 
33
import copy
35
34
import os
36
35
import re
37
36
import tarfile
43
42
    generate_ids,
44
43
    osutils,
45
44
    symbol_versioning,
46
 
    workingtree,
47
45
    )
48
46
""")
49
47
 
747
745
            [parent.name for parent in
748
746
             self._iter_file_id_parents(file_id)][:-1]))
749
747
 
750
 
    def iter_entries(self, from_dir=None):
751
 
        """Return (path, entry) pairs, in order by name."""
 
748
    def iter_entries(self, from_dir=None, recursive=True):
 
749
        """Return (path, entry) pairs, in order by name.
 
750
        
 
751
        :param from_dir: if None, start from the root,
 
752
          otherwise start from this directory (either file-id or entry)
 
753
        :param recursive: recurse into directories or not
 
754
        """
752
755
        if from_dir is None:
753
756
            if self.root is None:
754
757
                return
761
764
        # 440ms/663ms (inline/total) to 116ms/116ms
762
765
        children = from_dir.children.items()
763
766
        children.sort()
 
767
        if not recursive:
 
768
            for name, ie in children:
 
769
                yield name, ie
 
770
            return
764
771
        children = collections.deque(children)
765
772
        stack = [(u'', children)]
766
773
        while stack:
1081
1088
    def apply_delta(self, delta):
1082
1089
        """Apply a delta to this inventory.
1083
1090
 
 
1091
        See the inventory developers documentation for the theory behind
 
1092
        inventory deltas.
 
1093
 
1084
1094
        :param delta: A list of changes to apply. After all the changes are
1085
1095
            applied the final inventory must be internally consistent, but it
1086
1096
            is ok to supply changes which, if only half-applied would have an
1183
1193
 
1184
1194
    def _get_mutable_inventory(self):
1185
1195
        """See CommonInventory._get_mutable_inventory."""
1186
 
        return deepcopy(self)
 
1196
        return copy.deepcopy(self)
1187
1197
 
1188
1198
    def __iter__(self):
1189
1199
        """Iterate over all file-ids."""
1461
1471
        self._path_to_fileid_cache = {}
1462
1472
        self._search_key_name = search_key_name
1463
1473
 
 
1474
    def __eq__(self, other):
 
1475
        """Compare two sets by comparing their contents."""
 
1476
        if not isinstance(other, CHKInventory):
 
1477
            return NotImplemented
 
1478
 
 
1479
        this_key = self.id_to_entry.key()
 
1480
        other_key = other.id_to_entry.key()
 
1481
        this_pid_key = self.parent_id_basename_to_file_id.key()
 
1482
        other_pid_key = other.parent_id_basename_to_file_id.key()
 
1483
        if None in (this_key, this_pid_key, other_key, other_pid_key):
 
1484
            return False
 
1485
        return this_key == other_key and this_pid_key == other_pid_key
 
1486
 
1464
1487
    def _entry_to_bytes(self, entry):
1465
1488
        """Serialise entry as a single bytestring.
1466
1489
 
1547
1570
    def _get_mutable_inventory(self):
1548
1571
        """See CommonInventory._get_mutable_inventory."""
1549
1572
        entries = self.iter_entries()
1550
 
        if self.root_id is not None:
1551
 
            entries.next()
1552
 
        inv = Inventory(self.root_id, self.revision_id)
 
1573
        inv = Inventory(None, self.revision_id)
1553
1574
        for path, inv_entry in entries:
1554
 
            inv.add(inv_entry)
 
1575
            inv.add(inv_entry.copy())
1555
1576
        return inv
1556
1577
 
1557
1578
    def create_by_apply_delta(self, inventory_delta, new_revision_id,
1558
1579
        propagate_caches=False):
1559
1580
        """Create a new CHKInventory by applying inventory_delta to this one.
1560
1581
 
 
1582
        See the inventory developers documentation for the theory behind
 
1583
        inventory deltas.
 
1584
 
1561
1585
        :param inventory_delta: The inventory delta to apply. See
1562
1586
            Inventory.apply_delta for details.
1563
1587
        :param new_revision_id: The revision id of the resulting CHKInventory.
1709
1733
        :param maximum_size: The CHKMap node size limit.
1710
1734
        :param search_key_name: The identifier for the search key function
1711
1735
        """
1712
 
        result = CHKInventory(search_key_name)
 
1736
        result = klass(search_key_name)
1713
1737
        result.revision_id = inventory.revision_id
1714
1738
        result.root_id = inventory.root.file_id
1715
 
        search_key_func = chk_map.search_key_registry.get(search_key_name)
1716
 
        result.id_to_entry = chk_map.CHKMap(chk_store, None, search_key_func)
1717
 
        result.id_to_entry._root_node.set_maximum_size(maximum_size)
1718
 
        file_id_delta = []
1719
 
        result.parent_id_basename_to_file_id = chk_map.CHKMap(chk_store,
1720
 
            None, search_key_func)
1721
 
        result.parent_id_basename_to_file_id._root_node.set_maximum_size(
1722
 
            maximum_size)
1723
 
        result.parent_id_basename_to_file_id._root_node._key_width = 2
1724
 
        parent_id_delta = []
 
1739
 
 
1740
        entry_to_bytes = result._entry_to_bytes
 
1741
        parent_id_basename_key = result._parent_id_basename_key
 
1742
        id_to_entry_dict = {}
 
1743
        parent_id_basename_dict = {}
1725
1744
        for path, entry in inventory.iter_entries():
1726
 
            file_id_delta.append((None, (entry.file_id,),
1727
 
                result._entry_to_bytes(entry)))
1728
 
            parent_id_delta.append(
1729
 
                (None, result._parent_id_basename_key(entry),
1730
 
                 entry.file_id))
1731
 
        result.id_to_entry.apply_delta(file_id_delta)
1732
 
        result.parent_id_basename_to_file_id.apply_delta(parent_id_delta)
 
1745
            id_to_entry_dict[(entry.file_id,)] = entry_to_bytes(entry)
 
1746
            p_id_key = parent_id_basename_key(entry)
 
1747
            parent_id_basename_dict[p_id_key] = entry.file_id
 
1748
 
 
1749
        result._populate_from_dicts(chk_store, id_to_entry_dict,
 
1750
            parent_id_basename_dict, maximum_size=maximum_size)
1733
1751
        return result
1734
1752
 
 
1753
    def _populate_from_dicts(self, chk_store, id_to_entry_dict,
 
1754
                             parent_id_basename_dict, maximum_size):
 
1755
        search_key_func = chk_map.search_key_registry.get(self._search_key_name)
 
1756
        root_key = chk_map.CHKMap.from_dict(chk_store, id_to_entry_dict,
 
1757
                   maximum_size=maximum_size, key_width=1,
 
1758
                   search_key_func=search_key_func)
 
1759
        self.id_to_entry = chk_map.CHKMap(chk_store, root_key,
 
1760
                                          search_key_func)
 
1761
        root_key = chk_map.CHKMap.from_dict(chk_store,
 
1762
                   parent_id_basename_dict,
 
1763
                   maximum_size=maximum_size, key_width=2,
 
1764
                   search_key_func=search_key_func)
 
1765
        self.parent_id_basename_to_file_id = chk_map.CHKMap(chk_store,
 
1766
                                                    root_key, search_key_func)
 
1767
 
1735
1768
    def _parent_id_basename_key(self, entry):
1736
1769
        """Create a key for a entry in a parent_id_basename_to_file_id index."""
1737
1770
        if entry.parent_id is not None: