##// END OF EJS Templates
hgweb: add file sizes to manifest browsing
hgweb: add file sizes to manifest browsing

File last commit:

r3303:488d3062 default
r3305:0708bdb4 default
Show More
merge.py
463 lines | 15.1 KiB | text/x-python | PythonLexer
Matt Mackall
Move merge code to its own module...
r2775 # merge.py - directory-level update/merge handling for Mercurial
#
# Copyright 2006 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
from node import *
from i18n import gettext as _
from demandload import *
Benoit Boissinot
fix errors reported by pychecker...
r3018 demandload(globals(), "errno util os tempfile")
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
filemerge: use contexts rather than my and other
r3299 def filemerge(repo, fw, fo, fd, wctx, mctx, move):
Matt Mackall
merge: extend file merge function for renames
r3211 """perform a 3-way merge in the working directory
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: extend file merge function for renames
r3211 fw = filename in the working directory and first parent
fo = filename in other parent
fd = destination filename
Matt Mackall
merge: pass contexts to applyupdates
r3297 wctx, mctx = working and merge changecontexts
Matt Mackall
merge: extend file merge function for renames
r3211 move = whether to move or copy the file to the destination
TODO:
if fw is copied in the working directory, we get confused
implement move and fd
"""
def temp(prefix, ctx):
pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
Matt Mackall
Move merge code to its own module...
r2775 (fd, name) = tempfile.mkstemp(prefix=pre)
f = os.fdopen(fd, "wb")
Matt Mackall
merge: extend file merge function for renames
r3211 repo.wwrite(ctx.path(), ctx.data(), f)
Matt Mackall
Move merge code to its own module...
r2775 f.close()
return name
Matt Mackall
filemerge: use contexts rather than my and other
r3299 fcm = wctx.filectx(fw)
fco = mctx.filectx(fo)
Matt Mackall
merge: extend file merge function for renames
r3211 fca = fcm.ancestor(fco)
if not fca:
fca = repo.filectx(fw, fileid=-1)
a = repo.wjoin(fw)
b = temp("base", fca)
c = temp("other", fco)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: extend file merge function for renames
r3211 repo.ui.note(_("resolving %s\n") % fw)
repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
Matt Mackall
Move merge code to its own module...
r2775
cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
or "hgmerge")
r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
Matt Mackall
merge: extend file merge function for renames
r3211 environ={'HG_FILE': fw,
Matt Mackall
merge: pass contexts to applyupdates
r3297 'HG_MY_NODE': str(wctx.parents()[0]),
'HG_OTHER_NODE': str(mctx)})
Matt Mackall
Move merge code to its own module...
r2775 if r:
Matt Mackall
merge: extend file merge function for renames
r3211 repo.ui.warn(_("merging %s failed!\n") % fw)
Matt Mackall
merge: add rename following...
r3249 else:
if fd != fw:
repo.ui.debug(_("copying %s to %s\n") % (fw, fd))
repo.wwrite(fd, repo.wread(fw))
if move:
repo.ui.debug(_("removing %s\n") % fw)
os.unlink(a)
Matt Mackall
Move merge code to its own module...
r2775
os.unlink(b)
os.unlink(c)
return r
Matt Mackall
merge: use new working context object in update
r3218 def checkunknown(repo, m2, wctx):
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 """
check for collisions between unknown files and files in m2
"""
Matt Mackall
merge: use new working context object in update
r3218 for f in wctx.unknown():
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 if f in m2:
if repo.file(f).cmp(m2[f], repo.wread(f)):
raise util.Abort(_("'%s' already exists in the working"
" dir and differs from remote") % f)
Matt Mackall
merge: use new working context object in update
r3218 def forgetremoved(m2, wctx):
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 """
Forget removed files
If we're jumping between revisions (as opposed to merging), and if
neither the working directory nor the target rev has 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.
"""
action = []
Matt Mackall
merge: use new working context object in update
r3218 for f in wctx.deleted() + wctx.removed():
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 if f not in m2:
action.append((f, "f"))
return action
Matt Mackall
Add core copy detection algorithm...
r3153 def nonoverlap(d1, d2):
"""
Return list of elements in d1 not in d2
"""
l = []
for d in d1:
if d not in d2:
l.append(d)
l.sort()
return l
def findold(fctx, limit):
"""
find files that path was copied from, back to linkrev limit
"""
old = {}
orig = fctx.path()
visit = [fctx]
while visit:
fc = visit.pop()
if fc.rev() < limit:
continue
if fc.path() != orig and fc.path() not in old:
old[fc.path()] = 1
visit += fc.parents()
old = old.keys()
old.sort()
return old
def findcopies(repo, m1, m2, limit):
"""
Find moves and copies between m1 and m2 back to limit linkrev
"""
Matt Mackall
merge: add rename following...
r3249 if not repo.ui.config("merge", "followcopies"):
return {}
Matt Mackall
findcopies: shortcut for empty working dir
r3160 # avoid silly behavior for update from empty dir
if not m1:
return {}
Matt Mackall
findcopies: use dirstate rename information
r3155 dcopies = repo.dirstate.copies()
Matt Mackall
Add core copy detection algorithm...
r3153 copy = {}
match = {}
u1 = nonoverlap(m1, m2)
u2 = nonoverlap(m2, m1)
ctx = util.cachefunc(lambda f,n: repo.filectx(f, fileid=n[:20]))
def checkpair(c, f2, man):
''' check if an apparent pair actually matches '''
c2 = ctx(f2, man[f2])
ca = c.ancestor(c2)
Matt Mackall
merge: fixes for merge+rename...
r3251 if ca and ca.path() == c.path() or ca.path() == c2.path():
Matt Mackall
Add core copy detection algorithm...
r3153 copy[c.path()] = f2
copy[f2] = c.path()
for f in u1:
Matt Mackall
findcopies: use dirstate rename information
r3155 c = ctx(dcopies.get(f, f), m1[f])
Matt Mackall
Add core copy detection algorithm...
r3153 for of in findold(c, limit):
if of in m2:
checkpair(c, of, m2)
else:
match.setdefault(of, []).append(f)
for f in u2:
c = ctx(f, m2[f])
for of in findold(c, limit):
if of in m1:
checkpair(c, of, m1)
elif of in match:
for mf in match[of]:
checkpair(c, mf, m1)
return copy
Matt Mackall
merge: use contexts for manifestmerge...
r3295 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Merge manifest m1 with m2 using ancestor ma and generate merge action list
"""
Matt Mackall
merge: use contexts for manifestmerge...
r3295 m1 = p1.manifest()
m2 = p2.manifest()
ma = pa.manifest()
backwards = (pa == p2)
Matt Mackall
merge: add rename following...
r3249 def fmerge(f, f2=None, fa=None):
Matt Mackall
merge: simplify exec flag handling
r3118 """merge executable flags"""
Matt Mackall
merge: add rename following...
r3249 if not f2:
f2 = f
fa = f
a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
Matt Mackall
merge: simplify exec flag handling
r3118 return ((a^b) | (a^c)) ^ a
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 action = []
Matt Mackall
merge: simplify actions with helper function
r3121 def act(msg, f, m, *args):
Matt Mackall
merge: use contexts for manifestmerge...
r3295 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
Matt Mackall
merge: simplify actions with helper function
r3121 action.append((f, m) + args)
Matt Mackall
merge: use contexts for manifestmerge...
r3295 copy = {}
if not (backwards or overwrite):
copy = findcopies(repo, m1, m2, pa.rev())
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # Compare manifests
for f, n in m1.iteritems():
Matt Mackall
merge: reduce manifest copying
r3248 if partial and not partial(f):
continue
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 if f in m2:
# are files different?
if n != m2[f]:
a = ma.get(f, nullid)
# are both different from the ancestor?
if not overwrite and n != a and m2[f] != a:
Matt Mackall
merge: eliminate nodes from action list...
r3303 act("versions differ", f, "m", fmerge(f))
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # are we clobbering?
# is remote's version newer?
# or are we going back in time and clean?
elif overwrite or m2[f] != a or (backwards and not n[20:]):
Matt Mackall
merge: simplify actions with helper function
r3121 act("remote is newer", f, "g", m2.execf(f), m2[f])
Matt Mackall
merge: eliminate confusing queued variable
r3113 # local is newer, not overwrite, check mode bits
Matt Mackall
merge: simplify exec flag handling
r3118 elif fmerge(f) != m1.execf(f):
Matt Mackall
merge: simplify actions with helper function
r3121 act("update permissions", f, "e", m2.execf(f))
Matt Mackall
merge: eliminate confusing queued variable
r3113 # contents same, check mode bits
elif m1.execf(f) != m2.execf(f):
Matt Mackall
merge: simplify local created logic
r3120 if overwrite or fmerge(f) != m1.execf(f):
Matt Mackall
merge: simplify actions with helper function
r3121 act("update permissions", f, "e", m2.execf(f))
Matt Mackall
merge: add rename following...
r3249 elif f in copy:
f2 = copy[f]
if f in ma: # case 3,20 A/B/A
act("remote moved",
Matt Mackall
merge: eliminate nodes from action list...
r3303 f, "c", f2, f2, fmerge(f, f2, f), True)
Matt Mackall
merge: add rename following...
r3249 else:
if f2 in m1: # case 2 A,B/B/B
act("local copied",
Matt Mackall
merge: eliminate nodes from action list...
r3303 f, "c", f2, f, fmerge(f, f2, f2), False)
Matt Mackall
merge: add rename following...
r3249 else: # case 4,21 A/B/B
act("local moved",
Matt Mackall
merge: eliminate nodes from action list...
r3303 f, "c", f2, f, fmerge(f, f2, f2), False)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 elif f in ma:
Matt Mackall
merge: simplify tests for local changed/remote deleted
r3117 if n != ma[f] and not overwrite:
Matt Mackall
merge: use contexts for manifestmerge...
r3295 if repo.ui.prompt(
Matt Mackall
merge: simplify tests for local changed/remote deleted
r3117 (_(" local changed %s which remote deleted\n") % f) +
Matt Mackall
merge: simplify prompt code
r3119 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
Matt Mackall
merge: simplify actions with helper function
r3121 act("prompt delete", f, "r")
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 else:
Matt Mackall
merge: simplify actions with helper function
r3121 act("other deleted", f, "r")
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 else:
# file is created on branch or in working directory
Matt Mackall
merge: simplify local created logic
r3120 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
Matt Mackall
merge: simplify actions with helper function
r3121 act("remote deleted", f, "r")
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
for f, n in m2.iteritems():
Matt Mackall
merge: reduce manifest copying
r3248 if partial and not partial(f):
continue
if f in m1:
continue
Matt Mackall
merge: add rename following...
r3249 if f in copy:
f2 = copy[f]
Matt Mackall
merge: copy fixes and tests...
r3252 if f2 not in m2: # already seen
Matt Mackall
merge: add rename following...
r3249 continue
# rename case 1, A/A,B/A
Matt Mackall
merge: eliminate nodes from action list...
r3303 act("remote copied", f2, "c", f, f, fmerge(f2, f, f2), False)
Matt Mackall
merge: add rename following...
r3249 elif f in ma:
Matt Mackall
merge: more simplification of m2 manifest scanning
r3116 if overwrite or backwards:
Matt Mackall
merge: simplify actions with helper function
r3121 act("recreating", f, "g", m2.execf(f), n)
Matt Mackall
merge: more simplification of m2 manifest scanning
r3116 elif n != ma[f]:
Matt Mackall
merge: use contexts for manifestmerge...
r3295 if repo.ui.prompt(
Matt Mackall
merge: more simplification of m2 manifest scanning
r3116 (_("remote changed %s which local deleted\n") % f) +
Matt Mackall
merge: simplify prompt code
r3119 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"):
Matt Mackall
merge: simplify actions with helper function
r3121 act("prompt recreating", f, "g", m2.execf(f), n)
Matt Mackall
merge: reorder tests on m2 items in manifestmerge
r3115 else:
Matt Mackall
merge: simplify actions with helper function
r3121 act("remote created", f, "g", m2.execf(f), n)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
return action
Matt Mackall
merge: pass contexts to applyupdates
r3297 def applyupdates(repo, action, wctx, mctx):
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 updated, merged, removed, unresolved = 0, 0, 0, 0
action.sort()
for a in action:
f, m = a[:2]
if f[0] == "/":
continue
if m == "r": # remove
repo.ui.note(_("removing %s\n") % f)
util.audit_path(f)
try:
util.unlink(repo.wjoin(f))
except OSError, inst:
if inst.errno != errno.ENOENT:
repo.ui.warn(_("update failed to remove %s: %s!\n") %
(f, inst.strerror))
removed +=1
Matt Mackall
merge: add rename following...
r3249 elif m == "c": # copy
Matt Mackall
merge: eliminate nodes from action list...
r3303 f2, fd, flag, move = a[2:]
Matt Mackall
merge: copy fixes and tests...
r3252 repo.ui.status(_("merging %s and %s to %s\n") % (f, f2, fd))
Matt Mackall
filemerge: use contexts rather than my and other
r3299 if filemerge(repo, f, f2, fd, wctx, mctx, move):
Matt Mackall
merge: add rename following...
r3249 unresolved += 1
util.set_exec(repo.wjoin(fd), flag)
merged += 1
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 elif m == "m": # merge
Matt Mackall
merge: eliminate nodes from action list...
r3303 flag = a[2]
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 repo.ui.status(_("merging %s\n") % f)
Matt Mackall
filemerge: use contexts rather than my and other
r3299 if filemerge(repo, f, f, f, wctx, mctx, False):
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 unresolved += 1
util.set_exec(repo.wjoin(f), flag)
merged += 1
elif m == "g": # get
flag, node = a[2:]
repo.ui.note(_("getting %s\n") % f)
Matt Mackall
merge: eliminate nodes from action list...
r3303 t = mctx.filectx(f).data()
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 repo.wwrite(f, t)
util.set_exec(repo.wjoin(f), flag)
updated += 1
elif m == "e": # exec
Matt Mackall
merge: eliminate nodes from action list...
r3303 flag = a[2]
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 util.set_exec(repo.wjoin(f), flag)
return updated, merged, removed, unresolved
Matt Mackall
merge: eliminate nodes from action list...
r3303 def recordupdates(repo, action, branchmerge, mctx):
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 for a in action:
f, m = a[:2]
if m == "r": # remove
if branchmerge:
repo.dirstate.update([f], 'r')
else:
repo.dirstate.forget([f])
elif m == "f": # forget
repo.dirstate.forget([f])
elif m == "g": # get
if branchmerge:
repo.dirstate.update([f], 'n', st_mtime=-1)
else:
repo.dirstate.update([f], 'n')
elif m == "m": # merge
Matt Mackall
merge: eliminate nodes from action list...
r3303 flag = a[2]
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 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')
else:
# We've update-merged a locally modified file, so
# we set the dirstate to emulate a normal checkout
# of that file some time in the past. Thus our
# merge will appear as a normal local file
# modification.
fl = repo.file(f)
Matt Mackall
merge: eliminate nodes from action list...
r3303 f_len = mctx.filectx(f).size()
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1)
Matt Mackall
merge: fixes for merge+rename...
r3251 elif m == "c": # copy
Matt Mackall
merge: eliminate nodes from action list...
r3303 f2, fd, flag, move = a[2:]
Matt Mackall
merge: fixes for merge+rename...
r3251 if branchmerge:
# We've done a branch merge, mark this file as merged
# so that we properly record the merger later
repo.dirstate.update([fd], 'm')
else:
# We've update-merged a locally modified file, so
# we set the dirstate to emulate a normal checkout
# of that file some time in the past. Thus our
# merge will appear as a normal local file
# modification.
fl = repo.file(f)
Matt Mackall
merge: eliminate nodes from action list...
r3303 f_len = mctx.filectx(f).size()
Matt Mackall
merge: fixes for merge+rename...
r3251 repo.dirstate.update([fd], 'n', st_size=f_len, st_mtime=-1)
if move:
repo.dirstate.update([f], 'r')
if f != fd:
repo.dirstate.copy(f, fd)
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292 else:
repo.dirstate.copy(f2, fd)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
Matt Mackall
Merge: combine choose and moddirstate to partial
r2811 def update(repo, node, branchmerge=False, force=False, partial=None,
Matt Mackall
Merge: combine force and forcemerge arguments
r2815 wlock=None, show_stats=True, remind=True):
overwrite = force and not branchmerge
forcemerge = force and branchmerge
Matt Mackall
Refactor update locking slightly
r2812
if not wlock:
wlock = repo.wlock()
Matt Mackall
Merge: move most tests to the beginning
r2814 ### check phase
Matt Mackall
merge: use new working context object in update
r3218 wc = repo.workingctx()
pl = wc.parents()
Matt Mackall
merge: use repo.parents and parent contexts in update
r3167 if not overwrite and len(pl) > 1:
Matt Mackall
Move merge code to its own module...
r2775 raise util.Abort(_("outstanding uncommitted merges"))
Matt Mackall
merge: use repo.parents and parent contexts in update
r3167 p1, p2 = pl[0], repo.changectx(node)
pa = p1.ancestor(p2)
Matt Mackall
Merge: move most tests to the beginning
r2814
# is there a linear path from p1 to p2?
Matt Mackall
merge: remove linear variable
r3110 if pa == p1 or pa == p2:
if branchmerge:
raise util.Abort(_("there is nothing to merge, just use "
"'hg update' or look at 'hg heads'"))
elif not (overwrite or branchmerge):
Matt Mackall
Merge: combine force and forcemerge arguments
r2815 raise util.Abort(_("update spans branches, use 'hg merge' "
Matt Mackall
Merge: move most tests to the beginning
r2814 "or 'hg update -C' to lose changes"))
if branchmerge and not forcemerge:
Matt Mackall
merge: use new working context object in update
r3218 if wc.modified() or wc.added() or wc.removed():
Matt Mackall
Merge: move most tests to the beginning
r2814 raise util.Abort(_("outstanding uncommitted changes"))
Matt Mackall
merge: reduce manifest copying
r3248 m1 = wc.manifest()
m2 = p2.manifest()
Matt Mackall
Move merge code to its own module...
r2775
# resolve the manifest to determine which files
# we care about merging
repo.ui.note(_("resolving manifests\n"))
Matt Mackall
merge: remove linear variable
r3110 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s\n") %
(overwrite, branchmerge, bool(partial)))
Matt Mackall
merge: use repo.parents and parent contexts in update
r3167 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (p1, p2, pa))
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: convert actions to list
r3100 action = []
Matt Mackall
findcopies: use dirstate rename information
r3155
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 if not force:
Matt Mackall
merge: use new working context object in update
r3218 checkunknown(repo, m2, wc)
Matt Mackall
merge: remove linear variable
r3110 if not branchmerge:
Matt Mackall
merge: use new working context object in update
r3218 action += forgetremoved(m2, wc)
Matt Mackall
Add core copy detection algorithm...
r3153
Matt Mackall
merge: use contexts for manifestmerge...
r3295 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: move forgets to the apply stage
r2897 ### apply phase
Matt Mackall
merge: remove linear variable
r3110 if not branchmerge:
Matt Mackall
merge: don't call hooks for revert...
r3296 # just jump to the new rev
fp1, fp2, xp1, xp2 = p2.node(), nullid, str(p2), ''
else:
fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: don't call hooks for revert...
r3296 if not partial:
repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: pass contexts to applyupdates
r3297 updated, merged, removed, unresolved = applyupdates(repo, action, wc, p2)
Matt Mackall
merge: consolidate dirstate updates
r2899
# update dirstate
if not partial:
Matt Mackall
merge: eliminate nodes from action list...
r3303 recordupdates(repo, action, branchmerge, p2)
Matt Mackall
merge: don't call hooks for revert...
r3296 repo.dirstate.setparents(fp1, fp2)
repo.hook('update', parent1=xp1, parent2=xp2, error=unresolved)
Matt Mackall
Move merge code to its own module...
r2775
if show_stats:
Matt Mackall
merge: combine merge and get lists
r2977 stats = ((updated, _("updated")),
Matt Mackall
merge: make unresolved a counter
r2980 (merged - unresolved, _("merged")),
Matt Mackall
merge: add remove to the action hash
r2978 (removed, _("removed")),
Matt Mackall
merge: make unresolved a counter
r2980 (unresolved, _("unresolved")))
Matt Mackall
Move merge code to its own module...
r2775 note = ", ".join([_("%d files %s") % s for s in stats])
repo.ui.status("%s\n" % note)
Matt Mackall
Merge: combine choose and moddirstate to partial
r2811 if not partial:
Matt Mackall
Rename merge.allow -> merge.branchmerge
r2810 if branchmerge:
Matt Mackall
Merge: refactor err and failedmerge -> unresolved
r2813 if unresolved:
Matt Mackall
Move merge code to its own module...
r2775 repo.ui.status(_("There are unresolved merges,"
" you can redo the full merge using:\n"
" hg update -C %s\n"
" hg merge %s\n"
Matt Mackall
merge: use repo.parents and parent contexts in update
r3167 % (p1.rev(), p2.rev())))
Matt Mackall
Merge with crew
r2803 elif remind:
Matt Mackall
Move merge code to its own module...
r2775 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
Matt Mackall
Merge: refactor err and failedmerge -> unresolved
r2813 elif unresolved:
Matt Mackall
Move merge code to its own module...
r2775 repo.ui.status(_("There are unresolved merges with"
" locally modified files.\n"))
Matt Mackall
merge: make unresolved a counter
r2980 return unresolved
Matt Mackall
Move merge code to its own module...
r2775