mercurial/changegroup.py
changeset 28240 1ac8ce137377
parent 28232 829d369fc5a8
child 28241 a4286175ecba
--- a/mercurial/changegroup.py	Sun Dec 27 20:21:37 2015 +0900
+++ b/mercurial/changegroup.py	Fri Feb 12 23:09:09 2016 -0800
@@ -553,27 +553,6 @@
             return d
         return readexactly(self._fh, n)
 
-def _moddirs(files):
-    """Given a set of modified files, find the list of modified directories.
-
-    This returns a list of (path to changed dir, changed dir) tuples,
-    as that's what the one client needs anyway.
-
-    >>> _moddirs(['a/b/c.py', 'a/b/c.txt', 'a/d/e/f/g.txt', 'i.txt', ])
-    [('/', 'a/'), ('a/', 'b/'), ('a/', 'd/'), ('a/d/', 'e/'), ('a/d/e/', 'f/')]
-
-    """
-    alldirs = set()
-    for f in files:
-        path = f.split('/')[:-1]
-        for i in xrange(len(path) - 1, -1, -1):
-            dn = '/'.join(path[:i])
-            current = dn + '/', path[i] + '/'
-            if current in alldirs:
-                break
-            alldirs.add(current)
-    return sorted(alldirs)
-
 class cg1packer(object):
     deltaheader = _CHANGEGROUPV1_DELTA_HEADER
     version = '01'
@@ -755,7 +734,7 @@
     def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs,
                           mfchangedfiles, fnodes):
         repo = self._repo
-        ml = repo.manifest
+        dirlog = repo.manifest.dirlog
         tmfnodes = {'': mfs}
 
         # Callback for the manifest, used to collect linkrevs for filelog
@@ -766,9 +745,6 @@
                 assert not dir
                 return mfs.__getitem__
 
-            if dir:
-                return tmfnodes[dir].get
-
             def lookupmflinknode(x):
                 """Callback for looking up the linknode for manifests.
 
@@ -785,43 +761,34 @@
                 the client before you can trust the list of files and
                 treemanifests to send.
                 """
-                clnode = mfs[x]
-                # We no longer actually care about reading deltas of
-                # the manifest here, because we already know the list
-                # of changed files, so for treemanifests (which
-                # lazily-load anyway to *generate* a readdelta) we can
-                # just load them with read() and then we'll actually
-                # be able to correctly load node IDs from the
-                # submanifest entries.
+                clnode = tmfnodes[dir][x]
+                mdata = dirlog(dir).readshallowfast(x)
                 if 'treemanifest' in repo.requirements:
-                    mdata = ml.read(x)
+                    for p, n, fl in mdata.iterentries():
+                        if fl == 't': # subdirectory manifest
+                            subdir = dir + p + '/'
+                            tmfclnodes = tmfnodes.setdefault(subdir, {})
+                            tmfclnode = tmfclnodes.setdefault(n, clnode)
+                            if clrevorder[clnode] < clrevorder[tmfclnode]:
+                                tmfclnodes[n] = clnode
+                        else:
+                            f = dir + p
+                            fclnodes = fnodes.setdefault(f, {})
+                            fclnode = fclnodes.setdefault(n, clnode)
+                            if clrevorder[clnode] < clrevorder[fclnode]:
+                                fclnodes[n] = clnode
                 else:
-                    mdata = ml.readfast(x)
-                for f in mfchangedfiles[x]:
-                    try:
-                        n = mdata[f]
-                    except KeyError:
-                        continue
-                    # record the first changeset introducing this filelog
-                    # version
-                    fclnodes = fnodes.setdefault(f, {})
-                    fclnode = fclnodes.setdefault(n, clnode)
-                    if clrevorder[clnode] < clrevorder[fclnode]:
-                        fclnodes[n] = clnode
-                # gather list of changed treemanifest nodes
-                if 'treemanifest' in repo.requirements:
-                    submfs = {'/': mdata}
-                    for dn, bn in _moddirs(mfchangedfiles[x]):
+                    for f in mfchangedfiles[x]:
                         try:
-                            submf = submfs[dn]
-                            submf = submf._dirs[bn]
+                            n = mdata[f]
                         except KeyError:
-                            continue # deleted directory, so nothing to send
-                        submfs[submf.dir()] = submf
-                        tmfclnodes = tmfnodes.setdefault(submf.dir(), {})
-                        tmfclnode = tmfclnodes.setdefault(submf._node, clnode)
-                        if clrevorder[clnode] < clrevorder[tmfclnode]:
-                            tmfclnodes[n] = clnode
+                            continue
+                        # record the first changeset introducing this filelog
+                        # version
+                        fclnodes = fnodes.setdefault(f, {})
+                        fclnode = fclnodes.setdefault(n, clnode)
+                        if clrevorder[clnode] < clrevorder[fclnode]:
+                            fclnodes[n] = clnode
                 return clnode
             return lookupmflinknode
 
@@ -829,7 +796,7 @@
         while tmfnodes:
             dir = min(tmfnodes)
             nodes = tmfnodes[dir]
-            prunednodes = self.prune(ml.dirlog(dir), nodes, commonrevs)
+            prunednodes = self.prune(dirlog(dir), nodes, commonrevs)
             for x in self._packmanifests(dir, prunednodes,
                                          makelookupmflinknode(dir)):
                 size += len(x)