--- a/hgext/fetch.py
+++ b/hgext/fetch.py
@@ -36,8 +36,7 @@ def fetch(ui, repo, source='default', **
if newheads:
ui.status(_('merging with new head %d:%s\n') %
(repo.changelog.rev(newheads[0]), short(newheads[0])))
- err = hg.update(repo, newheads[0], allow=True, remind=False,
- wlock=wlock)
+ err = hg.merge(repo, newheads[0], remind=False, wlock=wlock)
if not err and len(newheads) > 1:
ui.status(_('not merging with %d other new heads '
'(use "hg heads" and "hg merge" to merge them)') %
--- a/hgext/hbisect.py
+++ b/hgext/hbisect.py
@@ -197,7 +197,7 @@ class bisect(object):
check_clean(self.ui, self.repo)
rev = self.next()
if rev is not None:
- return self.repo.update(rev, force=True)
+ return hg.clean(self.repo, rev)
def good(self, rev):
self.goodrevs.append(rev)
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -306,11 +306,11 @@ class queue:
self.ui.warn("patch didn't work out, merging %s\n" % patch)
# apply failed, strip away that rev and merge.
- hg.update(repo, head, allow=False, force=True, wlock=wlock)
+ hg.clean(repo, head, wlock=wlock)
self.strip(repo, n, update=False, backup='strip', wlock=wlock)
c = repo.changelog.read(rev)
- ret = hg.update(repo, rev, allow=True, wlock=wlock)
+ ret = hg.merge(repo, rev, wlock=wlock)
if ret:
raise util.Abort(_("update returned %d") % ret)
n = repo.commit(None, c[4], c[1], force=1, wlock=wlock)
@@ -653,7 +653,7 @@ class queue:
if c or a or d or r:
raise util.Abort(_("local changes found"))
urev = self.qparents(repo, rev)
- hg.update(repo, urev, allow=False, force=True, wlock=wlock)
+ hg.clean(repo, urev, wlock=wlock)
repo.dirstate.write()
# save is a list of all the branches we are truncating away
@@ -1148,7 +1148,7 @@ class queue:
if not r:
self.ui.warn("Unable to load queue repository\n")
return 1
- hg.update(r, qpp[0], allow=False, force=True)
+ hg.clean(r, qpp[0])
def save(self, repo, msg=None):
if len(self.applied) == 0:
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -976,7 +976,7 @@ def backout(ui, repo, rev, **opts):
if opts['parent']:
raise util.Abort(_('cannot use --parent on non-merge changeset'))
parent = p1
- hg.update(repo, node, force=True, show_stats=False)
+ hg.clean(repo, node, show_stats=False)
revert_opts = opts.copy()
revert_opts['rev'] = hex(parent)
revert(ui, repo, **revert_opts)
@@ -993,7 +993,8 @@ def backout(ui, repo, rev, **opts):
if op1 != node:
if opts['merge']:
ui.status(_('merging with changeset %s\n') % nice(op1))
- doupdate(ui, repo, hex(op1), merge=True)
+ n = _lookup(repo, hex(op1))
+ hg.merge(repo, n)
else:
ui.status(_('the backout changeset is a new head - '
'do not forget to merge\n'))
@@ -2152,7 +2153,7 @@ def manifest(ui, repo, rev=None):
for f in files:
ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
-def merge(ui, repo, node=None, **opts):
+def merge(ui, repo, node=None, force=None, branch=None):
"""Merge working directory with another revision
Merge the contents of the current working directory and the
@@ -2160,7 +2161,9 @@ def merge(ui, repo, node=None, **opts):
marked as changed for the next commit and a commit must be
performed before any further updates are allowed.
"""
- return doupdate(ui, repo, node=node, merge=True, **opts)
+
+ node = _lookup(repo, node, branch)
+ return hg.merge(repo, node, force=force)
def outgoing(ui, repo, dest=None, **opts):
"""show changesets not found in destination
@@ -2254,7 +2257,7 @@ def postincoming(ui, repo, modheads, opt
return
if optupdate:
if modheads == 1:
- return doupdate(ui, repo)
+ return hg.update(repo, repo.changelog.tip()) # update
else:
ui.status(_("not updating, since new heads added\n"))
if modheads > 1:
@@ -2603,8 +2606,7 @@ def revert(ui, repo, *pats, **opts):
if not opts.get('dry_run'):
repo.dirstate.forget(forget[0])
- r = hg.update(repo, node, False, True, update.has_key, False,
- wlock=wlock, show_stats=False)
+ r = hg.revert(repo, node, update.has_key, wlock)
repo.dirstate.update(add[0], 'a')
repo.dirstate.update(undelete[0], 'n')
repo.dirstate.update(remove[0], 'r')
@@ -2902,13 +2904,17 @@ def update(ui, repo, node=None, merge=Fa
By default, update will refuse to run if doing so would require
merging or discarding local changes.
"""
+ node = _lookup(repo, node, branch)
if merge:
ui.warn(_('(the -m/--merge option is deprecated; '
'use the merge command instead)\n'))
- return doupdate(ui, repo, node, merge, clean, force, branch)
-
-def doupdate(ui, repo, node=None, merge=False, clean=False, force=None,
- branch=None):
+ return hg.merge(repo, node, force=force)
+ elif clean:
+ return hg.clean(repo, node)
+ else:
+ return hg.update(repo, node)
+
+def _lookup(repo, node, branch=None):
if branch:
br = repo.branchlookup(branch=branch)
found = []
@@ -2916,19 +2922,19 @@ def doupdate(ui, repo, node=None, merge=
if branch in br[x]:
found.append(x)
if len(found) > 1:
- ui.warn(_("Found multiple heads for %s\n") % branch)
+ repo.ui.warn(_("Found multiple heads for %s\n") % branch)
for x in found:
show_changeset(ui, repo, {}).show(changenode=x, brinfo=br)
- return 1
+ raise util.Abort("")
if len(found) == 1:
node = found[0]
- ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
+ repo.ui.warn(_("Using head %s for branch %s\n")
+ % (short(node), branch))
else:
- ui.warn(_("branch %s not found\n") % (branch))
- return 1
+ raise util.Abort(_("branch %s not found\n") % (branch))
else:
node = node and repo.lookup(node) or repo.changelog.tip()
- return hg.update(repo, node, allow=merge, force=clean, forcemerge=force)
+ return node
def verify(ui, repo):
"""verify the integrity of the repository
--- a/mercurial/demandload.py
+++ b/mercurial/demandload.py
@@ -96,6 +96,7 @@ def demandload(scope, modules):
foo import foo
foo bar import foo, bar
+ foo@bar import foo as bar
foo.bar import foo.bar
foo:bar from foo import bar
foo:bar,quux from foo import bar, quux
@@ -108,6 +109,9 @@ def demandload(scope, modules):
mod = mod[:col]
else:
fromlist = []
+ as = None
+ if '@' in mod:
+ mod, as = mod.split("@")
importer = _importer(scope, mod, fromlist)
if fromlist:
for name in fromlist:
@@ -126,4 +130,6 @@ def demandload(scope, modules):
continue
else:
basemod = mod
- scope[basemod] = _replacer(importer, basemod)
+ if not as:
+ as = basemod
+ scope[as] = _replacer(importer, as)
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -10,7 +10,7 @@ from repo import *
from demandload import *
from i18n import gettext as _
demandload(globals(), "localrepo bundlerepo httprepo sshrepo statichttprepo")
-demandload(globals(), "errno lock os shutil util merge")
+demandload(globals(), "errno lock os shutil util merge@_merge verify@_verify")
def _local(path):
return (os.path.isfile(path and util.drop_scheme('file', path)) and
@@ -200,23 +200,31 @@ def clone(ui, source, dest=None, pull=Fa
dest_lock.release()
if update:
- merge.update(dest_repo, dest_repo.changelog.tip())
+ _merge.update(dest_repo, dest_repo.changelog.tip())
if dir_cleanup:
dir_cleanup.close()
return src_repo, dest_repo
+def update(repo, node):
+ """update the working directory to node, merging linear changes"""
+ return _merge.update(repo, node)
-# This should instead be several functions with short arglists, like
-# update/merge/revert
+def clean(repo, node, wlock=None, show_stats=True):
+ """forcibly switch the working directory to node, clobbering changes"""
+ return _merge.update(repo, node, force=True, wlock=wlock,
+ show_stats=show_stats)
-def update(repo, node, allow=False, force=False, choose=None,
- moddirstate=True, forcemerge=False, wlock=None, show_stats=True,
- remind=True):
- return merge.update(repo, node, allow, force, choose, moddirstate,
- forcemerge, wlock, show_stats, remind)
+def merge(repo, node, force=None, remind=True, wlock=None):
+ """branch merge with node, resolving changes"""
+ return _merge.update(repo, node, branchmerge=True, force=force,
+ remind=remind, wlock=wlock)
+
+def revert(repo, node, choose, wlock):
+ """revert changes to revision in node without updating dirstate"""
+ return _merge.update(repo, node, force=True, partial=choose,
+ show_stats=False, wlock=wlock)
def verify(repo):
"""verify the consistency of a repository"""
- import verify as _verify
return _verify.verify(repo)
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -47,17 +47,39 @@ def merge3(repo, fn, my, other, p1, p2):
os.unlink(c)
return r
-def update(repo, node, allow=False, force=False, choose=None,
- moddirstate=True, forcemerge=False, wlock=None, show_stats=True,
- remind=True):
+def update(repo, node, branchmerge=False, force=False, partial=None,
+ wlock=None, show_stats=True, remind=True):
+
+ overwrite = force and not branchmerge
+ forcemerge = force and branchmerge
+
+ if not wlock:
+ wlock = repo.wlock()
+
+ ### check phase
+
pl = repo.dirstate.parents()
- if not force and pl[1] != nullid:
+ if not overwrite and pl[1] != nullid:
raise util.Abort(_("outstanding uncommitted merges"))
- err = False
-
p1, p2 = pl[0], node
pa = repo.changelog.ancestor(p1, p2)
+
+ # is there a linear path from p1 to p2?
+ linear_path = (pa == p1 or pa == p2)
+ if branchmerge and linear_path:
+ raise util.Abort(_("there is nothing to merge, just use "
+ "'hg update' or look at 'hg heads'"))
+
+ if not overwrite and not linear_path and not branchmerge:
+ raise util.Abort(_("update spans branches, use 'hg merge' "
+ "or 'hg update -C' to lose changes"))
+
+ modified, added, removed, deleted, unknown = repo.changes()
+ if branchmerge and not forcemerge:
+ if modified or added or removed:
+ raise util.Abort(_("outstanding uncommitted changes"))
+
m1n = repo.changelog.read(p1)[0]
m2n = repo.changelog.read(p2)[0]
man = repo.manifest.ancestor(m1n, m2n)
@@ -68,20 +90,7 @@ def update(repo, node, allow=False, forc
ma = repo.manifest.read(man)
mfa = repo.manifest.readflags(man)
- modified, added, removed, deleted, unknown = repo.changes()
-
- # is this a jump, or a merge? i.e. is there a linear path
- # from p1 to p2?
- linear_path = (pa == p1 or pa == p2)
-
- if allow and linear_path:
- raise util.Abort(_("there is nothing to merge, just use "
- "'hg update' or look at 'hg heads'"))
- if allow and not forcemerge:
- if modified or added or removed:
- raise util.Abort(_("outstanding uncommitted changes"))
-
- if not forcemerge and not force:
+ if not forcemerge and not overwrite:
for f in unknown:
if f in m2:
t1 = repo.wread(f)
@@ -93,8 +102,8 @@ def update(repo, node, allow=False, forc
# resolve the manifest to determine which files
# we care about merging
repo.ui.note(_("resolving manifests\n"))
- repo.ui.debug(_(" force %s allow %s moddirstate %s linear %s\n") %
- (force, allow, moddirstate, linear_path))
+ repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") %
+ (overwrite, branchmerge, partial and True or False, linear_path))
repo.ui.debug(_(" ancestor %s local %s remote %s\n") %
(short(man), short(m1n), short(m2n)))
@@ -111,9 +120,6 @@ def update(repo, node, allow=False, forc
mw[f] = ""
mfw[f] = util.is_exec(repo.wjoin(f), mfw.get(f, False))
- if moddirstate and not wlock:
- wlock = repo.wlock()
-
for f in deleted + removed:
if f in mw:
del mw[f]
@@ -123,12 +129,12 @@ def update(repo, node, allow=False, forc
# the file, then we need to remove it from the dirstate, to
# prevent the dirstate from listing the file when it is no
# longer in the manifest.
- if moddirstate and linear_path and f not in m2:
+ if not partial and linear_path and f not in m2:
repo.dirstate.forget((f,))
# Compare manifests
for f, n in mw.iteritems():
- if choose and not choose(f):
+ if partial and not partial(f):
continue
if f in m2:
s = 0
@@ -156,7 +162,7 @@ def update(repo, node, allow=False, forc
# are we clobbering?
# is remote's version newer?
# or are we going back in time?
- elif force or m2[f] != a or (p2 == pa and mw[f] == m1[f]):
+ elif overwrite or m2[f] != a or (p2 == pa and mw[f] == m1[f]):
repo.ui.debug(_(" remote %s is newer, get\n") % f)
get[f] = m2[f]
s = 1
@@ -166,7 +172,7 @@ def update(repo, node, allow=False, forc
get[f] = m2[f]
if not s and mfw[f] != mf2[f]:
- if force:
+ if overwrite:
repo.ui.debug(_(" updating permissions for %s\n") % f)
util.set_exec(repo.wjoin(f), mf2[f])
else:
@@ -180,7 +186,7 @@ def update(repo, node, allow=False, forc
elif f in ma:
if n != ma[f]:
r = _("d")
- if not force and (linear_path or allow):
+ if not overwrite and (linear_path or branchmerge):
r = repo.ui.prompt(
(_(" local changed %s which remote deleted\n") % f) +
_("(k)eep or (d)elete?"), _("[kd]"), _("k"))
@@ -191,7 +197,7 @@ def update(repo, node, allow=False, forc
remove.append(f) # other deleted it
else:
# file is created on branch or in working directory
- if force and f not in umap:
+ if overwrite and f not in umap:
repo.ui.debug(_("remote deleted %s, clobbering\n") % f)
remove.append(f)
elif n == m1.get(f, nullid): # same as parent
@@ -204,13 +210,13 @@ def update(repo, node, allow=False, forc
repo.ui.debug(_("working dir created %s, keeping\n") % f)
for f, n in m2.iteritems():
- if choose and not choose(f):
+ if partial and not partial(f):
continue
if f[0] == "/":
continue
if f in ma and n != ma[f]:
r = _("k")
- if not force and (linear_path or allow):
+ if not overwrite and (linear_path or branchmerge):
r = repo.ui.prompt(
(_("remote changed %s which local deleted\n") % f) +
_("(k)eep or (d)elete?"), _("[kd]"), _("k"))
@@ -220,7 +226,7 @@ def update(repo, node, allow=False, forc
repo.ui.debug(_("remote created %s\n") % f)
get[f] = n
else:
- if force or p2 == pa: # going backwards?
+ if overwrite or p2 == pa: # going backwards?
repo.ui.debug(_("local deleted %s, recreating\n") % f)
get[f] = n
else:
@@ -228,31 +234,14 @@ def update(repo, node, allow=False, forc
del mw, m1, m2, ma
- if force:
+ if overwrite:
for f in merge:
get[f] = merge[f][1]
merge = {}
- if linear_path or force:
+ if linear_path or overwrite:
# we don't need to do any magic, just jump to the new rev
- branch_merge = False
p1, p2 = p2, nullid
- else:
- if not allow:
- repo.ui.status(_("this update spans a branch"
- " affecting the following files:\n"))
- fl = merge.keys() + get.keys()
- fl.sort()
- for f in fl:
- cf = ""
- if f in merge:
- cf = _(" (resolve)")
- repo.ui.status(" %s%s\n" % (f, cf))
- repo.ui.warn(_("aborting update spanning branches!\n"))
- repo.ui.status(_("(use 'hg merge' to merge across branches"
- " or 'hg update -C' to lose changes)\n"))
- return 1
- branch_merge = True
xp1 = hex(p1)
xp2 = hex(p2)
@@ -271,14 +260,14 @@ def update(repo, node, allow=False, forc
t = repo.file(f).read(get[f])
repo.wwrite(f, t)
util.set_exec(repo.wjoin(f), mf2[f])
- if moddirstate:
- if branch_merge:
+ if not partial:
+ if branchmerge:
repo.dirstate.update([f], 'n', st_mtime=-1)
else:
repo.dirstate.update([f], 'n')
# merge the tricky bits
- failedmerge = []
+ unresolved = []
files = merge.keys()
files.sort()
for f in files:
@@ -286,11 +275,10 @@ def update(repo, node, allow=False, forc
my, other, flag = merge[f]
ret = merge3(repo, f, my, other, xp1, xp2)
if ret:
- err = True
- failedmerge.append(f)
+ unresolved.append(f)
util.set_exec(repo.wjoin(f), flag)
- if moddirstate:
- if branch_merge:
+ if not partial:
+ if branchmerge:
# We've done a branch merge, mark this file as merged
# so that we properly record the merger later
repo.dirstate.update([f], 'm')
@@ -313,25 +301,25 @@ def update(repo, node, allow=False, forc
if inst.errno != errno.ENOENT:
repo.ui.warn(_("update failed to remove %s: %s!\n") %
(f, inst.strerror))
- if moddirstate:
- if branch_merge:
+ if not partial:
+ if branchmerge:
repo.dirstate.update(remove, 'r')
else:
repo.dirstate.forget(remove)
- if moddirstate:
+ if not partial:
repo.dirstate.setparents(p1, p2)
if show_stats:
stats = ((len(get), _("updated")),
- (len(merge) - len(failedmerge), _("merged")),
+ (len(merge) - len(unresolved), _("merged")),
(len(remove), _("removed")),
- (len(failedmerge), _("unresolved")))
+ (len(unresolved), _("unresolved")))
note = ", ".join([_("%d files %s") % s for s in stats])
repo.ui.status("%s\n" % note)
- if moddirstate:
- if branch_merge:
- if failedmerge:
+ if not partial:
+ if branchmerge:
+ if unresolved:
repo.ui.status(_("There are unresolved merges,"
" you can redo the full merge using:\n"
" hg update -C %s\n"
@@ -340,10 +328,10 @@ def update(repo, node, allow=False, forc
repo.changelog.rev(p2))))
elif remind:
repo.ui.status(_("(branch merge, don't forget to commit)\n"))
- elif failedmerge:
+ elif unresolved:
repo.ui.status(_("There are unresolved merges with"
" locally modified files.\n"))
- repo.hook('update', parent1=xp1, parent2=xxp2, error=int(err))
- return err
+ repo.hook('update', parent1=xp1, parent2=xxp2, error=len(unresolved))
+ return len(unresolved)
--- a/tests/test-merge5.out
+++ b/tests/test-merge5.out
@@ -1,6 +1,3 @@
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
removing b
-this update spans a branch affecting the following files:
- b
-aborting update spanning branches!
-(use 'hg merge' to merge across branches or 'hg update -C' to lose changes)
+abort: update spans branches, use 'hg merge' or 'hg update -C' to lose changes
--- a/tests/test-merge7.out
+++ b/tests/test-merge7.out
@@ -22,7 +22,7 @@ added 1 changesets with 1 changes to 1 f
(run 'hg heads' to see heads, 'hg merge' to merge)
merge: warning: conflicts during merge
resolving manifests
- force False allow True moddirstate True linear False
+ overwrite None branchmerge True partial False linear False
ancestor 055d847dd401 local 2eded9ab0a5c remote 84cf5750dd20
test.txt versions differ, resolve
merging test.txt
--- a/tests/test-up-local-change.out
+++ b/tests/test-up-local-change.out
@@ -17,7 +17,7 @@ date: Mon Jan 12 13:46:40 1970 +0
summary: 1
resolving manifests
- force None allow None moddirstate True linear True
+ overwrite False branchmerge False partial False linear True
ancestor a0c8bcbbb45c local a0c8bcbbb45c remote 1165e8bd193e
a versions differ, resolve
remote created b
@@ -33,7 +33,7 @@ date: Mon Jan 12 13:46:40 1970 +0
summary: 2
resolving manifests
- force None allow None moddirstate True linear True
+ overwrite False branchmerge False partial False linear True
ancestor a0c8bcbbb45c local 1165e8bd193e remote a0c8bcbbb45c
remote deleted b
removing b
@@ -51,7 +51,7 @@ date: Mon Jan 12 13:46:40 1970 +0
summary: 1
resolving manifests
- force None allow None moddirstate True linear True
+ overwrite False branchmerge False partial False linear True
ancestor a0c8bcbbb45c local a0c8bcbbb45c remote 1165e8bd193e
a versions differ, resolve
remote created b
@@ -98,21 +98,12 @@ user: test
date: Mon Jan 12 13:46:40 1970 +0000
summary: 2
-resolving manifests
- force None allow None moddirstate True linear False
- ancestor a0c8bcbbb45c local 1165e8bd193e remote 4096f2872392
- a versions differ, resolve
- b versions differ, resolve
-this update spans a branch affecting the following files:
- a (resolve)
- b (resolve)
-aborting update spanning branches!
-(use 'hg merge' to merge across branches or 'hg update -C' to lose changes)
+abort: update spans branches, use 'hg merge' or 'hg update -C' to lose changes
failed
abort: outstanding uncommitted changes
failed
resolving manifests
- force False allow True moddirstate True linear False
+ overwrite False branchmerge True partial False linear False
ancestor a0c8bcbbb45c local 1165e8bd193e remote 4096f2872392
a versions differ, resolve
b versions differ, resolve
--- a/tests/test-update-reverse.out
+++ b/tests/test-update-reverse.out
@@ -40,7 +40,7 @@ a
side1
side2
resolving manifests
- force 1 allow None moddirstate True linear False
+ overwrite True branchmerge False partial False linear False
ancestor 8515d4bfda76 local 1c0f48f8ece6 remote 0594b9004bae
remote deleted side2, clobbering
remote deleted side1, clobbering