mercurial/localrepo.py
changeset 13741 b51bf961b3cb
parent 13723 e615765fdcc7
child 13742 7abab875e647
--- a/mercurial/localrepo.py	Wed Mar 23 12:38:36 2011 -0500
+++ b/mercurial/localrepo.py	Wed Mar 23 16:02:11 2011 +0100
@@ -21,7 +21,7 @@
 
 class localrepository(repo.repository):
     capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey',
-                        'known'))
+                        'known', 'getbundle'))
     supportedformats = set(('revlogv1', 'parentdelta'))
     supported = supportedformats | set(('store', 'fncache', 'shared',
                                         'dotencode'))
@@ -1443,16 +1443,41 @@
         Another wrinkle is doing the reverse, figuring out which changeset in
         the changegroup a particular filenode or manifestnode belongs to.
         """
+        cl = self.changelog
+        if not bases:
+            bases = [nullid]
+        csets, bases, heads = cl.nodesbetween(bases, heads)
+        # We assume that all ancestors of bases are known
+        common = set(cl.ancestors(*[cl.rev(n) for n in bases]))
+        return self._changegroupsubset(common, csets, heads, source)
+
+    def getbundle(self, source, heads=None, common=None):
+        """Like changegroupsubset, but returns the set difference between the
+        ancestors of heads and the ancestors common.
+
+        If heads is None, use the local heads. If common is None, use [nullid].
+
+        The nodes in common might not all be known locally due to the way the
+        current discovery protocol works.
+        """
+        cl = self.changelog
+        if common:
+            nm = cl.nodemap
+            common = [n for n in common if n in nm]
+        else:
+            common = [nullid]
+        if not heads:
+            heads = cl.heads()
+        common, missing = cl.findcommonmissing(common, heads)
+        return self._changegroupsubset(common, missing, heads, source)
+
+    def _changegroupsubset(self, commonrevs, csets, heads, source):
 
         cl = self.changelog
         mf = self.manifest
         mfs = {} # needed manifests
         fnodes = {} # needed file nodes
 
-        if not bases:
-            bases = [nullid]
-        csets, bases, heads = cl.nodesbetween(bases, heads)
-
         # can we go through the fast path ?
         heads.sort()
         if heads == sorted(self.heads()):
@@ -1462,9 +1487,6 @@
         self.hook('preoutgoing', throw=True, source=source)
         self.changegroupinfo(csets, source)
 
-        # We assume that all ancestors of bases are known
-        commonrevs = set(cl.ancestors(*[cl.rev(n) for n in bases]))
-
         # A function generating function that sets up the initial environment
         # the inner function.
         def filenode_collector(changedfiles):