##// END OF EJS Templates
shelve: make unshelve be able to abort in any case
Kostia Balytskyi -
r29536:b17a6e3c default
parent child Browse files
Show More
@@ -1,908 +1,927
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 from __future__ import absolute_import
24 24
25 25 import collections
26 26 import errno
27 27 import itertools
28 28
29 29 from mercurial.i18n import _
30 30 from mercurial import (
31 31 bundle2,
32 32 bundlerepo,
33 33 changegroup,
34 34 cmdutil,
35 35 commands,
36 36 error,
37 37 exchange,
38 38 hg,
39 39 lock as lockmod,
40 40 mdiff,
41 41 merge,
42 42 node as nodemod,
43 43 patch,
44 44 phases,
45 45 repair,
46 46 scmutil,
47 47 templatefilters,
48 48 util,
49 49 )
50 50
51 51 from . import (
52 52 rebase,
53 53 )
54 54
55 55 cmdtable = {}
56 56 command = cmdutil.command(cmdtable)
57 57 # Note for extension authors: ONLY specify testedwith = 'internal' for
58 58 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
59 59 # be specifying the version(s) of Mercurial they are tested with, or
60 60 # leave the attribute unspecified.
61 61 testedwith = 'internal'
62 62
63 63 backupdir = 'shelve-backup'
64 64 shelvedir = 'shelved'
65 65
66 66 class shelvedfile(object):
67 67 """Helper for the file storing a single shelve
68 68
69 69 Handles common functions on shelve files (.hg/.patch) using
70 70 the vfs layer"""
71 71 def __init__(self, repo, name, filetype=None):
72 72 self.repo = repo
73 73 self.name = name
74 74 self.vfs = scmutil.vfs(repo.join(shelvedir))
75 75 self.backupvfs = scmutil.vfs(repo.join(backupdir))
76 76 self.ui = self.repo.ui
77 77 if filetype:
78 78 self.fname = name + '.' + filetype
79 79 else:
80 80 self.fname = name
81 81
82 82 def exists(self):
83 83 return self.vfs.exists(self.fname)
84 84
85 85 def filename(self):
86 86 return self.vfs.join(self.fname)
87 87
88 88 def backupfilename(self):
89 89 def gennames(base):
90 90 yield base
91 91 base, ext = base.rsplit('.', 1)
92 92 for i in itertools.count(1):
93 93 yield '%s-%d.%s' % (base, i, ext)
94 94
95 95 name = self.backupvfs.join(self.fname)
96 96 for n in gennames(name):
97 97 if not self.backupvfs.exists(n):
98 98 return n
99 99
100 100 def movetobackup(self):
101 101 if not self.backupvfs.isdir():
102 102 self.backupvfs.makedir()
103 103 util.rename(self.filename(), self.backupfilename())
104 104
105 105 def stat(self):
106 106 return self.vfs.stat(self.fname)
107 107
108 108 def opener(self, mode='rb'):
109 109 try:
110 110 return self.vfs(self.fname, mode)
111 111 except IOError as err:
112 112 if err.errno != errno.ENOENT:
113 113 raise
114 114 raise error.Abort(_("shelved change '%s' not found") % self.name)
115 115
116 116 def applybundle(self):
117 117 fp = self.opener()
118 118 try:
119 119 gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
120 120 if not isinstance(gen, bundle2.unbundle20):
121 121 gen.apply(self.repo, 'unshelve',
122 122 'bundle:' + self.vfs.join(self.fname),
123 123 targetphase=phases.secret)
124 124 if isinstance(gen, bundle2.unbundle20):
125 125 bundle2.applybundle(self.repo, gen,
126 126 self.repo.currenttransaction(),
127 127 source='unshelve',
128 128 url='bundle:' + self.vfs.join(self.fname))
129 129 finally:
130 130 fp.close()
131 131
132 132 def bundlerepo(self):
133 133 return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root,
134 134 self.vfs.join(self.fname))
135 135 def writebundle(self, bases, node):
136 136 cgversion = changegroup.safeversion(self.repo)
137 137 if cgversion == '01':
138 138 btype = 'HG10BZ'
139 139 compression = None
140 140 else:
141 141 btype = 'HG20'
142 142 compression = 'BZ'
143 143
144 144 cg = changegroup.changegroupsubset(self.repo, bases, [node], 'shelve',
145 145 version=cgversion)
146 146 bundle2.writebundle(self.ui, cg, self.fname, btype, self.vfs,
147 147 compression=compression)
148 148
149 149 class shelvedstate(object):
150 150 """Handle persistence during unshelving operations.
151 151
152 152 Handles saving and restoring a shelved state. Ensures that different
153 153 versions of a shelved state are possible and handles them appropriately.
154 154 """
155 155 _version = 1
156 156 _filename = 'shelvedstate'
157 157
158 158 @classmethod
159 159 def load(cls, repo):
160 160 fp = repo.vfs(cls._filename)
161 161 try:
162 162 version = int(fp.readline().strip())
163 163
164 164 if version != cls._version:
165 165 raise error.Abort(_('this version of shelve is incompatible '
166 166 'with the version used in this repo'))
167 167 name = fp.readline().strip()
168 wctx = fp.readline().strip()
169 pendingctx = fp.readline().strip()
168 wctx = nodemod.bin(fp.readline().strip())
169 pendingctx = nodemod.bin(fp.readline().strip())
170 170 parents = [nodemod.bin(h) for h in fp.readline().split()]
171 171 stripnodes = [nodemod.bin(h) for h in fp.readline().split()]
172 172 branchtorestore = fp.readline().strip()
173 except (ValueError, TypeError) as err:
174 raise error.CorruptedState(str(err))
173 175 finally:
174 176 fp.close()
175 177
176 obj = cls()
177 obj.name = name
178 obj.wctx = repo[nodemod.bin(wctx)]
179 obj.pendingctx = repo[nodemod.bin(pendingctx)]
180 obj.parents = parents
181 obj.stripnodes = stripnodes
182 obj.branchtorestore = branchtorestore
178 try:
179 obj = cls()
180 obj.name = name
181 obj.wctx = repo[wctx]
182 obj.pendingctx = repo[pendingctx]
183 obj.parents = parents
184 obj.stripnodes = stripnodes
185 obj.branchtorestore = branchtorestore
186 except error.RepoLookupError as err:
187 raise error.CorruptedState(str(err))
183 188
184 189 return obj
185 190
186 191 @classmethod
187 192 def save(cls, repo, name, originalwctx, pendingctx, stripnodes,
188 193 branchtorestore):
189 194 fp = repo.vfs(cls._filename, 'wb')
190 195 fp.write('%i\n' % cls._version)
191 196 fp.write('%s\n' % name)
192 197 fp.write('%s\n' % nodemod.hex(originalwctx.node()))
193 198 fp.write('%s\n' % nodemod.hex(pendingctx.node()))
194 199 fp.write('%s\n' %
195 200 ' '.join([nodemod.hex(p) for p in repo.dirstate.parents()]))
196 201 fp.write('%s\n' %
197 202 ' '.join([nodemod.hex(n) for n in stripnodes]))
198 203 fp.write('%s\n' % branchtorestore)
199 204 fp.close()
200 205
201 206 @classmethod
202 207 def clear(cls, repo):
203 208 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
204 209
205 210 def cleanupoldbackups(repo):
206 211 vfs = scmutil.vfs(repo.join(backupdir))
207 212 maxbackups = repo.ui.configint('shelve', 'maxbackups', 10)
208 213 hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')]
209 214 hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles])
210 215 if 0 < maxbackups and maxbackups < len(hgfiles):
211 216 bordermtime = hgfiles[-maxbackups][0]
212 217 else:
213 218 bordermtime = None
214 219 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
215 220 if mtime == bordermtime:
216 221 # keep it, because timestamp can't decide exact order of backups
217 222 continue
218 223 base = f[:-3]
219 224 for ext in 'hg patch'.split():
220 225 try:
221 226 vfs.unlink(base + '.' + ext)
222 227 except OSError as err:
223 228 if err.errno != errno.ENOENT:
224 229 raise
225 230
226 231 def _aborttransaction(repo):
227 232 '''Abort current transaction for shelve/unshelve, but keep dirstate
228 233 '''
229 234 tr = repo.currenttransaction()
230 235 repo.dirstate.savebackup(tr, suffix='.shelve')
231 236 tr.abort()
232 237 repo.dirstate.restorebackup(None, suffix='.shelve')
233 238
234 239 def createcmd(ui, repo, pats, opts):
235 240 """subcommand that creates a new shelve"""
236 241 with repo.wlock():
237 242 cmdutil.checkunfinished(repo)
238 243 return _docreatecmd(ui, repo, pats, opts)
239 244
240 245 def _docreatecmd(ui, repo, pats, opts):
241 246 def mutableancestors(ctx):
242 247 """return all mutable ancestors for ctx (included)
243 248
244 249 Much faster than the revset ancestors(ctx) & draft()"""
245 250 seen = set([nodemod.nullrev])
246 251 visit = collections.deque()
247 252 visit.append(ctx)
248 253 while visit:
249 254 ctx = visit.popleft()
250 255 yield ctx.node()
251 256 for parent in ctx.parents():
252 257 rev = parent.rev()
253 258 if rev not in seen:
254 259 seen.add(rev)
255 260 if parent.mutable():
256 261 visit.append(parent)
257 262
258 263 wctx = repo[None]
259 264 parents = wctx.parents()
260 265 if len(parents) > 1:
261 266 raise error.Abort(_('cannot shelve while merging'))
262 267 parent = parents[0]
263 268 origbranch = wctx.branch()
264 269
265 270 # we never need the user, so we use a generic user for all shelve operations
266 271 user = 'shelve@localhost'
267 272 label = repo._activebookmark or parent.branch() or 'default'
268 273
269 274 # slashes aren't allowed in filenames, therefore we rename it
270 275 label = label.replace('/', '_')
271 276
272 277 def gennames():
273 278 yield label
274 279 for i in xrange(1, 100):
275 280 yield '%s-%02d' % (label, i)
276 281
277 282 if parent.node() != nodemod.nullid:
278 283 desc = "changes to: %s" % parent.description().split('\n', 1)[0]
279 284 else:
280 285 desc = '(changes in empty repository)'
281 286
282 287 if not opts.get('message'):
283 288 opts['message'] = desc
284 289
285 290 name = opts.get('name')
286 291
287 292 lock = tr = None
288 293 try:
289 294 lock = repo.lock()
290 295
291 296 # use an uncommitted transaction to generate the bundle to avoid
292 297 # pull races. ensure we don't print the abort message to stderr.
293 298 tr = repo.transaction('commit', report=lambda x: None)
294 299
295 300 if name:
296 301 if shelvedfile(repo, name, 'hg').exists():
297 302 raise error.Abort(_("a shelved change named '%s' already exists"
298 303 ) % name)
299 304 else:
300 305 for n in gennames():
301 306 if not shelvedfile(repo, n, 'hg').exists():
302 307 name = n
303 308 break
304 309 else:
305 310 raise error.Abort(_("too many shelved changes named '%s'") %
306 311 label)
307 312
308 313 # ensure we are not creating a subdirectory or a hidden file
309 314 if '/' in name or '\\' in name:
310 315 raise error.Abort(_('shelved change names may not contain slashes'))
311 316 if name.startswith('.'):
312 317 raise error.Abort(_("shelved change names may not start with '.'"))
313 318 interactive = opts.get('interactive', False)
314 319 includeunknown = (opts.get('unknown', False) and
315 320 not opts.get('addremove', False))
316 321
317 322 extra={}
318 323 if includeunknown:
319 324 s = repo.status(match=scmutil.match(repo[None], pats, opts),
320 325 unknown=True)
321 326 if s.unknown:
322 327 extra['shelve_unknown'] = '\0'.join(s.unknown)
323 328 repo[None].add(s.unknown)
324 329
325 330 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts):
326 331 # In non-bare shelve we don't store newly created branch
327 332 # at bundled commit
328 333 repo.dirstate.setbranch(repo['.'].branch())
329 334
330 335 def commitfunc(ui, repo, message, match, opts):
331 336 hasmq = util.safehasattr(repo, 'mq')
332 337 if hasmq:
333 338 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
334 339 backup = repo.ui.backupconfig('phases', 'new-commit')
335 340 try:
336 341 repo.ui. setconfig('phases', 'new-commit', phases.secret)
337 342 editor = cmdutil.getcommiteditor(editform='shelve.shelve',
338 343 **opts)
339 344 return repo.commit(message, user, opts.get('date'), match,
340 345 editor=editor, extra=extra)
341 346 finally:
342 347 repo.ui.restoreconfig(backup)
343 348 if hasmq:
344 349 repo.mq.checkapplied = saved
345 350
346 351 def interactivecommitfunc(ui, repo, *pats, **opts):
347 352 match = scmutil.match(repo['.'], pats, {})
348 353 message = opts['message']
349 354 return commitfunc(ui, repo, message, match, opts)
350 355 if not interactive:
351 356 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
352 357 else:
353 358 node = cmdutil.dorecord(ui, repo, interactivecommitfunc, None,
354 359 False, cmdutil.recordfilter, *pats, **opts)
355 360 if not node:
356 361 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
357 362 if stat.deleted:
358 363 ui.status(_("nothing changed (%d missing files, see "
359 364 "'hg status')\n") % len(stat.deleted))
360 365 else:
361 366 ui.status(_("nothing changed\n"))
362 367 return 1
363 368
364 369 bases = list(mutableancestors(repo[node]))
365 370 shelvedfile(repo, name, 'hg').writebundle(bases, node)
366 371 cmdutil.export(repo, [node],
367 372 fp=shelvedfile(repo, name, 'patch').opener('wb'),
368 373 opts=mdiff.diffopts(git=True))
369 374
370 375
371 376 if ui.formatted():
372 377 desc = util.ellipsis(desc, ui.termwidth())
373 378 ui.status(_('shelved as %s\n') % name)
374 379 hg.update(repo, parent.node())
375 380 if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
376 381 repo.dirstate.setbranch(origbranch)
377 382
378 383 _aborttransaction(repo)
379 384 finally:
380 385 lockmod.release(tr, lock)
381 386
382 387 def _isbareshelve(pats, opts):
383 388 return (not pats
384 389 and not opts.get('interactive', False)
385 390 and not opts.get('include', False)
386 391 and not opts.get('exclude', False))
387 392
388 393 def _iswctxonnewbranch(repo):
389 394 return repo[None].branch() != repo['.'].branch()
390 395
391 396 def cleanupcmd(ui, repo):
392 397 """subcommand that deletes all shelves"""
393 398
394 399 with repo.wlock():
395 400 for (name, _type) in repo.vfs.readdir(shelvedir):
396 401 suffix = name.rsplit('.', 1)[-1]
397 402 if suffix in ('hg', 'patch'):
398 403 shelvedfile(repo, name).movetobackup()
399 404 cleanupoldbackups(repo)
400 405
401 406 def deletecmd(ui, repo, pats):
402 407 """subcommand that deletes a specific shelve"""
403 408 if not pats:
404 409 raise error.Abort(_('no shelved changes specified!'))
405 410 with repo.wlock():
406 411 try:
407 412 for name in pats:
408 413 for suffix in 'hg patch'.split():
409 414 shelvedfile(repo, name, suffix).movetobackup()
410 415 cleanupoldbackups(repo)
411 416 except OSError as err:
412 417 if err.errno != errno.ENOENT:
413 418 raise
414 419 raise error.Abort(_("shelved change '%s' not found") % name)
415 420
416 421 def listshelves(repo):
417 422 """return all shelves in repo as list of (time, filename)"""
418 423 try:
419 424 names = repo.vfs.readdir(shelvedir)
420 425 except OSError as err:
421 426 if err.errno != errno.ENOENT:
422 427 raise
423 428 return []
424 429 info = []
425 430 for (name, _type) in names:
426 431 pfx, sfx = name.rsplit('.', 1)
427 432 if not pfx or sfx != 'patch':
428 433 continue
429 434 st = shelvedfile(repo, name).stat()
430 435 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
431 436 return sorted(info, reverse=True)
432 437
433 438 def listcmd(ui, repo, pats, opts):
434 439 """subcommand that displays the list of shelves"""
435 440 pats = set(pats)
436 441 width = 80
437 442 if not ui.plain():
438 443 width = ui.termwidth()
439 444 namelabel = 'shelve.newest'
440 445 for mtime, name in listshelves(repo):
441 446 sname = util.split(name)[1]
442 447 if pats and sname not in pats:
443 448 continue
444 449 ui.write(sname, label=namelabel)
445 450 namelabel = 'shelve.name'
446 451 if ui.quiet:
447 452 ui.write('\n')
448 453 continue
449 454 ui.write(' ' * (16 - len(sname)))
450 455 used = 16
451 456 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
452 457 ui.write(age, label='shelve.age')
453 458 ui.write(' ' * (12 - len(age)))
454 459 used += 12
455 460 with open(name + '.patch', 'rb') as fp:
456 461 while True:
457 462 line = fp.readline()
458 463 if not line:
459 464 break
460 465 if not line.startswith('#'):
461 466 desc = line.rstrip()
462 467 if ui.formatted():
463 468 desc = util.ellipsis(desc, width - used)
464 469 ui.write(desc)
465 470 break
466 471 ui.write('\n')
467 472 if not (opts['patch'] or opts['stat']):
468 473 continue
469 474 difflines = fp.readlines()
470 475 if opts['patch']:
471 476 for chunk, label in patch.difflabel(iter, difflines):
472 477 ui.write(chunk, label=label)
473 478 if opts['stat']:
474 479 for chunk, label in patch.diffstatui(difflines, width=width,
475 480 git=True):
476 481 ui.write(chunk, label=label)
477 482
478 483 def singlepatchcmds(ui, repo, pats, opts, subcommand):
479 484 """subcommand that displays a single shelf"""
480 485 if len(pats) != 1:
481 486 raise error.Abort(_("--%s expects a single shelf") % subcommand)
482 487 shelfname = pats[0]
483 488
484 489 if not shelvedfile(repo, shelfname, 'patch').exists():
485 490 raise error.Abort(_("cannot find shelf %s") % shelfname)
486 491
487 492 listcmd(ui, repo, pats, opts)
488 493
489 494 def checkparents(repo, state):
490 495 """check parent while resuming an unshelve"""
491 496 if state.parents != repo.dirstate.parents():
492 497 raise error.Abort(_('working directory parents do not match unshelve '
493 498 'state'))
494 499
495 500 def pathtofiles(repo, files):
496 501 cwd = repo.getcwd()
497 502 return [repo.pathto(f, cwd) for f in files]
498 503
499 504 def unshelveabort(ui, repo, state, opts):
500 505 """subcommand that abort an in-progress unshelve"""
501 506 with repo.lock():
502 507 try:
503 508 checkparents(repo, state)
504 509
505 510 util.rename(repo.join('unshelverebasestate'),
506 511 repo.join('rebasestate'))
507 512 try:
508 513 rebase.rebase(ui, repo, **{
509 514 'abort' : True
510 515 })
511 516 except Exception:
512 517 util.rename(repo.join('rebasestate'),
513 518 repo.join('unshelverebasestate'))
514 519 raise
515 520
516 521 mergefiles(ui, repo, state.wctx, state.pendingctx)
517 522 repair.strip(ui, repo, state.stripnodes, backup=False,
518 523 topic='shelve')
519 524 finally:
520 525 shelvedstate.clear(repo)
521 526 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
522 527
523 528 def mergefiles(ui, repo, wctx, shelvectx):
524 529 """updates to wctx and merges the changes from shelvectx into the
525 530 dirstate."""
526 531 oldquiet = ui.quiet
527 532 try:
528 533 ui.quiet = True
529 534 hg.update(repo, wctx.node())
530 535 files = []
531 536 files.extend(shelvectx.files())
532 537 files.extend(shelvectx.parents()[0].files())
533 538
534 539 # revert will overwrite unknown files, so move them out of the way
535 540 for file in repo.status(unknown=True).unknown:
536 541 if file in files:
537 542 util.rename(file, scmutil.origpath(ui, repo, file))
538 543 ui.pushbuffer(True)
539 544 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
540 545 *pathtofiles(repo, files),
541 546 **{'no_backup': True})
542 547 ui.popbuffer()
543 548 finally:
544 549 ui.quiet = oldquiet
545 550
546 551 def restorebranch(ui, repo, branchtorestore):
547 552 if branchtorestore and branchtorestore != repo.dirstate.branch():
548 553 repo.dirstate.setbranch(branchtorestore)
549 554 ui.status(_('marked working directory as branch %s\n')
550 555 % branchtorestore)
551 556
552 557 def unshelvecleanup(ui, repo, name, opts):
553 558 """remove related files after an unshelve"""
554 559 if not opts.get('keep'):
555 560 for filetype in 'hg patch'.split():
556 561 shelvedfile(repo, name, filetype).movetobackup()
557 562 cleanupoldbackups(repo)
558 563
559 564 def unshelvecontinue(ui, repo, state, opts):
560 565 """subcommand to continue an in-progress unshelve"""
561 566 # We're finishing off a merge. First parent is our original
562 567 # parent, second is the temporary "fake" commit we're unshelving.
563 568 with repo.lock():
564 569 checkparents(repo, state)
565 570 ms = merge.mergestate.read(repo)
566 571 if [f for f in ms if ms[f] == 'u']:
567 572 raise error.Abort(
568 573 _("unresolved conflicts, can't continue"),
569 574 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
570 575
571 576 util.rename(repo.join('unshelverebasestate'),
572 577 repo.join('rebasestate'))
573 578 try:
574 579 rebase.rebase(ui, repo, **{
575 580 'continue' : True
576 581 })
577 582 except Exception:
578 583 util.rename(repo.join('rebasestate'),
579 584 repo.join('unshelverebasestate'))
580 585 raise
581 586
582 587 shelvectx = repo['tip']
583 588 if not shelvectx in state.pendingctx.children():
584 589 # rebase was a no-op, so it produced no child commit
585 590 shelvectx = state.pendingctx
586 591 else:
587 592 # only strip the shelvectx if the rebase produced it
588 593 state.stripnodes.append(shelvectx.node())
589 594
590 595 mergefiles(ui, repo, state.wctx, shelvectx)
591 596 restorebranch(ui, repo, state.branchtorestore)
592 597
593 598 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
594 599 shelvedstate.clear(repo)
595 600 unshelvecleanup(ui, repo, state.name, opts)
596 601 ui.status(_("unshelve of '%s' complete\n") % state.name)
597 602
598 603 @command('unshelve',
599 604 [('a', 'abort', None,
600 605 _('abort an incomplete unshelve operation')),
601 606 ('c', 'continue', None,
602 607 _('continue an incomplete unshelve operation')),
603 608 ('k', 'keep', None,
604 609 _('keep shelve after unshelving')),
605 610 ('t', 'tool', '', _('specify merge tool')),
606 611 ('', 'date', '',
607 612 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
608 613 _('hg unshelve [SHELVED]'))
609 614 def unshelve(ui, repo, *shelved, **opts):
610 615 """restore a shelved change to the working directory
611 616
612 617 This command accepts an optional name of a shelved change to
613 618 restore. If none is given, the most recent shelved change is used.
614 619
615 620 If a shelved change is applied successfully, the bundle that
616 621 contains the shelved changes is moved to a backup location
617 622 (.hg/shelve-backup).
618 623
619 624 Since you can restore a shelved change on top of an arbitrary
620 625 commit, it is possible that unshelving will result in a conflict
621 626 between your changes and the commits you are unshelving onto. If
622 627 this occurs, you must resolve the conflict, then use
623 628 ``--continue`` to complete the unshelve operation. (The bundle
624 629 will not be moved until you successfully complete the unshelve.)
625 630
626 631 (Alternatively, you can use ``--abort`` to abandon an unshelve
627 632 that causes a conflict. This reverts the unshelved changes, and
628 633 leaves the bundle in place.)
629 634
630 635 If bare shelved change(when no files are specified, without interactive,
631 636 include and exclude option) was done on newly created branch it would
632 637 restore branch information to the working directory.
633 638
634 639 After a successful unshelve, the shelved changes are stored in a
635 640 backup directory. Only the N most recent backups are kept. N
636 641 defaults to 10 but can be overridden using the ``shelve.maxbackups``
637 642 configuration option.
638 643
639 644 .. container:: verbose
640 645
641 646 Timestamp in seconds is used to decide order of backups. More
642 647 than ``maxbackups`` backups are kept, if same timestamp
643 648 prevents from deciding exact order of them, for safety.
644 649 """
645 650 with repo.wlock():
646 651 return _dounshelve(ui, repo, *shelved, **opts)
647 652
648 653 def _dounshelve(ui, repo, *shelved, **opts):
649 654 abortf = opts.get('abort')
650 655 continuef = opts.get('continue')
651 656 if not abortf and not continuef:
652 657 cmdutil.checkunfinished(repo)
653 658
654 659 if abortf or continuef:
655 660 if abortf and continuef:
656 661 raise error.Abort(_('cannot use both abort and continue'))
657 662 if shelved:
658 663 raise error.Abort(_('cannot combine abort/continue with '
659 664 'naming a shelved change'))
660 665 if abortf and opts.get('tool', False):
661 666 ui.warn(_('tool option will be ignored\n'))
662 667
663 668 try:
664 669 state = shelvedstate.load(repo)
665 670 except IOError as err:
666 671 if err.errno != errno.ENOENT:
667 672 raise
668 673 cmdutil.wrongtooltocontinue(repo, _('unshelve'))
674 except error.CorruptedState as err:
675 ui.debug(str(err) + '\n')
676 if continuef:
677 msg = _('corrupted shelved state file')
678 hint = _('please run hg unshelve --abort to abort unshelve '
679 'operation')
680 raise error.Abort(msg, hint=hint)
681 elif abortf:
682 msg = _('could not read shelved state file, your working copy '
683 'may be in an unexpected state\nplease update to some '
684 'commit\n')
685 ui.warn(msg)
686 shelvedstate.clear(repo)
687 return
669 688
670 689 if abortf:
671 690 return unshelveabort(ui, repo, state, opts)
672 691 elif continuef:
673 692 return unshelvecontinue(ui, repo, state, opts)
674 693 elif len(shelved) > 1:
675 694 raise error.Abort(_('can only unshelve one change at a time'))
676 695 elif not shelved:
677 696 shelved = listshelves(repo)
678 697 if not shelved:
679 698 raise error.Abort(_('no shelved changes to apply!'))
680 699 basename = util.split(shelved[0][1])[1]
681 700 ui.status(_("unshelving change '%s'\n") % basename)
682 701 else:
683 702 basename = shelved[0]
684 703
685 704 if not shelvedfile(repo, basename, 'patch').exists():
686 705 raise error.Abort(_("shelved change '%s' not found") % basename)
687 706
688 707 oldquiet = ui.quiet
689 708 lock = tr = None
690 709 forcemerge = ui.backupconfig('ui', 'forcemerge')
691 710 try:
692 711 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'unshelve')
693 712 lock = repo.lock()
694 713
695 714 tr = repo.transaction('unshelve', report=lambda x: None)
696 715 oldtiprev = len(repo)
697 716
698 717 pctx = repo['.']
699 718 tmpwctx = pctx
700 719 # The goal is to have a commit structure like so:
701 720 # ...-> pctx -> tmpwctx -> shelvectx
702 721 # where tmpwctx is an optional commit with the user's pending changes
703 722 # and shelvectx is the unshelved changes. Then we merge it all down
704 723 # to the original pctx.
705 724
706 725 # Store pending changes in a commit and remember added in case a shelve
707 726 # contains unknown files that are part of the pending change
708 727 s = repo.status()
709 728 addedbefore = frozenset(s.added)
710 729 if s.modified or s.added or s.removed or s.deleted:
711 730 ui.status(_("temporarily committing pending changes "
712 731 "(restore with 'hg unshelve --abort')\n"))
713 732 def commitfunc(ui, repo, message, match, opts):
714 733 hasmq = util.safehasattr(repo, 'mq')
715 734 if hasmq:
716 735 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
717 736
718 737 backup = repo.ui.backupconfig('phases', 'new-commit')
719 738 try:
720 739 repo.ui.setconfig('phases', 'new-commit', phases.secret)
721 740 return repo.commit(message, 'shelve@localhost',
722 741 opts.get('date'), match)
723 742 finally:
724 743 repo.ui.restoreconfig(backup)
725 744 if hasmq:
726 745 repo.mq.checkapplied = saved
727 746
728 747 tempopts = {}
729 748 tempopts['message'] = "pending changes temporary commit"
730 749 tempopts['date'] = opts.get('date')
731 750 ui.quiet = True
732 751 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
733 752 tmpwctx = repo[node]
734 753
735 754 ui.quiet = True
736 755 shelvedfile(repo, basename, 'hg').applybundle()
737 756
738 757 ui.quiet = oldquiet
739 758
740 759 shelvectx = repo['tip']
741 760
742 761 branchtorestore = ''
743 762 if shelvectx.branch() != shelvectx.p1().branch():
744 763 branchtorestore = shelvectx.branch()
745 764
746 765 # If the shelve is not immediately on top of the commit
747 766 # we'll be merging with, rebase it to be on top.
748 767 if tmpwctx.node() != shelvectx.parents()[0].node():
749 768 ui.status(_('rebasing shelved changes\n'))
750 769 try:
751 770 rebase.rebase(ui, repo, **{
752 771 'rev' : [shelvectx.rev()],
753 772 'dest' : str(tmpwctx.rev()),
754 773 'keep' : True,
755 774 'tool' : opts.get('tool', ''),
756 775 })
757 776 except error.InterventionRequired:
758 777 tr.close()
759 778
760 779 stripnodes = [repo.changelog.node(rev)
761 780 for rev in xrange(oldtiprev, len(repo))]
762 781 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes,
763 782 branchtorestore)
764 783
765 784 util.rename(repo.join('rebasestate'),
766 785 repo.join('unshelverebasestate'))
767 786 raise error.InterventionRequired(
768 787 _("unresolved conflicts (see 'hg resolve', then "
769 788 "'hg unshelve --continue')"))
770 789
771 790 # refresh ctx after rebase completes
772 791 shelvectx = repo['tip']
773 792
774 793 if not shelvectx in tmpwctx.children():
775 794 # rebase was a no-op, so it produced no child commit
776 795 shelvectx = tmpwctx
777 796
778 797 mergefiles(ui, repo, pctx, shelvectx)
779 798 restorebranch(ui, repo, branchtorestore)
780 799
781 800 # Forget any files that were unknown before the shelve, unknown before
782 801 # unshelve started, but are now added.
783 802 shelveunknown = shelvectx.extra().get('shelve_unknown')
784 803 if shelveunknown:
785 804 shelveunknown = frozenset(shelveunknown.split('\0'))
786 805 addedafter = frozenset(repo.status().added)
787 806 toforget = (addedafter & shelveunknown) - addedbefore
788 807 repo[None].forget(toforget)
789 808
790 809 shelvedstate.clear(repo)
791 810
792 811 # The transaction aborting will strip all the commits for us,
793 812 # but it doesn't update the inmemory structures, so addchangegroup
794 813 # hooks still fire and try to operate on the missing commits.
795 814 # Clean up manually to prevent this.
796 815 repo.unfiltered().changelog.strip(oldtiprev, tr)
797 816
798 817 unshelvecleanup(ui, repo, basename, opts)
799 818
800 819 _aborttransaction(repo)
801 820 finally:
802 821 ui.quiet = oldquiet
803 822 if tr:
804 823 tr.release()
805 824 lockmod.release(lock)
806 825 ui.restoreconfig(forcemerge)
807 826
808 827 @command('shelve',
809 828 [('A', 'addremove', None,
810 829 _('mark new/missing files as added/removed before shelving')),
811 830 ('u', 'unknown', None,
812 831 _('store unknown files in the shelve')),
813 832 ('', 'cleanup', None,
814 833 _('delete all shelved changes')),
815 834 ('', 'date', '',
816 835 _('shelve with the specified commit date'), _('DATE')),
817 836 ('d', 'delete', None,
818 837 _('delete the named shelved change(s)')),
819 838 ('e', 'edit', False,
820 839 _('invoke editor on commit messages')),
821 840 ('l', 'list', None,
822 841 _('list current shelves')),
823 842 ('m', 'message', '',
824 843 _('use text as shelve message'), _('TEXT')),
825 844 ('n', 'name', '',
826 845 _('use the given name for the shelved commit'), _('NAME')),
827 846 ('p', 'patch', None,
828 847 _('show patch')),
829 848 ('i', 'interactive', None,
830 849 _('interactive mode, only works while creating a shelve')),
831 850 ('', 'stat', None,
832 851 _('output diffstat-style summary of changes'))] + commands.walkopts,
833 852 _('hg shelve [OPTION]... [FILE]...'))
834 853 def shelvecmd(ui, repo, *pats, **opts):
835 854 '''save and set aside changes from the working directory
836 855
837 856 Shelving takes files that "hg status" reports as not clean, saves
838 857 the modifications to a bundle (a shelved change), and reverts the
839 858 files so that their state in the working directory becomes clean.
840 859
841 860 To restore these changes to the working directory, using "hg
842 861 unshelve"; this will work even if you switch to a different
843 862 commit.
844 863
845 864 When no files are specified, "hg shelve" saves all not-clean
846 865 files. If specific files or directories are named, only changes to
847 866 those files are shelved.
848 867
849 868 In bare shelve(when no files are specified, without interactive,
850 869 include and exclude option), shelving remembers information if the
851 870 working directory was on newly created branch, in other words working
852 871 directory was on different branch than its first parent. In this
853 872 situation unshelving restores branch information to the working directory.
854 873
855 874 Each shelved change has a name that makes it easier to find later.
856 875 The name of a shelved change defaults to being based on the active
857 876 bookmark, or if there is no active bookmark, the current named
858 877 branch. To specify a different name, use ``--name``.
859 878
860 879 To see a list of existing shelved changes, use the ``--list``
861 880 option. For each shelved change, this will print its name, age,
862 881 and description; use ``--patch`` or ``--stat`` for more details.
863 882
864 883 To delete specific shelved changes, use ``--delete``. To delete
865 884 all shelved changes, use ``--cleanup``.
866 885 '''
867 886 allowables = [
868 887 ('addremove', set(['create'])), # 'create' is pseudo action
869 888 ('unknown', set(['create'])),
870 889 ('cleanup', set(['cleanup'])),
871 890 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
872 891 ('delete', set(['delete'])),
873 892 ('edit', set(['create'])),
874 893 ('list', set(['list'])),
875 894 ('message', set(['create'])),
876 895 ('name', set(['create'])),
877 896 ('patch', set(['patch', 'list'])),
878 897 ('stat', set(['stat', 'list'])),
879 898 ]
880 899 def checkopt(opt):
881 900 if opts.get(opt):
882 901 for i, allowable in allowables:
883 902 if opts[i] and opt not in allowable:
884 903 raise error.Abort(_("options '--%s' and '--%s' may not be "
885 904 "used together") % (opt, i))
886 905 return True
887 906 if checkopt('cleanup'):
888 907 if pats:
889 908 raise error.Abort(_("cannot specify names when using '--cleanup'"))
890 909 return cleanupcmd(ui, repo)
891 910 elif checkopt('delete'):
892 911 return deletecmd(ui, repo, pats)
893 912 elif checkopt('list'):
894 913 return listcmd(ui, repo, pats, opts)
895 914 elif checkopt('patch'):
896 915 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
897 916 elif checkopt('stat'):
898 917 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
899 918 else:
900 919 return createcmd(ui, repo, pats, opts)
901 920
902 921 def extsetup(ui):
903 922 cmdutil.unfinishedstates.append(
904 923 [shelvedstate._filename, False, False,
905 924 _('unshelve already in progress'),
906 925 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
907 926 cmdutil.afterresolvedstates.append(
908 927 [shelvedstate._filename, _('hg unshelve --continue')])
@@ -1,242 +1,245
1 1 # error.py - Mercurial exceptions
2 2 #
3 3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
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 """Mercurial exceptions.
9 9
10 10 This allows us to catch exceptions at higher levels without forcing
11 11 imports.
12 12 """
13 13
14 14 from __future__ import absolute_import
15 15
16 16 # Do not import anything here, please
17 17
18 18 class Hint(object):
19 19 """Mix-in to provide a hint of an error
20 20
21 21 This should come first in the inheritance list to consume a hint and
22 22 pass remaining arguments to the exception class.
23 23 """
24 24 def __init__(self, *args, **kw):
25 25 self.hint = kw.pop('hint', None)
26 26 super(Hint, self).__init__(*args, **kw)
27 27
28 28 class RevlogError(Hint, Exception):
29 29 pass
30 30
31 31 class FilteredIndexError(IndexError):
32 32 pass
33 33
34 34 class LookupError(RevlogError, KeyError):
35 35 def __init__(self, name, index, message):
36 36 self.name = name
37 37 self.index = index
38 38 # this can't be called 'message' because at least some installs of
39 39 # Python 2.6+ complain about the 'message' property being deprecated
40 40 self.lookupmessage = message
41 41 if isinstance(name, str) and len(name) == 20:
42 42 from .node import short
43 43 name = short(name)
44 44 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message))
45 45
46 46 def __str__(self):
47 47 return RevlogError.__str__(self)
48 48
49 49 class FilteredLookupError(LookupError):
50 50 pass
51 51
52 52 class ManifestLookupError(LookupError):
53 53 pass
54 54
55 55 class CommandError(Exception):
56 56 """Exception raised on errors in parsing the command line."""
57 57
58 58 class InterventionRequired(Hint, Exception):
59 59 """Exception raised when a command requires human intervention."""
60 60
61 61 class Abort(Hint, Exception):
62 62 """Raised if a command needs to print an error and exit."""
63 63
64 64 class HookLoadError(Abort):
65 65 """raised when loading a hook fails, aborting an operation
66 66
67 67 Exists to allow more specialized catching."""
68 68
69 69 class HookAbort(Abort):
70 70 """raised when a validation hook fails, aborting an operation
71 71
72 72 Exists to allow more specialized catching."""
73 73
74 74 class ConfigError(Abort):
75 75 """Exception raised when parsing config files"""
76 76
77 77 class UpdateAbort(Abort):
78 78 """Raised when an update is aborted for destination issue"""
79 79
80 80 class MergeDestAbort(Abort):
81 81 """Raised when an update is aborted for destination issues"""
82 82
83 83 class NoMergeDestAbort(MergeDestAbort):
84 84 """Raised when an update is aborted because there is nothing to merge"""
85 85
86 86 class ManyMergeDestAbort(MergeDestAbort):
87 87 """Raised when an update is aborted because destination is ambigious"""
88 88
89 89 class ResponseExpected(Abort):
90 90 """Raised when an EOF is received for a prompt"""
91 91 def __init__(self):
92 92 from .i18n import _
93 93 Abort.__init__(self, _('response expected'))
94 94
95 95 class OutOfBandError(Hint, Exception):
96 96 """Exception raised when a remote repo reports failure"""
97 97
98 98 class ParseError(Hint, Exception):
99 99 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
100 100
101 101 class UnknownIdentifier(ParseError):
102 102 """Exception raised when a {rev,file}set references an unknown identifier"""
103 103
104 104 def __init__(self, function, symbols):
105 105 from .i18n import _
106 106 ParseError.__init__(self, _("unknown identifier: %s") % function)
107 107 self.function = function
108 108 self.symbols = symbols
109 109
110 110 class RepoError(Hint, Exception):
111 111 pass
112 112
113 113 class RepoLookupError(RepoError):
114 114 pass
115 115
116 116 class FilteredRepoLookupError(RepoLookupError):
117 117 pass
118 118
119 119 class CapabilityError(RepoError):
120 120 pass
121 121
122 122 class RequirementError(RepoError):
123 123 """Exception raised if .hg/requires has an unknown entry."""
124 124
125 125 class UnsupportedMergeRecords(Abort):
126 126 def __init__(self, recordtypes):
127 127 from .i18n import _
128 128 self.recordtypes = sorted(recordtypes)
129 129 s = ' '.join(self.recordtypes)
130 130 Abort.__init__(
131 131 self, _('unsupported merge state records: %s') % s,
132 132 hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for '
133 133 'more information'))
134 134
135 135 class LockError(IOError):
136 136 def __init__(self, errno, strerror, filename, desc):
137 137 IOError.__init__(self, errno, strerror, filename)
138 138 self.desc = desc
139 139
140 140 class LockHeld(LockError):
141 141 def __init__(self, errno, filename, desc, locker):
142 142 LockError.__init__(self, errno, 'Lock held', filename, desc)
143 143 self.locker = locker
144 144
145 145 class LockUnavailable(LockError):
146 146 pass
147 147
148 148 # LockError is for errors while acquiring the lock -- this is unrelated
149 149 class LockInheritanceContractViolation(RuntimeError):
150 150 pass
151 151
152 152 class ResponseError(Exception):
153 153 """Raised to print an error with part of output and exit."""
154 154
155 155 class UnknownCommand(Exception):
156 156 """Exception raised if command is not in the command table."""
157 157
158 158 class AmbiguousCommand(Exception):
159 159 """Exception raised if command shortcut matches more than one command."""
160 160
161 161 # derived from KeyboardInterrupt to simplify some breakout code
162 162 class SignalInterrupt(KeyboardInterrupt):
163 163 """Exception raised on SIGTERM and SIGHUP."""
164 164
165 165 class SignatureError(Exception):
166 166 pass
167 167
168 168 class PushRaced(RuntimeError):
169 169 """An exception raised during unbundling that indicate a push race"""
170 170
171 171 # bundle2 related errors
172 172 class BundleValueError(ValueError):
173 173 """error raised when bundle2 cannot be processed"""
174 174
175 175 class BundleUnknownFeatureError(BundleValueError):
176 176 def __init__(self, parttype=None, params=(), values=()):
177 177 self.parttype = parttype
178 178 self.params = params
179 179 self.values = values
180 180 if self.parttype is None:
181 181 msg = 'Stream Parameter'
182 182 else:
183 183 msg = parttype
184 184 entries = self.params
185 185 if self.params and self.values:
186 186 assert len(self.params) == len(self.values)
187 187 entries = []
188 188 for idx, par in enumerate(self.params):
189 189 val = self.values[idx]
190 190 if val is None:
191 191 entries.append(val)
192 192 else:
193 193 entries.append("%s=%r" % (par, val))
194 194 if entries:
195 195 msg = '%s - %s' % (msg, ', '.join(entries))
196 196 ValueError.__init__(self, msg)
197 197
198 198 class ReadOnlyPartError(RuntimeError):
199 199 """error raised when code tries to alter a part being generated"""
200 200
201 201 class PushkeyFailed(Abort):
202 202 """error raised when a pushkey part failed to update a value"""
203 203
204 204 def __init__(self, partid, namespace=None, key=None, new=None, old=None,
205 205 ret=None):
206 206 self.partid = partid
207 207 self.namespace = namespace
208 208 self.key = key
209 209 self.new = new
210 210 self.old = old
211 211 self.ret = ret
212 212 # no i18n expected to be processed into a better message
213 213 Abort.__init__(self, 'failed to update value for "%s/%s"'
214 214 % (namespace, key))
215 215
216 216 class CensoredNodeError(RevlogError):
217 217 """error raised when content verification fails on a censored node
218 218
219 219 Also contains the tombstone data substituted for the uncensored data.
220 220 """
221 221
222 222 def __init__(self, filename, node, tombstone):
223 223 from .node import short
224 224 RevlogError.__init__(self, '%s:%s' % (filename, short(node)))
225 225 self.tombstone = tombstone
226 226
227 227 class CensoredBaseError(RevlogError):
228 228 """error raised when a delta is rejected because its base is censored
229 229
230 230 A delta based on a censored revision must be formed as single patch
231 231 operation which replaces the entire base with new content. This ensures
232 232 the delta may be applied by clones which have not censored the base.
233 233 """
234 234
235 235 class InvalidBundleSpecification(Exception):
236 236 """error raised when a bundle specification is invalid.
237 237
238 238 This is used for syntax errors as opposed to support errors.
239 239 """
240 240
241 241 class UnsupportedBundleSpecification(Exception):
242 242 """error raised when a bundle specification is not supported."""
243
244 class CorruptedState(Exception):
245 """error raised when a command is not able to read its state from file"""
@@ -1,1587 +1,1624
1 1 $ cat <<EOF >> $HGRCPATH
2 2 > [extensions]
3 3 > mq =
4 4 > shelve =
5 5 > [defaults]
6 6 > diff = --nodates --git
7 7 > qnew = --date '0 0'
8 8 > [shelve]
9 9 > maxbackups = 2
10 10 > EOF
11 11
12 12 $ hg init repo
13 13 $ cd repo
14 14 $ mkdir a b
15 15 $ echo a > a/a
16 16 $ echo b > b/b
17 17 $ echo c > c
18 18 $ echo d > d
19 19 $ echo x > x
20 20 $ hg addremove -q
21 21
22 22 shelve has a help message
23 23 $ hg shelve -h
24 24 hg shelve [OPTION]... [FILE]...
25 25
26 26 save and set aside changes from the working directory
27 27
28 28 Shelving takes files that "hg status" reports as not clean, saves the
29 29 modifications to a bundle (a shelved change), and reverts the files so
30 30 that their state in the working directory becomes clean.
31 31
32 32 To restore these changes to the working directory, using "hg unshelve";
33 33 this will work even if you switch to a different commit.
34 34
35 35 When no files are specified, "hg shelve" saves all not-clean files. If
36 36 specific files or directories are named, only changes to those files are
37 37 shelved.
38 38
39 39 In bare shelve(when no files are specified, without interactive, include
40 40 and exclude option), shelving remembers information if the working
41 41 directory was on newly created branch, in other words working directory
42 42 was on different branch than its first parent. In this situation
43 43 unshelving restores branch information to the working directory.
44 44
45 45 Each shelved change has a name that makes it easier to find later. The
46 46 name of a shelved change defaults to being based on the active bookmark,
47 47 or if there is no active bookmark, the current named branch. To specify a
48 48 different name, use "--name".
49 49
50 50 To see a list of existing shelved changes, use the "--list" option. For
51 51 each shelved change, this will print its name, age, and description; use "
52 52 --patch" or "--stat" for more details.
53 53
54 54 To delete specific shelved changes, use "--delete". To delete all shelved
55 55 changes, use "--cleanup".
56 56
57 57 (use "hg help -e shelve" to show help for the shelve extension)
58 58
59 59 options ([+] can be repeated):
60 60
61 61 -A --addremove mark new/missing files as added/removed before
62 62 shelving
63 63 -u --unknown store unknown files in the shelve
64 64 --cleanup delete all shelved changes
65 65 --date DATE shelve with the specified commit date
66 66 -d --delete delete the named shelved change(s)
67 67 -e --edit invoke editor on commit messages
68 68 -l --list list current shelves
69 69 -m --message TEXT use text as shelve message
70 70 -n --name NAME use the given name for the shelved commit
71 71 -p --patch show patch
72 72 -i --interactive interactive mode, only works while creating a shelve
73 73 --stat output diffstat-style summary of changes
74 74 -I --include PATTERN [+] include names matching the given patterns
75 75 -X --exclude PATTERN [+] exclude names matching the given patterns
76 76 --mq operate on patch repository
77 77
78 78 (some details hidden, use --verbose to show complete help)
79 79
80 80 shelving in an empty repo should be possible
81 81 (this tests also that editor is not invoked, if '--edit' is not
82 82 specified)
83 83
84 84 $ HGEDITOR=cat hg shelve
85 85 shelved as default
86 86 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
87 87
88 88 $ hg unshelve
89 89 unshelving change 'default'
90 90
91 91 $ hg commit -q -m 'initial commit'
92 92
93 93 $ hg shelve
94 94 nothing changed
95 95 [1]
96 96
97 97 make sure shelve files were backed up
98 98
99 99 $ ls .hg/shelve-backup
100 100 default.hg
101 101 default.patch
102 102
103 103 create an mq patch - shelving should work fine with a patch applied
104 104
105 105 $ echo n > n
106 106 $ hg add n
107 107 $ hg commit n -m second
108 108 $ hg qnew second.patch
109 109
110 110 shelve a change that we will delete later
111 111
112 112 $ echo a >> a/a
113 113 $ hg shelve
114 114 shelved as default
115 115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 116
117 117 set up some more complex changes to shelve
118 118
119 119 $ echo a >> a/a
120 120 $ hg mv b b.rename
121 121 moving b/b to b.rename/b (glob)
122 122 $ hg cp c c.copy
123 123 $ hg status -C
124 124 M a/a
125 125 A b.rename/b
126 126 b/b
127 127 A c.copy
128 128 c
129 129 R b/b
130 130
131 131 prevent some foot-shooting
132 132
133 133 $ hg shelve -n foo/bar
134 134 abort: shelved change names may not contain slashes
135 135 [255]
136 136 $ hg shelve -n .baz
137 137 abort: shelved change names may not start with '.'
138 138 [255]
139 139
140 140 the common case - no options or filenames
141 141
142 142 $ hg shelve
143 143 shelved as default-01
144 144 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
145 145 $ hg status -C
146 146
147 147 ensure that our shelved changes exist
148 148
149 149 $ hg shelve -l
150 150 default-01 (*)* changes to: [mq]: second.patch (glob)
151 151 default (*)* changes to: [mq]: second.patch (glob)
152 152
153 153 $ hg shelve -l -p default
154 154 default (*)* changes to: [mq]: second.patch (glob)
155 155
156 156 diff --git a/a/a b/a/a
157 157 --- a/a/a
158 158 +++ b/a/a
159 159 @@ -1,1 +1,2 @@
160 160 a
161 161 +a
162 162
163 163 $ hg shelve --list --addremove
164 164 abort: options '--list' and '--addremove' may not be used together
165 165 [255]
166 166
167 167 delete our older shelved change
168 168
169 169 $ hg shelve -d default
170 170 $ hg qfinish -a -q
171 171
172 172 ensure shelve backups aren't overwritten
173 173
174 174 $ ls .hg/shelve-backup/
175 175 default-1.hg
176 176 default-1.patch
177 177 default.hg
178 178 default.patch
179 179
180 180 local edits should not prevent a shelved change from applying
181 181
182 182 $ printf "z\na\n" > a/a
183 183 $ hg unshelve --keep
184 184 unshelving change 'default-01'
185 185 temporarily committing pending changes (restore with 'hg unshelve --abort')
186 186 rebasing shelved changes
187 187 rebasing 4:32c69314e062 "changes to: [mq]: second.patch" (tip)
188 188 merging a/a
189 189
190 190 $ hg revert --all -q
191 191 $ rm a/a.orig b.rename/b c.copy
192 192
193 193 apply it and make sure our state is as expected
194 194
195 195 (this also tests that same timestamp prevents backups from being
196 196 removed, even though there are more than 'maxbackups' backups)
197 197
198 198 $ f -t .hg/shelve-backup/default.hg
199 199 .hg/shelve-backup/default.hg: file
200 200 $ touch -t 200001010000 .hg/shelve-backup/default.hg
201 201 $ f -t .hg/shelve-backup/default-1.hg
202 202 .hg/shelve-backup/default-1.hg: file
203 203 $ touch -t 200001010000 .hg/shelve-backup/default-1.hg
204 204
205 205 $ hg unshelve
206 206 unshelving change 'default-01'
207 207 $ hg status -C
208 208 M a/a
209 209 A b.rename/b
210 210 b/b
211 211 A c.copy
212 212 c
213 213 R b/b
214 214 $ hg shelve -l
215 215
216 216 (both of default.hg and default-1.hg should be still kept, because it
217 217 is difficult to decide actual order of them from same timestamp)
218 218
219 219 $ ls .hg/shelve-backup/
220 220 default-01.hg
221 221 default-01.patch
222 222 default-1.hg
223 223 default-1.patch
224 224 default.hg
225 225 default.patch
226 226
227 227 $ hg unshelve
228 228 abort: no shelved changes to apply!
229 229 [255]
230 230 $ hg unshelve foo
231 231 abort: shelved change 'foo' not found
232 232 [255]
233 233
234 234 named shelves, specific filenames, and "commit messages" should all work
235 235 (this tests also that editor is invoked, if '--edit' is specified)
236 236
237 237 $ hg status -C
238 238 M a/a
239 239 A b.rename/b
240 240 b/b
241 241 A c.copy
242 242 c
243 243 R b/b
244 244 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
245 245 wat
246 246
247 247
248 248 HG: Enter commit message. Lines beginning with 'HG:' are removed.
249 249 HG: Leave message empty to abort commit.
250 250 HG: --
251 251 HG: user: shelve@localhost
252 252 HG: branch 'default'
253 253 HG: changed a/a
254 254
255 255 expect "a" to no longer be present, but status otherwise unchanged
256 256
257 257 $ hg status -C
258 258 A b.rename/b
259 259 b/b
260 260 A c.copy
261 261 c
262 262 R b/b
263 263 $ hg shelve -l --stat
264 264 wibble (*) wat (glob)
265 265 a/a | 1 +
266 266 1 files changed, 1 insertions(+), 0 deletions(-)
267 267
268 268 and now "a/a" should reappear
269 269
270 270 $ cd a
271 271 $ hg unshelve -q wibble
272 272 $ cd ..
273 273 $ hg status -C
274 274 M a/a
275 275 A b.rename/b
276 276 b/b
277 277 A c.copy
278 278 c
279 279 R b/b
280 280
281 281 ensure old shelve backups are being deleted automatically
282 282
283 283 $ ls .hg/shelve-backup/
284 284 default-01.hg
285 285 default-01.patch
286 286 wibble.hg
287 287 wibble.patch
288 288
289 289 cause unshelving to result in a merge with 'a' conflicting
290 290
291 291 $ hg shelve -q
292 292 $ echo c>>a/a
293 293 $ hg commit -m second
294 294 $ hg tip --template '{files}\n'
295 295 a/a
296 296
297 297 add an unrelated change that should be preserved
298 298
299 299 $ mkdir foo
300 300 $ echo foo > foo/foo
301 301 $ hg add foo/foo
302 302
303 303 force a conflicted merge to occur
304 304
305 305 $ hg unshelve
306 306 unshelving change 'default'
307 307 temporarily committing pending changes (restore with 'hg unshelve --abort')
308 308 rebasing shelved changes
309 309 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
310 310 merging a/a
311 311 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
312 312 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
313 313 [1]
314 314
315 315 ensure that we have a merge with unresolved conflicts
316 316
317 317 $ hg heads -q --template '{rev}\n'
318 318 5
319 319 4
320 320 $ hg parents -q --template '{rev}\n'
321 321 4
322 322 5
323 323 $ hg status
324 324 M a/a
325 325 M b.rename/b
326 326 M c.copy
327 327 R b/b
328 328 ? a/a.orig
329 329 $ hg diff
330 330 diff --git a/a/a b/a/a
331 331 --- a/a/a
332 332 +++ b/a/a
333 333 @@ -1,2 +1,6 @@
334 334 a
335 335 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
336 336 c
337 337 +=======
338 338 +a
339 339 +>>>>>>> source: 32c69314e062 - shelve: changes to: [mq]: second.patch
340 340 diff --git a/b/b b/b.rename/b
341 341 rename from b/b
342 342 rename to b.rename/b
343 343 diff --git a/c b/c.copy
344 344 copy from c
345 345 copy to c.copy
346 346 $ hg resolve -l
347 347 U a/a
348 348
349 349 $ hg shelve
350 350 abort: unshelve already in progress
351 351 (use 'hg unshelve --continue' or 'hg unshelve --abort')
352 352 [255]
353 353
354 354 abort the unshelve and be happy
355 355
356 356 $ hg status
357 357 M a/a
358 358 M b.rename/b
359 359 M c.copy
360 360 R b/b
361 361 ? a/a.orig
362 362 $ hg unshelve -a
363 363 rebase aborted
364 364 unshelve of 'default' aborted
365 365 $ hg heads -q
366 366 3:2e69b451d1ea
367 367 $ hg parents
368 368 changeset: 3:2e69b451d1ea
369 369 tag: tip
370 370 user: test
371 371 date: Thu Jan 01 00:00:00 1970 +0000
372 372 summary: second
373 373
374 374 $ hg resolve -l
375 375 $ hg status
376 376 A foo/foo
377 377 ? a/a.orig
378 378
379 379 try to continue with no unshelve underway
380 380
381 381 $ hg unshelve -c
382 382 abort: no unshelve in progress
383 383 [255]
384 384 $ hg status
385 385 A foo/foo
386 386 ? a/a.orig
387 387
388 388 redo the unshelve to get a conflict
389 389
390 390 $ hg unshelve -q
391 391 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
392 392 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
393 393 [1]
394 394
395 395 attempt to continue
396 396
397 397 $ hg unshelve -c
398 398 abort: unresolved conflicts, can't continue
399 399 (see 'hg resolve', then 'hg unshelve --continue')
400 400 [255]
401 401
402 402 $ hg revert -r . a/a
403 403 $ hg resolve -m a/a
404 404 (no more unresolved files)
405 405 continue: hg unshelve --continue
406 406
407 407 $ hg commit -m 'commit while unshelve in progress'
408 408 abort: unshelve already in progress
409 409 (use 'hg unshelve --continue' or 'hg unshelve --abort')
410 410 [255]
411 411
412 412 $ hg graft --continue
413 413 abort: no graft in progress
414 414 (continue: hg unshelve --continue)
415 415 [255]
416 416 $ hg unshelve -c
417 417 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
418 418 unshelve of 'default' complete
419 419
420 420 ensure the repo is as we hope
421 421
422 422 $ hg parents
423 423 changeset: 3:2e69b451d1ea
424 424 tag: tip
425 425 user: test
426 426 date: Thu Jan 01 00:00:00 1970 +0000
427 427 summary: second
428 428
429 429 $ hg heads -q
430 430 3:2e69b451d1ea
431 431
432 432 $ hg status -C
433 433 A b.rename/b
434 434 b/b
435 435 A c.copy
436 436 c
437 437 A foo/foo
438 438 R b/b
439 439 ? a/a.orig
440 440
441 441 there should be no shelves left
442 442
443 443 $ hg shelve -l
444 444
445 445 #if execbit
446 446
447 447 ensure that metadata-only changes are shelved
448 448
449 449 $ chmod +x a/a
450 450 $ hg shelve -q -n execbit a/a
451 451 $ hg status a/a
452 452 $ hg unshelve -q execbit
453 453 $ hg status a/a
454 454 M a/a
455 455 $ hg revert a/a
456 456
457 457 #endif
458 458
459 459 #if symlink
460 460
461 461 $ rm a/a
462 462 $ ln -s foo a/a
463 463 $ hg shelve -q -n symlink a/a
464 464 $ hg status a/a
465 465 $ hg unshelve -q symlink
466 466 $ hg status a/a
467 467 M a/a
468 468 $ hg revert a/a
469 469
470 470 #endif
471 471
472 472 set up another conflict between a commit and a shelved change
473 473
474 474 $ hg revert -q -C -a
475 475 $ rm a/a.orig b.rename/b c.copy
476 476 $ echo a >> a/a
477 477 $ hg shelve -q
478 478 $ echo x >> a/a
479 479 $ hg ci -m 'create conflict'
480 480 $ hg add foo/foo
481 481
482 482 if we resolve a conflict while unshelving, the unshelve should succeed
483 483
484 484 $ hg unshelve --tool :merge-other --keep
485 485 unshelving change 'default'
486 486 temporarily committing pending changes (restore with 'hg unshelve --abort')
487 487 rebasing shelved changes
488 488 rebasing 6:2f694dd83a13 "changes to: second" (tip)
489 489 merging a/a
490 490 $ hg parents -q
491 491 4:33f7f61e6c5e
492 492 $ hg shelve -l
493 493 default (*)* changes to: second (glob)
494 494 $ hg status
495 495 M a/a
496 496 A foo/foo
497 497 $ cat a/a
498 498 a
499 499 c
500 500 a
501 501 $ cat > a/a << EOF
502 502 > a
503 503 > c
504 504 > x
505 505 > EOF
506 506
507 507 $ HGMERGE=true hg unshelve
508 508 unshelving change 'default'
509 509 temporarily committing pending changes (restore with 'hg unshelve --abort')
510 510 rebasing shelved changes
511 511 rebasing 6:2f694dd83a13 "changes to: second" (tip)
512 512 merging a/a
513 513 note: rebase of 6:2f694dd83a13 created no changes to commit
514 514 $ hg parents -q
515 515 4:33f7f61e6c5e
516 516 $ hg shelve -l
517 517 $ hg status
518 518 A foo/foo
519 519 $ cat a/a
520 520 a
521 521 c
522 522 x
523 523
524 524 test keep and cleanup
525 525
526 526 $ hg shelve
527 527 shelved as default
528 528 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
529 529 $ hg shelve --list
530 530 default (*)* changes to: create conflict (glob)
531 531 $ hg unshelve -k
532 532 unshelving change 'default'
533 533 $ hg shelve --list
534 534 default (*)* changes to: create conflict (glob)
535 535 $ hg shelve --cleanup
536 536 $ hg shelve --list
537 537
538 538 $ hg shelve --cleanup --delete
539 539 abort: options '--cleanup' and '--delete' may not be used together
540 540 [255]
541 541 $ hg shelve --cleanup --patch
542 542 abort: options '--cleanup' and '--patch' may not be used together
543 543 [255]
544 544 $ hg shelve --cleanup --message MESSAGE
545 545 abort: options '--cleanup' and '--message' may not be used together
546 546 [255]
547 547
548 548 test bookmarks
549 549
550 550 $ hg bookmark test
551 551 $ hg bookmark
552 552 * test 4:33f7f61e6c5e
553 553 $ hg shelve
554 554 shelved as test
555 555 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
556 556 $ hg bookmark
557 557 * test 4:33f7f61e6c5e
558 558 $ hg unshelve
559 559 unshelving change 'test'
560 560 $ hg bookmark
561 561 * test 4:33f7f61e6c5e
562 562
563 563 shelve should still work even if mq is disabled
564 564
565 565 $ hg --config extensions.mq=! shelve
566 566 shelved as test
567 567 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
568 568 $ hg --config extensions.mq=! shelve --list
569 569 test (*)* changes to: create conflict (glob)
570 570 $ hg bookmark
571 571 * test 4:33f7f61e6c5e
572 572 $ hg --config extensions.mq=! unshelve
573 573 unshelving change 'test'
574 574 $ hg bookmark
575 575 * test 4:33f7f61e6c5e
576 576
577 577 shelve should leave dirstate clean (issue4055)
578 578
579 579 $ cd ..
580 580 $ hg init shelverebase
581 581 $ cd shelverebase
582 582 $ printf 'x\ny\n' > x
583 583 $ echo z > z
584 584 $ hg commit -Aqm xy
585 585 $ echo z >> x
586 586 $ hg commit -Aqm z
587 587 $ hg up 0
588 588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 589 $ printf 'a\nx\ny\nz\n' > x
590 590 $ hg commit -Aqm xyz
591 591 $ echo c >> z
592 592 $ hg shelve
593 593 shelved as default
594 594 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
595 595 $ hg rebase -d 1 --config extensions.rebase=
596 596 rebasing 2:323bfa07f744 "xyz" (tip)
597 597 merging x
598 598 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
599 599 $ hg unshelve
600 600 unshelving change 'default'
601 601 rebasing shelved changes
602 602 rebasing 4:82a0d7d6ba61 "changes to: xyz" (tip)
603 603 $ hg status
604 604 M z
605 605
606 606 $ cd ..
607 607
608 608 shelve should only unshelve pending changes (issue4068)
609 609
610 610 $ hg init onlypendingchanges
611 611 $ cd onlypendingchanges
612 612 $ touch a
613 613 $ hg ci -Aqm a
614 614 $ touch b
615 615 $ hg ci -Aqm b
616 616 $ hg up -q 0
617 617 $ touch c
618 618 $ hg ci -Aqm c
619 619
620 620 $ touch d
621 621 $ hg add d
622 622 $ hg shelve
623 623 shelved as default
624 624 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
625 625 $ hg up -q 1
626 626 $ hg unshelve
627 627 unshelving change 'default'
628 628 rebasing shelved changes
629 629 rebasing 3:958bcbd1776e "changes to: c" (tip)
630 630 $ hg status
631 631 A d
632 632
633 633 unshelve should work on an ancestor of the original commit
634 634
635 635 $ hg shelve
636 636 shelved as default
637 637 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
638 638 $ hg up 0
639 639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 640 $ hg unshelve
641 641 unshelving change 'default'
642 642 rebasing shelved changes
643 643 rebasing 3:013284d9655e "changes to: b" (tip)
644 644 $ hg status
645 645 A d
646 646
647 647 test bug 4073 we need to enable obsolete markers for it
648 648
649 649 $ cat >> $HGRCPATH << EOF
650 650 > [experimental]
651 651 > evolution=createmarkers
652 652 > EOF
653 653 $ hg shelve
654 654 shelved as default
655 655 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
656 656 $ hg debugobsolete `hg --debug id -i -r 1`
657 657 $ hg unshelve
658 658 unshelving change 'default'
659 659
660 660 unshelve should leave unknown files alone (issue4113)
661 661
662 662 $ echo e > e
663 663 $ hg shelve
664 664 shelved as default
665 665 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
666 666 $ hg status
667 667 ? e
668 668 $ hg unshelve
669 669 unshelving change 'default'
670 670 $ hg status
671 671 A d
672 672 ? e
673 673 $ cat e
674 674 e
675 675
676 676 unshelve should keep a copy of unknown files
677 677
678 678 $ hg add e
679 679 $ hg shelve
680 680 shelved as default
681 681 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
682 682 $ echo z > e
683 683 $ hg unshelve
684 684 unshelving change 'default'
685 685 $ cat e
686 686 e
687 687 $ cat e.orig
688 688 z
689 689
690 690
691 691 unshelve and conflicts with tracked and untracked files
692 692
693 693 preparing:
694 694
695 695 $ rm *.orig
696 696 $ hg ci -qm 'commit stuff'
697 697 $ hg phase -p null:
698 698
699 699 no other changes - no merge:
700 700
701 701 $ echo f > f
702 702 $ hg add f
703 703 $ hg shelve
704 704 shelved as default
705 705 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
706 706 $ echo g > f
707 707 $ hg unshelve
708 708 unshelving change 'default'
709 709 $ hg st
710 710 A f
711 711 ? f.orig
712 712 $ cat f
713 713 f
714 714 $ cat f.orig
715 715 g
716 716
717 717 other uncommitted changes - merge:
718 718
719 719 $ hg st
720 720 A f
721 721 ? f.orig
722 722 $ hg shelve
723 723 shelved as default
724 724 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
725 725 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
726 726 o 4 changes to: commit stuff shelve@localhost
727 727 |
728 728 ~
729 729 $ hg log -G --template '{rev} {desc|firstline} {author}'
730 730 @ 3 commit stuff test
731 731 |
732 732 | o 2 c test
733 733 |/
734 734 o 0 a test
735 735
736 736 $ mv f.orig f
737 737 $ echo 1 > a
738 738 $ hg unshelve --date '1073741824 0'
739 739 unshelving change 'default'
740 740 temporarily committing pending changes (restore with 'hg unshelve --abort')
741 741 rebasing shelved changes
742 742 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
743 743 merging f
744 744 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
745 745 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
746 746 [1]
747 747 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
748 748 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
749 749 |
750 750 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
751 751 |/
752 752 o 3 commit stuff test 1970-01-01 00:00 +0000
753 753 |
754 754 | o 2 c test 1970-01-01 00:00 +0000
755 755 |/
756 756 o 0 a test 1970-01-01 00:00 +0000
757 757
758 758 $ hg st
759 759 M f
760 760 ? f.orig
761 761 $ cat f
762 762 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
763 763 g
764 764 =======
765 765 f
766 766 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
767 767 $ cat f.orig
768 768 g
769 769 $ hg unshelve --abort -t false
770 770 tool option will be ignored
771 771 rebase aborted
772 772 unshelve of 'default' aborted
773 773 $ hg st
774 774 M a
775 775 ? f.orig
776 776 $ cat f.orig
777 777 g
778 778 $ hg unshelve
779 779 unshelving change 'default'
780 780 temporarily committing pending changes (restore with 'hg unshelve --abort')
781 781 rebasing shelved changes
782 782 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
783 783 $ hg st
784 784 M a
785 785 A f
786 786 ? f.orig
787 787
788 788 other committed changes - merge:
789 789
790 790 $ hg shelve f
791 791 shelved as default
792 792 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
793 793 $ hg ci a -m 'intermediate other change'
794 794 $ mv f.orig f
795 795 $ hg unshelve
796 796 unshelving change 'default'
797 797 rebasing shelved changes
798 798 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
799 799 merging f
800 800 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
801 801 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
802 802 [1]
803 803 $ hg st
804 804 M f
805 805 ? f.orig
806 806 $ cat f
807 807 <<<<<<< dest: * - test: intermediate other change (glob)
808 808 g
809 809 =======
810 810 f
811 811 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
812 812 $ cat f.orig
813 813 g
814 814 $ hg unshelve --abort
815 815 rebase aborted
816 816 unshelve of 'default' aborted
817 817 $ hg st
818 818 ? f.orig
819 819 $ cat f.orig
820 820 g
821 821 $ hg shelve --delete default
822 822
823 823 Recreate some conflict again
824 824
825 825 $ cd ../repo
826 826 $ hg up -C -r 3
827 827 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
828 828 (leaving bookmark test)
829 829 $ echo y >> a/a
830 830 $ hg shelve
831 831 shelved as default
832 832 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
833 833 $ hg up test
834 834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
835 835 (activating bookmark test)
836 836 $ hg bookmark
837 837 * test 4:33f7f61e6c5e
838 838 $ hg unshelve
839 839 unshelving change 'default'
840 840 rebasing shelved changes
841 841 rebasing 5:e42a7da90865 "changes to: second" (tip)
842 842 merging a/a
843 843 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
844 844 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
845 845 [1]
846 846 $ hg bookmark
847 847 test 4:33f7f61e6c5e
848 848
849 849 Test that resolving all conflicts in one direction (so that the rebase
850 850 is a no-op), works (issue4398)
851 851
852 852 $ hg revert -a -r .
853 853 reverting a/a (glob)
854 854 $ hg resolve -m a/a
855 855 (no more unresolved files)
856 856 continue: hg unshelve --continue
857 857 $ hg unshelve -c
858 858 rebasing 5:e42a7da90865 "changes to: second" (tip)
859 859 note: rebase of 5:e42a7da90865 created no changes to commit
860 860 unshelve of 'default' complete
861 861 $ hg bookmark
862 862 * test 4:33f7f61e6c5e
863 863 $ hg diff
864 864 $ hg status
865 865 ? a/a.orig
866 866 ? foo/foo
867 867 $ hg summary
868 868 parent: 4:33f7f61e6c5e tip
869 869 create conflict
870 870 branch: default
871 871 bookmarks: *test
872 872 commit: 2 unknown (clean)
873 873 update: (current)
874 874 phases: 5 draft
875 875
876 876 $ hg shelve --delete --stat
877 877 abort: options '--delete' and '--stat' may not be used together
878 878 [255]
879 879 $ hg shelve --delete --name NAME
880 880 abort: options '--delete' and '--name' may not be used together
881 881 [255]
882 882
883 883 Test interactive shelve
884 884 $ cat <<EOF >> $HGRCPATH
885 885 > [ui]
886 886 > interactive = true
887 887 > EOF
888 888 $ echo 'a' >> a/b
889 889 $ cat a/a >> a/b
890 890 $ echo 'x' >> a/b
891 891 $ mv a/b a/a
892 892 $ echo 'a' >> foo/foo
893 893 $ hg st
894 894 M a/a
895 895 ? a/a.orig
896 896 ? foo/foo
897 897 $ cat a/a
898 898 a
899 899 a
900 900 c
901 901 x
902 902 x
903 903 $ cat foo/foo
904 904 foo
905 905 a
906 906 $ hg shelve --interactive --config ui.interactive=false
907 907 abort: running non-interactively
908 908 [255]
909 909 $ hg shelve --interactive << EOF
910 910 > y
911 911 > y
912 912 > n
913 913 > EOF
914 914 diff --git a/a/a b/a/a
915 915 2 hunks, 2 lines changed
916 916 examine changes to 'a/a'? [Ynesfdaq?] y
917 917
918 918 @@ -1,3 +1,4 @@
919 919 +a
920 920 a
921 921 c
922 922 x
923 923 record change 1/2 to 'a/a'? [Ynesfdaq?] y
924 924
925 925 @@ -1,3 +2,4 @@
926 926 a
927 927 c
928 928 x
929 929 +x
930 930 record change 2/2 to 'a/a'? [Ynesfdaq?] n
931 931
932 932 shelved as test
933 933 merging a/a
934 934 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
935 935 $ cat a/a
936 936 a
937 937 c
938 938 x
939 939 x
940 940 $ cat foo/foo
941 941 foo
942 942 a
943 943 $ hg st
944 944 M a/a
945 945 ? foo/foo
946 946 $ hg bookmark
947 947 * test 4:33f7f61e6c5e
948 948 $ hg unshelve
949 949 unshelving change 'test'
950 950 temporarily committing pending changes (restore with 'hg unshelve --abort')
951 951 rebasing shelved changes
952 952 rebasing 6:96a1354f65f6 "changes to: create conflict" (tip)
953 953 merging a/a
954 954 $ hg bookmark
955 955 * test 4:33f7f61e6c5e
956 956 $ cat a/a
957 957 a
958 958 a
959 959 c
960 960 x
961 961 x
962 962
963 963 shelve --patch and shelve --stat should work with a single valid shelfname
964 964
965 965 $ hg up --clean .
966 966 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
967 967 (leaving bookmark test)
968 968 $ hg shelve --list
969 969 $ echo 'patch a' > shelf-patch-a
970 970 $ hg add shelf-patch-a
971 971 $ hg shelve
972 972 shelved as default
973 973 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
974 974 $ echo 'patch b' > shelf-patch-b
975 975 $ hg add shelf-patch-b
976 976 $ hg shelve
977 977 shelved as default-01
978 978 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
979 979 $ hg shelve --patch default default-01
980 980 abort: --patch expects a single shelf
981 981 [255]
982 982 $ hg shelve --stat default default-01
983 983 abort: --stat expects a single shelf
984 984 [255]
985 985 $ hg shelve --patch default
986 986 default (*)* changes to: create conflict (glob)
987 987
988 988 diff --git a/shelf-patch-a b/shelf-patch-a
989 989 new file mode 100644
990 990 --- /dev/null
991 991 +++ b/shelf-patch-a
992 992 @@ -0,0 +1,1 @@
993 993 +patch a
994 994 $ hg shelve --stat default
995 995 default (*)* changes to: create conflict (glob)
996 996 shelf-patch-a | 1 +
997 997 1 files changed, 1 insertions(+), 0 deletions(-)
998 998 $ hg shelve --patch nonexistentshelf
999 999 abort: cannot find shelf nonexistentshelf
1000 1000 [255]
1001 1001 $ hg shelve --stat nonexistentshelf
1002 1002 abort: cannot find shelf nonexistentshelf
1003 1003 [255]
1004 1004
1005 1005 $ cd ..
1006 1006
1007 1007 Shelve from general delta repo uses bundle2 on disk
1008 1008 --------------------------------------------------
1009 1009
1010 1010 no general delta
1011 1011
1012 1012 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
1013 1013 requesting all changes
1014 1014 adding changesets
1015 1015 adding manifests
1016 1016 adding file changes
1017 1017 added 5 changesets with 8 changes to 6 files
1018 1018 updating to branch default
1019 1019 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1020 1020 $ cd bundle1
1021 1021 $ echo babar > jungle
1022 1022 $ hg add jungle
1023 1023 $ hg shelve
1024 1024 shelved as default
1025 1025 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1026 1026 $ hg debugbundle .hg/shelved/*.hg
1027 1027 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1028 1028 $ cd ..
1029 1029
1030 1030 with general delta
1031 1031
1032 1032 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
1033 1033 requesting all changes
1034 1034 adding changesets
1035 1035 adding manifests
1036 1036 adding file changes
1037 1037 added 5 changesets with 8 changes to 6 files
1038 1038 updating to branch default
1039 1039 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1040 1040 $ cd bundle2
1041 1041 $ echo babar > jungle
1042 1042 $ hg add jungle
1043 1043 $ hg shelve
1044 1044 shelved as default
1045 1045 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1046 1046 $ hg debugbundle .hg/shelved/*.hg
1047 1047 Stream params: {'Compression': 'BZ'}
1048 1048 changegroup -- "{'version': '02'}"
1049 1049 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1050 1050 $ cd ..
1051 1051
1052 1052 Test visibility of in-memory changes inside transaction to external hook
1053 1053 ------------------------------------------------------------------------
1054 1054
1055 1055 $ cd repo
1056 1056
1057 1057 $ echo xxxx >> x
1058 1058 $ hg commit -m "#5: changes to invoke rebase"
1059 1059
1060 1060 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1061 1061 > echo "==== \$1:"
1062 1062 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1063 1063 > # test that pending changes are hidden
1064 1064 > unset HG_PENDING
1065 1065 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1066 1066 > echo "===="
1067 1067 > EOF
1068 1068
1069 1069 $ cat >> .hg/hgrc <<EOF
1070 1070 > [defaults]
1071 1071 > # to fix hash id of temporary revisions
1072 1072 > unshelve = --date '0 0'
1073 1073 > EOF
1074 1074
1075 1075 "hg unshelve" at REV5 implies steps below:
1076 1076
1077 1077 (1) commit changes in the working directory (REV6)
1078 1078 (2) unbundle shelved revision (REV7)
1079 1079 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1080 1080 (4) rebase: commit merged revision (REV8)
1081 1081 (5) rebase: update to REV6 (REV8 => REV6)
1082 1082 (6) update to REV5 (REV6 => REV5)
1083 1083 (7) abort transaction
1084 1084
1085 1085 == test visibility to external preupdate hook
1086 1086
1087 1087 $ cat >> .hg/hgrc <<EOF
1088 1088 > [hooks]
1089 1089 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1090 1090 > EOF
1091 1091
1092 1092 $ echo nnnn >> n
1093 1093
1094 1094 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1095 1095 ==== before-unshelving:
1096 1096 VISIBLE 5:703117a2acfb
1097 1097 ACTUAL 5:703117a2acfb
1098 1098 ====
1099 1099
1100 1100 $ hg unshelve --keep default
1101 1101 temporarily committing pending changes (restore with 'hg unshelve --abort')
1102 1102 rebasing shelved changes
1103 1103 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1104 1104 ==== preupdate:
1105 1105 VISIBLE 6:66b86db80ee4
1106 1106 ACTUAL 5:703117a2acfb
1107 1107 ====
1108 1108 ==== preupdate:
1109 1109 VISIBLE 8:a0e04704317e
1110 1110 ACTUAL 5:703117a2acfb
1111 1111 ====
1112 1112 ==== preupdate:
1113 1113 VISIBLE 6:66b86db80ee4
1114 1114 ACTUAL 5:703117a2acfb
1115 1115 ====
1116 1116
1117 1117 $ cat >> .hg/hgrc <<EOF
1118 1118 > [hooks]
1119 1119 > preupdate.visibility =
1120 1120 > EOF
1121 1121
1122 1122 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1123 1123 ==== after-unshelving:
1124 1124 VISIBLE 5:703117a2acfb
1125 1125 ACTUAL 5:703117a2acfb
1126 1126 ====
1127 1127
1128 1128 == test visibility to external update hook
1129 1129
1130 1130 $ hg update -q -C 5
1131 1131
1132 1132 $ cat >> .hg/hgrc <<EOF
1133 1133 > [hooks]
1134 1134 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1135 1135 > EOF
1136 1136
1137 1137 $ echo nnnn >> n
1138 1138
1139 1139 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1140 1140 ==== before-unshelving:
1141 1141 VISIBLE 5:703117a2acfb
1142 1142 ACTUAL 5:703117a2acfb
1143 1143 ====
1144 1144
1145 1145 $ hg unshelve --keep default
1146 1146 temporarily committing pending changes (restore with 'hg unshelve --abort')
1147 1147 rebasing shelved changes
1148 1148 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1149 1149 ==== update:
1150 1150 VISIBLE 6:66b86db80ee4
1151 1151 VISIBLE 7:206bf5d4f922
1152 1152 ACTUAL 5:703117a2acfb
1153 1153 ====
1154 1154 ==== update:
1155 1155 VISIBLE 6:66b86db80ee4
1156 1156 ACTUAL 5:703117a2acfb
1157 1157 ====
1158 1158 ==== update:
1159 1159 VISIBLE 5:703117a2acfb
1160 1160 ACTUAL 5:703117a2acfb
1161 1161 ====
1162 1162
1163 1163 $ cat >> .hg/hgrc <<EOF
1164 1164 > [hooks]
1165 1165 > update.visibility =
1166 1166 > EOF
1167 1167
1168 1168 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1169 1169 ==== after-unshelving:
1170 1170 VISIBLE 5:703117a2acfb
1171 1171 ACTUAL 5:703117a2acfb
1172 1172 ====
1173 1173
1174 1174 $ cd ..
1175 1175
1176 1176 test .orig files go where the user wants them to
1177 1177 ---------------------------------------------------------------
1178 1178 $ hg init salvage
1179 1179 $ cd salvage
1180 1180 $ echo 'content' > root
1181 1181 $ hg commit -A -m 'root' -q
1182 1182 $ echo '' > root
1183 1183 $ hg shelve -q
1184 1184 $ echo 'contADDent' > root
1185 1185 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1186 1186 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1187 1187 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1188 1188 [1]
1189 1189 $ ls .hg/origbackups
1190 1190 root.orig
1191 1191 $ rm -rf .hg/origbackups
1192 1192
1193 1193 test Abort unshelve always gets user out of the unshelved state
1194 1194 ---------------------------------------------------------------
1195 1195 Wreak havoc on the unshelve process
1196 1196 $ rm .hg/unshelverebasestate
1197 1197 $ hg unshelve --abort
1198 1198 unshelve of 'default' aborted
1199 1199 abort: (No such file or directory|The system cannot find the file specified) (re)
1200 1200 [255]
1201 1201 Can the user leave the current state?
1202 1202 $ hg up -C .
1203 1203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1204 1204
1205 1205 Try again but with a corrupted shelve state file
1206 1206 $ hg strip -r 2 -r 1 -q
1207 1207 $ hg up -r 0 -q
1208 1208 $ echo '' > root
1209 1209 $ hg shelve -q
1210 1210 $ echo 'contADDent' > root
1211 1211 $ hg unshelve -q
1212 1212 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1213 1213 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1214 1214 [1]
1215 1215 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1216 1216 $ mv ../corrupt-shelvedstate .hg/histedit-state
1217 1217 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1218 1218 rebase aborted
1219 1219 $ hg up -C .
1220 1220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1221 1221
1222 1222 $ cd ..
1223 1223
1224 1224 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1225 1225 -----------------------------------------------------------------------
1226 1226
1227 1227 $ cat <<EOF >> $HGRCPATH
1228 1228 > [extensions]
1229 1229 > share =
1230 1230 > EOF
1231 1231
1232 1232 $ hg bookmarks -R repo
1233 1233 test 4:33f7f61e6c5e
1234 1234 $ hg share -B repo share
1235 1235 updating working directory
1236 1236 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1237 1237 $ cd share
1238 1238
1239 1239 $ hg bookmarks
1240 1240 test 4:33f7f61e6c5e
1241 1241 $ hg bookmarks foo
1242 1242 $ hg bookmarks
1243 1243 * foo 5:703117a2acfb
1244 1244 test 4:33f7f61e6c5e
1245 1245 $ echo x >> x
1246 1246 $ hg shelve
1247 1247 shelved as foo
1248 1248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1249 1249 $ hg bookmarks
1250 1250 * foo 5:703117a2acfb
1251 1251 test 4:33f7f61e6c5e
1252 1252
1253 1253 $ hg unshelve
1254 1254 unshelving change 'foo'
1255 1255 $ hg bookmarks
1256 1256 * foo 5:703117a2acfb
1257 1257 test 4:33f7f61e6c5e
1258 1258
1259 1259 $ cd ..
1260 1260
1261 1261 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
1262 1262 unknown file is the same as a shelved added file, except that it will be in
1263 1263 unknown state after unshelve if and only if it was either absent or unknown
1264 1264 before the unshelve operation.
1265 1265
1266 1266 $ hg init unknowns
1267 1267 $ cd unknowns
1268 1268
1269 1269 The simplest case is if I simply have an unknown file that I shelve and unshelve
1270 1270
1271 1271 $ echo unknown > unknown
1272 1272 $ hg status
1273 1273 ? unknown
1274 1274 $ hg shelve --unknown
1275 1275 shelved as default
1276 1276 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1277 1277 $ hg status
1278 1278 $ hg unshelve
1279 1279 unshelving change 'default'
1280 1280 $ hg status
1281 1281 ? unknown
1282 1282 $ rm unknown
1283 1283
1284 1284 If I shelve, add the file, and unshelve, does it stay added?
1285 1285
1286 1286 $ echo unknown > unknown
1287 1287 $ hg shelve -u
1288 1288 shelved as default
1289 1289 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1290 1290 $ hg status
1291 1291 $ touch unknown
1292 1292 $ hg add unknown
1293 1293 $ hg status
1294 1294 A unknown
1295 1295 $ hg unshelve
1296 1296 unshelving change 'default'
1297 1297 temporarily committing pending changes (restore with 'hg unshelve --abort')
1298 1298 rebasing shelved changes
1299 1299 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1300 1300 merging unknown
1301 1301 $ hg status
1302 1302 A unknown
1303 1303 $ hg forget unknown
1304 1304 $ rm unknown
1305 1305
1306 1306 And if I shelve, commit, then unshelve, does it become modified?
1307 1307
1308 1308 $ echo unknown > unknown
1309 1309 $ hg shelve -u
1310 1310 shelved as default
1311 1311 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1312 1312 $ hg status
1313 1313 $ touch unknown
1314 1314 $ hg add unknown
1315 1315 $ hg commit -qm "Add unknown"
1316 1316 $ hg status
1317 1317 $ hg unshelve
1318 1318 unshelving change 'default'
1319 1319 rebasing shelved changes
1320 1320 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1321 1321 merging unknown
1322 1322 $ hg status
1323 1323 M unknown
1324 1324 $ hg remove --force unknown
1325 1325 $ hg commit -qm "Remove unknown"
1326 1326
1327 1327 $ cd ..
1328 1328
1329 1329 We expects that non-bare shelve keeps newly created branch in
1330 1330 working directory.
1331 1331
1332 1332 $ hg init shelve-preserve-new-branch
1333 1333 $ cd shelve-preserve-new-branch
1334 1334 $ echo "a" >> a
1335 1335 $ hg add a
1336 1336 $ echo "b" >> b
1337 1337 $ hg add b
1338 1338 $ hg commit -m "ab"
1339 1339 $ echo "aa" >> a
1340 1340 $ echo "bb" >> b
1341 1341 $ hg branch new-branch
1342 1342 marked working directory as branch new-branch
1343 1343 (branches are permanent and global, did you want a bookmark?)
1344 1344 $ hg status
1345 1345 M a
1346 1346 M b
1347 1347 $ hg branch
1348 1348 new-branch
1349 1349 $ hg shelve a
1350 1350 shelved as default
1351 1351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1352 1352 $ hg branch
1353 1353 new-branch
1354 1354 $ hg status
1355 1355 M b
1356 1356 $ touch "c" >> c
1357 1357 $ hg add c
1358 1358 $ hg status
1359 1359 M b
1360 1360 A c
1361 1361 $ hg shelve --exclude c
1362 1362 shelved as default-01
1363 1363 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1364 1364 $ hg branch
1365 1365 new-branch
1366 1366 $ hg status
1367 1367 A c
1368 1368 $ hg shelve --include c
1369 1369 shelved as default-02
1370 1370 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1371 1371 $ hg branch
1372 1372 new-branch
1373 1373 $ hg status
1374 1374 $ echo "d" >> d
1375 1375 $ hg add d
1376 1376 $ hg status
1377 1377 A d
1378 1378
1379 1379 We expect that bare-shelve will not keep branch in current working directory.
1380 1380
1381 1381 $ hg shelve
1382 1382 shelved as default-03
1383 1383 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1384 1384 $ hg branch
1385 1385 default
1386 1386
1387 1387 When i shelve commit on newly created branch i expect
1388 1388 that after unshelve newly created branch will be preserved.
1389 1389
1390 1390 $ hg init shelve_on_new_branch_simple
1391 1391 $ cd shelve_on_new_branch_simple
1392 1392 $ echo "aaa" >> a
1393 1393 $ hg commit -A -m "a"
1394 1394 adding a
1395 1395 $ hg branch
1396 1396 default
1397 1397 $ hg branch test
1398 1398 marked working directory as branch test
1399 1399 (branches are permanent and global, did you want a bookmark?)
1400 1400 $ echo "bbb" >> a
1401 1401 $ hg status
1402 1402 M a
1403 1403 $ hg shelve
1404 1404 shelved as default
1405 1405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1406 1406 $ hg branch
1407 1407 default
1408 1408 $ echo "bbb" >> b
1409 1409 $ hg status
1410 1410 ? b
1411 1411 $ hg unshelve
1412 1412 unshelving change 'default'
1413 1413 marked working directory as branch test
1414 1414 $ hg status
1415 1415 M a
1416 1416 ? b
1417 1417 $ hg branch
1418 1418 test
1419 1419
1420 1420 When i shelve commit on newly created branch, make
1421 1421 some changes, unshelve it and running into merge
1422 1422 conflicts i expect that after fixing them and
1423 1423 running unshelve --continue newly created branch
1424 1424 will be preserved.
1425 1425
1426 1426 $ hg init shelve_on_new_branch_conflict
1427 1427 $ cd shelve_on_new_branch_conflict
1428 1428 $ echo "aaa" >> a
1429 1429 $ hg commit -A -m "a"
1430 1430 adding a
1431 1431 $ hg branch
1432 1432 default
1433 1433 $ hg branch test
1434 1434 marked working directory as branch test
1435 1435 (branches are permanent and global, did you want a bookmark?)
1436 1436 $ echo "bbb" >> a
1437 1437 $ hg status
1438 1438 M a
1439 1439 $ hg shelve
1440 1440 shelved as default
1441 1441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1442 1442 $ hg branch
1443 1443 default
1444 1444 $ echo "ccc" >> a
1445 1445 $ hg status
1446 1446 M a
1447 1447 $ hg unshelve
1448 1448 unshelving change 'default'
1449 1449 temporarily committing pending changes (restore with 'hg unshelve --abort')
1450 1450 rebasing shelved changes
1451 1451 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1452 1452 merging a
1453 1453 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1454 1454 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1455 1455 [1]
1456 1456 $ echo "aaabbbccc" > a
1457 1457 $ rm a.orig
1458 1458 $ hg resolve --mark a
1459 1459 (no more unresolved files)
1460 1460 continue: hg unshelve --continue
1461 1461 $ hg unshelve --continue
1462 1462 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1463 1463 marked working directory as branch test
1464 1464 unshelve of 'default' complete
1465 1465 $ cat a
1466 1466 aaabbbccc
1467 1467 $ hg status
1468 1468 M a
1469 1469 $ hg branch
1470 1470 test
1471 1471 $ hg commit -m "test-commit"
1472 1472
1473 1473 When i shelve on test branch, update to default branch
1474 1474 and unshelve i expect that it will not preserve previous
1475 1475 test branch.
1476 1476
1477 1477 $ echo "xxx" > b
1478 1478 $ hg add b
1479 1479 $ hg shelve
1480 1480 shelved as test
1481 1481 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1482 1482 $ hg update -r default
1483 1483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1484 1484 $ hg unshelve
1485 1485 unshelving change 'test'
1486 1486 rebasing shelved changes
1487 1487 rebasing 2:357525f34729 "changes to: test-commit" (tip)
1488 1488 $ hg status
1489 1489 A b
1490 1490 $ hg branch
1491 1491 default
1492 1492
1493 1493 When i unshelve resulting in merge conflicts and makes saved
1494 1494 file shelvedstate looks like in previous versions in
1495 1495 mercurial(without restore branch information in 7th line) i
1496 1496 expect that after resolving conflicts and succesfully
1497 1497 running 'shelve --continue' the branch information won't be
1498 1498 restored and branch will be unchanged.
1499 1499
1500 1500 shelve on new branch, conflict with previous shelvedstate
1501 1501
1502 1502 $ hg init conflict
1503 1503 $ cd conflict
1504 1504 $ echo "aaa" >> a
1505 1505 $ hg commit -A -m "a"
1506 1506 adding a
1507 1507 $ hg branch
1508 1508 default
1509 1509 $ hg branch test
1510 1510 marked working directory as branch test
1511 1511 (branches are permanent and global, did you want a bookmark?)
1512 1512 $ echo "bbb" >> a
1513 1513 $ hg status
1514 1514 M a
1515 1515 $ hg shelve
1516 1516 shelved as default
1517 1517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1518 1518 $ hg branch
1519 1519 default
1520 1520 $ echo "ccc" >> a
1521 1521 $ hg status
1522 1522 M a
1523 1523 $ hg unshelve
1524 1524 unshelving change 'default'
1525 1525 temporarily committing pending changes (restore with 'hg unshelve --abort')
1526 1526 rebasing shelved changes
1527 1527 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1528 1528 merging a
1529 1529 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1530 1530 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1531 1531 [1]
1532 1532
1533 1533 Removing restore branch information from shelvedstate file(making it looks like
1534 1534 in previous versions) and running unshelve --continue
1535 1535
1536 1536 $ head -n 6 < .hg/shelvedstate > .hg/shelvedstate_oldformat
1537 1537 $ rm .hg/shelvedstate
1538 1538 $ mv .hg/shelvedstate_oldformat .hg/shelvedstate
1539 1539
1540 1540 $ echo "aaabbbccc" > a
1541 1541 $ rm a.orig
1542 1542 $ hg resolve --mark a
1543 1543 (no more unresolved files)
1544 1544 continue: hg unshelve --continue
1545 1545 $ hg unshelve --continue
1546 1546 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1547 1547 unshelve of 'default' complete
1548 1548 $ cat a
1549 1549 aaabbbccc
1550 1550 $ hg status
1551 1551 M a
1552 1552 $ hg branch
1553 1553 default
1554 1554
1555 1555 On non bare shelve the branch information shouldn't be restored
1556 1556
1557 1557 $ hg init bare_shelve_on_new_branch
1558 1558 $ cd bare_shelve_on_new_branch
1559 1559 $ echo "aaa" >> a
1560 1560 $ hg commit -A -m "a"
1561 1561 adding a
1562 1562 $ hg branch
1563 1563 default
1564 1564 $ hg branch test
1565 1565 marked working directory as branch test
1566 1566 (branches are permanent and global, did you want a bookmark?)
1567 1567 $ echo "bbb" >> a
1568 1568 $ hg status
1569 1569 M a
1570 1570 $ hg shelve a
1571 1571 shelved as default
1572 1572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1573 1573 $ hg branch
1574 1574 test
1575 1575 $ hg branch default
1576 1576 marked working directory as branch default
1577 1577 (branches are permanent and global, did you want a bookmark?)
1578 1578 $ echo "bbb" >> b
1579 1579 $ hg status
1580 1580 ? b
1581 1581 $ hg unshelve
1582 1582 unshelving change 'default'
1583 1583 $ hg status
1584 1584 M a
1585 1585 ? b
1586 1586 $ hg branch
1587 1587 default
1588 $ cd ..
1589
1590 Prepare unshleve with a corrupted shelvedstate
1591 $ hg init r1 && cd r1
1592 $ echo text1 > file && hg add file
1593 $ hg shelve
1594 shelved as default
1595 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1596 $ echo text2 > file && hg ci -Am text1
1597 adding file
1598 $ hg unshelve
1599 unshelving change 'default'
1600 rebasing shelved changes
1601 rebasing 1:396ea74229f9 "(changes in empty repository)" (tip)
1602 merging file
1603 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
1604 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1605 [1]
1606 $ echo somethingsomething > .hg/shelvedstate
1607
1608 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
1609 $ hg unshelve --continue
1610 abort: corrupted shelved state file
1611 (please run hg unshelve --abort to abort unshelve operation)
1612 [255]
1613
1614 Unshelve --abort works with a corrupted shelvedstate
1615 $ hg unshelve --abort
1616 could not read shelved state file, your working copy may be in an unexpected state
1617 please update to some commit
1618
1619 Unshelve --abort fails with appropriate message if there's no unshelve in
1620 progress
1621 $ hg unshelve --abort
1622 abort: no unshelve in progress
1623 [255]
1624 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now