##// END OF EJS Templates
shelve: don't include invalid shelves in `hg shelve --list`...
Martin von Zweigbergk -
r46914:680cc423 default draft
parent child Browse files
Show More
@@ -1,1166 +1,1173 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 .node import (
31 from .node import (
32 bin,
32 bin,
33 hex,
33 hex,
34 nullid,
34 nullid,
35 nullrev,
35 nullrev,
36 )
36 )
37 from . import (
37 from . import (
38 bookmarks,
38 bookmarks,
39 bundle2,
39 bundle2,
40 changegroup,
40 changegroup,
41 cmdutil,
41 cmdutil,
42 discovery,
42 discovery,
43 error,
43 error,
44 exchange,
44 exchange,
45 hg,
45 hg,
46 lock as lockmod,
46 lock as lockmod,
47 mdiff,
47 mdiff,
48 merge,
48 merge,
49 mergestate as mergestatemod,
49 mergestate as mergestatemod,
50 patch,
50 patch,
51 phases,
51 phases,
52 pycompat,
52 pycompat,
53 repair,
53 repair,
54 scmutil,
54 scmutil,
55 templatefilters,
55 templatefilters,
56 util,
56 util,
57 vfs as vfsmod,
57 vfs as vfsmod,
58 )
58 )
59 from .utils import (
59 from .utils import (
60 dateutil,
60 dateutil,
61 stringutil,
61 stringutil,
62 )
62 )
63
63
64 backupdir = b'shelve-backup'
64 backupdir = b'shelve-backup'
65 shelvedir = b'shelved'
65 shelvedir = b'shelved'
66 shelvefileextensions = [b'hg', b'patch', b'shelve']
66 shelvefileextensions = [b'hg', b'patch', b'shelve']
67 # universal extension is present in all types of shelves
67 # universal extension is present in all types of shelves
68 patchextension = b'patch'
68 patchextension = b'patch'
69
69
70 # we never need the user, so we use a
70 # we never need the user, so we use a
71 # generic user for all shelve operations
71 # generic user for all shelve operations
72 shelveuser = b'shelve@localhost'
72 shelveuser = b'shelve@localhost'
73
73
74
74
75 class Shelf(object):
75 class Shelf(object):
76 """Represents a shelf, including possibly multiple files storing it.
76 """Represents a shelf, including possibly multiple files storing it.
77
77
78 Old shelves will have a .patch and a .hg file. Newer shelves will
78 Old shelves will have a .patch and a .hg file. Newer shelves will
79 also have a .shelve file. This class abstracts away some of the
79 also have a .shelve file. This class abstracts away some of the
80 differences and lets you work with the shelf as a whole.
80 differences and lets you work with the shelf as a whole.
81 """
81 """
82
82
83 def __init__(self, repo, name):
83 def __init__(self, repo, name):
84 self.repo = repo
84 self.repo = repo
85 self.name = name
85 self.name = name
86 self.vfs = vfsmod.vfs(repo.vfs.join(shelvedir))
86 self.vfs = vfsmod.vfs(repo.vfs.join(shelvedir))
87 self.backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
87 self.backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
88
88
89 def exists(self):
89 def exists(self):
90 return self.vfs.exists(self.name + b'.' + patchextension)
90 return self.vfs.exists(
91 self.name + b'.' + patchextension
92 ) and self.vfs.exists(self.name + b'.hg')
91
93
92 def mtime(self):
94 def mtime(self):
93 return self.vfs.stat(self.name + b'.' + patchextension)[stat.ST_MTIME]
95 return self.vfs.stat(self.name + b'.' + patchextension)[stat.ST_MTIME]
94
96
95 def writeinfo(self, info):
97 def writeinfo(self, info):
96 scmutil.simplekeyvaluefile(self.vfs, self.name + b'.shelve').write(info)
98 scmutil.simplekeyvaluefile(self.vfs, self.name + b'.shelve').write(info)
97
99
98 def hasinfo(self):
100 def hasinfo(self):
99 return self.vfs.exists(self.name + b'.shelve')
101 return self.vfs.exists(self.name + b'.shelve')
100
102
101 def readinfo(self):
103 def readinfo(self):
102 return scmutil.simplekeyvaluefile(
104 return scmutil.simplekeyvaluefile(
103 self.vfs, self.name + b'.shelve'
105 self.vfs, self.name + b'.shelve'
104 ).read()
106 ).read()
105
107
106 def writebundle(self, bases, node):
108 def writebundle(self, bases, node):
107 cgversion = changegroup.safeversion(self.repo)
109 cgversion = changegroup.safeversion(self.repo)
108 if cgversion == b'01':
110 if cgversion == b'01':
109 btype = b'HG10BZ'
111 btype = b'HG10BZ'
110 compression = None
112 compression = None
111 else:
113 else:
112 btype = b'HG20'
114 btype = b'HG20'
113 compression = b'BZ'
115 compression = b'BZ'
114
116
115 repo = self.repo.unfiltered()
117 repo = self.repo.unfiltered()
116
118
117 outgoing = discovery.outgoing(
119 outgoing = discovery.outgoing(
118 repo, missingroots=bases, ancestorsof=[node]
120 repo, missingroots=bases, ancestorsof=[node]
119 )
121 )
120 cg = changegroup.makechangegroup(repo, outgoing, cgversion, b'shelve')
122 cg = changegroup.makechangegroup(repo, outgoing, cgversion, b'shelve')
121
123
122 bundle_filename = self.vfs.join(self.name + b'.hg')
124 bundle_filename = self.vfs.join(self.name + b'.hg')
123 bundle2.writebundle(
125 bundle2.writebundle(
124 self.repo.ui,
126 self.repo.ui,
125 cg,
127 cg,
126 bundle_filename,
128 bundle_filename,
127 btype,
129 btype,
128 self.vfs,
130 self.vfs,
129 compression=compression,
131 compression=compression,
130 )
132 )
131
133
132 def applybundle(self, tr):
134 def applybundle(self, tr):
133 filename = self.name + b'.hg'
135 filename = self.name + b'.hg'
134 fp = self.vfs(filename)
136 fp = self.vfs(filename)
135 try:
137 try:
136 targetphase = phases.internal
138 targetphase = phases.internal
137 if not phases.supportinternal(self.repo):
139 if not phases.supportinternal(self.repo):
138 targetphase = phases.secret
140 targetphase = phases.secret
139 gen = exchange.readbundle(self.repo.ui, fp, filename, self.vfs)
141 gen = exchange.readbundle(self.repo.ui, fp, filename, self.vfs)
140 pretip = self.repo[b'tip']
142 pretip = self.repo[b'tip']
141 bundle2.applybundle(
143 bundle2.applybundle(
142 self.repo,
144 self.repo,
143 gen,
145 gen,
144 tr,
146 tr,
145 source=b'unshelve',
147 source=b'unshelve',
146 url=b'bundle:' + self.vfs.join(filename),
148 url=b'bundle:' + self.vfs.join(filename),
147 targetphase=targetphase,
149 targetphase=targetphase,
148 )
150 )
149 shelvectx = self.repo[b'tip']
151 shelvectx = self.repo[b'tip']
150 if pretip == shelvectx:
152 if pretip == shelvectx:
151 shelverev = tr.changes[b'revduplicates'][-1]
153 shelverev = tr.changes[b'revduplicates'][-1]
152 shelvectx = self.repo[shelverev]
154 shelvectx = self.repo[shelverev]
153 return shelvectx
155 return shelvectx
154 finally:
156 finally:
155 fp.close()
157 fp.close()
156
158
157 def open_patch(self, mode=b'rb'):
159 def open_patch(self, mode=b'rb'):
158 return self.vfs(self.name + b'.patch', mode)
160 return self.vfs(self.name + b'.patch', mode)
159
161
160 def _backupfilename(self, filename):
162 def _backupfilename(self, filename):
161 def gennames(base):
163 def gennames(base):
162 yield base
164 yield base
163 base, ext = base.rsplit(b'.', 1)
165 base, ext = base.rsplit(b'.', 1)
164 for i in itertools.count(1):
166 for i in itertools.count(1):
165 yield b'%s-%d.%s' % (base, i, ext)
167 yield b'%s-%d.%s' % (base, i, ext)
166
168
167 for n in gennames(filename):
169 for n in gennames(filename):
168 if not self.backupvfs.exists(n):
170 if not self.backupvfs.exists(n):
169 return self.backupvfs.join(n)
171 return self.backupvfs.join(n)
170
172
171 def movetobackup(self):
173 def movetobackup(self):
172 if not self.backupvfs.isdir():
174 if not self.backupvfs.isdir():
173 self.backupvfs.makedir()
175 self.backupvfs.makedir()
174 for suffix in shelvefileextensions:
176 for suffix in shelvefileextensions:
175 filename = self.name + b'.' + suffix
177 filename = self.name + b'.' + suffix
176 if self.vfs.exists(filename):
178 if self.vfs.exists(filename):
177 util.rename(
179 util.rename(
178 self.vfs.join(filename), self._backupfilename(filename)
180 self.vfs.join(filename), self._backupfilename(filename)
179 )
181 )
180
182
181
183
182 class shelvedstate(object):
184 class shelvedstate(object):
183 """Handle persistence during unshelving operations.
185 """Handle persistence during unshelving operations.
184
186
185 Handles saving and restoring a shelved state. Ensures that different
187 Handles saving and restoring a shelved state. Ensures that different
186 versions of a shelved state are possible and handles them appropriately.
188 versions of a shelved state are possible and handles them appropriately.
187 """
189 """
188
190
189 _version = 2
191 _version = 2
190 _filename = b'shelvedstate'
192 _filename = b'shelvedstate'
191 _keep = b'keep'
193 _keep = b'keep'
192 _nokeep = b'nokeep'
194 _nokeep = b'nokeep'
193 # colon is essential to differentiate from a real bookmark name
195 # colon is essential to differentiate from a real bookmark name
194 _noactivebook = b':no-active-bookmark'
196 _noactivebook = b':no-active-bookmark'
195 _interactive = b'interactive'
197 _interactive = b'interactive'
196
198
197 @classmethod
199 @classmethod
198 def _verifyandtransform(cls, d):
200 def _verifyandtransform(cls, d):
199 """Some basic shelvestate syntactic verification and transformation"""
201 """Some basic shelvestate syntactic verification and transformation"""
200 try:
202 try:
201 d[b'originalwctx'] = bin(d[b'originalwctx'])
203 d[b'originalwctx'] = bin(d[b'originalwctx'])
202 d[b'pendingctx'] = bin(d[b'pendingctx'])
204 d[b'pendingctx'] = bin(d[b'pendingctx'])
203 d[b'parents'] = [bin(h) for h in d[b'parents'].split(b' ')]
205 d[b'parents'] = [bin(h) for h in d[b'parents'].split(b' ')]
204 d[b'nodestoremove'] = [
206 d[b'nodestoremove'] = [
205 bin(h) for h in d[b'nodestoremove'].split(b' ')
207 bin(h) for h in d[b'nodestoremove'].split(b' ')
206 ]
208 ]
207 except (ValueError, TypeError, KeyError) as err:
209 except (ValueError, TypeError, KeyError) as err:
208 raise error.CorruptedState(pycompat.bytestr(err))
210 raise error.CorruptedState(pycompat.bytestr(err))
209
211
210 @classmethod
212 @classmethod
211 def _getversion(cls, repo):
213 def _getversion(cls, repo):
212 """Read version information from shelvestate file"""
214 """Read version information from shelvestate file"""
213 fp = repo.vfs(cls._filename)
215 fp = repo.vfs(cls._filename)
214 try:
216 try:
215 version = int(fp.readline().strip())
217 version = int(fp.readline().strip())
216 except ValueError as err:
218 except ValueError as err:
217 raise error.CorruptedState(pycompat.bytestr(err))
219 raise error.CorruptedState(pycompat.bytestr(err))
218 finally:
220 finally:
219 fp.close()
221 fp.close()
220 return version
222 return version
221
223
222 @classmethod
224 @classmethod
223 def _readold(cls, repo):
225 def _readold(cls, repo):
224 """Read the old position-based version of a shelvestate file"""
226 """Read the old position-based version of a shelvestate file"""
225 # Order is important, because old shelvestate file uses it
227 # Order is important, because old shelvestate file uses it
226 # to detemine values of fields (i.g. name is on the second line,
228 # to detemine values of fields (i.g. name is on the second line,
227 # originalwctx is on the third and so forth). Please do not change.
229 # originalwctx is on the third and so forth). Please do not change.
228 keys = [
230 keys = [
229 b'version',
231 b'version',
230 b'name',
232 b'name',
231 b'originalwctx',
233 b'originalwctx',
232 b'pendingctx',
234 b'pendingctx',
233 b'parents',
235 b'parents',
234 b'nodestoremove',
236 b'nodestoremove',
235 b'branchtorestore',
237 b'branchtorestore',
236 b'keep',
238 b'keep',
237 b'activebook',
239 b'activebook',
238 ]
240 ]
239 # this is executed only seldomly, so it is not a big deal
241 # this is executed only seldomly, so it is not a big deal
240 # that we open this file twice
242 # that we open this file twice
241 fp = repo.vfs(cls._filename)
243 fp = repo.vfs(cls._filename)
242 d = {}
244 d = {}
243 try:
245 try:
244 for key in keys:
246 for key in keys:
245 d[key] = fp.readline().strip()
247 d[key] = fp.readline().strip()
246 finally:
248 finally:
247 fp.close()
249 fp.close()
248 return d
250 return d
249
251
250 @classmethod
252 @classmethod
251 def load(cls, repo):
253 def load(cls, repo):
252 version = cls._getversion(repo)
254 version = cls._getversion(repo)
253 if version < cls._version:
255 if version < cls._version:
254 d = cls._readold(repo)
256 d = cls._readold(repo)
255 elif version == cls._version:
257 elif version == cls._version:
256 d = scmutil.simplekeyvaluefile(repo.vfs, cls._filename).read(
258 d = scmutil.simplekeyvaluefile(repo.vfs, cls._filename).read(
257 firstlinenonkeyval=True
259 firstlinenonkeyval=True
258 )
260 )
259 else:
261 else:
260 raise error.Abort(
262 raise error.Abort(
261 _(
263 _(
262 b'this version of shelve is incompatible '
264 b'this version of shelve is incompatible '
263 b'with the version used in this repo'
265 b'with the version used in this repo'
264 )
266 )
265 )
267 )
266
268
267 cls._verifyandtransform(d)
269 cls._verifyandtransform(d)
268 try:
270 try:
269 obj = cls()
271 obj = cls()
270 obj.name = d[b'name']
272 obj.name = d[b'name']
271 obj.wctx = repo[d[b'originalwctx']]
273 obj.wctx = repo[d[b'originalwctx']]
272 obj.pendingctx = repo[d[b'pendingctx']]
274 obj.pendingctx = repo[d[b'pendingctx']]
273 obj.parents = d[b'parents']
275 obj.parents = d[b'parents']
274 obj.nodestoremove = d[b'nodestoremove']
276 obj.nodestoremove = d[b'nodestoremove']
275 obj.branchtorestore = d.get(b'branchtorestore', b'')
277 obj.branchtorestore = d.get(b'branchtorestore', b'')
276 obj.keep = d.get(b'keep') == cls._keep
278 obj.keep = d.get(b'keep') == cls._keep
277 obj.activebookmark = b''
279 obj.activebookmark = b''
278 if d.get(b'activebook', b'') != cls._noactivebook:
280 if d.get(b'activebook', b'') != cls._noactivebook:
279 obj.activebookmark = d.get(b'activebook', b'')
281 obj.activebookmark = d.get(b'activebook', b'')
280 obj.interactive = d.get(b'interactive') == cls._interactive
282 obj.interactive = d.get(b'interactive') == cls._interactive
281 except (error.RepoLookupError, KeyError) as err:
283 except (error.RepoLookupError, KeyError) as err:
282 raise error.CorruptedState(pycompat.bytestr(err))
284 raise error.CorruptedState(pycompat.bytestr(err))
283
285
284 return obj
286 return obj
285
287
286 @classmethod
288 @classmethod
287 def save(
289 def save(
288 cls,
290 cls,
289 repo,
291 repo,
290 name,
292 name,
291 originalwctx,
293 originalwctx,
292 pendingctx,
294 pendingctx,
293 nodestoremove,
295 nodestoremove,
294 branchtorestore,
296 branchtorestore,
295 keep=False,
297 keep=False,
296 activebook=b'',
298 activebook=b'',
297 interactive=False,
299 interactive=False,
298 ):
300 ):
299 info = {
301 info = {
300 b"name": name,
302 b"name": name,
301 b"originalwctx": hex(originalwctx.node()),
303 b"originalwctx": hex(originalwctx.node()),
302 b"pendingctx": hex(pendingctx.node()),
304 b"pendingctx": hex(pendingctx.node()),
303 b"parents": b' '.join([hex(p) for p in repo.dirstate.parents()]),
305 b"parents": b' '.join([hex(p) for p in repo.dirstate.parents()]),
304 b"nodestoremove": b' '.join([hex(n) for n in nodestoremove]),
306 b"nodestoremove": b' '.join([hex(n) for n in nodestoremove]),
305 b"branchtorestore": branchtorestore,
307 b"branchtorestore": branchtorestore,
306 b"keep": cls._keep if keep else cls._nokeep,
308 b"keep": cls._keep if keep else cls._nokeep,
307 b"activebook": activebook or cls._noactivebook,
309 b"activebook": activebook or cls._noactivebook,
308 }
310 }
309 if interactive:
311 if interactive:
310 info[b'interactive'] = cls._interactive
312 info[b'interactive'] = cls._interactive
311 scmutil.simplekeyvaluefile(repo.vfs, cls._filename).write(
313 scmutil.simplekeyvaluefile(repo.vfs, cls._filename).write(
312 info, firstline=(b"%d" % cls._version)
314 info, firstline=(b"%d" % cls._version)
313 )
315 )
314
316
315 @classmethod
317 @classmethod
316 def clear(cls, repo):
318 def clear(cls, repo):
317 repo.vfs.unlinkpath(cls._filename, ignoremissing=True)
319 repo.vfs.unlinkpath(cls._filename, ignoremissing=True)
318
320
319
321
320 def cleanupoldbackups(repo):
322 def cleanupoldbackups(repo):
321 vfs = vfsmod.vfs(repo.vfs.join(backupdir))
323 vfs = vfsmod.vfs(repo.vfs.join(backupdir))
322 maxbackups = repo.ui.configint(b'shelve', b'maxbackups')
324 maxbackups = repo.ui.configint(b'shelve', b'maxbackups')
323 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)]
324 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])
325 if maxbackups > 0 and maxbackups < len(hgfiles):
327 if maxbackups > 0 and maxbackups < len(hgfiles):
326 bordermtime = hgfiles[-maxbackups][0]
328 bordermtime = hgfiles[-maxbackups][0]
327 else:
329 else:
328 bordermtime = None
330 bordermtime = None
329 for mtime, f in hgfiles[: len(hgfiles) - maxbackups]:
331 for mtime, f in hgfiles[: len(hgfiles) - maxbackups]:
330 if mtime == bordermtime:
332 if mtime == bordermtime:
331 # keep it, because timestamp can't decide exact order of backups
333 # keep it, because timestamp can't decide exact order of backups
332 continue
334 continue
333 base = f[: -(1 + len(patchextension))]
335 base = f[: -(1 + len(patchextension))]
334 for ext in shelvefileextensions:
336 for ext in shelvefileextensions:
335 vfs.tryunlink(base + b'.' + ext)
337 vfs.tryunlink(base + b'.' + ext)
336
338
337
339
338 def _backupactivebookmark(repo):
340 def _backupactivebookmark(repo):
339 activebookmark = repo._activebookmark
341 activebookmark = repo._activebookmark
340 if activebookmark:
342 if activebookmark:
341 bookmarks.deactivate(repo)
343 bookmarks.deactivate(repo)
342 return activebookmark
344 return activebookmark
343
345
344
346
345 def _restoreactivebookmark(repo, mark):
347 def _restoreactivebookmark(repo, mark):
346 if mark:
348 if mark:
347 bookmarks.activate(repo, mark)
349 bookmarks.activate(repo, mark)
348
350
349
351
350 def _aborttransaction(repo, tr):
352 def _aborttransaction(repo, tr):
351 """Abort current transaction for shelve/unshelve, but keep dirstate"""
353 """Abort current transaction for shelve/unshelve, but keep dirstate"""
352 dirstatebackupname = b'dirstate.shelve'
354 dirstatebackupname = b'dirstate.shelve'
353 repo.dirstate.savebackup(tr, dirstatebackupname)
355 repo.dirstate.savebackup(tr, dirstatebackupname)
354 tr.abort()
356 tr.abort()
355 repo.dirstate.restorebackup(None, dirstatebackupname)
357 repo.dirstate.restorebackup(None, dirstatebackupname)
356
358
357
359
358 def getshelvename(repo, parent, opts):
360 def getshelvename(repo, parent, opts):
359 """Decide on the name this shelve is going to have"""
361 """Decide on the name this shelve is going to have"""
360
362
361 def gennames():
363 def gennames():
362 yield label
364 yield label
363 for i in itertools.count(1):
365 for i in itertools.count(1):
364 yield b'%s-%02d' % (label, i)
366 yield b'%s-%02d' % (label, i)
365
367
366 name = opts.get(b'name')
368 name = opts.get(b'name')
367 label = repo._activebookmark or parent.branch() or b'default'
369 label = repo._activebookmark or parent.branch() or b'default'
368 # slashes aren't allowed in filenames, therefore we rename it
370 # slashes aren't allowed in filenames, therefore we rename it
369 label = label.replace(b'/', b'_')
371 label = label.replace(b'/', b'_')
370 label = label.replace(b'\\', b'_')
372 label = label.replace(b'\\', b'_')
371 # filenames must not start with '.' as it should not be hidden
373 # filenames must not start with '.' as it should not be hidden
372 if label.startswith(b'.'):
374 if label.startswith(b'.'):
373 label = label.replace(b'.', b'_', 1)
375 label = label.replace(b'.', b'_', 1)
374
376
375 if name:
377 if name:
376 if Shelf(repo, name).exists():
378 if Shelf(repo, name).exists():
377 e = _(b"a shelved change named '%s' already exists") % name
379 e = _(b"a shelved change named '%s' already exists") % name
378 raise error.Abort(e)
380 raise error.Abort(e)
379
381
380 # ensure we are not creating a subdirectory or a hidden file
382 # ensure we are not creating a subdirectory or a hidden file
381 if b'/' in name or b'\\' in name:
383 if b'/' in name or b'\\' in name:
382 raise error.Abort(
384 raise error.Abort(
383 _(b'shelved change names can not contain slashes')
385 _(b'shelved change names can not contain slashes')
384 )
386 )
385 if name.startswith(b'.'):
387 if name.startswith(b'.'):
386 raise error.Abort(_(b"shelved change names can not start with '.'"))
388 raise error.Abort(_(b"shelved change names can not start with '.'"))
387
389
388 else:
390 else:
389 for n in gennames():
391 for n in gennames():
390 if not Shelf(repo, n).exists():
392 if not Shelf(repo, n).exists():
391 name = n
393 name = n
392 break
394 break
393
395
394 return name
396 return name
395
397
396
398
397 def mutableancestors(ctx):
399 def mutableancestors(ctx):
398 """return all mutable ancestors for ctx (included)
400 """return all mutable ancestors for ctx (included)
399
401
400 Much faster than the revset ancestors(ctx) & draft()"""
402 Much faster than the revset ancestors(ctx) & draft()"""
401 seen = {nullrev}
403 seen = {nullrev}
402 visit = collections.deque()
404 visit = collections.deque()
403 visit.append(ctx)
405 visit.append(ctx)
404 while visit:
406 while visit:
405 ctx = visit.popleft()
407 ctx = visit.popleft()
406 yield ctx.node()
408 yield ctx.node()
407 for parent in ctx.parents():
409 for parent in ctx.parents():
408 rev = parent.rev()
410 rev = parent.rev()
409 if rev not in seen:
411 if rev not in seen:
410 seen.add(rev)
412 seen.add(rev)
411 if parent.mutable():
413 if parent.mutable():
412 visit.append(parent)
414 visit.append(parent)
413
415
414
416
415 def getcommitfunc(extra, interactive, editor=False):
417 def getcommitfunc(extra, interactive, editor=False):
416 def commitfunc(ui, repo, message, match, opts):
418 def commitfunc(ui, repo, message, match, opts):
417 hasmq = util.safehasattr(repo, b'mq')
419 hasmq = util.safehasattr(repo, b'mq')
418 if hasmq:
420 if hasmq:
419 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
421 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
420
422
421 targetphase = phases.internal
423 targetphase = phases.internal
422 if not phases.supportinternal(repo):
424 if not phases.supportinternal(repo):
423 targetphase = phases.secret
425 targetphase = phases.secret
424 overrides = {(b'phases', b'new-commit'): targetphase}
426 overrides = {(b'phases', b'new-commit'): targetphase}
425 try:
427 try:
426 editor_ = False
428 editor_ = False
427 if editor:
429 if editor:
428 editor_ = cmdutil.getcommiteditor(
430 editor_ = cmdutil.getcommiteditor(
429 editform=b'shelve.shelve', **pycompat.strkwargs(opts)
431 editform=b'shelve.shelve', **pycompat.strkwargs(opts)
430 )
432 )
431 with repo.ui.configoverride(overrides):
433 with repo.ui.configoverride(overrides):
432 return repo.commit(
434 return repo.commit(
433 message,
435 message,
434 shelveuser,
436 shelveuser,
435 opts.get(b'date'),
437 opts.get(b'date'),
436 match,
438 match,
437 editor=editor_,
439 editor=editor_,
438 extra=extra,
440 extra=extra,
439 )
441 )
440 finally:
442 finally:
441 if hasmq:
443 if hasmq:
442 repo.mq.checkapplied = saved
444 repo.mq.checkapplied = saved
443
445
444 def interactivecommitfunc(ui, repo, *pats, **opts):
446 def interactivecommitfunc(ui, repo, *pats, **opts):
445 opts = pycompat.byteskwargs(opts)
447 opts = pycompat.byteskwargs(opts)
446 match = scmutil.match(repo[b'.'], pats, {})
448 match = scmutil.match(repo[b'.'], pats, {})
447 message = opts[b'message']
449 message = opts[b'message']
448 return commitfunc(ui, repo, message, match, opts)
450 return commitfunc(ui, repo, message, match, opts)
449
451
450 return interactivecommitfunc if interactive else commitfunc
452 return interactivecommitfunc if interactive else commitfunc
451
453
452
454
453 def _nothingtoshelvemessaging(ui, repo, pats, opts):
455 def _nothingtoshelvemessaging(ui, repo, pats, opts):
454 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
456 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
455 if stat.deleted:
457 if stat.deleted:
456 ui.status(
458 ui.status(
457 _(b"nothing changed (%d missing files, see 'hg status')\n")
459 _(b"nothing changed (%d missing files, see 'hg status')\n")
458 % len(stat.deleted)
460 % len(stat.deleted)
459 )
461 )
460 else:
462 else:
461 ui.status(_(b"nothing changed\n"))
463 ui.status(_(b"nothing changed\n"))
462
464
463
465
464 def _shelvecreatedcommit(repo, node, name, match):
466 def _shelvecreatedcommit(repo, node, name, match):
465 info = {b'node': hex(node)}
467 info = {b'node': hex(node)}
466 shelf = Shelf(repo, name)
468 shelf = Shelf(repo, name)
467 shelf.writeinfo(info)
469 shelf.writeinfo(info)
468 bases = list(mutableancestors(repo[node]))
470 bases = list(mutableancestors(repo[node]))
469 shelf.writebundle(bases, node)
471 shelf.writebundle(bases, node)
470 with shelf.open_patch(b'wb') as fp:
472 with shelf.open_patch(b'wb') as fp:
471 cmdutil.exportfile(
473 cmdutil.exportfile(
472 repo, [node], fp, opts=mdiff.diffopts(git=True), match=match
474 repo, [node], fp, opts=mdiff.diffopts(git=True), match=match
473 )
475 )
474
476
475
477
476 def _includeunknownfiles(repo, pats, opts, extra):
478 def _includeunknownfiles(repo, pats, opts, extra):
477 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)
478 if s.unknown:
480 if s.unknown:
479 extra[b'shelve_unknown'] = b'\0'.join(s.unknown)
481 extra[b'shelve_unknown'] = b'\0'.join(s.unknown)
480 repo[None].add(s.unknown)
482 repo[None].add(s.unknown)
481
483
482
484
483 def _finishshelve(repo, tr):
485 def _finishshelve(repo, tr):
484 if phases.supportinternal(repo):
486 if phases.supportinternal(repo):
485 tr.close()
487 tr.close()
486 else:
488 else:
487 _aborttransaction(repo, tr)
489 _aborttransaction(repo, tr)
488
490
489
491
490 def createcmd(ui, repo, pats, opts):
492 def createcmd(ui, repo, pats, opts):
491 """subcommand that creates a new shelve"""
493 """subcommand that creates a new shelve"""
492 with repo.wlock():
494 with repo.wlock():
493 cmdutil.checkunfinished(repo)
495 cmdutil.checkunfinished(repo)
494 return _docreatecmd(ui, repo, pats, opts)
496 return _docreatecmd(ui, repo, pats, opts)
495
497
496
498
497 def _docreatecmd(ui, repo, pats, opts):
499 def _docreatecmd(ui, repo, pats, opts):
498 wctx = repo[None]
500 wctx = repo[None]
499 parents = wctx.parents()
501 parents = wctx.parents()
500 parent = parents[0]
502 parent = parents[0]
501 origbranch = wctx.branch()
503 origbranch = wctx.branch()
502
504
503 if parent.node() != nullid:
505 if parent.node() != nullid:
504 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]
505 else:
507 else:
506 desc = b'(changes in empty repository)'
508 desc = b'(changes in empty repository)'
507
509
508 if not opts.get(b'message'):
510 if not opts.get(b'message'):
509 opts[b'message'] = desc
511 opts[b'message'] = desc
510
512
511 lock = tr = activebookmark = None
513 lock = tr = activebookmark = None
512 try:
514 try:
513 lock = repo.lock()
515 lock = repo.lock()
514
516
515 # use an uncommitted transaction to generate the bundle to avoid
517 # use an uncommitted transaction to generate the bundle to avoid
516 # 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.
517 tr = repo.transaction(b'shelve', report=lambda x: None)
519 tr = repo.transaction(b'shelve', report=lambda x: None)
518
520
519 interactive = opts.get(b'interactive', False)
521 interactive = opts.get(b'interactive', False)
520 includeunknown = opts.get(b'unknown', False) and not opts.get(
522 includeunknown = opts.get(b'unknown', False) and not opts.get(
521 b'addremove', False
523 b'addremove', False
522 )
524 )
523
525
524 name = getshelvename(repo, parent, opts)
526 name = getshelvename(repo, parent, opts)
525 activebookmark = _backupactivebookmark(repo)
527 activebookmark = _backupactivebookmark(repo)
526 extra = {b'internal': b'shelve'}
528 extra = {b'internal': b'shelve'}
527 if includeunknown:
529 if includeunknown:
528 _includeunknownfiles(repo, pats, opts, extra)
530 _includeunknownfiles(repo, pats, opts, extra)
529
531
530 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts):
532 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts):
531 # In non-bare shelve we don't store newly created branch
533 # In non-bare shelve we don't store newly created branch
532 # at bundled commit
534 # at bundled commit
533 repo.dirstate.setbranch(repo[b'.'].branch())
535 repo.dirstate.setbranch(repo[b'.'].branch())
534
536
535 commitfunc = getcommitfunc(extra, interactive, editor=True)
537 commitfunc = getcommitfunc(extra, interactive, editor=True)
536 if not interactive:
538 if not interactive:
537 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
539 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
538 else:
540 else:
539 node = cmdutil.dorecord(
541 node = cmdutil.dorecord(
540 ui,
542 ui,
541 repo,
543 repo,
542 commitfunc,
544 commitfunc,
543 None,
545 None,
544 False,
546 False,
545 cmdutil.recordfilter,
547 cmdutil.recordfilter,
546 *pats,
548 *pats,
547 **pycompat.strkwargs(opts)
549 **pycompat.strkwargs(opts)
548 )
550 )
549 if not node:
551 if not node:
550 _nothingtoshelvemessaging(ui, repo, pats, opts)
552 _nothingtoshelvemessaging(ui, repo, pats, opts)
551 return 1
553 return 1
552
554
553 # Create a matcher so that prefetch doesn't attempt to fetch
555 # Create a matcher so that prefetch doesn't attempt to fetch
554 # the entire repository pointlessly, and as an optimisation
556 # the entire repository pointlessly, and as an optimisation
555 # for movedirstate, if needed.
557 # for movedirstate, if needed.
556 match = scmutil.matchfiles(repo, repo[node].files())
558 match = scmutil.matchfiles(repo, repo[node].files())
557 _shelvecreatedcommit(repo, node, name, match)
559 _shelvecreatedcommit(repo, node, name, match)
558
560
559 ui.status(_(b'shelved as %s\n') % name)
561 ui.status(_(b'shelved as %s\n') % name)
560 if opts[b'keep']:
562 if opts[b'keep']:
561 with repo.dirstate.parentchange():
563 with repo.dirstate.parentchange():
562 scmutil.movedirstate(repo, parent, match)
564 scmutil.movedirstate(repo, parent, match)
563 else:
565 else:
564 hg.update(repo, parent.node())
566 hg.update(repo, parent.node())
565 ms = mergestatemod.mergestate.read(repo)
567 ms = mergestatemod.mergestate.read(repo)
566 if not ms.unresolvedcount():
568 if not ms.unresolvedcount():
567 ms.reset()
569 ms.reset()
568
570
569 if origbranch != repo[b'.'].branch() and not _isbareshelve(pats, opts):
571 if origbranch != repo[b'.'].branch() and not _isbareshelve(pats, opts):
570 repo.dirstate.setbranch(origbranch)
572 repo.dirstate.setbranch(origbranch)
571
573
572 _finishshelve(repo, tr)
574 _finishshelve(repo, tr)
573 finally:
575 finally:
574 _restoreactivebookmark(repo, activebookmark)
576 _restoreactivebookmark(repo, activebookmark)
575 lockmod.release(tr, lock)
577 lockmod.release(tr, lock)
576
578
577
579
578 def _isbareshelve(pats, opts):
580 def _isbareshelve(pats, opts):
579 return (
581 return (
580 not pats
582 not pats
581 and not opts.get(b'interactive', False)
583 and not opts.get(b'interactive', False)
582 and not opts.get(b'include', False)
584 and not opts.get(b'include', False)
583 and not opts.get(b'exclude', False)
585 and not opts.get(b'exclude', False)
584 )
586 )
585
587
586
588
587 def _iswctxonnewbranch(repo):
589 def _iswctxonnewbranch(repo):
588 return repo[None].branch() != repo[b'.'].branch()
590 return repo[None].branch() != repo[b'.'].branch()
589
591
590
592
591 def cleanupcmd(ui, repo):
593 def cleanupcmd(ui, repo):
592 """subcommand that deletes all shelves"""
594 """subcommand that deletes all shelves"""
593
595
594 with repo.wlock():
596 with repo.wlock():
595 for _mtime, name in listshelves(repo):
597 for _mtime, name in listshelves(repo):
596 Shelf(repo, name).movetobackup()
598 Shelf(repo, name).movetobackup()
597 cleanupoldbackups(repo)
599 cleanupoldbackups(repo)
598
600
599
601
600 def deletecmd(ui, repo, pats):
602 def deletecmd(ui, repo, pats):
601 """subcommand that deletes a specific shelve"""
603 """subcommand that deletes a specific shelve"""
602 if not pats:
604 if not pats:
603 raise error.InputError(_(b'no shelved changes specified!'))
605 raise error.InputError(_(b'no shelved changes specified!'))
604 with repo.wlock():
606 with repo.wlock():
605 for name in pats:
607 for name in pats:
606 shelf = Shelf(repo, name)
608 shelf = Shelf(repo, name)
607 if not shelf.exists():
609 if not shelf.exists():
608 raise error.InputError(
610 raise error.InputError(
609 _(b"shelved change '%s' not found") % name
611 _(b"shelved change '%s' not found") % name
610 )
612 )
611 shelf.movetobackup()
613 shelf.movetobackup()
612 cleanupoldbackups(repo)
614 cleanupoldbackups(repo)
613
615
614
616
615 def listshelves(repo):
617 def listshelves(repo):
616 """return all shelves in repo as list of (time, name)"""
618 """return all shelves in repo as list of (time, name)"""
617 try:
619 try:
618 names = repo.vfs.readdir(shelvedir)
620 names = repo.vfs.readdir(shelvedir)
619 except OSError as err:
621 except OSError as err:
620 if err.errno != errno.ENOENT:
622 if err.errno != errno.ENOENT:
621 raise
623 raise
622 return []
624 return []
623 info = []
625 info = []
624 for (name, _type) in names:
626 seen = set()
625 pfx, sfx = name.rsplit(b'.', 1)
627 for (filename, _type) in names:
626 if not pfx or sfx != patchextension:
628 name, ext = filename.rsplit(b'.', 1)
629 if name in seen:
627 continue
630 continue
628 mtime = Shelf(repo, pfx).mtime()
631 seen.add(name)
629 info.append((mtime, pfx))
632 shelf = Shelf(repo, name)
633 if not shelf.exists():
634 continue
635 mtime = shelf.mtime()
636 info.append((mtime, name))
630 return sorted(info, reverse=True)
637 return sorted(info, reverse=True)
631
638
632
639
633 def listcmd(ui, repo, pats, opts):
640 def listcmd(ui, repo, pats, opts):
634 """subcommand that displays the list of shelves"""
641 """subcommand that displays the list of shelves"""
635 pats = set(pats)
642 pats = set(pats)
636 width = 80
643 width = 80
637 if not ui.plain():
644 if not ui.plain():
638 width = ui.termwidth()
645 width = ui.termwidth()
639 namelabel = b'shelve.newest'
646 namelabel = b'shelve.newest'
640 ui.pager(b'shelve')
647 ui.pager(b'shelve')
641 for mtime, name in listshelves(repo):
648 for mtime, name in listshelves(repo):
642 if pats and name not in pats:
649 if pats and name not in pats:
643 continue
650 continue
644 ui.write(name, label=namelabel)
651 ui.write(name, label=namelabel)
645 namelabel = b'shelve.name'
652 namelabel = b'shelve.name'
646 if ui.quiet:
653 if ui.quiet:
647 ui.write(b'\n')
654 ui.write(b'\n')
648 continue
655 continue
649 ui.write(b' ' * (16 - len(name)))
656 ui.write(b' ' * (16 - len(name)))
650 used = 16
657 used = 16
651 date = dateutil.makedate(mtime)
658 date = dateutil.makedate(mtime)
652 age = b'(%s)' % templatefilters.age(date, abbrev=True)
659 age = b'(%s)' % templatefilters.age(date, abbrev=True)
653 ui.write(age, label=b'shelve.age')
660 ui.write(age, label=b'shelve.age')
654 ui.write(b' ' * (12 - len(age)))
661 ui.write(b' ' * (12 - len(age)))
655 used += 12
662 used += 12
656 with Shelf(repo, name).open_patch() as fp:
663 with Shelf(repo, name).open_patch() as fp:
657 while True:
664 while True:
658 line = fp.readline()
665 line = fp.readline()
659 if not line:
666 if not line:
660 break
667 break
661 if not line.startswith(b'#'):
668 if not line.startswith(b'#'):
662 desc = line.rstrip()
669 desc = line.rstrip()
663 if ui.formatted():
670 if ui.formatted():
664 desc = stringutil.ellipsis(desc, width - used)
671 desc = stringutil.ellipsis(desc, width - used)
665 ui.write(desc)
672 ui.write(desc)
666 break
673 break
667 ui.write(b'\n')
674 ui.write(b'\n')
668 if not (opts[b'patch'] or opts[b'stat']):
675 if not (opts[b'patch'] or opts[b'stat']):
669 continue
676 continue
670 difflines = fp.readlines()
677 difflines = fp.readlines()
671 if opts[b'patch']:
678 if opts[b'patch']:
672 for chunk, label in patch.difflabel(iter, difflines):
679 for chunk, label in patch.difflabel(iter, difflines):
673 ui.write(chunk, label=label)
680 ui.write(chunk, label=label)
674 if opts[b'stat']:
681 if opts[b'stat']:
675 for chunk, label in patch.diffstatui(difflines, width=width):
682 for chunk, label in patch.diffstatui(difflines, width=width):
676 ui.write(chunk, label=label)
683 ui.write(chunk, label=label)
677
684
678
685
679 def patchcmds(ui, repo, pats, opts):
686 def patchcmds(ui, repo, pats, opts):
680 """subcommand that displays shelves"""
687 """subcommand that displays shelves"""
681 if len(pats) == 0:
688 if len(pats) == 0:
682 shelves = listshelves(repo)
689 shelves = listshelves(repo)
683 if not shelves:
690 if not shelves:
684 raise error.Abort(_(b"there are no shelves to show"))
691 raise error.Abort(_(b"there are no shelves to show"))
685 mtime, name = shelves[0]
692 mtime, name = shelves[0]
686 pats = [name]
693 pats = [name]
687
694
688 for shelfname in pats:
695 for shelfname in pats:
689 if not Shelf(repo, shelfname).exists():
696 if not Shelf(repo, shelfname).exists():
690 raise error.Abort(_(b"cannot find shelf %s") % shelfname)
697 raise error.Abort(_(b"cannot find shelf %s") % shelfname)
691
698
692 listcmd(ui, repo, pats, opts)
699 listcmd(ui, repo, pats, opts)
693
700
694
701
695 def checkparents(repo, state):
702 def checkparents(repo, state):
696 """check parent while resuming an unshelve"""
703 """check parent while resuming an unshelve"""
697 if state.parents != repo.dirstate.parents():
704 if state.parents != repo.dirstate.parents():
698 raise error.Abort(
705 raise error.Abort(
699 _(b'working directory parents do not match unshelve state')
706 _(b'working directory parents do not match unshelve state')
700 )
707 )
701
708
702
709
703 def _loadshelvedstate(ui, repo, opts):
710 def _loadshelvedstate(ui, repo, opts):
704 try:
711 try:
705 state = shelvedstate.load(repo)
712 state = shelvedstate.load(repo)
706 if opts.get(b'keep') is None:
713 if opts.get(b'keep') is None:
707 opts[b'keep'] = state.keep
714 opts[b'keep'] = state.keep
708 except IOError as err:
715 except IOError as err:
709 if err.errno != errno.ENOENT:
716 if err.errno != errno.ENOENT:
710 raise
717 raise
711 cmdutil.wrongtooltocontinue(repo, _(b'unshelve'))
718 cmdutil.wrongtooltocontinue(repo, _(b'unshelve'))
712 except error.CorruptedState as err:
719 except error.CorruptedState as err:
713 ui.debug(pycompat.bytestr(err) + b'\n')
720 ui.debug(pycompat.bytestr(err) + b'\n')
714 if opts.get(b'continue'):
721 if opts.get(b'continue'):
715 msg = _(b'corrupted shelved state file')
722 msg = _(b'corrupted shelved state file')
716 hint = _(
723 hint = _(
717 b'please run hg unshelve --abort to abort unshelve '
724 b'please run hg unshelve --abort to abort unshelve '
718 b'operation'
725 b'operation'
719 )
726 )
720 raise error.Abort(msg, hint=hint)
727 raise error.Abort(msg, hint=hint)
721 elif opts.get(b'abort'):
728 elif opts.get(b'abort'):
722 shelvedstate.clear(repo)
729 shelvedstate.clear(repo)
723 raise error.Abort(
730 raise error.Abort(
724 _(
731 _(
725 b'could not read shelved state file, your '
732 b'could not read shelved state file, your '
726 b'working copy may be in an unexpected state\n'
733 b'working copy may be in an unexpected state\n'
727 b'please update to some commit\n'
734 b'please update to some commit\n'
728 )
735 )
729 )
736 )
730 return state
737 return state
731
738
732
739
733 def unshelveabort(ui, repo, state):
740 def unshelveabort(ui, repo, state):
734 """subcommand that abort an in-progress unshelve"""
741 """subcommand that abort an in-progress unshelve"""
735 with repo.lock():
742 with repo.lock():
736 try:
743 try:
737 checkparents(repo, state)
744 checkparents(repo, state)
738
745
739 merge.clean_update(state.pendingctx)
746 merge.clean_update(state.pendingctx)
740 if state.activebookmark and state.activebookmark in repo._bookmarks:
747 if state.activebookmark and state.activebookmark in repo._bookmarks:
741 bookmarks.activate(repo, state.activebookmark)
748 bookmarks.activate(repo, state.activebookmark)
742 mergefiles(ui, repo, state.wctx, state.pendingctx)
749 mergefiles(ui, repo, state.wctx, state.pendingctx)
743 if not phases.supportinternal(repo):
750 if not phases.supportinternal(repo):
744 repair.strip(
751 repair.strip(
745 ui, repo, state.nodestoremove, backup=False, topic=b'shelve'
752 ui, repo, state.nodestoremove, backup=False, topic=b'shelve'
746 )
753 )
747 finally:
754 finally:
748 shelvedstate.clear(repo)
755 shelvedstate.clear(repo)
749 ui.warn(_(b"unshelve of '%s' aborted\n") % state.name)
756 ui.warn(_(b"unshelve of '%s' aborted\n") % state.name)
750
757
751
758
752 def hgabortunshelve(ui, repo):
759 def hgabortunshelve(ui, repo):
753 """logic to abort unshelve using 'hg abort"""
760 """logic to abort unshelve using 'hg abort"""
754 with repo.wlock():
761 with repo.wlock():
755 state = _loadshelvedstate(ui, repo, {b'abort': True})
762 state = _loadshelvedstate(ui, repo, {b'abort': True})
756 return unshelveabort(ui, repo, state)
763 return unshelveabort(ui, repo, state)
757
764
758
765
759 def mergefiles(ui, repo, wctx, shelvectx):
766 def mergefiles(ui, repo, wctx, shelvectx):
760 """updates to wctx and merges the changes from shelvectx into the
767 """updates to wctx and merges the changes from shelvectx into the
761 dirstate."""
768 dirstate."""
762 with ui.configoverride({(b'ui', b'quiet'): True}):
769 with ui.configoverride({(b'ui', b'quiet'): True}):
763 hg.update(repo, wctx.node())
770 hg.update(repo, wctx.node())
764 ui.pushbuffer(True)
771 ui.pushbuffer(True)
765 cmdutil.revert(ui, repo, shelvectx)
772 cmdutil.revert(ui, repo, shelvectx)
766 ui.popbuffer()
773 ui.popbuffer()
767
774
768
775
769 def restorebranch(ui, repo, branchtorestore):
776 def restorebranch(ui, repo, branchtorestore):
770 if branchtorestore and branchtorestore != repo.dirstate.branch():
777 if branchtorestore and branchtorestore != repo.dirstate.branch():
771 repo.dirstate.setbranch(branchtorestore)
778 repo.dirstate.setbranch(branchtorestore)
772 ui.status(
779 ui.status(
773 _(b'marked working directory as branch %s\n') % branchtorestore
780 _(b'marked working directory as branch %s\n') % branchtorestore
774 )
781 )
775
782
776
783
777 def unshelvecleanup(ui, repo, name, opts):
784 def unshelvecleanup(ui, repo, name, opts):
778 """remove related files after an unshelve"""
785 """remove related files after an unshelve"""
779 if not opts.get(b'keep'):
786 if not opts.get(b'keep'):
780 Shelf(repo, name).movetobackup()
787 Shelf(repo, name).movetobackup()
781 cleanupoldbackups(repo)
788 cleanupoldbackups(repo)
782
789
783
790
784 def unshelvecontinue(ui, repo, state, opts):
791 def unshelvecontinue(ui, repo, state, opts):
785 """subcommand to continue an in-progress unshelve"""
792 """subcommand to continue an in-progress unshelve"""
786 # We're finishing off a merge. First parent is our original
793 # We're finishing off a merge. First parent is our original
787 # parent, second is the temporary "fake" commit we're unshelving.
794 # parent, second is the temporary "fake" commit we're unshelving.
788 interactive = state.interactive
795 interactive = state.interactive
789 basename = state.name
796 basename = state.name
790 with repo.lock():
797 with repo.lock():
791 checkparents(repo, state)
798 checkparents(repo, state)
792 ms = mergestatemod.mergestate.read(repo)
799 ms = mergestatemod.mergestate.read(repo)
793 if list(ms.unresolved()):
800 if list(ms.unresolved()):
794 raise error.Abort(
801 raise error.Abort(
795 _(b"unresolved conflicts, can't continue"),
802 _(b"unresolved conflicts, can't continue"),
796 hint=_(b"see 'hg resolve', then 'hg unshelve --continue'"),
803 hint=_(b"see 'hg resolve', then 'hg unshelve --continue'"),
797 )
804 )
798
805
799 shelvectx = repo[state.parents[1]]
806 shelvectx = repo[state.parents[1]]
800 pendingctx = state.pendingctx
807 pendingctx = state.pendingctx
801
808
802 with repo.dirstate.parentchange():
809 with repo.dirstate.parentchange():
803 repo.setparents(state.pendingctx.node(), nullid)
810 repo.setparents(state.pendingctx.node(), nullid)
804 repo.dirstate.write(repo.currenttransaction())
811 repo.dirstate.write(repo.currenttransaction())
805
812
806 targetphase = phases.internal
813 targetphase = phases.internal
807 if not phases.supportinternal(repo):
814 if not phases.supportinternal(repo):
808 targetphase = phases.secret
815 targetphase = phases.secret
809 overrides = {(b'phases', b'new-commit'): targetphase}
816 overrides = {(b'phases', b'new-commit'): targetphase}
810 with repo.ui.configoverride(overrides, b'unshelve'):
817 with repo.ui.configoverride(overrides, b'unshelve'):
811 with repo.dirstate.parentchange():
818 with repo.dirstate.parentchange():
812 repo.setparents(state.parents[0], nullid)
819 repo.setparents(state.parents[0], nullid)
813 newnode, ispartialunshelve = _createunshelvectx(
820 newnode, ispartialunshelve = _createunshelvectx(
814 ui, repo, shelvectx, basename, interactive, opts
821 ui, repo, shelvectx, basename, interactive, opts
815 )
822 )
816
823
817 if newnode is None:
824 if newnode is None:
818 shelvectx = state.pendingctx
825 shelvectx = state.pendingctx
819 msg = _(
826 msg = _(
820 b'note: unshelved changes already existed '
827 b'note: unshelved changes already existed '
821 b'in the working copy\n'
828 b'in the working copy\n'
822 )
829 )
823 ui.status(msg)
830 ui.status(msg)
824 else:
831 else:
825 # only strip the shelvectx if we produced one
832 # only strip the shelvectx if we produced one
826 state.nodestoremove.append(newnode)
833 state.nodestoremove.append(newnode)
827 shelvectx = repo[newnode]
834 shelvectx = repo[newnode]
828
835
829 merge.update(pendingctx)
836 merge.update(pendingctx)
830 mergefiles(ui, repo, state.wctx, shelvectx)
837 mergefiles(ui, repo, state.wctx, shelvectx)
831 restorebranch(ui, repo, state.branchtorestore)
838 restorebranch(ui, repo, state.branchtorestore)
832
839
833 if not phases.supportinternal(repo):
840 if not phases.supportinternal(repo):
834 repair.strip(
841 repair.strip(
835 ui, repo, state.nodestoremove, backup=False, topic=b'shelve'
842 ui, repo, state.nodestoremove, backup=False, topic=b'shelve'
836 )
843 )
837 shelvedstate.clear(repo)
844 shelvedstate.clear(repo)
838 if not ispartialunshelve:
845 if not ispartialunshelve:
839 unshelvecleanup(ui, repo, state.name, opts)
846 unshelvecleanup(ui, repo, state.name, opts)
840 _restoreactivebookmark(repo, state.activebookmark)
847 _restoreactivebookmark(repo, state.activebookmark)
841 ui.status(_(b"unshelve of '%s' complete\n") % state.name)
848 ui.status(_(b"unshelve of '%s' complete\n") % state.name)
842
849
843
850
844 def hgcontinueunshelve(ui, repo):
851 def hgcontinueunshelve(ui, repo):
845 """logic to resume unshelve using 'hg continue'"""
852 """logic to resume unshelve using 'hg continue'"""
846 with repo.wlock():
853 with repo.wlock():
847 state = _loadshelvedstate(ui, repo, {b'continue': True})
854 state = _loadshelvedstate(ui, repo, {b'continue': True})
848 return unshelvecontinue(ui, repo, state, {b'keep': state.keep})
855 return unshelvecontinue(ui, repo, state, {b'keep': state.keep})
849
856
850
857
851 def _commitworkingcopychanges(ui, repo, opts, tmpwctx):
858 def _commitworkingcopychanges(ui, repo, opts, tmpwctx):
852 """Temporarily commit working copy changes before moving unshelve commit"""
859 """Temporarily commit working copy changes before moving unshelve commit"""
853 # Store pending changes in a commit and remember added in case a shelve
860 # Store pending changes in a commit and remember added in case a shelve
854 # contains unknown files that are part of the pending change
861 # contains unknown files that are part of the pending change
855 s = repo.status()
862 s = repo.status()
856 addedbefore = frozenset(s.added)
863 addedbefore = frozenset(s.added)
857 if not (s.modified or s.added or s.removed):
864 if not (s.modified or s.added or s.removed):
858 return tmpwctx, addedbefore
865 return tmpwctx, addedbefore
859 ui.status(
866 ui.status(
860 _(
867 _(
861 b"temporarily committing pending changes "
868 b"temporarily committing pending changes "
862 b"(restore with 'hg unshelve --abort')\n"
869 b"(restore with 'hg unshelve --abort')\n"
863 )
870 )
864 )
871 )
865 extra = {b'internal': b'shelve'}
872 extra = {b'internal': b'shelve'}
866 commitfunc = getcommitfunc(extra=extra, interactive=False, editor=False)
873 commitfunc = getcommitfunc(extra=extra, interactive=False, editor=False)
867 tempopts = {}
874 tempopts = {}
868 tempopts[b'message'] = b"pending changes temporary commit"
875 tempopts[b'message'] = b"pending changes temporary commit"
869 tempopts[b'date'] = opts.get(b'date')
876 tempopts[b'date'] = opts.get(b'date')
870 with ui.configoverride({(b'ui', b'quiet'): True}):
877 with ui.configoverride({(b'ui', b'quiet'): True}):
871 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
878 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
872 tmpwctx = repo[node]
879 tmpwctx = repo[node]
873 return tmpwctx, addedbefore
880 return tmpwctx, addedbefore
874
881
875
882
876 def _unshelverestorecommit(ui, repo, tr, basename):
883 def _unshelverestorecommit(ui, repo, tr, basename):
877 """Recreate commit in the repository during the unshelve"""
884 """Recreate commit in the repository during the unshelve"""
878 repo = repo.unfiltered()
885 repo = repo.unfiltered()
879 node = None
886 node = None
880 shelf = Shelf(repo, basename)
887 shelf = Shelf(repo, basename)
881 if shelf.hasinfo():
888 if shelf.hasinfo():
882 node = shelf.readinfo()[b'node']
889 node = shelf.readinfo()[b'node']
883 if node is None or node not in repo:
890 if node is None or node not in repo:
884 with ui.configoverride({(b'ui', b'quiet'): True}):
891 with ui.configoverride({(b'ui', b'quiet'): True}):
885 shelvectx = shelf.applybundle(tr)
892 shelvectx = shelf.applybundle(tr)
886 # We might not strip the unbundled changeset, so we should keep track of
893 # We might not strip the unbundled changeset, so we should keep track of
887 # the unshelve node in case we need to reuse it (eg: unshelve --keep)
894 # the unshelve node in case we need to reuse it (eg: unshelve --keep)
888 if node is None:
895 if node is None:
889 info = {b'node': hex(shelvectx.node())}
896 info = {b'node': hex(shelvectx.node())}
890 shelf.writeinfo(info)
897 shelf.writeinfo(info)
891 else:
898 else:
892 shelvectx = repo[node]
899 shelvectx = repo[node]
893
900
894 return repo, shelvectx
901 return repo, shelvectx
895
902
896
903
897 def _createunshelvectx(ui, repo, shelvectx, basename, interactive, opts):
904 def _createunshelvectx(ui, repo, shelvectx, basename, interactive, opts):
898 """Handles the creation of unshelve commit and updates the shelve if it
905 """Handles the creation of unshelve commit and updates the shelve if it
899 was partially unshelved.
906 was partially unshelved.
900
907
901 If interactive is:
908 If interactive is:
902
909
903 * False: Commits all the changes in the working directory.
910 * False: Commits all the changes in the working directory.
904 * True: Prompts the user to select changes to unshelve and commit them.
911 * True: Prompts the user to select changes to unshelve and commit them.
905 Update the shelve with remaining changes.
912 Update the shelve with remaining changes.
906
913
907 Returns the node of the new commit formed and a bool indicating whether
914 Returns the node of the new commit formed and a bool indicating whether
908 the shelve was partially unshelved.Creates a commit ctx to unshelve
915 the shelve was partially unshelved.Creates a commit ctx to unshelve
909 interactively or non-interactively.
916 interactively or non-interactively.
910
917
911 The user might want to unshelve certain changes only from the stored
918 The user might want to unshelve certain changes only from the stored
912 shelve in interactive. So, we would create two commits. One with requested
919 shelve in interactive. So, we would create two commits. One with requested
913 changes to unshelve at that time and the latter is shelved for future.
920 changes to unshelve at that time and the latter is shelved for future.
914
921
915 Here, we return both the newnode which is created interactively and a
922 Here, we return both the newnode which is created interactively and a
916 bool to know whether the shelve is partly done or completely done.
923 bool to know whether the shelve is partly done or completely done.
917 """
924 """
918 opts[b'message'] = shelvectx.description()
925 opts[b'message'] = shelvectx.description()
919 opts[b'interactive-unshelve'] = True
926 opts[b'interactive-unshelve'] = True
920 pats = []
927 pats = []
921 if not interactive:
928 if not interactive:
922 newnode = repo.commit(
929 newnode = repo.commit(
923 text=shelvectx.description(),
930 text=shelvectx.description(),
924 extra=shelvectx.extra(),
931 extra=shelvectx.extra(),
925 user=shelvectx.user(),
932 user=shelvectx.user(),
926 date=shelvectx.date(),
933 date=shelvectx.date(),
927 )
934 )
928 return newnode, False
935 return newnode, False
929
936
930 commitfunc = getcommitfunc(shelvectx.extra(), interactive=True, editor=True)
937 commitfunc = getcommitfunc(shelvectx.extra(), interactive=True, editor=True)
931 newnode = cmdutil.dorecord(
938 newnode = cmdutil.dorecord(
932 ui,
939 ui,
933 repo,
940 repo,
934 commitfunc,
941 commitfunc,
935 None,
942 None,
936 False,
943 False,
937 cmdutil.recordfilter,
944 cmdutil.recordfilter,
938 *pats,
945 *pats,
939 **pycompat.strkwargs(opts)
946 **pycompat.strkwargs(opts)
940 )
947 )
941 snode = repo.commit(
948 snode = repo.commit(
942 text=shelvectx.description(),
949 text=shelvectx.description(),
943 extra=shelvectx.extra(),
950 extra=shelvectx.extra(),
944 user=shelvectx.user(),
951 user=shelvectx.user(),
945 )
952 )
946 if snode:
953 if snode:
947 m = scmutil.matchfiles(repo, repo[snode].files())
954 m = scmutil.matchfiles(repo, repo[snode].files())
948 _shelvecreatedcommit(repo, snode, basename, m)
955 _shelvecreatedcommit(repo, snode, basename, m)
949
956
950 return newnode, bool(snode)
957 return newnode, bool(snode)
951
958
952
959
953 def _rebaserestoredcommit(
960 def _rebaserestoredcommit(
954 ui,
961 ui,
955 repo,
962 repo,
956 opts,
963 opts,
957 tr,
964 tr,
958 oldtiprev,
965 oldtiprev,
959 basename,
966 basename,
960 pctx,
967 pctx,
961 tmpwctx,
968 tmpwctx,
962 shelvectx,
969 shelvectx,
963 branchtorestore,
970 branchtorestore,
964 activebookmark,
971 activebookmark,
965 ):
972 ):
966 """Rebase restored commit from its original location to a destination"""
973 """Rebase restored commit from its original location to a destination"""
967 # If the shelve is not immediately on top of the commit
974 # If the shelve is not immediately on top of the commit
968 # we'll be merging with, rebase it to be on top.
975 # we'll be merging with, rebase it to be on top.
969 interactive = opts.get(b'interactive')
976 interactive = opts.get(b'interactive')
970 if tmpwctx.node() == shelvectx.p1().node() and not interactive:
977 if tmpwctx.node() == shelvectx.p1().node() and not interactive:
971 # We won't skip on interactive mode because, the user might want to
978 # We won't skip on interactive mode because, the user might want to
972 # unshelve certain changes only.
979 # unshelve certain changes only.
973 return shelvectx, False
980 return shelvectx, False
974
981
975 overrides = {
982 overrides = {
976 (b'ui', b'forcemerge'): opts.get(b'tool', b''),
983 (b'ui', b'forcemerge'): opts.get(b'tool', b''),
977 (b'phases', b'new-commit'): phases.secret,
984 (b'phases', b'new-commit'): phases.secret,
978 }
985 }
979 with repo.ui.configoverride(overrides, b'unshelve'):
986 with repo.ui.configoverride(overrides, b'unshelve'):
980 ui.status(_(b'rebasing shelved changes\n'))
987 ui.status(_(b'rebasing shelved changes\n'))
981 stats = merge.graft(
988 stats = merge.graft(
982 repo,
989 repo,
983 shelvectx,
990 shelvectx,
984 labels=[b'working-copy', b'shelve'],
991 labels=[b'working-copy', b'shelve'],
985 keepconflictparent=True,
992 keepconflictparent=True,
986 )
993 )
987 if stats.unresolvedcount:
994 if stats.unresolvedcount:
988 tr.close()
995 tr.close()
989
996
990 nodestoremove = [
997 nodestoremove = [
991 repo.changelog.node(rev)
998 repo.changelog.node(rev)
992 for rev in pycompat.xrange(oldtiprev, len(repo))
999 for rev in pycompat.xrange(oldtiprev, len(repo))
993 ]
1000 ]
994 shelvedstate.save(
1001 shelvedstate.save(
995 repo,
1002 repo,
996 basename,
1003 basename,
997 pctx,
1004 pctx,
998 tmpwctx,
1005 tmpwctx,
999 nodestoremove,
1006 nodestoremove,
1000 branchtorestore,
1007 branchtorestore,
1001 opts.get(b'keep'),
1008 opts.get(b'keep'),
1002 activebookmark,
1009 activebookmark,
1003 interactive,
1010 interactive,
1004 )
1011 )
1005 raise error.ConflictResolutionRequired(b'unshelve')
1012 raise error.ConflictResolutionRequired(b'unshelve')
1006
1013
1007 with repo.dirstate.parentchange():
1014 with repo.dirstate.parentchange():
1008 repo.setparents(tmpwctx.node(), nullid)
1015 repo.setparents(tmpwctx.node(), nullid)
1009 newnode, ispartialunshelve = _createunshelvectx(
1016 newnode, ispartialunshelve = _createunshelvectx(
1010 ui, repo, shelvectx, basename, interactive, opts
1017 ui, repo, shelvectx, basename, interactive, opts
1011 )
1018 )
1012
1019
1013 if newnode is None:
1020 if newnode is None:
1014 shelvectx = tmpwctx
1021 shelvectx = tmpwctx
1015 msg = _(
1022 msg = _(
1016 b'note: unshelved changes already existed '
1023 b'note: unshelved changes already existed '
1017 b'in the working copy\n'
1024 b'in the working copy\n'
1018 )
1025 )
1019 ui.status(msg)
1026 ui.status(msg)
1020 else:
1027 else:
1021 shelvectx = repo[newnode]
1028 shelvectx = repo[newnode]
1022 merge.update(tmpwctx)
1029 merge.update(tmpwctx)
1023
1030
1024 return shelvectx, ispartialunshelve
1031 return shelvectx, ispartialunshelve
1025
1032
1026
1033
1027 def _forgetunknownfiles(repo, shelvectx, addedbefore):
1034 def _forgetunknownfiles(repo, shelvectx, addedbefore):
1028 # Forget any files that were unknown before the shelve, unknown before
1035 # Forget any files that were unknown before the shelve, unknown before
1029 # unshelve started, but are now added.
1036 # unshelve started, but are now added.
1030 shelveunknown = shelvectx.extra().get(b'shelve_unknown')
1037 shelveunknown = shelvectx.extra().get(b'shelve_unknown')
1031 if not shelveunknown:
1038 if not shelveunknown:
1032 return
1039 return
1033 shelveunknown = frozenset(shelveunknown.split(b'\0'))
1040 shelveunknown = frozenset(shelveunknown.split(b'\0'))
1034 addedafter = frozenset(repo.status().added)
1041 addedafter = frozenset(repo.status().added)
1035 toforget = (addedafter & shelveunknown) - addedbefore
1042 toforget = (addedafter & shelveunknown) - addedbefore
1036 repo[None].forget(toforget)
1043 repo[None].forget(toforget)
1037
1044
1038
1045
1039 def _finishunshelve(repo, oldtiprev, tr, activebookmark):
1046 def _finishunshelve(repo, oldtiprev, tr, activebookmark):
1040 _restoreactivebookmark(repo, activebookmark)
1047 _restoreactivebookmark(repo, activebookmark)
1041 # The transaction aborting will strip all the commits for us,
1048 # The transaction aborting will strip all the commits for us,
1042 # but it doesn't update the inmemory structures, so addchangegroup
1049 # but it doesn't update the inmemory structures, so addchangegroup
1043 # hooks still fire and try to operate on the missing commits.
1050 # hooks still fire and try to operate on the missing commits.
1044 # Clean up manually to prevent this.
1051 # Clean up manually to prevent this.
1045 repo.unfiltered().changelog.strip(oldtiprev, tr)
1052 repo.unfiltered().changelog.strip(oldtiprev, tr)
1046 _aborttransaction(repo, tr)
1053 _aborttransaction(repo, tr)
1047
1054
1048
1055
1049 def _checkunshelveuntrackedproblems(ui, repo, shelvectx):
1056 def _checkunshelveuntrackedproblems(ui, repo, shelvectx):
1050 """Check potential problems which may result from working
1057 """Check potential problems which may result from working
1051 copy having untracked changes."""
1058 copy having untracked changes."""
1052 wcdeleted = set(repo.status().deleted)
1059 wcdeleted = set(repo.status().deleted)
1053 shelvetouched = set(shelvectx.files())
1060 shelvetouched = set(shelvectx.files())
1054 intersection = wcdeleted.intersection(shelvetouched)
1061 intersection = wcdeleted.intersection(shelvetouched)
1055 if intersection:
1062 if intersection:
1056 m = _(b"shelved change touches missing files")
1063 m = _(b"shelved change touches missing files")
1057 hint = _(b"run hg status to see which files are missing")
1064 hint = _(b"run hg status to see which files are missing")
1058 raise error.Abort(m, hint=hint)
1065 raise error.Abort(m, hint=hint)
1059
1066
1060
1067
1061 def unshelvecmd(ui, repo, *shelved, **opts):
1068 def unshelvecmd(ui, repo, *shelved, **opts):
1062 opts = pycompat.byteskwargs(opts)
1069 opts = pycompat.byteskwargs(opts)
1063 abortf = opts.get(b'abort')
1070 abortf = opts.get(b'abort')
1064 continuef = opts.get(b'continue')
1071 continuef = opts.get(b'continue')
1065 interactive = opts.get(b'interactive')
1072 interactive = opts.get(b'interactive')
1066 if not abortf and not continuef:
1073 if not abortf and not continuef:
1067 cmdutil.checkunfinished(repo)
1074 cmdutil.checkunfinished(repo)
1068 shelved = list(shelved)
1075 shelved = list(shelved)
1069 if opts.get(b"name"):
1076 if opts.get(b"name"):
1070 shelved.append(opts[b"name"])
1077 shelved.append(opts[b"name"])
1071
1078
1072 if interactive and opts.get(b'keep'):
1079 if interactive and opts.get(b'keep'):
1073 raise error.InputError(
1080 raise error.InputError(
1074 _(b'--keep on --interactive is not yet supported')
1081 _(b'--keep on --interactive is not yet supported')
1075 )
1082 )
1076 if abortf or continuef:
1083 if abortf or continuef:
1077 if abortf and continuef:
1084 if abortf and continuef:
1078 raise error.InputError(_(b'cannot use both abort and continue'))
1085 raise error.InputError(_(b'cannot use both abort and continue'))
1079 if shelved:
1086 if shelved:
1080 raise error.InputError(
1087 raise error.InputError(
1081 _(
1088 _(
1082 b'cannot combine abort/continue with '
1089 b'cannot combine abort/continue with '
1083 b'naming a shelved change'
1090 b'naming a shelved change'
1084 )
1091 )
1085 )
1092 )
1086 if abortf and opts.get(b'tool', False):
1093 if abortf and opts.get(b'tool', False):
1087 ui.warn(_(b'tool option will be ignored\n'))
1094 ui.warn(_(b'tool option will be ignored\n'))
1088
1095
1089 state = _loadshelvedstate(ui, repo, opts)
1096 state = _loadshelvedstate(ui, repo, opts)
1090 if abortf:
1097 if abortf:
1091 return unshelveabort(ui, repo, state)
1098 return unshelveabort(ui, repo, state)
1092 elif continuef and interactive:
1099 elif continuef and interactive:
1093 raise error.InputError(
1100 raise error.InputError(
1094 _(b'cannot use both continue and interactive')
1101 _(b'cannot use both continue and interactive')
1095 )
1102 )
1096 elif continuef:
1103 elif continuef:
1097 return unshelvecontinue(ui, repo, state, opts)
1104 return unshelvecontinue(ui, repo, state, opts)
1098 elif len(shelved) > 1:
1105 elif len(shelved) > 1:
1099 raise error.InputError(_(b'can only unshelve one change at a time'))
1106 raise error.InputError(_(b'can only unshelve one change at a time'))
1100 elif not shelved:
1107 elif not shelved:
1101 shelved = listshelves(repo)
1108 shelved = listshelves(repo)
1102 if not shelved:
1109 if not shelved:
1103 raise error.StateError(_(b'no shelved changes to apply!'))
1110 raise error.StateError(_(b'no shelved changes to apply!'))
1104 basename = shelved[0][1]
1111 basename = shelved[0][1]
1105 ui.status(_(b"unshelving change '%s'\n") % basename)
1112 ui.status(_(b"unshelving change '%s'\n") % basename)
1106 else:
1113 else:
1107 basename = shelved[0]
1114 basename = shelved[0]
1108
1115
1109 if not Shelf(repo, basename).exists():
1116 if not Shelf(repo, basename).exists():
1110 raise error.InputError(_(b"shelved change '%s' not found") % basename)
1117 raise error.InputError(_(b"shelved change '%s' not found") % basename)
1111
1118
1112 return _dounshelve(ui, repo, basename, opts)
1119 return _dounshelve(ui, repo, basename, opts)
1113
1120
1114
1121
1115 def _dounshelve(ui, repo, basename, opts):
1122 def _dounshelve(ui, repo, basename, opts):
1116 repo = repo.unfiltered()
1123 repo = repo.unfiltered()
1117 lock = tr = None
1124 lock = tr = None
1118 try:
1125 try:
1119 lock = repo.lock()
1126 lock = repo.lock()
1120 tr = repo.transaction(b'unshelve', report=lambda x: None)
1127 tr = repo.transaction(b'unshelve', report=lambda x: None)
1121 oldtiprev = len(repo)
1128 oldtiprev = len(repo)
1122
1129
1123 pctx = repo[b'.']
1130 pctx = repo[b'.']
1124 tmpwctx = pctx
1131 tmpwctx = pctx
1125 # The goal is to have a commit structure like so:
1132 # The goal is to have a commit structure like so:
1126 # ...-> pctx -> tmpwctx -> shelvectx
1133 # ...-> pctx -> tmpwctx -> shelvectx
1127 # where tmpwctx is an optional commit with the user's pending changes
1134 # where tmpwctx is an optional commit with the user's pending changes
1128 # and shelvectx is the unshelved changes. Then we merge it all down
1135 # and shelvectx is the unshelved changes. Then we merge it all down
1129 # to the original pctx.
1136 # to the original pctx.
1130
1137
1131 activebookmark = _backupactivebookmark(repo)
1138 activebookmark = _backupactivebookmark(repo)
1132 tmpwctx, addedbefore = _commitworkingcopychanges(
1139 tmpwctx, addedbefore = _commitworkingcopychanges(
1133 ui, repo, opts, tmpwctx
1140 ui, repo, opts, tmpwctx
1134 )
1141 )
1135 repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
1142 repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
1136 _checkunshelveuntrackedproblems(ui, repo, shelvectx)
1143 _checkunshelveuntrackedproblems(ui, repo, shelvectx)
1137 branchtorestore = b''
1144 branchtorestore = b''
1138 if shelvectx.branch() != shelvectx.p1().branch():
1145 if shelvectx.branch() != shelvectx.p1().branch():
1139 branchtorestore = shelvectx.branch()
1146 branchtorestore = shelvectx.branch()
1140
1147
1141 shelvectx, ispartialunshelve = _rebaserestoredcommit(
1148 shelvectx, ispartialunshelve = _rebaserestoredcommit(
1142 ui,
1149 ui,
1143 repo,
1150 repo,
1144 opts,
1151 opts,
1145 tr,
1152 tr,
1146 oldtiprev,
1153 oldtiprev,
1147 basename,
1154 basename,
1148 pctx,
1155 pctx,
1149 tmpwctx,
1156 tmpwctx,
1150 shelvectx,
1157 shelvectx,
1151 branchtorestore,
1158 branchtorestore,
1152 activebookmark,
1159 activebookmark,
1153 )
1160 )
1154 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
1161 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
1155 with ui.configoverride(overrides, b'unshelve'):
1162 with ui.configoverride(overrides, b'unshelve'):
1156 mergefiles(ui, repo, pctx, shelvectx)
1163 mergefiles(ui, repo, pctx, shelvectx)
1157 restorebranch(ui, repo, branchtorestore)
1164 restorebranch(ui, repo, branchtorestore)
1158 shelvedstate.clear(repo)
1165 shelvedstate.clear(repo)
1159 _finishunshelve(repo, oldtiprev, tr, activebookmark)
1166 _finishunshelve(repo, oldtiprev, tr, activebookmark)
1160 _forgetunknownfiles(repo, shelvectx, addedbefore)
1167 _forgetunknownfiles(repo, shelvectx, addedbefore)
1161 if not ispartialunshelve:
1168 if not ispartialunshelve:
1162 unshelvecleanup(ui, repo, basename, opts)
1169 unshelvecleanup(ui, repo, basename, opts)
1163 finally:
1170 finally:
1164 if tr:
1171 if tr:
1165 tr.release()
1172 tr.release()
1166 lockmod.release(lock)
1173 lockmod.release(lock)
@@ -1,997 +1,994 b''
1 #testcases stripbased phasebased
1 #testcases stripbased phasebased
2 #testcases abortflag abortcommand
2 #testcases abortflag abortcommand
3 #testcases continueflag continuecommand
3 #testcases continueflag continuecommand
4
4
5 $ cat <<EOF >> $HGRCPATH
5 $ cat <<EOF >> $HGRCPATH
6 > [extensions]
6 > [extensions]
7 > mq =
7 > mq =
8 > [defaults]
8 > [defaults]
9 > diff = --nodates --git
9 > diff = --nodates --git
10 > qnew = --date '0 0'
10 > qnew = --date '0 0'
11 > [shelve]
11 > [shelve]
12 > maxbackups = 2
12 > maxbackups = 2
13 > EOF
13 > EOF
14
14
15 #if phasebased
15 #if phasebased
16
16
17 $ cat <<EOF >> $HGRCPATH
17 $ cat <<EOF >> $HGRCPATH
18 > [format]
18 > [format]
19 > internal-phase = yes
19 > internal-phase = yes
20 > EOF
20 > EOF
21
21
22 #endif
22 #endif
23
23
24 #if abortflag
24 #if abortflag
25 $ cat >> $HGRCPATH <<EOF
25 $ cat >> $HGRCPATH <<EOF
26 > [alias]
26 > [alias]
27 > abort = unshelve --abort
27 > abort = unshelve --abort
28 > EOF
28 > EOF
29 #endif
29 #endif
30
30
31 #if continueflag
31 #if continueflag
32 $ cat >> $HGRCPATH <<EOF
32 $ cat >> $HGRCPATH <<EOF
33 > [alias]
33 > [alias]
34 > continue = unshelve --continue
34 > continue = unshelve --continue
35 > EOF
35 > EOF
36 #endif
36 #endif
37
37
38 shelve should leave dirstate clean (issue4055)
38 shelve should leave dirstate clean (issue4055)
39
39
40 $ hg init shelverebase
40 $ hg init shelverebase
41 $ cd shelverebase
41 $ cd shelverebase
42 $ printf 'x\ny\n' > x
42 $ printf 'x\ny\n' > x
43 $ echo z > z
43 $ echo z > z
44 $ hg commit -Aqm xy
44 $ hg commit -Aqm xy
45 $ echo z >> x
45 $ echo z >> x
46 $ hg commit -Aqm z
46 $ hg commit -Aqm z
47 $ hg up 5c4c67fb7dce
47 $ hg up 5c4c67fb7dce
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 $ printf 'a\nx\ny\nz\n' > x
49 $ printf 'a\nx\ny\nz\n' > x
50 $ hg commit -Aqm xyz
50 $ hg commit -Aqm xyz
51 $ echo c >> z
51 $ echo c >> z
52 $ hg shelve
52 $ hg shelve
53 shelved as default
53 shelved as default
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55
55
56 $ hg rebase -d 6c103be8f4e4 --config extensions.rebase=
56 $ hg rebase -d 6c103be8f4e4 --config extensions.rebase=
57 rebasing 2:323bfa07f744( tip)? "xyz" (re)
57 rebasing 2:323bfa07f744( tip)? "xyz" (re)
58 merging x
58 merging x
59 saved backup bundle to \$TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-(78114325|7ae538ef)-rebase.hg (re)
59 saved backup bundle to \$TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-(78114325|7ae538ef)-rebase.hg (re)
60 $ hg unshelve
60 $ hg unshelve
61 unshelving change 'default'
61 unshelving change 'default'
62 rebasing shelved changes
62 rebasing shelved changes
63 $ hg status
63 $ hg status
64 M z
64 M z
65
65
66 $ cd ..
66 $ cd ..
67
67
68 shelve should only unshelve pending changes (issue4068)
68 shelve should only unshelve pending changes (issue4068)
69
69
70 $ hg init onlypendingchanges
70 $ hg init onlypendingchanges
71 $ cd onlypendingchanges
71 $ cd onlypendingchanges
72 $ touch a
72 $ touch a
73 $ hg ci -Aqm a
73 $ hg ci -Aqm a
74 $ touch b
74 $ touch b
75 $ hg ci -Aqm b
75 $ hg ci -Aqm b
76 $ hg up -q 3903775176ed
76 $ hg up -q 3903775176ed
77 $ touch c
77 $ touch c
78 $ hg ci -Aqm c
78 $ hg ci -Aqm c
79
79
80 $ touch d
80 $ touch d
81 $ hg add d
81 $ hg add d
82 $ hg shelve
82 $ hg shelve
83 shelved as default
83 shelved as default
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ hg up -q 0e067c57feba
85 $ hg up -q 0e067c57feba
86 $ hg unshelve
86 $ hg unshelve
87 unshelving change 'default'
87 unshelving change 'default'
88 rebasing shelved changes
88 rebasing shelved changes
89 $ hg status
89 $ hg status
90 A d
90 A d
91
91
92 unshelve should work on an ancestor of the original commit
92 unshelve should work on an ancestor of the original commit
93
93
94 $ hg shelve
94 $ hg shelve
95 shelved as default
95 shelved as default
96 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
96 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
97 $ hg up 3903775176ed
97 $ hg up 3903775176ed
98 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
98 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
99 $ hg unshelve
99 $ hg unshelve
100 unshelving change 'default'
100 unshelving change 'default'
101 rebasing shelved changes
101 rebasing shelved changes
102 $ hg status
102 $ hg status
103 A d
103 A d
104
104
105 test bug 4073 we need to enable obsolete markers for it
105 test bug 4073 we need to enable obsolete markers for it
106
106
107 $ cat >> $HGRCPATH << EOF
107 $ cat >> $HGRCPATH << EOF
108 > [experimental]
108 > [experimental]
109 > evolution.createmarkers=True
109 > evolution.createmarkers=True
110 > EOF
110 > EOF
111 $ hg shelve
111 $ hg shelve
112 shelved as default
112 shelved as default
113 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
113 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
114 $ hg debugobsolete `hg log -r 0e067c57feba -T '{node}'`
114 $ hg debugobsolete `hg log -r 0e067c57feba -T '{node}'`
115 1 new obsolescence markers
115 1 new obsolescence markers
116 obsoleted 1 changesets
116 obsoleted 1 changesets
117 $ hg unshelve
117 $ hg unshelve
118 unshelving change 'default'
118 unshelving change 'default'
119
119
120 unshelve should leave unknown files alone (issue4113)
120 unshelve should leave unknown files alone (issue4113)
121
121
122 $ echo e > e
122 $ echo e > e
123 $ hg shelve
123 $ hg shelve
124 shelved as default
124 shelved as default
125 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
125 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
126 $ hg status
126 $ hg status
127 ? e
127 ? e
128 $ hg unshelve
128 $ hg unshelve
129 unshelving change 'default'
129 unshelving change 'default'
130 $ hg status
130 $ hg status
131 A d
131 A d
132 ? e
132 ? e
133 $ cat e
133 $ cat e
134 e
134 e
135
135
136 unshelve should keep a copy of unknown files
136 unshelve should keep a copy of unknown files
137
137
138 $ hg add e
138 $ hg add e
139 $ hg shelve
139 $ hg shelve
140 shelved as default
140 shelved as default
141 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
142 $ echo z > e
142 $ echo z > e
143 $ hg unshelve
143 $ hg unshelve
144 unshelving change 'default'
144 unshelving change 'default'
145 $ cat e
145 $ cat e
146 e
146 e
147 $ cat e.orig
147 $ cat e.orig
148 z
148 z
149 $ rm e.orig
149 $ rm e.orig
150
150
151 restores backup of unknown file to right directory
151 restores backup of unknown file to right directory
152
152
153 $ hg shelve
153 $ hg shelve
154 shelved as default
154 shelved as default
155 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
155 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
156 $ echo z > e
156 $ echo z > e
157 $ mkdir dir
157 $ mkdir dir
158 $ hg unshelve --cwd dir
158 $ hg unshelve --cwd dir
159 unshelving change 'default'
159 unshelving change 'default'
160 $ rmdir dir
160 $ rmdir dir
161 $ cat e
161 $ cat e
162 e
162 e
163 $ cat e.orig
163 $ cat e.orig
164 z
164 z
165
165
166 unshelve and conflicts with tracked and untracked files
166 unshelve and conflicts with tracked and untracked files
167
167
168 preparing:
168 preparing:
169
169
170 $ rm -f *.orig
170 $ rm -f *.orig
171 $ hg ci -qm 'commit stuff'
171 $ hg ci -qm 'commit stuff'
172 $ hg phase -p null:
172 $ hg phase -p null:
173
173
174 no other changes - no merge:
174 no other changes - no merge:
175
175
176 $ echo f > f
176 $ echo f > f
177 $ hg add f
177 $ hg add f
178 $ hg shelve
178 $ hg shelve
179 shelved as default
179 shelved as default
180 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
180 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
181 $ echo g > f
181 $ echo g > f
182 $ hg unshelve
182 $ hg unshelve
183 unshelving change 'default'
183 unshelving change 'default'
184 $ hg st
184 $ hg st
185 A f
185 A f
186 ? f.orig
186 ? f.orig
187 $ cat f
187 $ cat f
188 f
188 f
189 $ cat f.orig
189 $ cat f.orig
190 g
190 g
191
191
192 other uncommitted changes - merge:
192 other uncommitted changes - merge:
193
193
194 $ hg st
194 $ hg st
195 A f
195 A f
196 ? f.orig
196 ? f.orig
197 $ hg shelve
197 $ hg shelve
198 shelved as default
198 shelved as default
199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
200 #if repobundlerepo
200 #if repobundlerepo
201 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()' --hidden
201 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()' --hidden
202 o [48] changes to: commit stuff shelve@localhost (re)
202 o [48] changes to: commit stuff shelve@localhost (re)
203 |
203 |
204 ~
204 ~
205 #endif
205 #endif
206 $ hg log -G --template '{rev} {desc|firstline} {author}'
206 $ hg log -G --template '{rev} {desc|firstline} {author}'
207 @ [37] commit stuff test (re)
207 @ [37] commit stuff test (re)
208 |
208 |
209 | o 2 c test
209 | o 2 c test
210 |/
210 |/
211 o 0 a test
211 o 0 a test
212
212
213 $ mv f.orig f
213 $ mv f.orig f
214 $ echo 1 > a
214 $ echo 1 > a
215 $ hg unshelve --date '1073741824 0'
215 $ hg unshelve --date '1073741824 0'
216 unshelving change 'default'
216 unshelving change 'default'
217 temporarily committing pending changes (restore with 'hg unshelve --abort')
217 temporarily committing pending changes (restore with 'hg unshelve --abort')
218 rebasing shelved changes
218 rebasing shelved changes
219 merging f
219 merging f
220 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
220 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
221 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
221 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
222 [240]
222 [240]
223
223
224 #if phasebased
224 #if phasebased
225 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
225 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
226 @ 9 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
226 @ 9 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
227 |
227 |
228 | @ 8 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
228 | @ 8 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
229 |/
229 |/
230 o 7 commit stuff test 1970-01-01 00:00 +0000
230 o 7 commit stuff test 1970-01-01 00:00 +0000
231 |
231 |
232 | o 2 c test 1970-01-01 00:00 +0000
232 | o 2 c test 1970-01-01 00:00 +0000
233 |/
233 |/
234 o 0 a test 1970-01-01 00:00 +0000
234 o 0 a test 1970-01-01 00:00 +0000
235
235
236 #endif
236 #endif
237
237
238 #if stripbased
238 #if stripbased
239 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
239 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
240 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
240 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
241 |
241 |
242 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
242 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
243 |/
243 |/
244 o 3 commit stuff test 1970-01-01 00:00 +0000
244 o 3 commit stuff test 1970-01-01 00:00 +0000
245 |
245 |
246 | o 2 c test 1970-01-01 00:00 +0000
246 | o 2 c test 1970-01-01 00:00 +0000
247 |/
247 |/
248 o 0 a test 1970-01-01 00:00 +0000
248 o 0 a test 1970-01-01 00:00 +0000
249
249
250 #endif
250 #endif
251
251
252 $ hg st
252 $ hg st
253 M f
253 M f
254 ? f.orig
254 ? f.orig
255 $ cat f
255 $ cat f
256 <<<<<<< working-copy: d44eae5c3d33 - shelve: pending changes temporary commit
256 <<<<<<< working-copy: d44eae5c3d33 - shelve: pending changes temporary commit
257 g
257 g
258 =======
258 =======
259 f
259 f
260 >>>>>>> shelve: aef214a5229c - shelve: changes to: commit stuff
260 >>>>>>> shelve: aef214a5229c - shelve: changes to: commit stuff
261 $ cat f.orig
261 $ cat f.orig
262 g
262 g
263 $ hg unshelve --abort -t false
263 $ hg unshelve --abort -t false
264 tool option will be ignored
264 tool option will be ignored
265 unshelve of 'default' aborted
265 unshelve of 'default' aborted
266 $ hg st
266 $ hg st
267 M a
267 M a
268 ? f.orig
268 ? f.orig
269 $ cat f.orig
269 $ cat f.orig
270 g
270 g
271 $ hg unshelve
271 $ hg unshelve
272 unshelving change 'default'
272 unshelving change 'default'
273 temporarily committing pending changes (restore with 'hg unshelve --abort')
273 temporarily committing pending changes (restore with 'hg unshelve --abort')
274 rebasing shelved changes
274 rebasing shelved changes
275 $ hg st
275 $ hg st
276 M a
276 M a
277 A f
277 A f
278 ? f.orig
278 ? f.orig
279
279
280 other committed changes - merge:
280 other committed changes - merge:
281
281
282 $ hg shelve f
282 $ hg shelve f
283 shelved as default
283 shelved as default
284 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
284 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
285 $ hg ci a -m 'intermediate other change'
285 $ hg ci a -m 'intermediate other change'
286 $ mv f.orig f
286 $ mv f.orig f
287 $ hg unshelve
287 $ hg unshelve
288 unshelving change 'default'
288 unshelving change 'default'
289 rebasing shelved changes
289 rebasing shelved changes
290 merging f
290 merging f
291 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
291 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
292 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
292 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
293 [240]
293 [240]
294 $ hg st
294 $ hg st
295 M f
295 M f
296 ? f.orig
296 ? f.orig
297 $ cat f
297 $ cat f
298 <<<<<<< working-copy: 6b563750f973 - test: intermediate other change
298 <<<<<<< working-copy: 6b563750f973 - test: intermediate other change
299 g
299 g
300 =======
300 =======
301 f
301 f
302 >>>>>>> shelve: aef214a5229c - shelve: changes to: commit stuff
302 >>>>>>> shelve: aef214a5229c - shelve: changes to: commit stuff
303 $ cat f.orig
303 $ cat f.orig
304 g
304 g
305
305
306 #if abortcommand
306 #if abortcommand
307 when in dry-run mode
307 when in dry-run mode
308 $ hg abort --dry-run
308 $ hg abort --dry-run
309 unshelve in progress, will be aborted
309 unshelve in progress, will be aborted
310 #endif
310 #endif
311
311
312 $ hg abort
312 $ hg abort
313 unshelve of 'default' aborted
313 unshelve of 'default' aborted
314 $ hg st
314 $ hg st
315 ? f.orig
315 ? f.orig
316 $ cat f.orig
316 $ cat f.orig
317 g
317 g
318 $ hg shelve --delete default
318 $ hg shelve --delete default
319 $ cd ..
319 $ cd ..
320
320
321 you shouldn't be able to ask for the patch/stats of the most recent shelve if
321 you shouldn't be able to ask for the patch/stats of the most recent shelve if
322 there are no shelves
322 there are no shelves
323
323
324 $ hg init noshelves
324 $ hg init noshelves
325 $ cd noshelves
325 $ cd noshelves
326
326
327 $ hg shelve --patch
327 $ hg shelve --patch
328 abort: there are no shelves to show
328 abort: there are no shelves to show
329 [255]
329 [255]
330 $ hg shelve --stat
330 $ hg shelve --stat
331 abort: there are no shelves to show
331 abort: there are no shelves to show
332 [255]
332 [255]
333
333
334 $ cd ..
334 $ cd ..
335
335
336 test .orig files go where the user wants them to
336 test .orig files go where the user wants them to
337 ---------------------------------------------------------------
337 ---------------------------------------------------------------
338 $ hg init salvage
338 $ hg init salvage
339 $ cd salvage
339 $ cd salvage
340 $ echo 'content' > root
340 $ echo 'content' > root
341 $ hg commit -A -m 'root' -q
341 $ hg commit -A -m 'root' -q
342 $ echo '' > root
342 $ echo '' > root
343 $ hg shelve -q
343 $ hg shelve -q
344 $ echo 'contADDent' > root
344 $ echo 'contADDent' > root
345 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
345 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
346 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
346 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
347 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
347 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
348 [240]
348 [240]
349 $ ls .hg/origbackups
349 $ ls .hg/origbackups
350 root
350 root
351 $ rm -rf .hg/origbackups
351 $ rm -rf .hg/origbackups
352
352
353 test Abort unshelve always gets user out of the unshelved state
353 test Abort unshelve always gets user out of the unshelved state
354 ---------------------------------------------------------------
354 ---------------------------------------------------------------
355
355
356 with a corrupted shelve state file
356 with a corrupted shelve state file
357 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
357 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
358 $ mv ../corrupt-shelvedstate .hg/shelvestate
358 $ mv ../corrupt-shelvedstate .hg/shelvestate
359 $ hg unshelve --abort 2>&1 | grep 'aborted'
359 $ hg unshelve --abort 2>&1 | grep 'aborted'
360 unshelve of 'default' aborted
360 unshelve of 'default' aborted
361 $ hg summary
361 $ hg summary
362 parent: 0:ae8c668541e8 tip
362 parent: 0:ae8c668541e8 tip
363 root
363 root
364 branch: default
364 branch: default
365 commit: 1 modified
365 commit: 1 modified
366 update: (current)
366 update: (current)
367 phases: 1 draft
367 phases: 1 draft
368 $ hg up -C .
368 $ hg up -C .
369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
370
370
371 $ cd ..
371 $ cd ..
372
372
373 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
373 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
374 unknown file is the same as a shelved added file, except that it will be in
374 unknown file is the same as a shelved added file, except that it will be in
375 unknown state after unshelve if and only if it was either absent or unknown
375 unknown state after unshelve if and only if it was either absent or unknown
376 before the unshelve operation.
376 before the unshelve operation.
377
377
378 $ hg init unknowns
378 $ hg init unknowns
379 $ cd unknowns
379 $ cd unknowns
380
380
381 The simplest case is if I simply have an unknown file that I shelve and unshelve
381 The simplest case is if I simply have an unknown file that I shelve and unshelve
382
382
383 $ echo unknown > unknown
383 $ echo unknown > unknown
384 $ hg status
384 $ hg status
385 ? unknown
385 ? unknown
386 $ hg shelve --unknown
386 $ hg shelve --unknown
387 shelved as default
387 shelved as default
388 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
388 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
389 $ hg status
389 $ hg status
390 $ hg unshelve
390 $ hg unshelve
391 unshelving change 'default'
391 unshelving change 'default'
392 $ hg status
392 $ hg status
393 ? unknown
393 ? unknown
394 $ rm unknown
394 $ rm unknown
395
395
396 If I shelve, add the file, and unshelve, does it stay added?
396 If I shelve, add the file, and unshelve, does it stay added?
397
397
398 $ echo unknown > unknown
398 $ echo unknown > unknown
399 $ hg shelve -u
399 $ hg shelve -u
400 shelved as default
400 shelved as default
401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
402 $ hg status
402 $ hg status
403 $ touch unknown
403 $ touch unknown
404 $ hg add unknown
404 $ hg add unknown
405 $ hg status
405 $ hg status
406 A unknown
406 A unknown
407 $ hg unshelve
407 $ hg unshelve
408 unshelving change 'default'
408 unshelving change 'default'
409 temporarily committing pending changes (restore with 'hg unshelve --abort')
409 temporarily committing pending changes (restore with 'hg unshelve --abort')
410 rebasing shelved changes
410 rebasing shelved changes
411 merging unknown
411 merging unknown
412 $ hg status
412 $ hg status
413 A unknown
413 A unknown
414 $ hg forget unknown
414 $ hg forget unknown
415 $ rm unknown
415 $ rm unknown
416
416
417 And if I shelve, commit, then unshelve, does it become modified?
417 And if I shelve, commit, then unshelve, does it become modified?
418
418
419 $ echo unknown > unknown
419 $ echo unknown > unknown
420 $ hg shelve -u
420 $ hg shelve -u
421 shelved as default
421 shelved as default
422 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
422 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
423 $ hg status
423 $ hg status
424 $ touch unknown
424 $ touch unknown
425 $ hg add unknown
425 $ hg add unknown
426 $ hg commit -qm "Add unknown"
426 $ hg commit -qm "Add unknown"
427 $ hg status
427 $ hg status
428 $ hg unshelve
428 $ hg unshelve
429 unshelving change 'default'
429 unshelving change 'default'
430 rebasing shelved changes
430 rebasing shelved changes
431 merging unknown
431 merging unknown
432 $ hg status
432 $ hg status
433 M unknown
433 M unknown
434 $ hg remove --force unknown
434 $ hg remove --force unknown
435 $ hg commit -qm "Remove unknown"
435 $ hg commit -qm "Remove unknown"
436
436
437 $ cd ..
437 $ cd ..
438
438
439 We expects that non-bare shelve keeps newly created branch in
439 We expects that non-bare shelve keeps newly created branch in
440 working directory.
440 working directory.
441
441
442 $ hg init shelve-preserve-new-branch
442 $ hg init shelve-preserve-new-branch
443 $ cd shelve-preserve-new-branch
443 $ cd shelve-preserve-new-branch
444 $ echo "a" >> a
444 $ echo "a" >> a
445 $ hg add a
445 $ hg add a
446 $ echo "b" >> b
446 $ echo "b" >> b
447 $ hg add b
447 $ hg add b
448 $ hg commit -m "ab"
448 $ hg commit -m "ab"
449 $ echo "aa" >> a
449 $ echo "aa" >> a
450 $ echo "bb" >> b
450 $ echo "bb" >> b
451 $ hg branch new-branch
451 $ hg branch new-branch
452 marked working directory as branch new-branch
452 marked working directory as branch new-branch
453 (branches are permanent and global, did you want a bookmark?)
453 (branches are permanent and global, did you want a bookmark?)
454 $ hg status
454 $ hg status
455 M a
455 M a
456 M b
456 M b
457 $ hg branch
457 $ hg branch
458 new-branch
458 new-branch
459 $ hg shelve a
459 $ hg shelve a
460 shelved as default
460 shelved as default
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 $ hg branch
462 $ hg branch
463 new-branch
463 new-branch
464 $ hg status
464 $ hg status
465 M b
465 M b
466 $ touch "c" >> c
466 $ touch "c" >> c
467 $ hg add c
467 $ hg add c
468 $ hg status
468 $ hg status
469 M b
469 M b
470 A c
470 A c
471 $ hg shelve --exclude c
471 $ hg shelve --exclude c
472 shelved as default-01
472 shelved as default-01
473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 $ hg branch
474 $ hg branch
475 new-branch
475 new-branch
476 $ hg status
476 $ hg status
477 A c
477 A c
478 $ hg shelve --include c
478 $ hg shelve --include c
479 shelved as default-02
479 shelved as default-02
480 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
480 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
481 $ hg branch
481 $ hg branch
482 new-branch
482 new-branch
483 $ hg status
483 $ hg status
484 $ echo "d" >> d
484 $ echo "d" >> d
485 $ hg add d
485 $ hg add d
486 $ hg status
486 $ hg status
487 A d
487 A d
488
488
489 We expect that bare-shelve will not keep branch in current working directory.
489 We expect that bare-shelve will not keep branch in current working directory.
490
490
491 $ hg shelve
491 $ hg shelve
492 shelved as default-03
492 shelved as default-03
493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
494 $ hg branch
494 $ hg branch
495 default
495 default
496 $ cd ..
496 $ cd ..
497
497
498 When i shelve commit on newly created branch i expect
498 When i shelve commit on newly created branch i expect
499 that after unshelve newly created branch will be preserved.
499 that after unshelve newly created branch will be preserved.
500
500
501 $ hg init shelve_on_new_branch_simple
501 $ hg init shelve_on_new_branch_simple
502 $ cd shelve_on_new_branch_simple
502 $ cd shelve_on_new_branch_simple
503 $ echo "aaa" >> a
503 $ echo "aaa" >> a
504 $ hg commit -A -m "a"
504 $ hg commit -A -m "a"
505 adding a
505 adding a
506 $ hg branch
506 $ hg branch
507 default
507 default
508 $ hg branch test
508 $ hg branch test
509 marked working directory as branch test
509 marked working directory as branch test
510 (branches are permanent and global, did you want a bookmark?)
510 (branches are permanent and global, did you want a bookmark?)
511 $ echo "bbb" >> a
511 $ echo "bbb" >> a
512 $ hg status
512 $ hg status
513 M a
513 M a
514 $ hg shelve
514 $ hg shelve
515 shelved as default
515 shelved as default
516 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
517 $ hg branch
517 $ hg branch
518 default
518 default
519 $ echo "bbb" >> b
519 $ echo "bbb" >> b
520 $ hg status
520 $ hg status
521 ? b
521 ? b
522 $ hg unshelve
522 $ hg unshelve
523 unshelving change 'default'
523 unshelving change 'default'
524 marked working directory as branch test
524 marked working directory as branch test
525 $ hg status
525 $ hg status
526 M a
526 M a
527 ? b
527 ? b
528 $ hg branch
528 $ hg branch
529 test
529 test
530 $ cd ..
530 $ cd ..
531
531
532 When i shelve commit on newly created branch, make
532 When i shelve commit on newly created branch, make
533 some changes, unshelve it and running into merge
533 some changes, unshelve it and running into merge
534 conflicts i expect that after fixing them and
534 conflicts i expect that after fixing them and
535 running unshelve --continue newly created branch
535 running unshelve --continue newly created branch
536 will be preserved.
536 will be preserved.
537
537
538 $ hg init shelve_on_new_branch_conflict
538 $ hg init shelve_on_new_branch_conflict
539 $ cd shelve_on_new_branch_conflict
539 $ cd shelve_on_new_branch_conflict
540 $ echo "aaa" >> a
540 $ echo "aaa" >> a
541 $ hg commit -A -m "a"
541 $ hg commit -A -m "a"
542 adding a
542 adding a
543 $ hg branch
543 $ hg branch
544 default
544 default
545 $ hg branch test
545 $ hg branch test
546 marked working directory as branch test
546 marked working directory as branch test
547 (branches are permanent and global, did you want a bookmark?)
547 (branches are permanent and global, did you want a bookmark?)
548 $ echo "bbb" >> a
548 $ echo "bbb" >> a
549 $ hg status
549 $ hg status
550 M a
550 M a
551 $ hg shelve
551 $ hg shelve
552 shelved as default
552 shelved as default
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 $ hg branch
554 $ hg branch
555 default
555 default
556 $ echo "ccc" >> a
556 $ echo "ccc" >> a
557 $ hg status
557 $ hg status
558 M a
558 M a
559 $ hg unshelve
559 $ hg unshelve
560 unshelving change 'default'
560 unshelving change 'default'
561 temporarily committing pending changes (restore with 'hg unshelve --abort')
561 temporarily committing pending changes (restore with 'hg unshelve --abort')
562 rebasing shelved changes
562 rebasing shelved changes
563 merging a
563 merging a
564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
565 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
565 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
566 [240]
566 [240]
567 $ echo "aaabbbccc" > a
567 $ echo "aaabbbccc" > a
568 $ rm a.orig
568 $ rm a.orig
569 $ hg resolve --mark a
569 $ hg resolve --mark a
570 (no more unresolved files)
570 (no more unresolved files)
571 continue: hg unshelve --continue
571 continue: hg unshelve --continue
572 $ hg continue
572 $ hg continue
573 marked working directory as branch test
573 marked working directory as branch test
574 unshelve of 'default' complete
574 unshelve of 'default' complete
575 $ cat a
575 $ cat a
576 aaabbbccc
576 aaabbbccc
577 $ hg status
577 $ hg status
578 M a
578 M a
579 $ hg branch
579 $ hg branch
580 test
580 test
581 $ hg commit -m "test-commit"
581 $ hg commit -m "test-commit"
582
582
583 When i shelve on test branch, update to default branch
583 When i shelve on test branch, update to default branch
584 and unshelve i expect that it will not preserve previous
584 and unshelve i expect that it will not preserve previous
585 test branch.
585 test branch.
586
586
587 $ echo "xxx" > b
587 $ echo "xxx" > b
588 $ hg add b
588 $ hg add b
589 $ hg shelve
589 $ hg shelve
590 shelved as test
590 shelved as test
591 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
591 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
592 $ hg update -r 7049e48789d7
592 $ hg update -r 7049e48789d7
593 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
593 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 $ hg unshelve
594 $ hg unshelve
595 unshelving change 'test'
595 unshelving change 'test'
596 rebasing shelved changes
596 rebasing shelved changes
597 $ hg status
597 $ hg status
598 A b
598 A b
599 $ hg branch
599 $ hg branch
600 default
600 default
601 $ cd ..
601 $ cd ..
602
602
603 When i unshelve resulting in merge conflicts and makes saved
603 When i unshelve resulting in merge conflicts and makes saved
604 file shelvedstate looks like in previous versions in
604 file shelvedstate looks like in previous versions in
605 mercurial(without restore branch information in 7th line) i
605 mercurial(without restore branch information in 7th line) i
606 expect that after resolving conflicts and successfully
606 expect that after resolving conflicts and successfully
607 running 'shelve --continue' the branch information won't be
607 running 'shelve --continue' the branch information won't be
608 restored and branch will be unchanged.
608 restored and branch will be unchanged.
609
609
610 shelve on new branch, conflict with previous shelvedstate
610 shelve on new branch, conflict with previous shelvedstate
611
611
612 $ hg init conflict
612 $ hg init conflict
613 $ cd conflict
613 $ cd conflict
614 $ echo "aaa" >> a
614 $ echo "aaa" >> a
615 $ hg commit -A -m "a"
615 $ hg commit -A -m "a"
616 adding a
616 adding a
617 $ hg branch
617 $ hg branch
618 default
618 default
619 $ hg branch test
619 $ hg branch test
620 marked working directory as branch test
620 marked working directory as branch test
621 (branches are permanent and global, did you want a bookmark?)
621 (branches are permanent and global, did you want a bookmark?)
622 $ echo "bbb" >> a
622 $ echo "bbb" >> a
623 $ hg status
623 $ hg status
624 M a
624 M a
625 $ hg shelve
625 $ hg shelve
626 shelved as default
626 shelved as default
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 $ hg branch
628 $ hg branch
629 default
629 default
630 $ echo "ccc" >> a
630 $ echo "ccc" >> a
631 $ hg status
631 $ hg status
632 M a
632 M a
633 $ hg unshelve
633 $ hg unshelve
634 unshelving change 'default'
634 unshelving change 'default'
635 temporarily committing pending changes (restore with 'hg unshelve --abort')
635 temporarily committing pending changes (restore with 'hg unshelve --abort')
636 rebasing shelved changes
636 rebasing shelved changes
637 merging a
637 merging a
638 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
638 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
639 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
639 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
640 [240]
640 [240]
641
641
642 Removing restore branch information from shelvedstate file(making it looks like
642 Removing restore branch information from shelvedstate file(making it looks like
643 in previous versions) and running unshelve --continue
643 in previous versions) and running unshelve --continue
644
644
645 $ cp .hg/shelvedstate .hg/shelvedstate_old
645 $ cp .hg/shelvedstate .hg/shelvedstate_old
646 $ cat .hg/shelvedstate_old | grep -v 'branchtorestore' > .hg/shelvedstate
646 $ cat .hg/shelvedstate_old | grep -v 'branchtorestore' > .hg/shelvedstate
647
647
648 $ echo "aaabbbccc" > a
648 $ echo "aaabbbccc" > a
649 $ rm a.orig
649 $ rm a.orig
650 $ hg resolve --mark a
650 $ hg resolve --mark a
651 (no more unresolved files)
651 (no more unresolved files)
652 continue: hg unshelve --continue
652 continue: hg unshelve --continue
653
653
654 #if continuecommand
654 #if continuecommand
655 $ hg continue --dry-run
655 $ hg continue --dry-run
656 unshelve in progress, will be resumed
656 unshelve in progress, will be resumed
657 #endif
657 #endif
658
658
659 $ hg continue
659 $ hg continue
660 unshelve of 'default' complete
660 unshelve of 'default' complete
661 $ cat a
661 $ cat a
662 aaabbbccc
662 aaabbbccc
663 $ hg status
663 $ hg status
664 M a
664 M a
665 $ hg branch
665 $ hg branch
666 default
666 default
667 $ cd ..
667 $ cd ..
668
668
669 On non bare shelve the branch information shouldn't be restored
669 On non bare shelve the branch information shouldn't be restored
670
670
671 $ hg init bare_shelve_on_new_branch
671 $ hg init bare_shelve_on_new_branch
672 $ cd bare_shelve_on_new_branch
672 $ cd bare_shelve_on_new_branch
673 $ echo "aaa" >> a
673 $ echo "aaa" >> a
674 $ hg commit -A -m "a"
674 $ hg commit -A -m "a"
675 adding a
675 adding a
676 $ hg branch
676 $ hg branch
677 default
677 default
678 $ hg branch test
678 $ hg branch test
679 marked working directory as branch test
679 marked working directory as branch test
680 (branches are permanent and global, did you want a bookmark?)
680 (branches are permanent and global, did you want a bookmark?)
681 $ echo "bbb" >> a
681 $ echo "bbb" >> a
682 $ hg status
682 $ hg status
683 M a
683 M a
684 $ hg shelve a
684 $ hg shelve a
685 shelved as default
685 shelved as default
686 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
686 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
687 $ hg branch
687 $ hg branch
688 test
688 test
689 $ hg branch default
689 $ hg branch default
690 marked working directory as branch default
690 marked working directory as branch default
691 (branches are permanent and global, did you want a bookmark?)
691 (branches are permanent and global, did you want a bookmark?)
692 $ echo "bbb" >> b
692 $ echo "bbb" >> b
693 $ hg status
693 $ hg status
694 ? b
694 ? b
695 $ hg unshelve
695 $ hg unshelve
696 unshelving change 'default'
696 unshelving change 'default'
697 $ hg status
697 $ hg status
698 M a
698 M a
699 ? b
699 ? b
700 $ hg branch
700 $ hg branch
701 default
701 default
702 $ cd ..
702 $ cd ..
703
703
704 Prepare unshelve with a corrupted shelvedstate
704 Prepare unshelve with a corrupted shelvedstate
705 $ hg init r1 && cd r1
705 $ hg init r1 && cd r1
706 $ echo text1 > file && hg add file
706 $ echo text1 > file && hg add file
707 $ hg shelve
707 $ hg shelve
708 shelved as default
708 shelved as default
709 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
709 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
710 $ echo text2 > file && hg ci -Am text1
710 $ echo text2 > file && hg ci -Am text1
711 adding file
711 adding file
712 $ hg unshelve
712 $ hg unshelve
713 unshelving change 'default'
713 unshelving change 'default'
714 rebasing shelved changes
714 rebasing shelved changes
715 merging file
715 merging file
716 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
716 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
717 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
717 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
718 [240]
718 [240]
719 $ echo somethingsomething > .hg/shelvedstate
719 $ echo somethingsomething > .hg/shelvedstate
720
720
721 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
721 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
722 $ hg continue
722 $ hg continue
723 abort: corrupted shelved state file
723 abort: corrupted shelved state file
724 (please run hg unshelve --abort to abort unshelve operation)
724 (please run hg unshelve --abort to abort unshelve operation)
725 [255]
725 [255]
726
726
727 Unshelve --abort works with a corrupted shelvedstate
727 Unshelve --abort works with a corrupted shelvedstate
728 $ hg abort
728 $ hg abort
729 abort: could not read shelved state file, your working copy may be in an unexpected state
729 abort: could not read shelved state file, your working copy may be in an unexpected state
730 please update to some commit
730 please update to some commit
731
731
732 [255]
732 [255]
733
733
734 Unshelve --abort fails with appropriate message if there's no unshelve in
734 Unshelve --abort fails with appropriate message if there's no unshelve in
735 progress
735 progress
736
736
737 #if abortflag
737 #if abortflag
738 $ hg unshelve --abort
738 $ hg unshelve --abort
739 abort: no unshelve in progress
739 abort: no unshelve in progress
740 [20]
740 [20]
741 #else
741 #else
742 $ hg abort
742 $ hg abort
743 aborting the merge, updating back to 9451eaa6eee3
743 aborting the merge, updating back to 9451eaa6eee3
744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
745 #endif
745 #endif
746 $ cd ..
746 $ cd ..
747
747
748 Test corrupt shelves (in .hg/shelved/, not .hg/shelvestate)
748 Test corrupt shelves (in .hg/shelved/, not .hg/shelvestate)
749 $ hg init corrupt-shelves
749 $ hg init corrupt-shelves
750 $ cd corrupt-shelves
750 $ cd corrupt-shelves
751 $ mkdir .hg/shelved
751 $ mkdir .hg/shelved
752
752
753 # A (corrupt) .patch file without a .hg file
753 # A (corrupt) .patch file without a .hg file
754 $ touch .hg/shelved/junk1.patch
754 $ touch .hg/shelved/junk1.patch
755 $ hg shelve -l
755 $ hg shelve -l
756 junk1 (* ago) (glob)
757 $ hg unshelve
756 $ hg unshelve
758 unshelving change 'junk1'
757 abort: no shelved changes to apply!
759 abort: $ENOENT$: '$TESTTMP/corrupt-shelves/.hg/shelved/junk1.hg'
758 [20]
760 [255]
761 $ hg shelve -d junk1
759 $ hg shelve -d junk1
760 abort: shelved change 'junk1' not found
761 [10]
762 $ find .hg/shelve*
762 $ find .hg/shelve*
763 .hg/shelve-backup
764 .hg/shelve-backup/junk1.patch
765 .hg/shelved
763 .hg/shelved
764 .hg/shelved/junk1.patch
766
765
767 # A .hg file without a .patch file
766 # A .hg file without a .patch file
768 $ touch .hg/shelved/junk2.hg
767 $ touch .hg/shelved/junk2.hg
769 $ hg shelve -l
768 $ hg shelve -l
770 $ hg unshelve
769 $ hg unshelve
771 abort: no shelved changes to apply!
770 abort: no shelved changes to apply!
772 [20]
771 [20]
773 $ hg shelve -d junk2
772 $ hg shelve -d junk2
774 abort: shelved change 'junk2' not found
773 abort: shelved change 'junk2' not found
775 [10]
774 [10]
776 $ find .hg/shelve*
775 $ find .hg/shelve*
777 .hg/shelve-backup
778 .hg/shelve-backup/junk1.patch
779 .hg/shelved
776 .hg/shelved
777 .hg/shelved/junk1.patch
780 .hg/shelved/junk2.hg
778 .hg/shelved/junk2.hg
781
779
782 # A file with an unexpected extension
780 # A file with an unexpected extension
783 $ touch .hg/shelved/junk3
781 $ touch .hg/shelved/junk3
784 $ hg shelve -l 2>&1 | grep ValueError
782 $ hg shelve -l 2>&1 | grep ValueError
785 ValueError: not enough values to unpack (expected 2, got 1)
783 ValueError: not enough values to unpack (expected 2, got 1)
786 $ hg unshelve 2>&1 | grep ValueError
784 $ hg unshelve 2>&1 | grep ValueError
787 ValueError: not enough values to unpack (expected 2, got 1)
785 ValueError: not enough values to unpack (expected 2, got 1)
788 $ hg shelve -d junk3
786 $ hg shelve -d junk3
789 abort: shelved change 'junk3' not found
787 abort: shelved change 'junk3' not found
790 [10]
788 [10]
791 $ find .hg/shelve*
789 $ find .hg/shelve*
792 .hg/shelve-backup
793 .hg/shelve-backup/junk1.patch
794 .hg/shelved
790 .hg/shelved
791 .hg/shelved/junk1.patch
795 .hg/shelved/junk3
792 .hg/shelved/junk3
796 .hg/shelved/junk2.hg
793 .hg/shelved/junk2.hg
797
794
798 $ cd ..
795 $ cd ..
799
796
800 Unshelve respects --keep even if user intervention is needed
797 Unshelve respects --keep even if user intervention is needed
801 $ hg init unshelvekeep && cd unshelvekeep
798 $ hg init unshelvekeep && cd unshelvekeep
802 $ echo 1 > file && hg ci -Am 1
799 $ echo 1 > file && hg ci -Am 1
803 adding file
800 adding file
804 $ echo 2 >> file
801 $ echo 2 >> file
805 $ hg shelve
802 $ hg shelve
806 shelved as default
803 shelved as default
807 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
804 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
808 $ echo 3 >> file && hg ci -Am 13
805 $ echo 3 >> file && hg ci -Am 13
809 $ hg shelve --list
806 $ hg shelve --list
810 default (*s ago) * changes to: 1 (glob)
807 default (*s ago) * changes to: 1 (glob)
811 $ hg unshelve --keep
808 $ hg unshelve --keep
812 unshelving change 'default'
809 unshelving change 'default'
813 rebasing shelved changes
810 rebasing shelved changes
814 merging file
811 merging file
815 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
812 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
816 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
813 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
817 [240]
814 [240]
818 $ hg resolve --mark file
815 $ hg resolve --mark file
819 (no more unresolved files)
816 (no more unresolved files)
820 continue: hg unshelve --continue
817 continue: hg unshelve --continue
821 $ hg continue
818 $ hg continue
822 unshelve of 'default' complete
819 unshelve of 'default' complete
823 $ hg shelve --list
820 $ hg shelve --list
824 default (*s ago) * changes to: 1 (glob)
821 default (*s ago) * changes to: 1 (glob)
825 $ cd ..
822 $ cd ..
826
823
827 Unshelving when there are deleted files does not crash (issue4176)
824 Unshelving when there are deleted files does not crash (issue4176)
828 $ hg init unshelve-deleted-file && cd unshelve-deleted-file
825 $ hg init unshelve-deleted-file && cd unshelve-deleted-file
829 $ echo a > a && echo b > b && hg ci -Am ab
826 $ echo a > a && echo b > b && hg ci -Am ab
830 adding a
827 adding a
831 adding b
828 adding b
832 $ echo aa > a && hg shelve
829 $ echo aa > a && hg shelve
833 shelved as default
830 shelved as default
834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
835 $ rm b
832 $ rm b
836 $ hg st
833 $ hg st
837 ! b
834 ! b
838 $ hg unshelve
835 $ hg unshelve
839 unshelving change 'default'
836 unshelving change 'default'
840 $ hg shelve
837 $ hg shelve
841 shelved as default
838 shelved as default
842 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
843 $ rm a && echo b > b
840 $ rm a && echo b > b
844 $ hg st
841 $ hg st
845 ! a
842 ! a
846 $ hg unshelve
843 $ hg unshelve
847 unshelving change 'default'
844 unshelving change 'default'
848 abort: shelved change touches missing files
845 abort: shelved change touches missing files
849 (run hg status to see which files are missing)
846 (run hg status to see which files are missing)
850 [255]
847 [255]
851 $ hg st
848 $ hg st
852 ! a
849 ! a
853 $ cd ..
850 $ cd ..
854
851
855 New versions of Mercurial know how to read onld shelvedstate files
852 New versions of Mercurial know how to read onld shelvedstate files
856 $ hg init oldshelvedstate
853 $ hg init oldshelvedstate
857 $ cd oldshelvedstate
854 $ cd oldshelvedstate
858 $ echo root > root && hg ci -Am root
855 $ echo root > root && hg ci -Am root
859 adding root
856 adding root
860 $ echo 1 > a
857 $ echo 1 > a
861 $ hg add a
858 $ hg add a
862 $ hg shelve --name ashelve
859 $ hg shelve --name ashelve
863 shelved as ashelve
860 shelved as ashelve
864 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
861 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
865 $ echo 2 > a
862 $ echo 2 > a
866 $ hg ci -Am a
863 $ hg ci -Am a
867 adding a
864 adding a
868 $ hg unshelve
865 $ hg unshelve
869 unshelving change 'ashelve'
866 unshelving change 'ashelve'
870 rebasing shelved changes
867 rebasing shelved changes
871 merging a
868 merging a
872 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
869 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
873 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
870 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
874 [240]
871 [240]
875 putting v1 shelvedstate file in place of a created v2
872 putting v1 shelvedstate file in place of a created v2
876 $ cat << EOF > .hg/shelvedstate
873 $ cat << EOF > .hg/shelvedstate
877 > 1
874 > 1
878 > ashelve
875 > ashelve
879 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
876 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
880 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
877 > 8b058dae057a5a78f393f4535d9e363dd5efac9d
881 > 8b058dae057a5a78f393f4535d9e363dd5efac9d f543b27db2cdb41737e2e0008dc524c471da1446
878 > 8b058dae057a5a78f393f4535d9e363dd5efac9d f543b27db2cdb41737e2e0008dc524c471da1446
882 > f543b27db2cdb41737e2e0008dc524c471da1446
879 > f543b27db2cdb41737e2e0008dc524c471da1446
883 >
880 >
884 > nokeep
881 > nokeep
885 > :no-active-bookmark
882 > :no-active-bookmark
886 > EOF
883 > EOF
887 $ echo 1 > a
884 $ echo 1 > a
888 $ hg resolve --mark a
885 $ hg resolve --mark a
889 (no more unresolved files)
886 (no more unresolved files)
890 continue: hg unshelve --continue
887 continue: hg unshelve --continue
891 mercurial does not crash
888 mercurial does not crash
892 $ hg continue
889 $ hg continue
893 unshelve of 'ashelve' complete
890 unshelve of 'ashelve' complete
894
891
895 #if phasebased
892 #if phasebased
896
893
897 Unshelve with some metadata file missing
894 Unshelve with some metadata file missing
898 ----------------------------------------
895 ----------------------------------------
899
896
900 $ hg shelve
897 $ hg shelve
901 shelved as default
898 shelved as default
902 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
899 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
903 $ echo 3 > a
900 $ echo 3 > a
904
901
905 Test with the `.shelve` missing, but the changeset still in the repo (non-natural case)
902 Test with the `.shelve` missing, but the changeset still in the repo (non-natural case)
906
903
907 $ rm .hg/shelved/default.shelve
904 $ rm .hg/shelved/default.shelve
908 $ hg unshelve
905 $ hg unshelve
909 unshelving change 'default'
906 unshelving change 'default'
910 temporarily committing pending changes (restore with 'hg unshelve --abort')
907 temporarily committing pending changes (restore with 'hg unshelve --abort')
911 rebasing shelved changes
908 rebasing shelved changes
912 merging a
909 merging a
913 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
910 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
914 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
911 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
915 [240]
912 [240]
916 $ hg abort
913 $ hg abort
917 unshelve of 'default' aborted
914 unshelve of 'default' aborted
918
915
919 Unshelve without .shelve metadata (can happen when upgrading a repository with old shelve)
916 Unshelve without .shelve metadata (can happen when upgrading a repository with old shelve)
920
917
921 $ cat .hg/shelved/default.shelve
918 $ cat .hg/shelved/default.shelve
922 node=82e0cb9893247d12667017593ce1e5655860f1ac
919 node=82e0cb9893247d12667017593ce1e5655860f1ac
923 $ hg strip --hidden --rev 82e0cb989324 --no-backup
920 $ hg strip --hidden --rev 82e0cb989324 --no-backup
924 $ rm .hg/shelved/default.shelve
921 $ rm .hg/shelved/default.shelve
925 $ hg unshelve
922 $ hg unshelve
926 unshelving change 'default'
923 unshelving change 'default'
927 temporarily committing pending changes (restore with 'hg unshelve --abort')
924 temporarily committing pending changes (restore with 'hg unshelve --abort')
928 rebasing shelved changes
925 rebasing shelved changes
929 merging a
926 merging a
930 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
927 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
931 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
928 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
932 [240]
929 [240]
933 $ cat .hg/shelved/default.shelve
930 $ cat .hg/shelved/default.shelve
934 node=82e0cb9893247d12667017593ce1e5655860f1ac
931 node=82e0cb9893247d12667017593ce1e5655860f1ac
935 $ hg abort
932 $ hg abort
936 unshelve of 'default' aborted
933 unshelve of 'default' aborted
937
934
938 #endif
935 #endif
939
936
940 $ cd ..
937 $ cd ..
941
938
942 Block merge abort when unshelve in progress(issue6160)
939 Block merge abort when unshelve in progress(issue6160)
943 ------------------------------------------------------
940 ------------------------------------------------------
944
941
945 $ hg init a
942 $ hg init a
946 $ cd a
943 $ cd a
947 $ echo foo > a ; hg commit -qAm "initial commit"
944 $ echo foo > a ; hg commit -qAm "initial commit"
948 $ echo bar > a
945 $ echo bar > a
949 $ hg shelve
946 $ hg shelve
950 shelved as default
947 shelved as default
951 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
948 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
952 $ echo foobar > a
949 $ echo foobar > a
953 $ hg unshelve
950 $ hg unshelve
954 unshelving change 'default'
951 unshelving change 'default'
955 temporarily committing pending changes (restore with 'hg unshelve --abort')
952 temporarily committing pending changes (restore with 'hg unshelve --abort')
956 rebasing shelved changes
953 rebasing shelved changes
957 merging a
954 merging a
958 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
955 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
959 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
956 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
960 [240]
957 [240]
961
958
962 $ hg log --template '{desc|firstline} {author} {date|isodate} \n' -r .
959 $ hg log --template '{desc|firstline} {author} {date|isodate} \n' -r .
963 pending changes temporary commit shelve@localhost 1970-01-01 00:00 +0000
960 pending changes temporary commit shelve@localhost 1970-01-01 00:00 +0000
964 $ hg merge --abort
961 $ hg merge --abort
965 abort: cannot abort merge with unshelve in progress
962 abort: cannot abort merge with unshelve in progress
966 (use 'hg unshelve --continue' or 'hg unshelve --abort')
963 (use 'hg unshelve --continue' or 'hg unshelve --abort')
967 [20]
964 [20]
968
965
969 $ hg unshelve --abort
966 $ hg unshelve --abort
970 unshelve of 'default' aborted
967 unshelve of 'default' aborted
971
968
972 $ hg log -G --template '{desc|firstline} {author} {date|isodate} \n' -r .
969 $ hg log -G --template '{desc|firstline} {author} {date|isodate} \n' -r .
973 @ initial commit test 1970-01-01 00:00 +0000
970 @ initial commit test 1970-01-01 00:00 +0000
974
971
975 $ cd ..
972 $ cd ..
976
973
977 Demonstrate that the labels are correct in the merge conflict
974 Demonstrate that the labels are correct in the merge conflict
978 -------------------------------------------------------------
975 -------------------------------------------------------------
979 $ hg init labels
976 $ hg init labels
980 $ cd labels
977 $ cd labels
981 $ echo r0 > foo
978 $ echo r0 > foo
982 $ hg ci -qAm r0
979 $ hg ci -qAm r0
983 $ echo "this will be shelved" >> foo
980 $ echo "this will be shelved" >> foo
984 $ hg shelve -q
981 $ hg shelve -q
985 $ echo "this is in wdir, conflicts with shelve" >> foo
982 $ echo "this is in wdir, conflicts with shelve" >> foo
986 $ hg unshelve -q
983 $ hg unshelve -q
987 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
984 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
988 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
985 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
989 [240]
986 [240]
990 $ cat foo
987 $ cat foo
991 r0
988 r0
992 <<<<<<< working-copy: 0b2fcf2a90e9 - shelve: pending changes temporary commit
989 <<<<<<< working-copy: 0b2fcf2a90e9 - shelve: pending changes temporary commit
993 this is in wdir, conflicts with shelve
990 this is in wdir, conflicts with shelve
994 =======
991 =======
995 this will be shelved
992 this will be shelved
996 >>>>>>> shelve: 9c072a2163db - shelve: changes to: r0
993 >>>>>>> shelve: 9c072a2163db - shelve: changes to: r0
997 $ cd ..
994 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now