resolve: new command
- add basic resolve command functionality
- point failed update and merge at resolve
--- a/mercurial/commands.py Fri Apr 11 12:04:26 2008 +0200
+++ b/mercurial/commands.py Fri Apr 11 12:52:56 2008 -0500
@@ -13,6 +13,7 @@
import difflib, patch, time, help, mdiff, tempfile
import version, socket
import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
+import merge as merge_
# Commands start here, listed alphabetically
@@ -2236,6 +2237,35 @@
finally:
del wlock
+def resolve(ui, repo, *pats, **opts):
+ """resolve file merges from a branch merge or update
+
+ This command will attempt to resolve unresolved merges from the
+ last update or merge command. This will use the local file
+ revision preserved at the last update or merge to cleanly retry
+ the file merge attempt. With no file or options specified, this
+ command will attempt to resolve all unresolved files.
+ """
+
+ if len([x for x in opts if opts[x]]) > 1:
+ raise util.Abort(_("too many options specified"))
+
+ ms = merge_.mergestate(repo)
+ mf = util.matcher(repo.root, "", pats, [], [])[1]
+
+ for f in ms:
+ if mf(f):
+ if opts.get("list"):
+ ui.write("%s %s\n" % (ms[f].upper(), f))
+ elif opts.get("mark"):
+ ms.mark(f, "r")
+ elif opts.get("unmark"):
+ ms.mark(f, "u")
+ else:
+ wctx = repo.workingctx()
+ mctx = wctx.parents()[-1]
+ ms.resolve(f, wctx, mctx)
+
def revert(ui, repo, *pats, **opts):
"""restore individual files or dirs to an earlier state
@@ -3196,6 +3226,12 @@
_('forcibly copy over an existing managed file')),
] + walkopts + dryrunopts,
_('hg rename [OPTION]... SOURCE... DEST')),
+ "resolve":
+ (resolve,
+ [('l', 'list', None, _('list state of files needing merge')),
+ ('m', 'mark', None, _('mark files as resolved')),
+ ('u', 'unmark', None, _('unmark files as resolved'))],
+ ('hg resolve [OPTION] [FILES...]')),
"revert":
(revert,
[('a', 'all', None, _('revert all changes when no arguments given')),
--- a/mercurial/hg.py Fri Apr 11 12:04:26 2008 +0200
+++ b/mercurial/hg.py Fri Apr 11 12:52:56 2008 -0500
@@ -271,15 +271,7 @@
stats = _merge.update(repo, node, False, False, None)
_showstats(repo, stats)
if stats[3]:
- repo.ui.status(_("There are unresolved merges with"
- " locally modified files.\n"))
- if stats[1]:
- repo.ui.status(_("You can finish the partial merge using:\n"))
- else:
- repo.ui.status(_("You can redo the full merge using:\n"))
- # len(pl)==1, otherwise _merge.update() would have raised util.Abort:
- repo.ui.status(_(" hg update %s\n hg update %s\n")
- % (pl[0].rev(), repo.changectx(node).rev()))
+ repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
return stats[3] > 0
def clean(repo, node, show_stats=True):
@@ -294,11 +286,7 @@
_showstats(repo, stats)
if stats[3]:
pl = repo.parents()
- repo.ui.status(_("There are unresolved merges,"
- " you can redo the full merge using:\n"
- " hg update -C %s\n"
- " hg merge %s\n")
- % (pl[0].rev(), pl[1].rev()))
+ repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
elif remind:
repo.ui.status(_("(branch merge, don't forget to commit)\n"))
return stats[3] > 0
--- a/mercurial/merge.py Fri Apr 11 12:04:26 2008 +0200
+++ b/mercurial/merge.py Fri Apr 11 12:52:56 2008 -0500
@@ -5,7 +5,7 @@
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
-from node import nullid, nullrev, hex
+from node import nullid, nullrev, hex, bin
from i18n import _
import errno, util, os, filemerge, copies, shutil
@@ -13,27 +13,49 @@
'''track 3-way merge state of individual files'''
def __init__(self, repo):
self._repo = repo
+ self._read()
+ def reset(self, node):
self._state = {}
- self._data = {}
- def reset(self, node):
self._local = node
shutil.rmtree(self._repo.join("merge"), True)
+ def _read(self):
+ self._state = {}
+ try:
+ f = self._repo.opener("merge/state")
+ self._local = bin(f.readline()[:-1])
+ for l in f:
+ bits = l[:-1].split("\0")
+ self._state[bits[0]] = bits[1:]
+ except IOError, err:
+ if err.errno != errno.ENOENT:
+ raise
+ def _write(self):
+ f = self._repo.opener("merge/state", "w")
+ f.write(hex(self._local) + "\n")
+ for d, v in self._state.items():
+ f.write("\0".join([d] + v) + "\n")
def add(self, fcl, fco, fca, fd, flags):
hash = util.sha1(fcl.path()).hexdigest()
self._repo.opener("merge/" + hash, "w").write(fcl.data())
- self._state[fd] = 'u'
- self._data[fd] = (hash, fcl.path(), fca.path(), hex(fca.filenode()),
- fco.path(), flags)
+ self._state[fd] = ['u', hash, fcl.path(), fca.path(),
+ hex(fca.filenode()), fco.path(), flags]
+ self._write()
def __contains__(self, dfile):
return dfile in self._state
def __getitem__(self, dfile):
- return self._state[dfile]
+ return self._state[dfile][0]
+ def __iter__(self):
+ l = self._state.keys()
+ l.sort()
+ for f in l:
+ yield f
def mark(self, dfile, state):
- self._state[dfile] = state
+ self._state[dfile][0] = state
+ self._write()
def resolve(self, dfile, wctx, octx):
if self[dfile] == 'r':
return 0
- hash, lfile, afile, anode, ofile, flags = self._data[dfile]
+ state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
f = self._repo.opener("merge/" + hash)
self._repo.wwrite(dfile, f.read(), flags)
fcd = wctx[dfile]
@@ -41,7 +63,6 @@
fca = self._repo.filectx(afile, fileid=anode)
r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
if not r:
- util.set_flags(self._repo.wjoin(dfile), flags)
self.mark(dfile, 'r')
return r
--- a/tests/test-add.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-add.out Fri Apr 11 12:52:56 2008 -0500
@@ -18,9 +18,7 @@
warning: conflicts during merge.
merging a failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 2
- hg merge 1
+use 'hg resolve' to retry unresolved file merges
M a
? a.orig
% should fail
--- a/tests/test-conflict.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-conflict.out Fri Apr 11 12:52:56 2008 -0500
@@ -4,9 +4,7 @@
warning: conflicts during merge.
merging a failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 2
- hg merge 1
+use 'hg resolve' to retry unresolved file merges
e7fe8eb3e180+0d24b7662d3e+ tip
<<<<<<< local
something else
--- a/tests/test-convert-svn-sink.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-convert-svn-sink.out Fri Apr 11 12:52:56 2008 -0500
@@ -265,9 +265,7 @@
warning: conflicts during merge.
merging b failed!
2 files updated, 0 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 2
- hg merge 4
+use 'hg resolve' to retry unresolved file merges
assuming destination b-hg
initializing svn repo 'b-hg'
initializing svn wc 'b-hg-wc'
--- a/tests/test-debugcomplete.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-debugcomplete.out Fri Apr 11 12:52:56 2008 -0500
@@ -33,6 +33,7 @@
recover
remove
rename
+resolve
revert
rollback
root
@@ -79,6 +80,7 @@
recover
remove
rename
+resolve
revert
rollback
root
--- a/tests/test-globalopts.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-globalopts.out Fri Apr 11 12:52:56 2008 -0500
@@ -183,6 +183,7 @@
recover roll back an interrupted transaction
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
+ resolve resolve file merges from a branch merge or update
revert restore individual files or dirs to an earlier state
rollback roll back the last transaction
root print the root (top) of the current working dir
@@ -236,6 +237,7 @@
recover roll back an interrupted transaction
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
+ resolve resolve file merges from a branch merge or update
revert restore individual files or dirs to an earlier state
rollback roll back the last transaction
root print the root (top) of the current working dir
--- a/tests/test-help.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-help.out Fri Apr 11 12:52:56 2008 -0500
@@ -74,6 +74,7 @@
recover roll back an interrupted transaction
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
+ resolve resolve file merges from a branch merge or update
revert restore individual files or dirs to an earlier state
rollback roll back the last transaction
root print the root (top) of the current working dir
@@ -123,6 +124,7 @@
recover roll back an interrupted transaction
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
+ resolve resolve file merges from a branch merge or update
revert restore individual files or dirs to an earlier state
rollback roll back the last transaction
root print the root (top) of the current working dir
--- a/tests/test-merge-local.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-merge-local.out Fri Apr 11 12:52:56 2008 -0500
@@ -21,10 +21,7 @@
merging zzz2_merge_bad
merging zzz2_merge_bad failed!
3 files updated, 1 files merged, 2 files removed, 1 files unresolved
-There are unresolved merges with locally modified files.
-You can finish the partial merge using:
- hg update 0
- hg update 1
+use 'hg resolve' to retry unresolved file merges
2 files updated, 0 files merged, 3 files removed, 0 files unresolved
--- a/zzz1_merge_ok
+++ b/zzz1_merge_ok
@@ -42,10 +39,7 @@
warning: conflicts during merge.
merging zzz2_merge_bad failed!
3 files updated, 1 files merged, 2 files removed, 1 files unresolved
-There are unresolved merges with locally modified files.
-You can finish the partial merge using:
- hg update 0
- hg update 1
+use 'hg resolve' to retry unresolved file merges
2 files updated, 0 files merged, 3 files removed, 0 files unresolved
--- a/zzz1_merge_ok
+++ b/zzz1_merge_ok
--- a/tests/test-merge-revert2.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-merge-revert2.out Fri Apr 11 12:52:56 2008 -0500
@@ -13,10 +13,7 @@
warning: conflicts during merge.
merging file1 failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges with locally modified files.
-You can redo the full merge using:
- hg update 0
- hg update 1
+use 'hg resolve' to retry unresolved file merges
diff -r f248da0d4c3e file1
--- a/file1
+++ b/file1
--- a/tests/test-merge7.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-merge7.out Fri Apr 11 12:52:56 2008 -0500
@@ -11,9 +11,7 @@
warning: conflicts during merge.
merging test.txt failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 1
- hg merge 2
+use 'hg resolve' to retry unresolved file merges
pulling from ../test-a
searching for changes
adding changesets
@@ -33,9 +31,7 @@
warning: conflicts during merge.
merging test.txt failed!
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 3
- hg merge 4
+use 'hg resolve' to retry unresolved file merges
one
<<<<<<< local
two-point-five
--- a/tests/test-merge9 Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-merge9 Fri Apr 11 12:52:56 2008 -0500
@@ -23,9 +23,31 @@
# test with the rename on the remote side
HGMERGE=false hg merge
+hg resolve -l
# test with the rename on the local side
hg up -C 1
HGMERGE=false hg merge
+echo % show unresolved
+hg resolve -l
+
+echo % unmark baz
+hg resolve -u baz
+
+echo % show
+hg resolve -l
+
+echo % re-resolve baz
+hg resolve baz
+
+echo % after
+hg resolve -l
+
+echo % resolve all
+hg resolve
+
+echo % after
+hg resolve -l
+
true
--- a/tests/test-merge9.out Fri Apr 11 12:04:26 2008 +0200
+++ b/tests/test-merge9.out Fri Apr 11 12:52:56 2008 -0500
@@ -7,14 +7,31 @@
merging bar failed!
merging foo and baz to baz
1 files updated, 1 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 2
- hg merge 1
+use 'hg resolve' to retry unresolved file merges
+U bar
+R baz
3 files updated, 0 files merged, 1 files removed, 0 files unresolved
merging bar
merging bar failed!
merging baz and foo to baz
1 files updated, 1 files merged, 0 files removed, 1 files unresolved
-There are unresolved merges, you can redo the full merge using:
- hg update -C 1
- hg merge 2
+use 'hg resolve' to retry unresolved file merges
+% show unresolved
+U bar
+R baz
+% unmark baz
+% show
+U bar
+U baz
+% re-resolve baz
+merging baz and foo to baz
+% after
+U bar
+R baz
+% resolve all
+merging bar
+warning: conflicts during merge.
+merging bar failed!
+% after
+U bar
+R baz