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