discovery: drop findoutgoing and simplify findcommonincoming's api
authorPeter Arrenbrecht <peter.arrenbrecht@gmail.com>
Sat, 30 Apr 2011 17:21:37 +0200
changeset 14073 72c84f24b420
parent 14072 2e4d79dcc0a0
child 14074 e8271159c8c2
discovery: drop findoutgoing and simplify findcommonincoming's api This is a long desired cleanup and paves the way for new discovery. To specify subsets for bundling changes, all code should use the heads of the desired subset ("heads") and the heads of the common subset ("common") to be excluded from the bundled set. These can be used revlog.findmissing instead of revlog.nodesbetween. This fixes an actual bug exposed by the change in test-bundle-r.t where we try to bundle a changeset while specifying that said changeset is to be assumed already present in the target. This used to still bundle the changeset. It no longer does. This is similar to the bugs fixed by the recent switch to heads/common for incoming/pull.
hgext/patchbomb.py
hgext/transplant.py
mercurial/bundlerepo.py
mercurial/commands.py
mercurial/discovery.py
mercurial/hg.py
mercurial/localrepo.py
mercurial/revset.py
tests/test-acl.t
tests/test-bundle-r.t
tests/test-bundle.t
tests/test-push-warn.t
--- a/hgext/patchbomb.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/hgext/patchbomb.py	Sat Apr 30 17:21:37 2011 +0200
@@ -238,15 +238,14 @@
         dest = ui.expandpath(dest or 'default-push', dest or 'default')
         dest, branches = hg.parseurl(dest)
         revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
-        if revs:
-            revs = [repo.lookup(rev) for rev in revs]
         other = hg.repository(hg.remoteui(repo, opts), dest)
         ui.status(_('comparing with %s\n') % url.hidepassword(dest))
-        o = discovery.findoutgoing(repo, other)
+        common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
+        nodes = revs and map(repo.lookup, revs) or revs
+        o = repo.changelog.findmissing(common, heads=nodes)
         if not o:
             ui.status(_("no changes found\n"))
             return []
-        o = repo.changelog.nodesbetween(o, revs)[0]
         return [str(repo.changelog.rev(r)) for r in o]
 
     def getpatches(revs):
