##// END OF EJS Templates
shelve: some docstring cleanups
Augie Fackler -
r19911:1c58e368 default
parent child Browse files
Show More
@@ -1,632 +1,633 b''
1 1 # shelve.py - save/restore working directory state
2 2 #
3 3 # Copyright 2013 Facebook, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 """save and restore changes to the working directory
9 9
10 10 The "hg shelve" command saves changes made to the working directory
11 11 and reverts those changes, resetting the working directory to a clean
12 12 state.
13 13
14 14 Later on, the "hg unshelve" command restores the changes saved by "hg
15 15 shelve". Changes can be restored even after updating to a different
16 16 parent, in which case Mercurial's merge machinery will resolve any
17 17 conflicts if necessary.
18 18
19 19 You can have more than one shelved change outstanding at a time; each
20 20 shelved change has a distinct name. For details, see the help for "hg
21 21 shelve".
22 22 """
23 23
24 24 from mercurial.i18n import _
25 25 from mercurial.node import nullid, bin, hex
26 26 from mercurial import changegroup, cmdutil, scmutil, phases
27 27 from mercurial import error, hg, mdiff, merge, patch, repair, util
28 28 from mercurial import templatefilters
29 29 from mercurial import lock as lockmod
30 30 import errno
31 31
32 32 cmdtable = {}
33 33 command = cmdutil.command(cmdtable)
34 34 testedwith = 'internal'
35 35
36 36 class shelvedfile(object):
37 37 """Helper for the file storing a single shelve
38 38
39 39 Handles common functions on shelve files (.hg/.files/.patch) using
40 40 the vfs layer"""
41 41 def __init__(self, repo, name, filetype=None):
42 42 self.repo = repo
43 43 self.name = name
44 44 self.vfs = scmutil.vfs(repo.join('shelved'))
45 45 if filetype:
46 46 self.fname = name + '.' + filetype
47 47 else:
48 48 self.fname = name
49 49
50 50 def exists(self):
51 51 return self.vfs.exists(self.fname)
52 52
53 53 def filename(self):
54 54 return self.vfs.join(self.fname)
55 55
56 56 def unlink(self):
57 57 util.unlink(self.filename())
58 58
59 59 def stat(self):
60 60 return self.vfs.stat(self.fname)
61 61
62 62 def opener(self, mode='rb'):
63 63 try:
64 64 return self.vfs(self.fname, mode)
65 65 except IOError, err:
66 66 if err.errno != errno.ENOENT:
67 67 raise
68 68 if mode[0] in 'wa':
69 69 try:
70 70 self.vfs.mkdir()
71 71 return self.vfs(self.fname, mode)
72 72 except IOError, err:
73 73 if err.errno != errno.EEXIST:
74 74 raise
75 75 elif mode[0] == 'r':
76 76 raise util.Abort(_("shelved change '%s' not found") %
77 77 self.name)
78 78
79 79 class shelvedstate(object):
80 """Handle persistences during unshelving operation.
80 """Handle persistence during unshelving operations.
81 81
82 82 Handles saving and restoring a shelved state. Ensures that different
83 versions of a shelved state are possible and handles them appropriate"""
83 versions of a shelved state are possible and handles them appropriately.
84 """
84 85 _version = 1
85 86 _filename = 'shelvedstate'
86 87
87 88 @classmethod
88 89 def load(cls, repo):
89 90 fp = repo.opener(cls._filename)
90 91 try:
91 92 version = int(fp.readline().strip())
92 93
93 94 if version != cls._version:
94 95 raise util.Abort(_('this version of shelve is incompatible '
95 96 'with the version used in this repo'))
96 97 name = fp.readline().strip()
97 98 parents = [bin(h) for h in fp.readline().split()]
98 99 stripnodes = [bin(h) for h in fp.readline().split()]
99 100 finally:
100 101 fp.close()
101 102
102 103 obj = cls()
103 104 obj.name = name
104 105 obj.parents = parents
105 106 obj.stripnodes = stripnodes
106 107
107 108 return obj
108 109
109 110 @classmethod
110 111 def save(cls, repo, name, stripnodes):
111 112 fp = repo.opener(cls._filename, 'wb')
112 113 fp.write('%i\n' % cls._version)
113 114 fp.write('%s\n' % name)
114 115 fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
115 116 fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
116 117 fp.close()
117 118
118 119 @classmethod
119 120 def clear(cls, repo):
120 121 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
121 122
122 123 def createcmd(ui, repo, pats, opts):
123 """subcommand that create a new shelve"""
124 """subcommand that creates a new shelve"""
124 125
125 126 def publicancestors(ctx):
126 127 """Compute the heads of the public ancestors of a commit.
127 128
128 129 Much faster than the revset heads(ancestors(ctx) - draft())"""
129 130 seen = set()
130 131 visit = util.deque()
131 132 visit.append(ctx)
132 133 while visit:
133 134 ctx = visit.popleft()
134 135 for parent in ctx.parents():
135 136 rev = parent.rev()
136 137 if rev not in seen:
137 138 seen.add(rev)
138 139 if parent.mutable():
139 140 visit.append(parent)
140 141 else:
141 142 yield parent.node()
142 143
143 144 wctx = repo[None]
144 145 parents = wctx.parents()
145 146 if len(parents) > 1:
146 147 raise util.Abort(_('cannot shelve while merging'))
147 148 parent = parents[0]
148 149
149 150 # we never need the user, so we use a generic user for all shelve operations
150 151 user = 'shelve@localhost'
151 152 label = repo._bookmarkcurrent or parent.branch() or 'default'
152 153
153 154 # slashes aren't allowed in filenames, therefore we rename it
154 155 origlabel, label = label, label.replace('/', '_')
155 156
156 157 def gennames():
157 158 yield label
158 159 for i in xrange(1, 100):
159 160 yield '%s-%02d' % (label, i)
160 161
161 162 shelvedfiles = []
162 163
163 164 def commitfunc(ui, repo, message, match, opts):
164 165 # check modified, added, removed, deleted only
165 166 for flist in repo.status(match=match)[:4]:
166 167 shelvedfiles.extend(flist)
167 168 hasmq = util.safehasattr(repo, 'mq')
168 169 if hasmq:
169 170 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
170 171 try:
171 172 return repo.commit(message, user, opts.get('date'), match)
172 173 finally:
173 174 if hasmq:
174 175 repo.mq.checkapplied = saved
175 176
176 177 if parent.node() != nullid:
177 178 desc = parent.description().split('\n', 1)[0]
178 179 else:
179 180 desc = '(empty repository)'
180 181
181 182 if not opts['message']:
182 183 opts['message'] = desc
183 184
184 185 name = opts['name']
185 186
186 187 wlock = lock = tr = bms = None
187 188 try:
188 189 wlock = repo.wlock()
189 190 lock = repo.lock()
190 191
191 192 bms = repo._bookmarks.copy()
192 193 # use an uncommited transaction to generate the bundle to avoid
193 194 # pull races. ensure we don't print the abort message to stderr.
194 195 tr = repo.transaction('commit', report=lambda x: None)
195 196
196 197 if name:
197 198 if shelvedfile(repo, name, 'hg').exists():
198 199 raise util.Abort(_("a shelved change named '%s' already exists")
199 200 % name)
200 201 else:
201 202 for n in gennames():
202 203 if not shelvedfile(repo, n, 'hg').exists():
203 204 name = n
204 205 break
205 206 else:
206 207 raise util.Abort(_("too many shelved changes named '%s'") %
207 208 label)
208 209
209 210 # ensure we are not creating a subdirectory or a hidden file
210 211 if '/' in name or '\\' in name:
211 212 raise util.Abort(_('shelved change names may not contain slashes'))
212 213 if name.startswith('.'):
213 214 raise util.Abort(_("shelved change names may not start with '.'"))
214 215
215 216 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
216 217
217 218 if not node:
218 219 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
219 220 if stat[3]:
220 221 ui.status(_("nothing changed (%d missing files, see "
221 222 "'hg status')\n") % len(stat[3]))
222 223 else:
223 224 ui.status(_("nothing changed\n"))
224 225 return 1
225 226
226 227 phases.retractboundary(repo, phases.secret, [node])
227 228
228 229 fp = shelvedfile(repo, name, 'files').opener('wb')
229 230 fp.write('\0'.join(shelvedfiles))
230 231
231 232 bases = list(publicancestors(repo[node]))
232 233 cg = repo.changegroupsubset(bases, [node], 'shelve')
233 234 changegroup.writebundle(cg, shelvedfile(repo, name, 'hg').filename(),
234 235 'HG10UN')
235 236 cmdutil.export(repo, [node],
236 237 fp=shelvedfile(repo, name, 'patch').opener('wb'),
237 238 opts=mdiff.diffopts(git=True))
238 239
239 240
240 241 if ui.formatted():
241 242 desc = util.ellipsis(desc, ui.termwidth())
242 243 ui.status(_('shelved as %s\n') % name)
243 244 hg.update(repo, parent.node())
244 245 finally:
245 246 if bms:
246 247 # restore old bookmarks
247 248 repo._bookmarks.update(bms)
248 249 repo._bookmarks.write()
249 250 if tr:
250 251 tr.abort()
251 252 lockmod.release(lock, wlock)
252 253
253 254 def cleanupcmd(ui, repo):
254 """subcommand that delete all shelves"""
255 """subcommand that deletes all shelves"""
255 256
256 257 wlock = None
257 258 try:
258 259 wlock = repo.wlock()
259 260 for (name, _) in repo.vfs.readdir('shelved'):
260 261 suffix = name.rsplit('.', 1)[-1]
261 262 if suffix in ('hg', 'files', 'patch'):
262 263 shelvedfile(repo, name).unlink()
263 264 finally:
264 265 lockmod.release(wlock)
265 266
266 267 def deletecmd(ui, repo, pats):
267 """subcommand that delete a specific shelve"""
268 """subcommand that deletes a specific shelve"""
268 269 if not pats:
269 270 raise util.Abort(_('no shelved changes specified!'))
270 271 wlock = None
271 272 try:
272 273 wlock = repo.wlock()
273 274 try:
274 275 for name in pats:
275 276 for suffix in 'hg files patch'.split():
276 277 shelvedfile(repo, name, suffix).unlink()
277 278 except OSError, err:
278 279 if err.errno != errno.ENOENT:
279 280 raise
280 281 raise util.Abort(_("shelved change '%s' not found") % name)
281 282 finally:
282 283 lockmod.release(wlock)
283 284
284 285 def listshelves(repo):
285 """return all shelves in repo as list of (time, filename)"""
286 """return all shelves in repo as list of (time, filename)"""
286 287 try:
287 288 names = repo.vfs.readdir('shelved')
288 289 except OSError, err:
289 290 if err.errno != errno.ENOENT:
290 291 raise
291 292 return []
292 293 info = []
293 294 for (name, _) in names:
294 295 pfx, sfx = name.rsplit('.', 1)
295 296 if not pfx or sfx != 'patch':
296 297 continue
297 298 st = shelvedfile(repo, name).stat()
298 299 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
299 300 return sorted(info, reverse=True)
300 301
301 302 def listcmd(ui, repo, pats, opts):
302 """subcommand that display the list of shelve"""
303 """subcommand that displays the list of shelves"""
303 304 pats = set(pats)
304 305 width = 80
305 306 if not ui.plain():
306 307 width = ui.termwidth()
307 308 namelabel = 'shelve.newest'
308 309 for mtime, name in listshelves(repo):
309 310 sname = util.split(name)[1]
310 311 if pats and sname not in pats:
311 312 continue
312 313 ui.write(sname, label=namelabel)
313 314 namelabel = 'shelve.name'
314 315 if ui.quiet:
315 316 ui.write('\n')
316 317 continue
317 318 ui.write(' ' * (16 - len(sname)))
318 319 used = 16
319 320 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
320 321 ui.write(age, label='shelve.age')
321 322 ui.write(' ' * (12 - len(age)))
322 323 used += 12
323 324 fp = open(name + '.patch', 'rb')
324 325 try:
325 326 while True:
326 327 line = fp.readline()
327 328 if not line:
328 329 break
329 330 if not line.startswith('#'):
330 331 desc = line.rstrip()
331 332 if ui.formatted():
332 333 desc = util.ellipsis(desc, width - used)
333 334 ui.write(desc)
334 335 break
335 336 ui.write('\n')
336 337 if not (opts['patch'] or opts['stat']):
337 338 continue
338 339 difflines = fp.readlines()
339 340 if opts['patch']:
340 341 for chunk, label in patch.difflabel(iter, difflines):
341 342 ui.write(chunk, label=label)
342 343 if opts['stat']:
343 344 for chunk, label in patch.diffstatui(difflines, width=width,
344 345 git=True):
345 346 ui.write(chunk, label=label)
346 347 finally:
347 348 fp.close()
348 349
349 350 def readshelvedfiles(repo, basename):
350 """return the list of file touched in a shelve"""
351 """return the list of files touched in a shelve"""
351 352 fp = shelvedfile(repo, basename, 'files').opener()
352 353 return fp.read().split('\0')
353 354
354 355 def checkparents(repo, state):
355 356 """check parent while resuming an unshelve"""
356 357 if state.parents != repo.dirstate.parents():
357 358 raise util.Abort(_('working directory parents do not match unshelve '
358 359 'state'))
359 360
360 361 def unshelveabort(ui, repo, state, opts):
361 362 """subcommand that abort an in-progress unshelve"""
362 363 wlock = repo.wlock()
363 364 lock = None
364 365 try:
365 366 checkparents(repo, state)
366 367 lock = repo.lock()
367 368 merge.mergestate(repo).reset()
368 369 if opts['keep']:
369 370 repo.setparents(repo.dirstate.parents()[0])
370 371 else:
371 372 revertfiles = readshelvedfiles(repo, state.name)
372 373 wctx = repo.parents()[0]
373 374 cmdutil.revert(ui, repo, wctx, [wctx.node(), nullid],
374 375 *revertfiles, **{'no_backup': True})
375 376 # fix up the weird dirstate states the merge left behind
376 377 mf = wctx.manifest()
377 378 dirstate = repo.dirstate
378 379 for f in revertfiles:
379 380 if f in mf:
380 381 dirstate.normallookup(f)
381 382 else:
382 383 dirstate.drop(f)
383 384 dirstate._pl = (wctx.node(), nullid)
384 385 dirstate._dirty = True
385 386 repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
386 387 shelvedstate.clear(repo)
387 388 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
388 389 finally:
389 390 lockmod.release(lock, wlock)
390 391
391 392 def unshelvecleanup(ui, repo, name, opts):
392 """remove related file after an unshelve"""
393 """remove related files after an unshelve"""
393 394 if not opts['keep']:
394 395 for filetype in 'hg files patch'.split():
395 396 shelvedfile(repo, name, filetype).unlink()
396 397
397 398 def finishmerge(ui, repo, ms, stripnodes, name, opts):
398 399 # Reset the working dir so it's no longer in a merge state.
399 400 dirstate = repo.dirstate
400 401 dirstate.setparents(dirstate._pl[0])
401 402 shelvedstate.clear(repo)
402 403
403 404 def unshelvecontinue(ui, repo, state, opts):
404 405 """subcommand to continue an in-progress unshelve"""
405 406 # We're finishing off a merge. First parent is our original
406 407 # parent, second is the temporary "fake" commit we're unshelving.
407 408 wlock = repo.wlock()
408 409 lock = None
409 410 try:
410 411 checkparents(repo, state)
411 412 ms = merge.mergestate(repo)
412 413 if [f for f in ms if ms[f] == 'u']:
413 414 raise util.Abort(
414 415 _("unresolved conflicts, can't continue"),
415 416 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
416 417 finishmerge(ui, repo, ms, state.stripnodes, state.name, opts)
417 418 lock = repo.lock()
418 419 repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
419 420 unshelvecleanup(ui, repo, state.name, opts)
420 421 ui.status(_("unshelve of '%s' complete\n") % state.name)
421 422 finally:
422 423 lockmod.release(lock, wlock)
423 424
424 425 @command('unshelve',
425 426 [('a', 'abort', None,
426 427 _('abort an incomplete unshelve operation')),
427 428 ('c', 'continue', None,
428 429 _('continue an incomplete unshelve operation')),
429 430 ('', 'keep', None,
430 431 _('keep shelve after unshelving'))],
431 432 _('hg unshelve [SHELVED]'))
432 433 def unshelve(ui, repo, *shelved, **opts):
433 434 """restore a shelved change to the working directory
434 435
435 436 This command accepts an optional name of a shelved change to
436 437 restore. If none is given, the most recent shelved change is used.
437 438
438 439 If a shelved change is applied successfully, the bundle that
439 440 contains the shelved changes is deleted afterwards.
440 441
441 442 Since you can restore a shelved change on top of an arbitrary
442 443 commit, it is possible that unshelving will result in a conflict
443 444 between your changes and the commits you are unshelving onto. If
444 445 this occurs, you must resolve the conflict, then use
445 446 ``--continue`` to complete the unshelve operation. (The bundle
446 447 will not be deleted until you successfully complete the unshelve.)
447 448
448 449 (Alternatively, you can use ``--abort`` to abandon an unshelve
449 450 that causes a conflict. This reverts the unshelved changes, and
450 451 does not delete the bundle.)
451 452 """
452 453 abortf = opts['abort']
453 454 continuef = opts['continue']
454 455 if not abortf and not continuef:
455 456 cmdutil.checkunfinished(repo)
456 457
457 458 if abortf or continuef:
458 459 if abortf and continuef:
459 460 raise util.Abort(_('cannot use both abort and continue'))
460 461 if shelved:
461 462 raise util.Abort(_('cannot combine abort/continue with '
462 463 'naming a shelved change'))
463 464
464 465 try:
465 466 state = shelvedstate.load(repo)
466 467 except IOError, err:
467 468 if err.errno != errno.ENOENT:
468 469 raise
469 470 raise util.Abort(_('no unshelve operation underway'))
470 471
471 472 if abortf:
472 473 return unshelveabort(ui, repo, state, opts)
473 474 elif continuef:
474 475 return unshelvecontinue(ui, repo, state, opts)
475 476 elif len(shelved) > 1:
476 477 raise util.Abort(_('can only unshelve one change at a time'))
477 478 elif not shelved:
478 479 shelved = listshelves(repo)
479 480 if not shelved:
480 481 raise util.Abort(_('no shelved changes to apply!'))
481 482 basename = util.split(shelved[0][1])[1]
482 483 ui.status(_("unshelving change '%s'\n") % basename)
483 484 else:
484 485 basename = shelved[0]
485 486
486 487 shelvedfiles = readshelvedfiles(repo, basename)
487 488
488 489 m, a, r, d = repo.status()[:4]
489 490 unsafe = set(m + a + r + d).intersection(shelvedfiles)
490 491 if unsafe:
491 492 ui.warn(_('the following shelved files have been modified:\n'))
492 493 for f in sorted(unsafe):
493 494 ui.warn(' %s\n' % f)
494 495 ui.warn(_('you must commit, revert, or shelve your changes before you '
495 496 'can proceed\n'))
496 497 raise util.Abort(_('cannot unshelve due to local changes\n'))
497 498
498 499 wlock = lock = tr = None
499 500 try:
500 501 lock = repo.lock()
501 502
502 503 tr = repo.transaction('unshelve', report=lambda x: None)
503 504 oldtiprev = len(repo)
504 505 try:
505 506 fp = shelvedfile(repo, basename, 'hg').opener()
506 507 gen = changegroup.readbundle(fp, fp.name)
507 508 repo.addchangegroup(gen, 'unshelve', 'bundle:' + fp.name)
508 509 nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)]
509 510 phases.retractboundary(repo, phases.secret, nodes)
510 511 tr.close()
511 512 finally:
512 513 fp.close()
513 514
514 515 tip = repo['tip']
515 516 wctx = repo['.']
516 517 ancestor = tip.ancestor(wctx)
517 518
518 519 wlock = repo.wlock()
519 520
520 521 if ancestor.node() != wctx.node():
521 522 conflicts = hg.merge(repo, tip.node(), force=True, remind=False)
522 523 ms = merge.mergestate(repo)
523 524 stripnodes = [repo.changelog.node(rev)
524 525 for rev in xrange(oldtiprev, len(repo))]
525 526 if conflicts:
526 527 shelvedstate.save(repo, basename, stripnodes)
527 528 # Fix up the dirstate entries of files from the second
528 529 # parent as if we were not merging, except for those
529 530 # with unresolved conflicts.
530 531 parents = repo.parents()
531 532 revertfiles = set(parents[1].files()).difference(ms)
532 533 cmdutil.revert(ui, repo, parents[1],
533 534 (parents[0].node(), nullid),
534 535 *revertfiles, **{'no_backup': True})
535 536 raise error.InterventionRequired(
536 537 _("unresolved conflicts (see 'hg resolve', then "
537 538 "'hg unshelve --continue')"))
538 539 finishmerge(ui, repo, ms, stripnodes, basename, opts)
539 540 else:
540 541 parent = tip.parents()[0]
541 542 hg.update(repo, parent.node())
542 543 cmdutil.revert(ui, repo, tip, repo.dirstate.parents(), *tip.files(),
543 544 **{'no_backup': True})
544 545
545 546 prevquiet = ui.quiet
546 547 ui.quiet = True
547 548 try:
548 549 repo.rollback(force=True)
549 550 finally:
550 551 ui.quiet = prevquiet
551 552
552 553 unshelvecleanup(ui, repo, basename, opts)
553 554 finally:
554 555 if tr:
555 556 tr.release()
556 557 lockmod.release(lock, wlock)
557 558
558 559 @command('shelve',
559 560 [('A', 'addremove', None,
560 561 _('mark new/missing files as added/removed before shelving')),
561 562 ('', 'cleanup', None,
562 563 _('delete all shelved changes')),
563 564 ('', 'date', '',
564 565 _('shelve with the specified commit date'), _('DATE')),
565 566 ('d', 'delete', None,
566 567 _('delete the named shelved change(s)')),
567 568 ('l', 'list', None,
568 569 _('list current shelves')),
569 570 ('m', 'message', '',
570 571 _('use text as shelve message'), _('TEXT')),
571 572 ('n', 'name', '',
572 573 _('use the given name for the shelved commit'), _('NAME')),
573 574 ('p', 'patch', None,
574 575 _('show patch')),
575 576 ('', 'stat', None,
576 577 _('output diffstat-style summary of changes'))],
577 578 _('hg shelve'))
578 579 def shelvecmd(ui, repo, *pats, **opts):
579 580 '''save and set aside changes from the working directory
580 581
581 582 Shelving takes files that "hg status" reports as not clean, saves
582 583 the modifications to a bundle (a shelved change), and reverts the
583 584 files so that their state in the working directory becomes clean.
584 585
585 586 To restore these changes to the working directory, using "hg
586 587 unshelve"; this will work even if you switch to a different
587 588 commit.
588 589
589 590 When no files are specified, "hg shelve" saves all not-clean
590 591 files. If specific files or directories are named, only changes to
591 592 those files are shelved.
592 593
593 594 Each shelved change has a name that makes it easier to find later.
594 595 The name of a shelved change defaults to being based on the active
595 596 bookmark, or if there is no active bookmark, the current named
596 597 branch. To specify a different name, use ``--name``.
597 598
598 599 To see a list of existing shelved changes, use the ``--list``
599 600 option. For each shelved change, this will print its name, age,
600 601 and description; use ``--patch`` or ``--stat`` for more details.
601 602
602 603 To delete specific shelved changes, use ``--delete``. To delete
603 604 all shelved changes, use ``--cleanup``.
604 605 '''
605 606 cmdutil.checkunfinished(repo)
606 607
607 608 def checkopt(opt, incompatible):
608 609 if opts[opt]:
609 610 for i in incompatible.split():
610 611 if opts[i]:
611 612 raise util.Abort(_("options '--%s' and '--%s' may not be "
612 613 "used together") % (opt, i))
613 614 return True
614 615 if checkopt('cleanup', 'addremove delete list message name patch stat'):
615 616 if pats:
616 617 raise util.Abort(_("cannot specify names when using '--cleanup'"))
617 618 return cleanupcmd(ui, repo)
618 619 elif checkopt('delete', 'addremove cleanup list message name patch stat'):
619 620 return deletecmd(ui, repo, pats)
620 621 elif checkopt('list', 'addremove cleanup delete message name'):
621 622 return listcmd(ui, repo, pats, opts)
622 623 else:
623 624 for i in ('patch', 'stat'):
624 625 if opts[i]:
625 626 raise util.Abort(_("option '--%s' may not be "
626 627 "used when shelving a change") % (i,))
627 628 return createcmd(ui, repo, pats, opts)
628 629
629 630 def extsetup(ui):
630 631 cmdutil.unfinishedstates.append(
631 632 [shelvedstate._filename, False, True, _('unshelve already in progress'),
632 633 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
General Comments 0
You need to be logged in to leave comments. Login now