##// END OF EJS Templates
unshelve: forget unknown files after a partial unshelve...
Navaneeth Suresh -
r42961:d684449e default
parent child Browse files
Show More
@@ -1,1014 +1,1014 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 from __future__ import absolute_import
23 from __future__ import absolute_import
24
24
25 import collections
25 import collections
26 import errno
26 import errno
27 import itertools
27 import itertools
28 import stat
28 import stat
29
29
30 from .i18n import _
30 from .i18n import _
31 from . import (
31 from . import (
32 bookmarks,
32 bookmarks,
33 bundle2,
33 bundle2,
34 bundlerepo,
34 bundlerepo,
35 changegroup,
35 changegroup,
36 cmdutil,
36 cmdutil,
37 discovery,
37 discovery,
38 error,
38 error,
39 exchange,
39 exchange,
40 hg,
40 hg,
41 lock as lockmod,
41 lock as lockmod,
42 mdiff,
42 mdiff,
43 merge,
43 merge,
44 node as nodemod,
44 node as nodemod,
45 patch,
45 patch,
46 phases,
46 phases,
47 pycompat,
47 pycompat,
48 repair,
48 repair,
49 scmutil,
49 scmutil,
50 templatefilters,
50 templatefilters,
51 util,
51 util,
52 vfs as vfsmod,
52 vfs as vfsmod,
53 )
53 )
54 from .utils import (
54 from .utils import (
55 dateutil,
55 dateutil,
56 stringutil,
56 stringutil,
57 )
57 )
58
58
59 backupdir = 'shelve-backup'
59 backupdir = 'shelve-backup'
60 shelvedir = 'shelved'
60 shelvedir = 'shelved'
61 shelvefileextensions = ['hg', 'patch', 'shelve']
61 shelvefileextensions = ['hg', 'patch', 'shelve']
62 # universal extension is present in all types of shelves
62 # universal extension is present in all types of shelves
63 patchextension = 'patch'
63 patchextension = 'patch'
64
64
65 # we never need the user, so we use a
65 # we never need the user, so we use a
66 # generic user for all shelve operations
66 # generic user for all shelve operations
67 shelveuser = 'shelve@localhost'
67 shelveuser = 'shelve@localhost'
68
68
69 class shelvedfile(object):
69 class shelvedfile(object):
70 """Helper for the file storing a single shelve
70 """Helper for the file storing a single shelve
71
71
72 Handles common functions on shelve files (.hg/.patch) using
72 Handles common functions on shelve files (.hg/.patch) using
73 the vfs layer"""
73 the vfs layer"""
74 def __init__(self, repo, name, filetype=None):
74 def __init__(self, repo, name, filetype=None):
75 self.repo = repo
75 self.repo = repo
76 self.name = name
76 self.name = name
77 self.vfs = vfsmod.vfs(repo.vfs.join(shelvedir))
77 self.vfs = vfsmod.vfs(repo.vfs.join(shelvedir))
78 self.backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
78 self.backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
79 self.ui = self.repo.ui
79 self.ui = self.repo.ui
80 if filetype:
80 if filetype:
81 self.fname = name + '.' + filetype
81 self.fname = name + '.' + filetype
82 else:
82 else:
83 self.fname = name
83 self.fname = name
84
84
85 def exists(self):
85 def exists(self):
86 return self.vfs.exists(self.fname)
86 return self.vfs.exists(self.fname)
87
87
88 def filename(self):
88 def filename(self):
89 return self.vfs.join(self.fname)
89 return self.vfs.join(self.fname)
90
90
91 def backupfilename(self):
91 def backupfilename(self):
92 def gennames(base):
92 def gennames(base):
93 yield base
93 yield base
94 base, ext = base.rsplit('.', 1)
94 base, ext = base.rsplit('.', 1)
95 for i in itertools.count(1):
95 for i in itertools.count(1):
96 yield '%s-%d.%s' % (base, i, ext)
96 yield '%s-%d.%s' % (base, i, ext)
97
97
98 name = self.backupvfs.join(self.fname)
98 name = self.backupvfs.join(self.fname)
99 for n in gennames(name):
99 for n in gennames(name):
100 if not self.backupvfs.exists(n):
100 if not self.backupvfs.exists(n):
101 return n
101 return n
102
102
103 def movetobackup(self):
103 def movetobackup(self):
104 if not self.backupvfs.isdir():
104 if not self.backupvfs.isdir():
105 self.backupvfs.makedir()
105 self.backupvfs.makedir()
106 util.rename(self.filename(), self.backupfilename())
106 util.rename(self.filename(), self.backupfilename())
107
107
108 def stat(self):
108 def stat(self):
109 return self.vfs.stat(self.fname)
109 return self.vfs.stat(self.fname)
110
110
111 def opener(self, mode='rb'):
111 def opener(self, mode='rb'):
112 try:
112 try:
113 return self.vfs(self.fname, mode)
113 return self.vfs(self.fname, mode)
114 except IOError as err:
114 except IOError as err:
115 if err.errno != errno.ENOENT:
115 if err.errno != errno.ENOENT:
116 raise
116 raise
117 raise error.Abort(_("shelved change '%s' not found") % self.name)
117 raise error.Abort(_("shelved change '%s' not found") % self.name)
118
118
119 def applybundle(self, tr):
119 def applybundle(self, tr):
120 fp = self.opener()
120 fp = self.opener()
121 try:
121 try:
122 targetphase = phases.internal
122 targetphase = phases.internal
123 if not phases.supportinternal(self.repo):
123 if not phases.supportinternal(self.repo):
124 targetphase = phases.secret
124 targetphase = phases.secret
125 gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
125 gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
126 pretip = self.repo['tip']
126 pretip = self.repo['tip']
127 bundle2.applybundle(self.repo, gen, tr,
127 bundle2.applybundle(self.repo, gen, tr,
128 source='unshelve',
128 source='unshelve',
129 url='bundle:' + self.vfs.join(self.fname),
129 url='bundle:' + self.vfs.join(self.fname),
130 targetphase=targetphase)
130 targetphase=targetphase)
131 shelvectx = self.repo['tip']
131 shelvectx = self.repo['tip']
132 if pretip == shelvectx:
132 if pretip == shelvectx:
133 shelverev = tr.changes['revduplicates'][-1]
133 shelverev = tr.changes['revduplicates'][-1]
134 shelvectx = self.repo[shelverev]
134 shelvectx = self.repo[shelverev]
135 return shelvectx
135 return shelvectx
136 finally:
136 finally:
137 fp.close()
137 fp.close()
138
138
139 def bundlerepo(self):
139 def bundlerepo(self):
140 path = self.vfs.join(self.fname)
140 path = self.vfs.join(self.fname)
141 return bundlerepo.instance(self.repo.baseui,
141 return bundlerepo.instance(self.repo.baseui,
142 'bundle://%s+%s' % (self.repo.root, path))
142 'bundle://%s+%s' % (self.repo.root, path))
143
143
144 def writebundle(self, bases, node):
144 def writebundle(self, bases, node):
145 cgversion = changegroup.safeversion(self.repo)
145 cgversion = changegroup.safeversion(self.repo)
146 if cgversion == '01':
146 if cgversion == '01':
147 btype = 'HG10BZ'
147 btype = 'HG10BZ'
148 compression = None
148 compression = None
149 else:
149 else:
150 btype = 'HG20'
150 btype = 'HG20'
151 compression = 'BZ'
151 compression = 'BZ'
152
152
153 repo = self.repo.unfiltered()
153 repo = self.repo.unfiltered()
154
154
155 outgoing = discovery.outgoing(repo, missingroots=bases,
155 outgoing = discovery.outgoing(repo, missingroots=bases,
156 missingheads=[node])
156 missingheads=[node])
157 cg = changegroup.makechangegroup(repo, outgoing, cgversion, 'shelve')
157 cg = changegroup.makechangegroup(repo, outgoing, cgversion, 'shelve')
158
158
159 bundle2.writebundle(self.ui, cg, self.fname, btype, self.vfs,
159 bundle2.writebundle(self.ui, cg, self.fname, btype, self.vfs,
160 compression=compression)
160 compression=compression)
161
161
162 def writeinfo(self, info):
162 def writeinfo(self, info):
163 scmutil.simplekeyvaluefile(self.vfs, self.fname).write(info)
163 scmutil.simplekeyvaluefile(self.vfs, self.fname).write(info)
164
164
165 def readinfo(self):
165 def readinfo(self):
166 return scmutil.simplekeyvaluefile(self.vfs, self.fname).read()
166 return scmutil.simplekeyvaluefile(self.vfs, self.fname).read()
167
167
168 class shelvedstate(object):
168 class shelvedstate(object):
169 """Handle persistence during unshelving operations.
169 """Handle persistence during unshelving operations.
170
170
171 Handles saving and restoring a shelved state. Ensures that different
171 Handles saving and restoring a shelved state. Ensures that different
172 versions of a shelved state are possible and handles them appropriately.
172 versions of a shelved state are possible and handles them appropriately.
173 """
173 """
174 _version = 2
174 _version = 2
175 _filename = 'shelvedstate'
175 _filename = 'shelvedstate'
176 _keep = 'keep'
176 _keep = 'keep'
177 _nokeep = 'nokeep'
177 _nokeep = 'nokeep'
178 # colon is essential to differentiate from a real bookmark name
178 # colon is essential to differentiate from a real bookmark name
179 _noactivebook = ':no-active-bookmark'
179 _noactivebook = ':no-active-bookmark'
180 _interactive = 'interactive'
180 _interactive = 'interactive'
181
181
182 @classmethod
182 @classmethod
183 def _verifyandtransform(cls, d):
183 def _verifyandtransform(cls, d):
184 """Some basic shelvestate syntactic verification and transformation"""
184 """Some basic shelvestate syntactic verification and transformation"""
185 try:
185 try:
186 d['originalwctx'] = nodemod.bin(d['originalwctx'])
186 d['originalwctx'] = nodemod.bin(d['originalwctx'])
187 d['pendingctx'] = nodemod.bin(d['pendingctx'])
187 d['pendingctx'] = nodemod.bin(d['pendingctx'])
188 d['parents'] = [nodemod.bin(h)
188 d['parents'] = [nodemod.bin(h)
189 for h in d['parents'].split(' ')]
189 for h in d['parents'].split(' ')]
190 d['nodestoremove'] = [nodemod.bin(h)
190 d['nodestoremove'] = [nodemod.bin(h)
191 for h in d['nodestoremove'].split(' ')]
191 for h in d['nodestoremove'].split(' ')]
192 except (ValueError, TypeError, KeyError) as err:
192 except (ValueError, TypeError, KeyError) as err:
193 raise error.CorruptedState(pycompat.bytestr(err))
193 raise error.CorruptedState(pycompat.bytestr(err))
194
194
195 @classmethod
195 @classmethod
196 def _getversion(cls, repo):
196 def _getversion(cls, repo):
197 """Read version information from shelvestate file"""
197 """Read version information from shelvestate file"""
198 fp = repo.vfs(cls._filename)
198 fp = repo.vfs(cls._filename)
199 try:
199 try:
200 version = int(fp.readline().strip())
200 version = int(fp.readline().strip())
201 except ValueError as err:
201 except ValueError as err:
202 raise error.CorruptedState(pycompat.bytestr(err))
202 raise error.CorruptedState(pycompat.bytestr(err))
203 finally:
203 finally:
204 fp.close()
204 fp.close()
205 return version
205 return version
206
206
207 @classmethod
207 @classmethod
208 def _readold(cls, repo):
208 def _readold(cls, repo):
209 """Read the old position-based version of a shelvestate file"""
209 """Read the old position-based version of a shelvestate file"""
210 # Order is important, because old shelvestate file uses it
210 # Order is important, because old shelvestate file uses it
211 # to detemine values of fields (i.g. name is on the second line,
211 # to detemine values of fields (i.g. name is on the second line,
212 # originalwctx is on the third and so forth). Please do not change.
212 # originalwctx is on the third and so forth). Please do not change.
213 keys = ['version', 'name', 'originalwctx', 'pendingctx', 'parents',
213 keys = ['version', 'name', 'originalwctx', 'pendingctx', 'parents',
214 'nodestoremove', 'branchtorestore', 'keep', 'activebook']
214 'nodestoremove', 'branchtorestore', 'keep', 'activebook']
215 # this is executed only seldomly, so it is not a big deal
215 # this is executed only seldomly, so it is not a big deal
216 # that we open this file twice
216 # that we open this file twice
217 fp = repo.vfs(cls._filename)
217 fp = repo.vfs(cls._filename)
218 d = {}
218 d = {}
219 try:
219 try:
220 for key in keys:
220 for key in keys:
221 d[key] = fp.readline().strip()
221 d[key] = fp.readline().strip()
222 finally:
222 finally:
223 fp.close()
223 fp.close()
224 return d
224 return d
225
225
226 @classmethod
226 @classmethod
227 def load(cls, repo):
227 def load(cls, repo):
228 version = cls._getversion(repo)
228 version = cls._getversion(repo)
229 if version < cls._version:
229 if version < cls._version:
230 d = cls._readold(repo)
230 d = cls._readold(repo)
231 elif version == cls._version:
231 elif version == cls._version:
232 d = scmutil.simplekeyvaluefile(
232 d = scmutil.simplekeyvaluefile(
233 repo.vfs, cls._filename).read(firstlinenonkeyval=True)
233 repo.vfs, cls._filename).read(firstlinenonkeyval=True)
234 else:
234 else:
235 raise error.Abort(_('this version of shelve is incompatible '
235 raise error.Abort(_('this version of shelve is incompatible '
236 'with the version used in this repo'))
236 'with the version used in this repo'))
237
237
238 cls._verifyandtransform(d)
238 cls._verifyandtransform(d)
239 try:
239 try:
240 obj = cls()
240 obj = cls()
241 obj.name = d['name']
241 obj.name = d['name']
242 obj.wctx = repo[d['originalwctx']]
242 obj.wctx = repo[d['originalwctx']]
243 obj.pendingctx = repo[d['pendingctx']]
243 obj.pendingctx = repo[d['pendingctx']]
244 obj.parents = d['parents']
244 obj.parents = d['parents']
245 obj.nodestoremove = d['nodestoremove']
245 obj.nodestoremove = d['nodestoremove']
246 obj.branchtorestore = d.get('branchtorestore', '')
246 obj.branchtorestore = d.get('branchtorestore', '')
247 obj.keep = d.get('keep') == cls._keep
247 obj.keep = d.get('keep') == cls._keep
248 obj.activebookmark = ''
248 obj.activebookmark = ''
249 if d.get('activebook', '') != cls._noactivebook:
249 if d.get('activebook', '') != cls._noactivebook:
250 obj.activebookmark = d.get('activebook', '')
250 obj.activebookmark = d.get('activebook', '')
251 obj.interactive = d.get('interactive') == cls._interactive
251 obj.interactive = d.get('interactive') == cls._interactive
252 except (error.RepoLookupError, KeyError) as err:
252 except (error.RepoLookupError, KeyError) as err:
253 raise error.CorruptedState(pycompat.bytestr(err))
253 raise error.CorruptedState(pycompat.bytestr(err))
254
254
255 return obj
255 return obj
256
256
257 @classmethod
257 @classmethod
258 def save(cls, repo, name, originalwctx, pendingctx, nodestoremove,
258 def save(cls, repo, name, originalwctx, pendingctx, nodestoremove,
259 branchtorestore, keep=False, activebook='', interactive=False):
259 branchtorestore, keep=False, activebook='', interactive=False):
260 info = {
260 info = {
261 "name": name,
261 "name": name,
262 "originalwctx": nodemod.hex(originalwctx.node()),
262 "originalwctx": nodemod.hex(originalwctx.node()),
263 "pendingctx": nodemod.hex(pendingctx.node()),
263 "pendingctx": nodemod.hex(pendingctx.node()),
264 "parents": ' '.join([nodemod.hex(p)
264 "parents": ' '.join([nodemod.hex(p)
265 for p in repo.dirstate.parents()]),
265 for p in repo.dirstate.parents()]),
266 "nodestoremove": ' '.join([nodemod.hex(n)
266 "nodestoremove": ' '.join([nodemod.hex(n)
267 for n in nodestoremove]),
267 for n in nodestoremove]),
268 "branchtorestore": branchtorestore,
268 "branchtorestore": branchtorestore,
269 "keep": cls._keep if keep else cls._nokeep,
269 "keep": cls._keep if keep else cls._nokeep,
270 "activebook": activebook or cls._noactivebook
270 "activebook": activebook or cls._noactivebook
271 }
271 }
272 if interactive:
272 if interactive:
273 info['interactive'] = cls._interactive
273 info['interactive'] = cls._interactive
274 scmutil.simplekeyvaluefile(
274 scmutil.simplekeyvaluefile(
275 repo.vfs, cls._filename).write(info,
275 repo.vfs, cls._filename).write(info,
276 firstline=("%d" % cls._version))
276 firstline=("%d" % cls._version))
277
277
278 @classmethod
278 @classmethod
279 def clear(cls, repo):
279 def clear(cls, repo):
280 repo.vfs.unlinkpath(cls._filename, ignoremissing=True)
280 repo.vfs.unlinkpath(cls._filename, ignoremissing=True)
281
281
282 def cleanupoldbackups(repo):
282 def cleanupoldbackups(repo):
283 vfs = vfsmod.vfs(repo.vfs.join(backupdir))
283 vfs = vfsmod.vfs(repo.vfs.join(backupdir))
284 maxbackups = repo.ui.configint('shelve', 'maxbackups')
284 maxbackups = repo.ui.configint('shelve', 'maxbackups')
285 hgfiles = [f for f in vfs.listdir()
285 hgfiles = [f for f in vfs.listdir()
286 if f.endswith('.' + patchextension)]
286 if f.endswith('.' + patchextension)]
287 hgfiles = sorted([(vfs.stat(f)[stat.ST_MTIME], f) for f in hgfiles])
287 hgfiles = sorted([(vfs.stat(f)[stat.ST_MTIME], f) for f in hgfiles])
288 if maxbackups > 0 and maxbackups < len(hgfiles):
288 if maxbackups > 0 and maxbackups < len(hgfiles):
289 bordermtime = hgfiles[-maxbackups][0]
289 bordermtime = hgfiles[-maxbackups][0]
290 else:
290 else:
291 bordermtime = None
291 bordermtime = None
292 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
292 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
293 if mtime == bordermtime:
293 if mtime == bordermtime:
294 # keep it, because timestamp can't decide exact order of backups
294 # keep it, because timestamp can't decide exact order of backups
295 continue
295 continue
296 base = f[:-(1 + len(patchextension))]
296 base = f[:-(1 + len(patchextension))]
297 for ext in shelvefileextensions:
297 for ext in shelvefileextensions:
298 vfs.tryunlink(base + '.' + ext)
298 vfs.tryunlink(base + '.' + ext)
299
299
300 def _backupactivebookmark(repo):
300 def _backupactivebookmark(repo):
301 activebookmark = repo._activebookmark
301 activebookmark = repo._activebookmark
302 if activebookmark:
302 if activebookmark:
303 bookmarks.deactivate(repo)
303 bookmarks.deactivate(repo)
304 return activebookmark
304 return activebookmark
305
305
306 def _restoreactivebookmark(repo, mark):
306 def _restoreactivebookmark(repo, mark):
307 if mark:
307 if mark:
308 bookmarks.activate(repo, mark)
308 bookmarks.activate(repo, mark)
309
309
310 def _aborttransaction(repo, tr):
310 def _aborttransaction(repo, tr):
311 '''Abort current transaction for shelve/unshelve, but keep dirstate
311 '''Abort current transaction for shelve/unshelve, but keep dirstate
312 '''
312 '''
313 dirstatebackupname = 'dirstate.shelve'
313 dirstatebackupname = 'dirstate.shelve'
314 repo.dirstate.savebackup(tr, dirstatebackupname)
314 repo.dirstate.savebackup(tr, dirstatebackupname)
315 tr.abort()
315 tr.abort()
316 repo.dirstate.restorebackup(None, dirstatebackupname)
316 repo.dirstate.restorebackup(None, dirstatebackupname)
317
317
318 def getshelvename(repo, parent, opts):
318 def getshelvename(repo, parent, opts):
319 """Decide on the name this shelve is going to have"""
319 """Decide on the name this shelve is going to have"""
320 def gennames():
320 def gennames():
321 yield label
321 yield label
322 for i in itertools.count(1):
322 for i in itertools.count(1):
323 yield '%s-%02d' % (label, i)
323 yield '%s-%02d' % (label, i)
324 name = opts.get('name')
324 name = opts.get('name')
325 label = repo._activebookmark or parent.branch() or 'default'
325 label = repo._activebookmark or parent.branch() or 'default'
326 # slashes aren't allowed in filenames, therefore we rename it
326 # slashes aren't allowed in filenames, therefore we rename it
327 label = label.replace('/', '_')
327 label = label.replace('/', '_')
328 label = label.replace('\\', '_')
328 label = label.replace('\\', '_')
329 # filenames must not start with '.' as it should not be hidden
329 # filenames must not start with '.' as it should not be hidden
330 if label.startswith('.'):
330 if label.startswith('.'):
331 label = label.replace('.', '_', 1)
331 label = label.replace('.', '_', 1)
332
332
333 if name:
333 if name:
334 if shelvedfile(repo, name, patchextension).exists():
334 if shelvedfile(repo, name, patchextension).exists():
335 e = _("a shelved change named '%s' already exists") % name
335 e = _("a shelved change named '%s' already exists") % name
336 raise error.Abort(e)
336 raise error.Abort(e)
337
337
338 # ensure we are not creating a subdirectory or a hidden file
338 # ensure we are not creating a subdirectory or a hidden file
339 if '/' in name or '\\' in name:
339 if '/' in name or '\\' in name:
340 raise error.Abort(_('shelved change names can not contain slashes'))
340 raise error.Abort(_('shelved change names can not contain slashes'))
341 if name.startswith('.'):
341 if name.startswith('.'):
342 raise error.Abort(_("shelved change names can not start with '.'"))
342 raise error.Abort(_("shelved change names can not start with '.'"))
343
343
344 else:
344 else:
345 for n in gennames():
345 for n in gennames():
346 if not shelvedfile(repo, n, patchextension).exists():
346 if not shelvedfile(repo, n, patchextension).exists():
347 name = n
347 name = n
348 break
348 break
349
349
350 return name
350 return name
351
351
352 def mutableancestors(ctx):
352 def mutableancestors(ctx):
353 """return all mutable ancestors for ctx (included)
353 """return all mutable ancestors for ctx (included)
354
354
355 Much faster than the revset ancestors(ctx) & draft()"""
355 Much faster than the revset ancestors(ctx) & draft()"""
356 seen = {nodemod.nullrev}
356 seen = {nodemod.nullrev}
357 visit = collections.deque()
357 visit = collections.deque()
358 visit.append(ctx)
358 visit.append(ctx)
359 while visit:
359 while visit:
360 ctx = visit.popleft()
360 ctx = visit.popleft()
361 yield ctx.node()
361 yield ctx.node()
362 for parent in ctx.parents():
362 for parent in ctx.parents():
363 rev = parent.rev()
363 rev = parent.rev()
364 if rev not in seen:
364 if rev not in seen:
365 seen.add(rev)
365 seen.add(rev)
366 if parent.mutable():
366 if parent.mutable():
367 visit.append(parent)
367 visit.append(parent)
368
368
369 def getcommitfunc(extra, interactive, editor=False):
369 def getcommitfunc(extra, interactive, editor=False):
370 def commitfunc(ui, repo, message, match, opts):
370 def commitfunc(ui, repo, message, match, opts):
371 hasmq = util.safehasattr(repo, 'mq')
371 hasmq = util.safehasattr(repo, 'mq')
372 if hasmq:
372 if hasmq:
373 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
373 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
374
374
375 targetphase = phases.internal
375 targetphase = phases.internal
376 if not phases.supportinternal(repo):
376 if not phases.supportinternal(repo):
377 targetphase = phases.secret
377 targetphase = phases.secret
378 overrides = {('phases', 'new-commit'): targetphase}
378 overrides = {('phases', 'new-commit'): targetphase}
379 try:
379 try:
380 editor_ = False
380 editor_ = False
381 if editor:
381 if editor:
382 editor_ = cmdutil.getcommiteditor(editform='shelve.shelve',
382 editor_ = cmdutil.getcommiteditor(editform='shelve.shelve',
383 **pycompat.strkwargs(opts))
383 **pycompat.strkwargs(opts))
384 with repo.ui.configoverride(overrides):
384 with repo.ui.configoverride(overrides):
385 return repo.commit(message, shelveuser, opts.get('date'),
385 return repo.commit(message, shelveuser, opts.get('date'),
386 match, editor=editor_, extra=extra)
386 match, editor=editor_, extra=extra)
387 finally:
387 finally:
388 if hasmq:
388 if hasmq:
389 repo.mq.checkapplied = saved
389 repo.mq.checkapplied = saved
390
390
391 def interactivecommitfunc(ui, repo, *pats, **opts):
391 def interactivecommitfunc(ui, repo, *pats, **opts):
392 opts = pycompat.byteskwargs(opts)
392 opts = pycompat.byteskwargs(opts)
393 match = scmutil.match(repo['.'], pats, {})
393 match = scmutil.match(repo['.'], pats, {})
394 message = opts['message']
394 message = opts['message']
395 return commitfunc(ui, repo, message, match, opts)
395 return commitfunc(ui, repo, message, match, opts)
396
396
397 return interactivecommitfunc if interactive else commitfunc
397 return interactivecommitfunc if interactive else commitfunc
398
398
399 def _nothingtoshelvemessaging(ui, repo, pats, opts):
399 def _nothingtoshelvemessaging(ui, repo, pats, opts):
400 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
400 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
401 if stat.deleted:
401 if stat.deleted:
402 ui.status(_("nothing changed (%d missing files, see "
402 ui.status(_("nothing changed (%d missing files, see "
403 "'hg status')\n") % len(stat.deleted))
403 "'hg status')\n") % len(stat.deleted))
404 else:
404 else:
405 ui.status(_("nothing changed\n"))
405 ui.status(_("nothing changed\n"))
406
406
407 def _shelvecreatedcommit(repo, node, name, match):
407 def _shelvecreatedcommit(repo, node, name, match):
408 info = {'node': nodemod.hex(node)}
408 info = {'node': nodemod.hex(node)}
409 shelvedfile(repo, name, 'shelve').writeinfo(info)
409 shelvedfile(repo, name, 'shelve').writeinfo(info)
410 bases = list(mutableancestors(repo[node]))
410 bases = list(mutableancestors(repo[node]))
411 shelvedfile(repo, name, 'hg').writebundle(bases, node)
411 shelvedfile(repo, name, 'hg').writebundle(bases, node)
412 with shelvedfile(repo, name, patchextension).opener('wb') as fp:
412 with shelvedfile(repo, name, patchextension).opener('wb') as fp:
413 cmdutil.exportfile(repo, [node], fp, opts=mdiff.diffopts(git=True),
413 cmdutil.exportfile(repo, [node], fp, opts=mdiff.diffopts(git=True),
414 match=match)
414 match=match)
415
415
416 def _includeunknownfiles(repo, pats, opts, extra):
416 def _includeunknownfiles(repo, pats, opts, extra):
417 s = repo.status(match=scmutil.match(repo[None], pats, opts),
417 s = repo.status(match=scmutil.match(repo[None], pats, opts),
418 unknown=True)
418 unknown=True)
419 if s.unknown:
419 if s.unknown:
420 extra['shelve_unknown'] = '\0'.join(s.unknown)
420 extra['shelve_unknown'] = '\0'.join(s.unknown)
421 repo[None].add(s.unknown)
421 repo[None].add(s.unknown)
422
422
423 def _finishshelve(repo, tr):
423 def _finishshelve(repo, tr):
424 if phases.supportinternal(repo):
424 if phases.supportinternal(repo):
425 tr.close()
425 tr.close()
426 else:
426 else:
427 _aborttransaction(repo, tr)
427 _aborttransaction(repo, tr)
428
428
429 def createcmd(ui, repo, pats, opts):
429 def createcmd(ui, repo, pats, opts):
430 """subcommand that creates a new shelve"""
430 """subcommand that creates a new shelve"""
431 with repo.wlock():
431 with repo.wlock():
432 cmdutil.checkunfinished(repo)
432 cmdutil.checkunfinished(repo)
433 return _docreatecmd(ui, repo, pats, opts)
433 return _docreatecmd(ui, repo, pats, opts)
434
434
435 def _docreatecmd(ui, repo, pats, opts):
435 def _docreatecmd(ui, repo, pats, opts):
436 wctx = repo[None]
436 wctx = repo[None]
437 parents = wctx.parents()
437 parents = wctx.parents()
438 parent = parents[0]
438 parent = parents[0]
439 origbranch = wctx.branch()
439 origbranch = wctx.branch()
440
440
441 if parent.node() != nodemod.nullid:
441 if parent.node() != nodemod.nullid:
442 desc = "changes to: %s" % parent.description().split('\n', 1)[0]
442 desc = "changes to: %s" % parent.description().split('\n', 1)[0]
443 else:
443 else:
444 desc = '(changes in empty repository)'
444 desc = '(changes in empty repository)'
445
445
446 if not opts.get('message'):
446 if not opts.get('message'):
447 opts['message'] = desc
447 opts['message'] = desc
448
448
449 lock = tr = activebookmark = None
449 lock = tr = activebookmark = None
450 try:
450 try:
451 lock = repo.lock()
451 lock = repo.lock()
452
452
453 # use an uncommitted transaction to generate the bundle to avoid
453 # use an uncommitted transaction to generate the bundle to avoid
454 # pull races. ensure we don't print the abort message to stderr.
454 # pull races. ensure we don't print the abort message to stderr.
455 tr = repo.transaction('shelve', report=lambda x: None)
455 tr = repo.transaction('shelve', report=lambda x: None)
456
456
457 interactive = opts.get('interactive', False)
457 interactive = opts.get('interactive', False)
458 includeunknown = (opts.get('unknown', False) and
458 includeunknown = (opts.get('unknown', False) and
459 not opts.get('addremove', False))
459 not opts.get('addremove', False))
460
460
461 name = getshelvename(repo, parent, opts)
461 name = getshelvename(repo, parent, opts)
462 activebookmark = _backupactivebookmark(repo)
462 activebookmark = _backupactivebookmark(repo)
463 extra = {'internal': 'shelve'}
463 extra = {'internal': 'shelve'}
464 if includeunknown:
464 if includeunknown:
465 _includeunknownfiles(repo, pats, opts, extra)
465 _includeunknownfiles(repo, pats, opts, extra)
466
466
467 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts):
467 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts):
468 # In non-bare shelve we don't store newly created branch
468 # In non-bare shelve we don't store newly created branch
469 # at bundled commit
469 # at bundled commit
470 repo.dirstate.setbranch(repo['.'].branch())
470 repo.dirstate.setbranch(repo['.'].branch())
471
471
472 commitfunc = getcommitfunc(extra, interactive, editor=True)
472 commitfunc = getcommitfunc(extra, interactive, editor=True)
473 if not interactive:
473 if not interactive:
474 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
474 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
475 else:
475 else:
476 node = cmdutil.dorecord(ui, repo, commitfunc, None,
476 node = cmdutil.dorecord(ui, repo, commitfunc, None,
477 False, cmdutil.recordfilter, *pats,
477 False, cmdutil.recordfilter, *pats,
478 **pycompat.strkwargs(opts))
478 **pycompat.strkwargs(opts))
479 if not node:
479 if not node:
480 _nothingtoshelvemessaging(ui, repo, pats, opts)
480 _nothingtoshelvemessaging(ui, repo, pats, opts)
481 return 1
481 return 1
482
482
483 # Create a matcher so that prefetch doesn't attempt to fetch
483 # Create a matcher so that prefetch doesn't attempt to fetch
484 # the entire repository pointlessly, and as an optimisation
484 # the entire repository pointlessly, and as an optimisation
485 # for movedirstate, if needed.
485 # for movedirstate, if needed.
486 match = scmutil.matchfiles(repo, repo[node].files())
486 match = scmutil.matchfiles(repo, repo[node].files())
487 _shelvecreatedcommit(repo, node, name, match)
487 _shelvecreatedcommit(repo, node, name, match)
488
488
489 if ui.formatted():
489 if ui.formatted():
490 desc = stringutil.ellipsis(desc, ui.termwidth())
490 desc = stringutil.ellipsis(desc, ui.termwidth())
491 ui.status(_('shelved as %s\n') % name)
491 ui.status(_('shelved as %s\n') % name)
492 if opts['keep']:
492 if opts['keep']:
493 with repo.dirstate.parentchange():
493 with repo.dirstate.parentchange():
494 scmutil.movedirstate(repo, parent, match)
494 scmutil.movedirstate(repo, parent, match)
495 else:
495 else:
496 hg.update(repo, parent.node())
496 hg.update(repo, parent.node())
497 if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
497 if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
498 repo.dirstate.setbranch(origbranch)
498 repo.dirstate.setbranch(origbranch)
499
499
500 _finishshelve(repo, tr)
500 _finishshelve(repo, tr)
501 finally:
501 finally:
502 _restoreactivebookmark(repo, activebookmark)
502 _restoreactivebookmark(repo, activebookmark)
503 lockmod.release(tr, lock)
503 lockmod.release(tr, lock)
504
504
505 def _isbareshelve(pats, opts):
505 def _isbareshelve(pats, opts):
506 return (not pats
506 return (not pats
507 and not opts.get('interactive', False)
507 and not opts.get('interactive', False)
508 and not opts.get('include', False)
508 and not opts.get('include', False)
509 and not opts.get('exclude', False))
509 and not opts.get('exclude', False))
510
510
511 def _iswctxonnewbranch(repo):
511 def _iswctxonnewbranch(repo):
512 return repo[None].branch() != repo['.'].branch()
512 return repo[None].branch() != repo['.'].branch()
513
513
514 def cleanupcmd(ui, repo):
514 def cleanupcmd(ui, repo):
515 """subcommand that deletes all shelves"""
515 """subcommand that deletes all shelves"""
516
516
517 with repo.wlock():
517 with repo.wlock():
518 for (name, _type) in repo.vfs.readdir(shelvedir):
518 for (name, _type) in repo.vfs.readdir(shelvedir):
519 suffix = name.rsplit('.', 1)[-1]
519 suffix = name.rsplit('.', 1)[-1]
520 if suffix in shelvefileextensions:
520 if suffix in shelvefileextensions:
521 shelvedfile(repo, name).movetobackup()
521 shelvedfile(repo, name).movetobackup()
522 cleanupoldbackups(repo)
522 cleanupoldbackups(repo)
523
523
524 def deletecmd(ui, repo, pats):
524 def deletecmd(ui, repo, pats):
525 """subcommand that deletes a specific shelve"""
525 """subcommand that deletes a specific shelve"""
526 if not pats:
526 if not pats:
527 raise error.Abort(_('no shelved changes specified!'))
527 raise error.Abort(_('no shelved changes specified!'))
528 with repo.wlock():
528 with repo.wlock():
529 try:
529 try:
530 for name in pats:
530 for name in pats:
531 for suffix in shelvefileextensions:
531 for suffix in shelvefileextensions:
532 shfile = shelvedfile(repo, name, suffix)
532 shfile = shelvedfile(repo, name, suffix)
533 # patch file is necessary, as it should
533 # patch file is necessary, as it should
534 # be present for any kind of shelve,
534 # be present for any kind of shelve,
535 # but the .hg file is optional as in future we
535 # but the .hg file is optional as in future we
536 # will add obsolete shelve with does not create a
536 # will add obsolete shelve with does not create a
537 # bundle
537 # bundle
538 if shfile.exists() or suffix == patchextension:
538 if shfile.exists() or suffix == patchextension:
539 shfile.movetobackup()
539 shfile.movetobackup()
540 cleanupoldbackups(repo)
540 cleanupoldbackups(repo)
541 except OSError as err:
541 except OSError as err:
542 if err.errno != errno.ENOENT:
542 if err.errno != errno.ENOENT:
543 raise
543 raise
544 raise error.Abort(_("shelved change '%s' not found") % name)
544 raise error.Abort(_("shelved change '%s' not found") % name)
545
545
546 def listshelves(repo):
546 def listshelves(repo):
547 """return all shelves in repo as list of (time, filename)"""
547 """return all shelves in repo as list of (time, filename)"""
548 try:
548 try:
549 names = repo.vfs.readdir(shelvedir)
549 names = repo.vfs.readdir(shelvedir)
550 except OSError as err:
550 except OSError as err:
551 if err.errno != errno.ENOENT:
551 if err.errno != errno.ENOENT:
552 raise
552 raise
553 return []
553 return []
554 info = []
554 info = []
555 for (name, _type) in names:
555 for (name, _type) in names:
556 pfx, sfx = name.rsplit('.', 1)
556 pfx, sfx = name.rsplit('.', 1)
557 if not pfx or sfx != patchextension:
557 if not pfx or sfx != patchextension:
558 continue
558 continue
559 st = shelvedfile(repo, name).stat()
559 st = shelvedfile(repo, name).stat()
560 info.append((st[stat.ST_MTIME], shelvedfile(repo, pfx).filename()))
560 info.append((st[stat.ST_MTIME], shelvedfile(repo, pfx).filename()))
561 return sorted(info, reverse=True)
561 return sorted(info, reverse=True)
562
562
563 def listcmd(ui, repo, pats, opts):
563 def listcmd(ui, repo, pats, opts):
564 """subcommand that displays the list of shelves"""
564 """subcommand that displays the list of shelves"""
565 pats = set(pats)
565 pats = set(pats)
566 width = 80
566 width = 80
567 if not ui.plain():
567 if not ui.plain():
568 width = ui.termwidth()
568 width = ui.termwidth()
569 namelabel = 'shelve.newest'
569 namelabel = 'shelve.newest'
570 ui.pager('shelve')
570 ui.pager('shelve')
571 for mtime, name in listshelves(repo):
571 for mtime, name in listshelves(repo):
572 sname = util.split(name)[1]
572 sname = util.split(name)[1]
573 if pats and sname not in pats:
573 if pats and sname not in pats:
574 continue
574 continue
575 ui.write(sname, label=namelabel)
575 ui.write(sname, label=namelabel)
576 namelabel = 'shelve.name'
576 namelabel = 'shelve.name'
577 if ui.quiet:
577 if ui.quiet:
578 ui.write('\n')
578 ui.write('\n')
579 continue
579 continue
580 ui.write(' ' * (16 - len(sname)))
580 ui.write(' ' * (16 - len(sname)))
581 used = 16
581 used = 16
582 date = dateutil.makedate(mtime)
582 date = dateutil.makedate(mtime)
583 age = '(%s)' % templatefilters.age(date, abbrev=True)
583 age = '(%s)' % templatefilters.age(date, abbrev=True)
584 ui.write(age, label='shelve.age')
584 ui.write(age, label='shelve.age')
585 ui.write(' ' * (12 - len(age)))
585 ui.write(' ' * (12 - len(age)))
586 used += 12
586 used += 12
587 with open(name + '.' + patchextension, 'rb') as fp:
587 with open(name + '.' + patchextension, 'rb') as fp:
588 while True:
588 while True:
589 line = fp.readline()
589 line = fp.readline()
590 if not line:
590 if not line:
591 break
591 break
592 if not line.startswith('#'):
592 if not line.startswith('#'):
593 desc = line.rstrip()
593 desc = line.rstrip()
594 if ui.formatted():
594 if ui.formatted():
595 desc = stringutil.ellipsis(desc, width - used)
595 desc = stringutil.ellipsis(desc, width - used)
596 ui.write(desc)
596 ui.write(desc)
597 break
597 break
598 ui.write('\n')
598 ui.write('\n')
599 if not (opts['patch'] or opts['stat']):
599 if not (opts['patch'] or opts['stat']):
600 continue
600 continue
601 difflines = fp.readlines()
601 difflines = fp.readlines()
602 if opts['patch']:
602 if opts['patch']:
603 for chunk, label in patch.difflabel(iter, difflines):
603 for chunk, label in patch.difflabel(iter, difflines):
604 ui.write(chunk, label=label)
604 ui.write(chunk, label=label)
605 if opts['stat']:
605 if opts['stat']:
606 for chunk, label in patch.diffstatui(difflines, width=width):
606 for chunk, label in patch.diffstatui(difflines, width=width):
607 ui.write(chunk, label=label)
607 ui.write(chunk, label=label)
608
608
609 def patchcmds(ui, repo, pats, opts):
609 def patchcmds(ui, repo, pats, opts):
610 """subcommand that displays shelves"""
610 """subcommand that displays shelves"""
611 if len(pats) == 0:
611 if len(pats) == 0:
612 shelves = listshelves(repo)
612 shelves = listshelves(repo)
613 if not shelves:
613 if not shelves:
614 raise error.Abort(_("there are no shelves to show"))
614 raise error.Abort(_("there are no shelves to show"))
615 mtime, name = shelves[0]
615 mtime, name = shelves[0]
616 sname = util.split(name)[1]
616 sname = util.split(name)[1]
617 pats = [sname]
617 pats = [sname]
618
618
619 for shelfname in pats:
619 for shelfname in pats:
620 if not shelvedfile(repo, shelfname, patchextension).exists():
620 if not shelvedfile(repo, shelfname, patchextension).exists():
621 raise error.Abort(_("cannot find shelf %s") % shelfname)
621 raise error.Abort(_("cannot find shelf %s") % shelfname)
622
622
623 listcmd(ui, repo, pats, opts)
623 listcmd(ui, repo, pats, opts)
624
624
625 def checkparents(repo, state):
625 def checkparents(repo, state):
626 """check parent while resuming an unshelve"""
626 """check parent while resuming an unshelve"""
627 if state.parents != repo.dirstate.parents():
627 if state.parents != repo.dirstate.parents():
628 raise error.Abort(_('working directory parents do not match unshelve '
628 raise error.Abort(_('working directory parents do not match unshelve '
629 'state'))
629 'state'))
630
630
631 def _loadshelvedstate(ui, repo, opts):
631 def _loadshelvedstate(ui, repo, opts):
632 try:
632 try:
633 state = shelvedstate.load(repo)
633 state = shelvedstate.load(repo)
634 if opts.get('keep') is None:
634 if opts.get('keep') is None:
635 opts['keep'] = state.keep
635 opts['keep'] = state.keep
636 except IOError as err:
636 except IOError as err:
637 if err.errno != errno.ENOENT:
637 if err.errno != errno.ENOENT:
638 raise
638 raise
639 cmdutil.wrongtooltocontinue(repo, _('unshelve'))
639 cmdutil.wrongtooltocontinue(repo, _('unshelve'))
640 except error.CorruptedState as err:
640 except error.CorruptedState as err:
641 ui.debug(pycompat.bytestr(err) + '\n')
641 ui.debug(pycompat.bytestr(err) + '\n')
642 if opts.get('continue'):
642 if opts.get('continue'):
643 msg = _('corrupted shelved state file')
643 msg = _('corrupted shelved state file')
644 hint = _('please run hg unshelve --abort to abort unshelve '
644 hint = _('please run hg unshelve --abort to abort unshelve '
645 'operation')
645 'operation')
646 raise error.Abort(msg, hint=hint)
646 raise error.Abort(msg, hint=hint)
647 elif opts.get('abort'):
647 elif opts.get('abort'):
648 shelvedstate.clear(repo)
648 shelvedstate.clear(repo)
649 raise error.Abort(_('could not read shelved state file, your '
649 raise error.Abort(_('could not read shelved state file, your '
650 'working copy may be in an unexpected state\n'
650 'working copy may be in an unexpected state\n'
651 'please update to some commit\n'))
651 'please update to some commit\n'))
652 return state
652 return state
653
653
654 def unshelveabort(ui, repo, state):
654 def unshelveabort(ui, repo, state):
655 """subcommand that abort an in-progress unshelve"""
655 """subcommand that abort an in-progress unshelve"""
656 with repo.lock():
656 with repo.lock():
657 try:
657 try:
658 checkparents(repo, state)
658 checkparents(repo, state)
659
659
660 merge.update(repo, state.pendingctx, branchmerge=False, force=True)
660 merge.update(repo, state.pendingctx, branchmerge=False, force=True)
661 if (state.activebookmark
661 if (state.activebookmark
662 and state.activebookmark in repo._bookmarks):
662 and state.activebookmark in repo._bookmarks):
663 bookmarks.activate(repo, state.activebookmark)
663 bookmarks.activate(repo, state.activebookmark)
664 mergefiles(ui, repo, state.wctx, state.pendingctx)
664 mergefiles(ui, repo, state.wctx, state.pendingctx)
665 if not phases.supportinternal(repo):
665 if not phases.supportinternal(repo):
666 repair.strip(ui, repo, state.nodestoremove, backup=False,
666 repair.strip(ui, repo, state.nodestoremove, backup=False,
667 topic='shelve')
667 topic='shelve')
668 finally:
668 finally:
669 shelvedstate.clear(repo)
669 shelvedstate.clear(repo)
670 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
670 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
671
671
672 def hgabortunshelve(ui, repo):
672 def hgabortunshelve(ui, repo):
673 """logic to abort unshelve using 'hg abort"""
673 """logic to abort unshelve using 'hg abort"""
674 with repo.wlock():
674 with repo.wlock():
675 state = _loadshelvedstate(ui, repo, {'abort' : True})
675 state = _loadshelvedstate(ui, repo, {'abort' : True})
676 return unshelveabort(ui, repo, state)
676 return unshelveabort(ui, repo, state)
677
677
678 def mergefiles(ui, repo, wctx, shelvectx):
678 def mergefiles(ui, repo, wctx, shelvectx):
679 """updates to wctx and merges the changes from shelvectx into the
679 """updates to wctx and merges the changes from shelvectx into the
680 dirstate."""
680 dirstate."""
681 with ui.configoverride({('ui', 'quiet'): True}):
681 with ui.configoverride({('ui', 'quiet'): True}):
682 hg.update(repo, wctx.node())
682 hg.update(repo, wctx.node())
683 ui.pushbuffer(True)
683 ui.pushbuffer(True)
684 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents())
684 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents())
685 ui.popbuffer()
685 ui.popbuffer()
686
686
687 def restorebranch(ui, repo, branchtorestore):
687 def restorebranch(ui, repo, branchtorestore):
688 if branchtorestore and branchtorestore != repo.dirstate.branch():
688 if branchtorestore and branchtorestore != repo.dirstate.branch():
689 repo.dirstate.setbranch(branchtorestore)
689 repo.dirstate.setbranch(branchtorestore)
690 ui.status(_('marked working directory as branch %s\n')
690 ui.status(_('marked working directory as branch %s\n')
691 % branchtorestore)
691 % branchtorestore)
692
692
693 def unshelvecleanup(ui, repo, name, opts):
693 def unshelvecleanup(ui, repo, name, opts):
694 """remove related files after an unshelve"""
694 """remove related files after an unshelve"""
695 if not opts.get('keep'):
695 if not opts.get('keep'):
696 for filetype in shelvefileextensions:
696 for filetype in shelvefileextensions:
697 shfile = shelvedfile(repo, name, filetype)
697 shfile = shelvedfile(repo, name, filetype)
698 if shfile.exists():
698 if shfile.exists():
699 shfile.movetobackup()
699 shfile.movetobackup()
700 cleanupoldbackups(repo)
700 cleanupoldbackups(repo)
701 def unshelvecontinue(ui, repo, state, opts):
701 def unshelvecontinue(ui, repo, state, opts):
702 """subcommand to continue an in-progress unshelve"""
702 """subcommand to continue an in-progress unshelve"""
703 # We're finishing off a merge. First parent is our original
703 # We're finishing off a merge. First parent is our original
704 # parent, second is the temporary "fake" commit we're unshelving.
704 # parent, second is the temporary "fake" commit we're unshelving.
705 interactive = state.interactive
705 interactive = state.interactive
706 basename = state.name
706 basename = state.name
707 with repo.lock():
707 with repo.lock():
708 checkparents(repo, state)
708 checkparents(repo, state)
709 ms = merge.mergestate.read(repo)
709 ms = merge.mergestate.read(repo)
710 if list(ms.unresolved()):
710 if list(ms.unresolved()):
711 raise error.Abort(
711 raise error.Abort(
712 _("unresolved conflicts, can't continue"),
712 _("unresolved conflicts, can't continue"),
713 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
713 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
714
714
715 shelvectx = repo[state.parents[1]]
715 shelvectx = repo[state.parents[1]]
716 pendingctx = state.pendingctx
716 pendingctx = state.pendingctx
717
717
718 with repo.dirstate.parentchange():
718 with repo.dirstate.parentchange():
719 repo.setparents(state.pendingctx.node(), nodemod.nullid)
719 repo.setparents(state.pendingctx.node(), nodemod.nullid)
720 repo.dirstate.write(repo.currenttransaction())
720 repo.dirstate.write(repo.currenttransaction())
721
721
722 targetphase = phases.internal
722 targetphase = phases.internal
723 if not phases.supportinternal(repo):
723 if not phases.supportinternal(repo):
724 targetphase = phases.secret
724 targetphase = phases.secret
725 overrides = {('phases', 'new-commit'): targetphase}
725 overrides = {('phases', 'new-commit'): targetphase}
726 with repo.ui.configoverride(overrides, 'unshelve'):
726 with repo.ui.configoverride(overrides, 'unshelve'):
727 with repo.dirstate.parentchange():
727 with repo.dirstate.parentchange():
728 repo.setparents(state.parents[0], nodemod.nullid)
728 repo.setparents(state.parents[0], nodemod.nullid)
729 newnode, ispartialunshelve = _createunshelvectx(ui,
729 newnode, ispartialunshelve = _createunshelvectx(ui,
730 repo, shelvectx, basename, interactive, opts)
730 repo, shelvectx, basename, interactive, opts)
731
731
732 if newnode is None:
732 if newnode is None:
733 # If it ended up being a no-op commit, then the normal
733 # If it ended up being a no-op commit, then the normal
734 # merge state clean-up path doesn't happen, so do it
734 # merge state clean-up path doesn't happen, so do it
735 # here. Fix issue5494
735 # here. Fix issue5494
736 merge.mergestate.clean(repo)
736 merge.mergestate.clean(repo)
737 shelvectx = state.pendingctx
737 shelvectx = state.pendingctx
738 msg = _('note: unshelved changes already existed '
738 msg = _('note: unshelved changes already existed '
739 'in the working copy\n')
739 'in the working copy\n')
740 ui.status(msg)
740 ui.status(msg)
741 else:
741 else:
742 # only strip the shelvectx if we produced one
742 # only strip the shelvectx if we produced one
743 state.nodestoremove.append(newnode)
743 state.nodestoremove.append(newnode)
744 shelvectx = repo[newnode]
744 shelvectx = repo[newnode]
745
745
746 hg.updaterepo(repo, pendingctx.node(), overwrite=False)
746 hg.updaterepo(repo, pendingctx.node(), overwrite=False)
747 mergefiles(ui, repo, state.wctx, shelvectx)
747 mergefiles(ui, repo, state.wctx, shelvectx)
748 restorebranch(ui, repo, state.branchtorestore)
748 restorebranch(ui, repo, state.branchtorestore)
749
749
750 if not phases.supportinternal(repo):
750 if not phases.supportinternal(repo):
751 repair.strip(ui, repo, state.nodestoremove, backup=False,
751 repair.strip(ui, repo, state.nodestoremove, backup=False,
752 topic='shelve')
752 topic='shelve')
753 shelvedstate.clear(repo)
753 shelvedstate.clear(repo)
754 if not ispartialunshelve:
754 if not ispartialunshelve:
755 unshelvecleanup(ui, repo, state.name, opts)
755 unshelvecleanup(ui, repo, state.name, opts)
756 _restoreactivebookmark(repo, state.activebookmark)
756 _restoreactivebookmark(repo, state.activebookmark)
757 ui.status(_("unshelve of '%s' complete\n") % state.name)
757 ui.status(_("unshelve of '%s' complete\n") % state.name)
758
758
759 def hgcontinueunshelve(ui, repo):
759 def hgcontinueunshelve(ui, repo):
760 """logic to resume unshelve using 'hg continue'"""
760 """logic to resume unshelve using 'hg continue'"""
761 with repo.wlock():
761 with repo.wlock():
762 state = _loadshelvedstate(ui, repo, {'continue' : True})
762 state = _loadshelvedstate(ui, repo, {'continue' : True})
763 return unshelvecontinue(ui, repo, state, {'keep' : state.keep})
763 return unshelvecontinue(ui, repo, state, {'keep' : state.keep})
764
764
765 def _commitworkingcopychanges(ui, repo, opts, tmpwctx):
765 def _commitworkingcopychanges(ui, repo, opts, tmpwctx):
766 """Temporarily commit working copy changes before moving unshelve commit"""
766 """Temporarily commit working copy changes before moving unshelve commit"""
767 # Store pending changes in a commit and remember added in case a shelve
767 # Store pending changes in a commit and remember added in case a shelve
768 # contains unknown files that are part of the pending change
768 # contains unknown files that are part of the pending change
769 s = repo.status()
769 s = repo.status()
770 addedbefore = frozenset(s.added)
770 addedbefore = frozenset(s.added)
771 if not (s.modified or s.added or s.removed):
771 if not (s.modified or s.added or s.removed):
772 return tmpwctx, addedbefore
772 return tmpwctx, addedbefore
773 ui.status(_("temporarily committing pending changes "
773 ui.status(_("temporarily committing pending changes "
774 "(restore with 'hg unshelve --abort')\n"))
774 "(restore with 'hg unshelve --abort')\n"))
775 extra = {'internal': 'shelve'}
775 extra = {'internal': 'shelve'}
776 commitfunc = getcommitfunc(extra=extra, interactive=False,
776 commitfunc = getcommitfunc(extra=extra, interactive=False,
777 editor=False)
777 editor=False)
778 tempopts = {}
778 tempopts = {}
779 tempopts['message'] = "pending changes temporary commit"
779 tempopts['message'] = "pending changes temporary commit"
780 tempopts['date'] = opts.get('date')
780 tempopts['date'] = opts.get('date')
781 with ui.configoverride({('ui', 'quiet'): True}):
781 with ui.configoverride({('ui', 'quiet'): True}):
782 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
782 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
783 tmpwctx = repo[node]
783 tmpwctx = repo[node]
784 return tmpwctx, addedbefore
784 return tmpwctx, addedbefore
785
785
786 def _unshelverestorecommit(ui, repo, tr, basename):
786 def _unshelverestorecommit(ui, repo, tr, basename):
787 """Recreate commit in the repository during the unshelve"""
787 """Recreate commit in the repository during the unshelve"""
788 repo = repo.unfiltered()
788 repo = repo.unfiltered()
789 node = None
789 node = None
790 if shelvedfile(repo, basename, 'shelve').exists():
790 if shelvedfile(repo, basename, 'shelve').exists():
791 node = shelvedfile(repo, basename, 'shelve').readinfo()['node']
791 node = shelvedfile(repo, basename, 'shelve').readinfo()['node']
792 if node is None or node not in repo:
792 if node is None or node not in repo:
793 with ui.configoverride({('ui', 'quiet'): True}):
793 with ui.configoverride({('ui', 'quiet'): True}):
794 shelvectx = shelvedfile(repo, basename, 'hg').applybundle(tr)
794 shelvectx = shelvedfile(repo, basename, 'hg').applybundle(tr)
795 # We might not strip the unbundled changeset, so we should keep track of
795 # We might not strip the unbundled changeset, so we should keep track of
796 # the unshelve node in case we need to reuse it (eg: unshelve --keep)
796 # the unshelve node in case we need to reuse it (eg: unshelve --keep)
797 if node is None:
797 if node is None:
798 info = {'node': nodemod.hex(shelvectx.node())}
798 info = {'node': nodemod.hex(shelvectx.node())}
799 shelvedfile(repo, basename, 'shelve').writeinfo(info)
799 shelvedfile(repo, basename, 'shelve').writeinfo(info)
800 else:
800 else:
801 shelvectx = repo[node]
801 shelvectx = repo[node]
802
802
803 return repo, shelvectx
803 return repo, shelvectx
804
804
805 def _createunshelvectx(ui, repo, shelvectx, basename, interactive, opts):
805 def _createunshelvectx(ui, repo, shelvectx, basename, interactive, opts):
806 """Handles the creation of unshelve commit and updates the shelve if it
806 """Handles the creation of unshelve commit and updates the shelve if it
807 was partially unshelved.
807 was partially unshelved.
808
808
809 If interactive is:
809 If interactive is:
810
810
811 * False: Commits all the changes in the working directory.
811 * False: Commits all the changes in the working directory.
812 * True: Prompts the user to select changes to unshelve and commit them.
812 * True: Prompts the user to select changes to unshelve and commit them.
813 Update the shelve with remaining changes.
813 Update the shelve with remaining changes.
814
814
815 Returns the node of the new commit formed and a bool indicating whether
815 Returns the node of the new commit formed and a bool indicating whether
816 the shelve was partially unshelved.Creates a commit ctx to unshelve
816 the shelve was partially unshelved.Creates a commit ctx to unshelve
817 interactively or non-interactively.
817 interactively or non-interactively.
818
818
819 The user might want to unshelve certain changes only from the stored
819 The user might want to unshelve certain changes only from the stored
820 shelve in interactive. So, we would create two commits. One with requested
820 shelve in interactive. So, we would create two commits. One with requested
821 changes to unshelve at that time and the latter is shelved for future.
821 changes to unshelve at that time and the latter is shelved for future.
822
822
823 Here, we return both the newnode which is created interactively and a
823 Here, we return both the newnode which is created interactively and a
824 bool to know whether the shelve is partly done or completely done.
824 bool to know whether the shelve is partly done or completely done.
825 """
825 """
826 opts['message'] = shelvectx.description()
826 opts['message'] = shelvectx.description()
827 opts['interactive-unshelve'] = True
827 opts['interactive-unshelve'] = True
828 pats = []
828 pats = []
829 if not interactive:
829 if not interactive:
830 newnode = repo.commit(text=shelvectx.description(),
830 newnode = repo.commit(text=shelvectx.description(),
831 extra=shelvectx.extra(),
831 extra=shelvectx.extra(),
832 user=shelvectx.user(),
832 user=shelvectx.user(),
833 date=shelvectx.date())
833 date=shelvectx.date())
834 return newnode, False
834 return newnode, False
835
835
836 commitfunc = getcommitfunc(shelvectx.extra(), interactive=True,
836 commitfunc = getcommitfunc(shelvectx.extra(), interactive=True,
837 editor=True)
837 editor=True)
838 newnode = cmdutil.dorecord(ui, repo, commitfunc, None, False,
838 newnode = cmdutil.dorecord(ui, repo, commitfunc, None, False,
839 cmdutil.recordfilter, *pats,
839 cmdutil.recordfilter, *pats,
840 **pycompat.strkwargs(opts))
840 **pycompat.strkwargs(opts))
841 snode = repo.commit(text=shelvectx.description(),
841 snode = repo.commit(text=shelvectx.description(),
842 extra=shelvectx.extra(),
842 extra=shelvectx.extra(),
843 user=shelvectx.user())
843 user=shelvectx.user())
844 if snode:
844 if snode:
845 m = scmutil.matchfiles(repo, repo[snode].files())
845 m = scmutil.matchfiles(repo, repo[snode].files())
846 _shelvecreatedcommit(repo, snode, basename, m)
846 _shelvecreatedcommit(repo, snode, basename, m)
847
847
848 return newnode, bool(snode)
848 return newnode, bool(snode)
849
849
850 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx,
850 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx,
851 tmpwctx, shelvectx, branchtorestore,
851 tmpwctx, shelvectx, branchtorestore,
852 activebookmark):
852 activebookmark):
853 """Rebase restored commit from its original location to a destination"""
853 """Rebase restored commit from its original location to a destination"""
854 # If the shelve is not immediately on top of the commit
854 # If the shelve is not immediately on top of the commit
855 # we'll be merging with, rebase it to be on top.
855 # we'll be merging with, rebase it to be on top.
856 interactive = opts.get('interactive')
856 interactive = opts.get('interactive')
857 if tmpwctx.node() == shelvectx.p1().node() and not interactive:
857 if tmpwctx.node() == shelvectx.p1().node() and not interactive:
858 # We won't skip on interactive mode because, the user might want to
858 # We won't skip on interactive mode because, the user might want to
859 # unshelve certain changes only.
859 # unshelve certain changes only.
860 return shelvectx, False
860 return shelvectx, False
861
861
862 overrides = {
862 overrides = {
863 ('ui', 'forcemerge'): opts.get('tool', ''),
863 ('ui', 'forcemerge'): opts.get('tool', ''),
864 ('phases', 'new-commit'): phases.secret,
864 ('phases', 'new-commit'): phases.secret,
865 }
865 }
866 with repo.ui.configoverride(overrides, 'unshelve'):
866 with repo.ui.configoverride(overrides, 'unshelve'):
867 ui.status(_('rebasing shelved changes\n'))
867 ui.status(_('rebasing shelved changes\n'))
868 stats = merge.graft(repo, shelvectx, shelvectx.p1(),
868 stats = merge.graft(repo, shelvectx, shelvectx.p1(),
869 labels=['shelve', 'working-copy'],
869 labels=['shelve', 'working-copy'],
870 keepconflictparent=True)
870 keepconflictparent=True)
871 if stats.unresolvedcount:
871 if stats.unresolvedcount:
872 tr.close()
872 tr.close()
873
873
874 nodestoremove = [repo.changelog.node(rev)
874 nodestoremove = [repo.changelog.node(rev)
875 for rev in pycompat.xrange(oldtiprev, len(repo))]
875 for rev in pycompat.xrange(oldtiprev, len(repo))]
876 shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoremove,
876 shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoremove,
877 branchtorestore, opts.get('keep'), activebookmark,
877 branchtorestore, opts.get('keep'), activebookmark,
878 interactive)
878 interactive)
879 raise error.InterventionRequired(
879 raise error.InterventionRequired(
880 _("unresolved conflicts (see 'hg resolve', then "
880 _("unresolved conflicts (see 'hg resolve', then "
881 "'hg unshelve --continue')"))
881 "'hg unshelve --continue')"))
882
882
883 with repo.dirstate.parentchange():
883 with repo.dirstate.parentchange():
884 repo.setparents(tmpwctx.node(), nodemod.nullid)
884 repo.setparents(tmpwctx.node(), nodemod.nullid)
885 newnode, ispartialunshelve = _createunshelvectx(ui, repo,
885 newnode, ispartialunshelve = _createunshelvectx(ui, repo,
886 shelvectx, basename, interactive, opts)
886 shelvectx, basename, interactive, opts)
887
887
888 if newnode is None:
888 if newnode is None:
889 # If it ended up being a no-op commit, then the normal
889 # If it ended up being a no-op commit, then the normal
890 # merge state clean-up path doesn't happen, so do it
890 # merge state clean-up path doesn't happen, so do it
891 # here. Fix issue5494
891 # here. Fix issue5494
892 merge.mergestate.clean(repo)
892 merge.mergestate.clean(repo)
893 shelvectx = tmpwctx
893 shelvectx = tmpwctx
894 msg = _('note: unshelved changes already existed '
894 msg = _('note: unshelved changes already existed '
895 'in the working copy\n')
895 'in the working copy\n')
896 ui.status(msg)
896 ui.status(msg)
897 else:
897 else:
898 shelvectx = repo[newnode]
898 shelvectx = repo[newnode]
899 hg.updaterepo(repo, tmpwctx.node(), False)
899 hg.updaterepo(repo, tmpwctx.node(), False)
900
900
901 return shelvectx, ispartialunshelve
901 return shelvectx, ispartialunshelve
902
902
903 def _forgetunknownfiles(repo, shelvectx, addedbefore):
903 def _forgetunknownfiles(repo, shelvectx, addedbefore):
904 # Forget any files that were unknown before the shelve, unknown before
904 # Forget any files that were unknown before the shelve, unknown before
905 # unshelve started, but are now added.
905 # unshelve started, but are now added.
906 shelveunknown = shelvectx.extra().get('shelve_unknown')
906 shelveunknown = shelvectx.extra().get('shelve_unknown')
907 if not shelveunknown:
907 if not shelveunknown:
908 return
908 return
909 shelveunknown = frozenset(shelveunknown.split('\0'))
909 shelveunknown = frozenset(shelveunknown.split('\0'))
910 addedafter = frozenset(repo.status().added)
910 addedafter = frozenset(repo.status().added)
911 toforget = (addedafter & shelveunknown) - addedbefore
911 toforget = (addedafter & shelveunknown) - addedbefore
912 repo[None].forget(toforget)
912 repo[None].forget(toforget)
913
913
914 def _finishunshelve(repo, oldtiprev, tr, activebookmark):
914 def _finishunshelve(repo, oldtiprev, tr, activebookmark):
915 _restoreactivebookmark(repo, activebookmark)
915 _restoreactivebookmark(repo, activebookmark)
916 # The transaction aborting will strip all the commits for us,
916 # The transaction aborting will strip all the commits for us,
917 # but it doesn't update the inmemory structures, so addchangegroup
917 # but it doesn't update the inmemory structures, so addchangegroup
918 # hooks still fire and try to operate on the missing commits.
918 # hooks still fire and try to operate on the missing commits.
919 # Clean up manually to prevent this.
919 # Clean up manually to prevent this.
920 repo.unfiltered().changelog.strip(oldtiprev, tr)
920 repo.unfiltered().changelog.strip(oldtiprev, tr)
921 _aborttransaction(repo, tr)
921 _aborttransaction(repo, tr)
922
922
923 def _checkunshelveuntrackedproblems(ui, repo, shelvectx):
923 def _checkunshelveuntrackedproblems(ui, repo, shelvectx):
924 """Check potential problems which may result from working
924 """Check potential problems which may result from working
925 copy having untracked changes."""
925 copy having untracked changes."""
926 wcdeleted = set(repo.status().deleted)
926 wcdeleted = set(repo.status().deleted)
927 shelvetouched = set(shelvectx.files())
927 shelvetouched = set(shelvectx.files())
928 intersection = wcdeleted.intersection(shelvetouched)
928 intersection = wcdeleted.intersection(shelvetouched)
929 if intersection:
929 if intersection:
930 m = _("shelved change touches missing files")
930 m = _("shelved change touches missing files")
931 hint = _("run hg status to see which files are missing")
931 hint = _("run hg status to see which files are missing")
932 raise error.Abort(m, hint=hint)
932 raise error.Abort(m, hint=hint)
933
933
934 def dounshelve(ui, repo, *shelved, **opts):
934 def dounshelve(ui, repo, *shelved, **opts):
935 opts = pycompat.byteskwargs(opts)
935 opts = pycompat.byteskwargs(opts)
936 abortf = opts.get('abort')
936 abortf = opts.get('abort')
937 continuef = opts.get('continue')
937 continuef = opts.get('continue')
938 interactive = opts.get('interactive')
938 interactive = opts.get('interactive')
939 if not abortf and not continuef:
939 if not abortf and not continuef:
940 cmdutil.checkunfinished(repo)
940 cmdutil.checkunfinished(repo)
941 shelved = list(shelved)
941 shelved = list(shelved)
942 if opts.get("name"):
942 if opts.get("name"):
943 shelved.append(opts["name"])
943 shelved.append(opts["name"])
944
944
945 if abortf or continuef:
945 if abortf or continuef:
946 if abortf and continuef:
946 if abortf and continuef:
947 raise error.Abort(_('cannot use both abort and continue'))
947 raise error.Abort(_('cannot use both abort and continue'))
948 if shelved:
948 if shelved:
949 raise error.Abort(_('cannot combine abort/continue with '
949 raise error.Abort(_('cannot combine abort/continue with '
950 'naming a shelved change'))
950 'naming a shelved change'))
951 if abortf and opts.get('tool', False):
951 if abortf and opts.get('tool', False):
952 ui.warn(_('tool option will be ignored\n'))
952 ui.warn(_('tool option will be ignored\n'))
953
953
954 state = _loadshelvedstate(ui, repo, opts)
954 state = _loadshelvedstate(ui, repo, opts)
955 if abortf:
955 if abortf:
956 return unshelveabort(ui, repo, state)
956 return unshelveabort(ui, repo, state)
957 elif continuef and interactive:
957 elif continuef and interactive:
958 raise error.Abort(_('cannot use both continue and interactive'))
958 raise error.Abort(_('cannot use both continue and interactive'))
959 elif continuef:
959 elif continuef:
960 return unshelvecontinue(ui, repo, state, opts)
960 return unshelvecontinue(ui, repo, state, opts)
961 elif len(shelved) > 1:
961 elif len(shelved) > 1:
962 raise error.Abort(_('can only unshelve one change at a time'))
962 raise error.Abort(_('can only unshelve one change at a time'))
963 elif not shelved:
963 elif not shelved:
964 shelved = listshelves(repo)
964 shelved = listshelves(repo)
965 if not shelved:
965 if not shelved:
966 raise error.Abort(_('no shelved changes to apply!'))
966 raise error.Abort(_('no shelved changes to apply!'))
967 basename = util.split(shelved[0][1])[1]
967 basename = util.split(shelved[0][1])[1]
968 ui.status(_("unshelving change '%s'\n") % basename)
968 ui.status(_("unshelving change '%s'\n") % basename)
969 else:
969 else:
970 basename = shelved[0]
970 basename = shelved[0]
971
971
972 if not shelvedfile(repo, basename, patchextension).exists():
972 if not shelvedfile(repo, basename, patchextension).exists():
973 raise error.Abort(_("shelved change '%s' not found") % basename)
973 raise error.Abort(_("shelved change '%s' not found") % basename)
974
974
975 repo = repo.unfiltered()
975 repo = repo.unfiltered()
976 lock = tr = None
976 lock = tr = None
977 try:
977 try:
978 lock = repo.lock()
978 lock = repo.lock()
979 tr = repo.transaction('unshelve', report=lambda x: None)
979 tr = repo.transaction('unshelve', report=lambda x: None)
980 oldtiprev = len(repo)
980 oldtiprev = len(repo)
981
981
982 pctx = repo['.']
982 pctx = repo['.']
983 tmpwctx = pctx
983 tmpwctx = pctx
984 # The goal is to have a commit structure like so:
984 # The goal is to have a commit structure like so:
985 # ...-> pctx -> tmpwctx -> shelvectx
985 # ...-> pctx -> tmpwctx -> shelvectx
986 # where tmpwctx is an optional commit with the user's pending changes
986 # where tmpwctx is an optional commit with the user's pending changes
987 # and shelvectx is the unshelved changes. Then we merge it all down
987 # and shelvectx is the unshelved changes. Then we merge it all down
988 # to the original pctx.
988 # to the original pctx.
989
989
990 activebookmark = _backupactivebookmark(repo)
990 activebookmark = _backupactivebookmark(repo)
991 tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
991 tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
992 tmpwctx)
992 tmpwctx)
993 repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
993 repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
994 _checkunshelveuntrackedproblems(ui, repo, shelvectx)
994 _checkunshelveuntrackedproblems(ui, repo, shelvectx)
995 branchtorestore = ''
995 branchtorestore = ''
996 if shelvectx.branch() != shelvectx.p1().branch():
996 if shelvectx.branch() != shelvectx.p1().branch():
997 branchtorestore = shelvectx.branch()
997 branchtorestore = shelvectx.branch()
998
998
999 shelvectx, ispartialunshelve = _rebaserestoredcommit(ui, repo, opts,
999 shelvectx, ispartialunshelve = _rebaserestoredcommit(ui, repo, opts,
1000 tr, oldtiprev, basename, pctx, tmpwctx, shelvectx,
1000 tr, oldtiprev, basename, pctx, tmpwctx, shelvectx,
1001 branchtorestore, activebookmark)
1001 branchtorestore, activebookmark)
1002 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
1002 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
1003 with ui.configoverride(overrides, 'unshelve'):
1003 with ui.configoverride(overrides, 'unshelve'):
1004 mergefiles(ui, repo, pctx, shelvectx)
1004 mergefiles(ui, repo, pctx, shelvectx)
1005 restorebranch(ui, repo, branchtorestore)
1005 restorebranch(ui, repo, branchtorestore)
1006 shelvedstate.clear(repo)
1006 shelvedstate.clear(repo)
1007 _finishunshelve(repo, oldtiprev, tr, activebookmark)
1007 _finishunshelve(repo, oldtiprev, tr, activebookmark)
1008 _forgetunknownfiles(repo, shelvectx, addedbefore)
1008 if not ispartialunshelve:
1009 if not ispartialunshelve:
1009 _forgetunknownfiles(repo, shelvectx, addedbefore)
1010 unshelvecleanup(ui, repo, basename, opts)
1010 unshelvecleanup(ui, repo, basename, opts)
1011 finally:
1011 finally:
1012 if tr:
1012 if tr:
1013 tr.release()
1013 tr.release()
1014 lockmod.release(lock)
1014 lockmod.release(lock)
@@ -1,1458 +1,1477 b''
1 #testcases stripbased phasebased
1 #testcases stripbased phasebased
2
2
3 $ cat <<EOF >> $HGRCPATH
3 $ cat <<EOF >> $HGRCPATH
4 > [extensions]
4 > [extensions]
5 > mq =
5 > mq =
6 > [defaults]
6 > [defaults]
7 > diff = --nodates --git
7 > diff = --nodates --git
8 > qnew = --date '0 0'
8 > qnew = --date '0 0'
9 > [shelve]
9 > [shelve]
10 > maxbackups = 2
10 > maxbackups = 2
11 > EOF
11 > EOF
12
12
13 #if phasebased
13 #if phasebased
14
14
15 $ cat <<EOF >> $HGRCPATH
15 $ cat <<EOF >> $HGRCPATH
16 > [format]
16 > [format]
17 > internal-phase = yes
17 > internal-phase = yes
18 > EOF
18 > EOF
19
19
20 #endif
20 #endif
21
21
22 $ hg init repo
22 $ hg init repo
23 $ cd repo
23 $ cd repo
24 $ mkdir a b
24 $ mkdir a b
25 $ echo a > a/a
25 $ echo a > a/a
26 $ echo b > b/b
26 $ echo b > b/b
27 $ echo c > c
27 $ echo c > c
28 $ echo d > d
28 $ echo d > d
29 $ echo x > x
29 $ echo x > x
30 $ hg addremove -q
30 $ hg addremove -q
31
31
32 shelve has a help message
32 shelve has a help message
33 $ hg shelve -h
33 $ hg shelve -h
34 hg shelve [OPTION]... [FILE]...
34 hg shelve [OPTION]... [FILE]...
35
35
36 save and set aside changes from the working directory
36 save and set aside changes from the working directory
37
37
38 Shelving takes files that "hg status" reports as not clean, saves the
38 Shelving takes files that "hg status" reports as not clean, saves the
39 modifications to a bundle (a shelved change), and reverts the files so
39 modifications to a bundle (a shelved change), and reverts the files so
40 that their state in the working directory becomes clean.
40 that their state in the working directory becomes clean.
41
41
42 To restore these changes to the working directory, using "hg unshelve";
42 To restore these changes to the working directory, using "hg unshelve";
43 this will work even if you switch to a different commit.
43 this will work even if you switch to a different commit.
44
44
45 When no files are specified, "hg shelve" saves all not-clean files. If
45 When no files are specified, "hg shelve" saves all not-clean files. If
46 specific files or directories are named, only changes to those files are
46 specific files or directories are named, only changes to those files are
47 shelved.
47 shelved.
48
48
49 In bare shelve (when no files are specified, without interactive, include
49 In bare shelve (when no files are specified, without interactive, include
50 and exclude option), shelving remembers information if the working
50 and exclude option), shelving remembers information if the working
51 directory was on newly created branch, in other words working directory
51 directory was on newly created branch, in other words working directory
52 was on different branch than its first parent. In this situation
52 was on different branch than its first parent. In this situation
53 unshelving restores branch information to the working directory.
53 unshelving restores branch information to the working directory.
54
54
55 Each shelved change has a name that makes it easier to find later. The
55 Each shelved change has a name that makes it easier to find later. The
56 name of a shelved change defaults to being based on the active bookmark,
56 name of a shelved change defaults to being based on the active bookmark,
57 or if there is no active bookmark, the current named branch. To specify a
57 or if there is no active bookmark, the current named branch. To specify a
58 different name, use "--name".
58 different name, use "--name".
59
59
60 To see a list of existing shelved changes, use the "--list" option. For
60 To see a list of existing shelved changes, use the "--list" option. For
61 each shelved change, this will print its name, age, and description; use "
61 each shelved change, this will print its name, age, and description; use "
62 --patch" or "--stat" for more details.
62 --patch" or "--stat" for more details.
63
63
64 To delete specific shelved changes, use "--delete". To delete all shelved
64 To delete specific shelved changes, use "--delete". To delete all shelved
65 changes, use "--cleanup".
65 changes, use "--cleanup".
66
66
67 options ([+] can be repeated):
67 options ([+] can be repeated):
68
68
69 -A --addremove mark new/missing files as added/removed before
69 -A --addremove mark new/missing files as added/removed before
70 shelving
70 shelving
71 -u --unknown store unknown files in the shelve
71 -u --unknown store unknown files in the shelve
72 --cleanup delete all shelved changes
72 --cleanup delete all shelved changes
73 --date DATE shelve with the specified commit date
73 --date DATE shelve with the specified commit date
74 -d --delete delete the named shelved change(s)
74 -d --delete delete the named shelved change(s)
75 -e --edit invoke editor on commit messages
75 -e --edit invoke editor on commit messages
76 -k --keep shelve, but keep changes in the working directory
76 -k --keep shelve, but keep changes in the working directory
77 -l --list list current shelves
77 -l --list list current shelves
78 -m --message TEXT use text as shelve message
78 -m --message TEXT use text as shelve message
79 -n --name NAME use the given name for the shelved commit
79 -n --name NAME use the given name for the shelved commit
80 -p --patch output patches for changes (provide the names of the
80 -p --patch output patches for changes (provide the names of the
81 shelved changes as positional arguments)
81 shelved changes as positional arguments)
82 -i --interactive interactive mode
82 -i --interactive interactive mode
83 --stat output diffstat-style summary of changes (provide
83 --stat output diffstat-style summary of changes (provide
84 the names of the shelved changes as positional
84 the names of the shelved changes as positional
85 arguments)
85 arguments)
86 -I --include PATTERN [+] include names matching the given patterns
86 -I --include PATTERN [+] include names matching the given patterns
87 -X --exclude PATTERN [+] exclude names matching the given patterns
87 -X --exclude PATTERN [+] exclude names matching the given patterns
88 --mq operate on patch repository
88 --mq operate on patch repository
89
89
90 (some details hidden, use --verbose to show complete help)
90 (some details hidden, use --verbose to show complete help)
91
91
92 shelving in an empty repo should be possible
92 shelving in an empty repo should be possible
93 (this tests also that editor is not invoked, if '--edit' is not
93 (this tests also that editor is not invoked, if '--edit' is not
94 specified)
94 specified)
95
95
96 $ HGEDITOR=cat hg shelve
96 $ HGEDITOR=cat hg shelve
97 shelved as default
97 shelved as default
98 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
98 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
99
99
100 $ hg unshelve
100 $ hg unshelve
101 unshelving change 'default'
101 unshelving change 'default'
102
102
103 $ hg commit -q -m 'initial commit'
103 $ hg commit -q -m 'initial commit'
104
104
105 $ hg shelve
105 $ hg shelve
106 nothing changed
106 nothing changed
107 [1]
107 [1]
108
108
109 make sure shelve files were backed up
109 make sure shelve files were backed up
110
110
111 $ ls .hg/shelve-backup
111 $ ls .hg/shelve-backup
112 default.hg
112 default.hg
113 default.patch
113 default.patch
114 default.shelve
114 default.shelve
115
115
116 checks to make sure we dont create a directory or
116 checks to make sure we dont create a directory or
117 hidden file while choosing a new shelve name
117 hidden file while choosing a new shelve name
118
118
119 when we are given a name
119 when we are given a name
120
120
121 $ hg shelve -n foo/bar
121 $ hg shelve -n foo/bar
122 abort: shelved change names can not contain slashes
122 abort: shelved change names can not contain slashes
123 [255]
123 [255]
124 $ hg shelve -n .baz
124 $ hg shelve -n .baz
125 abort: shelved change names can not start with '.'
125 abort: shelved change names can not start with '.'
126 [255]
126 [255]
127 $ hg shelve -n foo\\bar
127 $ hg shelve -n foo\\bar
128 abort: shelved change names can not contain slashes
128 abort: shelved change names can not contain slashes
129 [255]
129 [255]
130
130
131 when shelve has to choose itself
131 when shelve has to choose itself
132
132
133 $ hg branch x/y -q
133 $ hg branch x/y -q
134 $ hg commit -q -m "Branch commit 0"
134 $ hg commit -q -m "Branch commit 0"
135 $ hg shelve
135 $ hg shelve
136 nothing changed
136 nothing changed
137 [1]
137 [1]
138 $ hg branch .x -q
138 $ hg branch .x -q
139 $ hg commit -q -m "Branch commit 1"
139 $ hg commit -q -m "Branch commit 1"
140 $ hg shelve
140 $ hg shelve
141 nothing changed
141 nothing changed
142 [1]
142 [1]
143 $ hg branch x\\y -q
143 $ hg branch x\\y -q
144 $ hg commit -q -m "Branch commit 2"
144 $ hg commit -q -m "Branch commit 2"
145 $ hg shelve
145 $ hg shelve
146 nothing changed
146 nothing changed
147 [1]
147 [1]
148
148
149 cleaning the branches made for name checking tests
149 cleaning the branches made for name checking tests
150
150
151 $ hg up default -q
151 $ hg up default -q
152 $ hg strip e9177275307e+6a6d231f43d+882bae7c62c2 -q
152 $ hg strip e9177275307e+6a6d231f43d+882bae7c62c2 -q
153
153
154 create an mq patch - shelving should work fine with a patch applied
154 create an mq patch - shelving should work fine with a patch applied
155
155
156 $ echo n > n
156 $ echo n > n
157 $ hg add n
157 $ hg add n
158 $ hg commit n -m second
158 $ hg commit n -m second
159 $ hg qnew second.patch
159 $ hg qnew second.patch
160
160
161 shelve a change that we will delete later
161 shelve a change that we will delete later
162
162
163 $ echo a >> a/a
163 $ echo a >> a/a
164 $ hg shelve
164 $ hg shelve
165 shelved as default
165 shelved as default
166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
167
167
168 set up some more complex changes to shelve
168 set up some more complex changes to shelve
169
169
170 $ echo a >> a/a
170 $ echo a >> a/a
171 $ hg mv b b.rename
171 $ hg mv b b.rename
172 moving b/b to b.rename/b
172 moving b/b to b.rename/b
173 $ hg cp c c.copy
173 $ hg cp c c.copy
174 $ hg status -C
174 $ hg status -C
175 M a/a
175 M a/a
176 A b.rename/b
176 A b.rename/b
177 b/b
177 b/b
178 A c.copy
178 A c.copy
179 c
179 c
180 R b/b
180 R b/b
181
181
182 the common case - no options or filenames
182 the common case - no options or filenames
183
183
184 $ hg shelve
184 $ hg shelve
185 shelved as default-01
185 shelved as default-01
186 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
186 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
187 $ hg status -C
187 $ hg status -C
188
188
189 ensure that our shelved changes exist
189 ensure that our shelved changes exist
190
190
191 $ hg shelve -l
191 $ hg shelve -l
192 default-01 (*)* changes to: [mq]: second.patch (glob)
192 default-01 (*)* changes to: [mq]: second.patch (glob)
193 default (*)* changes to: [mq]: second.patch (glob)
193 default (*)* changes to: [mq]: second.patch (glob)
194
194
195 $ hg shelve -l -p default
195 $ hg shelve -l -p default
196 default (*)* changes to: [mq]: second.patch (glob)
196 default (*)* changes to: [mq]: second.patch (glob)
197
197
198 diff --git a/a/a b/a/a
198 diff --git a/a/a b/a/a
199 --- a/a/a
199 --- a/a/a
200 +++ b/a/a
200 +++ b/a/a
201 @@ -1,1 +1,2 @@
201 @@ -1,1 +1,2 @@
202 a
202 a
203 +a
203 +a
204
204
205 $ hg shelve --list --addremove
205 $ hg shelve --list --addremove
206 abort: options '--list' and '--addremove' may not be used together
206 abort: options '--list' and '--addremove' may not be used together
207 [255]
207 [255]
208
208
209 delete our older shelved change
209 delete our older shelved change
210
210
211 $ hg shelve -d default
211 $ hg shelve -d default
212 $ hg qfinish -a -q
212 $ hg qfinish -a -q
213
213
214 ensure shelve backups aren't overwritten
214 ensure shelve backups aren't overwritten
215
215
216 $ ls .hg/shelve-backup/
216 $ ls .hg/shelve-backup/
217 default-1.hg
217 default-1.hg
218 default-1.patch
218 default-1.patch
219 default-1.shelve
219 default-1.shelve
220 default.hg
220 default.hg
221 default.patch
221 default.patch
222 default.shelve
222 default.shelve
223
223
224 local edits should not prevent a shelved change from applying
224 local edits should not prevent a shelved change from applying
225
225
226 $ printf "z\na\n" > a/a
226 $ printf "z\na\n" > a/a
227 $ hg unshelve --keep
227 $ hg unshelve --keep
228 unshelving change 'default-01'
228 unshelving change 'default-01'
229 temporarily committing pending changes (restore with 'hg unshelve --abort')
229 temporarily committing pending changes (restore with 'hg unshelve --abort')
230 rebasing shelved changes
230 rebasing shelved changes
231 merging a/a
231 merging a/a
232
232
233 $ hg revert --all -q
233 $ hg revert --all -q
234 $ rm a/a.orig b.rename/b c.copy
234 $ rm a/a.orig b.rename/b c.copy
235
235
236 apply it and make sure our state is as expected
236 apply it and make sure our state is as expected
237
237
238 (this also tests that same timestamp prevents backups from being
238 (this also tests that same timestamp prevents backups from being
239 removed, even though there are more than 'maxbackups' backups)
239 removed, even though there are more than 'maxbackups' backups)
240
240
241 $ f -t .hg/shelve-backup/default.patch
241 $ f -t .hg/shelve-backup/default.patch
242 .hg/shelve-backup/default.patch: file
242 .hg/shelve-backup/default.patch: file
243 $ touch -t 200001010000 .hg/shelve-backup/default.patch
243 $ touch -t 200001010000 .hg/shelve-backup/default.patch
244 $ f -t .hg/shelve-backup/default-1.patch
244 $ f -t .hg/shelve-backup/default-1.patch
245 .hg/shelve-backup/default-1.patch: file
245 .hg/shelve-backup/default-1.patch: file
246 $ touch -t 200001010000 .hg/shelve-backup/default-1.patch
246 $ touch -t 200001010000 .hg/shelve-backup/default-1.patch
247
247
248 $ hg unshelve
248 $ hg unshelve
249 unshelving change 'default-01'
249 unshelving change 'default-01'
250 $ hg status -C
250 $ hg status -C
251 M a/a
251 M a/a
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
257 $ hg shelve -l
258
258
259 (both of default.hg and default-1.hg should be still kept, because it
259 (both of default.hg and default-1.hg should be still kept, because it
260 is difficult to decide actual order of them from same timestamp)
260 is difficult to decide actual order of them from same timestamp)
261
261
262 $ ls .hg/shelve-backup/
262 $ ls .hg/shelve-backup/
263 default-01.hg
263 default-01.hg
264 default-01.patch
264 default-01.patch
265 default-01.shelve
265 default-01.shelve
266 default-1.hg
266 default-1.hg
267 default-1.patch
267 default-1.patch
268 default-1.shelve
268 default-1.shelve
269 default.hg
269 default.hg
270 default.patch
270 default.patch
271 default.shelve
271 default.shelve
272
272
273 $ hg unshelve
273 $ hg unshelve
274 abort: no shelved changes to apply!
274 abort: no shelved changes to apply!
275 [255]
275 [255]
276 $ hg unshelve foo
276 $ hg unshelve foo
277 abort: shelved change 'foo' not found
277 abort: shelved change 'foo' not found
278 [255]
278 [255]
279
279
280 named shelves, specific filenames, and "commit messages" should all work
280 named shelves, specific filenames, and "commit messages" should all work
281 (this tests also that editor is invoked, if '--edit' is specified)
281 (this tests also that editor is invoked, if '--edit' is specified)
282
282
283 $ hg status -C
283 $ hg status -C
284 M a/a
284 M a/a
285 A b.rename/b
285 A b.rename/b
286 b/b
286 b/b
287 A c.copy
287 A c.copy
288 c
288 c
289 R b/b
289 R b/b
290 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
290 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
291 wat
291 wat
292
292
293
293
294 HG: Enter commit message. Lines beginning with 'HG:' are removed.
294 HG: Enter commit message. Lines beginning with 'HG:' are removed.
295 HG: Leave message empty to abort commit.
295 HG: Leave message empty to abort commit.
296 HG: --
296 HG: --
297 HG: user: shelve@localhost
297 HG: user: shelve@localhost
298 HG: branch 'default'
298 HG: branch 'default'
299 HG: changed a/a
299 HG: changed a/a
300
300
301 expect "a" to no longer be present, but status otherwise unchanged
301 expect "a" to no longer be present, but status otherwise unchanged
302
302
303 $ hg status -C
303 $ hg status -C
304 A b.rename/b
304 A b.rename/b
305 b/b
305 b/b
306 A c.copy
306 A c.copy
307 c
307 c
308 R b/b
308 R b/b
309 $ hg shelve -l --stat
309 $ hg shelve -l --stat
310 wibble (*) wat (glob)
310 wibble (*) wat (glob)
311 a/a | 1 +
311 a/a | 1 +
312 1 files changed, 1 insertions(+), 0 deletions(-)
312 1 files changed, 1 insertions(+), 0 deletions(-)
313
313
314 and now "a/a" should reappear
314 and now "a/a" should reappear
315
315
316 $ cd a
316 $ cd a
317 $ hg unshelve -q wibble
317 $ hg unshelve -q wibble
318 $ cd ..
318 $ cd ..
319 $ hg status -C
319 $ hg status -C
320 M a/a
320 M a/a
321 A b.rename/b
321 A b.rename/b
322 b/b
322 b/b
323 A c.copy
323 A c.copy
324 c
324 c
325 R b/b
325 R b/b
326
326
327 ensure old shelve backups are being deleted automatically
327 ensure old shelve backups are being deleted automatically
328
328
329 $ ls .hg/shelve-backup/
329 $ ls .hg/shelve-backup/
330 default-01.hg
330 default-01.hg
331 default-01.patch
331 default-01.patch
332 default-01.shelve
332 default-01.shelve
333 wibble.hg
333 wibble.hg
334 wibble.patch
334 wibble.patch
335 wibble.shelve
335 wibble.shelve
336
336
337 cause unshelving to result in a merge with 'a' conflicting
337 cause unshelving to result in a merge with 'a' conflicting
338
338
339 $ hg shelve -q
339 $ hg shelve -q
340 $ echo c>>a/a
340 $ echo c>>a/a
341 $ hg commit -m second
341 $ hg commit -m second
342 $ hg tip --template '{files}\n'
342 $ hg tip --template '{files}\n'
343 a/a
343 a/a
344
344
345 add an unrelated change that should be preserved
345 add an unrelated change that should be preserved
346
346
347 $ mkdir foo
347 $ mkdir foo
348 $ echo foo > foo/foo
348 $ echo foo > foo/foo
349 $ hg add foo/foo
349 $ hg add foo/foo
350
350
351 force a conflicted merge to occur
351 force a conflicted merge to occur
352
352
353 $ hg unshelve
353 $ hg unshelve
354 unshelving change 'default'
354 unshelving change 'default'
355 temporarily committing pending changes (restore with 'hg unshelve --abort')
355 temporarily committing pending changes (restore with 'hg unshelve --abort')
356 rebasing shelved changes
356 rebasing shelved changes
357 merging a/a
357 merging a/a
358 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
358 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
359 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
359 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
360 [1]
360 [1]
361 $ hg status -v
361 $ hg status -v
362 M a/a
362 M a/a
363 M b.rename/b
363 M b.rename/b
364 M c.copy
364 M c.copy
365 R b/b
365 R b/b
366 ? a/a.orig
366 ? a/a.orig
367 # The repository is in an unfinished *unshelve* state.
367 # The repository is in an unfinished *unshelve* state.
368
368
369 # Unresolved merge conflicts:
369 # Unresolved merge conflicts:
370 #
370 #
371 # a/a
371 # a/a
372 #
372 #
373 # To mark files as resolved: hg resolve --mark FILE
373 # To mark files as resolved: hg resolve --mark FILE
374
374
375 # To continue: hg unshelve --continue
375 # To continue: hg unshelve --continue
376 # To abort: hg unshelve --abort
376 # To abort: hg unshelve --abort
377
377
378
378
379 ensure that we have a merge with unresolved conflicts
379 ensure that we have a merge with unresolved conflicts
380
380
381 #if phasebased
381 #if phasebased
382 $ hg heads -q --template '{rev}\n'
382 $ hg heads -q --template '{rev}\n'
383 8
383 8
384 5
384 5
385 $ hg parents -q --template '{rev}\n'
385 $ hg parents -q --template '{rev}\n'
386 8
386 8
387 5
387 5
388 #endif
388 #endif
389
389
390 #if stripbased
390 #if stripbased
391 $ hg heads -q --template '{rev}\n'
391 $ hg heads -q --template '{rev}\n'
392 5
392 5
393 4
393 4
394 $ hg parents -q --template '{rev}\n'
394 $ hg parents -q --template '{rev}\n'
395 4
395 4
396 5
396 5
397 #endif
397 #endif
398
398
399 $ hg status
399 $ hg status
400 M a/a
400 M a/a
401 M b.rename/b
401 M b.rename/b
402 M c.copy
402 M c.copy
403 R b/b
403 R b/b
404 ? a/a.orig
404 ? a/a.orig
405 $ hg diff
405 $ hg diff
406 diff --git a/a/a b/a/a
406 diff --git a/a/a b/a/a
407 --- a/a/a
407 --- a/a/a
408 +++ b/a/a
408 +++ b/a/a
409 @@ -1,2 +1,6 @@
409 @@ -1,2 +1,6 @@
410 a
410 a
411 +<<<<<<< shelve: 2377350b6337 - shelve: pending changes temporary commit
411 +<<<<<<< shelve: 2377350b6337 - shelve: pending changes temporary commit
412 c
412 c
413 +=======
413 +=======
414 +a
414 +a
415 +>>>>>>> working-copy: a68ec3400638 - shelve: changes to: [mq]: second.patch
415 +>>>>>>> working-copy: a68ec3400638 - shelve: changes to: [mq]: second.patch
416 diff --git a/b/b b/b.rename/b
416 diff --git a/b/b b/b.rename/b
417 rename from b/b
417 rename from b/b
418 rename to b.rename/b
418 rename to b.rename/b
419 diff --git a/c b/c.copy
419 diff --git a/c b/c.copy
420 copy from c
420 copy from c
421 copy to c.copy
421 copy to c.copy
422 $ hg resolve -l
422 $ hg resolve -l
423 U a/a
423 U a/a
424
424
425 $ hg shelve
425 $ hg shelve
426 abort: unshelve already in progress
426 abort: unshelve already in progress
427 (use 'hg unshelve --continue' or 'hg unshelve --abort')
427 (use 'hg unshelve --continue' or 'hg unshelve --abort')
428 [255]
428 [255]
429
429
430 abort the unshelve and be happy
430 abort the unshelve and be happy
431
431
432 $ hg status
432 $ hg status
433 M a/a
433 M a/a
434 M b.rename/b
434 M b.rename/b
435 M c.copy
435 M c.copy
436 R b/b
436 R b/b
437 ? a/a.orig
437 ? a/a.orig
438 $ hg unshelve -a
438 $ hg unshelve -a
439 unshelve of 'default' aborted
439 unshelve of 'default' aborted
440 $ hg heads -q
440 $ hg heads -q
441 [37]:2e69b451d1ea (re)
441 [37]:2e69b451d1ea (re)
442 $ hg parents
442 $ hg parents
443 changeset: [37]:2e69b451d1ea (re)
443 changeset: [37]:2e69b451d1ea (re)
444 tag: tip
444 tag: tip
445 parent: 3:509104101065 (?)
445 parent: 3:509104101065 (?)
446 user: test
446 user: test
447 date: Thu Jan 01 00:00:00 1970 +0000
447 date: Thu Jan 01 00:00:00 1970 +0000
448 summary: second
448 summary: second
449
449
450 $ hg resolve -l
450 $ hg resolve -l
451 $ hg status
451 $ hg status
452 A foo/foo
452 A foo/foo
453 ? a/a.orig
453 ? a/a.orig
454
454
455 try to continue with no unshelve underway
455 try to continue with no unshelve underway
456
456
457 $ hg unshelve -c
457 $ hg unshelve -c
458 abort: no unshelve in progress
458 abort: no unshelve in progress
459 [255]
459 [255]
460 $ hg status
460 $ hg status
461 A foo/foo
461 A foo/foo
462 ? a/a.orig
462 ? a/a.orig
463
463
464 redo the unshelve to get a conflict
464 redo the unshelve to get a conflict
465
465
466 $ hg unshelve -q
466 $ hg unshelve -q
467 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
467 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
468 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
468 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
469 [1]
469 [1]
470
470
471 attempt to continue
471 attempt to continue
472
472
473 $ hg unshelve -c
473 $ hg unshelve -c
474 abort: unresolved conflicts, can't continue
474 abort: unresolved conflicts, can't continue
475 (see 'hg resolve', then 'hg unshelve --continue')
475 (see 'hg resolve', then 'hg unshelve --continue')
476 [255]
476 [255]
477
477
478 $ hg revert -r . a/a
478 $ hg revert -r . a/a
479 $ hg resolve -m a/a
479 $ hg resolve -m a/a
480 (no more unresolved files)
480 (no more unresolved files)
481 continue: hg unshelve --continue
481 continue: hg unshelve --continue
482
482
483 $ hg commit -m 'commit while unshelve in progress'
483 $ hg commit -m 'commit while unshelve in progress'
484 abort: unshelve already in progress
484 abort: unshelve already in progress
485 (use 'hg unshelve --continue' or 'hg unshelve --abort')
485 (use 'hg unshelve --continue' or 'hg unshelve --abort')
486 [255]
486 [255]
487
487
488 $ hg graft --continue
488 $ hg graft --continue
489 abort: no graft in progress
489 abort: no graft in progress
490 (continue: hg unshelve --continue)
490 (continue: hg unshelve --continue)
491 [255]
491 [255]
492 $ hg unshelve -c
492 $ hg unshelve -c
493 unshelve of 'default' complete
493 unshelve of 'default' complete
494
494
495 ensure the repo is as we hope
495 ensure the repo is as we hope
496
496
497 $ hg parents
497 $ hg parents
498 changeset: [37]:2e69b451d1ea (re)
498 changeset: [37]:2e69b451d1ea (re)
499 tag: tip
499 tag: tip
500 parent: 3:509104101065 (?)
500 parent: 3:509104101065 (?)
501 user: test
501 user: test
502 date: Thu Jan 01 00:00:00 1970 +0000
502 date: Thu Jan 01 00:00:00 1970 +0000
503 summary: second
503 summary: second
504
504
505 $ hg heads -q
505 $ hg heads -q
506 [37]:2e69b451d1ea (re)
506 [37]:2e69b451d1ea (re)
507
507
508 $ hg status -C
508 $ hg status -C
509 A b.rename/b
509 A b.rename/b
510 b/b
510 b/b
511 A c.copy
511 A c.copy
512 c
512 c
513 A foo/foo
513 A foo/foo
514 R b/b
514 R b/b
515 ? a/a.orig
515 ? a/a.orig
516
516
517 there should be no shelves left
517 there should be no shelves left
518
518
519 $ hg shelve -l
519 $ hg shelve -l
520
520
521 #if execbit
521 #if execbit
522
522
523 ensure that metadata-only changes are shelved
523 ensure that metadata-only changes are shelved
524
524
525 $ chmod +x a/a
525 $ chmod +x a/a
526 $ hg shelve -q -n execbit a/a
526 $ hg shelve -q -n execbit a/a
527 $ hg status a/a
527 $ hg status a/a
528 $ hg unshelve -q execbit
528 $ hg unshelve -q execbit
529 $ hg status a/a
529 $ hg status a/a
530 M a/a
530 M a/a
531 $ hg revert a/a
531 $ hg revert a/a
532
532
533 #else
533 #else
534
534
535 Dummy shelve op, to keep rev numbers aligned
535 Dummy shelve op, to keep rev numbers aligned
536
536
537 $ echo foo > a/a
537 $ echo foo > a/a
538 $ hg shelve -q -n dummy a/a
538 $ hg shelve -q -n dummy a/a
539 $ hg unshelve -q dummy
539 $ hg unshelve -q dummy
540 $ hg revert a/a
540 $ hg revert a/a
541
541
542 #endif
542 #endif
543
543
544 #if symlink
544 #if symlink
545
545
546 $ rm a/a
546 $ rm a/a
547 $ ln -s foo a/a
547 $ ln -s foo a/a
548 $ hg shelve -q -n symlink a/a
548 $ hg shelve -q -n symlink a/a
549 $ hg status a/a
549 $ hg status a/a
550 $ hg unshelve -q -n symlink
550 $ hg unshelve -q -n symlink
551 $ hg status a/a
551 $ hg status a/a
552 M a/a
552 M a/a
553 $ hg revert a/a
553 $ hg revert a/a
554
554
555 #else
555 #else
556
556
557 Dummy shelve op, to keep rev numbers aligned
557 Dummy shelve op, to keep rev numbers aligned
558
558
559 $ echo bar > a/a
559 $ echo bar > a/a
560 $ hg shelve -q -n dummy a/a
560 $ hg shelve -q -n dummy a/a
561 $ hg unshelve -q dummy
561 $ hg unshelve -q dummy
562 $ hg revert a/a
562 $ hg revert a/a
563
563
564 #endif
564 #endif
565
565
566 set up another conflict between a commit and a shelved change
566 set up another conflict between a commit and a shelved change
567
567
568 $ hg revert -q -C -a
568 $ hg revert -q -C -a
569 $ rm a/a.orig b.rename/b c.copy
569 $ rm a/a.orig b.rename/b c.copy
570 $ echo a >> a/a
570 $ echo a >> a/a
571 $ hg shelve -q
571 $ hg shelve -q
572 $ echo x >> a/a
572 $ echo x >> a/a
573 $ hg ci -m 'create conflict'
573 $ hg ci -m 'create conflict'
574 $ hg add foo/foo
574 $ hg add foo/foo
575
575
576 if we resolve a conflict while unshelving, the unshelve should succeed
576 if we resolve a conflict while unshelving, the unshelve should succeed
577
577
578 $ hg unshelve --tool :merge-other --keep
578 $ hg unshelve --tool :merge-other --keep
579 unshelving change 'default'
579 unshelving change 'default'
580 temporarily committing pending changes (restore with 'hg unshelve --abort')
580 temporarily committing pending changes (restore with 'hg unshelve --abort')
581 rebasing shelved changes
581 rebasing shelved changes
582 merging a/a
582 merging a/a
583 $ hg parents -q
583 $ hg parents -q
584 (4|13):33f7f61e6c5e (re)
584 (4|13):33f7f61e6c5e (re)
585 $ hg shelve -l
585 $ hg shelve -l
586 default (*)* changes to: second (glob)
586 default (*)* changes to: second (glob)
587 $ hg status
587 $ hg status
588 M a/a
588 M a/a
589 A foo/foo
589 A foo/foo
590 $ cat a/a
590 $ cat a/a
591 a
591 a
592 c
592 c
593 a
593 a
594 $ cat > a/a << EOF
594 $ cat > a/a << EOF
595 > a
595 > a
596 > c
596 > c
597 > x
597 > x
598 > EOF
598 > EOF
599
599
600 $ HGMERGE=true hg unshelve
600 $ HGMERGE=true hg unshelve
601 unshelving change 'default'
601 unshelving change 'default'
602 temporarily committing pending changes (restore with 'hg unshelve --abort')
602 temporarily committing pending changes (restore with 'hg unshelve --abort')
603 rebasing shelved changes
603 rebasing shelved changes
604 merging a/a
604 merging a/a
605 note: unshelved changes already existed in the working copy
605 note: unshelved changes already existed in the working copy
606 $ hg parents -q
606 $ hg parents -q
607 (4|13):33f7f61e6c5e (re)
607 (4|13):33f7f61e6c5e (re)
608 $ hg shelve -l
608 $ hg shelve -l
609 $ hg status
609 $ hg status
610 A foo/foo
610 A foo/foo
611 $ cat a/a
611 $ cat a/a
612 a
612 a
613 c
613 c
614 x
614 x
615
615
616 test keep and cleanup
616 test keep and cleanup
617
617
618 $ hg shelve
618 $ hg shelve
619 shelved as default
619 shelved as default
620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 $ hg shelve --list
621 $ hg shelve --list
622 default (*)* changes to: create conflict (glob)
622 default (*)* changes to: create conflict (glob)
623 $ hg unshelve -k
623 $ hg unshelve -k
624 unshelving change 'default'
624 unshelving change 'default'
625 $ hg shelve --list
625 $ hg shelve --list
626 default (*)* changes to: create conflict (glob)
626 default (*)* changes to: create conflict (glob)
627 $ hg shelve --cleanup
627 $ hg shelve --cleanup
628 $ hg shelve --list
628 $ hg shelve --list
629
629
630 $ hg shelve --cleanup --delete
630 $ hg shelve --cleanup --delete
631 abort: options '--cleanup' and '--delete' may not be used together
631 abort: options '--cleanup' and '--delete' may not be used together
632 [255]
632 [255]
633 $ hg shelve --cleanup --patch
633 $ hg shelve --cleanup --patch
634 abort: options '--cleanup' and '--patch' may not be used together
634 abort: options '--cleanup' and '--patch' may not be used together
635 [255]
635 [255]
636 $ hg shelve --cleanup --message MESSAGE
636 $ hg shelve --cleanup --message MESSAGE
637 abort: options '--cleanup' and '--message' may not be used together
637 abort: options '--cleanup' and '--message' may not be used together
638 [255]
638 [255]
639
639
640 test bookmarks
640 test bookmarks
641
641
642 $ hg bookmark test
642 $ hg bookmark test
643 $ hg bookmark
643 $ hg bookmark
644 \* test (4|13):33f7f61e6c5e (re)
644 \* test (4|13):33f7f61e6c5e (re)
645 $ hg shelve
645 $ hg shelve
646 shelved as test
646 shelved as test
647 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
647 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
648 $ hg bookmark
648 $ hg bookmark
649 \* test (4|13):33f7f61e6c5e (re)
649 \* test (4|13):33f7f61e6c5e (re)
650 $ hg unshelve
650 $ hg unshelve
651 unshelving change 'test'
651 unshelving change 'test'
652 $ hg bookmark
652 $ hg bookmark
653 \* test (4|13):33f7f61e6c5e (re)
653 \* test (4|13):33f7f61e6c5e (re)
654
654
655 shelve should still work even if mq is disabled
655 shelve should still work even if mq is disabled
656
656
657 $ hg --config extensions.mq=! shelve
657 $ hg --config extensions.mq=! shelve
658 shelved as test
658 shelved as test
659 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
660 $ hg --config extensions.mq=! shelve --list
660 $ hg --config extensions.mq=! shelve --list
661 test (*)* changes to: create conflict (glob)
661 test (*)* changes to: create conflict (glob)
662 $ hg bookmark
662 $ hg bookmark
663 \* test (4|13):33f7f61e6c5e (re)
663 \* test (4|13):33f7f61e6c5e (re)
664 $ hg --config extensions.mq=! unshelve
664 $ hg --config extensions.mq=! unshelve
665 unshelving change 'test'
665 unshelving change 'test'
666 $ hg bookmark
666 $ hg bookmark
667 \* test (4|13):33f7f61e6c5e (re)
667 \* test (4|13):33f7f61e6c5e (re)
668
668
669 Recreate some conflict again
669 Recreate some conflict again
670
670
671 $ hg up -C -r 2e69b451d1ea
671 $ hg up -C -r 2e69b451d1ea
672 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
672 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
673 (leaving bookmark test)
673 (leaving bookmark test)
674 $ echo y >> a/a
674 $ echo y >> a/a
675 $ hg shelve
675 $ hg shelve
676 shelved as default
676 shelved as default
677 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
677 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
678 $ hg up test
678 $ hg up test
679 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
679 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
680 (activating bookmark test)
680 (activating bookmark test)
681 $ hg bookmark
681 $ hg bookmark
682 \* test (4|13):33f7f61e6c5e (re)
682 \* test (4|13):33f7f61e6c5e (re)
683 $ hg unshelve
683 $ hg unshelve
684 unshelving change 'default'
684 unshelving change 'default'
685 rebasing shelved changes
685 rebasing shelved changes
686 merging a/a
686 merging a/a
687 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
687 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
688 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
688 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
689 [1]
689 [1]
690 $ hg bookmark
690 $ hg bookmark
691 test (4|13):33f7f61e6c5e (re)
691 test (4|13):33f7f61e6c5e (re)
692
692
693 Test that resolving all conflicts in one direction (so that the rebase
693 Test that resolving all conflicts in one direction (so that the rebase
694 is a no-op), works (issue4398)
694 is a no-op), works (issue4398)
695
695
696 $ hg revert -a -r .
696 $ hg revert -a -r .
697 reverting a/a
697 reverting a/a
698 $ hg resolve -m a/a
698 $ hg resolve -m a/a
699 (no more unresolved files)
699 (no more unresolved files)
700 continue: hg unshelve --continue
700 continue: hg unshelve --continue
701 $ hg unshelve -c
701 $ hg unshelve -c
702 note: unshelved changes already existed in the working copy
702 note: unshelved changes already existed in the working copy
703 unshelve of 'default' complete
703 unshelve of 'default' complete
704 $ hg bookmark
704 $ hg bookmark
705 \* test (4|13):33f7f61e6c5e (re)
705 \* test (4|13):33f7f61e6c5e (re)
706 $ hg diff
706 $ hg diff
707 $ hg status
707 $ hg status
708 ? a/a.orig
708 ? a/a.orig
709 ? foo/foo
709 ? foo/foo
710 $ hg summary
710 $ hg summary
711 parent: (4|13):33f7f61e6c5e tip (re)
711 parent: (4|13):33f7f61e6c5e tip (re)
712 create conflict
712 create conflict
713 branch: default
713 branch: default
714 bookmarks: *test
714 bookmarks: *test
715 commit: 2 unknown (clean)
715 commit: 2 unknown (clean)
716 update: (current)
716 update: (current)
717 phases: 5 draft
717 phases: 5 draft
718
718
719 $ hg shelve --delete --stat
719 $ hg shelve --delete --stat
720 abort: options '--delete' and '--stat' may not be used together
720 abort: options '--delete' and '--stat' may not be used together
721 [255]
721 [255]
722 $ hg shelve --delete --name NAME
722 $ hg shelve --delete --name NAME
723 abort: options '--delete' and '--name' may not be used together
723 abort: options '--delete' and '--name' may not be used together
724 [255]
724 [255]
725
725
726 Test interactive shelve
726 Test interactive shelve
727 $ cat <<EOF >> $HGRCPATH
727 $ cat <<EOF >> $HGRCPATH
728 > [ui]
728 > [ui]
729 > interactive = true
729 > interactive = true
730 > EOF
730 > EOF
731 $ echo 'a' >> a/b
731 $ echo 'a' >> a/b
732 $ cat a/a >> a/b
732 $ cat a/a >> a/b
733 $ echo 'x' >> a/b
733 $ echo 'x' >> a/b
734 $ mv a/b a/a
734 $ mv a/b a/a
735 $ echo 'a' >> foo/foo
735 $ echo 'a' >> foo/foo
736 $ hg st
736 $ hg st
737 M a/a
737 M a/a
738 ? a/a.orig
738 ? a/a.orig
739 ? foo/foo
739 ? foo/foo
740 $ cat a/a
740 $ cat a/a
741 a
741 a
742 a
742 a
743 c
743 c
744 x
744 x
745 x
745 x
746 $ cat foo/foo
746 $ cat foo/foo
747 foo
747 foo
748 a
748 a
749 $ hg shelve --interactive --config ui.interactive=false
749 $ hg shelve --interactive --config ui.interactive=false
750 abort: running non-interactively
750 abort: running non-interactively
751 [255]
751 [255]
752 $ hg shelve --interactive << EOF
752 $ hg shelve --interactive << EOF
753 > y
753 > y
754 > y
754 > y
755 > n
755 > n
756 > EOF
756 > EOF
757 diff --git a/a/a b/a/a
757 diff --git a/a/a b/a/a
758 2 hunks, 2 lines changed
758 2 hunks, 2 lines changed
759 examine changes to 'a/a'?
759 examine changes to 'a/a'?
760 (enter ? for help) [Ynesfdaq?] y
760 (enter ? for help) [Ynesfdaq?] y
761
761
762 @@ -1,3 +1,4 @@
762 @@ -1,3 +1,4 @@
763 +a
763 +a
764 a
764 a
765 c
765 c
766 x
766 x
767 record change 1/2 to 'a/a'?
767 record change 1/2 to 'a/a'?
768 (enter ? for help) [Ynesfdaq?] y
768 (enter ? for help) [Ynesfdaq?] y
769
769
770 @@ -1,3 +2,4 @@
770 @@ -1,3 +2,4 @@
771 a
771 a
772 c
772 c
773 x
773 x
774 +x
774 +x
775 record change 2/2 to 'a/a'?
775 record change 2/2 to 'a/a'?
776 (enter ? for help) [Ynesfdaq?] n
776 (enter ? for help) [Ynesfdaq?] n
777
777
778 shelved as test
778 shelved as test
779 merging a/a
779 merging a/a
780 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
780 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
781 $ cat a/a
781 $ cat a/a
782 a
782 a
783 c
783 c
784 x
784 x
785 x
785 x
786 $ cat foo/foo
786 $ cat foo/foo
787 foo
787 foo
788 a
788 a
789 $ hg st
789 $ hg st
790 M a/a
790 M a/a
791 ? foo/foo
791 ? foo/foo
792 $ hg bookmark
792 $ hg bookmark
793 \* test (4|13):33f7f61e6c5e (re)
793 \* test (4|13):33f7f61e6c5e (re)
794 $ hg unshelve
794 $ hg unshelve
795 unshelving change 'test'
795 unshelving change 'test'
796 temporarily committing pending changes (restore with 'hg unshelve --abort')
796 temporarily committing pending changes (restore with 'hg unshelve --abort')
797 rebasing shelved changes
797 rebasing shelved changes
798 merging a/a
798 merging a/a
799 $ hg bookmark
799 $ hg bookmark
800 \* test (4|13):33f7f61e6c5e (re)
800 \* test (4|13):33f7f61e6c5e (re)
801 $ cat a/a
801 $ cat a/a
802 a
802 a
803 a
803 a
804 c
804 c
805 x
805 x
806 x
806 x
807
807
808 shelve --patch and shelve --stat should work with valid shelfnames
808 shelve --patch and shelve --stat should work with valid shelfnames
809
809
810 $ hg up --clean .
810 $ hg up --clean .
811 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
811 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
812 (leaving bookmark test)
812 (leaving bookmark test)
813 $ hg shelve --list
813 $ hg shelve --list
814 $ echo 'patch a' > shelf-patch-a
814 $ echo 'patch a' > shelf-patch-a
815 $ hg add shelf-patch-a
815 $ hg add shelf-patch-a
816 $ hg shelve
816 $ hg shelve
817 shelved as default
817 shelved as default
818 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
818 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
819 $ echo 'patch b' > shelf-patch-b
819 $ echo 'patch b' > shelf-patch-b
820 $ hg add shelf-patch-b
820 $ hg add shelf-patch-b
821 $ hg shelve
821 $ hg shelve
822 shelved as default-01
822 shelved as default-01
823 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
823 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
824 $ hg shelve --patch default default-01
824 $ hg shelve --patch default default-01
825 default-01 (*)* changes to: create conflict (glob)
825 default-01 (*)* changes to: create conflict (glob)
826
826
827 diff --git a/shelf-patch-b b/shelf-patch-b
827 diff --git a/shelf-patch-b b/shelf-patch-b
828 new file mode 100644
828 new file mode 100644
829 --- /dev/null
829 --- /dev/null
830 +++ b/shelf-patch-b
830 +++ b/shelf-patch-b
831 @@ -0,0 +1,1 @@
831 @@ -0,0 +1,1 @@
832 +patch b
832 +patch b
833 default (*)* changes to: create conflict (glob)
833 default (*)* changes to: create conflict (glob)
834
834
835 diff --git a/shelf-patch-a b/shelf-patch-a
835 diff --git a/shelf-patch-a b/shelf-patch-a
836 new file mode 100644
836 new file mode 100644
837 --- /dev/null
837 --- /dev/null
838 +++ b/shelf-patch-a
838 +++ b/shelf-patch-a
839 @@ -0,0 +1,1 @@
839 @@ -0,0 +1,1 @@
840 +patch a
840 +patch a
841 $ hg shelve --stat default default-01
841 $ hg shelve --stat default default-01
842 default-01 (*)* changes to: create conflict (glob)
842 default-01 (*)* changes to: create conflict (glob)
843 shelf-patch-b | 1 +
843 shelf-patch-b | 1 +
844 1 files changed, 1 insertions(+), 0 deletions(-)
844 1 files changed, 1 insertions(+), 0 deletions(-)
845 default (*)* changes to: create conflict (glob)
845 default (*)* changes to: create conflict (glob)
846 shelf-patch-a | 1 +
846 shelf-patch-a | 1 +
847 1 files changed, 1 insertions(+), 0 deletions(-)
847 1 files changed, 1 insertions(+), 0 deletions(-)
848 $ hg shelve --patch default
848 $ hg shelve --patch default
849 default (*)* changes to: create conflict (glob)
849 default (*)* changes to: create conflict (glob)
850
850
851 diff --git a/shelf-patch-a b/shelf-patch-a
851 diff --git a/shelf-patch-a b/shelf-patch-a
852 new file mode 100644
852 new file mode 100644
853 --- /dev/null
853 --- /dev/null
854 +++ b/shelf-patch-a
854 +++ b/shelf-patch-a
855 @@ -0,0 +1,1 @@
855 @@ -0,0 +1,1 @@
856 +patch a
856 +patch a
857 $ hg shelve --stat default
857 $ hg shelve --stat default
858 default (*)* changes to: create conflict (glob)
858 default (*)* changes to: create conflict (glob)
859 shelf-patch-a | 1 +
859 shelf-patch-a | 1 +
860 1 files changed, 1 insertions(+), 0 deletions(-)
860 1 files changed, 1 insertions(+), 0 deletions(-)
861 $ hg shelve --patch nonexistentshelf
861 $ hg shelve --patch nonexistentshelf
862 abort: cannot find shelf nonexistentshelf
862 abort: cannot find shelf nonexistentshelf
863 [255]
863 [255]
864 $ hg shelve --stat nonexistentshelf
864 $ hg shelve --stat nonexistentshelf
865 abort: cannot find shelf nonexistentshelf
865 abort: cannot find shelf nonexistentshelf
866 [255]
866 [255]
867 $ hg shelve --patch default nonexistentshelf
867 $ hg shelve --patch default nonexistentshelf
868 abort: cannot find shelf nonexistentshelf
868 abort: cannot find shelf nonexistentshelf
869 [255]
869 [255]
870
870
871 when the user asks for a patch, we assume they want the most recent shelve if
871 when the user asks for a patch, we assume they want the most recent shelve if
872 they don't provide a shelve name
872 they don't provide a shelve name
873
873
874 $ hg shelve --patch
874 $ hg shelve --patch
875 default-01 (*)* changes to: create conflict (glob)
875 default-01 (*)* changes to: create conflict (glob)
876
876
877 diff --git a/shelf-patch-b b/shelf-patch-b
877 diff --git a/shelf-patch-b b/shelf-patch-b
878 new file mode 100644
878 new file mode 100644
879 --- /dev/null
879 --- /dev/null
880 +++ b/shelf-patch-b
880 +++ b/shelf-patch-b
881 @@ -0,0 +1,1 @@
881 @@ -0,0 +1,1 @@
882 +patch b
882 +patch b
883
883
884 $ cd ..
884 $ cd ..
885
885
886 Shelve from general delta repo uses bundle2 on disk
886 Shelve from general delta repo uses bundle2 on disk
887 --------------------------------------------------
887 --------------------------------------------------
888
888
889 no general delta
889 no general delta
890
890
891 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
891 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
892 requesting all changes
892 requesting all changes
893 adding changesets
893 adding changesets
894 adding manifests
894 adding manifests
895 adding file changes
895 adding file changes
896 added 5 changesets with 8 changes to 6 files
896 added 5 changesets with 8 changes to 6 files
897 new changesets cc01e2b0c59f:33f7f61e6c5e
897 new changesets cc01e2b0c59f:33f7f61e6c5e
898 updating to branch default
898 updating to branch default
899 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
899 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
900 $ cd bundle1
900 $ cd bundle1
901 $ echo babar > jungle
901 $ echo babar > jungle
902 $ hg add jungle
902 $ hg add jungle
903 $ hg shelve
903 $ hg shelve
904 shelved as default
904 shelved as default
905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
906 $ hg debugbundle .hg/shelved/*.hg
906 $ hg debugbundle .hg/shelved/*.hg
907 330882a04d2ce8487636b1fb292e5beea77fa1e3
907 330882a04d2ce8487636b1fb292e5beea77fa1e3
908 $ cd ..
908 $ cd ..
909
909
910 with general delta
910 with general delta
911
911
912 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
912 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
913 requesting all changes
913 requesting all changes
914 adding changesets
914 adding changesets
915 adding manifests
915 adding manifests
916 adding file changes
916 adding file changes
917 added 5 changesets with 8 changes to 6 files
917 added 5 changesets with 8 changes to 6 files
918 new changesets cc01e2b0c59f:33f7f61e6c5e
918 new changesets cc01e2b0c59f:33f7f61e6c5e
919 updating to branch default
919 updating to branch default
920 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
920 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
921 $ cd bundle2
921 $ cd bundle2
922 $ echo babar > jungle
922 $ echo babar > jungle
923 $ hg add jungle
923 $ hg add jungle
924 $ hg shelve
924 $ hg shelve
925 shelved as default
925 shelved as default
926 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
926 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
927 $ hg debugbundle .hg/shelved/*.hg
927 $ hg debugbundle .hg/shelved/*.hg
928 Stream params: {Compression: BZ}
928 Stream params: {Compression: BZ}
929 changegroup -- {nbchanges: 1, version: 02} (mandatory: True)
929 changegroup -- {nbchanges: 1, version: 02} (mandatory: True)
930 330882a04d2ce8487636b1fb292e5beea77fa1e3
930 330882a04d2ce8487636b1fb292e5beea77fa1e3
931
931
932 Test shelve --keep
932 Test shelve --keep
933
933
934 $ hg unshelve
934 $ hg unshelve
935 unshelving change 'default'
935 unshelving change 'default'
936 $ hg shelve --keep --list
936 $ hg shelve --keep --list
937 abort: options '--list' and '--keep' may not be used together
937 abort: options '--list' and '--keep' may not be used together
938 [255]
938 [255]
939 $ hg shelve --keep --patch
939 $ hg shelve --keep --patch
940 abort: options '--patch' and '--keep' may not be used together
940 abort: options '--patch' and '--keep' may not be used together
941 [255]
941 [255]
942 $ hg shelve --keep --delete
942 $ hg shelve --keep --delete
943 abort: options '--delete' and '--keep' may not be used together
943 abort: options '--delete' and '--keep' may not be used together
944 [255]
944 [255]
945 $ hg shelve --keep
945 $ hg shelve --keep
946 shelved as default
946 shelved as default
947 $ hg diff
947 $ hg diff
948 diff --git a/jungle b/jungle
948 diff --git a/jungle b/jungle
949 new file mode 100644
949 new file mode 100644
950 --- /dev/null
950 --- /dev/null
951 +++ b/jungle
951 +++ b/jungle
952 @@ -0,0 +1,1 @@
952 @@ -0,0 +1,1 @@
953 +babar
953 +babar
954 $ cd ..
954 $ cd ..
955
955
956 Test visibility of in-memory changes inside transaction to external hook
956 Test visibility of in-memory changes inside transaction to external hook
957 ------------------------------------------------------------------------
957 ------------------------------------------------------------------------
958
958
959 $ cd repo
959 $ cd repo
960
960
961 $ echo xxxx >> x
961 $ echo xxxx >> x
962 $ hg commit -m "#5: changes to invoke rebase"
962 $ hg commit -m "#5: changes to invoke rebase"
963
963
964 $ cat > $TESTTMP/checkvisibility.sh <<EOF
964 $ cat > $TESTTMP/checkvisibility.sh <<EOF
965 > echo "==== \$1:"
965 > echo "==== \$1:"
966 > hg parents --template "VISIBLE {rev}:{node|short}\n"
966 > hg parents --template "VISIBLE {rev}:{node|short}\n"
967 > # test that pending changes are hidden
967 > # test that pending changes are hidden
968 > unset HG_PENDING
968 > unset HG_PENDING
969 > hg parents --template "ACTUAL {rev}:{node|short}\n"
969 > hg parents --template "ACTUAL {rev}:{node|short}\n"
970 > echo "===="
970 > echo "===="
971 > EOF
971 > EOF
972
972
973 $ cat >> .hg/hgrc <<EOF
973 $ cat >> .hg/hgrc <<EOF
974 > [defaults]
974 > [defaults]
975 > # to fix hash id of temporary revisions
975 > # to fix hash id of temporary revisions
976 > unshelve = --date '0 0'
976 > unshelve = --date '0 0'
977 > EOF
977 > EOF
978
978
979 "hg unshelve" at REV5 implies steps below:
979 "hg unshelve" at REV5 implies steps below:
980
980
981 (1) commit changes in the working directory (REV6)
981 (1) commit changes in the working directory (REV6)
982 (2) unbundle shelved revision (REV7)
982 (2) unbundle shelved revision (REV7)
983 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
983 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
984 (4) rebase: commit merged revision (REV8)
984 (4) rebase: commit merged revision (REV8)
985 (5) rebase: update to REV6 (REV8 => REV6)
985 (5) rebase: update to REV6 (REV8 => REV6)
986 (6) update to REV5 (REV6 => REV5)
986 (6) update to REV5 (REV6 => REV5)
987 (7) abort transaction
987 (7) abort transaction
988
988
989 == test visibility to external preupdate hook
989 == test visibility to external preupdate hook
990
990
991 $ cat >> .hg/hgrc <<EOF
991 $ cat >> .hg/hgrc <<EOF
992 > [hooks]
992 > [hooks]
993 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
993 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
994 > EOF
994 > EOF
995
995
996 $ echo nnnn >> n
996 $ echo nnnn >> n
997
997
998 $ sh $TESTTMP/checkvisibility.sh before-unshelving
998 $ sh $TESTTMP/checkvisibility.sh before-unshelving
999 ==== before-unshelving:
999 ==== before-unshelving:
1000 VISIBLE (5|19):703117a2acfb (re)
1000 VISIBLE (5|19):703117a2acfb (re)
1001 ACTUAL (5|19):703117a2acfb (re)
1001 ACTUAL (5|19):703117a2acfb (re)
1002 ====
1002 ====
1003
1003
1004 $ hg unshelve --keep default
1004 $ hg unshelve --keep default
1005 temporarily committing pending changes (restore with 'hg unshelve --abort')
1005 temporarily committing pending changes (restore with 'hg unshelve --abort')
1006 rebasing shelved changes
1006 rebasing shelved changes
1007 ==== preupdate:
1007 ==== preupdate:
1008 VISIBLE (6|20):54c00d20fb3f (re)
1008 VISIBLE (6|20):54c00d20fb3f (re)
1009 ACTUAL (5|19):703117a2acfb (re)
1009 ACTUAL (5|19):703117a2acfb (re)
1010 ====
1010 ====
1011 ==== preupdate:
1011 ==== preupdate:
1012 VISIBLE (8|21):8efe6f7537dc (re)
1012 VISIBLE (8|21):8efe6f7537dc (re)
1013 ACTUAL (5|19):703117a2acfb (re)
1013 ACTUAL (5|19):703117a2acfb (re)
1014 ====
1014 ====
1015 ==== preupdate:
1015 ==== preupdate:
1016 VISIBLE (6|20):54c00d20fb3f (re)
1016 VISIBLE (6|20):54c00d20fb3f (re)
1017 ACTUAL (5|19):703117a2acfb (re)
1017 ACTUAL (5|19):703117a2acfb (re)
1018 ====
1018 ====
1019
1019
1020 $ cat >> .hg/hgrc <<EOF
1020 $ cat >> .hg/hgrc <<EOF
1021 > [hooks]
1021 > [hooks]
1022 > preupdate.visibility =
1022 > preupdate.visibility =
1023 > EOF
1023 > EOF
1024
1024
1025 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1025 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1026 ==== after-unshelving:
1026 ==== after-unshelving:
1027 VISIBLE (5|19):703117a2acfb (re)
1027 VISIBLE (5|19):703117a2acfb (re)
1028 ACTUAL (5|19):703117a2acfb (re)
1028 ACTUAL (5|19):703117a2acfb (re)
1029 ====
1029 ====
1030
1030
1031 == test visibility to external update hook
1031 == test visibility to external update hook
1032
1032
1033 $ hg update -q -C 703117a2acfb
1033 $ hg update -q -C 703117a2acfb
1034
1034
1035 $ cat >> .hg/hgrc <<EOF
1035 $ cat >> .hg/hgrc <<EOF
1036 > [hooks]
1036 > [hooks]
1037 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1037 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1038 > EOF
1038 > EOF
1039
1039
1040 $ echo nnnn >> n
1040 $ echo nnnn >> n
1041
1041
1042 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1042 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1043 ==== before-unshelving:
1043 ==== before-unshelving:
1044 VISIBLE (5|19):703117a2acfb (re)
1044 VISIBLE (5|19):703117a2acfb (re)
1045 ACTUAL (5|19):703117a2acfb (re)
1045 ACTUAL (5|19):703117a2acfb (re)
1046 ====
1046 ====
1047
1047
1048 $ hg unshelve --keep default
1048 $ hg unshelve --keep default
1049 temporarily committing pending changes (restore with 'hg unshelve --abort')
1049 temporarily committing pending changes (restore with 'hg unshelve --abort')
1050 rebasing shelved changes
1050 rebasing shelved changes
1051 ==== update:
1051 ==== update:
1052 VISIBLE (6|20):54c00d20fb3f (re)
1052 VISIBLE (6|20):54c00d20fb3f (re)
1053 VISIBLE 1?7:492ed9d705e5 (re)
1053 VISIBLE 1?7:492ed9d705e5 (re)
1054 ACTUAL (5|19):703117a2acfb (re)
1054 ACTUAL (5|19):703117a2acfb (re)
1055 ====
1055 ====
1056 ==== update:
1056 ==== update:
1057 VISIBLE (6|20):54c00d20fb3f (re)
1057 VISIBLE (6|20):54c00d20fb3f (re)
1058 ACTUAL (5|19):703117a2acfb (re)
1058 ACTUAL (5|19):703117a2acfb (re)
1059 ====
1059 ====
1060 ==== update:
1060 ==== update:
1061 VISIBLE (5|19):703117a2acfb (re)
1061 VISIBLE (5|19):703117a2acfb (re)
1062 ACTUAL (5|19):703117a2acfb (re)
1062 ACTUAL (5|19):703117a2acfb (re)
1063 ====
1063 ====
1064
1064
1065 $ cat >> .hg/hgrc <<EOF
1065 $ cat >> .hg/hgrc <<EOF
1066 > [hooks]
1066 > [hooks]
1067 > update.visibility =
1067 > update.visibility =
1068 > EOF
1068 > EOF
1069
1069
1070 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1070 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1071 ==== after-unshelving:
1071 ==== after-unshelving:
1072 VISIBLE (5|19):703117a2acfb (re)
1072 VISIBLE (5|19):703117a2acfb (re)
1073 ACTUAL (5|19):703117a2acfb (re)
1073 ACTUAL (5|19):703117a2acfb (re)
1074 ====
1074 ====
1075
1075
1076 $ cd ..
1076 $ cd ..
1077
1077
1078 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1078 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1079 -----------------------------------------------------------------------
1079 -----------------------------------------------------------------------
1080
1080
1081 $ cat <<EOF >> $HGRCPATH
1081 $ cat <<EOF >> $HGRCPATH
1082 > [extensions]
1082 > [extensions]
1083 > share =
1083 > share =
1084 > EOF
1084 > EOF
1085
1085
1086 $ hg bookmarks -R repo
1086 $ hg bookmarks -R repo
1087 test (4|13):33f7f61e6c5e (re)
1087 test (4|13):33f7f61e6c5e (re)
1088 $ hg share -B repo share
1088 $ hg share -B repo share
1089 updating working directory
1089 updating working directory
1090 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1090 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1091 $ cd share
1091 $ cd share
1092
1092
1093 $ hg bookmarks
1093 $ hg bookmarks
1094 test (4|13):33f7f61e6c5e (re)
1094 test (4|13):33f7f61e6c5e (re)
1095 $ hg bookmarks foo
1095 $ hg bookmarks foo
1096 $ hg bookmarks
1096 $ hg bookmarks
1097 \* foo (5|19):703117a2acfb (re)
1097 \* foo (5|19):703117a2acfb (re)
1098 test (4|13):33f7f61e6c5e (re)
1098 test (4|13):33f7f61e6c5e (re)
1099 $ echo x >> x
1099 $ echo x >> x
1100 $ hg shelve
1100 $ hg shelve
1101 shelved as foo
1101 shelved as foo
1102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1103 $ hg bookmarks
1103 $ hg bookmarks
1104 \* foo (5|19):703117a2acfb (re)
1104 \* foo (5|19):703117a2acfb (re)
1105 test (4|13):33f7f61e6c5e (re)
1105 test (4|13):33f7f61e6c5e (re)
1106
1106
1107 $ hg unshelve
1107 $ hg unshelve
1108 unshelving change 'foo'
1108 unshelving change 'foo'
1109 $ hg bookmarks
1109 $ hg bookmarks
1110 \* foo (5|19):703117a2acfb (re)
1110 \* foo (5|19):703117a2acfb (re)
1111 test (4|13):33f7f61e6c5e (re)
1111 test (4|13):33f7f61e6c5e (re)
1112
1112
1113 $ cd ..
1113 $ cd ..
1114
1114
1115 Abort unshelve while merging (issue5123)
1115 Abort unshelve while merging (issue5123)
1116 ----------------------------------------
1116 ----------------------------------------
1117
1117
1118 $ hg init issue5123
1118 $ hg init issue5123
1119 $ cd issue5123
1119 $ cd issue5123
1120 $ echo > a
1120 $ echo > a
1121 $ hg ci -Am a
1121 $ hg ci -Am a
1122 adding a
1122 adding a
1123 $ hg co null
1123 $ hg co null
1124 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1124 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1125 $ echo > b
1125 $ echo > b
1126 $ hg ci -Am b
1126 $ hg ci -Am b
1127 adding b
1127 adding b
1128 created new head
1128 created new head
1129 $ echo > c
1129 $ echo > c
1130 $ hg add c
1130 $ hg add c
1131 $ hg shelve
1131 $ hg shelve
1132 shelved as default
1132 shelved as default
1133 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1133 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1134 $ hg co 1
1134 $ hg co 1
1135 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1135 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1136 $ hg merge 0
1136 $ hg merge 0
1137 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1137 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1138 (branch merge, don't forget to commit)
1138 (branch merge, don't forget to commit)
1139 -- successful merge with two parents
1139 -- successful merge with two parents
1140 $ hg log -G
1140 $ hg log -G
1141 @ changeset: 1:406bf70c274f
1141 @ changeset: 1:406bf70c274f
1142 tag: tip
1142 tag: tip
1143 parent: -1:000000000000
1143 parent: -1:000000000000
1144 user: test
1144 user: test
1145 date: Thu Jan 01 00:00:00 1970 +0000
1145 date: Thu Jan 01 00:00:00 1970 +0000
1146 summary: b
1146 summary: b
1147
1147
1148 @ changeset: 0:ada8c9eb8252
1148 @ changeset: 0:ada8c9eb8252
1149 user: test
1149 user: test
1150 date: Thu Jan 01 00:00:00 1970 +0000
1150 date: Thu Jan 01 00:00:00 1970 +0000
1151 summary: a
1151 summary: a
1152
1152
1153 -- trying to pull in the shelve bits
1153 -- trying to pull in the shelve bits
1154 -- unshelve should abort otherwise, it'll eat my second parent.
1154 -- unshelve should abort otherwise, it'll eat my second parent.
1155 $ hg unshelve
1155 $ hg unshelve
1156 abort: outstanding uncommitted merge
1156 abort: outstanding uncommitted merge
1157 (use 'hg commit' or 'hg merge --abort')
1157 (use 'hg commit' or 'hg merge --abort')
1158 [255]
1158 [255]
1159
1159
1160 $ cd ..
1160 $ cd ..
1161
1161
1162 -- test for interactive mode on unshelve
1162 -- test for interactive mode on unshelve
1163
1163
1164 $ hg init a
1164 $ hg init a
1165 $ cd a
1165 $ cd a
1166 $ echo > b
1166 $ echo > b
1167 $ hg ci -Am b
1167 $ hg ci -Am b
1168 adding b
1168 adding b
1169 $ echo > c
1169 $ echo > c
1170 $ echo > d
1170 $ echo > d
1171 $ hg add .
1171 $ hg add .
1172 adding c
1172 adding c
1173 adding d
1173 adding d
1174 $ hg shelve
1174 $ hg shelve
1175 shelved as default
1175 shelved as default
1176 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1176 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1177 $ echo > e
1177 $ echo > e
1178 $ hg add e
1178 $ hg add e
1179 $ hg ci -m e
1179 $ hg ci -m e
1180 $ hg shelve --patch
1180 $ hg shelve --patch
1181 default (*s ago) changes to: b (glob)
1181 default (*s ago) changes to: b (glob)
1182
1182
1183 diff --git a/c b/c
1183 diff --git a/c b/c
1184 new file mode 100644
1184 new file mode 100644
1185 --- /dev/null
1185 --- /dev/null
1186 +++ b/c
1186 +++ b/c
1187 @@ -0,0 +1,1 @@
1187 @@ -0,0 +1,1 @@
1188 +
1188 +
1189 diff --git a/d b/d
1189 diff --git a/d b/d
1190 new file mode 100644
1190 new file mode 100644
1191 --- /dev/null
1191 --- /dev/null
1192 +++ b/d
1192 +++ b/d
1193 @@ -0,0 +1,1 @@
1193 @@ -0,0 +1,1 @@
1194 +
1194 +
1195 $ hg unshelve -i <<EOF
1195 $ hg unshelve -i <<EOF
1196 > y
1196 > y
1197 > y
1197 > y
1198 > y
1198 > y
1199 > n
1199 > n
1200 > EOF
1200 > EOF
1201 unshelving change 'default'
1201 unshelving change 'default'
1202 rebasing shelved changes
1202 rebasing shelved changes
1203 diff --git a/c b/c
1203 diff --git a/c b/c
1204 new file mode 100644
1204 new file mode 100644
1205 examine changes to 'c'?
1205 examine changes to 'c'?
1206 (enter ? for help) [Ynesfdaq?] y
1206 (enter ? for help) [Ynesfdaq?] y
1207
1207
1208 @@ -0,0 +1,1 @@
1208 @@ -0,0 +1,1 @@
1209 +
1209 +
1210 record change 1/2 to 'c'?
1210 record change 1/2 to 'c'?
1211 (enter ? for help) [Ynesfdaq?] y
1211 (enter ? for help) [Ynesfdaq?] y
1212
1212
1213 diff --git a/d b/d
1213 diff --git a/d b/d
1214 new file mode 100644
1214 new file mode 100644
1215 examine changes to 'd'?
1215 examine changes to 'd'?
1216 (enter ? for help) [Ynesfdaq?] y
1216 (enter ? for help) [Ynesfdaq?] y
1217
1217
1218 @@ -0,0 +1,1 @@
1218 @@ -0,0 +1,1 @@
1219 +
1219 +
1220 record change 2/2 to 'd'?
1220 record change 2/2 to 'd'?
1221 (enter ? for help) [Ynesfdaq?] n
1221 (enter ? for help) [Ynesfdaq?] n
1222
1222
1223 $ ls
1223 $ ls
1224 b
1224 b
1225 c
1225 c
1226 e
1226 e
1227 -- shelve should not contain `c` now
1227 -- shelve should not contain `c` now
1228 $ hg shelve --patch
1228 $ hg shelve --patch
1229 default (*s ago) changes to: b (glob)
1229 default (*s ago) changes to: b (glob)
1230
1230
1231 diff --git a/d b/d
1231 diff --git a/d b/d
1232 new file mode 100644
1232 new file mode 100644
1233 --- /dev/null
1233 --- /dev/null
1234 +++ b/d
1234 +++ b/d
1235 @@ -0,0 +1,1 @@
1235 @@ -0,0 +1,1 @@
1236 +
1236 +
1237 $ hg unshelve -i <<EOF
1237 $ hg unshelve -i <<EOF
1238 > y
1238 > y
1239 > y
1239 > y
1240 > EOF
1240 > EOF
1241 unshelving change 'default'
1241 unshelving change 'default'
1242 temporarily committing pending changes (restore with 'hg unshelve --abort')
1242 temporarily committing pending changes (restore with 'hg unshelve --abort')
1243 rebasing shelved changes
1243 rebasing shelved changes
1244 diff --git a/d b/d
1244 diff --git a/d b/d
1245 new file mode 100644
1245 new file mode 100644
1246 examine changes to 'd'?
1246 examine changes to 'd'?
1247 (enter ? for help) [Ynesfdaq?] y
1247 (enter ? for help) [Ynesfdaq?] y
1248
1248
1249 @@ -0,0 +1,1 @@
1249 @@ -0,0 +1,1 @@
1250 +
1250 +
1251 record this change to 'd'?
1251 record this change to 'd'?
1252 (enter ? for help) [Ynesfdaq?] y
1252 (enter ? for help) [Ynesfdaq?] y
1253
1253
1254
1254
1255 $ hg status -v
1255 $ hg status -v
1256 A c
1256 A c
1257 A d
1257 A d
1258 $ ls
1258 $ ls
1259 b
1259 b
1260 c
1260 c
1261 d
1261 d
1262 e
1262 e
1263 $ hg shelve --list
1263 $ hg shelve --list
1264
1264
1265 -- now, unshelve selected changes from a file
1265 -- now, unshelve selected changes from a file
1266
1266
1267 $ echo B > foo
1267 $ echo B > foo
1268 $ hg add foo
1268 $ hg add foo
1269 $ hg ci -m 'add B to foo'
1269 $ hg ci -m 'add B to foo'
1270 $ cat > foo <<EOF
1270 $ cat > foo <<EOF
1271 > A
1271 > A
1272 > B
1272 > B
1273 > C
1273 > C
1274 > EOF
1274 > EOF
1275 $ hg shelve
1275 $ echo > garbage
1276 $ hg st
1277 M foo
1278 ? garbage
1279 $ hg shelve --unknown
1276 shelved as default
1280 shelved as default
1277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1281 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1278 $ cat foo
1282 $ cat foo
1279 B
1283 B
1280 $ hg unshelve -i <<EOF
1284 $ hg unshelve -i <<EOF
1281 > y
1285 > y
1282 > y
1286 > y
1283 > n
1287 > n
1288 > y
1289 > y
1284 > EOF
1290 > EOF
1285 unshelving change 'default'
1291 unshelving change 'default'
1286 rebasing shelved changes
1292 rebasing shelved changes
1287 diff --git a/foo b/foo
1293 diff --git a/foo b/foo
1288 2 hunks, 2 lines changed
1294 2 hunks, 2 lines changed
1289 examine changes to 'foo'?
1295 examine changes to 'foo'?
1290 (enter ? for help) [Ynesfdaq?] y
1296 (enter ? for help) [Ynesfdaq?] y
1291
1297
1292 @@ -1,1 +1,2 @@
1298 @@ -1,1 +1,2 @@
1293 +A
1299 +A
1294 B
1300 B
1295 record change 1/2 to 'foo'?
1301 record change 1/3 to 'foo'?
1296 (enter ? for help) [Ynesfdaq?] y
1302 (enter ? for help) [Ynesfdaq?] y
1297
1303
1298 @@ -1,1 +2,2 @@
1304 @@ -1,1 +2,2 @@
1299 B
1305 B
1300 +C
1306 +C
1301 record change 2/2 to 'foo'?
1307 record change 2/3 to 'foo'?
1302 (enter ? for help) [Ynesfdaq?] n
1308 (enter ? for help) [Ynesfdaq?] n
1303
1309
1310 diff --git a/garbage b/garbage
1311 new file mode 100644
1312 examine changes to 'garbage'?
1313 (enter ? for help) [Ynesfdaq?] y
1314
1315 @@ -0,0 +1,1 @@
1316 +
1317 record change 3/3 to 'garbage'?
1318 (enter ? for help) [Ynesfdaq?] y
1319
1320 $ hg st
1321 M foo
1322 ? garbage
1304 $ cat foo
1323 $ cat foo
1305 A
1324 A
1306 B
1325 B
1307 $ hg shelve --patch
1326 $ hg shelve --patch
1308 default (*s ago) changes to: add B to foo (glob)
1327 default (*s ago) changes to: add B to foo (glob)
1309
1328
1310 diff --git a/foo b/foo
1329 diff --git a/foo b/foo
1311 --- a/foo
1330 --- a/foo
1312 +++ b/foo
1331 +++ b/foo
1313 @@ -1,2 +1,3 @@
1332 @@ -1,2 +1,3 @@
1314 A
1333 A
1315 B
1334 B
1316 +C
1335 +C
1317
1336
1318 -- unshelve interactive on conflicts
1337 -- unshelve interactive on conflicts
1319
1338
1320 $ echo A >> bar1
1339 $ echo A >> bar1
1321 $ echo A >> bar2
1340 $ echo A >> bar2
1322 $ hg add bar1 bar2
1341 $ hg add bar1 bar2
1323 $ hg ci -m 'add A to bars'
1342 $ hg ci -m 'add A to bars'
1324 $ echo B >> bar1
1343 $ echo B >> bar1
1325 $ echo B >> bar2
1344 $ echo B >> bar2
1326 $ hg shelve
1345 $ hg shelve
1327 shelved as default-01
1346 shelved as default-01
1328 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1347 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1329 $ echo C >> bar1
1348 $ echo C >> bar1
1330 $ echo C >> bar2
1349 $ echo C >> bar2
1331 $ hg ci -m 'add C to bars'
1350 $ hg ci -m 'add C to bars'
1332 $ hg unshelve -i
1351 $ hg unshelve -i
1333 unshelving change 'default-01'
1352 unshelving change 'default-01'
1334 rebasing shelved changes
1353 rebasing shelved changes
1335 merging bar1
1354 merging bar1
1336 merging bar2
1355 merging bar2
1337 warning: conflicts while merging bar1! (edit, then use 'hg resolve --mark')
1356 warning: conflicts while merging bar1! (edit, then use 'hg resolve --mark')
1338 warning: conflicts while merging bar2! (edit, then use 'hg resolve --mark')
1357 warning: conflicts while merging bar2! (edit, then use 'hg resolve --mark')
1339 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1358 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1340 [1]
1359 [1]
1341
1360
1342 $ cat > bar1 <<EOF
1361 $ cat > bar1 <<EOF
1343 > A
1362 > A
1344 > B
1363 > B
1345 > C
1364 > C
1346 > EOF
1365 > EOF
1347 $ cat > bar2 <<EOF
1366 $ cat > bar2 <<EOF
1348 > A
1367 > A
1349 > B
1368 > B
1350 > C
1369 > C
1351 > EOF
1370 > EOF
1352 $ hg resolve -m bar1 bar2
1371 $ hg resolve -m bar1 bar2
1353 (no more unresolved files)
1372 (no more unresolved files)
1354 continue: hg unshelve --continue
1373 continue: hg unshelve --continue
1355
1374
1356 -- using --continue with --interactive should throw an error
1375 -- using --continue with --interactive should throw an error
1357 $ hg unshelve --continue -i
1376 $ hg unshelve --continue -i
1358 abort: cannot use both continue and interactive
1377 abort: cannot use both continue and interactive
1359 [255]
1378 [255]
1360
1379
1361 $ cat bar1
1380 $ cat bar1
1362 A
1381 A
1363 B
1382 B
1364 C
1383 C
1365
1384
1366 #if stripbased
1385 #if stripbased
1367 $ hg log -r 3:: -G
1386 $ hg log -r 3:: -G
1368 @ changeset: 5:f1d5f53e397b
1387 @ changeset: 5:f1d5f53e397b
1369 | tag: tip
1388 | tag: tip
1370 | parent: 3:e28fd7fa7938
1389 | parent: 3:e28fd7fa7938
1371 | user: shelve@localhost
1390 | user: shelve@localhost
1372 | date: Thu Jan 01 00:00:00 1970 +0000
1391 | date: Thu Jan 01 00:00:00 1970 +0000
1373 | summary: changes to: add A to bars
1392 | summary: changes to: add A to bars
1374 |
1393 |
1375 | @ changeset: 4:fe451a778c81
1394 | @ changeset: 4:fe451a778c81
1376 |/ user: test
1395 |/ user: test
1377 | date: Thu Jan 01 00:00:00 1970 +0000
1396 | date: Thu Jan 01 00:00:00 1970 +0000
1378 | summary: add C to bars
1397 | summary: add C to bars
1379 |
1398 |
1380 o changeset: 3:e28fd7fa7938
1399 o changeset: 3:e28fd7fa7938
1381 | user: test
1400 | user: test
1382 ~ date: Thu Jan 01 00:00:00 1970 +0000
1401 ~ date: Thu Jan 01 00:00:00 1970 +0000
1383 summary: add A to bars
1402 summary: add A to bars
1384
1403
1385 #endif
1404 #endif
1386
1405
1387 $ hg unshelve --continue <<EOF
1406 $ hg unshelve --continue <<EOF
1388 > y
1407 > y
1389 > y
1408 > y
1390 > y
1409 > y
1391 > n
1410 > n
1392 > EOF
1411 > EOF
1393 diff --git a/bar1 b/bar1
1412 diff --git a/bar1 b/bar1
1394 1 hunks, 1 lines changed
1413 1 hunks, 1 lines changed
1395 examine changes to 'bar1'?
1414 examine changes to 'bar1'?
1396 (enter ? for help) [Ynesfdaq?] y
1415 (enter ? for help) [Ynesfdaq?] y
1397
1416
1398 @@ -1,2 +1,3 @@
1417 @@ -1,2 +1,3 @@
1399 A
1418 A
1400 +B
1419 +B
1401 C
1420 C
1402 record change 1/2 to 'bar1'?
1421 record change 1/2 to 'bar1'?
1403 (enter ? for help) [Ynesfdaq?] y
1422 (enter ? for help) [Ynesfdaq?] y
1404
1423
1405 diff --git a/bar2 b/bar2
1424 diff --git a/bar2 b/bar2
1406 1 hunks, 1 lines changed
1425 1 hunks, 1 lines changed
1407 examine changes to 'bar2'?
1426 examine changes to 'bar2'?
1408 (enter ? for help) [Ynesfdaq?] y
1427 (enter ? for help) [Ynesfdaq?] y
1409
1428
1410 @@ -1,2 +1,3 @@
1429 @@ -1,2 +1,3 @@
1411 A
1430 A
1412 +B
1431 +B
1413 C
1432 C
1414 record change 2/2 to 'bar2'?
1433 record change 2/2 to 'bar2'?
1415 (enter ? for help) [Ynesfdaq?] n
1434 (enter ? for help) [Ynesfdaq?] n
1416
1435
1417 unshelve of 'default-01' complete
1436 unshelve of 'default-01' complete
1418
1437
1419 #if stripbased
1438 #if stripbased
1420 $ hg log -r 3:: -G
1439 $ hg log -r 3:: -G
1421 @ changeset: 4:fe451a778c81
1440 @ changeset: 4:fe451a778c81
1422 | tag: tip
1441 | tag: tip
1423 | user: test
1442 | user: test
1424 | date: Thu Jan 01 00:00:00 1970 +0000
1443 | date: Thu Jan 01 00:00:00 1970 +0000
1425 | summary: add C to bars
1444 | summary: add C to bars
1426 |
1445 |
1427 o changeset: 3:e28fd7fa7938
1446 o changeset: 3:e28fd7fa7938
1428 | user: test
1447 | user: test
1429 ~ date: Thu Jan 01 00:00:00 1970 +0000
1448 ~ date: Thu Jan 01 00:00:00 1970 +0000
1430 summary: add A to bars
1449 summary: add A to bars
1431
1450
1432 #endif
1451 #endif
1433
1452
1434 $ hg unshelve --continue
1453 $ hg unshelve --continue
1435 abort: no unshelve in progress
1454 abort: no unshelve in progress
1436 [255]
1455 [255]
1437
1456
1438 $ hg shelve --list
1457 $ hg shelve --list
1439 default-01 (*)* changes to: add A to bars (glob)
1458 default-01 (*)* changes to: add A to bars (glob)
1440 default (*)* changes to: add B to foo (glob)
1459 default (*)* changes to: add B to foo (glob)
1441 $ hg unshelve -n default-01 -i <<EOF
1460 $ hg unshelve -n default-01 -i <<EOF
1442 > y
1461 > y
1443 > y
1462 > y
1444 > EOF
1463 > EOF
1445 temporarily committing pending changes (restore with 'hg unshelve --abort')
1464 temporarily committing pending changes (restore with 'hg unshelve --abort')
1446 rebasing shelved changes
1465 rebasing shelved changes
1447 diff --git a/bar2 b/bar2
1466 diff --git a/bar2 b/bar2
1448 1 hunks, 1 lines changed
1467 1 hunks, 1 lines changed
1449 examine changes to 'bar2'?
1468 examine changes to 'bar2'?
1450 (enter ? for help) [Ynesfdaq?] y
1469 (enter ? for help) [Ynesfdaq?] y
1451
1470
1452 @@ -1,2 +1,3 @@
1471 @@ -1,2 +1,3 @@
1453 A
1472 A
1454 +B
1473 +B
1455 C
1474 C
1456 record this change to 'bar2'?
1475 record this change to 'bar2'?
1457 (enter ? for help) [Ynesfdaq?] y
1476 (enter ? for help) [Ynesfdaq?] y
1458
1477
General Comments 0
You need to be logged in to leave comments. Login now