# HG changeset patch # User Peter Arrenbrecht # Date 2011-05-02 10:36:23 # Node ID 8a0fca925992aed2bd938a5953191e6753b9041b # Parent a881a058823c87e5f33fb76f9053e46bf34f9285 bundlerepo: fix and improve getremotechanges Fixes the regression where incoming could show local changes introduced by rev 72c84f24b420. diff --git a/hgext/transplant.py b/hgext/transplant.py --- a/hgext/transplant.py +++ b/hgext/transplant.py @@ -494,10 +494,8 @@ def transplant(ui, repo, *revs, **opts): and then resume where you left off by calling :hg:`transplant --continue/-c`. ''' - def incwalk(repo, commmon, branches, match=util.always): - if not branches: - branches = None - for node in repo.changelog.findmissing(common, branches): + def incwalk(repo, csets, match=util.always): + for node in csets: if match(node): yield node @@ -547,15 +545,16 @@ def transplant(ui, repo, *revs, **opts): if m or a or r or d: raise util.Abort(_('outstanding local changes')) - bundle = None - source = opts.get('source') - if source: - sourcerepo = ui.expandpath(source) - source = hg.repository(ui, sourcerepo) - source, common, anyinc, bundle = bundlerepo.getremotechanges(ui, repo, - source, force=True) + sourcerepo = opts.get('source') + if sourcerepo: + source = hg.repository(ui, ui.expandpath(sourcerepo)) + branches = map(source.lookup, opts.get('branch', ())) + source, csets, cleanupfn = bundlerepo.getremotechanges(ui, repo, source, + onlyheads=branches, force=True) else: source = repo + branches = map(source.lookup, opts.get('branch', ())) + cleanupfn = None try: if opts.get('continue'): @@ -569,7 +568,6 @@ def transplant(ui, repo, *revs, **opts): matchfn = lambda x: tf(x) and x not in prune else: matchfn = tf - branches = map(source.lookup, opts.get('branch', ())) merges = map(source.lookup, opts.get('merge', ())) revmap = {} if revs: @@ -577,8 +575,7 @@ def transplant(ui, repo, *revs, **opts): revmap[int(r)] = source.lookup(r) elif opts.get('all') or not merges: if source != repo: - alltransplants = incwalk(source, common, branches, - match=matchfn) + alltransplants = incwalk(source, csets, match=matchfn) else: alltransplants = transplantwalk(source, p1, branches, match=matchfn) @@ -594,9 +591,8 @@ def transplant(ui, repo, *revs, **opts): tp.apply(repo, source, revmap, merges, opts) finally: - if bundle: - source.close() - os.unlink(bundle) + if cleanupfn: + cleanupfn() def revsettransplanted(repo, subset, x): """``transplanted(set)`` diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -288,30 +288,48 @@ def instance(ui, path, create): repopath, bundlename = parentpath, path return bundlerepository(ui, repopath, bundlename) -def getremotechanges(ui, repo, other, revs=None, bundlename=None, +def getremotechanges(ui, repo, other, onlyheads=None, bundlename=None, force=False): - tmp = discovery.findcommonincoming(repo, other, heads=revs, force=force) + '''obtains a bundle of changes incoming from other + + "onlyheads" restricts the returned changes to those reachable from the + specified heads. + "bundlename", if given, stores the bundle to this file path permanently; + the returned "bundle" will be None. + "force" indicates whether to proceed on unrelated repos. + + Returns a tuple (local, csets, cleanupfn): + + "local" is a local repo from which to obtain the actual incoming changesets; it + is a bundlerepo for the obtained bundle when the original "other" is remote. + "csets" lists the incoming changeset node ids. + "cleanupfn" must be called without arguments when you're done processing the + changes; it closes both the original "other" and the one returned here. + ''' + tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force) common, incoming, rheads = tmp if not incoming: try: os.unlink(bundlename) except OSError: pass - return other, None, None, None + return other, [], other.close bundle = None + bundlerepo = None + localrepo = other if bundlename or not other.local(): # create a bundle (uncompressed if other repo is not local) - if revs is None and other.capable('changegroupsubset'): - revs = rheads + if onlyheads is None and other.capable('changegroupsubset'): + onlyheads = rheads if other.capable('getbundle'): - cg = other.getbundle('incoming', common=common, heads=revs) - elif revs is None: + cg = other.getbundle('incoming', common=common, heads=onlyheads) + elif onlyheads is None: cg = other.changegroup(incoming, "incoming") else: - cg = other.changegroupsubset(incoming, revs, 'incoming') + cg = other.changegroupsubset(incoming, onlyheads, 'incoming') bundletype = other.local() and "HG10BZ" or "HG10UN" fname = bundle = changegroup.writebundle(cg, bundlename, bundletype) # keep written bundle? @@ -319,6 +337,18 @@ def getremotechanges(ui, repo, other, re bundle = None if not other.local(): # use the created uncompressed bundlerepo - other = bundlerepository(ui, repo.root, fname) - return (other, common, incoming, bundle) + localrepo = bundlerepo = bundlerepository(ui, repo.root, fname) + # this repo contains local and other now, so filter out local again + common = repo.heads() + + csets = localrepo.changelog.findmissing(common, onlyheads) + def cleanup(): + if bundlerepo: + bundlerepo.close() + if bundle: + os.unlink(bundle) + localrepo.close() + + return (localrepo, csets, cleanup) + diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -427,14 +427,13 @@ def _incoming(displaychlist, subreporecu if revs: revs = [other.lookup(rev) for rev in revs] - 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() + other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other, + revs, opts["bundle"], opts["force"]) + try: + if not chlist: + ui.status(_("no changes found\n")) + return subreporecurse() - try: - chlist = other.changelog.findmissing(common, revs) displayer = cmdutil.show_changeset(ui, other, opts, buffered) # XXX once graphlog extension makes it into core, @@ -443,10 +442,7 @@ def _incoming(displaychlist, subreporecu displayer.close() finally: - if hasattr(other, 'close'): - other.close() - if bundle: - os.unlink(bundle) + cleanupfn() subreporecurse() return 0 # exit code is zero since we found incoming changes diff --git a/tests/test-http.t b/tests/test-http.t --- a/tests/test-http.t +++ b/tests/test-http.t @@ -70,6 +70,24 @@ clone via pull adding bar $ cd .. +incoming via HTTP + + $ hg clone http://localhost:$HGPORT1/ --rev 0 partial + adding changesets + adding manifests + adding file changes + added 1 changesets with 4 changes to 4 files + updating to branch default + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd partial + $ touch LOCAL + $ hg ci -qAm LOCAL + $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n' + comparing with http://localhost:$HGPORT1/ + searching for changes + 2 + $ cd .. + pull $ cd copy-pull