~jelmer/brz/tree-reference-fixes

« back to all changes in this revision

Viewing changes to breezy/bzr/inventory.py

  • Committer: Jelmer Vernooij
  • Date: 2018-03-25 12:47:13 UTC
  • mfrom: (6926.1.2 work)
  • Revision ID: jelmer@jelmer.uk-20180325124713-dq64vm9bhch1gjow
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
112
112
    '2325'
113
113
    >>> i.add(InventoryFile('2326', 'wibble.c', '2325'))
114
114
    InventoryFile('2326', 'wibble.c', parent_id='2325', sha1=None, len=None, revision=None)
115
 
    >>> i['2326']
 
115
    >>> i.get_entry('2326')
116
116
    InventoryFile('2326', 'wibble.c', parent_id='2325', sha1=None, len=None, revision=None)
117
117
    >>> for path, entry in i.iter_entries():
118
118
    ...     print path
123
123
    src/hello.c
124
124
    src/wibble
125
125
    src/wibble/wibble.c
126
 
    >>> i.id2path('2326')
 
126
    >>> i.id2path(b'2326')
127
127
    'src/wibble/wibble.c'
128
128
    """
129
129
 
179
179
        # identify candidate head revision ids.
180
180
        for inv in previous_inventories:
181
181
            try:
182
 
                ie = inv[self.file_id]
 
182
                ie = inv.get_entry(self.file_id)
183
183
            except errors.NoSuchId:
184
184
                pass
185
185
            else:
655
655
        """Return as a string the path to file_id.
656
656
 
657
657
        >>> i = Inventory()
658
 
        >>> e = i.add(InventoryDirectory('src-id', 'src', ROOT_ID))
659
 
        >>> e = i.add(InventoryFile('foo-id', 'foo.c', parent_id='src-id'))
660
 
        >>> print i.id2path('foo-id')
 
658
        >>> e = i.add(InventoryDirectory(b'src-id', 'src', ROOT_ID))
 
659
        >>> e = i.add(InventoryFile(b'foo-id', 'foo.c', parent_id='src-id'))
 
660
        >>> print i.id2path(b'foo-id')
661
661
        src/foo.c
662
662
 
663
663
        :raises NoSuchId: If file_id is not present in the inventory.
679
679
                return
680
680
            from_dir = self.root
681
681
            yield '', self.root
682
 
        elif isinstance(from_dir, (str, text_type)):
683
 
            from_dir = self[from_dir]
 
682
        elif isinstance(from_dir, bytes):
 
683
            from_dir = self.get_entry(from_dir)
684
684
 
685
685
        # unrolling the recursive called changed the time from
686
686
        # 440ms/663ms (inline/total) to 116ms/116ms
762
762
                    except errors.NoSuchId:
763
763
                        pass
764
764
                    else:
765
 
                        yield path, self[file_id]
 
765
                        yield path, self.get_entry(file_id)
766
766
                return
767
767
            from_dir = self.root
768
768
            if (specific_file_ids is None or yield_parents or
769
769
                self.root.file_id in specific_file_ids):
770
770
                yield u'', self.root
771
771
        elif isinstance(from_dir, (str, text_type)):
772
 
            from_dir = self[from_dir]
 
772
            from_dir = self.get_entry(from_dir)
773
773
 
774
774
        if specific_file_ids is not None:
775
775
            # TODO: jam 20070302 This could really be done as a loop rather
779
779
            def add_ancestors(file_id):
780
780
                if not byid.has_id(file_id):
781
781
                    return
782
 
                parent_id = byid[file_id].parent_id
 
782
                parent_id = byid.get_entry(file_id).parent_id
783
783
                if parent_id is None:
784
784
                    return
785
785
                if parent_id not in parents:
811
811
 
812
812
    def _make_delta(self, old):
813
813
        """Make an inventory delta from two inventories."""
814
 
        old_ids = set(old)
815
 
        new_ids = set(self)
 
814
        old_ids = set(old.iter_all_ids())
 
815
        new_ids = set(self.iter_all_ids())
816
816
        adds = new_ids - old_ids
817
817
        deletes = old_ids - new_ids
818
818
        common = old_ids.intersection(new_ids)
820
820
        for file_id in deletes:
821
821
            delta.append((old.id2path(file_id), None, file_id, None))
822
822
        for file_id in adds:
823
 
            delta.append((None, self.id2path(file_id), file_id, self[file_id]))
 
823
            delta.append((None, self.id2path(file_id), file_id, self.get_entry(file_id)))
824
824
        for file_id in common:
