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