##// END OF EJS Templates
changegroup: fix treemanifests on merges...
Martin von Zweigbergk -
r28240:1ac8ce13 default
parent child Browse files
Show More
@@ -553,27 +553,6 b' class headerlessfixup(object):'
553 return d
553 return d
554 return readexactly(self._fh, n)
554 return readexactly(self._fh, n)
555
555
556 def _moddirs(files):
557 """Given a set of modified files, find the list of modified directories.
558
559 This returns a list of (path to changed dir, changed dir) tuples,
560 as that's what the one client needs anyway.
561
562 >>> _moddirs(['a/b/c.py', 'a/b/c.txt', 'a/d/e/f/g.txt', 'i.txt', ])
563 [('/', 'a/'), ('a/', 'b/'), ('a/', 'd/'), ('a/d/', 'e/'), ('a/d/e/', 'f/')]
564
565 """
566 alldirs = set()
567 for f in files:
568 path = f.split('/')[:-1]
569 for i in xrange(len(path) - 1, -1, -1):
570 dn = '/'.join(path[:i])
571 current = dn + '/', path[i] + '/'
572 if current in alldirs:
573 break
574 alldirs.add(current)
575 return sorted(alldirs)
576
577 class cg1packer(object):
556 class cg1packer(object):
578 deltaheader = _CHANGEGROUPV1_DELTA_HEADER
557 deltaheader = _CHANGEGROUPV1_DELTA_HEADER
579 version = '01'
558 version = '01'
@@ -755,7 +734,7 b' class cg1packer(object):'
755 def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs,
734 def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs,
756 mfchangedfiles, fnodes):
735 mfchangedfiles, fnodes):
757 repo = self._repo
736 repo = self._repo
758 ml = repo.manifest
737 dirlog = repo.manifest.dirlog
759 tmfnodes = {'': mfs}
738 tmfnodes = {'': mfs}
760
739
761 # Callback for the manifest, used to collect linkrevs for filelog
740 # Callback for the manifest, used to collect linkrevs for filelog
@@ -766,9 +745,6 b' class cg1packer(object):'
766 assert not dir
745 assert not dir
767 return mfs.__getitem__
746 return mfs.__getitem__
768
747
769 if dir:
770 return tmfnodes[dir].get
771
772 def lookupmflinknode(x):
748 def lookupmflinknode(x):
773 """Callback for looking up the linknode for manifests.
749 """Callback for looking up the linknode for manifests.
774
750
@@ -785,43 +761,34 b' class cg1packer(object):'
785 the client before you can trust the list of files and
761 the client before you can trust the list of files and
786 treemanifests to send.
762 treemanifests to send.
787 """
763 """
788 clnode = mfs[x]
764 clnode = tmfnodes[dir][x]
789 # We no longer actually care about reading deltas of
765 mdata = dirlog(dir).readshallowfast(x)
790 # the manifest here, because we already know the list
791 # of changed files, so for treemanifests (which
792 # lazily-load anyway to *generate* a readdelta) we can
793 # just load them with read() and then we'll actually
794 # be able to correctly load node IDs from the
795 # submanifest entries.
796 if 'treemanifest' in repo.requirements:
766 if 'treemanifest' in repo.requirements:
797 mdata = ml.read(x)
767 for p, n, fl in mdata.iterentries():
768 if fl == 't': # subdirectory manifest
769 subdir = dir + p + '/'
770 tmfclnodes = tmfnodes.setdefault(subdir, {})
771 tmfclnode = tmfclnodes.setdefault(n, clnode)
772 if clrevorder[clnode] < clrevorder[tmfclnode]:
773 tmfclnodes[n] = clnode
774 else:
775 f = dir + p
776 fclnodes = fnodes.setdefault(f, {})
777 fclnode = fclnodes.setdefault(n, clnode)
778 if clrevorder[clnode] < clrevorder[fclnode]:
779 fclnodes[n] = clnode
798 else:
780 else:
799 mdata = ml.readfast(x)
781 for f in mfchangedfiles[x]:
800 for f in mfchangedfiles[x]:
801 try:
802 n = mdata[f]
803 except KeyError:
804 continue
805 # record the first changeset introducing this filelog
806 # version
807 fclnodes = fnodes.setdefault(f, {})
808 fclnode = fclnodes.setdefault(n, clnode)
809 if clrevorder[clnode] < clrevorder[fclnode]:
810 fclnodes[n] = clnode
811 # gather list of changed treemanifest nodes
812 if 'treemanifest' in repo.requirements:
813 submfs = {'/': mdata}
814 for dn, bn in _moddirs(mfchangedfiles[x]):
815 try:
782 try:
816 submf = submfs[dn]
783 n = mdata[f]
817 submf = submf._dirs[bn]
818 except KeyError:
784 except KeyError:
819 continue # deleted directory, so nothing to send
785 continue
820 submfs[submf.dir()] = submf
786 # record the first changeset introducing this filelog
821 tmfclnodes = tmfnodes.setdefault(submf.dir(), {})
787 # version
822 tmfclnode = tmfclnodes.setdefault(submf._node, clnode)
788 fclnodes = fnodes.setdefault(f, {})
823 if clrevorder[clnode] < clrevorder[tmfclnode]:
789 fclnode = fclnodes.setdefault(n, clnode)
824 tmfclnodes[n] = clnode
790 if clrevorder[clnode] < clrevorder[fclnode]:
791 fclnodes[n] = clnode
825 return clnode
792 return clnode
826 return lookupmflinknode
793 return lookupmflinknode
827
794
@@ -829,7 +796,7 b' class cg1packer(object):'
829 while tmfnodes:
796 while tmfnodes:
830 dir = min(tmfnodes)
797 dir = min(tmfnodes)
831 nodes = tmfnodes[dir]
798 nodes = tmfnodes[dir]
832 prunednodes = self.prune(ml.dirlog(dir), nodes, commonrevs)
799 prunednodes = self.prune(dirlog(dir), nodes, commonrevs)
833 for x in self._packmanifests(dir, prunednodes,
800 for x in self._packmanifests(dir, prunednodes,
834 makelookupmflinknode(dir)):
801 makelookupmflinknode(dir)):
835 size += len(x)
802 size += len(x)
@@ -985,6 +985,15 b' class manifest(revlog.revlog):'
985 return self.readdelta(node)
985 return self.readdelta(node)
986 return self.read(node)
986 return self.read(node)
987
987
988 def readshallowfast(self, node):
989 '''like readfast(), but calls readshallowdelta() instead of readdelta()
990 '''
991 r = self.rev(node)
992 deltaparent = self.deltaparent(r)
993 if deltaparent != revlog.nullrev and deltaparent in self.parentrevs(r):
994 return self.readshallowdelta(node)
995 return self.readshallow(node)
996
988 def read(self, node):
997 def read(self, node):
989 if node == revlog.nullid:
998 if node == revlog.nullid:
990 return self._newmanifest() # don't upset local cache
999 return self._newmanifest() # don't upset local cache
@@ -1006,6 +1015,13 b' class manifest(revlog.revlog):'
1006 self._mancache[node] = (m, arraytext)
1015 self._mancache[node] = (m, arraytext)
1007 return m
1016 return m
1008
1017
1018 def readshallow(self, node):
1019 '''Reads the manifest in this directory. When using flat manifests,
1020 this manifest will generally have files in subdirectories in it. Does
1021 not cache the manifest as the callers generally do not read the same
1022 version twice.'''
1023 return manifestdict(self.revision(node))
1024
1009 def find(self, node, f):
1025 def find(self, node, f):
1010 '''look up entry for a single file efficiently.
1026 '''look up entry for a single file efficiently.
1011 return (node, flags) pair if found, (None, None) if not.'''
1027 return (node, flags) pair if found, (None, None) if not.'''
@@ -363,6 +363,13 b' Pushing to an empty repo works'
363 added 11 changesets with 15 changes to 10 files (+3 heads)
363 added 11 changesets with 15 changes to 10 files (+3 heads)
364 $ grep treemanifest clone/.hg/requires
364 $ grep treemanifest clone/.hg/requires
365 treemanifest
365 treemanifest
366 $ hg -R clone verify
367 checking changesets
368 checking manifests
369 checking directory manifests
370 crosschecking files in changesets and manifests
371 checking files
372 10 files, 11 changesets, 15 total revisions
366
373
367 Create deeper repo with tree manifests.
374 Create deeper repo with tree manifests.
368
375
General Comments 0
You need to be logged in to leave comments. Login now