##// END OF EJS Templates
unshelve: add support for custom merge tools...
Siddharth Agarwal -
r27021:f2554154 default
parent child Browse files
Show More
@@ -1,839 +1,846
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 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.read(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 ('k', 'keep', None,
576 576 _('keep shelve after unshelving')),
577 ('t', 'tool', '', _('specify merge tool')),
577 578 ('', 'date', '',
578 579 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
579 580 _('hg unshelve [SHELVED]'))
580 581 def unshelve(ui, repo, *shelved, **opts):
581 582 """restore a shelved change to the working directory
582 583
583 584 This command accepts an optional name of a shelved change to
584 585 restore. If none is given, the most recent shelved change is used.
585 586
586 587 If a shelved change is applied successfully, the bundle that
587 588 contains the shelved changes is moved to a backup location
588 589 (.hg/shelve-backup).
589 590
590 591 Since you can restore a shelved change on top of an arbitrary
591 592 commit, it is possible that unshelving will result in a conflict
592 593 between your changes and the commits you are unshelving onto. If
593 594 this occurs, you must resolve the conflict, then use
594 595 ``--continue`` to complete the unshelve operation. (The bundle
595 596 will not be moved until you successfully complete the unshelve.)
596 597
597 598 (Alternatively, you can use ``--abort`` to abandon an unshelve
598 599 that causes a conflict. This reverts the unshelved changes, and
599 600 leaves the bundle in place.)
600 601
601 602 After a successful unshelve, the shelved changes are stored in a
602 603 backup directory. Only the N most recent backups are kept. N
603 604 defaults to 10 but can be overridden using the ``shelve.maxbackups``
604 605 configuration option.
605 606
606 607 .. container:: verbose
607 608
608 609 Timestamp in seconds is used to decide order of backups. More
609 610 than ``maxbackups`` backups are kept, if same timestamp
610 611 prevents from deciding exact order of them, for safety.
611 612 """
612 613 abortf = opts['abort']
613 614 continuef = opts['continue']
614 615 if not abortf and not continuef:
615 616 cmdutil.checkunfinished(repo)
616 617
617 618 if abortf or continuef:
618 619 if abortf and continuef:
619 620 raise error.Abort(_('cannot use both abort and continue'))
620 621 if shelved:
621 622 raise error.Abort(_('cannot combine abort/continue with '
622 623 'naming a shelved change'))
624 if abortf and opts.get('tool', False):
625 ui.warn(_('tool option will be ignored\n'))
623 626
624 627 try:
625 628 state = shelvedstate.load(repo)
626 629 except IOError as err:
627 630 if err.errno != errno.ENOENT:
628 631 raise
629 632 raise error.Abort(_('no unshelve operation underway'))
630 633
631 634 if abortf:
632 635 return unshelveabort(ui, repo, state, opts)
633 636 elif continuef:
634 637 return unshelvecontinue(ui, repo, state, opts)
635 638 elif len(shelved) > 1:
636 639 raise error.Abort(_('can only unshelve one change at a time'))
637 640 elif not shelved:
638 641 shelved = listshelves(repo)
639 642 if not shelved:
640 643 raise error.Abort(_('no shelved changes to apply!'))
641 644 basename = util.split(shelved[0][1])[1]
642 645 ui.status(_("unshelving change '%s'\n") % basename)
643 646 else:
644 647 basename = shelved[0]
645 648
646 649 if not shelvedfile(repo, basename, 'patch').exists():
647 650 raise error.Abort(_("shelved change '%s' not found") % basename)
648 651
649 652 oldquiet = ui.quiet
650 653 wlock = lock = tr = None
654 forcemerge = ui.backupconfig('ui', 'forcemerge')
651 655 try:
656 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'unshelve')
652 657 wlock = repo.wlock()
653 658 lock = repo.lock()
654 659
655 660 tr = repo.transaction('unshelve', report=lambda x: None)
656 661 oldtiprev = len(repo)
657 662
658 663 pctx = repo['.']
659 664 tmpwctx = pctx
660 665 # The goal is to have a commit structure like so:
661 666 # ...-> pctx -> tmpwctx -> shelvectx
662 667 # where tmpwctx is an optional commit with the user's pending changes
663 668 # and shelvectx is the unshelved changes. Then we merge it all down
664 669 # to the original pctx.
665 670
666 671 # Store pending changes in a commit
667 672 s = repo.status()
668 673 if s.modified or s.added or s.removed or s.deleted:
669 674 ui.status(_("temporarily committing pending changes "
670 675 "(restore with 'hg unshelve --abort')\n"))
671 676 def commitfunc(ui, repo, message, match, opts):
672 677 hasmq = util.safehasattr(repo, 'mq')
673 678 if hasmq:
674 679 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
675 680
676 681 backup = repo.ui.backupconfig('phases', 'new-commit')
677 682 try:
678 683 repo.ui.setconfig('phases', 'new-commit', phases.secret)
679 684 return repo.commit(message, 'shelve@localhost',
680 685 opts.get('date'), match)
681 686 finally:
682 687 repo.ui.restoreconfig(backup)
683 688 if hasmq:
684 689 repo.mq.checkapplied = saved
685 690
686 691 tempopts = {}
687 692 tempopts['message'] = "pending changes temporary commit"
688 693 tempopts['date'] = opts.get('date')
689 694 ui.quiet = True
690 695 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
691 696 tmpwctx = repo[node]
692 697
693 698 ui.quiet = True
694 699 shelvedfile(repo, basename, 'hg').applybundle()
695 700
696 701 ui.quiet = oldquiet
697 702
698 703 shelvectx = repo['tip']
699 704
700 705 # If the shelve is not immediately on top of the commit
701 706 # we'll be merging with, rebase it to be on top.
702 707 if tmpwctx.node() != shelvectx.parents()[0].node():
703 708 ui.status(_('rebasing shelved changes\n'))
704 709 try:
705 710 rebase.rebase(ui, repo, **{
706 711 'rev' : [shelvectx.rev()],
707 712 'dest' : str(tmpwctx.rev()),
708 713 'keep' : True,
714 'tool' : opts.get('tool', ''),
709 715 })
710 716 except error.InterventionRequired:
711 717 tr.close()
712 718
713 719 stripnodes = [repo.changelog.node(rev)
714 720 for rev in xrange(oldtiprev, len(repo))]
715 721 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
716 722
717 723 util.rename(repo.join('rebasestate'),
718 724 repo.join('unshelverebasestate'))
719 725 raise error.InterventionRequired(
720 726 _("unresolved conflicts (see 'hg resolve', then "
721 727 "'hg unshelve --continue')"))
722 728
723 729 # refresh ctx after rebase completes
724 730 shelvectx = repo['tip']
725 731
726 732 if not shelvectx in tmpwctx.children():
727 733 # rebase was a no-op, so it produced no child commit
728 734 shelvectx = tmpwctx
729 735
730 736 mergefiles(ui, repo, pctx, shelvectx)
731 737 shelvedstate.clear(repo)
732 738
733 739 # The transaction aborting will strip all the commits for us,
734 740 # but it doesn't update the inmemory structures, so addchangegroup
735 741 # hooks still fire and try to operate on the missing commits.
736 742 # Clean up manually to prevent this.
737 743 repo.unfiltered().changelog.strip(oldtiprev, tr)
738 744
739 745 unshelvecleanup(ui, repo, basename, opts)
740 746
741 747 _aborttransaction(repo)
742 748 finally:
743 749 ui.quiet = oldquiet
744 750 if tr:
745 751 tr.release()
746 752 lockmod.release(lock, wlock)
753 ui.restoreconfig(forcemerge)
747 754
748 755 @command('shelve',
749 756 [('A', 'addremove', None,
750 757 _('mark new/missing files as added/removed before shelving')),
751 758 ('', 'cleanup', None,
752 759 _('delete all shelved changes')),
753 760 ('', 'date', '',
754 761 _('shelve with the specified commit date'), _('DATE')),
755 762 ('d', 'delete', None,
756 763 _('delete the named shelved change(s)')),
757 764 ('e', 'edit', False,
758 765 _('invoke editor on commit messages')),
759 766 ('l', 'list', None,
760 767 _('list current shelves')),
761 768 ('m', 'message', '',
762 769 _('use text as shelve message'), _('TEXT')),
763 770 ('n', 'name', '',
764 771 _('use the given name for the shelved commit'), _('NAME')),
765 772 ('p', 'patch', None,
766 773 _('show patch')),
767 774 ('i', 'interactive', None,
768 775 _('interactive mode, only works while creating a shelve')),
769 776 ('', 'stat', None,
770 777 _('output diffstat-style summary of changes'))] + commands.walkopts,
771 778 _('hg shelve [OPTION]... [FILE]...'))
772 779 def shelvecmd(ui, repo, *pats, **opts):
773 780 '''save and set aside changes from the working directory
774 781
775 782 Shelving takes files that "hg status" reports as not clean, saves
776 783 the modifications to a bundle (a shelved change), and reverts the
777 784 files so that their state in the working directory becomes clean.
778 785
779 786 To restore these changes to the working directory, using "hg
780 787 unshelve"; this will work even if you switch to a different
781 788 commit.
782 789
783 790 When no files are specified, "hg shelve" saves all not-clean
784 791 files. If specific files or directories are named, only changes to
785 792 those files are shelved.
786 793
787 794 Each shelved change has a name that makes it easier to find later.
788 795 The name of a shelved change defaults to being based on the active
789 796 bookmark, or if there is no active bookmark, the current named
790 797 branch. To specify a different name, use ``--name``.
791 798
792 799 To see a list of existing shelved changes, use the ``--list``
793 800 option. For each shelved change, this will print its name, age,
794 801 and description; use ``--patch`` or ``--stat`` for more details.
795 802
796 803 To delete specific shelved changes, use ``--delete``. To delete
797 804 all shelved changes, use ``--cleanup``.
798 805 '''
799 806 cmdutil.checkunfinished(repo)
800 807
801 808 allowables = [
802 809 ('addremove', set(['create'])), # 'create' is pseudo action
803 810 ('cleanup', set(['cleanup'])),
804 811 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
805 812 ('delete', set(['delete'])),
806 813 ('edit', set(['create'])),
807 814 ('list', set(['list'])),
808 815 ('message', set(['create'])),
809 816 ('name', set(['create'])),
810 817 ('patch', set(['patch', 'list'])),
811 818 ('stat', set(['stat', 'list'])),
812 819 ]
813 820 def checkopt(opt):
814 821 if opts[opt]:
815 822 for i, allowable in allowables:
816 823 if opts[i] and opt not in allowable:
817 824 raise error.Abort(_("options '--%s' and '--%s' may not be "
818 825 "used together") % (opt, i))
819 826 return True
820 827 if checkopt('cleanup'):
821 828 if pats:
822 829 raise error.Abort(_("cannot specify names when using '--cleanup'"))
823 830 return cleanupcmd(ui, repo)
824 831 elif checkopt('delete'):
825 832 return deletecmd(ui, repo, pats)
826 833 elif checkopt('list'):
827 834 return listcmd(ui, repo, pats, opts)
828 835 elif checkopt('patch'):
829 836 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
830 837 elif checkopt('stat'):
831 838 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
832 839 else:
833 840 return createcmd(ui, repo, pats, opts)
834 841
835 842 def extsetup(ui):
836 843 cmdutil.unfinishedstates.append(
837 844 [shelvedstate._filename, False, False,
838 845 _('unshelve already in progress'),
839 846 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
@@ -1,1221 +1,1245
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 $ hg unshelve --tool :merge-other --keep
473 unshelving change 'default'
474 temporarily committing pending changes (restore with 'hg unshelve --abort')
475 rebasing shelved changes
476 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
477 merging a/a
478 $ hg parents -q
479 4:33f7f61e6c5e
480 $ hg shelve -l
481 default (*)* changes to 'second' (glob)
482 $ hg status
483 M a/a
484 A foo/foo
485 $ cat a/a
486 a
487 c
488 a
489 $ cat > a/a << EOF
490 > a
491 > c
492 > x
493 > EOF
494
472 495 $ HGMERGE=true hg unshelve
473 496 unshelving change 'default'
474 497 temporarily committing pending changes (restore with 'hg unshelve --abort')
475 498 rebasing shelved changes
476 499 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
477 500 merging a/a
478 501 note: rebase of 6:c5e6910e7601 created no changes to commit
479 502 $ hg parents -q
480 503 4:33f7f61e6c5e
481 504 $ hg shelve -l
482 505 $ hg status
483 506 A foo/foo
484 507 $ cat a/a
485 508 a
486 509 c
487 510 x
488 511
489 512 test keep and cleanup
490 513
491 514 $ hg shelve
492 515 shelved as default
493 516 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
494 517 $ hg shelve --list
495 518 default (*) changes to 'create conflict' (glob)
496 519 $ hg unshelve -k
497 520 unshelving change 'default'
498 521 $ hg shelve --list
499 522 default (*) changes to 'create conflict' (glob)
500 523 $ hg shelve --cleanup
501 524 $ hg shelve --list
502 525
503 526 $ hg shelve --cleanup --delete
504 527 abort: options '--cleanup' and '--delete' may not be used together
505 528 [255]
506 529 $ hg shelve --cleanup --patch
507 530 abort: options '--cleanup' and '--patch' may not be used together
508 531 [255]
509 532 $ hg shelve --cleanup --message MESSAGE
510 533 abort: options '--cleanup' and '--message' may not be used together
511 534 [255]
512 535
513 536 test bookmarks
514 537
515 538 $ hg bookmark test
516 539 $ hg bookmark
517 540 * test 4:33f7f61e6c5e
518 541 $ hg shelve
519 542 shelved as test
520 543 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
521 544 $ hg bookmark
522 545 * test 4:33f7f61e6c5e
523 546 $ hg unshelve
524 547 unshelving change 'test'
525 548 $ hg bookmark
526 549 * test 4:33f7f61e6c5e
527 550
528 551 shelve should still work even if mq is disabled
529 552
530 553 $ hg --config extensions.mq=! shelve
531 554 shelved as test
532 555 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
533 556 $ hg --config extensions.mq=! shelve --list
534 557 test (*) changes to 'create conflict' (glob)
535 558 $ hg bookmark
536 559 * test 4:33f7f61e6c5e
537 560 $ hg --config extensions.mq=! unshelve
538 561 unshelving change 'test'
539 562 $ hg bookmark
540 563 * test 4:33f7f61e6c5e
541 564
542 565 shelve should leave dirstate clean (issue4055)
543 566
544 567 $ cd ..
545 568 $ hg init shelverebase
546 569 $ cd shelverebase
547 570 $ printf 'x\ny\n' > x
548 571 $ echo z > z
549 572 $ hg commit -Aqm xy
550 573 $ echo z >> x
551 574 $ hg commit -Aqm z
552 575 $ hg up 0
553 576 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 577 $ printf 'a\nx\ny\nz\n' > x
555 578 $ hg commit -Aqm xyz
556 579 $ echo c >> z
557 580 $ hg shelve
558 581 shelved as default
559 582 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 583 $ hg rebase -d 1 --config extensions.rebase=
561 584 rebasing 2:323bfa07f744 "xyz" (tip)
562 585 merging x
563 586 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
564 587 $ hg unshelve
565 588 unshelving change 'default'
566 589 rebasing shelved changes
567 590 rebasing 4:b8fefe789ed0 "changes to 'xyz'" (tip)
568 591 $ hg status
569 592 M z
570 593
571 594 $ cd ..
572 595
573 596 shelve should only unshelve pending changes (issue4068)
574 597
575 598 $ hg init onlypendingchanges
576 599 $ cd onlypendingchanges
577 600 $ touch a
578 601 $ hg ci -Aqm a
579 602 $ touch b
580 603 $ hg ci -Aqm b
581 604 $ hg up -q 0
582 605 $ touch c
583 606 $ hg ci -Aqm c
584 607
585 608 $ touch d
586 609 $ hg add d
587 610 $ hg shelve
588 611 shelved as default
589 612 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
590 613 $ hg up -q 1
591 614 $ hg unshelve
592 615 unshelving change 'default'
593 616 rebasing shelved changes
594 617 rebasing 3:0cae6656c016 "changes to 'c'" (tip)
595 618 $ hg status
596 619 A d
597 620
598 621 unshelve should work on an ancestor of the original commit
599 622
600 623 $ hg shelve
601 624 shelved as default
602 625 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
603 626 $ hg up 0
604 627 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
605 628 $ hg unshelve
606 629 unshelving change 'default'
607 630 rebasing shelved changes
608 631 rebasing 3:be58f65f55fb "changes to 'b'" (tip)
609 632 $ hg status
610 633 A d
611 634
612 635 test bug 4073 we need to enable obsolete markers for it
613 636
614 637 $ cat >> $HGRCPATH << EOF
615 638 > [experimental]
616 639 > evolution=createmarkers
617 640 > EOF
618 641 $ hg shelve
619 642 shelved as default
620 643 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 644 $ hg debugobsolete `hg --debug id -i -r 1`
622 645 $ hg unshelve
623 646 unshelving change 'default'
624 647
625 648 unshelve should leave unknown files alone (issue4113)
626 649
627 650 $ echo e > e
628 651 $ hg shelve
629 652 shelved as default
630 653 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
631 654 $ hg status
632 655 ? e
633 656 $ hg unshelve
634 657 unshelving change 'default'
635 658 $ hg status
636 659 A d
637 660 ? e
638 661 $ cat e
639 662 e
640 663
641 664 unshelve should keep a copy of unknown files
642 665
643 666 $ hg add e
644 667 $ hg shelve
645 668 shelved as default
646 669 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
647 670 $ echo z > e
648 671 $ hg unshelve
649 672 unshelving change 'default'
650 673 $ cat e
651 674 e
652 675 $ cat e.orig
653 676 z
654 677
655 678
656 679 unshelve and conflicts with tracked and untracked files
657 680
658 681 preparing:
659 682
660 683 $ rm *.orig
661 684 $ hg ci -qm 'commit stuff'
662 685 $ hg phase -p null:
663 686
664 687 no other changes - no merge:
665 688
666 689 $ echo f > f
667 690 $ hg add f
668 691 $ hg shelve
669 692 shelved as default
670 693 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
671 694 $ echo g > f
672 695 $ hg unshelve
673 696 unshelving change 'default'
674 697 $ hg st
675 698 A f
676 699 ? f.orig
677 700 $ cat f
678 701 f
679 702 $ cat f.orig
680 703 g
681 704
682 705 other uncommitted changes - merge:
683 706
684 707 $ hg st
685 708 A f
686 709 ? f.orig
687 710 $ hg shelve
688 711 shelved as default
689 712 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
690 713 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
691 714 o 4 changes to 'commit stuff' shelve@localhost
692 715 |
693 716 $ hg log -G --template '{rev} {desc|firstline} {author}'
694 717 @ 3 commit stuff test
695 718 |
696 719 | o 2 c test
697 720 |/
698 721 o 0 a test
699 722
700 723 $ mv f.orig f
701 724 $ echo 1 > a
702 725 $ hg unshelve --date '1073741824 0'
703 726 unshelving change 'default'
704 727 temporarily committing pending changes (restore with 'hg unshelve --abort')
705 728 rebasing shelved changes
706 729 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
707 730 merging f
708 731 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
709 732 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
710 733 [1]
711 734 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
712 735 @ 5 changes to 'commit stuff' shelve@localhost 1970-01-01 00:00 +0000
713 736 |
714 737 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
715 738 |/
716 739 o 3 commit stuff test 1970-01-01 00:00 +0000
717 740 |
718 741 | o 2 c test 1970-01-01 00:00 +0000
719 742 |/
720 743 o 0 a test 1970-01-01 00:00 +0000
721 744
722 745 $ hg st
723 746 M f
724 747 ? f.orig
725 748 $ cat f
726 749 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
727 750 g
728 751 =======
729 752 f
730 753 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
731 754 $ cat f.orig
732 755 g
733 $ hg unshelve --abort
756 $ hg unshelve --abort -t false
757 tool option will be ignored
734 758 rebase aborted
735 759 unshelve of 'default' aborted
736 760 $ hg st
737 761 M a
738 762 ? f.orig
739 763 $ cat f.orig
740 764 g
741 765 $ hg unshelve
742 766 unshelving change 'default'
743 767 temporarily committing pending changes (restore with 'hg unshelve --abort')
744 768 rebasing shelved changes
745 769 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
746 770 $ hg st
747 771 M a
748 772 A f
749 773 ? f.orig
750 774
751 775 other committed changes - merge:
752 776
753 777 $ hg shelve f
754 778 shelved as default
755 779 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
756 780 $ hg ci a -m 'intermediate other change'
757 781 $ mv f.orig f
758 782 $ hg unshelve
759 783 unshelving change 'default'
760 784 rebasing shelved changes
761 785 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
762 786 merging f
763 787 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
764 788 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
765 789 [1]
766 790 $ hg st
767 791 M f
768 792 ? f.orig
769 793 $ cat f
770 794 <<<<<<< dest: * - test: intermediate other change (glob)
771 795 g
772 796 =======
773 797 f
774 798 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
775 799 $ cat f.orig
776 800 g
777 801 $ hg unshelve --abort
778 802 rebase aborted
779 803 unshelve of 'default' aborted
780 804 $ hg st
781 805 ? f.orig
782 806 $ cat f.orig
783 807 g
784 808 $ hg shelve --delete default
785 809
786 810 Recreate some conflict again
787 811
788 812 $ cd ../repo
789 813 $ hg up -C -r 3
790 814 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
791 815 (leaving bookmark test)
792 816 $ echo y >> a/a
793 817 $ hg shelve
794 818 shelved as default
795 819 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
796 820 $ hg up test
797 821 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
798 822 (activating bookmark test)
799 823 $ hg bookmark
800 824 * test 4:33f7f61e6c5e
801 825 $ hg unshelve
802 826 unshelving change 'default'
803 827 rebasing shelved changes
804 828 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
805 829 merging a/a
806 830 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
807 831 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
808 832 [1]
809 833 $ hg bookmark
810 834 test 4:33f7f61e6c5e
811 835
812 836 Test that resolving all conflicts in one direction (so that the rebase
813 837 is a no-op), works (issue4398)
814 838
815 839 $ hg revert -a -r .
816 840 reverting a/a (glob)
817 841 $ hg resolve -m a/a
818 842 (no more unresolved files)
819 843 $ hg unshelve -c
820 844 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
821 845 note: rebase of 5:4b555fdb4e96 created no changes to commit
822 846 unshelve of 'default' complete
823 847 $ hg bookmark
824 848 * test 4:33f7f61e6c5e
825 849 $ hg diff
826 850 $ hg status
827 851 ? a/a.orig
828 852 ? foo/foo
829 853 $ hg summary
830 854 parent: 4:33f7f61e6c5e tip
831 855 create conflict
832 856 branch: default
833 857 bookmarks: *test
834 858 commit: 2 unknown (clean)
835 859 update: (current)
836 860 phases: 5 draft
837 861
838 862 $ hg shelve --delete --stat
839 863 abort: options '--delete' and '--stat' may not be used together
840 864 [255]
841 865 $ hg shelve --delete --name NAME
842 866 abort: options '--delete' and '--name' may not be used together
843 867 [255]
844 868
845 869 Test interactive shelve
846 870 $ cat <<EOF >> $HGRCPATH
847 871 > [ui]
848 872 > interactive = true
849 873 > EOF
850 874 $ echo 'a' >> a/b
851 875 $ cat a/a >> a/b
852 876 $ echo 'x' >> a/b
853 877 $ mv a/b a/a
854 878 $ echo 'a' >> foo/foo
855 879 $ hg st
856 880 M a/a
857 881 ? a/a.orig
858 882 ? foo/foo
859 883 $ cat a/a
860 884 a
861 885 a
862 886 c
863 887 x
864 888 x
865 889 $ cat foo/foo
866 890 foo
867 891 a
868 892 $ hg shelve --interactive --config ui.interactive=false
869 893 abort: running non-interactively
870 894 [255]
871 895 $ hg shelve --interactive << EOF
872 896 > y
873 897 > y
874 898 > n
875 899 > EOF
876 900 diff --git a/a/a b/a/a
877 901 2 hunks, 2 lines changed
878 902 examine changes to 'a/a'? [Ynesfdaq?] y
879 903
880 904 @@ -1,3 +1,4 @@
881 905 +a
882 906 a
883 907 c
884 908 x
885 909 record change 1/2 to 'a/a'? [Ynesfdaq?] y
886 910
887 911 @@ -1,3 +2,4 @@
888 912 a
889 913 c
890 914 x
891 915 +x
892 916 record change 2/2 to 'a/a'? [Ynesfdaq?] n
893 917
894 918 shelved as test
895 919 merging a/a
896 920 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
897 921 $ cat a/a
898 922 a
899 923 c
900 924 x
901 925 x
902 926 $ cat foo/foo
903 927 foo
904 928 a
905 929 $ hg st
906 930 M a/a
907 931 ? foo/foo
908 932 $ hg bookmark
909 933 * test 4:33f7f61e6c5e
910 934 $ hg unshelve
911 935 unshelving change 'test'
912 936 temporarily committing pending changes (restore with 'hg unshelve --abort')
913 937 rebasing shelved changes
914 938 rebasing 6:65b5d1c34c34 "changes to 'create conflict'" (tip)
915 939 merging a/a
916 940 $ hg bookmark
917 941 * test 4:33f7f61e6c5e
918 942 $ cat a/a
919 943 a
920 944 a
921 945 c
922 946 x
923 947 x
924 948
925 949 shelve --patch and shelve --stat should work with a single valid shelfname
926 950
927 951 $ hg up --clean .
928 952 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
929 953 (leaving bookmark test)
930 954 $ hg shelve --list
931 955 $ echo 'patch a' > shelf-patch-a
932 956 $ hg add shelf-patch-a
933 957 $ hg shelve
934 958 shelved as default
935 959 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
936 960 $ echo 'patch b' > shelf-patch-b
937 961 $ hg add shelf-patch-b
938 962 $ hg shelve
939 963 shelved as default-01
940 964 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
941 965 $ hg shelve --patch default default-01
942 966 abort: --patch expects a single shelf
943 967 [255]
944 968 $ hg shelve --stat default default-01
945 969 abort: --stat expects a single shelf
946 970 [255]
947 971 $ hg shelve --patch default
948 972 default (* ago) changes to 'create conflict' (glob)
949 973
950 974 diff --git a/shelf-patch-a b/shelf-patch-a
951 975 new file mode 100644
952 976 --- /dev/null
953 977 +++ b/shelf-patch-a
954 978 @@ -0,0 +1,1 @@
955 979 +patch a
956 980 $ hg shelve --stat default
957 981 default (* ago) changes to 'create conflict' (glob)
958 982 shelf-patch-a | 1 +
959 983 1 files changed, 1 insertions(+), 0 deletions(-)
960 984 $ hg shelve --patch nonexistentshelf
961 985 abort: cannot find shelf nonexistentshelf
962 986 [255]
963 987 $ hg shelve --stat nonexistentshelf
964 988 abort: cannot find shelf nonexistentshelf
965 989 [255]
966 990
967 991 $ cd ..
968 992
969 993 Shelve from general delta repo uses bundle2 on disk
970 994 --------------------------------------------------
971 995
972 996 no general delta
973 997
974 998 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
975 999 requesting all changes
976 1000 adding changesets
977 1001 adding manifests
978 1002 adding file changes
979 1003 added 5 changesets with 8 changes to 6 files
980 1004 updating to branch default
981 1005 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
982 1006 $ cd bundle1
983 1007 $ echo babar > jungle
984 1008 $ hg add jungle
985 1009 $ hg shelve
986 1010 shelved as default
987 1011 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
988 1012 $ hg debugbundle .hg/shelved/*.hg
989 1013 7e30d8ac6f23cfc84330fd7e698730374615d21a
990 1014 $ cd ..
991 1015
992 1016 with general delta
993 1017
994 1018 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
995 1019 requesting all changes
996 1020 adding changesets
997 1021 adding manifests
998 1022 adding file changes
999 1023 added 5 changesets with 8 changes to 6 files
1000 1024 updating to branch default
1001 1025 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1002 1026 $ cd bundle2
1003 1027 $ echo babar > jungle
1004 1028 $ hg add jungle
1005 1029 $ hg shelve
1006 1030 shelved as default
1007 1031 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1008 1032 $ hg debugbundle .hg/shelved/*.hg
1009 1033 Stream params: {'Compression': 'BZ'}
1010 1034 changegroup -- "{'version': '02'}"
1011 1035 7e30d8ac6f23cfc84330fd7e698730374615d21a
1012 1036 $ cd ..
1013 1037
1014 1038 Test visibility of in-memory changes inside transaction to external hook
1015 1039 ------------------------------------------------------------------------
1016 1040
1017 1041 $ cd repo
1018 1042
1019 1043 $ echo xxxx >> x
1020 1044 $ hg commit -m "#5: changes to invoke rebase"
1021 1045
1022 1046 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1023 1047 > echo "==== \$1:"
1024 1048 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1025 1049 > # test that pending changes are hidden
1026 1050 > unset HG_PENDING
1027 1051 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1028 1052 > echo "===="
1029 1053 > EOF
1030 1054
1031 1055 $ cat >> .hg/hgrc <<EOF
1032 1056 > [defaults]
1033 1057 > # to fix hash id of temporary revisions
1034 1058 > unshelve = --date '0 0'
1035 1059 > EOF
1036 1060
1037 1061 "hg unshelve" at REV5 implies steps below:
1038 1062
1039 1063 (1) commit changes in the working directory (REV6)
1040 1064 (2) unbundle shelved revision (REV7)
1041 1065 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1042 1066 (4) rebase: commit merged revision (REV8)
1043 1067 (5) rebase: update to REV6 (REV8 => REV6)
1044 1068 (6) update to REV5 (REV6 => REV5)
1045 1069 (7) abort transaction
1046 1070
1047 1071 == test visibility to external preupdate hook
1048 1072
1049 1073 $ cat >> .hg/hgrc <<EOF
1050 1074 > [hooks]
1051 1075 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1052 1076 > EOF
1053 1077
1054 1078 $ echo nnnn >> n
1055 1079
1056 1080 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1057 1081 ==== before-unshelving:
1058 1082 VISIBLE 5:703117a2acfb
1059 1083 ACTUAL 5:703117a2acfb
1060 1084 ====
1061 1085
1062 1086 $ hg unshelve --keep default
1063 1087 temporarily committing pending changes (restore with 'hg unshelve --abort')
1064 1088 rebasing shelved changes
1065 1089 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1066 1090 ==== preupdate:
1067 1091 VISIBLE 6:66b86db80ee4
1068 1092 ACTUAL 5:703117a2acfb
1069 1093 ====
1070 1094 ==== preupdate:
1071 1095 VISIBLE 8:cb2a4e59c2d5
1072 1096 ACTUAL 5:703117a2acfb
1073 1097 ====
1074 1098 ==== preupdate:
1075 1099 VISIBLE 6:66b86db80ee4
1076 1100 ACTUAL 5:703117a2acfb
1077 1101 ====
1078 1102
1079 1103 $ cat >> .hg/hgrc <<EOF
1080 1104 > [hooks]
1081 1105 > preupdate.visibility =
1082 1106 > EOF
1083 1107
1084 1108 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1085 1109 ==== after-unshelving:
1086 1110 VISIBLE 5:703117a2acfb
1087 1111 ACTUAL 5:703117a2acfb
1088 1112 ====
1089 1113
1090 1114 == test visibility to external update hook
1091 1115
1092 1116 $ hg update -q -C 5
1093 1117
1094 1118 $ cat >> .hg/hgrc <<EOF
1095 1119 > [hooks]
1096 1120 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1097 1121 > EOF
1098 1122
1099 1123 $ echo nnnn >> n
1100 1124
1101 1125 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1102 1126 ==== before-unshelving:
1103 1127 VISIBLE 5:703117a2acfb
1104 1128 ACTUAL 5:703117a2acfb
1105 1129 ====
1106 1130
1107 1131 $ hg unshelve --keep default
1108 1132 temporarily committing pending changes (restore with 'hg unshelve --abort')
1109 1133 rebasing shelved changes
1110 1134 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1111 1135 ==== update:
1112 1136 VISIBLE 6:66b86db80ee4
1113 1137 VISIBLE 7:fcbb97608399
1114 1138 ACTUAL 5:703117a2acfb
1115 1139 ====
1116 1140 ==== update:
1117 1141 VISIBLE 6:66b86db80ee4
1118 1142 ACTUAL 5:703117a2acfb
1119 1143 ====
1120 1144 ==== update:
1121 1145 VISIBLE 5:703117a2acfb
1122 1146 ACTUAL 5:703117a2acfb
1123 1147 ====
1124 1148
1125 1149 $ cat >> .hg/hgrc <<EOF
1126 1150 > [hooks]
1127 1151 > update.visibility =
1128 1152 > EOF
1129 1153
1130 1154 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1131 1155 ==== after-unshelving:
1132 1156 VISIBLE 5:703117a2acfb
1133 1157 ACTUAL 5:703117a2acfb
1134 1158 ====
1135 1159
1136 1160 $ cd ..
1137 1161
1138 1162 test .orig files go where the user wants them to
1139 1163 ---------------------------------------------------------------
1140 1164 $ hg init salvage
1141 1165 $ cd salvage
1142 1166 $ echo 'content' > root
1143 1167 $ hg commit -A -m 'root' -q
1144 1168 $ echo '' > root
1145 1169 $ hg shelve -q
1146 1170 $ echo 'contADDent' > root
1147 1171 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1148 1172 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1149 1173 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1150 1174 [1]
1151 1175 $ ls .hg/origbackups
1152 1176 root.orig
1153 1177 $ rm -rf .hg/origbackups
1154 1178
1155 1179 test Abort unshelve always gets user out of the unshelved state
1156 1180 ---------------------------------------------------------------
1157 1181 Wreak havoc on the unshelve process
1158 1182 $ rm .hg/unshelverebasestate
1159 1183 $ hg unshelve --abort
1160 1184 unshelve of 'default' aborted
1161 1185 abort: (No such file or directory|The system cannot find the file specified) (re)
1162 1186 [255]
1163 1187 Can the user leave the current state?
1164 1188 $ hg up -C .
1165 1189 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1166 1190
1167 1191 Try again but with a corrupted shelve state file
1168 1192 $ hg strip -r 2 -r 1 -q
1169 1193 $ hg up -r 0 -q
1170 1194 $ echo '' > root
1171 1195 $ hg shelve -q
1172 1196 $ echo 'contADDent' > root
1173 1197 $ hg unshelve -q
1174 1198 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1175 1199 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1176 1200 [1]
1177 1201 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1178 1202 $ mv ../corrupt-shelvedstate .hg/histedit-state
1179 1203 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1180 1204 rebase aborted
1181 1205 $ hg up -C .
1182 1206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1183 1207
1184 1208 $ cd ..
1185 1209
1186 1210 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1187 1211 -----------------------------------------------------------------------
1188 1212
1189 1213 $ cat <<EOF >> $HGRCPATH
1190 1214 > [extensions]
1191 1215 > share =
1192 1216 > EOF
1193 1217
1194 1218 $ hg bookmarks -R repo
1195 1219 test 4:33f7f61e6c5e
1196 1220 $ hg share -B repo share
1197 1221 updating working directory
1198 1222 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1199 1223 $ cd share
1200 1224
1201 1225 $ hg bookmarks
1202 1226 test 4:33f7f61e6c5e
1203 1227 $ hg bookmarks foo
1204 1228 $ hg bookmarks
1205 1229 * foo 5:703117a2acfb
1206 1230 test 4:33f7f61e6c5e
1207 1231 $ echo x >> x
1208 1232 $ hg shelve
1209 1233 shelved as foo
1210 1234 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1211 1235 $ hg bookmarks
1212 1236 * foo 5:703117a2acfb
1213 1237 test 4:33f7f61e6c5e
1214 1238
1215 1239 $ hg unshelve
1216 1240 unshelving change 'foo'
1217 1241 $ hg bookmarks
1218 1242 * foo 5:703117a2acfb
1219 1243 test 4:33f7f61e6c5e
1220 1244
1221 1245 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now