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