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