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