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