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