Mercurial > hg
annotate hgext/imerge.py @ 6344:ffeb926d57ce
tests: make test-rebuildstate repeatable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Fri, 21 Mar 2008 15:57:22 -0500 |
parents | c0c4c7b1e8d3 |
children | bc3dbdb1d430 |
rev | line source |
---|---|
5044 | 1 # Copyright (C) 2007 Brendan Cully <brendan@kublai.com> |
2 # Published under the GNU GPL | |
3 | |
4 ''' | |
5 imerge - interactive merge | |
6 ''' | |
7 | |
8 from mercurial.i18n import _ | |
6211
f89fd07fc51d
Expand import * to allow Pyflakes to find problems
Joel Rosdahl <joel@rosdahl.net>
parents:
6003
diff
changeset
|
9 from mercurial.node import hex, short |
6003
7855b88ba838
filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
5241
diff
changeset
|
10 from mercurial import commands, cmdutil, dispatch, fancyopts |
6213
5c5e45766224
imerge: Fix unbound name error and add a test case
Joel Rosdahl <joel@rosdahl.net>
parents:
6211
diff
changeset
|
11 from mercurial import hg, filemerge, util, revlog |
5044 | 12 import os, tarfile |
13 | |
14 class InvalidStateFileException(Exception): pass | |
15 | |
16 class ImergeStateFile(object): | |
17 def __init__(self, im): | |
18 self.im = im | |
19 | |
20 def save(self, dest): | |
21 tf = tarfile.open(dest, 'w:gz') | |
22 | |
23 st = os.path.join(self.im.path, 'status') | |
24 tf.add(st, os.path.join('.hg', 'imerge', 'status')) | |
25 | |
26 for f in self.im.resolved: | |
5109 | 27 (fd, fo) = self.im.conflicts[f] |
28 abssrc = self.im.repo.wjoin(fd) | |
29 tf.add(abssrc, fd) | |
5044 | 30 |
31 tf.close() | |
32 | |
33 def load(self, source): | |
34 wlock = self.im.repo.wlock() | |
35 lock = self.im.repo.lock() | |
36 | |
37 tf = tarfile.open(source, 'r') | |
38 contents = tf.getnames() | |
5164
1d5ebb0d366f
imerge: fix status file lookups
Patrick Mezard <pmezard@gmail.com>
parents:
5143
diff
changeset
|
39 # tarfile normalizes path separators to '/' |
5165
ec24bfd852ab
imerge: simplify 1d5ebb0d366f
Brendan Cully <brendan@kublai.com>
parents:
5164
diff
changeset
|
40 statusfile = '.hg/imerge/status' |
5044 | 41 if statusfile not in contents: |
42 raise InvalidStateFileException('no status file') | |
43 | |
44 tf.extract(statusfile, self.im.repo.root) | |
5109 | 45 p1, p2 = self.im.load() |
46 if self.im.repo.dirstate.parents()[0] != p1.node(): | |
47 hg.clean(self.im.repo, p1.node()) | |
48 self.im.start(p2.node()) | |
5055
56d48aed1f69
imerge: tarfile.extractall is only available in python2.5
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
5054
diff
changeset
|
49 for tarinfo in tf: |
56d48aed1f69
imerge: tarfile.extractall is only available in python2.5
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
5054
diff
changeset
|
50 tf.extract(tarinfo, self.im.repo.root) |
5044 | 51 self.im.load() |
52 | |
53 class Imerge(object): | |
54 def __init__(self, ui, repo): | |
55 self.ui = ui | |
56 self.repo = repo | |
57 | |
58 self.path = repo.join('imerge') | |
59 self.opener = util.opener(self.path) | |
60 | |
5109 | 61 self.wctx = self.repo.workingctx() |
5044 | 62 self.conflicts = {} |
63 self.resolved = [] | |
64 | |
65 def merging(self): | |
5109 | 66 return len(self.wctx.parents()) > 1 |
5044 | 67 |
68 def load(self): | |
69 # status format. \0-delimited file, fields are | |
70 # p1, p2, conflict count, conflict filenames, resolved filenames | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5044
diff
changeset
|
71 # conflict filenames are tuples of localname, remoteorig, remotenew |
5044 | 72 |
73 statusfile = self.opener('status') | |
74 | |
75 status = statusfile.read().split('\0') | |
76 if len(status) < 3: | |
77 raise util.Abort('invalid imerge status file') | |
78 | |
79 try: | |
5109 | 80 parents = [self.repo.changectx(n) for n in status[:2]] |
6213
5c5e45766224
imerge: Fix unbound name error and add a test case
Joel Rosdahl <joel@rosdahl.net>
parents:
6211
diff
changeset
|
81 except revlog.LookupError, e: |
6228
c0c4c7b1e8d3
revlog: report node and file when lookup fails
Matt Mackall <mpm@selenic.com>
parents:
6213
diff
changeset
|
82 raise util.Abort(_('merge parent %s not in repository') % |
c0c4c7b1e8d3
revlog: report node and file when lookup fails
Matt Mackall <mpm@selenic.com>
parents:
6213
diff
changeset
|
83 short(e.name)) |
5044 | 84 |
85 status = status[2:] | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5044
diff
changeset
|
86 conflicts = int(status.pop(0)) * 3 |
5044 | 87 self.resolved = status[conflicts:] |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5044
diff
changeset
|
88 for i in xrange(0, conflicts, 3): |
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5044
diff
changeset
|
89 self.conflicts[status[i]] = (status[i+1], status[i+2]) |
5044 | 90 |
5109 | 91 return parents |
92 | |
5044 | 93 def save(self): |
94 lock = self.repo.lock() | |
95 | |
96 if not os.path.isdir(self.path): | |
97 os.mkdir(self.path) | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
98 statusfile = self.opener('status', 'wb') |
5044 | 99 |
5109 | 100 out = [hex(n.node()) for n in self.wctx.parents()] |
5044 | 101 out.append(str(len(self.conflicts))) |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
102 conflicts = self.conflicts.items() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
103 conflicts.sort() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
104 for fw, fd_fo in conflicts: |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
105 out.append(fw) |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
106 out.extend(fd_fo) |
5044 | 107 out.extend(self.resolved) |
108 | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
109 statusfile.write('\0'.join(out)) |
5044 | 110 |
111 def remaining(self): | |
112 return [f for f in self.conflicts if f not in self.resolved] | |
113 | |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
114 def filemerge(self, fn, interactive=True): |
5044 | 115 wlock = self.repo.wlock() |
116 | |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5044
diff
changeset
|
117 (fd, fo) = self.conflicts[fn] |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
118 p1, p2 = self.wctx.parents() |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
119 |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
120 # this could be greatly improved |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
121 realmerge = os.environ.get('HGMERGE') |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
122 if not interactive: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
123 os.environ['HGMERGE'] = 'merge' |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
124 |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
125 # The filemerge ancestor algorithm does not work if self.wctx |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
126 # already has two parents (in normal merge it doesn't yet). But |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
127 # this is very dirty. |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
128 self.wctx._parents.pop() |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
129 try: |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
130 # TODO: we should probably revert the file if merge fails |
6003
7855b88ba838
filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
5241
diff
changeset
|
131 return filemerge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
132 finally: |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
133 self.wctx._parents.append(p2) |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
134 if realmerge: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
135 os.environ['HGMERGE'] = realmerge |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
136 elif not interactive: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
137 del os.environ['HGMERGE'] |
5044 | 138 |
139 def start(self, rev=None): | |
6003
7855b88ba838
filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
5241
diff
changeset
|
140 _filemerge = filemerge.filemerge |
7855b88ba838
filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
5241
diff
changeset
|
141 def filemerge_(repo, fw, fd, fo, wctx, mctx): |
5054
ec70fd08e16c
Update imerge for new filemerge interface
Brendan Cully <brendan@kublai.com>
parents:
5044
diff
changeset
|
142 self.conflicts[fw] = (fd, fo) |
5044 | 143 |
6003
7855b88ba838
filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
5241
diff
changeset
|
144 filemerge.filemerge = filemerge_ |
5044 | 145 commands.merge(self.ui, self.repo, rev=rev) |
6003
7855b88ba838
filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
5241
diff
changeset
|
146 filemerge.filemerge = _filemerge |
5044 | 147 |
5109 | 148 self.wctx = self.repo.workingctx() |
5044 | 149 self.save() |
150 | |
151 def resume(self): | |
152 self.load() | |
153 | |
154 dp = self.repo.dirstate.parents() | |
5109 | 155 p1, p2 = self.wctx.parents() |
156 if p1.node() != dp[0] or p2.node() != dp[1]: | |
5044 | 157 raise util.Abort('imerge state does not match working directory') |
158 | |
159 def next(self): | |
160 remaining = self.remaining() | |
161 return remaining and remaining[0] | |
162 | |
163 def resolve(self, files): | |
164 resolved = dict.fromkeys(self.resolved) | |
165 for fn in files: | |
166 if fn not in self.conflicts: | |
167 raise util.Abort('%s is not in the merge set' % fn) | |
168 resolved[fn] = True | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
169 self.resolved = resolved.keys() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
170 self.resolved.sort() |
5044 | 171 self.save() |
172 return 0 | |
173 | |
174 def unresolve(self, files): | |
175 resolved = dict.fromkeys(self.resolved) | |
176 for fn in files: | |
177 if fn not in resolved: | |
178 raise util.Abort('%s is not resolved' % fn) | |
179 del resolved[fn] | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
180 self.resolved = resolved.keys() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
181 self.resolved.sort() |
5044 | 182 self.save() |
183 return 0 | |
184 | |
185 def pickle(self, dest): | |
186 '''write current merge state to file to be resumed elsewhere''' | |
187 state = ImergeStateFile(self) | |
188 return state.save(dest) | |
189 | |
190 def unpickle(self, source): | |
191 '''read merge state from file''' | |
192 state = ImergeStateFile(self) | |
193 return state.load(source) | |
194 | |
195 def load(im, source): | |
196 if im.merging(): | |
197 raise util.Abort('there is already a merge in progress ' | |
198 '(update -C <rev> to abort it)' ) | |
199 m, a, r, d = im.repo.status()[:4] | |
200 if m or a or r or d: | |
201 raise util.Abort('working directory has uncommitted changes') | |
202 | |
203 rc = im.unpickle(source) | |
204 if not rc: | |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
205 status(im) |
5044 | 206 return rc |
207 | |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
208 def merge_(im, filename=None, auto=False): |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
209 success = True |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
210 if auto and not filename: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
211 for fn in im.remaining(): |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
212 rc = im.filemerge(fn, interactive=False) |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
213 if rc: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
214 success = False |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
215 else: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
216 im.resolve([fn]) |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
217 if success: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
218 im.ui.write('all conflicts resolved\n') |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
219 else: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
220 status(im) |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
221 return 0 |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
222 |
5044 | 223 if not filename: |
224 filename = im.next() | |
225 if not filename: | |
226 im.ui.write('all conflicts resolved\n') | |
227 return 0 | |
228 | |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
229 rc = im.filemerge(filename, interactive=not auto) |
5044 | 230 if not rc: |
231 im.resolve([filename]) | |
232 if not im.next(): | |
233 im.ui.write('all conflicts resolved\n') | |
234 return rc | |
235 | |
236 def next(im): | |
237 n = im.next() | |
238 if n: | |
239 im.ui.write('%s\n' % n) | |
240 else: | |
241 im.ui.write('all conflicts resolved\n') | |
242 return 0 | |
243 | |
244 def resolve(im, *files): | |
245 if not files: | |
246 raise util.Abort('resolve requires at least one filename') | |
247 return im.resolve(files) | |
248 | |
249 def save(im, dest): | |
250 return im.pickle(dest) | |
251 | |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
252 def status(im, **opts): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
253 if not opts.get('resolved') and not opts.get('unresolved'): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
254 opts['resolved'] = True |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
255 opts['unresolved'] = True |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
256 |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
257 if im.ui.verbose: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
258 p1, p2 = [short(p.node()) for p in im.wctx.parents()] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
259 im.ui.note(_('merging %s and %s\n') % (p1, p2)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
260 |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
261 conflicts = im.conflicts.keys() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
262 conflicts.sort() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
263 remaining = dict.fromkeys(im.remaining()) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
264 st = [] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
265 for fn in conflicts: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
266 if opts.get('no_status'): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
267 mode = '' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
268 elif fn in remaining: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
269 mode = 'U ' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
270 else: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
271 mode = 'R ' |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
272 if ((opts.get('resolved') and fn not in remaining) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
273 or (opts.get('unresolved') and fn in remaining)): |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
274 st.append((mode, fn)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
275 st.sort() |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
276 for (mode, fn) in st: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
277 if im.ui.verbose: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
278 fo, fd = im.conflicts[fn] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
279 if fd != fn: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
280 fn = '%s (%s)' % (fn, fd) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
281 im.ui.write('%s%s\n' % (mode, fn)) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
282 if opts.get('unresolved') and not remaining: |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
283 im.ui.write(_('all conflicts resolved\n')) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
284 |
5044 | 285 return 0 |
286 | |
287 def unresolve(im, *files): | |
288 if not files: | |
289 raise util.Abort('unresolve requires at least one filename') | |
290 return im.unresolve(files) | |
291 | |
292 subcmdtable = { | |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
293 'load': (load, []), |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
294 'merge': |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
295 (merge_, |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
296 [('a', 'auto', None, _('automatically resolve if possible'))]), |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
297 'next': (next, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
298 'resolve': (resolve, []), |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
299 'save': (save, []), |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
300 'status': |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
301 (status, |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
302 [('n', 'no-status', None, _('hide status prefix')), |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
303 ('', 'resolved', None, _('only show resolved conflicts')), |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
304 ('', 'unresolved', None, _('only show unresolved conflicts'))]), |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
305 'unresolve': (unresolve, []) |
5044 | 306 } |
307 | |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
308 def dispatch_(im, args, opts): |
5044 | 309 def complete(s, choices): |
310 candidates = [] | |
311 for choice in choices: | |
312 if choice.startswith(s): | |
313 candidates.append(choice) | |
314 return candidates | |
315 | |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
316 c, args = args[0], list(args[1:]) |
5044 | 317 cmd = complete(c, subcmdtable.keys()) |
318 if not cmd: | |
319 raise cmdutil.UnknownCommand('imerge ' + c) | |
320 if len(cmd) > 1: | |
5056
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
321 cmd.sort() |
34a54cc5df1b
imerge: sorted() is only available in python2.4 and above
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5055
diff
changeset
|
322 raise cmdutil.AmbiguousCommand('imerge ' + c, cmd) |
5044 | 323 cmd = cmd[0] |
324 | |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
325 func, optlist = subcmdtable[cmd] |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
326 opts = {} |
5044 | 327 try: |
5111
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
328 args = fancyopts.fancyopts(args, optlist, opts) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
329 return func(im, *args, **opts) |
12930b97a729
imerge: gussy up dispatcher to support subcommand opts.
Brendan Cully <brendan@kublai.com>
parents:
5110
diff
changeset
|
330 except fancyopts.getopt.GetoptError, inst: |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
331 raise dispatch.ParseError('imerge', '%s: %s' % (cmd, inst)) |
5044 | 332 except TypeError: |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
333 raise dispatch.ParseError('imerge', _('%s: invalid arguments') % cmd) |
5044 | 334 |
335 def imerge(ui, repo, *args, **opts): | |
336 '''interactive merge | |
337 | |
338 imerge lets you split a merge into pieces. When you start a merge | |
339 with imerge, the names of all files with conflicts are recorded. | |
340 You can then merge any of these files, and if the merge is | |
341 successful, they will be marked as resolved. When all files are | |
342 resolved, the merge is complete. | |
343 | |
344 If no merge is in progress, hg imerge [rev] will merge the working | |
345 directory with rev (defaulting to the other head if the repository | |
346 only has two heads). You may also resume a saved merge with | |
347 hg imerge load <file>. | |
348 | |
349 If a merge is in progress, hg imerge will default to merging the | |
350 next unresolved file. | |
351 | |
352 The following subcommands are available: | |
353 | |
354 status: | |
355 show the current state of the merge | |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
356 options: |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
357 -n --no-status: do not print the status prefix |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
358 --resolved: only print resolved conflicts |
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
359 --unresolved: only print unresolved conflicts |
5044 | 360 next: |
361 show the next unresolved file merge | |
362 merge [<file>]: | |
363 merge <file>. If the file merge is successful, the file will be | |
364 recorded as resolved. If no file is given, the next unresolved | |
365 file will be merged. | |
366 resolve <file>...: | |
367 mark files as successfully merged | |
368 unresolve <file>...: | |
369 mark files as requiring merging. | |
370 save <file>: | |
371 save the state of the merge to a file to be resumed elsewhere | |
372 load <file>: | |
373 load the state of the merge from a file created by save | |
374 ''' | |
375 | |
376 im = Imerge(ui, repo) | |
377 | |
378 if im.merging(): | |
379 im.resume() | |
380 else: | |
381 rev = opts.get('rev') | |
382 if rev and args: | |
383 raise util.Abort('please specify just one revision') | |
5143
d4fa6bafc43a
Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5111
diff
changeset
|
384 |
5044 | 385 if len(args) == 2 and args[0] == 'load': |
386 pass | |
387 else: | |
388 if args: | |
389 rev = args[0] | |
390 im.start(rev=rev) | |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
391 if opts.get('auto'): |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
392 args = ['merge', '--auto'] |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
393 else: |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
394 args = ['status'] |
5044 | 395 |
396 if not args: | |
397 args = ['merge'] | |
398 | |
5239
8860f29447c1
imerge: fix ancestor calculation
Brendan Cully <brendan@kublai.com>
parents:
5165
diff
changeset
|
399 return dispatch_(im, args, opts) |
5044 | 400 |
401 cmdtable = { | |
402 '^imerge': | |
403 (imerge, | |
5241
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
404 [('r', 'rev', '', _('revision to merge')), |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
405 ('a', 'auto', None, _('automatically merge where possible'))], |
3786ef8877d5
imerge: add automerge flag to attempt to batch merge all conflicts
Brendan Cully <brendan@kublai.com>
parents:
5239
diff
changeset
|
406 'hg imerge [command]') |
5044 | 407 } |