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