--- a/hgext/transplant.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/hgext/transplant.py	Sat Apr 30 17:21:37 2011 +0200
@@ -494,10 +494,10 @@
     and then resume where you left off by calling :hg:`transplant
     --continue/-c`.
     '''
-    def incwalk(repo, incoming, branches, match=util.always):
+    def incwalk(repo, commmon, branches, match=util.always):
         if not branches:
             branches = None
-        for node in repo.changelog.nodesbetween(incoming, branches)[0]:
+        for node in repo.changelog.findmissing(common, branches):
             if match(node):
                 yield node
 
@@ -552,8 +552,8 @@
     if source:
         sourcerepo = ui.expandpath(source)
         source = hg.repository(ui, sourcerepo)
-        source, common, incoming, bundle = bundlerepo.getremotechanges(ui, repo,
-                                            source, force=True)
+        source, common, anyinc, bundle = bundlerepo.getremotechanges(ui, repo,
+                                          source, force=True)
     else:
         source = repo
 
@@ -577,7 +577,7 @@
                 revmap[int(r)] = source.lookup(r)
         elif opts.get('all') or not merges:
             if source != repo:
-                alltransplants = incwalk(source, incoming, branches,
+                alltransplants = incwalk(source, common, branches,
                                          match=matchfn)
             else:
                 alltransplants = transplantwalk(source, p1, branches,
--- a/mercurial/bundlerepo.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/mercurial/bundlerepo.py	Sat Apr 30 17:21:37 2011 +0200
@@ -287,9 +287,8 @@
     return bundlerepository(ui, repopath, bundlename)
 
 def getremotechanges(ui, repo, other, revs=None, bundlename=None,
-                     force=False, usecommon=False):
-    tmp = discovery.findcommonincoming(repo, other, heads=revs, force=force,
-                                       commononly=usecommon)
+                     force=False):
+    tmp = discovery.findcommonincoming(repo, other, heads=revs, force=force)
     common, incoming, rheads = tmp
     if not incoming:
         try:
@@ -305,7 +304,7 @@
         if revs is None and other.capable('changegroupsubset'):
             revs = rheads
 
-        if usecommon:
+        if other.capable('getbundle'):
             cg = other.getbundle('incoming', common=common, heads=revs)
         elif revs is None:
             cg = other.changegroup(incoming, "incoming")
--- a/mercurial/commands.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/mercurial/commands.py	Sat Apr 30 17:21:37 2011 +0200
@@ -696,49 +696,21 @@
         if dest:
             raise util.Abort(_("--base is incompatible with specifying "
                                "a destination"))
-        base = [repo.lookup(rev) for rev in base]
-        # create the right base
-        # XXX: nodesbetween / changegroup* should be "fixed" instead
-        o = []
-        has = set((nullid,))
-        for n in base:
-            has.update(repo.changelog.reachable(n))
-        if revs:
-            revs = [repo.lookup(rev) for rev in revs]
-            visit = revs[:]
-            has.difference_update(visit)
-        else:
-            visit = repo.changelog.heads()
-        seen = {}
-        while visit:
-            n = visit.pop(0)
-            parents = [p for p in repo.changelog.parents(n) if p not in has]
-            if len(parents) == 0:
-                if n not in has:
-                    o.append(n)
-            else:
-                for p in parents:
-                    if p not in seen:
-                        seen[p] = 1
-                        visit.append(p)
+        common = [repo.lookup(rev) for rev in base]
     else:
         dest = ui.expandpath(dest or 'default-push', dest or 'default')
         dest, branches = hg.parseurl(dest, opts.get('branch'))
         other = hg.repository(hg.remoteui(repo, opts), dest)
         revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
-        if revs:
-            revs = [repo.lookup(rev) for rev in revs]
-        o = discovery.findoutgoing(repo, other, force=opts.get('force'))
-
-    if not o:
+        inc = discovery.findcommonincoming(repo, other, force=opts.get('force'))
+        common, _anyinc, _heads = inc
+
+    nodes = revs and map(repo.lookup, revs) or revs
+    cg = repo.getbundle('bundle', common=common, heads=nodes)
+    if not cg:
         ui.status(_("no changes found\n"))
         return 1
 
-    if revs:
-        cg = repo.changegroupsubset(o, revs, 'bundle')
-    else:
-        cg = repo.changegroup(o, 'bundle')
-
     bundletype = opts.get('type', 'bzip2').lower()
     btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
     bundletype = btypes.get(bundletype)
@@ -3959,9 +3931,9 @@
         other = hg.repository(hg.remoteui(repo, {}), dest)
         ui.debug('comparing with %s\n' % url.hidepassword(dest))
         repo.ui.pushbuffer()
-        o = discovery.findoutgoing(repo, other)
+        common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
         repo.ui.popbuffer()
-        o = repo.changelog.nodesbetween(o, None)[0]
+        o = repo.changelog.findmissing(common=common)
         if o:
             t.append(_('%d outgoing') % len(o))
         if 'bookmarks' in other.listkeys('namespaces'):
--- a/mercurial/discovery.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/mercurial/discovery.py	Sat Apr 30 17:21:37 2011 +0200
@@ -9,14 +9,19 @@
 from i18n import _
 import util, error
 
-def findcommonincoming(repo, remote, heads=None, force=False, commononly=False):
-    """Return a tuple (common, missing, heads) used to identify missing nodes
-    from remote. "missing" is either a boolean indicating if any nodes are missing
-    (when commononly=True), or else a list of the root nodes of the missing set.
+def findcommonincoming(repo, remote, heads=None, force=False):
+    """Return a tuple (common, anyincoming, heads) used to identify the common
+    subset of nodes between repo and remote.
 
-    If a list of heads is specified, return only nodes which are heads
-    or ancestors of these heads.
+    "common" is a list of (at least) the heads of the common subset.
+    "anyincoming" is testable as a boolean indicating if any nodes are missing
+      locally. If remote does not support getbundle, this actually is a list of
+      roots of the nodes that would be incoming, to be supplied to
+      changegroupsubset. No code except for pull should be relying on this fact
+      any longer.
+    "heads" is either the supplied heads, or else the remote's heads.
     """
+
     m = repo.changelog.nodemap
     search = []
     fetch = set()
@@ -37,7 +42,7 @@
     # and start by examining the heads
     repo.ui.status(_("searching for changes\n"))
 
-    if commononly:
+    if remote.capable('getbundle'):
         myheads = repo.heads()
         known = remote.known(myheads)
         if util.all(known):
@@ -155,45 +160,6 @@
 
     return base, list(fetch), heads
 
-def findoutgoing(repo, remote, base=None, remoteheads=None, force=False):
-    """Return list of nodes that are roots of subsets not in remote
-
-    If base dict is specified, assume that these nodes and their parents
-    exist on the remote side.
-    If remotehead is specified, assume it is the list of the heads from
-    the remote repository.
-    """
-    if base is None:
-        base = findcommonincoming(repo, remote, heads=remoteheads,
-                                  force=force)[0]
-    else:
-        base = list(base)
-
-    repo.ui.debug("common changesets up to "
-                  + " ".join(map(short, base)) + "\n")
-
-    remain = set(repo.changelog.nodemap)
-
-    # prune everything remote has from the tree
-    remain.remove(nullid)
-    remove = base
-    while remove:
-        n = remove.pop(0)
-        if n in remain:
-            remain.remove(n)
-            for p in repo.changelog.parents(n):
-                remove.append(p)
-
-    # find every node whose parents have been pruned
-    subset = []
-    # find every remote head that will get new children
-    for n in remain:
-        p1, p2 = repo.changelog.parents(n)
-        if p1 not in remain and p2 not in remain:
-            subset.append(n)
-
-    return subset
-
 def prepush(repo, remote, force, revs, newbranch):
     '''Analyze the local and remote repositories and determine which
     changesets need to be pushed to the remote. Return value depends
