##// END OF EJS Templates
shelve: choose where .orig file locations are kept...
Christian Delahousse -
r26942:d55d2284 default
parent child Browse files
Show More
@@ -1,839 +1,839 b''
1 # shelve.py - save/restore working directory state
1 # shelve.py - save/restore working directory state
2 #
2 #
3 # Copyright 2013 Facebook, Inc.
3 # Copyright 2013 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """save and restore changes to the working directory
8 """save and restore changes to the working directory
9
9
10 The "hg shelve" command saves changes made to the working directory
10 The "hg shelve" command saves changes made to the working directory
11 and reverts those changes, resetting the working directory to a clean
11 and reverts those changes, resetting the working directory to a clean
12 state.
12 state.
13
13
14 Later on, the "hg unshelve" command restores the changes saved by "hg
14 Later on, the "hg unshelve" command restores the changes saved by "hg
15 shelve". Changes can be restored even after updating to a different
15 shelve". Changes can be restored even after updating to a different
16 parent, in which case Mercurial's merge machinery will resolve any
16 parent, in which case Mercurial's merge machinery will resolve any
17 conflicts if necessary.
17 conflicts if necessary.
18
18
19 You can have more than one shelved change outstanding at a time; each
19 You can have more than one shelved change outstanding at a time; each
20 shelved change has a distinct name. For details, see the help for "hg
20 shelved change has a distinct name. For details, see the help for "hg
21 shelve".
21 shelve".
22 """
22 """
23
23
24 import collections
24 import collections
25 import 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, file + ".orig")
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(repo)
534 ms = merge.mergestate(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 ('', 'keep', None,
575 ('', 'keep', None,
576 _('keep shelve after unshelving')),
576 _('keep shelve after unshelving')),
577 ('', 'date', '',
577 ('', 'date', '',
578 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
578 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
579 _('hg unshelve [SHELVED]'))
579 _('hg unshelve [SHELVED]'))
580 def unshelve(ui, repo, *shelved, **opts):
580 def unshelve(ui, repo, *shelved, **opts):
581 """restore a shelved change to the working directory
581 """restore a shelved change to the working directory
582
582
583 This command accepts an optional name of a shelved change to
583 This command accepts an optional name of a shelved change to
584 restore. If none is given, the most recent shelved change is used.
584 restore. If none is given, the most recent shelved change is used.
585
585
586 If a shelved change is applied successfully, the bundle that
586 If a shelved change is applied successfully, the bundle that
587 contains the shelved changes is moved to a backup location
587 contains the shelved changes is moved to a backup location
588 (.hg/shelve-backup).
588 (.hg/shelve-backup).
589
589
590 Since you can restore a shelved change on top of an arbitrary
590 Since you can restore a shelved change on top of an arbitrary
591 commit, it is possible that unshelving will result in a conflict
591 commit, it is possible that unshelving will result in a conflict
592 between your changes and the commits you are unshelving onto. If
592 between your changes and the commits you are unshelving onto. If
593 this occurs, you must resolve the conflict, then use
593 this occurs, you must resolve the conflict, then use
594 ``--continue`` to complete the unshelve operation. (The bundle
594 ``--continue`` to complete the unshelve operation. (The bundle
595 will not be moved until you successfully complete the unshelve.)
595 will not be moved until you successfully complete the unshelve.)
596
596
597 (Alternatively, you can use ``--abort`` to abandon an unshelve
597 (Alternatively, you can use ``--abort`` to abandon an unshelve
598 that causes a conflict. This reverts the unshelved changes, and
598 that causes a conflict. This reverts the unshelved changes, and
599 leaves the bundle in place.)
599 leaves the bundle in place.)
600
600
601 After a successful unshelve, the shelved changes are stored in a
601 After a successful unshelve, the shelved changes are stored in a
602 backup directory. Only the N most recent backups are kept. N
602 backup directory. Only the N most recent backups are kept. N
603 defaults to 10 but can be overridden using the ``shelve.maxbackups``
603 defaults to 10 but can be overridden using the ``shelve.maxbackups``
604 configuration option.
604 configuration option.
605
605
606 .. container:: verbose
606 .. container:: verbose
607
607
608 Timestamp in seconds is used to decide order of backups. More
608 Timestamp in seconds is used to decide order of backups. More
609 than ``maxbackups`` backups are kept, if same timestamp
609 than ``maxbackups`` backups are kept, if same timestamp
610 prevents from deciding exact order of them, for safety.
610 prevents from deciding exact order of them, for safety.
611 """
611 """
612 abortf = opts['abort']
612 abortf = opts['abort']
613 continuef = opts['continue']
613 continuef = opts['continue']
614 if not abortf and not continuef:
614 if not abortf and not continuef:
615 cmdutil.checkunfinished(repo)
615 cmdutil.checkunfinished(repo)
616
616
617 if abortf or continuef:
617 if abortf or continuef:
618 if abortf and continuef:
618 if abortf and continuef:
619 raise error.Abort(_('cannot use both abort and continue'))
619 raise error.Abort(_('cannot use both abort and continue'))
620 if shelved:
620 if shelved:
621 raise error.Abort(_('cannot combine abort/continue with '
621 raise error.Abort(_('cannot combine abort/continue with '
622 'naming a shelved change'))
622 'naming a shelved change'))
623
623
624 try:
624 try:
625 state = shelvedstate.load(repo)
625 state = shelvedstate.load(repo)
626 except IOError as err:
626 except IOError as err:
627 if err.errno != errno.ENOENT:
627 if err.errno != errno.ENOENT:
628 raise
628 raise
629 raise error.Abort(_('no unshelve operation underway'))
629 raise error.Abort(_('no unshelve operation underway'))
630
630
631 if abortf:
631 if abortf:
632 return unshelveabort(ui, repo, state, opts)
632 return unshelveabort(ui, repo, state, opts)
633 elif continuef:
633 elif continuef:
634 return unshelvecontinue(ui, repo, state, opts)
634 return unshelvecontinue(ui, repo, state, opts)
635 elif len(shelved) > 1:
635 elif len(shelved) > 1:
636 raise error.Abort(_('can only unshelve one change at a time'))
636 raise error.Abort(_('can only unshelve one change at a time'))
637 elif not shelved:
637 elif not shelved:
638 shelved = listshelves(repo)
638 shelved = listshelves(repo)
639 if not shelved:
639 if not shelved:
640 raise error.Abort(_('no shelved changes to apply!'))
640 raise error.Abort(_('no shelved changes to apply!'))
641 basename = util.split(shelved[0][1])[1]
641 basename = util.split(shelved[0][1])[1]
642 ui.status(_("unshelving change '%s'\n") % basename)
642 ui.status(_("unshelving change '%s'\n") % basename)
643 else:
643 else:
644 basename = shelved[0]
644 basename = shelved[0]
645
645
646 if not shelvedfile(repo, basename, 'patch').exists():
646 if not shelvedfile(repo, basename, 'patch').exists():
647 raise error.Abort(_("shelved change '%s' not found") % basename)
647 raise error.Abort(_("shelved change '%s' not found") % basename)
648
648
649 oldquiet = ui.quiet
649 oldquiet = ui.quiet
650 wlock = lock = tr = None
650 wlock = lock = tr = None
651 try:
651 try:
652 wlock = repo.wlock()
652 wlock = repo.wlock()
653 lock = repo.lock()
653 lock = repo.lock()
654
654
655 tr = repo.transaction('unshelve', report=lambda x: None)
655 tr = repo.transaction('unshelve', report=lambda x: None)
656 oldtiprev = len(repo)
656 oldtiprev = len(repo)
657
657
658 pctx = repo['.']
658 pctx = repo['.']
659 tmpwctx = pctx
659 tmpwctx = pctx
660 # The goal is to have a commit structure like so:
660 # The goal is to have a commit structure like so:
661 # ...-> pctx -> tmpwctx -> shelvectx
661 # ...-> pctx -> tmpwctx -> shelvectx
662 # where tmpwctx is an optional commit with the user's pending changes
662 # 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
663 # and shelvectx is the unshelved changes. Then we merge it all down
664 # to the original pctx.
664 # to the original pctx.
665
665
666 # Store pending changes in a commit
666 # Store pending changes in a commit
667 s = repo.status()
667 s = repo.status()
668 if s.modified or s.added or s.removed or s.deleted:
668 if s.modified or s.added or s.removed or s.deleted:
669 ui.status(_("temporarily committing pending changes "
669 ui.status(_("temporarily committing pending changes "
670 "(restore with 'hg unshelve --abort')\n"))
670 "(restore with 'hg unshelve --abort')\n"))
671 def commitfunc(ui, repo, message, match, opts):
671 def commitfunc(ui, repo, message, match, opts):
672 hasmq = util.safehasattr(repo, 'mq')
672 hasmq = util.safehasattr(repo, 'mq')
673 if hasmq:
673 if hasmq:
674 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
674 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
675
675
676 backup = repo.ui.backupconfig('phases', 'new-commit')
676 backup = repo.ui.backupconfig('phases', 'new-commit')
677 try:
677 try:
678 repo.ui. setconfig('phases', 'new-commit', phases.secret)
678 repo.ui. setconfig('phases', 'new-commit', phases.secret)
679 return repo.commit(message, 'shelve@localhost',
679 return repo.commit(message, 'shelve@localhost',
680 opts.get('date'), match)
680 opts.get('date'), match)
681 finally:
681 finally:
682 repo.ui.restoreconfig(backup)
682 repo.ui.restoreconfig(backup)
683 if hasmq:
683 if hasmq:
684 repo.mq.checkapplied = saved
684 repo.mq.checkapplied = saved
685
685
686 tempopts = {}
686 tempopts = {}
687 tempopts['message'] = "pending changes temporary commit"
687 tempopts['message'] = "pending changes temporary commit"
688 tempopts['date'] = opts.get('date')
688 tempopts['date'] = opts.get('date')
689 ui.quiet = True
689 ui.quiet = True
690 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
690 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
691 tmpwctx = repo[node]
691 tmpwctx = repo[node]
692
692
693 ui.quiet = True
693 ui.quiet = True
694 shelvedfile(repo, basename, 'hg').applybundle()
694 shelvedfile(repo, basename, 'hg').applybundle()
695
695
696 ui.quiet = oldquiet
696 ui.quiet = oldquiet
697
697
698 shelvectx = repo['tip']
698 shelvectx = repo['tip']
699
699
700 # If the shelve is not immediately on top of the commit
700 # If the shelve is not immediately on top of the commit
701 # we'll be merging with, rebase it to be on top.
701 # we'll be merging with, rebase it to be on top.
702 if tmpwctx.node() != shelvectx.parents()[0].node():
702 if tmpwctx.node() != shelvectx.parents()[0].node():
703 ui.status(_('rebasing shelved changes\n'))
703 ui.status(_('rebasing shelved changes\n'))
704 try:
704 try:
705 rebase.rebase(ui, repo, **{
705 rebase.rebase(ui, repo, **{
706 'rev' : [shelvectx.rev()],
706 'rev' : [shelvectx.rev()],
707 'dest' : str(tmpwctx.rev()),
707 'dest' : str(tmpwctx.rev()),
708 'keep' : True,
708 'keep' : True,
709 })
709 })
710 except error.InterventionRequired:
710 except error.InterventionRequired:
711 tr.close()
711 tr.close()
712
712
713 stripnodes = [repo.changelog.node(rev)
713 stripnodes = [repo.changelog.node(rev)
714 for rev in xrange(oldtiprev, len(repo))]
714 for rev in xrange(oldtiprev, len(repo))]
715 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
715 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
716
716
717 util.rename(repo.join('rebasestate'),
717 util.rename(repo.join('rebasestate'),
718 repo.join('unshelverebasestate'))
718 repo.join('unshelverebasestate'))
719 raise error.InterventionRequired(
719 raise error.InterventionRequired(
720 _("unresolved conflicts (see 'hg resolve', then "
720 _("unresolved conflicts (see 'hg resolve', then "
721 "'hg unshelve --continue')"))
721 "'hg unshelve --continue')"))
722
722
723 # refresh ctx after rebase completes
723 # refresh ctx after rebase completes
724 shelvectx = repo['tip']
724 shelvectx = repo['tip']
725
725
726 if not shelvectx in tmpwctx.children():
726 if not shelvectx in tmpwctx.children():
727 # rebase was a no-op, so it produced no child commit
727 # rebase was a no-op, so it produced no child commit
728 shelvectx = tmpwctx
728 shelvectx = tmpwctx
729
729
730 mergefiles(ui, repo, pctx, shelvectx)
730 mergefiles(ui, repo, pctx, shelvectx)
731 shelvedstate.clear(repo)
731 shelvedstate.clear(repo)
732
732
733 # The transaction aborting will strip all the commits for us,
733 # The transaction aborting will strip all the commits for us,
734 # but it doesn't update the inmemory structures, so addchangegroup
734 # but it doesn't update the inmemory structures, so addchangegroup
735 # hooks still fire and try to operate on the missing commits.
735 # hooks still fire and try to operate on the missing commits.
736 # Clean up manually to prevent this.
736 # Clean up manually to prevent this.
737 repo.unfiltered().changelog.strip(oldtiprev, tr)
737 repo.unfiltered().changelog.strip(oldtiprev, tr)
738
738
739 unshelvecleanup(ui, repo, basename, opts)
739 unshelvecleanup(ui, repo, basename, opts)
740
740
741 _aborttransaction(repo)
741 _aborttransaction(repo)
742 finally:
742 finally:
743 ui.quiet = oldquiet
743 ui.quiet = oldquiet
744 if tr:
744 if tr:
745 tr.release()
745 tr.release()
746 lockmod.release(lock, wlock)
746 lockmod.release(lock, wlock)
747
747
748 @command('shelve',
748 @command('shelve',
749 [('A', 'addremove', None,
749 [('A', 'addremove', None,
750 _('mark new/missing files as added/removed before shelving')),
750 _('mark new/missing files as added/removed before shelving')),
751 ('', 'cleanup', None,
751 ('', 'cleanup', None,
752 _('delete all shelved changes')),
752 _('delete all shelved changes')),
753 ('', 'date', '',
753 ('', 'date', '',
754 _('shelve with the specified commit date'), _('DATE')),
754 _('shelve with the specified commit date'), _('DATE')),
755 ('d', 'delete', None,
755 ('d', 'delete', None,
756 _('delete the named shelved change(s)')),
756 _('delete the named shelved change(s)')),
757 ('e', 'edit', False,
757 ('e', 'edit', False,
758 _('invoke editor on commit messages')),
758 _('invoke editor on commit messages')),
759 ('l', 'list', None,
759 ('l', 'list', None,
760 _('list current shelves')),
760 _('list current shelves')),
761 ('m', 'message', '',
761 ('m', 'message', '',
762 _('use text as shelve message'), _('TEXT')),
762 _('use text as shelve message'), _('TEXT')),
763 ('n', 'name', '',
763 ('n', 'name', '',
764 _('use the given name for the shelved commit'), _('NAME')),
764 _('use the given name for the shelved commit'), _('NAME')),
765 ('p', 'patch', None,
765 ('p', 'patch', None,
766 _('show patch')),
766 _('show patch')),
767 ('i', 'interactive', None,
767 ('i', 'interactive', None,
768 _('interactive mode, only works while creating a shelve')),
768 _('interactive mode, only works while creating a shelve')),
769 ('', 'stat', None,
769 ('', 'stat', None,
770 _('output diffstat-style summary of changes'))] + commands.walkopts,
770 _('output diffstat-style summary of changes'))] + commands.walkopts,
771 _('hg shelve [OPTION]... [FILE]...'))
771 _('hg shelve [OPTION]... [FILE]...'))
772 def shelvecmd(ui, repo, *pats, **opts):
772 def shelvecmd(ui, repo, *pats, **opts):
773 '''save and set aside changes from the working directory
773 '''save and set aside changes from the working directory
774
774
775 Shelving takes files that "hg status" reports as not clean, saves
775 Shelving takes files that "hg status" reports as not clean, saves
776 the modifications to a bundle (a shelved change), and reverts the
776 the modifications to a bundle (a shelved change), and reverts the
777 files so that their state in the working directory becomes clean.
777 files so that their state in the working directory becomes clean.
778
778
779 To restore these changes to the working directory, using "hg
779 To restore these changes to the working directory, using "hg
780 unshelve"; this will work even if you switch to a different
780 unshelve"; this will work even if you switch to a different
781 commit.
781 commit.
782
782
783 When no files are specified, "hg shelve" saves all not-clean
783 When no files are specified, "hg shelve" saves all not-clean
784 files. If specific files or directories are named, only changes to
784 files. If specific files or directories are named, only changes to
785 those files are shelved.
785 those files are shelved.
786
786
787 Each shelved change has a name that makes it easier to find later.
787 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
788 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
789 bookmark, or if there is no active bookmark, the current named
790 branch. To specify a different name, use ``--name``.
790 branch. To specify a different name, use ``--name``.
791
791
792 To see a list of existing shelved changes, use the ``--list``
792 To see a list of existing shelved changes, use the ``--list``
793 option. For each shelved change, this will print its name, age,
793 option. For each shelved change, this will print its name, age,
794 and description; use ``--patch`` or ``--stat`` for more details.
794 and description; use ``--patch`` or ``--stat`` for more details.
795
795
796 To delete specific shelved changes, use ``--delete``. To delete
796 To delete specific shelved changes, use ``--delete``. To delete
797 all shelved changes, use ``--cleanup``.
797 all shelved changes, use ``--cleanup``.
798 '''
798 '''
799 cmdutil.checkunfinished(repo)
799 cmdutil.checkunfinished(repo)
800
800
801 allowables = [
801 allowables = [
802 ('addremove', set(['create'])), # 'create' is pseudo action
802 ('addremove', set(['create'])), # 'create' is pseudo action
803 ('cleanup', set(['cleanup'])),
803 ('cleanup', set(['cleanup'])),
804 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
804 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
805 ('delete', set(['delete'])),
805 ('delete', set(['delete'])),
806 ('edit', set(['create'])),
806 ('edit', set(['create'])),
807 ('list', set(['list'])),
807 ('list', set(['list'])),
808 ('message', set(['create'])),
808 ('message', set(['create'])),
809 ('name', set(['create'])),
809 ('name', set(['create'])),
810 ('patch', set(['patch', 'list'])),
810 ('patch', set(['patch', 'list'])),
811 ('stat', set(['stat', 'list'])),
811 ('stat', set(['stat', 'list'])),
812 ]
812 ]
813 def checkopt(opt):
813 def checkopt(opt):
814 if opts[opt]:
814 if opts[opt]:
815 for i, allowable in allowables:
815 for i, allowable in allowables:
816 if opts[i] and opt not in allowable:
816 if opts[i] and opt not in allowable:
817 raise error.Abort(_("options '--%s' and '--%s' may not be "
817 raise error.Abort(_("options '--%s' and '--%s' may not be "
818 "used together") % (opt, i))
818 "used together") % (opt, i))
819 return True
819 return True
820 if checkopt('cleanup'):
820 if checkopt('cleanup'):
821 if pats:
821 if pats:
822 raise error.Abort(_("cannot specify names when using '--cleanup'"))
822 raise error.Abort(_("cannot specify names when using '--cleanup'"))
823 return cleanupcmd(ui, repo)
823 return cleanupcmd(ui, repo)
824 elif checkopt('delete'):
824 elif checkopt('delete'):
825 return deletecmd(ui, repo, pats)
825 return deletecmd(ui, repo, pats)
826 elif checkopt('list'):
826 elif checkopt('list'):
827 return listcmd(ui, repo, pats, opts)
827 return listcmd(ui, repo, pats, opts)
828 elif checkopt('patch'):
828 elif checkopt('patch'):
829 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
829 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
830 elif checkopt('stat'):
830 elif checkopt('stat'):
831 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
831 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
832 else:
832 else:
833 return createcmd(ui, repo, pats, opts)
833 return createcmd(ui, repo, pats, opts)
834
834
835 def extsetup(ui):
835 def extsetup(ui):
836 cmdutil.unfinishedstates.append(
836 cmdutil.unfinishedstates.append(
837 [shelvedstate._filename, False, False,
837 [shelvedstate._filename, False, False,
838 _('unshelve already in progress'),
838 _('unshelve already in progress'),
839 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
839 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
@@ -1,1215 +1,1221 b''
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 $ HGMERGE=true hg unshelve
472 $ HGMERGE=true hg unshelve
473 unshelving change 'default'
473 unshelving change 'default'
474 temporarily committing pending changes (restore with 'hg unshelve --abort')
474 temporarily committing pending changes (restore with 'hg unshelve --abort')
475 rebasing shelved changes
475 rebasing shelved changes
476 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
476 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
477 merging a/a
477 merging a/a
478 note: rebase of 6:c5e6910e7601 created no changes to commit
478 note: rebase of 6:c5e6910e7601 created no changes to commit
479 $ hg parents -q
479 $ hg parents -q
480 4:33f7f61e6c5e
480 4:33f7f61e6c5e
481 $ hg shelve -l
481 $ hg shelve -l
482 $ hg status
482 $ hg status
483 A foo/foo
483 A foo/foo
484 $ cat a/a
484 $ cat a/a
485 a
485 a
486 c
486 c
487 x
487 x
488
488
489 test keep and cleanup
489 test keep and cleanup
490
490
491 $ hg shelve
491 $ hg shelve
492 shelved as default
492 shelved as default
493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
493 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
494 $ hg shelve --list
494 $ hg shelve --list
495 default (*) changes to 'create conflict' (glob)
495 default (*) changes to 'create conflict' (glob)
496 $ hg unshelve --keep
496 $ hg unshelve --keep
497 unshelving change 'default'
497 unshelving change 'default'
498 $ hg shelve --list
498 $ hg shelve --list
499 default (*) changes to 'create conflict' (glob)
499 default (*) changes to 'create conflict' (glob)
500 $ hg shelve --cleanup
500 $ hg shelve --cleanup
501 $ hg shelve --list
501 $ hg shelve --list
502
502
503 $ hg shelve --cleanup --delete
503 $ hg shelve --cleanup --delete
504 abort: options '--cleanup' and '--delete' may not be used together
504 abort: options '--cleanup' and '--delete' may not be used together
505 [255]
505 [255]
506 $ hg shelve --cleanup --patch
506 $ hg shelve --cleanup --patch
507 abort: options '--cleanup' and '--patch' may not be used together
507 abort: options '--cleanup' and '--patch' may not be used together
508 [255]
508 [255]
509 $ hg shelve --cleanup --message MESSAGE
509 $ hg shelve --cleanup --message MESSAGE
510 abort: options '--cleanup' and '--message' may not be used together
510 abort: options '--cleanup' and '--message' may not be used together
511 [255]
511 [255]
512
512
513 test bookmarks
513 test bookmarks
514
514
515 $ hg bookmark test
515 $ hg bookmark test
516 $ hg bookmark
516 $ hg bookmark
517 * test 4:33f7f61e6c5e
517 * test 4:33f7f61e6c5e
518 $ hg shelve
518 $ hg shelve
519 shelved as test
519 shelved as test
520 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
520 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
521 $ hg bookmark
521 $ hg bookmark
522 * test 4:33f7f61e6c5e
522 * test 4:33f7f61e6c5e
523 $ hg unshelve
523 $ hg unshelve
524 unshelving change 'test'
524 unshelving change 'test'
525 $ hg bookmark
525 $ hg bookmark
526 * test 4:33f7f61e6c5e
526 * test 4:33f7f61e6c5e
527
527
528 shelve should still work even if mq is disabled
528 shelve should still work even if mq is disabled
529
529
530 $ hg --config extensions.mq=! shelve
530 $ hg --config extensions.mq=! shelve
531 shelved as test
531 shelved as test
532 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
532 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
533 $ hg --config extensions.mq=! shelve --list
533 $ hg --config extensions.mq=! shelve --list
534 test (*) changes to 'create conflict' (glob)
534 test (*) changes to 'create conflict' (glob)
535 $ hg bookmark
535 $ hg bookmark
536 * test 4:33f7f61e6c5e
536 * test 4:33f7f61e6c5e
537 $ hg --config extensions.mq=! unshelve
537 $ hg --config extensions.mq=! unshelve
538 unshelving change 'test'
538 unshelving change 'test'
539 $ hg bookmark
539 $ hg bookmark
540 * test 4:33f7f61e6c5e
540 * test 4:33f7f61e6c5e
541
541
542 shelve should leave dirstate clean (issue4055)
542 shelve should leave dirstate clean (issue4055)
543
543
544 $ cd ..
544 $ cd ..
545 $ hg init shelverebase
545 $ hg init shelverebase
546 $ cd shelverebase
546 $ cd shelverebase
547 $ printf 'x\ny\n' > x
547 $ printf 'x\ny\n' > x
548 $ echo z > z
548 $ echo z > z
549 $ hg commit -Aqm xy
549 $ hg commit -Aqm xy
550 $ echo z >> x
550 $ echo z >> x
551 $ hg commit -Aqm z
551 $ hg commit -Aqm z
552 $ hg up 0
552 $ hg up 0
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 $ printf 'a\nx\ny\nz\n' > x
554 $ printf 'a\nx\ny\nz\n' > x
555 $ hg commit -Aqm xyz
555 $ hg commit -Aqm xyz
556 $ echo c >> z
556 $ echo c >> z
557 $ hg shelve
557 $ hg shelve
558 shelved as default
558 shelved as default
559 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
559 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
560 $ hg rebase -d 1 --config extensions.rebase=
560 $ hg rebase -d 1 --config extensions.rebase=
561 rebasing 2:323bfa07f744 "xyz" (tip)
561 rebasing 2:323bfa07f744 "xyz" (tip)
562 merging x
562 merging x
563 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
563 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
564 $ hg unshelve
564 $ hg unshelve
565 unshelving change 'default'
565 unshelving change 'default'
566 rebasing shelved changes
566 rebasing shelved changes
567 rebasing 4:b8fefe789ed0 "changes to 'xyz'" (tip)
567 rebasing 4:b8fefe789ed0 "changes to 'xyz'" (tip)
568 $ hg status
568 $ hg status
569 M z
569 M z
570
570
571 $ cd ..
571 $ cd ..
572
572
573 shelve should only unshelve pending changes (issue4068)
573 shelve should only unshelve pending changes (issue4068)
574
574
575 $ hg init onlypendingchanges
575 $ hg init onlypendingchanges
576 $ cd onlypendingchanges
576 $ cd onlypendingchanges
577 $ touch a
577 $ touch a
578 $ hg ci -Aqm a
578 $ hg ci -Aqm a
579 $ touch b
579 $ touch b
580 $ hg ci -Aqm b
580 $ hg ci -Aqm b
581 $ hg up -q 0
581 $ hg up -q 0
582 $ touch c
582 $ touch c
583 $ hg ci -Aqm c
583 $ hg ci -Aqm c
584
584
585 $ touch d
585 $ touch d
586 $ hg add d
586 $ hg add d
587 $ hg shelve
587 $ hg shelve
588 shelved as default
588 shelved as default
589 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
589 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
590 $ hg up -q 1
590 $ hg up -q 1
591 $ hg unshelve
591 $ hg unshelve
592 unshelving change 'default'
592 unshelving change 'default'
593 rebasing shelved changes
593 rebasing shelved changes
594 rebasing 3:0cae6656c016 "changes to 'c'" (tip)
594 rebasing 3:0cae6656c016 "changes to 'c'" (tip)
595 $ hg status
595 $ hg status
596 A d
596 A d
597
597
598 unshelve should work on an ancestor of the original commit
598 unshelve should work on an ancestor of the original commit
599
599
600 $ hg shelve
600 $ hg shelve
601 shelved as default
601 shelved as default
602 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
602 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
603 $ hg up 0
603 $ hg up 0
604 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
604 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
605 $ hg unshelve
605 $ hg unshelve
606 unshelving change 'default'
606 unshelving change 'default'
607 rebasing shelved changes
607 rebasing shelved changes
608 rebasing 3:be58f65f55fb "changes to 'b'" (tip)
608 rebasing 3:be58f65f55fb "changes to 'b'" (tip)
609 $ hg status
609 $ hg status
610 A d
610 A d
611
611
612 test bug 4073 we need to enable obsolete markers for it
612 test bug 4073 we need to enable obsolete markers for it
613
613
614 $ cat >> $HGRCPATH << EOF
614 $ cat >> $HGRCPATH << EOF
615 > [experimental]
615 > [experimental]
616 > evolution=createmarkers
616 > evolution=createmarkers
617 > EOF
617 > EOF
618 $ hg shelve
618 $ hg shelve
619 shelved as default
619 shelved as default
620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 $ hg debugobsolete `hg --debug id -i -r 1`
621 $ hg debugobsolete `hg --debug id -i -r 1`
622 $ hg unshelve
622 $ hg unshelve
623 unshelving change 'default'
623 unshelving change 'default'
624
624
625 unshelve should leave unknown files alone (issue4113)
625 unshelve should leave unknown files alone (issue4113)
626
626
627 $ echo e > e
627 $ echo e > e
628 $ hg shelve
628 $ hg shelve
629 shelved as default
629 shelved as default
630 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
630 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
631 $ hg status
631 $ hg status
632 ? e
632 ? e
633 $ hg unshelve
633 $ hg unshelve
634 unshelving change 'default'
634 unshelving change 'default'
635 $ hg status
635 $ hg status
636 A d
636 A d
637 ? e
637 ? e
638 $ cat e
638 $ cat e
639 e
639 e
640
640
641 unshelve should keep a copy of unknown files
641 unshelve should keep a copy of unknown files
642
642
643 $ hg add e
643 $ hg add e
644 $ hg shelve
644 $ hg shelve
645 shelved as default
645 shelved as default
646 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
646 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
647 $ echo z > e
647 $ echo z > e
648 $ hg unshelve
648 $ hg unshelve
649 unshelving change 'default'
649 unshelving change 'default'
650 $ cat e
650 $ cat e
651 e
651 e
652 $ cat e.orig
652 $ cat e.orig
653 z
653 z
654
654
655
655
656 unshelve and conflicts with tracked and untracked files
656 unshelve and conflicts with tracked and untracked files
657
657
658 preparing:
658 preparing:
659
659
660 $ rm *.orig
660 $ rm *.orig
661 $ hg ci -qm 'commit stuff'
661 $ hg ci -qm 'commit stuff'
662 $ hg phase -p null:
662 $ hg phase -p null:
663
663
664 no other changes - no merge:
664 no other changes - no merge:
665
665
666 $ echo f > f
666 $ echo f > f
667 $ hg add f
667 $ hg add f
668 $ hg shelve
668 $ hg shelve
669 shelved as default
669 shelved as default
670 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
670 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
671 $ echo g > f
671 $ echo g > f
672 $ hg unshelve
672 $ hg unshelve
673 unshelving change 'default'
673 unshelving change 'default'
674 $ hg st
674 $ hg st
675 A f
675 A f
676 ? f.orig
676 ? f.orig
677 $ cat f
677 $ cat f
678 f
678 f
679 $ cat f.orig
679 $ cat f.orig
680 g
680 g
681
681
682 other uncommitted changes - merge:
682 other uncommitted changes - merge:
683
683
684 $ hg st
684 $ hg st
685 A f
685 A f
686 ? f.orig
686 ? f.orig
687 $ hg shelve
687 $ hg shelve
688 shelved as default
688 shelved as default
689 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
689 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()'
690 $ 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
691 o 4 changes to 'commit stuff' shelve@localhost
692 |
692 |
693 $ hg log -G --template '{rev} {desc|firstline} {author}'
693 $ hg log -G --template '{rev} {desc|firstline} {author}'
694 @ 3 commit stuff test
694 @ 3 commit stuff test
695 |
695 |
696 | o 2 c test
696 | o 2 c test
697 |/
697 |/
698 o 0 a test
698 o 0 a test
699
699
700 $ mv f.orig f
700 $ mv f.orig f
701 $ echo 1 > a
701 $ echo 1 > a
702 $ hg unshelve --date '1073741824 0'
702 $ hg unshelve --date '1073741824 0'
703 unshelving change 'default'
703 unshelving change 'default'
704 temporarily committing pending changes (restore with 'hg unshelve --abort')
704 temporarily committing pending changes (restore with 'hg unshelve --abort')
705 rebasing shelved changes
705 rebasing shelved changes
706 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
706 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
707 merging f
707 merging f
708 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
708 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
709 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
709 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
710 [1]
710 [1]
711 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
711 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
712 @ 5 changes to 'commit stuff' shelve@localhost 1970-01-01 00:00 +0000
712 @ 5 changes to 'commit stuff' shelve@localhost 1970-01-01 00:00 +0000
713 |
713 |
714 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
714 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
715 |/
715 |/
716 o 3 commit stuff test 1970-01-01 00:00 +0000
716 o 3 commit stuff test 1970-01-01 00:00 +0000
717 |
717 |
718 | o 2 c test 1970-01-01 00:00 +0000
718 | o 2 c test 1970-01-01 00:00 +0000
719 |/
719 |/
720 o 0 a test 1970-01-01 00:00 +0000
720 o 0 a test 1970-01-01 00:00 +0000
721
721
722 $ hg st
722 $ hg st
723 M f
723 M f
724 ? f.orig
724 ? f.orig
725 $ cat f
725 $ cat f
726 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
726 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
727 g
727 g
728 =======
728 =======
729 f
729 f
730 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
730 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
731 $ cat f.orig
731 $ cat f.orig
732 g
732 g
733 $ hg unshelve --abort
733 $ hg unshelve --abort
734 rebase aborted
734 rebase aborted
735 unshelve of 'default' aborted
735 unshelve of 'default' aborted
736 $ hg st
736 $ hg st
737 M a
737 M a
738 ? f.orig
738 ? f.orig
739 $ cat f.orig
739 $ cat f.orig
740 g
740 g
741 $ hg unshelve
741 $ hg unshelve
742 unshelving change 'default'
742 unshelving change 'default'
743 temporarily committing pending changes (restore with 'hg unshelve --abort')
743 temporarily committing pending changes (restore with 'hg unshelve --abort')
744 rebasing shelved changes
744 rebasing shelved changes
745 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
745 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
746 $ hg st
746 $ hg st
747 M a
747 M a
748 A f
748 A f
749 ? f.orig
749 ? f.orig
750
750
751 other committed changes - merge:
751 other committed changes - merge:
752
752
753 $ hg shelve f
753 $ hg shelve f
754 shelved as default
754 shelved as default
755 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
755 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
756 $ hg ci a -m 'intermediate other change'
756 $ hg ci a -m 'intermediate other change'
757 $ mv f.orig f
757 $ mv f.orig f
758 $ hg unshelve
758 $ hg unshelve
759 unshelving change 'default'
759 unshelving change 'default'
760 rebasing shelved changes
760 rebasing shelved changes
761 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
761 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
762 merging f
762 merging f
763 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
763 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
764 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
764 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
765 [1]
765 [1]
766 $ hg st
766 $ hg st
767 M f
767 M f
768 ? f.orig
768 ? f.orig
769 $ cat f
769 $ cat f
770 <<<<<<< dest: * - test: intermediate other change (glob)
770 <<<<<<< dest: * - test: intermediate other change (glob)
771 g
771 g
772 =======
772 =======
773 f
773 f
774 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
774 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
775 $ cat f.orig
775 $ cat f.orig
776 g
776 g
777 $ hg unshelve --abort
777 $ hg unshelve --abort
778 rebase aborted
778 rebase aborted
779 unshelve of 'default' aborted
779 unshelve of 'default' aborted
780 $ hg st
780 $ hg st
781 ? f.orig
781 ? f.orig
782 $ cat f.orig
782 $ cat f.orig
783 g
783 g
784 $ hg shelve --delete default
784 $ hg shelve --delete default
785
785
786 Recreate some conflict again
786 Recreate some conflict again
787
787
788 $ cd ../repo
788 $ cd ../repo
789 $ hg up -C -r 3
789 $ hg up -C -r 3
790 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
790 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
791 (leaving bookmark test)
791 (leaving bookmark test)
792 $ echo y >> a/a
792 $ echo y >> a/a
793 $ hg shelve
793 $ hg shelve
794 shelved as default
794 shelved as default
795 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
795 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
796 $ hg up test
796 $ hg up test
797 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
797 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
798 (activating bookmark test)
798 (activating bookmark test)
799 $ hg bookmark
799 $ hg bookmark
800 * test 4:33f7f61e6c5e
800 * test 4:33f7f61e6c5e
801 $ hg unshelve
801 $ hg unshelve
802 unshelving change 'default'
802 unshelving change 'default'
803 rebasing shelved changes
803 rebasing shelved changes
804 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
804 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
805 merging a/a
805 merging a/a
806 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
806 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
807 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
807 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
808 [1]
808 [1]
809 $ hg bookmark
809 $ hg bookmark
810 test 4:33f7f61e6c5e
810 test 4:33f7f61e6c5e
811
811
812 Test that resolving all conflicts in one direction (so that the rebase
812 Test that resolving all conflicts in one direction (so that the rebase
813 is a no-op), works (issue4398)
813 is a no-op), works (issue4398)
814
814
815 $ hg revert -a -r .
815 $ hg revert -a -r .
816 reverting a/a (glob)
816 reverting a/a (glob)
817 $ hg resolve -m a/a
817 $ hg resolve -m a/a
818 (no more unresolved files)
818 (no more unresolved files)
819 $ hg unshelve -c
819 $ hg unshelve -c
820 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
820 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
821 note: rebase of 5:4b555fdb4e96 created no changes to commit
821 note: rebase of 5:4b555fdb4e96 created no changes to commit
822 unshelve of 'default' complete
822 unshelve of 'default' complete
823 $ hg bookmark
823 $ hg bookmark
824 * test 4:33f7f61e6c5e
824 * test 4:33f7f61e6c5e
825 $ hg diff
825 $ hg diff
826 $ hg status
826 $ hg status
827 ? a/a.orig
827 ? a/a.orig
828 ? foo/foo
828 ? foo/foo
829 $ hg summary
829 $ hg summary
830 parent: 4:33f7f61e6c5e tip
830 parent: 4:33f7f61e6c5e tip
831 create conflict
831 create conflict
832 branch: default
832 branch: default
833 bookmarks: *test
833 bookmarks: *test
834 commit: 2 unknown (clean)
834 commit: 2 unknown (clean)
835 update: (current)
835 update: (current)
836 phases: 5 draft
836 phases: 5 draft
837
837
838 $ hg shelve --delete --stat
838 $ hg shelve --delete --stat
839 abort: options '--delete' and '--stat' may not be used together
839 abort: options '--delete' and '--stat' may not be used together
840 [255]
840 [255]
841 $ hg shelve --delete --name NAME
841 $ hg shelve --delete --name NAME
842 abort: options '--delete' and '--name' may not be used together
842 abort: options '--delete' and '--name' may not be used together
843 [255]
843 [255]
844
844
845 Test interactive shelve
845 Test interactive shelve
846 $ cat <<EOF >> $HGRCPATH
846 $ cat <<EOF >> $HGRCPATH
847 > [ui]
847 > [ui]
848 > interactive = true
848 > interactive = true
849 > EOF
849 > EOF
850 $ echo 'a' >> a/b
850 $ echo 'a' >> a/b
851 $ cat a/a >> a/b
851 $ cat a/a >> a/b
852 $ echo 'x' >> a/b
852 $ echo 'x' >> a/b
853 $ mv a/b a/a
853 $ mv a/b a/a
854 $ echo 'a' >> foo/foo
854 $ echo 'a' >> foo/foo
855 $ hg st
855 $ hg st
856 M a/a
856 M a/a
857 ? a/a.orig
857 ? a/a.orig
858 ? foo/foo
858 ? foo/foo
859 $ cat a/a
859 $ cat a/a
860 a
860 a
861 a
861 a
862 c
862 c
863 x
863 x
864 x
864 x
865 $ cat foo/foo
865 $ cat foo/foo
866 foo
866 foo
867 a
867 a
868 $ hg shelve --interactive --config ui.interactive=false
868 $ hg shelve --interactive --config ui.interactive=false
869 abort: running non-interactively
869 abort: running non-interactively
870 [255]
870 [255]
871 $ hg shelve --interactive << EOF
871 $ hg shelve --interactive << EOF
872 > y
872 > y
873 > y
873 > y
874 > n
874 > n
875 > EOF
875 > EOF
876 diff --git a/a/a b/a/a
876 diff --git a/a/a b/a/a
877 2 hunks, 2 lines changed
877 2 hunks, 2 lines changed
878 examine changes to 'a/a'? [Ynesfdaq?] y
878 examine changes to 'a/a'? [Ynesfdaq?] y
879
879
880 @@ -1,3 +1,4 @@
880 @@ -1,3 +1,4 @@
881 +a
881 +a
882 a
882 a
883 c
883 c
884 x
884 x
885 record change 1/2 to 'a/a'? [Ynesfdaq?] y
885 record change 1/2 to 'a/a'? [Ynesfdaq?] y
886
886
887 @@ -1,3 +2,4 @@
887 @@ -1,3 +2,4 @@
888 a
888 a
889 c
889 c
890 x
890 x
891 +x
891 +x
892 record change 2/2 to 'a/a'? [Ynesfdaq?] n
892 record change 2/2 to 'a/a'? [Ynesfdaq?] n
893
893
894 shelved as test
894 shelved as test
895 merging a/a
895 merging a/a
896 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
896 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
897 $ cat a/a
897 $ cat a/a
898 a
898 a
899 c
899 c
900 x
900 x
901 x
901 x
902 $ cat foo/foo
902 $ cat foo/foo
903 foo
903 foo
904 a
904 a
905 $ hg st
905 $ hg st
906 M a/a
906 M a/a
907 ? foo/foo
907 ? foo/foo
908 $ hg bookmark
908 $ hg bookmark
909 * test 4:33f7f61e6c5e
909 * test 4:33f7f61e6c5e
910 $ hg unshelve
910 $ hg unshelve
911 unshelving change 'test'
911 unshelving change 'test'
912 temporarily committing pending changes (restore with 'hg unshelve --abort')
912 temporarily committing pending changes (restore with 'hg unshelve --abort')
913 rebasing shelved changes
913 rebasing shelved changes
914 rebasing 6:65b5d1c34c34 "changes to 'create conflict'" (tip)
914 rebasing 6:65b5d1c34c34 "changes to 'create conflict'" (tip)
915 merging a/a
915 merging a/a
916 $ hg bookmark
916 $ hg bookmark
917 * test 4:33f7f61e6c5e
917 * test 4:33f7f61e6c5e
918 $ cat a/a
918 $ cat a/a
919 a
919 a
920 a
920 a
921 c
921 c
922 x
922 x
923 x
923 x
924
924
925 shelve --patch and shelve --stat should work with a single valid shelfname
925 shelve --patch and shelve --stat should work with a single valid shelfname
926
926
927 $ hg up --clean .
927 $ hg up --clean .
928 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
928 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
929 (leaving bookmark test)
929 (leaving bookmark test)
930 $ hg shelve --list
930 $ hg shelve --list
931 $ echo 'patch a' > shelf-patch-a
931 $ echo 'patch a' > shelf-patch-a
932 $ hg add shelf-patch-a
932 $ hg add shelf-patch-a
933 $ hg shelve
933 $ hg shelve
934 shelved as default
934 shelved as default
935 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
935 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
936 $ echo 'patch b' > shelf-patch-b
936 $ echo 'patch b' > shelf-patch-b
937 $ hg add shelf-patch-b
937 $ hg add shelf-patch-b
938 $ hg shelve
938 $ hg shelve
939 shelved as default-01
939 shelved as default-01
940 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
940 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
941 $ hg shelve --patch default default-01
941 $ hg shelve --patch default default-01
942 abort: --patch expects a single shelf
942 abort: --patch expects a single shelf
943 [255]
943 [255]
944 $ hg shelve --stat default default-01
944 $ hg shelve --stat default default-01
945 abort: --stat expects a single shelf
945 abort: --stat expects a single shelf
946 [255]
946 [255]
947 $ hg shelve --patch default
947 $ hg shelve --patch default
948 default (* ago) changes to 'create conflict' (glob)
948 default (* ago) changes to 'create conflict' (glob)
949
949
950 diff --git a/shelf-patch-a b/shelf-patch-a
950 diff --git a/shelf-patch-a b/shelf-patch-a
951 new file mode 100644
951 new file mode 100644
952 --- /dev/null
952 --- /dev/null
953 +++ b/shelf-patch-a
953 +++ b/shelf-patch-a
954 @@ -0,0 +1,1 @@
954 @@ -0,0 +1,1 @@
955 +patch a
955 +patch a
956 $ hg shelve --stat default
956 $ hg shelve --stat default
957 default (* ago) changes to 'create conflict' (glob)
957 default (* ago) changes to 'create conflict' (glob)
958 shelf-patch-a | 1 +
958 shelf-patch-a | 1 +
959 1 files changed, 1 insertions(+), 0 deletions(-)
959 1 files changed, 1 insertions(+), 0 deletions(-)
960 $ hg shelve --patch nonexistentshelf
960 $ hg shelve --patch nonexistentshelf
961 abort: cannot find shelf nonexistentshelf
961 abort: cannot find shelf nonexistentshelf
962 [255]
962 [255]
963 $ hg shelve --stat nonexistentshelf
963 $ hg shelve --stat nonexistentshelf
964 abort: cannot find shelf nonexistentshelf
964 abort: cannot find shelf nonexistentshelf
965 [255]
965 [255]
966
966
967 $ cd ..
967 $ cd ..
968
968
969 Shelve from general delta repo uses bundle2 on disk
969 Shelve from general delta repo uses bundle2 on disk
970 --------------------------------------------------
970 --------------------------------------------------
971
971
972 no general delta
972 no general delta
973
973
974 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
974 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
975 requesting all changes
975 requesting all changes
976 adding changesets
976 adding changesets
977 adding manifests
977 adding manifests
978 adding file changes
978 adding file changes
979 added 5 changesets with 8 changes to 6 files
979 added 5 changesets with 8 changes to 6 files
980 updating to branch default
980 updating to branch default
981 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
981 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
982 $ cd bundle1
982 $ cd bundle1
983 $ echo babar > jungle
983 $ echo babar > jungle
984 $ hg add jungle
984 $ hg add jungle
985 $ hg shelve
985 $ hg shelve
986 shelved as default
986 shelved as default
987 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
987 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
988 $ hg debugbundle .hg/shelved/*.hg
988 $ hg debugbundle .hg/shelved/*.hg
989 7e30d8ac6f23cfc84330fd7e698730374615d21a
989 7e30d8ac6f23cfc84330fd7e698730374615d21a
990 $ cd ..
990 $ cd ..
991
991
992 with general delta
992 with general delta
993
993
994 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
994 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
995 requesting all changes
995 requesting all changes
996 adding changesets
996 adding changesets
997 adding manifests
997 adding manifests
998 adding file changes
998 adding file changes
999 added 5 changesets with 8 changes to 6 files
999 added 5 changesets with 8 changes to 6 files
1000 updating to branch default
1000 updating to branch default
1001 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1001 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1002 $ cd bundle2
1002 $ cd bundle2
1003 $ echo babar > jungle
1003 $ echo babar > jungle
1004 $ hg add jungle
1004 $ hg add jungle
1005 $ hg shelve
1005 $ hg shelve
1006 shelved as default
1006 shelved as default
1007 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1007 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1008 $ hg debugbundle .hg/shelved/*.hg
1008 $ hg debugbundle .hg/shelved/*.hg
1009 Stream params: {'Compression': 'BZ'}
1009 Stream params: {'Compression': 'BZ'}
1010 changegroup -- "{'version': '02'}"
1010 changegroup -- "{'version': '02'}"
1011 7e30d8ac6f23cfc84330fd7e698730374615d21a
1011 7e30d8ac6f23cfc84330fd7e698730374615d21a
1012 $ cd ..
1012 $ cd ..
1013
1013
1014 Test visibility of in-memory changes inside transaction to external hook
1014 Test visibility of in-memory changes inside transaction to external hook
1015 ------------------------------------------------------------------------
1015 ------------------------------------------------------------------------
1016
1016
1017 $ cd repo
1017 $ cd repo
1018
1018
1019 $ echo xxxx >> x
1019 $ echo xxxx >> x
1020 $ hg commit -m "#5: changes to invoke rebase"
1020 $ hg commit -m "#5: changes to invoke rebase"
1021
1021
1022 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1022 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1023 > echo "==== \$1:"
1023 > echo "==== \$1:"
1024 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1024 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1025 > # test that pending changes are hidden
1025 > # test that pending changes are hidden
1026 > unset HG_PENDING
1026 > unset HG_PENDING
1027 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1027 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1028 > echo "===="
1028 > echo "===="
1029 > EOF
1029 > EOF
1030
1030
1031 $ cat >> .hg/hgrc <<EOF
1031 $ cat >> .hg/hgrc <<EOF
1032 > [defaults]
1032 > [defaults]
1033 > # to fix hash id of temporary revisions
1033 > # to fix hash id of temporary revisions
1034 > unshelve = --date '0 0'
1034 > unshelve = --date '0 0'
1035 > EOF
1035 > EOF
1036
1036
1037 "hg unshelve" at REV5 implies steps below:
1037 "hg unshelve" at REV5 implies steps below:
1038
1038
1039 (1) commit changes in the working directory (REV6)
1039 (1) commit changes in the working directory (REV6)
1040 (2) unbundle shelved revision (REV7)
1040 (2) unbundle shelved revision (REV7)
1041 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1041 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1042 (4) rebase: commit merged revision (REV8)
1042 (4) rebase: commit merged revision (REV8)
1043 (5) rebase: update to REV6 (REV8 => REV6)
1043 (5) rebase: update to REV6 (REV8 => REV6)
1044 (6) update to REV5 (REV6 => REV5)
1044 (6) update to REV5 (REV6 => REV5)
1045 (7) abort transaction
1045 (7) abort transaction
1046
1046
1047 == test visibility to external preupdate hook
1047 == test visibility to external preupdate hook
1048
1048
1049 $ cat >> .hg/hgrc <<EOF
1049 $ cat >> .hg/hgrc <<EOF
1050 > [hooks]
1050 > [hooks]
1051 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1051 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1052 > EOF
1052 > EOF
1053
1053
1054 $ echo nnnn >> n
1054 $ echo nnnn >> n
1055
1055
1056 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1056 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1057 ==== before-unshelving:
1057 ==== before-unshelving:
1058 VISIBLE 5:703117a2acfb
1058 VISIBLE 5:703117a2acfb
1059 ACTUAL 5:703117a2acfb
1059 ACTUAL 5:703117a2acfb
1060 ====
1060 ====
1061
1061
1062 $ hg unshelve --keep default
1062 $ hg unshelve --keep default
1063 temporarily committing pending changes (restore with 'hg unshelve --abort')
1063 temporarily committing pending changes (restore with 'hg unshelve --abort')
1064 rebasing shelved changes
1064 rebasing shelved changes
1065 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1065 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1066 ==== preupdate:
1066 ==== preupdate:
1067 VISIBLE 6:66b86db80ee4
1067 VISIBLE 6:66b86db80ee4
1068 ACTUAL 5:703117a2acfb
1068 ACTUAL 5:703117a2acfb
1069 ====
1069 ====
1070 ==== preupdate:
1070 ==== preupdate:
1071 VISIBLE 8:cb2a4e59c2d5
1071 VISIBLE 8:cb2a4e59c2d5
1072 ACTUAL 5:703117a2acfb
1072 ACTUAL 5:703117a2acfb
1073 ====
1073 ====
1074 ==== preupdate:
1074 ==== preupdate:
1075 VISIBLE 6:66b86db80ee4
1075 VISIBLE 6:66b86db80ee4
1076 ACTUAL 5:703117a2acfb
1076 ACTUAL 5:703117a2acfb
1077 ====
1077 ====
1078
1078
1079 $ cat >> .hg/hgrc <<EOF
1079 $ cat >> .hg/hgrc <<EOF
1080 > [hooks]
1080 > [hooks]
1081 > preupdate.visibility =
1081 > preupdate.visibility =
1082 > EOF
1082 > EOF
1083
1083
1084 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1084 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1085 ==== after-unshelving:
1085 ==== after-unshelving:
1086 VISIBLE 5:703117a2acfb
1086 VISIBLE 5:703117a2acfb
1087 ACTUAL 5:703117a2acfb
1087 ACTUAL 5:703117a2acfb
1088 ====
1088 ====
1089
1089
1090 == test visibility to external update hook
1090 == test visibility to external update hook
1091
1091
1092 $ hg update -q -C 5
1092 $ hg update -q -C 5
1093
1093
1094 $ cat >> .hg/hgrc <<EOF
1094 $ cat >> .hg/hgrc <<EOF
1095 > [hooks]
1095 > [hooks]
1096 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1096 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1097 > EOF
1097 > EOF
1098
1098
1099 $ echo nnnn >> n
1099 $ echo nnnn >> n
1100
1100
1101 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1101 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1102 ==== before-unshelving:
1102 ==== before-unshelving:
1103 VISIBLE 5:703117a2acfb
1103 VISIBLE 5:703117a2acfb
1104 ACTUAL 5:703117a2acfb
1104 ACTUAL 5:703117a2acfb
1105 ====
1105 ====
1106
1106
1107 $ hg unshelve --keep default
1107 $ hg unshelve --keep default
1108 temporarily committing pending changes (restore with 'hg unshelve --abort')
1108 temporarily committing pending changes (restore with 'hg unshelve --abort')
1109 rebasing shelved changes
1109 rebasing shelved changes
1110 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1110 rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip)
1111 ==== update:
1111 ==== update:
1112 VISIBLE 6:66b86db80ee4
1112 VISIBLE 6:66b86db80ee4
1113 VISIBLE 7:fcbb97608399
1113 VISIBLE 7:fcbb97608399
1114 ACTUAL 5:703117a2acfb
1114 ACTUAL 5:703117a2acfb
1115 ====
1115 ====
1116 ==== update:
1116 ==== update:
1117 VISIBLE 6:66b86db80ee4
1117 VISIBLE 6:66b86db80ee4
1118 ACTUAL 5:703117a2acfb
1118 ACTUAL 5:703117a2acfb
1119 ====
1119 ====
1120 ==== update:
1120 ==== update:
1121 VISIBLE 5:703117a2acfb
1121 VISIBLE 5:703117a2acfb
1122 ACTUAL 5:703117a2acfb
1122 ACTUAL 5:703117a2acfb
1123 ====
1123 ====
1124
1124
1125 $ cat >> .hg/hgrc <<EOF
1125 $ cat >> .hg/hgrc <<EOF
1126 > [hooks]
1126 > [hooks]
1127 > update.visibility =
1127 > update.visibility =
1128 > EOF
1128 > EOF
1129
1129
1130 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1130 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1131 ==== after-unshelving:
1131 ==== after-unshelving:
1132 VISIBLE 5:703117a2acfb
1132 VISIBLE 5:703117a2acfb
1133 ACTUAL 5:703117a2acfb
1133 ACTUAL 5:703117a2acfb
1134 ====
1134 ====
1135
1135
1136 $ cd ..
1136 $ cd ..
1137
1137
1138 test Abort unshelve always gets user out of the unshelved state
1138 test .orig files go where the user wants them to
1139 ---------------------------------------------------------------
1139 ---------------------------------------------------------------
1140 $ hg init salvage
1140 $ hg init salvage
1141 $ cd salvage
1141 $ cd salvage
1142 $ echo 'content' > root
1142 $ echo 'content' > root
1143 $ hg commit -A -m 'root' -q
1143 $ hg commit -A -m 'root' -q
1144 $ echo '' > root
1144 $ echo '' > root
1145 $ hg shelve -q
1145 $ hg shelve -q
1146 $ echo 'contADDent' > root
1146 $ echo 'contADDent' > root
1147 $ hg unshelve -q
1147 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1148 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1148 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1149 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1149 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1150 [1]
1150 [1]
1151 $ ls .hg/origbackups
1152 root.orig
1153 $ rm -rf .hg/origbackups
1154
1155 test Abort unshelve always gets user out of the unshelved state
1156 ---------------------------------------------------------------
1151 Wreak havoc on the unshelve process
1157 Wreak havoc on the unshelve process
1152 $ rm .hg/unshelverebasestate
1158 $ rm .hg/unshelverebasestate
1153 $ hg unshelve --abort
1159 $ hg unshelve --abort
1154 unshelve of 'default' aborted
1160 unshelve of 'default' aborted
1155 abort: No such file or directory
1161 abort: No such file or directory
1156 [255]
1162 [255]
1157 Can the user leave the current state?
1163 Can the user leave the current state?
1158 $ hg up -C .
1164 $ hg up -C .
1159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1165 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1160
1166
1161 Try again but with a corrupted shelve state file
1167 Try again but with a corrupted shelve state file
1162 $ hg strip -r 2 -r 1 -q
1168 $ hg strip -r 2 -r 1 -q
1163 $ hg up -r 0 -q
1169 $ hg up -r 0 -q
1164 $ echo '' > root
1170 $ echo '' > root
1165 $ hg shelve -q
1171 $ hg shelve -q
1166 $ echo 'contADDent' > root
1172 $ echo 'contADDent' > root
1167 $ hg unshelve -q
1173 $ hg unshelve -q
1168 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1174 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1169 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1175 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1170 [1]
1176 [1]
1171 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1177 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1172 $ mv ../corrupt-shelvedstate .hg/histedit-state
1178 $ mv ../corrupt-shelvedstate .hg/histedit-state
1173 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1179 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1174 rebase aborted
1180 rebase aborted
1175 $ hg up -C .
1181 $ hg up -C .
1176 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1182 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1177
1183
1178 $ cd ..
1184 $ cd ..
1179
1185
1180 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1186 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1181 -----------------------------------------------------------------------
1187 -----------------------------------------------------------------------
1182
1188
1183 $ cat <<EOF >> $HGRCPATH
1189 $ cat <<EOF >> $HGRCPATH
1184 > [extensions]
1190 > [extensions]
1185 > share =
1191 > share =
1186 > EOF
1192 > EOF
1187
1193
1188 $ hg bookmarks -R repo
1194 $ hg bookmarks -R repo
1189 test 4:33f7f61e6c5e
1195 test 4:33f7f61e6c5e
1190 $ hg share -B repo share
1196 $ hg share -B repo share
1191 updating working directory
1197 updating working directory
1192 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1198 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1193 $ cd share
1199 $ cd share
1194
1200
1195 $ hg bookmarks
1201 $ hg bookmarks
1196 test 4:33f7f61e6c5e
1202 test 4:33f7f61e6c5e
1197 $ hg bookmarks foo
1203 $ hg bookmarks foo
1198 $ hg bookmarks
1204 $ hg bookmarks
1199 * foo 5:703117a2acfb
1205 * foo 5:703117a2acfb
1200 test 4:33f7f61e6c5e
1206 test 4:33f7f61e6c5e
1201 $ echo x >> x
1207 $ echo x >> x
1202 $ hg shelve
1208 $ hg shelve
1203 shelved as foo
1209 shelved as foo
1204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1205 $ hg bookmarks
1211 $ hg bookmarks
1206 * foo 5:703117a2acfb
1212 * foo 5:703117a2acfb
1207 test 4:33f7f61e6c5e
1213 test 4:33f7f61e6c5e
1208
1214
1209 $ hg unshelve
1215 $ hg unshelve
1210 unshelving change 'foo'
1216 unshelving change 'foo'
1211 $ hg bookmarks
1217 $ hg bookmarks
1212 * foo 5:703117a2acfb
1218 * foo 5:703117a2acfb
1213 test 4:33f7f61e6c5e
1219 test 4:33f7f61e6c5e
1214
1220
1215 $ cd ..
1221 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now