##// END OF EJS Templates
treemanifest: speed up diff by keeping track of dirty nodes...
Martin von Zweigbergk -
r25220:f0fbd88b default
parent child Browse files
Show More
@@ -445,14 +445,17 b' class treemanifest(object):'
445 445 def __init__(self, dir='', text=''):
446 446 self._dir = dir
447 447 self._node = revlog.nullid
448 self._dirty = False
448 449 self._dirs = {}
449 450 # Using _lazymanifest here is a little slower than plain old dicts
450 451 self._files = {}
451 452 self._flags = {}
452 def readsubtree(subdir, subm):
453 raise AssertionError('treemanifest constructor only accepts '
454 'flat manifests')
455 self.parse(text, readsubtree)
453 if text:
454 def readsubtree(subdir, subm):
455 raise AssertionError('treemanifest constructor only accepts '
456 'flat manifests')
457 self.parse(text, readsubtree)
458 self._dirty = True # Mark flat manifest dirty after parsing
456 459
457 460 def _subpath(self, path):
458 461 return self._dir + path
@@ -468,8 +471,8 b' class treemanifest(object):'
468 471 all(m._isempty() for m in self._dirs.values())))
469 472
470 473 def __str__(self):
471 return ('<treemanifest dir=%s, node=%s>' %
472 (self._dir, revlog.hex(self._node)))
474 return ('<treemanifest dir=%s, node=%s, dirty=%s>' %
475 (self._dir, revlog.hex(self._node), self._dirty))
473 476
474 477 def dir(self):
475 478 '''The directory that this tree manifest represents, including a
@@ -480,10 +483,12 b' class treemanifest(object):'
480 483 '''This node of this instance. nullid for unsaved instances. Should
481 484 be updated when the instance is read or written from a revlog.
482 485 '''
486 assert not self._dirty
483 487 return self._node
484 488
485 489 def setnode(self, node):
486 490 self._node = node
491 self._dirty = False
487 492
488 493 def iteritems(self):
489 494 for p, n in sorted(self._dirs.items() + self._files.items()):
@@ -563,6 +568,7 b' class treemanifest(object):'
563 568 del self._files[f]
564 569 if f in self._flags:
565 570 del self._flags[f]
571 self._dirty = True
566 572
567 573 def __setitem__(self, f, n):
568 574 assert n is not None
@@ -573,6 +579,7 b' class treemanifest(object):'
573 579 self._dirs[dir].__setitem__(subpath, n)
574 580 else:
575 581 self._files[f] = n[:21] # to match manifestdict's behavior
582 self._dirty = True
576 583
577 584 def setflag(self, f, flags):
578 585 """Set the flags (symlink, executable) for path f."""
@@ -584,10 +591,12 b' class treemanifest(object):'
584 591 self._dirs[dir].setflag(subpath, flags)
585 592 else:
586 593 self._flags[f] = flags
594 self._dirty = True
587 595
588 596 def copy(self):
589 597 copy = treemanifest(self._dir)
590 598 copy._node = self._node
599 copy._dirty = self._dirty
591 600 for d in self._dirs:
592 601 copy._dirs[d] = self._dirs[d].copy()
593 602 copy._files = dict.copy(self._files)
@@ -598,6 +607,8 b' class treemanifest(object):'
598 607 '''Set of files in this manifest that are not in the other'''
599 608 files = set()
600 609 def _filesnotin(t1, t2):
610 if t1._node == t2._node and not t1._dirty and not t2._dirty:
611 return
601 612 for d, m1 in t1._dirs.iteritems():
602 613 if d in t2._dirs:
603 614 m2 = t2._dirs[d]
@@ -699,6 +710,8 b' class treemanifest(object):'
699 710 if not m._isempty():
700 711 ret._dirs[dir] = m
701 712
713 if not ret._isempty():
714 ret._dirty = True
702 715 return ret
703 716
704 717 def diff(self, m2, clean=False):
@@ -719,6 +732,8 b' class treemanifest(object):'
719 732 result = {}
720 733 emptytree = treemanifest()
721 734 def _diff(t1, t2):
735 if t1._node == t2._node and not t1._dirty and not t2._dirty:
736 return
722 737 for d, m1 in t1._dirs.iteritems():
723 738 m2 = t2._dirs.get(d, emptytree)
724 739 _diff(m1, m2)
@@ -749,13 +764,20 b' class treemanifest(object):'
749 764 if fl == 'd':
750 765 f = f + '/'
751 766 self._dirs[f] = readsubtree(self._subpath(f), n)
752 else:
753 # Use __setitem__ and setflag rather than assigning directly
754 # to _files and _flags, thereby letting us parse flat manifests
755 # as well as tree manifests.
767 elif '/' in f:
768 # This is a flat manifest, so use __setitem__ and setflag rather
769 # than assigning directly to _files and _flags, so we can
770 # assign a path in a subdirectory, and to mark dirty (compared
771 # to nullid).
756 772 self[f] = n
757 773 if fl:
758 774 self.setflag(f, fl)
775 else:
776 # Assigning to _files and _flags avoids marking as dirty,
777 # and should be a little faster.
778 self._files[f] = n
779 if fl:
780 self._flags[f] = fl
759 781
760 782 def text(self, usemanifestv2=False):
761 783 """Get the full data of this manifest as a bytestring."""
General Comments 0
You need to be logged in to leave comments. Login now