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