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