~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-11 21:41:24 UTC
  • mto: This revision was merged to the branch mainline in revision 3543.
  • Revision ID: john@arbash-meinel.com-20080711214124-qi09irlj7pd5cuzg
Shortcut the case when one revision is in the ancestry of the other.

At the cost of a heads() check, when one parent supersedes, we don't have to extract
the text for the other. Changes merge time from 3m37s => 3m21s. Using a
CachingParentsProvider would drop the time down to 3m11s.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
    BzrCheckError,
51
51
    BzrError,
52
52
    )
53
 
from bzrlib.symbol_versioning import deprecated_in, deprecated_method
 
53
from bzrlib.symbol_versioning import deprecated_method
54
54
from bzrlib.trace import mutter
55
55
 
56
56
 
176
176
                    candidates[ie.revision] = ie
177
177
        return candidates
178
178
 
179
 
    @deprecated_method(deprecated_in((1, 6, 0)))
180
179
    def get_tar_item(self, root, dp, now, tree):
181
180
        """Get a tarfile item and a file stream for its content."""
182
181
        item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
239
238
        raise BzrError("don't know how to export {%s} of kind %r" %
240
239
                       (self.file_id, self.kind))
241
240
 
242
 
    @deprecated_method(deprecated_in((1, 6, 0)))
243
241
    def put_on_disk(self, dest, dp, tree):
244
242
        """Create a representation of self on disk in the prefix dest.
245
243
        
341
339
                   self.revision))
342
340
 
343
341
    def __eq__(self, other):
344
 
        if other is self:
345
 
            # For the case when objects are cached
346
 
            return True
347
342
        if not isinstance(other, InventoryEntry):
348
343
            return NotImplemented
349
344
 
477
472
 
478
473
    def _check(self, checker, tree_revision_id, tree):
479
474
        """See InventoryEntry._check"""
480
 
        key = (self.file_id, self.revision)
481
 
        if key in checker.checked_texts:
482
 
            prev_sha = checker.checked_texts[key]
 
475
        t = (self.file_id, self.revision)
 
476
        if t in checker.checked_texts:
 
477
            prev_sha = checker.checked_texts[t]
483
478
            if prev_sha != self.text_sha1:
484
479
                raise BzrCheckError(
485
480
                    'mismatched sha1 on {%s} in {%s} (%s != %s) %r' %
494
489
        # We can't check the length, because Weave doesn't store that
495
490
        # information, and the whole point of looking at the weave's
496
491
        # sha1sum is that we don't have to extract the text.
497
 
        if (self.text_sha1 != tree._repository.texts.get_sha1s([key])[key]):
498
 
            raise BzrCheckError('text {%s} version {%s} wrong sha1' % key)
499
 
        checker.checked_texts[key] = self.text_sha1
 
492
        if (self.text_sha1 !=
 
493
            tree._repository.texts.get_sha1s([(self.file_id, self.revision)])[0]):
 
494
            raise BzrCheckError('text {%s} version {%s} wrong sha1' 
 
495
                                % (self.file_id, self.revision))
 
496
        checker.checked_texts[t] = self.text_sha1
500
497
 
501
498
    def copy(self):
502
499
        other = InventoryFile(self.file_id, self.name, self.parent_id)
818
815
                # adds come later
819
816
                continue
820
817
            # Preserve unaltered children of file_id for later reinsertion.
821
 
            file_id_children = getattr(self[file_id], 'children', {})
822
 
            if len(file_id_children):
823
 
                children[file_id] = file_id_children
 
818
            children[file_id] = getattr(self[file_id], 'children', {})
824
819
            # Remove file_id and the unaltered children. If file_id is not
825
820
            # being deleted it will be reinserted back later.
826
821
            self.remove_recursive_id(file_id)
832
827
        for new_path, new_entry in sorted((np, e) for op, np, f, e in
833
828
                                          delta if np is not None):
834
829
            if new_entry.kind == 'directory':
835
 
                # Pop the child which to allow detection of children whose
836
 
                # parents were deleted and which were not reattached to a new
837
 
                # parent.
838
 
                new_entry.children = children.pop(new_entry.file_id, {})
 
830
                new_entry.children = children.get(new_entry.file_id, {})
839
831
            self.add(new_entry)
840
 
        if len(children):
841
 
            # Get the parent id that was deleted
842
 
            parent_id, children = children.popitem()
843
 
            raise errors.InconsistentDelta("<deleted>", parent_id,
844
 
                "The file id was deleted but its children were not deleted.")
845
832
 
846
833
    def _set_root(self, ie):
847
834
        self.root = ie
853
840
        if self.root is None:
854
841
            return Inventory(root_id=None)
855
842
        other = Inventory(entries.next()[1].file_id)
856
 
        other.root.revision = self.root.revision
857
843
        # copy recursively so we know directories will be added before
858
844
        # their children.  There are more efficient ways than this...
859
845
        for path, entry in entries:
1236
1222
    def has_id(self, file_id):
1237
1223
        return (file_id in self._byid)
1238
1224
 
1239
 
    def _make_delta(self, old):
1240
 
        """Make an inventory delta from two inventories."""
1241
 
        old_getter = getattr(old, '_byid', old)
1242
 
        new_getter = self._byid
1243
 
        old_ids = set(old_getter)
1244
 
        new_ids = set(new_getter)
1245
 
        adds = new_ids - old_ids
1246
 
        deletes = old_ids - new_ids
1247
 
        if not adds and not deletes:
1248
 
            common = new_ids
1249
 
        else:
1250
 
            common = old_ids.intersection(new_ids)
1251
 
        delta = []
1252
 
        for file_id in deletes:
1253
 
            delta.append((old.id2path(file_id), None, file_id, None))
1254
 
        for file_id in adds:
1255
 
            delta.append((None, self.id2path(file_id), file_id, self[file_id]))
1256
 
        for file_id in common:
1257
 
            new_ie = new_getter[file_id]
1258
 
            old_ie = old_getter[file_id]
1259
 
            # If xml_serializer returns the cached InventoryEntries (rather
1260
 
            # than always doing .copy()), inlining the 'is' check saves 2.7M
1261
 
            # calls to __eq__.  Under lsprof this saves 20s => 6s.
1262
 
            # It is a minor improvement without lsprof.
1263
 
            if old_ie is new_ie or old_ie == new_ie:
1264
 
                continue
1265
 
            else:
1266
 
                delta.append((old.id2path(file_id), self.id2path(file_id),
1267
 
                              file_id, new_ie))
1268
 
        return delta
1269
 
 
1270
1225
    def remove_recursive_id(self, file_id):
1271
1226
        """Remove file_id, and children, from the inventory.
1272
 
 
 
1227
        
1273
1228
        :param file_id: A file_id to remove.
1274
1229
        """
1275
1230
        to_find_delete = [self._byid[file_id]]