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