##// END OF EJS Templates
resolve: new command...
Matt Mackall -
r6518:92ccccb5 default
parent child Browse files
Show More
@@ -13,6 +13,7 b' import hg, util, revlog, bundlerepo, ext'
13 import difflib, patch, time, help, mdiff, tempfile
13 import difflib, patch, time, help, mdiff, tempfile
14 import version, socket
14 import version, socket
15 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
15 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
16 import merge as merge_
16
17
17 # Commands start here, listed alphabetically
18 # Commands start here, listed alphabetically
18
19
@@ -2236,6 +2237,35 b' def rename(ui, repo, *pats, **opts):'
2236 finally:
2237 finally:
2237 del wlock
2238 del wlock
2238
2239
2240 def resolve(ui, repo, *pats, **opts):
2241 """resolve file merges from a branch merge or update
2242
2243 This command will attempt to resolve unresolved merges from the
2244 last update or merge command. This will use the local file
2245 revision preserved at the last update or merge to cleanly retry
2246 the file merge attempt. With no file or options specified, this
2247 command will attempt to resolve all unresolved files.
2248 """
2249
2250 if len([x for x in opts if opts[x]]) > 1:
2251 raise util.Abort(_("too many options specified"))
2252
2253 ms = merge_.mergestate(repo)
2254 mf = util.matcher(repo.root, "", pats, [], [])[1]
2255
2256 for f in ms:
2257 if mf(f):
2258 if opts.get("list"):
2259 ui.write("%s %s\n" % (ms[f].upper(), f))
2260 elif opts.get("mark"):
2261 ms.mark(f, "r")
2262 elif opts.get("unmark"):
2263 ms.mark(f, "u")
2264 else:
2265 wctx = repo.workingctx()
2266 mctx = wctx.parents()[-1]
2267 ms.resolve(f, wctx, mctx)
2268
2239 def revert(ui, repo, *pats, **opts):
2269 def revert(ui, repo, *pats, **opts):
2240 """restore individual files or dirs to an earlier state
2270 """restore individual files or dirs to an earlier state
2241
2271
@@ -3196,6 +3226,12 b' table = {'
3196 _('forcibly copy over an existing managed file')),
3226 _('forcibly copy over an existing managed file')),
3197 ] + walkopts + dryrunopts,
3227 ] + walkopts + dryrunopts,
3198 _('hg rename [OPTION]... SOURCE... DEST')),
3228 _('hg rename [OPTION]... SOURCE... DEST')),
3229 "resolve":
3230 (resolve,
3231 [('l', 'list', None, _('list state of files needing merge')),
3232 ('m', 'mark', None, _('mark files as resolved')),
3233 ('u', 'unmark', None, _('unmark files as resolved'))],
3234 ('hg resolve [OPTION] [FILES...]')),
3199 "revert":
3235 "revert":
3200 (revert,
3236 (revert,
3201 [('a', 'all', None, _('revert all changes when no arguments given')),
3237 [('a', 'all', None, _('revert all changes when no arguments given')),
@@ -271,15 +271,7 b' def update(repo, node):'
271 stats = _merge.update(repo, node, False, False, None)
271 stats = _merge.update(repo, node, False, False, None)
272 _showstats(repo, stats)
272 _showstats(repo, stats)
273 if stats[3]:
273 if stats[3]:
274 repo.ui.status(_("There are unresolved merges with"
274 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
275 " locally modified files.\n"))
276 if stats[1]:
277 repo.ui.status(_("You can finish the partial merge using:\n"))
278 else:
279 repo.ui.status(_("You can redo the full merge using:\n"))
280 # len(pl)==1, otherwise _merge.update() would have raised util.Abort:
281 repo.ui.status(_(" hg update %s\n hg update %s\n")
282 % (pl[0].rev(), repo.changectx(node).rev()))
283 return stats[3] > 0
275 return stats[3] > 0
284
276
285 def clean(repo, node, show_stats=True):
277 def clean(repo, node, show_stats=True):
@@ -294,11 +286,7 b' def merge(repo, node, force=None, remind'
294 _showstats(repo, stats)
286 _showstats(repo, stats)
295 if stats[3]:
287 if stats[3]:
296 pl = repo.parents()
288 pl = repo.parents()
297 repo.ui.status(_("There are unresolved merges,"
289 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
298 " you can redo the full merge using:\n"
299 " hg update -C %s\n"
300 " hg merge %s\n")
301 % (pl[0].rev(), pl[1].rev()))
302 elif remind:
290 elif remind:
303 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
291 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
304 return stats[3] > 0
292 return stats[3] > 0
@@ -5,7 +5,7 b''
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import nullid, nullrev, hex
8 from node import nullid, nullrev, hex, bin
9 from i18n import _
9 from i18n import _
10 import errno, util, os, filemerge, copies, shutil
10 import errno, util, os, filemerge, copies, shutil
11
11
@@ -13,27 +13,49 b' class mergestate(object):'
13 '''track 3-way merge state of individual files'''
13 '''track 3-way merge state of individual files'''
14 def __init__(self, repo):
14 def __init__(self, repo):
15 self._repo = repo
15 self._repo = repo
16 self._read()
17 def reset(self, node):
16 self._state = {}
18 self._state = {}
17 self._data = {}
18 def reset(self, node):
19 self._local = node
19 self._local = node
20 shutil.rmtree(self._repo.join("merge"), True)
20 shutil.rmtree(self._repo.join("merge"), True)
21 def _read(self):
22 self._state = {}
23 try:
24 f = self._repo.opener("merge/state")
25 self._local = bin(f.readline()[:-1])
26 for l in f:
27 bits = l[:-1].split("\0")
28 self._state[bits[0]] = bits[1:]
29 except IOError, err:
30 if err.errno != errno.ENOENT:
31 raise
32 def _write(self):
33 f = self._repo.opener("merge/state", "w")
34 f.write(hex(self._local) + "\n")
35 for d, v in self._state.items():
36 f.write("\0".join([d] + v) + "\n")
21 def add(self, fcl, fco, fca, fd, flags):
37 def add(self, fcl, fco, fca, fd, flags):
22 hash = util.sha1(fcl.path()).hexdigest()
38 hash = util.sha1(fcl.path()).hexdigest()
23 self._repo.opener("merge/" + hash, "w").write(fcl.data())
39 self._repo.opener("merge/" + hash, "w").write(fcl.data())
24 self._state[fd] = 'u'
40 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
25 self._data[fd] = (hash, fcl.path(), fca.path(), hex(fca.filenode()),
41 hex(fca.filenode()), fco.path(), flags]
26 fco.path(), flags)
42 self._write()
27 def __contains__(self, dfile):
43 def __contains__(self, dfile):
28 return dfile in self._state
44 return dfile in self._state
29 def __getitem__(self, dfile):
45 def __getitem__(self, dfile):
30 return self._state[dfile]
46 return self._state[dfile][0]
47 def __iter__(self):
48 l = self._state.keys()
49 l.sort()
50 for f in l:
51 yield f
31 def mark(self, dfile, state):
52 def mark(self, dfile, state):
32 self._state[dfile] = state
53 self._state[dfile][0] = state
54 self._write()
33 def resolve(self, dfile, wctx, octx):
55 def resolve(self, dfile, wctx, octx):
34 if self[dfile] == 'r':
56 if self[dfile] == 'r':
35 return 0
57 return 0
36 hash, lfile, afile, anode, ofile, flags = self._data[dfile]
58 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
37 f = self._repo.opener("merge/" + hash)
59 f = self._repo.opener("merge/" + hash)
38 self._repo.wwrite(dfile, f.read(), flags)
60 self._repo.wwrite(dfile, f.read(), flags)
39 fcd = wctx[dfile]
61 fcd = wctx[dfile]
@@ -41,7 +63,6 b' class mergestate(object):'
41 fca = self._repo.filectx(afile, fileid=anode)
63 fca = self._repo.filectx(afile, fileid=anode)
42 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
64 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
43 if not r:
65 if not r:
44 util.set_flags(self._repo.wjoin(dfile), flags)
45 self.mark(dfile, 'r')
66 self.mark(dfile, 'r')
46 return r
67 return r
47
68
@@ -18,9 +18,7 b' merging a'
18 warning: conflicts during merge.
18 warning: conflicts during merge.
19 merging a failed!
19 merging a failed!
20 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
20 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
21 There are unresolved merges, you can redo the full merge using:
21 use 'hg resolve' to retry unresolved file merges
22 hg update -C 2
23 hg merge 1
24 M a
22 M a
25 ? a.orig
23 ? a.orig
26 % should fail
24 % should fail
@@ -4,9 +4,7 b' merging a'
4 warning: conflicts during merge.
4 warning: conflicts during merge.
5 merging a failed!
5 merging a failed!
6 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
6 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
7 There are unresolved merges, you can redo the full merge using:
7 use 'hg resolve' to retry unresolved file merges
8 hg update -C 2
9 hg merge 1
10 e7fe8eb3e180+0d24b7662d3e+ tip
8 e7fe8eb3e180+0d24b7662d3e+ tip
11 <<<<<<< local
9 <<<<<<< local
12 something else
10 something else
@@ -265,9 +265,7 b' merging b'
265 warning: conflicts during merge.
265 warning: conflicts during merge.
266 merging b failed!
266 merging b failed!
267 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
267 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
268 There are unresolved merges, you can redo the full merge using:
268 use 'hg resolve' to retry unresolved file merges
269 hg update -C 2
270 hg merge 4
271 assuming destination b-hg
269 assuming destination b-hg
272 initializing svn repo 'b-hg'
270 initializing svn repo 'b-hg'
273 initializing svn wc 'b-hg-wc'
271 initializing svn wc 'b-hg-wc'
@@ -33,6 +33,7 b' push'
33 recover
33 recover
34 remove
34 remove
35 rename
35 rename
36 resolve
36 revert
37 revert
37 rollback
38 rollback
38 root
39 root
@@ -79,6 +80,7 b' debugwalk'
79 recover
80 recover
80 remove
81 remove
81 rename
82 rename
83 resolve
82 revert
84 revert
83 rollback
85 rollback
84 root
86 root
@@ -183,6 +183,7 b' list of commands:'
183 recover roll back an interrupted transaction
183 recover roll back an interrupted transaction
184 remove remove the specified files on the next commit
184 remove remove the specified files on the next commit
185 rename rename files; equivalent of copy + remove
185 rename rename files; equivalent of copy + remove
186 resolve resolve file merges from a branch merge or update
186 revert restore individual files or dirs to an earlier state
187 revert restore individual files or dirs to an earlier state
187 rollback roll back the last transaction
188 rollback roll back the last transaction
188 root print the root (top) of the current working dir
189 root print the root (top) of the current working dir
@@ -236,6 +237,7 b' list of commands:'
236 recover roll back an interrupted transaction
237 recover roll back an interrupted transaction
237 remove remove the specified files on the next commit
238 remove remove the specified files on the next commit
238 rename rename files; equivalent of copy + remove
239 rename rename files; equivalent of copy + remove
240 resolve resolve file merges from a branch merge or update
239 revert restore individual files or dirs to an earlier state
241 revert restore individual files or dirs to an earlier state
240 rollback roll back the last transaction
242 rollback roll back the last transaction
241 root print the root (top) of the current working dir
243 root print the root (top) of the current working dir
@@ -74,6 +74,7 b' list of commands:'
74 recover roll back an interrupted transaction
74 recover roll back an interrupted transaction
75 remove remove the specified files on the next commit
75 remove remove the specified files on the next commit
76 rename rename files; equivalent of copy + remove
76 rename rename files; equivalent of copy + remove
77 resolve resolve file merges from a branch merge or update
77 revert restore individual files or dirs to an earlier state
78 revert restore individual files or dirs to an earlier state
78 rollback roll back the last transaction
79 rollback roll back the last transaction
79 root print the root (top) of the current working dir
80 root print the root (top) of the current working dir
@@ -123,6 +124,7 b' use "hg -v help" to show aliases and glo'
123 recover roll back an interrupted transaction
124 recover roll back an interrupted transaction
124 remove remove the specified files on the next commit
125 remove remove the specified files on the next commit
125 rename rename files; equivalent of copy + remove
126 rename rename files; equivalent of copy + remove
127 resolve resolve file merges from a branch merge or update
126 revert restore individual files or dirs to an earlier state
128 revert restore individual files or dirs to an earlier state
127 rollback roll back the last transaction
129 rollback roll back the last transaction
128 root print the root (top) of the current working dir
130 root print the root (top) of the current working dir
@@ -21,10 +21,7 b' merging zzz1_merge_ok'
21 merging zzz2_merge_bad
21 merging zzz2_merge_bad
22 merging zzz2_merge_bad failed!
22 merging zzz2_merge_bad failed!
23 3 files updated, 1 files merged, 2 files removed, 1 files unresolved
23 3 files updated, 1 files merged, 2 files removed, 1 files unresolved
24 There are unresolved merges with locally modified files.
24 use 'hg resolve' to retry unresolved file merges
25 You can finish the partial merge using:
26 hg update 0
27 hg update 1
28 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
25 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
29 --- a/zzz1_merge_ok
26 --- a/zzz1_merge_ok
30 +++ b/zzz1_merge_ok
27 +++ b/zzz1_merge_ok
@@ -42,10 +39,7 b' merging zzz2_merge_bad'
42 warning: conflicts during merge.
39 warning: conflicts during merge.
43 merging zzz2_merge_bad failed!
40 merging zzz2_merge_bad failed!
44 3 files updated, 1 files merged, 2 files removed, 1 files unresolved
41 3 files updated, 1 files merged, 2 files removed, 1 files unresolved
45 There are unresolved merges with locally modified files.
42 use 'hg resolve' to retry unresolved file merges
46 You can finish the partial merge using:
47 hg update 0
48 hg update 1
49 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
43 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
50 --- a/zzz1_merge_ok
44 --- a/zzz1_merge_ok
51 +++ b/zzz1_merge_ok
45 +++ b/zzz1_merge_ok
@@ -13,10 +13,7 b' merging file1'
13 warning: conflicts during merge.
13 warning: conflicts during merge.
14 merging file1 failed!
14 merging file1 failed!
15 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
15 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
16 There are unresolved merges with locally modified files.
16 use 'hg resolve' to retry unresolved file merges
17 You can redo the full merge using:
18 hg update 0
19 hg update 1
20 diff -r f248da0d4c3e file1
17 diff -r f248da0d4c3e file1
21 --- a/file1
18 --- a/file1
22 +++ b/file1
19 +++ b/file1
@@ -11,9 +11,7 b' merging test.txt'
11 warning: conflicts during merge.
11 warning: conflicts during merge.
12 merging test.txt failed!
12 merging test.txt failed!
13 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
13 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
14 There are unresolved merges, you can redo the full merge using:
14 use 'hg resolve' to retry unresolved file merges
15 hg update -C 1
16 hg merge 2
17 pulling from ../test-a
15 pulling from ../test-a
18 searching for changes
16 searching for changes
19 adding changesets
17 adding changesets
@@ -33,9 +31,7 b' my test.txt@451c744aabcc+ other test.txt'
33 warning: conflicts during merge.
31 warning: conflicts during merge.
34 merging test.txt failed!
32 merging test.txt failed!
35 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
33 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
36 There are unresolved merges, you can redo the full merge using:
34 use 'hg resolve' to retry unresolved file merges
37 hg update -C 3
38 hg merge 4
39 one
35 one
40 <<<<<<< local
36 <<<<<<< local
41 two-point-five
37 two-point-five
@@ -23,9 +23,31 b" hg ci -Am 'change foo' -d '0 0'"
23
23
24 # test with the rename on the remote side
24 # test with the rename on the remote side
25 HGMERGE=false hg merge
25 HGMERGE=false hg merge
26 hg resolve -l
26
27
27 # test with the rename on the local side
28 # test with the rename on the local side
28 hg up -C 1
29 hg up -C 1
29 HGMERGE=false hg merge
30 HGMERGE=false hg merge
30
31
32 echo % show unresolved
33 hg resolve -l
34
35 echo % unmark baz
36 hg resolve -u baz
37
38 echo % show
39 hg resolve -l
40
41 echo % re-resolve baz
42 hg resolve baz
43
44 echo % after
45 hg resolve -l
46
47 echo % resolve all
48 hg resolve
49
50 echo % after
51 hg resolve -l
52
31 true
53 true
@@ -7,14 +7,31 b' merging bar'
7 merging bar failed!
7 merging bar failed!
8 merging foo and baz to baz
8 merging foo and baz to baz
9 1 files updated, 1 files merged, 0 files removed, 1 files unresolved
9 1 files updated, 1 files merged, 0 files removed, 1 files unresolved
10 There are unresolved merges, you can redo the full merge using:
10 use 'hg resolve' to retry unresolved file merges
11 hg update -C 2
11 U bar
12 hg merge 1
12 R baz
13 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
13 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
14 merging bar
14 merging bar
15 merging bar failed!
15 merging bar failed!
16 merging baz and foo to baz
16 merging baz and foo to baz
17 1 files updated, 1 files merged, 0 files removed, 1 files unresolved
17 1 files updated, 1 files merged, 0 files removed, 1 files unresolved
18 There are unresolved merges, you can redo the full merge using:
18 use 'hg resolve' to retry unresolved file merges
19 hg update -C 1
19 % show unresolved
20 hg merge 2
20 U bar
21 R baz
22 % unmark baz
23 % show
24 U bar
25 U baz
26 % re-resolve baz
27 merging baz and foo to baz
28 % after
29 U bar
30 R baz
31 % resolve all
32 merging bar
33 warning: conflicts during merge.
34 merging bar failed!
35 % after
36 U bar
37 R baz
General Comments 0
You need to be logged in to leave comments. Login now