825
 
            if old[file_id] != self[file_id]:
 
825
            if old.get_entry(file_id) != self.get_entry(file_id):
826
826
                delta.append((old.id2path(file_id), self.id2path(file_id),
827
 
                    file_id, self[file_id]))
 
827
                    file_id, self.get_entry(file_id)))
828
828
        return delta
829
829
 
830
830
    def make_entry(self, kind, name, parent_id, file_id=None):
943
943
    >>> inv = Inventory()
944
944
    >>> inv.add(InventoryFile('123-123', 'hello.c', ROOT_ID))
945
945
    InventoryFile('123-123', 'hello.c', parent_id='TREE_ROOT', sha1=None, len=None, revision=None)
946
 
    >>> inv['123-123'].name
 
946
    >>> inv.get_entry('123-123').name
947
947
    'hello.c'
948
948
 
949
949
    Id's may be looked up from paths:
1046
1046
        for old_path, file_id in sorted(((op, f) for op, np, f, e in delta
1047
1047
                                        if op is not None), reverse=True):
1048
1048
            # Preserve unaltered children of file_id for later reinsertion.
1049
 
            file_id_children = getattr(self[file_id], 'children', {})
 
1049
            file_id_children = getattr(self.get_entry(file_id), 'children', {})
1050
1050
            if len(file_id_children):
1051
1051
                children[file_id] = file_id_children
1052
1052
            if self.id2path(file_id) != old_path:
1113
1113
            other.add(entry.copy())
1114
1114
        return other
1115
1115
 
1116
 
    def __iter__(self):
 
1116
    def iter_all_ids(self):
1117
1117
        """Iterate over all file-ids."""
1118
1118
        return iter(self._byid)
1119
1119
 
1133
1133
        """Returns number of entries."""
1134
1134
        return len(self._byid)
1135
1135
 
1136
 
    def __getitem__(self, file_id):
 
1136
    def get_entry(self, file_id):
1137
1137
        """Return the entry for given file_id.
1138
1138
 
1139
1139
        >>> inv = Inventory()
1140
1140
        >>> inv.add(InventoryFile('123123', 'hello.c', ROOT_ID))
1141
1141
        InventoryFile('123123', 'hello.c', parent_id='TREE_ROOT', sha1=None, len=None, revision=None)
1142
 
        >>> inv['123123'].name
 
1142
        >>> inv.get_entry('123123').name
1143
1143
        'hello.c'
1144
1144
        """
1145
1145
        try:
1152
1152
        return self._byid[file_id].kind
1153
1153
 
1154
1154
    def get_child(self, parent_id, filename):
1155
 
        return self[parent_id].children.get(filename)
 
1155
        return self.get_entry(parent_id).children.get(filename)
1156
1156
 
1157
1157
    def _add_child(self, entry):
1158
1158
        """Add an entry to the inventory, without adding it to its parent"""
1214
1214
        ie = make_entry(kind, parts[-1], parent_id, file_id)
1215
1215
        return self.add(ie)
1216
1216
 
1217
 
    def __delitem__(self, file_id):
 
1217
    def delete(self, file_id):
1218
1218
        """Remove entry by id.
1219
1219
 
1220
1220
        >>> inv = Inventory()
1222
1222
        InventoryFile('123', 'foo.c', parent_id='TREE_ROOT', sha1=None, len=None, revision=None)
1223
1223
        >>> inv.has_id('123')
1224
1224
        True
1225
 
        >>> del inv['123']
 
1225
        >>> inv.delete('123')
1226
1226
        >>> inv.has_id('123')
1227
1227
        False
1228
1228
        """
1229
 
        ie = self[file_id]
 
1229
        ie = self.get_entry(file_id)
1230
1230
        del self._byid[file_id]
1231
1231
        if ie.parent_id is not None:
1232
 
            del self[ie.parent_id].children[ie.name]
 
1232
            del self.get_entry(ie.parent_id).children[ie.name]
1233
1233
 
1234
1234
    def __eq__(self, other):
