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