@@ -209,14 +175,13 @@
     successive changegroup chunks ready to be sent over the wire and
     remoteheads is the list of remote heads.'''
     remoteheads = remote.heads()
-    common, inc, rheads = findcommonincoming(repo, remote, heads=remoteheads,
-                                             force=force)
+    common, inc, _rheads = findcommonincoming(repo, remote, heads=remoteheads,
+                                              force=force)
 
     cl = repo.changelog
-    update = findoutgoing(repo, remote, common, remoteheads)
-    outg, bases, heads = cl.nodesbetween(update, revs)
+    outg = cl.findmissing(common, revs)
 
-    if not bases:
+    if not outg:
         repo.ui.status(_("no changes found\n"))
         return None, 1
 
@@ -317,8 +282,7 @@
 
     if revs is None:
         # use the fast path, no race possible on push
-        nodes = repo.changelog.findmissing(common)
-        cg = repo._changegroup(nodes, 'push')
+        cg = repo._changegroup(outg, 'push')
     else:
-        cg = repo.changegroupsubset(update, revs, 'push')
+        cg = repo.getbundle('push', heads=revs, common=common)
     return cg, remoteheads
--- a/mercurial/hg.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/mercurial/hg.py	Sat Apr 30 17:21:37 2011 +0200
@@ -426,19 +426,14 @@
 
     if revs:
         revs = [other.lookup(rev) for rev in revs]
-    usecommon = other.capable('getbundle')
-    other, common, incoming, bundle = bundlerepo.getremotechanges(ui, repo, other,
-                                       revs, opts["bundle"], opts["force"],
-                                       usecommon=usecommon)
-    if not incoming:
+    other, common, anyinc, bundle = bundlerepo.getremotechanges(ui, repo, other,
+                                     revs, opts["bundle"], opts["force"])
+    if not anyinc:
         ui.status(_("no changes found\n"))
         return subreporecurse()
 
     try:
-        if usecommon:
-            chlist = other.changelog.findmissing(common, revs)
-        else:
-            chlist = other.changelog.nodesbetween(incoming, revs)[0]
+        chlist = other.changelog.findmissing(common, revs)
         displayer = cmdutil.show_changeset(ui, other, opts, buffered)
 
         # XXX once graphlog extension makes it into core,
@@ -488,12 +483,13 @@
         revs = [repo.lookup(rev) for rev in revs]
 
     other = repository(remoteui(repo, opts), dest)
-    o = discovery.findoutgoing(repo, other, force=opts.get('force'))
+    inc = discovery.findcommonincoming(repo, other, force=opts.get('force'))
+    common, _anyinc, _heads = inc
+    o = repo.changelog.findmissing(common, revs)
     if not o:
         ui.status(_("no changes found\n"))
         return None
-
-    return repo.changelog.nodesbetween(o, revs)[0]
+    return o
 
 def outgoing(ui, repo, dest, opts):
     def recurse():
--- a/mercurial/localrepo.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/mercurial/localrepo.py	Sat Apr 30 17:21:37 2011 +0200
@@ -1327,9 +1327,8 @@
     def pull(self, remote, heads=None, force=False):
         lock = self.lock()
         try:
-            usecommon = remote.capable('getbundle')
             tmp = discovery.findcommonincoming(self, remote, heads=heads,
-                                               force=force, commononly=usecommon)
+                                               force=force)
             common, fetch, rheads = tmp
             if not fetch:
                 self.ui.status(_("no changes found\n"))
@@ -1341,7 +1340,7 @@
                     # issue1320, avoid a race if remote changed after discovery
                     heads = rheads
 
-                if usecommon:
+                if remote.capable('getbundle'):
                     cg = remote.getbundle('pull', common=common,
                                           heads=heads or rheads)
                 elif heads is None:
@@ -1475,6 +1474,8 @@
         if not heads:
             heads = cl.heads()
         common, missing = cl.findcommonmissing(common, heads)
+        if not missing:
+            return None
         return self._changegroupsubset(common, missing, heads, source)
 
     def _changegroupsubset(self, commonrevs, csets, heads, source):
--- a/mercurial/revset.py	Sat Apr 30 18:25:45 2011 +0200
+++ b/mercurial/revset.py	Sat Apr 30 17:21:37 2011 +0200
@@ -554,10 +554,10 @@
         revs = [repo.lookup(rev) for rev in revs]
     other = hg.repository(hg.remoteui(repo, {}), dest)
     repo.ui.pushbuffer()
-    o = discovery.findoutgoing(repo, other)
+    common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
     repo.ui.popbuffer()
     cl = repo.changelog
-    o = set([cl.rev(r) for r in repo.changelog.nodesbetween(o, revs)[0]])
+    o = set([cl.rev(r) for r in repo.changelog.findmissing(common, revs)])
     return [r for r in subset if r in o]
 
 def p1(repo, subset, x):
--- a/tests/test-acl.t	Sat Apr 30 18:25:45 2011 +0200
+++ b/tests/test-acl.t	Sat Apr 30 17:21:37 2011 +0200
@@ -83,7 +83,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -137,7 +136,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -195,7 +193,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -262,7 +259,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -327,7 +323,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -396,7 +391,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -462,7 +456,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -533,7 +526,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -601,7 +593,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -671,7 +662,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -744,7 +734,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -822,7 +811,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -893,7 +881,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -976,7 +963,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -1050,7 +1036,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -1121,7 +1106,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -1195,7 +1179,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   3 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -1266,7 +1249,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 6675d58eff77
   invalidating branch cache (tip differs)
   3 changesets found
   list of changesets:
@@ -1378,7 +1360,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   4 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -1456,7 +1437,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   invalidating branch cache (tip differs)
   4 changesets found
   list of changesets:
@@ -1533,7 +1513,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   4 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -1605,7 +1584,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   4 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -1671,7 +1649,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   4 changesets found
   list of changesets:
   ef1ea85a6374b77d6da9dcda9541f498f2d17df7
@@ -1754,7 +1731,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   invalidating branch cache (tip differs)
   4 changesets found
   list of changesets:
@@ -1837,7 +1813,6 @@
   """
   pushing to ../b
   searching for changes
-  common changesets up to 07e028174695
   invalidating branch cache (tip differs)
   4 changesets found
   list of changesets:
--- a/tests/test-bundle-r.t	Sat Apr 30 18:25:45 2011 +0200
+++ b/tests/test-bundle-r.t	Sat Apr 30 17:21:37 2011 +0200
@@ -231,7 +231,8 @@
 issue76 msg2163
 
   $ hg -R test bundle --base 3 -r 3 -r 3 test-bundle-cset-3.hg
-  1 changesets found
+  no changes found
+  [1]
 
 Issue1910: 'hg bundle --base $head' does not exclude $head from
 result
--- a/tests/test-bundle.t	Sat Apr 30 18:25:45 2011 +0200
+++ b/tests/test-bundle.t	Sat Apr 30 17:21:37 2011 +0200
@@ -562,7 +562,6 @@
 
   $ hg bundle bundle.hg part --debug
   searching for changes
-  common changesets up to c0025332f9ed
   2 changesets found
   list of changesets:
   d2ae7f538514cd87c17547b0de4cea71fe1af9fb
--- a/tests/test-push-warn.t	Sat Apr 30 18:25:45 2011 +0200
+++ b/tests/test-push-warn.t	Sat Apr 30 17:21:37 2011 +0200
@@ -39,7 +39,6 @@
   found new branch changeset 1c9246a22a0a
   found new changesets starting at 1c9246a22a0a
   1 total queries
-  common changesets up to d8d565842d04
   new remote heads on branch 'default'
   new remote head 1e108cc5548c
   abort: push creates new remote heads on branch 'default'!