1235
1235
        """Compare two sets by comparing their contents.
1273
1273
 
1274
1274
    def _make_delta(self, old):
1275
1275
        """Make an inventory delta from two inventories."""
1276
 
        old_getter = getattr(old, '_byid', old)
1277
 
        new_getter = self._byid
1278
 
        old_ids = set(old_getter)
1279
 
        new_ids = set(new_getter)
 
1276
        old_getter = old.get_entry
 
1277
        new_getter = self.get_entry
 
1278
        old_ids = set(old.iter_all_ids())
 
1279
        new_ids = set(self.iter_all_ids())
1280
1280
        adds = new_ids - old_ids
1281
1281
        deletes = old_ids - new_ids
1282
1282
        if not adds and not deletes:
1287
1287
        for file_id in deletes:
1288
1288
            delta.append((old.id2path(file_id), None, file_id, None))
1289
1289
        for file_id in adds:
1290
 
            delta.append((None, self.id2path(file_id), file_id, self[file_id]))
 
1290
            delta.append((None, self.id2path(file_id), file_id, self.get_entry(file_id)))
1291
1291
        for file_id in common:
1292
 
            new_ie = new_getter[file_id]
1293
 
            old_ie = old_getter[file_id]
 
1292
            new_ie = new_getter(file_id)
 
1293
            old_ie = old_getter(file_id)
1294
1294
            # If xml_serializer returns the cached InventoryEntries (rather
1295
1295
            # than always doing .copy()), inlining the 'is' check saves 2.7M
1296
1296
            # calls to __eq__.  Under lsprof this saves 20s => 6s.
1315
1315
            if ie.kind == 'directory':
1316
1316
                to_find_delete.extend(viewvalues(ie.children))
1317
1317
        for file_id in reversed(to_delete):
1318
 
            ie = self[file_id]
 
1318
            ie = self.get_entry(file_id)
1319
1319
            del self._byid[file_id]
1320
1320
        if ie.parent_id is not None:
1321
 
            del self[ie.parent_id].children[ie.name]
 
1321
            del self.get_entry(ie.parent_id).children[ie.name]
1322
1322
        else:
1323
1323
            self.root = None
1324
1324
 
1707
1707
                if old_path is None:
1708
1708
                    old_key = None
1709
1709
                else:
1710
 
                    old_entry = self[file_id]
 
1710
                    old_entry = self.get_entry(file_id)
1711
1711
                    old_key = self._parent_id_basename_key(old_entry)
1712
1712
                if new_path is None:
1713
1713
                    new_key = None
1728
1728
                            new_key, [None, None])[1] = new_value
1729
1729
        # validate that deletes are complete.
1730
1730
        for file_id in deletes:
1731
 
            entry = self[file_id]
 
1731
            entry = self.get_entry(file_id)
1732
1732
            if entry.kind != 'directory':
1733
1733
                continue
1734
1734
            # This loop could potentially be better by using the id_basename
1754
1754
        parents.discard(('', None))
1755
1755
        for parent_path, parent in parents:
1756
1756
            try:
1757
 
                if result[parent].kind != 'directory':
 
1757
                if result.get_entry(parent).kind != 'directory':
1758
1758
                    raise errors.InconsistentDelta(result.id2path(parent), parent,
1759
1759
                        'Not a directory, but given children')
1760
1760
            except errors.NoSuchId:
1880
1880
            parent_id = b''
1881
1881
        return StaticTuple(parent_id, entry.name.encode('utf8')).intern()
1882
1882
 
1883
 
    def __getitem__(self, file_id):
 
1883
    def get_entry(self, file_id):
1884
1884
        """map a single file_id -> InventoryEntry."""
1885
1885
        if file_id is None:
1886
1886
            raise errors.NoSuchId(self, file_id)
1895
1895
            raise errors.NoSuchId(self, file_id)
1896
1896
 
1897
1897
    def _getitems(self, file_ids):
1898
 
        """Similar to __getitem__, but lets you query for multiple.
 
1898
        """Similar to get_entry, but lets you query for multiple.
1899
1899
        
1900
1900
        The returned order is undefined. And currently if an item doesn't
1901
1901
        exist, it isn't included in the output.
1929
1929
        """Yield the parents of file_id up to the root."""
1930
1930
        while file_id is not None:
1931
1931
            try:
1932
 
                ie = self[file_id]
 
1932
                ie = self.get_entry(file_id)
1933
1933
            except KeyError:
1934
1934
                raise errors.NoSuchId(tree=self, file_id=file_id)
1935
1935
            yield ie
1936
1936
            file_id = ie.parent_id
1937
1937
 
1938
 
    def __iter__(self):
 
1938
    def iter_all_ids(self):
1939
1939
        """Iterate over all file-ids."""
1940
1940
        for key, _ in self.id_to_entry.iteritems():
1941
1941
            yield key[-1]
2172
2172
    @property
2173
2173
    def root(self):
2174
2174
        """Get the root entry."""
2175
 
        return self[self.root_id]
 
2175
        return self.get_entry(self.root_id)
2176
2176
 
2177
2177
 
2178
2178
class CHKInventoryDirectory(InventoryDirectory):