##// END OF EJS Templates
shelve: choose where .orig file locations are kept...
Christian Delahousse -
r26942:d55d2284 default
parent child Browse files
Show More
@@ -1,839 +1,839 b''
1 1 # shelve.py - save/restore working directory state
2 2 #
3 3 # Copyright 2013 Facebook, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 """save and restore changes to the working directory
9 9
10 10 The "hg shelve" command saves changes made to the working directory
11 11 and reverts those changes, resetting the working directory to a clean
12 12 state.
13 13
14 14 Later on, the "hg unshelve" command restores the changes saved by "hg
15 15 shelve". Changes can be restored even after updating to a different
16 16 parent, in which case Mercurial's merge machinery will resolve any
17 17 conflicts if necessary.
18 18
19 19 You can have more than one shelved change outstanding at a time; each
20 20 shelved change has a distinct name. For details, see the help for "hg
21 21 shelve".
22 22 """
23 23
24 24 import collections
25 25 import itertools
26 26 from mercurial.i18n import _
27 27 from mercurial.node import nullid, nullrev, bin, hex
28 28 from mercurial import changegroup, cmdutil, scmutil, phases, commands
29 29 from mercurial import error, hg, mdiff, merge, patch, repair, util
30 30 from mercurial import templatefilters, exchange, bundlerepo, bundle2
31 31 from mercurial import lock as lockmod
32 32 from hgext import rebase
33 33 import errno
34 34
35 35 cmdtable = {}
36 36 command = cmdutil.command(cmdtable)
37 37 # Note for extension authors: ONLY specify testedwith = 'internal' for
38 38 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
39 39 # be specifying the version(s) of Mercurial they are tested with, or
40 40 # leave the attribute unspecified.
41 41 testedwith = 'internal'
42 42
43 43 backupdir = 'shelve-backup'
44 44
45 45 class shelvedfile(object):
46 46 """Helper for the file storing a single shelve
47 47
48 48 Handles common functions on shelve files (.hg/.patch) using
49 49 the vfs layer"""
50 50 def __init__(self, repo, name, filetype=None):
51 51 self.repo = repo
52 52 self.name = name
53 53 self.vfs = scmutil.vfs(repo.join('shelved'))
54 54 self.backupvfs = scmutil.vfs(repo.join(backupdir))
55 55 self.ui = self.repo.ui
56 56 if filetype:
57 57 self.fname = name + '.' + filetype
58 58 else:
59 59 self.fname = name
60 60
61 61 def exists(self):
62 62 return self.vfs.exists(self.fname)
63 63
64 64 def filename(self):
65 65 return self.vfs.join(self.fname)
66 66
67 67 def backupfilename(self):
68 68 def gennames(base):
69 69 yield base
70 70 base, ext = base.rsplit('.', 1)
71 71 for i in itertools.count(1):
72 72 yield '%s-%d.%s' % (base, i, ext)
73 73
74 74 name = self.backupvfs.join(self.fname)
75 75 for n in gennames(name):
76 76 if not self.backupvfs.exists(n):
77 77 return n
78 78
79 79 def movetobackup(self):
80 80 if not self.backupvfs.isdir():
81 81 self.backupvfs.makedir()
82 82 util.rename(self.filename(), self.backupfilename())
83 83
84 84 def stat(self):
85 85 return self.vfs.stat(self.fname)
86 86
87 87 def opener(self, mode='rb'):
88 88 try:
89 89 return self.vfs(self.fname, mode)
90 90 except IOError as err:
91 91 if err.errno != errno.ENOENT:
92 92 raise
93 93 raise error.Abort(_("shelved change '%s' not found") % self.name)
94 94
95 95 def applybundle(self):
96 96 fp = self.opener()
97 97 try:
98 98 gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
99 99 if not isinstance(gen, bundle2.unbundle20):
100 100 gen.apply(self.repo, 'unshelve',
101 101 'bundle:' + self.vfs.join(self.fname),
102 102 targetphase=phases.secret)
103 103 if isinstance(gen, bundle2.unbundle20):
104 104 bundle2.applybundle(self.repo, gen,
105 105 self.repo.currenttransaction(),
106 106 source='unshelve',
107 107 url='bundle:' + self.vfs.join(self.fname))
108 108 finally:
109 109 fp.close()
110 110
111 111 def bundlerepo(self):
112 112 return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root,
113 113 self.vfs.join(self.fname))
114 114 def writebundle(self, bases, node):
115 115 btype = 'HG10BZ'
116 116 cgversion = '01'
117 117 compression = None
118 118 if 'generaldelta' in self.repo.requirements:
119 119 btype = 'HG20'
120 120 cgversion = '02'
121 121 compression = 'BZ'
122 122
123 123 cg = changegroup.changegroupsubset(self.repo, bases, [node], 'shelve',
124 124 version=cgversion)
125 125 changegroup.writebundle(self.ui, cg, self.fname, btype, self.vfs,
126 126 compression=compression)
127 127
128 128 class shelvedstate(object):
129 129 """Handle persistence during unshelving operations.
130 130
131 131 Handles saving and restoring a shelved state. Ensures that different
132 132 versions of a shelved state are possible and handles them appropriately.
133 133 """
134 134 _version = 1
135 135 _filename = 'shelvedstate'
136 136
137 137 @classmethod
138 138 def load(cls, repo):
139 139 fp = repo.vfs(cls._filename)
140 140 try:
141 141 version = int(fp.readline().strip())
142 142
143 143 if version != cls._version:
144 144 raise error.Abort(_('this version of shelve is incompatible '
145 145 'with the version used in this repo'))
146 146 name = fp.readline().strip()
147 147 wctx = fp.readline().strip()
148 148 pendingctx = fp.readline().strip()
149 149 parents = [bin(h) for h in fp.readline().split()]
150 150 stripnodes = [bin(h) for h in fp.readline().split()]
151 151 finally:
152 152 fp.close()
153 153
154 154 obj = cls()
155 155 obj.name = name
156 156 obj.wctx = repo[bin(wctx)]
157 157 obj.pendingctx = repo[bin(pendingctx)]
158 158 obj.parents = parents
159 159 obj.stripnodes = stripnodes
160 160
161 161 return obj
162 162
163 163 @classmethod
164 164 def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
165 165 fp = repo.vfs(cls._filename, 'wb')
166 166 fp.write('%i\n' % cls._version)
167 167 fp.write('%s\n' % name)
168 168 fp.write('%s\n' % hex(originalwctx.node()))
169 169 fp.write('%s\n' % hex(pendingctx.node()))
170 170 fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
171 171 fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
172 172 fp.close()
173 173
174 174 @classmethod
175 175 def clear(cls, repo):
176 176 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
177 177
178 178 def cleanupoldbackups(repo):
179 179 vfs = scmutil.vfs(repo.join(backupdir))
180 180 maxbackups = repo.ui.configint('shelve', 'maxbackups', 10)
181 181 hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')]
182 182 hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles])
183 183 if 0 < maxbackups and maxbackups < len(hgfiles):
184 184 bordermtime = hgfiles[-maxbackups][0]
185 185 else:
186 186 bordermtime = None
187 187 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
188 188 if mtime == bordermtime:
189 189 # keep it, because timestamp can't decide exact order of backups
190 190 continue
191 191 base = f[:-3]
192 192 for ext in 'hg patch'.split():
193 193 try:
194 194 vfs.unlink(base + '.' + ext)
195 195 except OSError as err:
196 196 if err.errno != errno.ENOENT:
197 197 raise
198 198
199 199 def _aborttransaction(repo):
200 200 '''Abort current transaction for shelve/unshelve, but keep dirstate
201 201 '''
202 202 backupname = 'dirstate.shelve'
203 203 dirstatebackup = None
204 204 try:
205 205 # create backup of (un)shelved dirstate, because aborting transaction
206 206 # should restore dirstate to one at the beginning of the
207 207 # transaction, which doesn't include the result of (un)shelving
208 208 fp = repo.vfs.open(backupname, "w")
209 209 dirstatebackup = backupname
210 210 # clearing _dirty/_dirtypl of dirstate by _writedirstate below
211 211 # is unintentional. but it doesn't cause problem in this case,
212 212 # because no code path refers them until transaction is aborted.
213 213 repo.dirstate._writedirstate(fp) # write in-memory changes forcibly
214 214
215 215 tr = repo.currenttransaction()
216 216 tr.abort()
217 217
218 218 # restore to backuped dirstate
219 219 repo.vfs.rename(dirstatebackup, 'dirstate')
220 220 dirstatebackup = None
221 221 finally:
222 222 if dirstatebackup:
223 223 repo.vfs.unlink(dirstatebackup)
224 224
225 225 def createcmd(ui, repo, pats, opts):
226 226 """subcommand that creates a new shelve"""
227 227
228 228 def mutableancestors(ctx):
229 229 """return all mutable ancestors for ctx (included)
230 230
231 231 Much faster than the revset ancestors(ctx) & draft()"""
232 232 seen = set([nullrev])
233 233 visit = collections.deque()
234 234 visit.append(ctx)
235 235 while visit:
236 236 ctx = visit.popleft()
237 237 yield ctx.node()
238 238 for parent in ctx.parents():
239 239 rev = parent.rev()
240 240 if rev not in seen:
241 241 seen.add(rev)
242 242 if parent.mutable():
243 243 visit.append(parent)
244 244
245 245 wctx = repo[None]
246 246 parents = wctx.parents()
247 247 if len(parents) > 1:
248 248 raise error.Abort(_('cannot shelve while merging'))
249 249 parent = parents[0]
250 250
251 251 # we never need the user, so we use a generic user for all shelve operations
252 252 user = 'shelve@localhost'
253 253 label = repo._activebookmark or parent.branch() or 'default'
254 254
255 255 # slashes aren't allowed in filenames, therefore we rename it
256 256 label = label.replace('/', '_')
257 257
258 258 def gennames():
259 259 yield label
260 260 for i in xrange(1, 100):
261 261 yield '%s-%02d' % (label, i)
262 262
263 263 def commitfunc(ui, repo, message, match, opts):
264 264 hasmq = util.safehasattr(repo, 'mq')
265 265 if hasmq:
266 266 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
267 267 backup = repo.ui.backupconfig('phases', 'new-commit')
268 268 try:
269 269 repo.ui. setconfig('phases', 'new-commit', phases.secret)
270 270 editor = cmdutil.getcommiteditor(editform='shelve.shelve', **opts)
271 271 return repo.commit(message, user, opts.get('date'), match,
272 272 editor=editor)
273 273 finally:
274 274 repo.ui.restoreconfig(backup)
275 275 if hasmq:
276 276 repo.mq.checkapplied = saved
277 277
278 278 if parent.node() != nullid:
279 279 desc = "changes to '%s'" % parent.description().split('\n', 1)[0]
280 280 else:
281 281 desc = '(changes in empty repository)'
282 282
283 283 if not opts['message']:
284 284 opts['message'] = desc
285 285
286 286 name = opts['name']
287 287
288 288 wlock = lock = tr = None
289 289 try:
290 290 wlock = repo.wlock()
291 291 lock = repo.lock()
292 292
293 293 # use an uncommitted transaction to generate the bundle to avoid
294 294 # pull races. ensure we don't print the abort message to stderr.
295 295 tr = repo.transaction('commit', report=lambda x: None)
296 296
297 297 if name:
298 298 if shelvedfile(repo, name, 'hg').exists():
299 299 raise error.Abort(_("a shelved change named '%s' already exists"
300 300 ) % name)
301 301 else:
302 302 for n in gennames():
303 303 if not shelvedfile(repo, n, 'hg').exists():
304 304 name = n
305 305 break
306 306 else:
307 307 raise error.Abort(_("too many shelved changes named '%s'") %
308 308 label)
309 309
310 310 # ensure we are not creating a subdirectory or a hidden file
311 311 if '/' in name or '\\' in name:
312 312 raise error.Abort(_('shelved change names may not contain slashes'))
313 313 if name.startswith('.'):
314 314 raise error.Abort(_("shelved change names may not start with '.'"))
315 315 interactive = opts.get('interactive', False)
316 316
317 317 def interactivecommitfunc(ui, repo, *pats, **opts):
318 318 match = scmutil.match(repo['.'], pats, {})
319 319 message = opts['message']
320 320 return commitfunc(ui, repo, message, match, opts)
321 321 if not interactive:
322 322 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
323 323 else:
324 324 node = cmdutil.dorecord(ui, repo, interactivecommitfunc, None,
325 325 False, cmdutil.recordfilter, *pats, **opts)
326 326 if not node:
327 327 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
328 328 if stat.deleted:
329 329 ui.status(_("nothing changed (%d missing files, see "
330 330 "'hg status')\n") % len(stat.deleted))
331 331 else:
332 332 ui.status(_("nothing changed\n"))
333 333 return 1
334 334
335 335 bases = list(mutableancestors(repo[node]))
336 336 shelvedfile(repo, name, 'hg').writebundle(bases, node)
337 337 cmdutil.export(repo, [node],
338 338 fp=shelvedfile(repo, name, 'patch').opener('wb'),
339 339 opts=mdiff.diffopts(git=True))
340 340
341 341
342 342 if ui.formatted():
343 343 desc = util.ellipsis(desc, ui.termwidth())
344 344 ui.status(_('shelved as %s\n') % name)
345 345 hg.update(repo, parent.node())
346 346
347 347 _aborttransaction(repo)
348 348 finally:
349 349 lockmod.release(tr, lock, wlock)
350 350
351 351 def cleanupcmd(ui, repo):
352 352 """subcommand that deletes all shelves"""
353 353
354 354 wlock = None
355 355 try:
356 356 wlock = repo.wlock()
357 357 for (name, _type) in repo.vfs.readdir('shelved'):
358 358 suffix = name.rsplit('.', 1)[-1]
359 359 if suffix in ('hg', 'patch'):
360 360 shelvedfile(repo, name).movetobackup()
361 361 cleanupoldbackups(repo)
362 362 finally:
363 363 lockmod.release(wlock)
364 364
365 365 def deletecmd(ui, repo, pats):
366 366 """subcommand that deletes a specific shelve"""
367 367 if not pats:
368 368 raise error.Abort(_('no shelved changes specified!'))
369 369 wlock = repo.wlock()
370 370 try:
371 371 for name in pats:
372 372 for suffix in 'hg patch'.split():
373 373 shelvedfile(repo, name, suffix).movetobackup()
374 374 cleanupoldbackups(repo)
375 375 except OSError as err:
376 376 if err.errno != errno.ENOENT:
377 377 raise
378 378 raise error.Abort(_("shelved change '%s' not found") % name)
379 379 finally:
380 380 lockmod.release(wlock)
381 381
382 382 def listshelves(repo):
383 383 """return all shelves in repo as list of (time, filename)"""
384 384 try:
385 385 names = repo.vfs.readdir('shelved')
386 386 except OSError as err:
387 387 if err.errno != errno.ENOENT:
388 388 raise
389 389 return []
390 390 info = []
391 391 for (name, _type) in names:
392 392 pfx, sfx = name.rsplit('.', 1)
393 393 if not pfx or sfx != 'patch':
394 394 continue
395 395 st = shelvedfile(repo, name).stat()
396 396 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
397 397 return sorted(info, reverse=True)
398 398
399 399 def listcmd(ui, repo, pats, opts):
400 400 """subcommand that displays the list of shelves"""
401 401 pats = set(pats)
402 402 width = 80
403 403 if not ui.plain():
404 404 width = ui.termwidth()
405 405 namelabel = 'shelve.newest'
406 406 for mtime, name in listshelves(repo):
407 407 sname = util.split(name)[1]
408 408 if pats and sname not in pats:
409 409 continue
410 410 ui.write(sname, label=namelabel)
411 411 namelabel = 'shelve.name'
412 412 if ui.quiet:
413 413 ui.write('\n')
414 414 continue
415 415 ui.write(' ' * (16 - len(sname)))
416 416 used = 16
417 417 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
418 418 ui.write(age, label='shelve.age')
419 419 ui.write(' ' * (12 - len(age)))
420 420 used += 12
421 421 fp = open(name + '.patch', 'rb')
422 422 try:
423 423 while True:
424 424 line = fp.readline()
425 425 if not line:
426 426 break
427 427 if not line.startswith('#'):
428 428 desc = line.rstrip()
429 429 if ui.formatted():
430 430 desc = util.ellipsis(desc, width - used)
431 431 ui.write(desc)
432 432 break
433 433 ui.write('\n')
434 434 if not (opts['patch'] or opts['stat']):
435 435 continue
436 436 difflines = fp.readlines()
437 437 if opts['patch']:
438 438 for chunk, label in patch.difflabel(iter, difflines):
439 439 ui.write(chunk, label=label)
440 440 if opts['stat']:
441 441 for chunk, label in patch.diffstatui(difflines, width=width,
442 442 git=True):
443 443 ui.write(chunk, label=label)
444 444 finally:
445 445 fp.close()
446 446
447 447 def singlepatchcmds(ui, repo, pats, opts, subcommand):
448 448 """subcommand that displays a single shelf"""
449 449 if len(pats) != 1:
450 450 raise error.Abort(_("--%s expects a single shelf") % subcommand)
451 451 shelfname = pats[0]
452 452
453 453 if not shelvedfile(repo, shelfname, 'patch').exists():
454 454 raise error.Abort(_("cannot find shelf %s") % shelfname)
455 455
456 456 listcmd(ui, repo, pats, opts)
457 457
458 458 def checkparents(repo, state):
459 459 """check parent while resuming an unshelve"""
460 460 if state.parents != repo.dirstate.parents():
461 461 raise error.Abort(_('working directory parents do not match unshelve '
462 462 'state'))
463 463
464 464 def pathtofiles(repo, files):
465 465 cwd = repo.getcwd()
466 466 return [repo.pathto(f, cwd) for f in files]
467 467
468 468 def unshelveabort(ui, repo, state, opts):
469 469 """subcommand that abort an in-progress unshelve"""
470 470 wlock = repo.wlock()
471 471 lock = None
472 472 try:
473 473 checkparents(repo, state)
474 474
475 475 util.rename(repo.join('unshelverebasestate'),
476 476 repo.join('rebasestate'))
477 477 try:
478 478 rebase.rebase(ui, repo, **{
479 479 'abort' : True
480 480 })
481 481 except Exception:
482 482 util.rename(repo.join('rebasestate'),
483 483 repo.join('unshelverebasestate'))
484 484 raise
485 485
486 486 lock = repo.lock()
487 487
488 488 mergefiles(ui, repo, state.wctx, state.pendingctx)
489 489
490 490 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
491 491 finally:
492 492 shelvedstate.clear(repo)
493 493 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
494 494 lockmod.release(lock, wlock)
495 495
496 496 def mergefiles(ui, repo, wctx, shelvectx):
497 497 """updates to wctx and merges the changes from shelvectx into the
498 498 dirstate."""
499 499 oldquiet = ui.quiet
500 500 try:
501 501 ui.quiet = True
502 502 hg.update(repo, wctx.node())
503 503 files = []
504 504 files.extend(shelvectx.files())
505 505 files.extend(shelvectx.parents()[0].files())
506 506
507 507 # revert will overwrite unknown files, so move them out of the way
508 508 for file in repo.status(unknown=True).unknown:
509 509 if file in files:
510 util.rename(file, file + ".orig")
510 util.rename(file, cmdutil.origpath(ui, repo, file))
511 511 ui.pushbuffer(True)
512 512 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
513 513 *pathtofiles(repo, files),
514 514 **{'no_backup': True})
515 515 ui.popbuffer()
516 516 finally:
517 517 ui.quiet = oldquiet
518 518
519 519 def unshelvecleanup(ui, repo, name, opts):
520 520 """remove related files after an unshelve"""
521 521 if not opts['keep']:
522 522 for filetype in 'hg patch'.split():
523 523 shelvedfile(repo, name, filetype).movetobackup()
524 524 cleanupoldbackups(repo)
525 525
526 526 def unshelvecontinue(ui, repo, state, opts):
527 527 """subcommand to continue an in-progress unshelve"""
528 528 # We're finishing off a merge. First parent is our original
529 529 # parent, second is the temporary "fake" commit we're unshelving.
530 530 wlock = repo.wlock()
531 531 lock = None
532 532 try:
533 533 checkparents(repo, state)
534 534 ms = merge.mergestate(repo)
535 535 if [f for f in ms if ms[f] == 'u']:
536 536 raise error.Abort(
537 537 _("unresolved conflicts, can't continue"),
538 538 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
539 539
540 540 lock = repo.lock()
541 541
542 542 util.rename(repo.join('unshelverebasestate'),
543 543 repo.join('rebasestate'))
544 544 try:
545 545 rebase.rebase(ui, repo, **{
546 546 'continue' : True
547 547 })
548 548 except Exception:
549 549 util.rename(repo.join('rebasestate'),
550 550 repo.join('unshelverebasestate'))
551 551 raise
552 552
553 553 shelvectx = repo['tip']
554 554 if not shelvectx in state.pendingctx.children():
555 555 # rebase was a no-op, so it produced no child commit
556 556 shelvectx = state.pendingctx
557 557 else:
558 558 # only strip the shelvectx if the rebase produced it
559 559 state.stripnodes.append(shelvectx.node())
560 560
561 561 mergefiles(ui, repo, state.wctx, shelvectx)
562 562
563 563 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
564 564 shelvedstate.clear(repo)
565 565 unshelvecleanup(ui, repo, state.name, opts)
566 566 ui.status(_("unshelve of '%s' complete\n") % state.name)
567 567 finally:
568 568 lockmod.release(lock, wlock)
569 569
570 570 @command('unshelve',
571 571 [('a', 'abort', None,
572 572 _('abort an incomplete unshelve operation')),
573 573 ('c', 'continue', None,
574 574 _('continue an incomplete unshelve operation')),
575 575 ('', 'keep', None,
576 576 _('keep shelve after unshelving')),
577 577 ('', 'date', '',
578 578 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
579 579 _('hg unshelve [SHELVED]'))
580 580 def unshelve(ui, repo, *shelved, **opts):
581 581 """restore a shelved change to the working directory
582 582
583 583 This command accepts an optional name of a shelved change to
584 584 restore. If none is given, the most recent shelved change is used.
585 585
586 586 If a shelved change is applied successfully, the bundle that
587 587 contains the shelved changes is moved to a backup location
588 588 (.hg/shelve-backup).
589 589
590 590 Since you can restore a shelved change on top of an arbitrary
591 591 commit, it is possible that unshelving will result in a conflict
592 592 between your changes and the commits you are unshelving onto. If
593 593 this occurs, you must resolve the conflict, then use
594 594 ``--continue`` to complete the unshelve operation. (The bundle
595 595 will not be moved until you successfully complete the unshelve.)
596 596
597 597 (Alternatively, you can use ``--abort`` to abandon an unshelve
598 598 that causes a conflict. This reverts the unshelved changes, and
599 599 leaves the bundle in place.)
600 600
601 601 After a successful unshelve, the shelved changes are stored in a
602 602 backup directory. Only the N most recent backups are kept. N
603 603 defaults to 10 but can be overridden using the ``shelve.maxbackups``
604 604 configuration option.
605 605
606 606 .. container:: verbose
607 607
608 608 Timestamp in seconds is used to decide order of backups. More
609 609 than ``maxbackups`` backups are kept, if same timestamp
610 610 prevents from deciding exact order of them, for safety.
611 611 """
612 612 abortf = opts['abort']
613 613 continuef = opts['continue']
614 614 if not abortf and not continuef:
615 615 cmdutil.checkunfinished(repo)
616 616
617 617 if abortf or continuef:
618 618 if abortf and continuef:
619 619 raise error.Abort(_('cannot use both abort and continue'))
620 620 if shelved:
621 621 raise error.Abort(_('cannot combine abort/continue with '
622 622 'naming a shelved change'))
623 623
624 624 try:
625 625 state = shelvedstate.load(repo)
626 626 except IOError as err:
627 627 if err.errno != errno.ENOENT:
628 628 raise
629 629 raise error.Abort(_('no unshelve operation underway'))
630 630
631 631 if abortf:
632 632 return unshelveabort(ui, repo, state, opts)
633 633 elif continuef:
634 634 return unshelvecontinue(ui, repo, state, opts)
635 635 elif len(shelved) > 1:
636 636 raise error.Abort(_('can only unshelve one change at a time'))
637 637 elif not shelved:
638 638 shelved = listshelves(repo)
639 639 if not shelved:
640 640 raise error.Abort(_('no shelved changes to apply!'))
641 641 basename = util.split(shelved[0][1])[1]
642 642 ui.status(_("unshelving change '%s'\n") % basename)
643 643 else:
644 644 basename = shelved[0]
645 645
646 646 if not shelvedfile(repo, basename, 'patch').exists():
647 647 raise error.Abort(_("shelved change '%s' not found") % basename)
648 648
649 649 oldquiet = ui.quiet
650 650 wlock = lock = tr = None
651 651 try:
652 652 wlock = repo.wlock()
653 653 lock = repo.lock()
654 654
655 655 tr = repo.transaction('unshelve', report=lambda x: None)
656 656 oldtiprev = len(repo)
657 657
658 658 pctx = repo['.']
659 659 tmpwctx = pctx
660 660 # The goal is to have a commit structure like so:
661 661 # ...-> pctx -> tmpwctx -> shelvectx
662 662 # where tmpwctx is an optional commit with the user's pending changes
663 663 # and shelvectx is the unshelved changes. Then we merge it all down
664 664 # to the original pctx.
665 665
666 666 # Store pending changes in a commit
667 667 s = repo.status()
668 668 if s.modified or s.added or s.removed or s.deleted:
669 669 ui.status(_("temporarily committing pending changes "
670 670 "(restore with 'hg unshelve --abort')\n"))
671 671 def commitfunc(ui, repo, message, match, opts):
672 672 hasmq = util.safehasattr(repo, 'mq')
673 673 if hasmq:
674 674 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
675 675
676 676 backup = repo.ui.backupconfig('phases', 'new-commit')
677 677 try:
678 678 repo.ui. setconfig('phases', 'new-commit', phases.secret)
679 679 return repo.commit(message, 'shelve@localhost',
680 680 opts.get('date'), match)
681 681 finally:
682 682 repo.ui.restoreconfig(backup)
683 683 if hasmq:
684 684 repo.mq.checkapplied = saved
685 685
686 686 tempopts = {}
687 687 tempopts['message'] = "pending changes temporary commit"
688 688 tempopts['date'] = opts.get('date')
689 689 ui.quiet = True
690 690 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
691 691 tmpwctx = repo[node]
692 692
693 693 ui.quiet = True
694 694 shelvedfile(repo, basename, 'hg').applybundle()
695 695
696 696 ui.quiet = oldquiet
697 697
698 698 shelvectx = repo['tip']
699 699
700 700 # If the shelve is not immediately on top of the commit
701 701 # we'll be merging with, rebase it to be on top.
702 702 if tmpwctx.node() != shelvectx.parents()[0].node():
703 703 ui.status(_('rebasing shelved changes\n'))
704 704 try:
705 705 rebase.rebase(ui, repo, **{
706 706 'rev' : [shelvectx.rev()],
707 707 'dest' : str(tmpwctx.rev()),
708 708 'keep' : True,
709 709 })
710 710 except error.InterventionRequired:
711 711 tr.close()
712 712
713 713 stripnodes = [repo.changelog.node(rev)
714 714 for rev in xrange(oldtiprev, len(repo))]
715 715 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
716 716
717 717 util.rename(repo.join('rebasestate'),
718 718 repo.join('unshelverebasestate'))
719 719 raise error.InterventionRequired(
720 720 _("unresolved conflicts (see 'hg resolve', then "
721 721 "'hg unshelve --continue')"))
722 722
723 723 # refresh ctx after rebase completes
724 724 shelvectx = repo['tip']
725 725
726 726 if not shelvectx in tmpwctx.children():
727 727 # rebase was a no-op, so it produced no child commit
728 728 shelvectx = tmpwctx
729 729
730 730 mergefiles(ui, repo, pctx, shelvectx)
731 731 shelvedstate.clear(repo)
732 732
733 733 # The transaction aborting will strip all the commits for us,
734 734 # but it doesn't update the inmemory structures, so addchangegroup
735 735 # hooks still fire and try to operate on the missing commits.
736 736 # Clean up manually to prevent this.
737 737 repo.unfiltered().changelog.strip(oldtiprev, tr)
738 738
739 739 unshelvecleanup(ui, repo, basename, opts)
740 740
741 741 _aborttransaction(repo)
742 742 finally:
743 743 ui.quiet = oldquiet
744 744 if tr:
745 745 tr.release()
746 746 lockmod.release(lock, wlock)
747 747
748 748 @command('shelve',
749 749 [('A', 'addremove', None,
750 750 _('mark new/missing files as added/removed before shelving')),
751 751 ('', 'cleanup', None,
752 752 _('delete all shelved changes')),
753 753 ('', 'date', '',
754 754 _('shelve with the specified commit date'), _('DATE')),
755 755 ('d', 'delete', None,
756 756 _('delete the named shelved change(s)')),
757 757 ('e', 'edit', False,
758 758 _('invoke editor on commit messages')),
759 759 ('l', 'list', None,
760 760 _('list current shelves')),
761 761 ('m', 'message', '',
762 762 _('use text as shelve message'), _('TEXT')),
763 763 ('n', 'name', '',
764 764 _('use the given name for the shelved commit'), _('NAME')),
765 765 ('p', 'patch', None,
766 766 _('show patch')),
767 767 ('i', 'interactive', None,
768 768 _('interactive mode, only works while creating a shelve')),
769 769 ('', 'stat', None,
770 770 _('output diffstat-style summary of changes'))] + commands.walkopts,
771 771 _('hg shelve [OPTION]... [FILE]...'))
772 772 def shelvecmd(ui, repo, *pats, **opts):
773 773 '''save and set aside changes from the working directory
774 774
775 775 Shelving takes files that "hg status" reports as not clean, saves
776 776 the modifications to a bundle (a shelved change), and reverts the
777 777 files so that their state in the working directory becomes clean.
778 778
779 779 To restore these changes to the working directory, using "hg
780 780 unshelve"; this will work even if you switch to a different
781 781 commit.
782 782
783 783 When no files are specified, "hg shelve" saves all not-clean
784 784 files. If specific files or directories are named, only changes to
785 785 those files are shelved.
786 786
787 787 Each shelved change has a name that makes it easier to find later.
788 788 The name of a shelved change defaults to being based on the active
789 789 bookmark, or if there is no active bookmark, the current named
790 790 branch. To specify a different name, use ``--name``.
791 791
792 792 To see a list of existing shelved changes, use the ``--list``
793 793 option. For each shelved change, this will print its name, age,
794 794 and description; use ``--patch`` or ``--stat`` for more details.
795 795
796 796 To delete specific shelved changes, use ``--delete``. To delete
797 797 all shelved changes, use ``--cleanup``.
798 798 '''
799 799 cmdutil.checkunfinished(repo)
800 800
801 801 allowables = [
802 802 ('addremove', set(['create'])), # 'create' is pseudo action
803 803 ('cleanup', set(['cleanup'])),
804 804 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
805 805 ('delete', set(['delete'])),
806 806 ('edit', set(['create'])),
807 807 ('list', set(['list'])),
808 808 ('message', set(['create'])),
809 809 ('name', set(['create'])),
810 810 ('patch', set(['patch', 'list'])),
811 811 ('stat', set(['stat', 'list'])),
812 812 ]
813 813 def checkopt(opt):
814 814 if opts[opt]:
815 815 for i, allowable in allowables:
816 816 if opts[i] and opt not in allowable:
817 817 raise error.Abort(_("options '--%s' and '--%s' may not be "
818 818 "used together") % (opt, i))
819 819 return True
820 820 if checkopt('cleanup'):
821 821 if pats:
822 822 raise error.Abort(_("cannot specify names when using '--cleanup'"))
823 823 return cleanupcmd(ui, repo)
824 824 elif checkopt('delete'):
825 825 return deletecmd(ui, repo, pats)
826 826 elif checkopt('list'):
827 827 return listcmd(ui, repo, pats, opts)
828 828 elif checkopt('patch'):
829 829 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
830 830 elif checkopt('stat'):
831 831 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
832 832 else:
833 833 return createcmd(ui, repo, pats, opts)
834 834
835 835 def extsetup(ui):
836 836 cmdutil.unfinishedstates.append(
837 837 [shelvedstate._filename, False, False,
838 838 _('unshelve already in progress'),
839 839 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
@@ -1,1215 +1,1221 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 Each shelved change has a name that makes it easier to find later. The
40 40 name of a shelved change defaults to being based on the active bookmark,
41 41 or if there is no active bookmark, the current named branch. To specify a
42 42 different name, use "--name".
43 43
44 44 To see a list of existing shelved changes, use the "--list" option. For
45 45 each shelved change, this will print its name, age, and description; use "
46 46 --patch" or "--stat" for more details.
47 47
48 48 To delete specific shelved changes, use "--delete". To delete all shelved
49 49 changes, use "--cleanup".
50 50
51 51 (use "hg help -e shelve" to show help for the shelve extension)
52 52
53 53 options ([+] can be repeated):
54 54
55 55 -A --addremove mark new/missing files as added/removed before
56 56 shelving
57 57 --cleanup delete all shelved changes
58 58 --date DATE shelve with the specified commit date
59 59 -d --delete delete the named shelved change(s)
60 60 -e --edit invoke editor on commit messages
61 61 -l --list list current shelves
62 62 -m --message TEXT use text as shelve message
63 63 -n --name NAME use the given name for the shelved commit
64 64 -p --patch show patch
65 65 -i --interactive interactive mode, only works while creating a shelve
66 66 --stat output diffstat-style summary of changes
67 67 -I --include PATTERN [+] include names matching the given patterns
68 68 -X --exclude PATTERN [+] exclude names matching the given patterns
69 69 --mq operate on patch repository
70 70
71 71 (some details hidden, use --verbose to show complete help)
72 72
73 73 shelving in an empty repo should be possible
74 74 (this tests also that editor is not invoked, if '--edit' is not
75 75 specified)
76 76
77 77 $ HGEDITOR=cat hg shelve
78 78 shelved as default
79 79 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
80 80
81 81 $ hg unshelve
82 82 unshelving change 'default'
83 83
84 84 $ hg commit -q -m 'initial commit'
85 85
86 86 $ hg shelve
87 87 nothing changed
88 88 [1]
89 89
90 90 make sure shelve files were backed up
91 91
92 92 $ ls .hg/shelve-backup
93 93 default.hg
94 94 default.patch
95 95
96 96 create an mq patch - shelving should work fine with a patch applied
97 97
98 98 $ echo n > n
99 99 $ hg add n
100 100 $ hg commit n -m second
101 101 $ hg qnew second.patch
102 102
103 103 shelve a change that we will delete later
104 104
105 105 $ echo a >> a/a
106 106 $ hg shelve
107 107 shelved as default
108 108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109
110 110 set up some more complex changes to shelve
111 111
112 112 $ echo a >> a/a
113 113 $ hg mv b b.rename
114 114 moving b/b to b.rename/b (glob)
115 115 $ hg cp c c.copy
116 116 $ hg status -C
117 117 M a/a
118 118 A b.rename/b
119 119 b/b
120 120 A c.copy
121 121 c
122 122 R b/b
123 123
124 124 prevent some foot-shooting
125 125
126 126 $ hg shelve -n foo/bar
127 127 abort: shelved change names may not contain slashes
128 128 [255]
129 129 $ hg shelve -n .baz
130 130 abort: shelved change names may not start with '.'
131 131 [255]
132 132
133 133 the common case - no options or filenames
134 134
135 135 $ hg shelve
136 136 shelved as default-01
137 137 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
138 138 $ hg status -C
139 139
140 140 ensure that our shelved changes exist
141 141
142 142 $ hg shelve -l
143 143 default-01 (*)* changes to '[mq]: second.patch' (glob)
144 144 default (*)* changes to '[mq]: second.patch' (glob)
145 145
146 146 $ hg shelve -l -p default
147 147 default (*)* changes to '[mq]: second.patch' (glob)
148 148
149 149 diff --git a/a/a b/a/a
150 150 --- a/a/a
151 151 +++ b/a/a
152 152 @@ -1,1 +1,2 @@
153 153 a
154 154 +a
155 155
156 156 $ hg shelve --list --addremove
157 157 abort: options '--list' and '--addremove' may not be used together
158 158 [255]
159 159
160 160 delete our older shelved change
161 161
162 162 $ hg shelve -d default
163 163 $ hg qfinish -a -q
164 164
165 165 ensure shelve backups aren't overwritten
166 166
167 167 $ ls .hg/shelve-backup/
168 168 default-1.hg
169 169 default-1.patch
170 170 default.hg
171 171 default.patch
172 172
173 173 local edits should not prevent a shelved change from applying
174 174
175 175 $ printf "z\na\n" > a/a
176 176 $ hg unshelve --keep
177 177 unshelving change 'default-01'
178 178 temporarily committing pending changes (restore with 'hg unshelve --abort')
179 179 rebasing shelved changes
180 180 rebasing 4:4702e8911fe0 "changes to '[mq]: second.patch'" (tip)
181 181 merging a/a
182 182
183 183 $ hg revert --all -q
184 184 $ rm a/a.orig b.rename/b c.copy
185 185
186 186 apply it and make sure our state is as expected
187 187
188 188 (this also tests that same timestamp prevents backups from being
189 189 removed, even though there are more than 'maxbackups' backups)
190 190
191 191 $ f -t .hg/shelve-backup/default.hg
192 192 .hg/shelve-backup/default.hg: file
193 193 $ touch -t 200001010000 .hg/shelve-backup/default.hg
194 194 $ f -t .hg/shelve-backup/default-1.hg
195 195 .hg/shelve-backup/default-1.hg: file
196 196 $ touch -t 200001010000 .hg/shelve-backup/default-1.hg
197 197
198 198 $ hg unshelve
199 199 unshelving change 'default-01'
200 200 $ hg status -C
201 201 M a/a
202 202 A b.rename/b
203 203 b/b
204 204 A c.copy
205 205 c
206 206 R b/b
207 207 $ hg shelve -l
208 208
209 209 (both of default.hg and default-1.hg should be still kept, because it
210 210 is difficult to decide actual order of them from same timestamp)
211 211
212 212 $ ls .hg/shelve-backup/
213 213 default-01.hg
214 214 default-01.patch
215 215 default-1.hg
216 216 default-1.patch
217 217 default.hg
218 218 default.patch
219 219
220 220 $ hg unshelve
221 221 abort: no shelved changes to apply!
222 222 [255]
223 223 $ hg unshelve foo
224 224 abort: shelved change 'foo' not found
225 225 [255]
226 226
227 227 named shelves, specific filenames, and "commit messages" should all work
228 228 (this tests also that editor is invoked, if '--edit' is specified)
229 229
230 230 $ hg status -C
231 231 M a/a
232 232 A b.rename/b
233 233 b/b
234 234 A c.copy
235 235 c
236 236 R b/b
237 237 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
238 238 wat
239 239
240 240
241 241 HG: Enter commit message. Lines beginning with 'HG:' are removed.
242 242 HG: Leave message empty to abort commit.
243 243 HG: --
244 244 HG: user: shelve@localhost
245 245 HG: branch 'default'
246 246 HG: changed a/a
247 247
248 248 expect "a" to no longer be present, but status otherwise unchanged
249 249
250 250 $ hg status -C
251 251 A b.rename/b
252 252 b/b
253 253 A c.copy
254 254 c
255 255 R b/b
256 256 $ hg shelve -l --stat
257 257 wibble (*) wat (glob)
258 258 a/a | 1 +
259 259 1 files changed, 1 insertions(+), 0 deletions(-)
260 260
261 261 and now "a/a" should reappear
262 262
263 263 $ cd a
264 264 $ hg unshelve -q wibble
265 265 $ cd ..
266 266 $ hg status -C
267 267 M a/a
268 268 A b.rename/b
269 269 b/b
270 270 A c.copy
271 271 c
272 272 R b/b
273 273
274 274 ensure old shelve backups are being deleted automatically
275 275
276 276 $ ls .hg/shelve-backup/
277 277 default-01.hg
278 278 default-01.patch
279 279 wibble.hg
280 280 wibble.patch
281 281
282 282 cause unshelving to result in a merge with 'a' conflicting
283 283
284 284 $ hg shelve -q
285 285 $ echo c>>a/a
286 286 $ hg commit -m second
287 287 $ hg tip --template '{files}\n'
288 288 a/a
289 289
290 290 add an unrelated change that should be preserved
291 291
292 292 $ mkdir foo
293 293 $ echo foo > foo/foo
294 294 $ hg add foo/foo
295 295
296 296 force a conflicted merge to occur
297 297
298 298 $ hg unshelve
299 299 unshelving change 'default'
300 300 temporarily committing pending changes (restore with 'hg unshelve --abort')
301 301 rebasing shelved changes
302 302 rebasing 5:4702e8911fe0 "changes to '[mq]: second.patch'" (tip)
303 303 merging a/a
304 304 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
305 305 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
306 306 [1]
307 307
308 308 ensure that we have a merge with unresolved conflicts
309 309
310 310 $ hg heads -q --template '{rev}\n'
311 311 5
312 312 4
313 313 $ hg parents -q --template '{rev}\n'
314 314 4
315 315 5
316 316 $ hg status
317 317 M a/a
318 318 M b.rename/b
319 319 M c.copy
320 320 R b/b
321 321 ? a/a.orig
322 322 $ hg diff
323 323 diff --git a/a/a b/a/a
324 324 --- a/a/a
325 325 +++ b/a/a
326 326 @@ -1,2 +1,6 @@
327 327 a
328 328 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
329 329 c
330 330 +=======
331 331 +a
332 332 +>>>>>>> source: 4702e8911fe0 - shelve: changes to '[mq]: second.patch'
333 333 diff --git a/b/b b/b.rename/b
334 334 rename from b/b
335 335 rename to b.rename/b
336 336 diff --git a/c b/c.copy
337 337 copy from c
338 338 copy to c.copy
339 339 $ hg resolve -l
340 340 U a/a
341 341
342 342 $ hg shelve
343 343 abort: unshelve already in progress
344 344 (use 'hg unshelve --continue' or 'hg unshelve --abort')
345 345 [255]
346 346
347 347 abort the unshelve and be happy
348 348
349 349 $ hg status
350 350 M a/a
351 351 M b.rename/b
352 352 M c.copy
353 353 R b/b
354 354 ? a/a.orig
355 355 $ hg unshelve -a
356 356 rebase aborted
357 357 unshelve of 'default' aborted
358 358 $ hg heads -q
359 359 3:2e69b451d1ea
360 360 $ hg parents
361 361 changeset: 3:2e69b451d1ea
362 362 tag: tip
363 363 user: test
364 364 date: Thu Jan 01 00:00:00 1970 +0000
365 365 summary: second
366 366
367 367 $ hg resolve -l
368 368 $ hg status
369 369 A foo/foo
370 370 ? a/a.orig
371 371
372 372 try to continue with no unshelve underway
373 373
374 374 $ hg unshelve -c
375 375 abort: no unshelve operation underway
376 376 [255]
377 377 $ hg status
378 378 A foo/foo
379 379 ? a/a.orig
380 380
381 381 redo the unshelve to get a conflict
382 382
383 383 $ hg unshelve -q
384 384 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
385 385 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
386 386 [1]
387 387
388 388 attempt to continue
389 389
390 390 $ hg unshelve -c
391 391 abort: unresolved conflicts, can't continue
392 392 (see 'hg resolve', then 'hg unshelve --continue')
393 393 [255]
394 394
395 395 $ hg revert -r . a/a
396 396 $ hg resolve -m a/a
397 397 (no more unresolved files)
398 398
399 399 $ hg commit -m 'commit while unshelve in progress'
400 400 abort: unshelve already in progress
401 401 (use 'hg unshelve --continue' or 'hg unshelve --abort')
402 402 [255]
403 403
404 404 $ hg unshelve -c
405 405 rebasing 5:4702e8911fe0 "changes to '[mq]: second.patch'" (tip)
406 406 unshelve of 'default' complete
407 407
408 408 ensure the repo is as we hope
409 409
410 410 $ hg parents
411 411 changeset: 3:2e69b451d1ea
412 412 tag: tip
413 413 user: test
414 414 date: Thu Jan 01 00:00:00 1970 +0000
415 415 summary: second
416 416
417 417 $ hg heads -q
418 418 3:2e69b451d1ea
419 419
420 420 $ hg status -C
421 421 A b.rename/b
422 422 b/b
423 423 A c.copy
424 424 c
425 425 A foo/foo
426 426 R b/b
427 427 ? a/a.orig
428 428
429 429 there should be no shelves left
430 430
431 431 $ hg shelve -l
432 432
433 433 #if execbit
434 434
435 435 ensure that metadata-only changes are shelved
436 436
437 437 $ chmod +x a/a
438 438 $ hg shelve -q -n execbit a/a
439 439 $ hg status a/a
440 440 $ hg unshelve -q execbit
441 441 $ hg status a/a
442 442 M a/a
443 443 $ hg revert a/a
444 444
445 445 #endif
446 446
447 447 #if symlink
448 448
449 449 $ rm a/a
450 450 $ ln -s foo a/a
451 451 $ hg shelve -q -n symlink a/a
452 452 $ hg status a/a
453 453 $ hg unshelve -q symlink
454 454 $ hg status a/a
455 455 M a/a
456 456 $ hg revert a/a
457 457
458 458 #endif
459 459
460 460 set up another conflict between a commit and a shelved change
461 461
462 462 $ hg revert -q -C -a
463 463 $ rm a/a.orig b.rename/b c.copy
464 464 $ echo a >> a/a
465 465 $ hg shelve -q
466 466 $ echo x >> a/a
467 467 $ hg ci -m 'create conflict'
468 468 $ hg add foo/foo
469 469
470 470 if we resolve a conflict while unshelving, the unshelve should succeed
471 471
472 472 $ HGMERGE=true hg unshelve
473 473 unshelving change 'default'
474 474 temporarily committing pending changes (restore with 'hg unshelve --abort')
475 475 rebasing shelved changes
476 476 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
477 477 merging a/a
478 478 note: rebase of 6:c5e6910e7601 created no changes to commit
479 479 $ hg parents -q
480 480 4:33f7f61e6c5e
481 481 $ hg shelve -l
482 482 $ hg status
483 483 A foo/foo
484 484 $ cat a/a
485 485 a
486 486 c
487 487 x
488 488
489 489 test keep and cleanup
490 490
491 491 $ hg shelve
492 492 shelved as default
493 493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
494 494 $ hg shelve --list
495 495 default (*) changes to 'create conflict' (glob)
496 496 $ hg unshelve --keep
497 497 unshelving change 'default'
498 498 $ hg shelve --list
499 499 default (*) changes to 'create conflict' (glob)
500 500 $ hg shelve --cleanup
501 501 $ hg shelve --list
502 502
503 503 $ hg shelve --cleanup --delete
504 504 abort: options '--cleanup' and '--delete' may not be used together
505 505 [255]
506 506 $ hg shelve --cleanup --patch
507 507 abort: options '--cleanup' and '--patch' may not be used together
508 508 [255]
509 509 $ hg shelve --cleanup --message MESSAGE
510 510 abort: options '--cleanup' and '--message' may not be used together
511 511 [255]
512 512
513 513 test bookmarks
514 514
515 515 $ hg bookmark test
516 516 $ hg bookmark
517 517 * test 4:33f7f61e6c5e
518 518 $ hg shelve
519 519 shelved as test
520 520 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
521 521 $ hg bookmark
522 522 * test 4:33f7f61e6c5e
523 523 $ hg unshelve
524 524 unshelving change 'test'
525 525 $ hg bookmark
526 526 * test 4:33f7f61e6c5e
527 527
528 528 shelve should still work even if mq is disabled
529 529
530 530 $ hg --config extensions.mq=! shelve
531 531 shelved as test
532 532 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
533 533 $ hg --config extensions.mq=! shelve --list
534 534 test (*) changes to 'create conflict' (glob)
535 535 $ hg bookmark
536 536 * test 4:33f7f61e6c5e
537 537 $ hg --config extensions.mq=! unshelve
538 538 unshelving change 'test'
539 539 $ hg bookmark
540 540 * test 4:33f7f61e6c5e
541 541
542 542 shelve should leave dirstate clean (issue4055)
543 543
544 544 $ cd ..
545 545 $ hg init shelverebase
546 546 $ cd shelverebase
547 547 $ printf 'x\ny\n' > x
548 548 $ echo z > z
549 549 $ hg commit -Aqm xy
550 550 $ echo z >> x
551 551 $ hg commit -Aqm z
552 552 $ hg up 0
553 553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 554 $ printf 'a\nx\ny\nz\n' > x
555 555 $ hg commit -Aqm xyz
556 556 $ echo c >> z
557 557 $ hg shelve
558 558 shelved as default
559 559 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 560 $ hg rebase -d 1 --config extensions.rebase=
561 561 rebasing 2:323bfa07f744 "xyz" (tip)
562 562 merging x
563 563 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
564 564 $ hg unshelve
565 565 unshelving change 'default'
566 566 rebasing shelved changes
567 567 rebasing 4:b8fefe789ed0 "changes to 'xyz'" (tip)
568 568 $ hg status
569 569 M z
570 570
571 571 $ cd ..
572 572
573 573 shelve should only unshelve pending changes (issue4068)
574 574
575 575 $ hg init onlypendingchanges
576 576 $ cd onlypendingchanges
577 577 $ touch a
578 578 $ hg ci -Aqm a
579 579 $ touch b
580 580 $ hg ci -Aqm b
581 581 $ hg up -q 0
582 582 $ touch c
583 583 $ hg ci -Aqm c
584 584
585 585 $ touch d
586 586 $ hg add d
587 587 $ hg shelve
588 588 shelved as default
589 589 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
590 590 $ hg up -q 1
591 591 $ hg unshelve
592 592 unshelving change 'default'
593 593 rebasing shelved changes
594 594 rebasing 3:0cae6656c016 "changes to 'c'" (tip)
595 595 $ hg status
596 596 A d
597 597
598 598 unshelve should work on an ancestor of the original commit
599 599
600 600 $ hg shelve
601 601 shelved as default
602 602 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
603 603 $ hg up 0
604 604 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
605 605 $ hg unshelve
606 606 unshelving change 'default'
607 607 rebasing shelved changes
608 608 rebasing 3:be58f65f55fb "changes to 'b'" (tip)
609 609 $ hg status
610 610 A d
611 611
612 612 test bug 4073 we need to enable obsolete markers for it
613 613
614 614 $ cat >> $HGRCPATH << EOF
615 615 > [experimental]
616 616 > evolution=createmarkers
617 617 > EOF
618 618 $ hg shelve
619 619 shelved as default
620 620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 621 $ hg debugobsolete `hg --debug id -i -r 1`
622 622 $ hg unshelve
623 623 unshelving change 'default'
624 624
625 625 unshelve should leave unknown files alone (issue4113)
626 626
627 627 $ echo e > e
628 628 $ hg shelve
629 629 shelved as default
630 630 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
631 631 $ hg status
632 632 ? e
633 633 $ hg unshelve
634 634 unshelving change 'default'
635 635 $ hg status
636 636 A d
637 637 ? e
638 638 $ cat e
639 639 e
640 640
641 641 unshelve should keep a copy of unknown files
642 642
643 643 $ hg add e
644 644 $ hg shelve
645 645 shelved as default
646 646 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
647 647 $ echo z > e
648 648 $ hg unshelve
649 649 unshelving change 'default'
650 650 $ cat e
651 651 e
652 652 $ cat e.orig
653 653 z
654 654
655 655
656 656 unshelve and conflicts with tracked and untracked files
657 657
658 658 preparing:
659 659
660 660 $ rm *.orig
661 661 $ hg ci -qm 'commit stuff'
662 662 $ hg phase -p null:
663 663
664 664 no other changes - no merge:
665 665
666 666 $ echo f > f
667 667 $ hg add f
668 668 $ hg shelve
669 669 shelved as default
670 670 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
671 671 $ echo g > f
672 672 $ hg unshelve
673 673 unshelving change 'default'
674 674 $ hg st
675 675 A f
676 676 ? f.orig
677 677 $ cat f
678 678 f
679 679 $ cat f.orig
680 680 g
681 681
682 682 other uncommitted changes - merge:
683 683
684 684 $ hg st
685 685 A f
686 686 ? f.orig
687 687 $ hg shelve
688 688 shelved as default
689 689 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
690 690 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
691 691 o 4 changes to 'commit stuff' shelve@localhost
692 692 |
693 693 $ hg log -G --template '{rev} {desc|firstline} {author}'
694 694 @ 3 commit stuff test
695 695 |
696 696 | o 2 c test
697 697 |/
698 698 o 0 a test
699 699
700 700 $ mv f.orig f
701 701 $ echo 1 > a
702 702 $ hg unshelve --date '1073741824 0'
703 703 unshelving change 'default'
704 704 temporarily committing pending changes (restore with 'hg unshelve --abort')
705 705 rebasing shelved changes
706 706 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
707 707 merging f
708 708 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
709 709 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
710 710 [1]
711 711 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
712 712 @ 5 changes to 'commit stuff' shelve@localhost 1970-01-01 00:00 +0000
713 713 |
714 714 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
715 715 |/
716 716 o 3 commit stuff test 1970-01-01 00:00 +0000
717 717 |
718 718 | o 2 c test 1970-01-01 00:00 +0000
719 719 |/
720 720 o 0 a test 1970-01-01 00:00 +0000
721 721
722 722 $ hg st
723 723 M f
724 724 ? f.orig
725 725 $ cat f
726 726 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
727 727 g
728 728 =======
729 729 f
730 730 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
731 731 $ cat f.orig
732 732 g
733 733 $ hg unshelve --abort
734 734 rebase aborted
735 735 unshelve of 'default' aborted
736 736 $ hg st
737 737 M a
738 738 ? f.orig
739 739 $ cat f.orig
740 740 g
741 741 $ hg unshelve
742 742 unshelving change 'default'
743 743 temporarily committing pending changes (restore with 'hg unshelve --abort')
744 744 rebasing shelved changes
745 745 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
746 746 $ hg st
747 747 M a
748 748 A f
749 749 ? f.orig
750 750
751 751 other committed changes - merge:
752 752
753 753 $ hg shelve f
754 754 shelved as default
755 755 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
756 756 $ hg ci a -m 'intermediate other change'
757 757 $ mv f.orig f
758 758 $ hg unshelve
759 759 unshelving change 'default'
760 760 rebasing shelved changes
761 761 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
762 762 merging f
763 763 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
764 764 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
765 765 [1]
766 766 $ hg st
767 767 M f
768 768 ? f.orig
769 769 $ cat f
770 770 <<<<<<< dest: * - test: intermediate other change (glob)
771 771 g
772 772 =======
773 773 f
774 774 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
775 775 $ cat f.orig
776 776 g
777 777 $ hg unshelve --abort
778 778 rebase aborted
779 779 unshelve of 'default' aborted
780 780 $ hg st
781 781 ? f.orig
782 782 $ cat f.orig
783 783 g
784 784 $ hg shelve --delete default
785 785
786 786 Recreate some conflict again
787 787
788 788 $ cd ../repo
789 789 $ hg up -C -r 3
790 790 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
791 791 (leaving bookmark test)
792 792 $ echo y >> a/a
793 793 $ hg shelve
794 794 shelved as default
795 795 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
796 796 $ hg up test
797 797 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
798 798 (activating bookmark test)
799 799 $ hg bookmark
800 800 * test 4:33f7f61e6c5e
801 801 $ hg unshelve
802 802 unshelving change 'default'
803 803 rebasing shelved changes
804 804 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
805 805 merging a/a
806 806 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
807 807 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
808 808 [1]
809 809 $ hg bookmark
810 810 test 4:33f7f61e6c5e
811 811
812 812 Test that resolving all conflicts in one direction (so that the rebase
813 813 is a no-op), works (issue4398)
814 814
815 815 $ hg revert -a -r .
816 816 reverting a/a (glob)
817 817 $ hg resolve -m a/a
818 818 (no more unresolved files)
819 819 $ hg unshelve -c
820 820 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
821 821 note: rebase of 5:4b555fdb4e96 created no changes to commit
822 822 unshelve of 'default' complete
823 823 $ hg bookmark
824 824 * test 4:33f7f61e6c5e
825 825 $ hg diff
826 826 $ hg status
827 827 ? a/a.orig
828 828 ? foo/foo
829 829 $ hg summary
830 830 parent: 4:33f7f61e6c5e tip
831 831 create conflict
832 832 branch: default
833 833 bookmarks: *test
834 834 commit: 2 unknown (clean)
835 835 update: (current)
836 836 phases: 5 draft
837 837
838 838 $ hg shelve --delete --stat
839 839 abort: options '--delete' and '--stat' may not be used together
840 840 [255]
841 841 $ hg shelve --delete --name NAME
842 842 abort: options '--delete' and '--name' may not be used together
843 843 [255]
844 844
845 845 Test interactive shelve
846 846 $ cat <<EOF >> $HGRCPATH
847 847 > [ui]
848 848 > interactive = true
849 849 > EOF
850 850 $ echo 'a' >> a/b
851 851 $ cat a/a >> a/b
852 852 $ echo 'x' >> a/b
853 853 $ mv a/b a/a
854 854 $ echo 'a' >> foo/foo
855 855 $ hg st
856 856 M a/a
857 857 ? a/a.orig
858 858 ? foo/foo
859 859 $ cat a/a
860 860 a
861 861 a
862 862 c
863 863 x
864 864 x
865 865 $ cat foo/foo
866 866 foo
867 867 a
868 868 $ hg shelve --interactive --config ui.interactive=false
869 869 abort: running non-interactively
870 870 [255]
871 871 $ hg shelve --interactive << EOF
872 872 > y
873 873 > y
874 874 > n
875 875 > EOF
876 876 diff --git a/a/a b/a/a
877 877 2 hunks, 2 lines changed
878 878 examine changes to 'a/a'? [Ynesfdaq?] y
879 879
880 880 @@ -1,3 +1,4 @@
881 881 +a
882 882 a
883 883 c
884 884 x
885 885 record change 1/2 to 'a/a'? [Ynesfdaq?] y
886 886
887 887 @@ -1,3 +2,4 @@
888 888 a
889 889 c
890 890 x
891 891 +x
892 892 record change 2/2 to 'a/a'? [Ynesfdaq?] n
893 893
894 894 shelved as test
895 895 merging a/a
896 896 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
897 897 $ cat a/a
898 898 a
899 899 c
900 900 x
901 901 x
902 902 $ cat foo/foo
903 903 foo
904 904 a
905 905 $ hg st
906 906 M a/a
907 907 ? foo/foo
908 908 $ hg bookmark
909 909 * test 4:33f7f61e6c5e
910 910 $ hg unshelve
911 911 unshelving change 'test'
912 912 temporarily committing pending changes (restore with 'hg unshelve --abort')
913 913 rebasing shelved changes
914 914 rebasing 6:65b5d1c34c34 "changes to 'create conflict'" (tip)
915 915 merging a/a
916 916 $ hg bookmark
917 917 * test 4:33f7f61e6c5e
918 918 $ cat a/a
919 919 a
920 920 a
921 921 c
922 922 x
923 923 x
924 924
925 925 shelve --patch and shelve --stat should work with a single valid shelfname
926 926
927 927 $ hg up --clean .
928 928 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
929 929 (leaving bookmark test)
930 930 $ hg shelve --list
931 931 $ echo 'patch a' > shelf-patch-a
932 932 $ hg add shelf-patch-a
933 933 $ hg shelve
934 934 shelved as default
935 935 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
936 936 $ echo 'patch b' > shelf-patch-b
937 937 $ hg add shelf-patch-b
938 938 $ hg shelve
939 939 shelved as default-01
940 940 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
941 941 $ hg shelve --patch default default-01
942 942 abort: --patch expects a single shelf
943 943 [255]
944 944 $ hg shelve --stat default default-01
945 945 abort: --stat expects a single shelf
946 946 [255]
947 947 $ hg shelve --patch default
948 948 default (* ago) changes to 'create conflict' (glob)
949 949
950 950 diff --git a/shelf-patch-a b/shelf-patch-a
951 951 new file mode 100644
952 952 --- /dev/null
953 953 +++ b/shelf-patch-a
954 954 @@ -0,0 +1,1 @@
955 955 +patch a
956 956 $ hg shelve --stat default
957 957 default (* ago) changes to 'create conflict' (glob)
958 958 shelf-patch-a | 1 +
959 959 1 files changed, 1 insertions(+), 0 deletions(-)
960 960 $ hg shelve --patch nonexistentshelf
961 961 abort: cannot find shelf nonexistentshelf
962 962 [255]
963 963 $ hg shelve --stat nonexistentshelf
964 964 abort: cannot find shelf nonexistentshelf
965 965 [255]
966 966
967 967 $ cd ..
968 968
969 969 Shelve from general delta repo uses bundle2 on disk
970 970 --------------------------------------------------
971 971
972 972 no general delta
973 973
974 974 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
975 975 requesting all changes
976 976 adding changesets
977 977 adding manifests
978 978 adding file changes
979 979 added 5 changesets with 8 changes to 6 files
980 980 updating to branch default
981 981 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
982 982 $ cd bundle1
983 983 $ echo babar > jungle
984 984 $ hg add jungle
985 985 $ hg shelve
986 986 shelved as default
987 987 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
988 988 $ hg debugbundle .hg/shelved/*.hg
989 989 7e30d8ac6f23cfc84330fd7e698730374615d21a
990 990 $ cd ..
991 991
992 992 with general delta
993 993
994 994 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
995 995 requesting all changes
996 996 adding changesets
997 997 adding manifests
998 998 adding file changes
999 999 added 5 changesets with 8 changes to 6 files
1000 1000 updating to branch default
1001 1001 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1002 1002 $ cd bundle2
1003 1003 $ echo babar > jungle
1004 1004 $ hg add jungle
1005 1005 $ hg shelve
1006 1006 shelved as default
1007 1007 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1008 1008 $ hg debugbundle .hg/shelved/*.hg
1009 1009 Stream params: {'Compression': 'BZ'}
1010 1010 changegroup -- "{'version': '02'}"
1011 1011 7e30d8ac6f23cfc84330fd7e698730374615d21a
1012 1012 $ cd ..
1013 1013
1014 1014 Test visibility of in-memory changes inside transaction to external hook
1015 1015 ------------------------------------------------------------------------
1016 1016
1017 1017 $ cd repo
1018 1018
1019 1019 $ echo xxxx >> x
1020 1020 $ hg commit -m "#5: changes to invoke rebase"
1021 1021
1022 1022 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1023 1023 > echo "==== \$1:"
1024 1024 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1025 1025 > # test that pending changes are hidden
1026 1026 > unset HG_PENDING
1027 1027 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1028 1028 > echo "===="
1029 1029 > EOF
1030 1030
1031 1031 $ cat >> .hg/hgrc <<EOF
1032 1032 > [defaults]
1033 1033 > # to fix hash id of temporary revisions
1034 1034 > unshelve = --date '0 0'
1035 1035 > EOF
1036 1036
1037 1037 "hg unshelve" at REV5 implies steps below:
1038 1038
1039 1039 (1) commit changes in the working directory (REV6)
1040 1040 (2) unbundle shelved revision (REV7)
1041 1041 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1042 1042 (4) rebase: commit merged revision (REV8)
1043 1043 (5) rebase: update to REV6 (REV8 => REV6)
1044 1044 (6) update to REV5 (REV6 => REV5)
1045 1045 (7) abort transaction
1046 1046
1047 1047 == test visibility to external preupdate hook
1048 1048
1049 1049 $ cat >> .hg/hgrc <<EOF
1050 1050 > [hooks]
1051 1051 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1052 1052 > EOF
1053 1053
1054 1054 $ echo nnnn >> n
1055 1055
1056 1056 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1057 1057 ==== before-unshelving:
1058 1058 VISIBLE 5:703117a2acfb
1059 1059 ACTUAL 5:703117a2acfb
1060 1060 ====
1061 1061
1062 1062 $ hg unshelve --keep default
1063 1063 temporarily committing pending changes (restore with 'hg unshelve --abort')
1064 1064 rebasing shelved changes
1065 1065 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1066 1066 ==== preupdate:
1067 1067 VISIBLE 6:66b86db80ee4
1068 1068 ACTUAL 5:703117a2acfb
1069 1069 ====
1070 1070 ==== preupdate:
1071 1071 VISIBLE 8:cb2a4e59c2d5
1072 1072 ACTUAL 5:703117a2acfb
1073 1073 ====
1074 1074 ==== preupdate:
1075 1075 VISIBLE 6:66b86db80ee4
1076 1076 ACTUAL 5:703117a2acfb
1077 1077 ====
1078 1078
1079 1079 $ cat >> .hg/hgrc <<EOF
1080 1080 > [hooks]
1081 1081 > preupdate.visibility =
1082 1082 > EOF
1083 1083
1084 1084 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1085 1085 ==== after-unshelving:
1086 1086 VISIBLE 5:703117a2acfb
1087 1087 ACTUAL 5:703117a2acfb
1088 1088 ====
1089 1089
1090 1090 == test visibility to external update hook
1091 1091
1092 1092 $ hg update -q -C 5
1093 1093
1094 1094 $ cat >> .hg/hgrc <<EOF
1095 1095 > [hooks]
1096 1096 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1097 1097 > EOF
1098 1098
1099 1099 $ echo nnnn >> n
1100 1100
1101 1101 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1102 1102 ==== before-unshelving:
1103 1103 VISIBLE 5:703117a2acfb
1104 1104 ACTUAL 5:703117a2acfb
1105 1105 ====
1106 1106
1107 1107 $ hg unshelve --keep default
1108 1108 temporarily committing pending changes (restore with 'hg unshelve --abort')
1109 1109 rebasing shelved changes
1110 1110 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1111 1111 ==== update:
1112 1112 VISIBLE 6:66b86db80ee4
1113 1113 VISIBLE 7:fcbb97608399
1114 1114 ACTUAL 5:703117a2acfb
1115 1115 ====
1116 1116 ==== update:
1117 1117 VISIBLE 6:66b86db80ee4
1118 1118 ACTUAL 5:703117a2acfb
1119 1119 ====
1120 1120 ==== update:
1121 1121 VISIBLE 5:703117a2acfb
1122 1122 ACTUAL 5:703117a2acfb
1123 1123 ====
1124 1124
1125 1125 $ cat >> .hg/hgrc <<EOF
1126 1126 > [hooks]
1127 1127 > update.visibility =
1128 1128 > EOF
1129 1129
1130 1130 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1131 1131 ==== after-unshelving:
1132 1132 VISIBLE 5:703117a2acfb
1133 1133 ACTUAL 5:703117a2acfb
1134 1134 ====
1135 1135
1136 1136 $ cd ..
1137 1137
1138 test Abort unshelve always gets user out of the unshelved state
1138 test .orig files go where the user wants them to
1139 1139 ---------------------------------------------------------------
1140 1140 $ hg init salvage
1141 1141 $ cd salvage
1142 1142 $ echo 'content' > root
1143 1143 $ hg commit -A -m 'root' -q
1144 1144 $ echo '' > root
1145 1145 $ hg shelve -q
1146 1146 $ echo 'contADDent' > root
1147 $ hg unshelve -q
1147 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1148 1148 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1149 1149 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1150 1150 [1]
1151 $ ls .hg/origbackups
1152 root.orig
1153 $ rm -rf .hg/origbackups
1154
1155 test Abort unshelve always gets user out of the unshelved state
1156 ---------------------------------------------------------------
1151 1157 Wreak havoc on the unshelve process
1152 1158 $ rm .hg/unshelverebasestate
1153 1159 $ hg unshelve --abort
1154 1160 unshelve of 'default' aborted
1155 1161 abort: No such file or directory
1156 1162 [255]
1157 1163 Can the user leave the current state?
1158 1164 $ hg up -C .
1159 1165 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1160 1166
1161 1167 Try again but with a corrupted shelve state file
1162 1168 $ hg strip -r 2 -r 1 -q
1163 1169 $ hg up -r 0 -q
1164 1170 $ echo '' > root
1165 1171 $ hg shelve -q
1166 1172 $ echo 'contADDent' > root
1167 1173 $ hg unshelve -q
1168 1174 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1169 1175 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1170 1176 [1]
1171 1177 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1172 1178 $ mv ../corrupt-shelvedstate .hg/histedit-state
1173 1179 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1174 1180 rebase aborted
1175 1181 $ hg up -C .
1176 1182 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1177 1183
1178 1184 $ cd ..
1179 1185
1180 1186 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1181 1187 -----------------------------------------------------------------------
1182 1188
1183 1189 $ cat <<EOF >> $HGRCPATH
1184 1190 > [extensions]
1185 1191 > share =
1186 1192 > EOF
1187 1193
1188 1194 $ hg bookmarks -R repo
1189 1195 test 4:33f7f61e6c5e
1190 1196 $ hg share -B repo share
1191 1197 updating working directory
1192 1198 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1193 1199 $ cd share
1194 1200
1195 1201 $ hg bookmarks
1196 1202 test 4:33f7f61e6c5e
1197 1203 $ hg bookmarks foo
1198 1204 $ hg bookmarks
1199 1205 * foo 5:703117a2acfb
1200 1206 test 4:33f7f61e6c5e
1201 1207 $ echo x >> x
1202 1208 $ hg shelve
1203 1209 shelved as foo
1204 1210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1205 1211 $ hg bookmarks
1206 1212 * foo 5:703117a2acfb
1207 1213 test 4:33f7f61e6c5e
1208 1214
1209 1215 $ hg unshelve
1210 1216 unshelving change 'foo'
1211 1217 $ hg bookmarks
1212 1218 * foo 5:703117a2acfb
1213 1219 test 4:33f7f61e6c5e
1214 1220
1215 1221 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now