Show More
@@ -7,7 +7,7 imerge - interactive merge | |||||
7 |
|
7 | |||
8 | from mercurial.i18n import _ |
|
8 | from mercurial.i18n import _ | |
9 | from mercurial.node import * |
|
9 | from mercurial.node import * | |
10 | from mercurial import commands, cmdutil, fancyopts, hg, merge, util |
|
10 | from mercurial import commands, cmdutil, dispatch, fancyopts, hg, merge, util | |
11 | import os, tarfile |
|
11 | import os, tarfile | |
12 |
|
12 | |||
13 | class InvalidStateFileException(Exception): pass |
|
13 | class InvalidStateFileException(Exception): pass | |
@@ -109,12 +109,30 class Imerge(object): | |||||
109 | def remaining(self): |
|
109 | def remaining(self): | |
110 | return [f for f in self.conflicts if f not in self.resolved] |
|
110 | return [f for f in self.conflicts if f not in self.resolved] | |
111 |
|
111 | |||
112 | def filemerge(self, fn): |
|
112 | def filemerge(self, fn, interactive=True): | |
113 | wlock = self.repo.wlock() |
|
113 | wlock = self.repo.wlock() | |
114 |
|
114 | |||
115 | (fd, fo) = self.conflicts[fn] |
|
115 | (fd, fo) = self.conflicts[fn] | |
116 |
p2 = self.wctx.parents() |
|
116 | p1, p2 = self.wctx.parents() | |
|
117 | ||||
|
118 | # this could be greatly improved | |||
|
119 | realmerge = os.environ.get('HGMERGE') | |||
|
120 | if not interactive: | |||
|
121 | os.environ['HGMERGE'] = 'merge' | |||
|
122 | ||||
|
123 | # The filemerge ancestor algorithm does not work if self.wctx | |||
|
124 | # already has two parents (in normal merge it doesn't yet). But | |||
|
125 | # this is very dirty. | |||
|
126 | self.wctx._parents.pop() | |||
|
127 | try: | |||
|
128 | # TODO: we should probably revert the file if merge fails | |||
117 | return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) |
|
129 | return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) | |
|
130 | finally: | |||
|
131 | self.wctx._parents.append(p2) | |||
|
132 | if realmerge: | |||
|
133 | os.environ['HGMERGE'] = realmerge | |||
|
134 | elif not interactive: | |||
|
135 | del os.environ['HGMERGE'] | |||
118 |
|
136 | |||
119 | def start(self, rev=None): |
|
137 | def start(self, rev=None): | |
120 | _filemerge = merge.filemerge |
|
138 | _filemerge = merge.filemerge | |
@@ -185,19 +203,32 def load(im, source): | |||||
185 | status(im) |
|
203 | status(im) | |
186 | return rc |
|
204 | return rc | |
187 |
|
205 | |||
188 | def merge_(im, filename=None): |
|
206 | def merge_(im, filename=None, auto=False): | |
|
207 | success = True | |||
|
208 | if auto and not filename: | |||
|
209 | for fn in im.remaining(): | |||
|
210 | rc = im.filemerge(fn, interactive=False) | |||
|
211 | if rc: | |||
|
212 | success = False | |||
|
213 | else: | |||
|
214 | im.resolve([fn]) | |||
|
215 | if success: | |||
|
216 | im.ui.write('all conflicts resolved\n') | |||
|
217 | else: | |||
|
218 | status(im) | |||
|
219 | return 0 | |||
|
220 | ||||
189 | if not filename: |
|
221 | if not filename: | |
190 | filename = im.next() |
|
222 | filename = im.next() | |
191 | if not filename: |
|
223 | if not filename: | |
192 | im.ui.write('all conflicts resolved\n') |
|
224 | im.ui.write('all conflicts resolved\n') | |
193 | return 0 |
|
225 | return 0 | |
194 |
|
226 | |||
195 | rc = im.filemerge(filename) |
|
227 | rc = im.filemerge(filename, interactive=not auto) | |
196 | if not rc: |
|
228 | if not rc: | |
197 | im.resolve([filename]) |
|
229 | im.resolve([filename]) | |
198 | if not im.next(): |
|
230 | if not im.next(): | |
199 | im.ui.write('all conflicts resolved\n') |
|
231 | im.ui.write('all conflicts resolved\n') | |
200 | return 0 |
|
|||
201 | return rc |
|
232 | return rc | |
202 |
|
233 | |||
203 | def next(im): |
|
234 | def next(im): | |
@@ -258,18 +289,21 def unresolve(im, *files): | |||||
258 |
|
289 | |||
259 | subcmdtable = { |
|
290 | subcmdtable = { | |
260 | 'load': (load, []), |
|
291 | 'load': (load, []), | |
261 |
'merge': |
|
292 | 'merge': | |
|
293 | (merge_, | |||
|
294 | [('a', 'auto', None, _('automatically resolve if possible'))]), | |||
262 | 'next': (next, []), |
|
295 | 'next': (next, []), | |
263 | 'resolve': (resolve, []), |
|
296 | 'resolve': (resolve, []), | |
264 | 'save': (save, []), |
|
297 | 'save': (save, []), | |
265 |
'status': |
|
298 | 'status': | |
|
299 | (status, | |||
266 |
|
|
300 | [('n', 'no-status', None, _('hide status prefix')), | |
267 |
|
|
301 | ('', 'resolved', None, _('only show resolved conflicts')), | |
268 |
|
|
302 | ('', 'unresolved', None, _('only show unresolved conflicts'))]), | |
269 | 'unresolve': (unresolve, []) |
|
303 | 'unresolve': (unresolve, []) | |
270 | } |
|
304 | } | |
271 |
|
305 | |||
272 | def dispatch(im, args, opts): |
|
306 | def dispatch_(im, args, opts): | |
273 | def complete(s, choices): |
|
307 | def complete(s, choices): | |
274 | candidates = [] |
|
308 | candidates = [] | |
275 | for choice in choices: |
|
309 | for choice in choices: | |
@@ -292,9 +326,9 def dispatch(im, args, opts): | |||||
292 | args = fancyopts.fancyopts(args, optlist, opts) |
|
326 | args = fancyopts.fancyopts(args, optlist, opts) | |
293 | return func(im, *args, **opts) |
|
327 | return func(im, *args, **opts) | |
294 | except fancyopts.getopt.GetoptError, inst: |
|
328 | except fancyopts.getopt.GetoptError, inst: | |
295 |
raise |
|
329 | raise dispatch.ParseError('imerge', '%s: %s' % (cmd, inst)) | |
296 | except TypeError: |
|
330 | except TypeError: | |
297 |
raise |
|
331 | raise dispatch.ParseError('imerge', _('%s: invalid arguments') % cmd) | |
298 |
|
332 | |||
299 | def imerge(ui, repo, *args, **opts): |
|
333 | def imerge(ui, repo, *args, **opts): | |
300 | '''interactive merge |
|
334 | '''interactive merge | |
@@ -317,6 +351,10 def imerge(ui, repo, *args, **opts): | |||||
317 |
|
351 | |||
318 | status: |
|
352 | status: | |
319 | show the current state of the merge |
|
353 | show the current state of the merge | |
|
354 | options: | |||
|
355 | -n --no-status: do not print the status prefix | |||
|
356 | --resolved: only print resolved conflicts | |||
|
357 | --unresolved: only print unresolved conflicts | |||
320 | next: |
|
358 | next: | |
321 | show the next unresolved file merge |
|
359 | show the next unresolved file merge | |
322 | merge [<file>]: |
|
360 | merge [<file>]: | |
@@ -348,15 +386,20 def imerge(ui, repo, *args, **opts): | |||||
348 | if args: |
|
386 | if args: | |
349 | rev = args[0] |
|
387 | rev = args[0] | |
350 | im.start(rev=rev) |
|
388 | im.start(rev=rev) | |
|
389 | if opts.get('auto'): | |||
|
390 | args = ['merge', '--auto'] | |||
|
391 | else: | |||
351 | args = ['status'] |
|
392 | args = ['status'] | |
352 |
|
393 | |||
353 | if not args: |
|
394 | if not args: | |
354 | args = ['merge'] |
|
395 | args = ['merge'] | |
355 |
|
396 | |||
356 | return dispatch(im, args, opts) |
|
397 | return dispatch_(im, args, opts) | |
357 |
|
398 | |||
358 | cmdtable = { |
|
399 | cmdtable = { | |
359 | '^imerge': |
|
400 | '^imerge': | |
360 | (imerge, |
|
401 | (imerge, | |
361 |
[('r', 'rev', '', _('revision to merge')) |
|
402 | [('r', 'rev', '', _('revision to merge')), | |
|
403 | ('a', 'auto', None, _('automatically merge where possible'))], | |||
|
404 | 'hg imerge [command]') | |||
362 | } |
|
405 | } |
General Comments 0
You need to be logged in to leave comments.
Login now