comparison hgext/imerge.py @ 5065:12930b97a729

imerge: gussy up dispatcher to support subcommand opts. Add -n, --resolved, --unresolved to status.
author Brendan Cully <brendan@kublai.com>
date Sat, 04 Aug 2007 12:26:48 -0700
parents 420e1166a876
children d4fa6bafc43a
comparison
equal deleted inserted replaced
5064:420e1166a876 5065:12930b97a729
5 imerge - interactive merge 5 imerge - interactive merge
6 ''' 6 '''
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, hg, merge, util 10 from mercurial import commands, cmdutil, fancyopts, hg, merge, util
11 import os, tarfile 11 import os, tarfile
12 12
13 class InvalidStateFileException(Exception): pass 13 class InvalidStateFileException(Exception): pass
14 14
15 class ImergeStateFile(object): 15 class ImergeStateFile(object):
132 132
133 dp = self.repo.dirstate.parents() 133 dp = self.repo.dirstate.parents()
134 p1, p2 = self.wctx.parents() 134 p1, p2 = self.wctx.parents()
135 if p1.node() != dp[0] or p2.node() != dp[1]: 135 if p1.node() != dp[0] or p2.node() != dp[1]:
136 raise util.Abort('imerge state does not match working directory') 136 raise util.Abort('imerge state does not match working directory')
137
138 def status(self):
139 p1, p2 = self.wctx.parents()
140 self.ui.write('merging %s and %s\n' % \
141 (short(p1.node()), short(p2.node())))
142
143 if self.resolved:
144 self.ui.write('resolved:\n')
145 for fn in self.resolved:
146 self.ui.write(' %s\n' % fn)
147 remaining = [f for f in self.conflicts if f not in self.resolved]
148 if remaining:
149 self.ui.write('remaining:\n')
150 for fn in remaining:
151 (fd, fo) = self.conflicts[fn]
152 if fn == fo:
153 self.ui.write(' %s\n' % (fn,))
154 else:
155 self.ui.write(' %s (%s)\n' % (fn, fd))
156 else:
157 self.ui.write('all conflicts resolved\n')
158 137
159 def next(self): 138 def next(self):
160 remaining = self.remaining() 139 remaining = self.remaining()
161 return remaining and remaining[0] 140 return remaining and remaining[0]
162 141
200 if m or a or r or d: 179 if m or a or r or d:
201 raise util.Abort('working directory has uncommitted changes') 180 raise util.Abort('working directory has uncommitted changes')
202 181
203 rc = im.unpickle(source) 182 rc = im.unpickle(source)
204 if not rc: 183 if not rc:
205 im.status() 184 status(im)
206 return rc 185 return rc
207 186
208 def merge_(im, filename=None): 187 def merge_(im, filename=None):
209 if not filename: 188 if not filename:
210 filename = im.next() 189 filename = im.next()
234 return im.resolve(files) 213 return im.resolve(files)
235 214
236 def save(im, dest): 215 def save(im, dest):
237 return im.pickle(dest) 216 return im.pickle(dest)
238 217
239 def status(im): 218 def status(im, **opts):
240 im.status() 219 if not opts.get('resolved') and not opts.get('unresolved'):
220 opts['resolved'] = True
221 opts['unresolved'] = True
222
223 if im.ui.verbose:
224 p1, p2 = [short(p.node()) for p in im.wctx.parents()]
225 im.ui.note(_('merging %s and %s\n') % (p1, p2))
226
227 conflicts = im.conflicts.keys()
228 conflicts.sort()
229 remaining = dict.fromkeys(im.remaining())
230 st = []
231 for fn in conflicts:
232 if opts.get('no_status'):
233 mode = ''
234 elif fn in remaining:
235 mode = 'U '
236 else:
237 mode = 'R '
238 if ((opts.get('resolved') and fn not in remaining)
239 or (opts.get('unresolved') and fn in remaining)):
240 st.append((mode, fn))
241 st.sort()
242 for (mode, fn) in st:
243 if im.ui.verbose:
244 fo, fd = im.conflicts[fn]
245 if fd != fn:
246 fn = '%s (%s)' % (fn, fd)
247 im.ui.write('%s%s\n' % (mode, fn))
248 if opts.get('unresolved') and not remaining:
249 im.ui.write(_('all conflicts resolved\n'))
250
241 return 0 251 return 0
242 252
243 def unresolve(im, *files): 253 def unresolve(im, *files):
244 if not files: 254 if not files:
245 raise util.Abort('unresolve requires at least one filename') 255 raise util.Abort('unresolve requires at least one filename')
246 return im.unresolve(files) 256 return im.unresolve(files)
247 257
248 subcmdtable = { 258 subcmdtable = {
249 'load': load, 259 'load': (load, []),
250 'merge': merge_, 260 'merge': (merge_, []),
251 'next': next, 261 'next': (next, []),
252 'resolve': resolve, 262 'resolve': (resolve, []),
253 'save': save, 263 'save': (save, []),
254 'status': status, 264 'status': (status,
255 'unresolve': unresolve 265 [('n', 'no-status', None, _('hide status prefix')),
266 ('', 'resolved', None, _('only show resolved conflicts')),
267 ('', 'unresolved', None, _('only show unresolved conflicts'))]),
268 'unresolve': (unresolve, [])
256 } 269 }
257 270
258 def dispatch(im, args, opts): 271 def dispatch(im, args, opts):
259 def complete(s, choices): 272 def complete(s, choices):
260 candidates = [] 273 candidates = []
261 for choice in choices: 274 for choice in choices:
262 if choice.startswith(s): 275 if choice.startswith(s):
263 candidates.append(choice) 276 candidates.append(choice)
264 return candidates 277 return candidates
265 278
266 c, args = args[0], args[1:] 279 c, args = args[0], list(args[1:])
267 cmd = complete(c, subcmdtable.keys()) 280 cmd = complete(c, subcmdtable.keys())
268 if not cmd: 281 if not cmd:
269 raise cmdutil.UnknownCommand('imerge ' + c) 282 raise cmdutil.UnknownCommand('imerge ' + c)
270 if len(cmd) > 1: 283 if len(cmd) > 1:
271 cmd.sort() 284 cmd.sort()
272 raise cmdutil.AmbiguousCommand('imerge ' + c, cmd) 285 raise cmdutil.AmbiguousCommand('imerge ' + c, cmd)
273 cmd = cmd[0] 286 cmd = cmd[0]
274 287
275 func = subcmdtable[cmd] 288 func, optlist = subcmdtable[cmd]
289 opts = {}
276 try: 290 try:
277 return func(im, *args) 291 args = fancyopts.fancyopts(args, optlist, opts)
292 return func(im, *args, **opts)
293 except fancyopts.getopt.GetoptError, inst:
294 raise cmdutil.ParseError('imerge', '%s: %s' % (cmd, inst))
278 except TypeError: 295 except TypeError:
279 raise cmdutil.ParseError('imerge', '%s: invalid arguments' % cmd) 296 raise cmdutil.ParseError('imerge', _('%s: invalid arguments') % cmd)
280 297
281 def imerge(ui, repo, *args, **opts): 298 def imerge(ui, repo, *args, **opts):
282 '''interactive merge 299 '''interactive merge
283 300
284 imerge lets you split a merge into pieces. When you start a merge 301 imerge lets you split a merge into pieces. When you start a merge