bundlerepo: fix and improve getremotechanges
Fixes the regression where incoming could show local changes
introduced by rev
72c84f24b420.
--- a/hgext/transplant.py Mon May 02 00:04:49 2011 +0200
+++ b/hgext/transplant.py Mon May 02 12:36:23 2011 +0200
@@ -494,10 +494,8 @@
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 @@
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 @@
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 @@
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 @@
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)``
--- a/mercurial/bundlerepo.py Mon May 02 00:04:49 2011 +0200
+++ b/mercurial/bundlerepo.py Mon May 02 12:36:23 2011 +0200
@@ -288,30 +288,48 @@
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 @@
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)
+
--- a/mercurial/hg.py Mon May 02 00:04:49 2011 +0200
+++ b/mercurial/hg.py Mon May 02 12:36:23 2011 +0200
@@ -427,14 +427,13 @@
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 @@
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
--- a/tests/test-http.t Mon May 02 00:04:49 2011 +0200
+++ b/tests/test-http.t Mon May 02 12:36:23 2011 +0200
@@ -70,6 +70,24 @@
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