##// END OF EJS Templates
shelve: omit incorrect 'commit' suggestion at 'hg shelve -i'...
FUJIWARA Katsunori -
r25799:0eb093e4 default
parent child Browse files
Show More
@@ -1,800 +1,800 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
30 from mercurial import templatefilters, exchange, bundlerepo
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 util.Abort(_("shelved change '%s' not found") % self.name)
93 raise util.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 changegroup.addchangegroup(self.repo, gen, 'unshelve',
99 changegroup.addchangegroup(self.repo, gen, 'unshelve',
100 'bundle:' + self.vfs.join(self.fname),
100 'bundle:' + self.vfs.join(self.fname),
101 targetphase=phases.secret)
101 targetphase=phases.secret)
102 finally:
102 finally:
103 fp.close()
103 fp.close()
104
104
105 def bundlerepo(self):
105 def bundlerepo(self):
106 return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root,
106 return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root,
107 self.vfs.join(self.fname))
107 self.vfs.join(self.fname))
108 def writebundle(self, cg):
108 def writebundle(self, cg):
109 changegroup.writebundle(self.ui, cg, self.fname, 'HG10UN', self.vfs)
109 changegroup.writebundle(self.ui, cg, self.fname, 'HG10UN', self.vfs)
110
110
111 class shelvedstate(object):
111 class shelvedstate(object):
112 """Handle persistence during unshelving operations.
112 """Handle persistence during unshelving operations.
113
113
114 Handles saving and restoring a shelved state. Ensures that different
114 Handles saving and restoring a shelved state. Ensures that different
115 versions of a shelved state are possible and handles them appropriately.
115 versions of a shelved state are possible and handles them appropriately.
116 """
116 """
117 _version = 1
117 _version = 1
118 _filename = 'shelvedstate'
118 _filename = 'shelvedstate'
119
119
120 @classmethod
120 @classmethod
121 def load(cls, repo):
121 def load(cls, repo):
122 fp = repo.vfs(cls._filename)
122 fp = repo.vfs(cls._filename)
123 try:
123 try:
124 version = int(fp.readline().strip())
124 version = int(fp.readline().strip())
125
125
126 if version != cls._version:
126 if version != cls._version:
127 raise util.Abort(_('this version of shelve is incompatible '
127 raise util.Abort(_('this version of shelve is incompatible '
128 'with the version used in this repo'))
128 'with the version used in this repo'))
129 name = fp.readline().strip()
129 name = fp.readline().strip()
130 wctx = fp.readline().strip()
130 wctx = fp.readline().strip()
131 pendingctx = fp.readline().strip()
131 pendingctx = fp.readline().strip()
132 parents = [bin(h) for h in fp.readline().split()]
132 parents = [bin(h) for h in fp.readline().split()]
133 stripnodes = [bin(h) for h in fp.readline().split()]
133 stripnodes = [bin(h) for h in fp.readline().split()]
134 finally:
134 finally:
135 fp.close()
135 fp.close()
136
136
137 obj = cls()
137 obj = cls()
138 obj.name = name
138 obj.name = name
139 obj.wctx = repo[bin(wctx)]
139 obj.wctx = repo[bin(wctx)]
140 obj.pendingctx = repo[bin(pendingctx)]
140 obj.pendingctx = repo[bin(pendingctx)]
141 obj.parents = parents
141 obj.parents = parents
142 obj.stripnodes = stripnodes
142 obj.stripnodes = stripnodes
143
143
144 return obj
144 return obj
145
145
146 @classmethod
146 @classmethod
147 def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
147 def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
148 fp = repo.vfs(cls._filename, 'wb')
148 fp = repo.vfs(cls._filename, 'wb')
149 fp.write('%i\n' % cls._version)
149 fp.write('%i\n' % cls._version)
150 fp.write('%s\n' % name)
150 fp.write('%s\n' % name)
151 fp.write('%s\n' % hex(originalwctx.node()))
151 fp.write('%s\n' % hex(originalwctx.node()))
152 fp.write('%s\n' % hex(pendingctx.node()))
152 fp.write('%s\n' % hex(pendingctx.node()))
153 fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
153 fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
154 fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
154 fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
155 fp.close()
155 fp.close()
156
156
157 @classmethod
157 @classmethod
158 def clear(cls, repo):
158 def clear(cls, repo):
159 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
159 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
160
160
161 def cleanupoldbackups(repo):
161 def cleanupoldbackups(repo):
162 vfs = scmutil.vfs(repo.join(backupdir))
162 vfs = scmutil.vfs(repo.join(backupdir))
163 maxbackups = repo.ui.configint('shelve', 'maxbackups', 10)
163 maxbackups = repo.ui.configint('shelve', 'maxbackups', 10)
164 hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')]
164 hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')]
165 hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles])
165 hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles])
166 if 0 < maxbackups and maxbackups < len(hgfiles):
166 if 0 < maxbackups and maxbackups < len(hgfiles):
167 bordermtime = hgfiles[-maxbackups][0]
167 bordermtime = hgfiles[-maxbackups][0]
168 else:
168 else:
169 bordermtime = None
169 bordermtime = None
170 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
170 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
171 if mtime == bordermtime:
171 if mtime == bordermtime:
172 # keep it, because timestamp can't decide exact order of backups
172 # keep it, because timestamp can't decide exact order of backups
173 continue
173 continue
174 base = f[:-3]
174 base = f[:-3]
175 for ext in 'hg patch'.split():
175 for ext in 'hg patch'.split():
176 try:
176 try:
177 vfs.unlink(base + '.' + ext)
177 vfs.unlink(base + '.' + ext)
178 except OSError as err:
178 except OSError as err:
179 if err.errno != errno.ENOENT:
179 if err.errno != errno.ENOENT:
180 raise
180 raise
181
181
182 def createcmd(ui, repo, pats, opts):
182 def createcmd(ui, repo, pats, opts):
183 """subcommand that creates a new shelve"""
183 """subcommand that creates a new shelve"""
184
184
185 def publicancestors(ctx):
185 def publicancestors(ctx):
186 """Compute the public ancestors of a commit.
186 """Compute the public ancestors of a commit.
187
187
188 Much faster than the revset ancestors(ctx) & draft()"""
188 Much faster than the revset ancestors(ctx) & draft()"""
189 seen = set([nullrev])
189 seen = set([nullrev])
190 visit = collections.deque()
190 visit = collections.deque()
191 visit.append(ctx)
191 visit.append(ctx)
192 while visit:
192 while visit:
193 ctx = visit.popleft()
193 ctx = visit.popleft()
194 yield ctx.node()
194 yield ctx.node()
195 for parent in ctx.parents():
195 for parent in ctx.parents():
196 rev = parent.rev()
196 rev = parent.rev()
197 if rev not in seen:
197 if rev not in seen:
198 seen.add(rev)
198 seen.add(rev)
199 if parent.mutable():
199 if parent.mutable():
200 visit.append(parent)
200 visit.append(parent)
201
201
202 wctx = repo[None]
202 wctx = repo[None]
203 parents = wctx.parents()
203 parents = wctx.parents()
204 if len(parents) > 1:
204 if len(parents) > 1:
205 raise util.Abort(_('cannot shelve while merging'))
205 raise util.Abort(_('cannot shelve while merging'))
206 parent = parents[0]
206 parent = parents[0]
207
207
208 # we never need the user, so we use a generic user for all shelve operations
208 # we never need the user, so we use a generic user for all shelve operations
209 user = 'shelve@localhost'
209 user = 'shelve@localhost'
210 label = repo._activebookmark or parent.branch() or 'default'
210 label = repo._activebookmark or parent.branch() or 'default'
211
211
212 # slashes aren't allowed in filenames, therefore we rename it
212 # slashes aren't allowed in filenames, therefore we rename it
213 label = label.replace('/', '_')
213 label = label.replace('/', '_')
214
214
215 def gennames():
215 def gennames():
216 yield label
216 yield label
217 for i in xrange(1, 100):
217 for i in xrange(1, 100):
218 yield '%s-%02d' % (label, i)
218 yield '%s-%02d' % (label, i)
219
219
220 def commitfunc(ui, repo, message, match, opts):
220 def commitfunc(ui, repo, message, match, opts):
221 hasmq = util.safehasattr(repo, 'mq')
221 hasmq = util.safehasattr(repo, 'mq')
222 if hasmq:
222 if hasmq:
223 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
223 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
224 backup = repo.ui.backupconfig('phases', 'new-commit')
224 backup = repo.ui.backupconfig('phases', 'new-commit')
225 try:
225 try:
226 repo.ui. setconfig('phases', 'new-commit', phases.secret)
226 repo.ui. setconfig('phases', 'new-commit', phases.secret)
227 editor = cmdutil.getcommiteditor(editform='shelve.shelve', **opts)
227 editor = cmdutil.getcommiteditor(editform='shelve.shelve', **opts)
228 return repo.commit(message, user, opts.get('date'), match,
228 return repo.commit(message, user, opts.get('date'), match,
229 editor=editor)
229 editor=editor)
230 finally:
230 finally:
231 repo.ui.restoreconfig(backup)
231 repo.ui.restoreconfig(backup)
232 if hasmq:
232 if hasmq:
233 repo.mq.checkapplied = saved
233 repo.mq.checkapplied = saved
234
234
235 if parent.node() != nullid:
235 if parent.node() != nullid:
236 desc = "changes to '%s'" % parent.description().split('\n', 1)[0]
236 desc = "changes to '%s'" % parent.description().split('\n', 1)[0]
237 else:
237 else:
238 desc = '(changes in empty repository)'
238 desc = '(changes in empty repository)'
239
239
240 if not opts['message']:
240 if not opts['message']:
241 opts['message'] = desc
241 opts['message'] = desc
242
242
243 name = opts['name']
243 name = opts['name']
244
244
245 wlock = lock = tr = bms = None
245 wlock = lock = tr = bms = None
246 try:
246 try:
247 wlock = repo.wlock()
247 wlock = repo.wlock()
248 lock = repo.lock()
248 lock = repo.lock()
249
249
250 bms = repo._bookmarks.copy()
250 bms = repo._bookmarks.copy()
251 # use an uncommitted transaction to generate the bundle to avoid
251 # use an uncommitted transaction to generate the bundle to avoid
252 # pull races. ensure we don't print the abort message to stderr.
252 # pull races. ensure we don't print the abort message to stderr.
253 tr = repo.transaction('commit', report=lambda x: None)
253 tr = repo.transaction('commit', report=lambda x: None)
254
254
255 if name:
255 if name:
256 if shelvedfile(repo, name, 'hg').exists():
256 if shelvedfile(repo, name, 'hg').exists():
257 raise util.Abort(_("a shelved change named '%s' already exists")
257 raise util.Abort(_("a shelved change named '%s' already exists")
258 % name)
258 % name)
259 else:
259 else:
260 for n in gennames():
260 for n in gennames():
261 if not shelvedfile(repo, n, 'hg').exists():
261 if not shelvedfile(repo, n, 'hg').exists():
262 name = n
262 name = n
263 break
263 break
264 else:
264 else:
265 raise util.Abort(_("too many shelved changes named '%s'") %
265 raise util.Abort(_("too many shelved changes named '%s'") %
266 label)
266 label)
267
267
268 # ensure we are not creating a subdirectory or a hidden file
268 # ensure we are not creating a subdirectory or a hidden file
269 if '/' in name or '\\' in name:
269 if '/' in name or '\\' in name:
270 raise util.Abort(_('shelved change names may not contain slashes'))
270 raise util.Abort(_('shelved change names may not contain slashes'))
271 if name.startswith('.'):
271 if name.startswith('.'):
272 raise util.Abort(_("shelved change names may not start with '.'"))
272 raise util.Abort(_("shelved change names may not start with '.'"))
273 interactive = opts.get('interactive', False)
273 interactive = opts.get('interactive', False)
274
274
275 def interactivecommitfunc(ui, repo, *pats, **opts):
275 def interactivecommitfunc(ui, repo, *pats, **opts):
276 match = scmutil.match(repo['.'], pats, {})
276 match = scmutil.match(repo['.'], pats, {})
277 message = opts['message']
277 message = opts['message']
278 return commitfunc(ui, repo, message, match, opts)
278 return commitfunc(ui, repo, message, match, opts)
279 if not interactive:
279 if not interactive:
280 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
280 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
281 else:
281 else:
282 node = cmdutil.dorecord(ui, repo, interactivecommitfunc, 'commit',
282 node = cmdutil.dorecord(ui, repo, interactivecommitfunc, None,
283 False, cmdutil.recordfilter, *pats, **opts)
283 False, cmdutil.recordfilter, *pats, **opts)
284 if not node:
284 if not node:
285 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
285 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
286 if stat.deleted:
286 if stat.deleted:
287 ui.status(_("nothing changed (%d missing files, see "
287 ui.status(_("nothing changed (%d missing files, see "
288 "'hg status')\n") % len(stat.deleted))
288 "'hg status')\n") % len(stat.deleted))
289 else:
289 else:
290 ui.status(_("nothing changed\n"))
290 ui.status(_("nothing changed\n"))
291 return 1
291 return 1
292
292
293 bases = list(publicancestors(repo[node]))
293 bases = list(publicancestors(repo[node]))
294 cg = changegroup.changegroupsubset(repo, bases, [node], 'shelve')
294 cg = changegroup.changegroupsubset(repo, bases, [node], 'shelve')
295 shelvedfile(repo, name, 'hg').writebundle(cg)
295 shelvedfile(repo, name, 'hg').writebundle(cg)
296 cmdutil.export(repo, [node],
296 cmdutil.export(repo, [node],
297 fp=shelvedfile(repo, name, 'patch').opener('wb'),
297 fp=shelvedfile(repo, name, 'patch').opener('wb'),
298 opts=mdiff.diffopts(git=True))
298 opts=mdiff.diffopts(git=True))
299
299
300
300
301 if ui.formatted():
301 if ui.formatted():
302 desc = util.ellipsis(desc, ui.termwidth())
302 desc = util.ellipsis(desc, ui.termwidth())
303 ui.status(_('shelved as %s\n') % name)
303 ui.status(_('shelved as %s\n') % name)
304 hg.update(repo, parent.node())
304 hg.update(repo, parent.node())
305 finally:
305 finally:
306 if bms:
306 if bms:
307 # restore old bookmarks
307 # restore old bookmarks
308 repo._bookmarks.update(bms)
308 repo._bookmarks.update(bms)
309 repo._bookmarks.write()
309 repo._bookmarks.write()
310 if tr:
310 if tr:
311 tr.abort()
311 tr.abort()
312 lockmod.release(lock, wlock)
312 lockmod.release(lock, wlock)
313
313
314 def cleanupcmd(ui, repo):
314 def cleanupcmd(ui, repo):
315 """subcommand that deletes all shelves"""
315 """subcommand that deletes all shelves"""
316
316
317 wlock = None
317 wlock = None
318 try:
318 try:
319 wlock = repo.wlock()
319 wlock = repo.wlock()
320 for (name, _type) in repo.vfs.readdir('shelved'):
320 for (name, _type) in repo.vfs.readdir('shelved'):
321 suffix = name.rsplit('.', 1)[-1]
321 suffix = name.rsplit('.', 1)[-1]
322 if suffix in ('hg', 'patch'):
322 if suffix in ('hg', 'patch'):
323 shelvedfile(repo, name).movetobackup()
323 shelvedfile(repo, name).movetobackup()
324 cleanupoldbackups(repo)
324 cleanupoldbackups(repo)
325 finally:
325 finally:
326 lockmod.release(wlock)
326 lockmod.release(wlock)
327
327
328 def deletecmd(ui, repo, pats):
328 def deletecmd(ui, repo, pats):
329 """subcommand that deletes a specific shelve"""
329 """subcommand that deletes a specific shelve"""
330 if not pats:
330 if not pats:
331 raise util.Abort(_('no shelved changes specified!'))
331 raise util.Abort(_('no shelved changes specified!'))
332 wlock = repo.wlock()
332 wlock = repo.wlock()
333 try:
333 try:
334 for name in pats:
334 for name in pats:
335 for suffix in 'hg patch'.split():
335 for suffix in 'hg patch'.split():
336 shelvedfile(repo, name, suffix).movetobackup()
336 shelvedfile(repo, name, suffix).movetobackup()
337 cleanupoldbackups(repo)
337 cleanupoldbackups(repo)
338 except OSError as err:
338 except OSError as err:
339 if err.errno != errno.ENOENT:
339 if err.errno != errno.ENOENT:
340 raise
340 raise
341 raise util.Abort(_("shelved change '%s' not found") % name)
341 raise util.Abort(_("shelved change '%s' not found") % name)
342 finally:
342 finally:
343 lockmod.release(wlock)
343 lockmod.release(wlock)
344
344
345 def listshelves(repo):
345 def listshelves(repo):
346 """return all shelves in repo as list of (time, filename)"""
346 """return all shelves in repo as list of (time, filename)"""
347 try:
347 try:
348 names = repo.vfs.readdir('shelved')
348 names = repo.vfs.readdir('shelved')
349 except OSError as err:
349 except OSError as err:
350 if err.errno != errno.ENOENT:
350 if err.errno != errno.ENOENT:
351 raise
351 raise
352 return []
352 return []
353 info = []
353 info = []
354 for (name, _type) in names:
354 for (name, _type) in names:
355 pfx, sfx = name.rsplit('.', 1)
355 pfx, sfx = name.rsplit('.', 1)
356 if not pfx or sfx != 'patch':
356 if not pfx or sfx != 'patch':
357 continue
357 continue
358 st = shelvedfile(repo, name).stat()
358 st = shelvedfile(repo, name).stat()
359 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
359 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
360 return sorted(info, reverse=True)
360 return sorted(info, reverse=True)
361
361
362 def listcmd(ui, repo, pats, opts):
362 def listcmd(ui, repo, pats, opts):
363 """subcommand that displays the list of shelves"""
363 """subcommand that displays the list of shelves"""
364 pats = set(pats)
364 pats = set(pats)
365 width = 80
365 width = 80
366 if not ui.plain():
366 if not ui.plain():
367 width = ui.termwidth()
367 width = ui.termwidth()
368 namelabel = 'shelve.newest'
368 namelabel = 'shelve.newest'
369 for mtime, name in listshelves(repo):
369 for mtime, name in listshelves(repo):
370 sname = util.split(name)[1]
370 sname = util.split(name)[1]
371 if pats and sname not in pats:
371 if pats and sname not in pats:
372 continue
372 continue
373 ui.write(sname, label=namelabel)
373 ui.write(sname, label=namelabel)
374 namelabel = 'shelve.name'
374 namelabel = 'shelve.name'
375 if ui.quiet:
375 if ui.quiet:
376 ui.write('\n')
376 ui.write('\n')
377 continue
377 continue
378 ui.write(' ' * (16 - len(sname)))
378 ui.write(' ' * (16 - len(sname)))
379 used = 16
379 used = 16
380 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
380 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
381 ui.write(age, label='shelve.age')
381 ui.write(age, label='shelve.age')
382 ui.write(' ' * (12 - len(age)))
382 ui.write(' ' * (12 - len(age)))
383 used += 12
383 used += 12
384 fp = open(name + '.patch', 'rb')
384 fp = open(name + '.patch', 'rb')
385 try:
385 try:
386 while True:
386 while True:
387 line = fp.readline()
387 line = fp.readline()
388 if not line:
388 if not line:
389 break
389 break
390 if not line.startswith('#'):
390 if not line.startswith('#'):
391 desc = line.rstrip()
391 desc = line.rstrip()
392 if ui.formatted():
392 if ui.formatted():
393 desc = util.ellipsis(desc, width - used)
393 desc = util.ellipsis(desc, width - used)
394 ui.write(desc)
394 ui.write(desc)
395 break
395 break
396 ui.write('\n')
396 ui.write('\n')
397 if not (opts['patch'] or opts['stat']):
397 if not (opts['patch'] or opts['stat']):
398 continue
398 continue
399 difflines = fp.readlines()
399 difflines = fp.readlines()
400 if opts['patch']:
400 if opts['patch']:
401 for chunk, label in patch.difflabel(iter, difflines):
401 for chunk, label in patch.difflabel(iter, difflines):
402 ui.write(chunk, label=label)
402 ui.write(chunk, label=label)
403 if opts['stat']:
403 if opts['stat']:
404 for chunk, label in patch.diffstatui(difflines, width=width,
404 for chunk, label in patch.diffstatui(difflines, width=width,
405 git=True):
405 git=True):
406 ui.write(chunk, label=label)
406 ui.write(chunk, label=label)
407 finally:
407 finally:
408 fp.close()
408 fp.close()
409
409
410 def singlepatchcmds(ui, repo, pats, opts, subcommand):
410 def singlepatchcmds(ui, repo, pats, opts, subcommand):
411 """subcommand that displays a single shelf"""
411 """subcommand that displays a single shelf"""
412 if len(pats) != 1:
412 if len(pats) != 1:
413 raise util.Abort(_("--%s expects a single shelf") % subcommand)
413 raise util.Abort(_("--%s expects a single shelf") % subcommand)
414 shelfname = pats[0]
414 shelfname = pats[0]
415
415
416 if not shelvedfile(repo, shelfname, 'patch').exists():
416 if not shelvedfile(repo, shelfname, 'patch').exists():
417 raise util.Abort(_("cannot find shelf %s") % shelfname)
417 raise util.Abort(_("cannot find shelf %s") % shelfname)
418
418
419 listcmd(ui, repo, pats, opts)
419 listcmd(ui, repo, pats, opts)
420
420
421 def checkparents(repo, state):
421 def checkparents(repo, state):
422 """check parent while resuming an unshelve"""
422 """check parent while resuming an unshelve"""
423 if state.parents != repo.dirstate.parents():
423 if state.parents != repo.dirstate.parents():
424 raise util.Abort(_('working directory parents do not match unshelve '
424 raise util.Abort(_('working directory parents do not match unshelve '
425 'state'))
425 'state'))
426
426
427 def pathtofiles(repo, files):
427 def pathtofiles(repo, files):
428 cwd = repo.getcwd()
428 cwd = repo.getcwd()
429 return [repo.pathto(f, cwd) for f in files]
429 return [repo.pathto(f, cwd) for f in files]
430
430
431 def unshelveabort(ui, repo, state, opts):
431 def unshelveabort(ui, repo, state, opts):
432 """subcommand that abort an in-progress unshelve"""
432 """subcommand that abort an in-progress unshelve"""
433 wlock = repo.wlock()
433 wlock = repo.wlock()
434 lock = None
434 lock = None
435 try:
435 try:
436 checkparents(repo, state)
436 checkparents(repo, state)
437
437
438 util.rename(repo.join('unshelverebasestate'),
438 util.rename(repo.join('unshelverebasestate'),
439 repo.join('rebasestate'))
439 repo.join('rebasestate'))
440 try:
440 try:
441 rebase.rebase(ui, repo, **{
441 rebase.rebase(ui, repo, **{
442 'abort' : True
442 'abort' : True
443 })
443 })
444 except Exception:
444 except Exception:
445 util.rename(repo.join('rebasestate'),
445 util.rename(repo.join('rebasestate'),
446 repo.join('unshelverebasestate'))
446 repo.join('unshelverebasestate'))
447 raise
447 raise
448
448
449 lock = repo.lock()
449 lock = repo.lock()
450
450
451 mergefiles(ui, repo, state.wctx, state.pendingctx)
451 mergefiles(ui, repo, state.wctx, state.pendingctx)
452
452
453 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
453 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
454 shelvedstate.clear(repo)
454 shelvedstate.clear(repo)
455 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
455 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
456 finally:
456 finally:
457 lockmod.release(lock, wlock)
457 lockmod.release(lock, wlock)
458
458
459 def mergefiles(ui, repo, wctx, shelvectx):
459 def mergefiles(ui, repo, wctx, shelvectx):
460 """updates to wctx and merges the changes from shelvectx into the
460 """updates to wctx and merges the changes from shelvectx into the
461 dirstate."""
461 dirstate."""
462 oldquiet = ui.quiet
462 oldquiet = ui.quiet
463 try:
463 try:
464 ui.quiet = True
464 ui.quiet = True
465 hg.update(repo, wctx.node())
465 hg.update(repo, wctx.node())
466 files = []
466 files = []
467 files.extend(shelvectx.files())
467 files.extend(shelvectx.files())
468 files.extend(shelvectx.parents()[0].files())
468 files.extend(shelvectx.parents()[0].files())
469
469
470 # revert will overwrite unknown files, so move them out of the way
470 # revert will overwrite unknown files, so move them out of the way
471 for file in repo.status(unknown=True).unknown:
471 for file in repo.status(unknown=True).unknown:
472 if file in files:
472 if file in files:
473 util.rename(file, file + ".orig")
473 util.rename(file, file + ".orig")
474 ui.pushbuffer(True)
474 ui.pushbuffer(True)
475 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
475 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
476 *pathtofiles(repo, files),
476 *pathtofiles(repo, files),
477 **{'no_backup': True})
477 **{'no_backup': True})
478 ui.popbuffer()
478 ui.popbuffer()
479 finally:
479 finally:
480 ui.quiet = oldquiet
480 ui.quiet = oldquiet
481
481
482 def unshelvecleanup(ui, repo, name, opts):
482 def unshelvecleanup(ui, repo, name, opts):
483 """remove related files after an unshelve"""
483 """remove related files after an unshelve"""
484 if not opts['keep']:
484 if not opts['keep']:
485 for filetype in 'hg patch'.split():
485 for filetype in 'hg patch'.split():
486 shelvedfile(repo, name, filetype).movetobackup()
486 shelvedfile(repo, name, filetype).movetobackup()
487 cleanupoldbackups(repo)
487 cleanupoldbackups(repo)
488
488
489 def unshelvecontinue(ui, repo, state, opts):
489 def unshelvecontinue(ui, repo, state, opts):
490 """subcommand to continue an in-progress unshelve"""
490 """subcommand to continue an in-progress unshelve"""
491 # We're finishing off a merge. First parent is our original
491 # We're finishing off a merge. First parent is our original
492 # parent, second is the temporary "fake" commit we're unshelving.
492 # parent, second is the temporary "fake" commit we're unshelving.
493 wlock = repo.wlock()
493 wlock = repo.wlock()
494 lock = None
494 lock = None
495 try:
495 try:
496 checkparents(repo, state)
496 checkparents(repo, state)
497 ms = merge.mergestate(repo)
497 ms = merge.mergestate(repo)
498 if [f for f in ms if ms[f] == 'u']:
498 if [f for f in ms if ms[f] == 'u']:
499 raise util.Abort(
499 raise util.Abort(
500 _("unresolved conflicts, can't continue"),
500 _("unresolved conflicts, can't continue"),
501 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
501 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
502
502
503 lock = repo.lock()
503 lock = repo.lock()
504
504
505 util.rename(repo.join('unshelverebasestate'),
505 util.rename(repo.join('unshelverebasestate'),
506 repo.join('rebasestate'))
506 repo.join('rebasestate'))
507 try:
507 try:
508 rebase.rebase(ui, repo, **{
508 rebase.rebase(ui, repo, **{
509 'continue' : True
509 'continue' : True
510 })
510 })
511 except Exception:
511 except Exception:
512 util.rename(repo.join('rebasestate'),
512 util.rename(repo.join('rebasestate'),
513 repo.join('unshelverebasestate'))
513 repo.join('unshelverebasestate'))
514 raise
514 raise
515
515
516 shelvectx = repo['tip']
516 shelvectx = repo['tip']
517 if not shelvectx in state.pendingctx.children():
517 if not shelvectx in state.pendingctx.children():
518 # rebase was a no-op, so it produced no child commit
518 # rebase was a no-op, so it produced no child commit
519 shelvectx = state.pendingctx
519 shelvectx = state.pendingctx
520 else:
520 else:
521 # only strip the shelvectx if the rebase produced it
521 # only strip the shelvectx if the rebase produced it
522 state.stripnodes.append(shelvectx.node())
522 state.stripnodes.append(shelvectx.node())
523
523
524 mergefiles(ui, repo, state.wctx, shelvectx)
524 mergefiles(ui, repo, state.wctx, shelvectx)
525
525
526 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
526 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
527 shelvedstate.clear(repo)
527 shelvedstate.clear(repo)
528 unshelvecleanup(ui, repo, state.name, opts)
528 unshelvecleanup(ui, repo, state.name, opts)
529 ui.status(_("unshelve of '%s' complete\n") % state.name)
529 ui.status(_("unshelve of '%s' complete\n") % state.name)
530 finally:
530 finally:
531 lockmod.release(lock, wlock)
531 lockmod.release(lock, wlock)
532
532
533 @command('unshelve',
533 @command('unshelve',
534 [('a', 'abort', None,
534 [('a', 'abort', None,
535 _('abort an incomplete unshelve operation')),
535 _('abort an incomplete unshelve operation')),
536 ('c', 'continue', None,
536 ('c', 'continue', None,
537 _('continue an incomplete unshelve operation')),
537 _('continue an incomplete unshelve operation')),
538 ('', 'keep', None,
538 ('', 'keep', None,
539 _('keep shelve after unshelving')),
539 _('keep shelve after unshelving')),
540 ('', 'date', '',
540 ('', 'date', '',
541 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
541 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
542 _('hg unshelve [SHELVED]'))
542 _('hg unshelve [SHELVED]'))
543 def unshelve(ui, repo, *shelved, **opts):
543 def unshelve(ui, repo, *shelved, **opts):
544 """restore a shelved change to the working directory
544 """restore a shelved change to the working directory
545
545
546 This command accepts an optional name of a shelved change to
546 This command accepts an optional name of a shelved change to
547 restore. If none is given, the most recent shelved change is used.
547 restore. If none is given, the most recent shelved change is used.
548
548
549 If a shelved change is applied successfully, the bundle that
549 If a shelved change is applied successfully, the bundle that
550 contains the shelved changes is moved to a backup location
550 contains the shelved changes is moved to a backup location
551 (.hg/shelve-backup).
551 (.hg/shelve-backup).
552
552
553 Since you can restore a shelved change on top of an arbitrary
553 Since you can restore a shelved change on top of an arbitrary
554 commit, it is possible that unshelving will result in a conflict
554 commit, it is possible that unshelving will result in a conflict
555 between your changes and the commits you are unshelving onto. If
555 between your changes and the commits you are unshelving onto. If
556 this occurs, you must resolve the conflict, then use
556 this occurs, you must resolve the conflict, then use
557 ``--continue`` to complete the unshelve operation. (The bundle
557 ``--continue`` to complete the unshelve operation. (The bundle
558 will not be moved until you successfully complete the unshelve.)
558 will not be moved until you successfully complete the unshelve.)
559
559
560 (Alternatively, you can use ``--abort`` to abandon an unshelve
560 (Alternatively, you can use ``--abort`` to abandon an unshelve
561 that causes a conflict. This reverts the unshelved changes, and
561 that causes a conflict. This reverts the unshelved changes, and
562 leaves the bundle in place.)
562 leaves the bundle in place.)
563
563
564 After a successful unshelve, the shelved changes are stored in a
564 After a successful unshelve, the shelved changes are stored in a
565 backup directory. Only the N most recent backups are kept. N
565 backup directory. Only the N most recent backups are kept. N
566 defaults to 10 but can be overridden using the shelve.maxbackups
566 defaults to 10 but can be overridden using the shelve.maxbackups
567 configuration option.
567 configuration option.
568
568
569 .. container:: verbose
569 .. container:: verbose
570
570
571 Timestamp in seconds is used to decide order of backups. More
571 Timestamp in seconds is used to decide order of backups. More
572 than ``maxbackups`` backups are kept, if same timestamp
572 than ``maxbackups`` backups are kept, if same timestamp
573 prevents from deciding exact order of them, for safety.
573 prevents from deciding exact order of them, for safety.
574 """
574 """
575 abortf = opts['abort']
575 abortf = opts['abort']
576 continuef = opts['continue']
576 continuef = opts['continue']
577 if not abortf and not continuef:
577 if not abortf and not continuef:
578 cmdutil.checkunfinished(repo)
578 cmdutil.checkunfinished(repo)
579
579
580 if abortf or continuef:
580 if abortf or continuef:
581 if abortf and continuef:
581 if abortf and continuef:
582 raise util.Abort(_('cannot use both abort and continue'))
582 raise util.Abort(_('cannot use both abort and continue'))
583 if shelved:
583 if shelved:
584 raise util.Abort(_('cannot combine abort/continue with '
584 raise util.Abort(_('cannot combine abort/continue with '
585 'naming a shelved change'))
585 'naming a shelved change'))
586
586
587 try:
587 try:
588 state = shelvedstate.load(repo)
588 state = shelvedstate.load(repo)
589 except IOError as err:
589 except IOError as err:
590 if err.errno != errno.ENOENT:
590 if err.errno != errno.ENOENT:
591 raise
591 raise
592 raise util.Abort(_('no unshelve operation underway'))
592 raise util.Abort(_('no unshelve operation underway'))
593
593
594 if abortf:
594 if abortf:
595 return unshelveabort(ui, repo, state, opts)
595 return unshelveabort(ui, repo, state, opts)
596 elif continuef:
596 elif continuef:
597 return unshelvecontinue(ui, repo, state, opts)
597 return unshelvecontinue(ui, repo, state, opts)
598 elif len(shelved) > 1:
598 elif len(shelved) > 1:
599 raise util.Abort(_('can only unshelve one change at a time'))
599 raise util.Abort(_('can only unshelve one change at a time'))
600 elif not shelved:
600 elif not shelved:
601 shelved = listshelves(repo)
601 shelved = listshelves(repo)
602 if not shelved:
602 if not shelved:
603 raise util.Abort(_('no shelved changes to apply!'))
603 raise util.Abort(_('no shelved changes to apply!'))
604 basename = util.split(shelved[0][1])[1]
604 basename = util.split(shelved[0][1])[1]
605 ui.status(_("unshelving change '%s'\n") % basename)
605 ui.status(_("unshelving change '%s'\n") % basename)
606 else:
606 else:
607 basename = shelved[0]
607 basename = shelved[0]
608
608
609 if not shelvedfile(repo, basename, 'patch').exists():
609 if not shelvedfile(repo, basename, 'patch').exists():
610 raise util.Abort(_("shelved change '%s' not found") % basename)
610 raise util.Abort(_("shelved change '%s' not found") % basename)
611
611
612 oldquiet = ui.quiet
612 oldquiet = ui.quiet
613 wlock = lock = tr = None
613 wlock = lock = tr = None
614 try:
614 try:
615 wlock = repo.wlock()
615 wlock = repo.wlock()
616 lock = repo.lock()
616 lock = repo.lock()
617
617
618 tr = repo.transaction('unshelve', report=lambda x: None)
618 tr = repo.transaction('unshelve', report=lambda x: None)
619 oldtiprev = len(repo)
619 oldtiprev = len(repo)
620
620
621 pctx = repo['.']
621 pctx = repo['.']
622 tmpwctx = pctx
622 tmpwctx = pctx
623 # The goal is to have a commit structure like so:
623 # The goal is to have a commit structure like so:
624 # ...-> pctx -> tmpwctx -> shelvectx
624 # ...-> pctx -> tmpwctx -> shelvectx
625 # where tmpwctx is an optional commit with the user's pending changes
625 # where tmpwctx is an optional commit with the user's pending changes
626 # and shelvectx is the unshelved changes. Then we merge it all down
626 # and shelvectx is the unshelved changes. Then we merge it all down
627 # to the original pctx.
627 # to the original pctx.
628
628
629 # Store pending changes in a commit
629 # Store pending changes in a commit
630 s = repo.status()
630 s = repo.status()
631 if s.modified or s.added or s.removed or s.deleted:
631 if s.modified or s.added or s.removed or s.deleted:
632 ui.status(_("temporarily committing pending changes "
632 ui.status(_("temporarily committing pending changes "
633 "(restore with 'hg unshelve --abort')\n"))
633 "(restore with 'hg unshelve --abort')\n"))
634 def commitfunc(ui, repo, message, match, opts):
634 def commitfunc(ui, repo, message, match, opts):
635 hasmq = util.safehasattr(repo, 'mq')
635 hasmq = util.safehasattr(repo, 'mq')
636 if hasmq:
636 if hasmq:
637 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
637 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
638
638
639 backup = repo.ui.backupconfig('phases', 'new-commit')
639 backup = repo.ui.backupconfig('phases', 'new-commit')
640 try:
640 try:
641 repo.ui. setconfig('phases', 'new-commit', phases.secret)
641 repo.ui. setconfig('phases', 'new-commit', phases.secret)
642 return repo.commit(message, 'shelve@localhost',
642 return repo.commit(message, 'shelve@localhost',
643 opts.get('date'), match)
643 opts.get('date'), match)
644 finally:
644 finally:
645 repo.ui.restoreconfig(backup)
645 repo.ui.restoreconfig(backup)
646 if hasmq:
646 if hasmq:
647 repo.mq.checkapplied = saved
647 repo.mq.checkapplied = saved
648
648
649 tempopts = {}
649 tempopts = {}
650 tempopts['message'] = "pending changes temporary commit"
650 tempopts['message'] = "pending changes temporary commit"
651 tempopts['date'] = opts.get('date')
651 tempopts['date'] = opts.get('date')
652 ui.quiet = True
652 ui.quiet = True
653 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
653 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
654 tmpwctx = repo[node]
654 tmpwctx = repo[node]
655
655
656 ui.quiet = True
656 ui.quiet = True
657 shelvedfile(repo, basename, 'hg').applybundle()
657 shelvedfile(repo, basename, 'hg').applybundle()
658
658
659 ui.quiet = oldquiet
659 ui.quiet = oldquiet
660
660
661 shelvectx = repo['tip']
661 shelvectx = repo['tip']
662
662
663 # If the shelve is not immediately on top of the commit
663 # If the shelve is not immediately on top of the commit
664 # we'll be merging with, rebase it to be on top.
664 # we'll be merging with, rebase it to be on top.
665 if tmpwctx.node() != shelvectx.parents()[0].node():
665 if tmpwctx.node() != shelvectx.parents()[0].node():
666 ui.status(_('rebasing shelved changes\n'))
666 ui.status(_('rebasing shelved changes\n'))
667 try:
667 try:
668 rebase.rebase(ui, repo, **{
668 rebase.rebase(ui, repo, **{
669 'rev' : [shelvectx.rev()],
669 'rev' : [shelvectx.rev()],
670 'dest' : str(tmpwctx.rev()),
670 'dest' : str(tmpwctx.rev()),
671 'keep' : True,
671 'keep' : True,
672 })
672 })
673 except error.InterventionRequired:
673 except error.InterventionRequired:
674 tr.close()
674 tr.close()
675
675
676 stripnodes = [repo.changelog.node(rev)
676 stripnodes = [repo.changelog.node(rev)
677 for rev in xrange(oldtiprev, len(repo))]
677 for rev in xrange(oldtiprev, len(repo))]
678 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
678 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
679
679
680 util.rename(repo.join('rebasestate'),
680 util.rename(repo.join('rebasestate'),
681 repo.join('unshelverebasestate'))
681 repo.join('unshelverebasestate'))
682 raise error.InterventionRequired(
682 raise error.InterventionRequired(
683 _("unresolved conflicts (see 'hg resolve', then "
683 _("unresolved conflicts (see 'hg resolve', then "
684 "'hg unshelve --continue')"))
684 "'hg unshelve --continue')"))
685
685
686 # refresh ctx after rebase completes
686 # refresh ctx after rebase completes
687 shelvectx = repo['tip']
687 shelvectx = repo['tip']
688
688
689 if not shelvectx in tmpwctx.children():
689 if not shelvectx in tmpwctx.children():
690 # rebase was a no-op, so it produced no child commit
690 # rebase was a no-op, so it produced no child commit
691 shelvectx = tmpwctx
691 shelvectx = tmpwctx
692
692
693 mergefiles(ui, repo, pctx, shelvectx)
693 mergefiles(ui, repo, pctx, shelvectx)
694 shelvedstate.clear(repo)
694 shelvedstate.clear(repo)
695
695
696 # The transaction aborting will strip all the commits for us,
696 # The transaction aborting will strip all the commits for us,
697 # but it doesn't update the inmemory structures, so addchangegroup
697 # but it doesn't update the inmemory structures, so addchangegroup
698 # hooks still fire and try to operate on the missing commits.
698 # hooks still fire and try to operate on the missing commits.
699 # Clean up manually to prevent this.
699 # Clean up manually to prevent this.
700 repo.unfiltered().changelog.strip(oldtiprev, tr)
700 repo.unfiltered().changelog.strip(oldtiprev, tr)
701
701
702 unshelvecleanup(ui, repo, basename, opts)
702 unshelvecleanup(ui, repo, basename, opts)
703 finally:
703 finally:
704 ui.quiet = oldquiet
704 ui.quiet = oldquiet
705 if tr:
705 if tr:
706 tr.release()
706 tr.release()
707 lockmod.release(lock, wlock)
707 lockmod.release(lock, wlock)
708
708
709 @command('shelve',
709 @command('shelve',
710 [('A', 'addremove', None,
710 [('A', 'addremove', None,
711 _('mark new/missing files as added/removed before shelving')),
711 _('mark new/missing files as added/removed before shelving')),
712 ('', 'cleanup', None,
712 ('', 'cleanup', None,
713 _('delete all shelved changes')),
713 _('delete all shelved changes')),
714 ('', 'date', '',
714 ('', 'date', '',
715 _('shelve with the specified commit date'), _('DATE')),
715 _('shelve with the specified commit date'), _('DATE')),
716 ('d', 'delete', None,
716 ('d', 'delete', None,
717 _('delete the named shelved change(s)')),
717 _('delete the named shelved change(s)')),
718 ('e', 'edit', False,
718 ('e', 'edit', False,
719 _('invoke editor on commit messages')),
719 _('invoke editor on commit messages')),
720 ('l', 'list', None,
720 ('l', 'list', None,
721 _('list current shelves')),
721 _('list current shelves')),
722 ('m', 'message', '',
722 ('m', 'message', '',
723 _('use text as shelve message'), _('TEXT')),
723 _('use text as shelve message'), _('TEXT')),
724 ('n', 'name', '',
724 ('n', 'name', '',
725 _('use the given name for the shelved commit'), _('NAME')),
725 _('use the given name for the shelved commit'), _('NAME')),
726 ('p', 'patch', None,
726 ('p', 'patch', None,
727 _('show patch')),
727 _('show patch')),
728 ('i', 'interactive', None,
728 ('i', 'interactive', None,
729 _('interactive mode, only works while creating a shelve')),
729 _('interactive mode, only works while creating a shelve')),
730 ('', 'stat', None,
730 ('', 'stat', None,
731 _('output diffstat-style summary of changes'))] + commands.walkopts,
731 _('output diffstat-style summary of changes'))] + commands.walkopts,
732 _('hg shelve [OPTION]... [FILE]...'))
732 _('hg shelve [OPTION]... [FILE]...'))
733 def shelvecmd(ui, repo, *pats, **opts):
733 def shelvecmd(ui, repo, *pats, **opts):
734 '''save and set aside changes from the working directory
734 '''save and set aside changes from the working directory
735
735
736 Shelving takes files that "hg status" reports as not clean, saves
736 Shelving takes files that "hg status" reports as not clean, saves
737 the modifications to a bundle (a shelved change), and reverts the
737 the modifications to a bundle (a shelved change), and reverts the
738 files so that their state in the working directory becomes clean.
738 files so that their state in the working directory becomes clean.
739
739
740 To restore these changes to the working directory, using "hg
740 To restore these changes to the working directory, using "hg
741 unshelve"; this will work even if you switch to a different
741 unshelve"; this will work even if you switch to a different
742 commit.
742 commit.
743
743
744 When no files are specified, "hg shelve" saves all not-clean
744 When no files are specified, "hg shelve" saves all not-clean
745 files. If specific files or directories are named, only changes to
745 files. If specific files or directories are named, only changes to
746 those files are shelved.
746 those files are shelved.
747
747
748 Each shelved change has a name that makes it easier to find later.
748 Each shelved change has a name that makes it easier to find later.
749 The name of a shelved change defaults to being based on the active
749 The name of a shelved change defaults to being based on the active
750 bookmark, or if there is no active bookmark, the current named
750 bookmark, or if there is no active bookmark, the current named
751 branch. To specify a different name, use ``--name``.
751 branch. To specify a different name, use ``--name``.
752
752
753 To see a list of existing shelved changes, use the ``--list``
753 To see a list of existing shelved changes, use the ``--list``
754 option. For each shelved change, this will print its name, age,
754 option. For each shelved change, this will print its name, age,
755 and description; use ``--patch`` or ``--stat`` for more details.
755 and description; use ``--patch`` or ``--stat`` for more details.
756
756
757 To delete specific shelved changes, use ``--delete``. To delete
757 To delete specific shelved changes, use ``--delete``. To delete
758 all shelved changes, use ``--cleanup``.
758 all shelved changes, use ``--cleanup``.
759 '''
759 '''
760 cmdutil.checkunfinished(repo)
760 cmdutil.checkunfinished(repo)
761
761
762 allowables = [
762 allowables = [
763 ('addremove', set(['create'])), # 'create' is pseudo action
763 ('addremove', set(['create'])), # 'create' is pseudo action
764 ('cleanup', set(['cleanup'])),
764 ('cleanup', set(['cleanup'])),
765 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
765 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
766 ('delete', set(['delete'])),
766 ('delete', set(['delete'])),
767 ('edit', set(['create'])),
767 ('edit', set(['create'])),
768 ('list', set(['list'])),
768 ('list', set(['list'])),
769 ('message', set(['create'])),
769 ('message', set(['create'])),
770 ('name', set(['create'])),
770 ('name', set(['create'])),
771 ('patch', set(['patch', 'list'])),
771 ('patch', set(['patch', 'list'])),
772 ('stat', set(['stat', 'list'])),
772 ('stat', set(['stat', 'list'])),
773 ]
773 ]
774 def checkopt(opt):
774 def checkopt(opt):
775 if opts[opt]:
775 if opts[opt]:
776 for i, allowable in allowables:
776 for i, allowable in allowables:
777 if opts[i] and opt not in allowable:
777 if opts[i] and opt not in allowable:
778 raise util.Abort(_("options '--%s' and '--%s' may not be "
778 raise util.Abort(_("options '--%s' and '--%s' may not be "
779 "used together") % (opt, i))
779 "used together") % (opt, i))
780 return True
780 return True
781 if checkopt('cleanup'):
781 if checkopt('cleanup'):
782 if pats:
782 if pats:
783 raise util.Abort(_("cannot specify names when using '--cleanup'"))
783 raise util.Abort(_("cannot specify names when using '--cleanup'"))
784 return cleanupcmd(ui, repo)
784 return cleanupcmd(ui, repo)
785 elif checkopt('delete'):
785 elif checkopt('delete'):
786 return deletecmd(ui, repo, pats)
786 return deletecmd(ui, repo, pats)
787 elif checkopt('list'):
787 elif checkopt('list'):
788 return listcmd(ui, repo, pats, opts)
788 return listcmd(ui, repo, pats, opts)
789 elif checkopt('patch'):
789 elif checkopt('patch'):
790 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
790 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
791 elif checkopt('stat'):
791 elif checkopt('stat'):
792 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
792 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
793 else:
793 else:
794 return createcmd(ui, repo, pats, opts)
794 return createcmd(ui, repo, pats, opts)
795
795
796 def extsetup(ui):
796 def extsetup(ui):
797 cmdutil.unfinishedstates.append(
797 cmdutil.unfinishedstates.append(
798 [shelvedstate._filename, False, False,
798 [shelvedstate._filename, False, False,
799 _('unshelve already in progress'),
799 _('unshelve already in progress'),
800 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
800 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
@@ -1,953 +1,956 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 during merge.
304 warning: conflicts during merge.
305 merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
305 merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
306 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
306 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
307 [1]
307 [1]
308
308
309 ensure that we have a merge with unresolved conflicts
309 ensure that we have a merge with unresolved conflicts
310
310
311 $ hg heads -q --template '{rev}\n'
311 $ hg heads -q --template '{rev}\n'
312 5
312 5
313 4
313 4
314 $ hg parents -q --template '{rev}\n'
314 $ hg parents -q --template '{rev}\n'
315 4
315 4
316 5
316 5
317 $ hg status
317 $ hg status
318 M a/a
318 M a/a
319 M b.rename/b
319 M b.rename/b
320 M c.copy
320 M c.copy
321 R b/b
321 R b/b
322 ? a/a.orig
322 ? a/a.orig
323 $ hg diff
323 $ hg diff
324 diff --git a/a/a b/a/a
324 diff --git a/a/a b/a/a
325 --- a/a/a
325 --- a/a/a
326 +++ b/a/a
326 +++ b/a/a
327 @@ -1,2 +1,6 @@
327 @@ -1,2 +1,6 @@
328 a
328 a
329 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
329 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
330 c
330 c
331 +=======
331 +=======
332 +a
332 +a
333 +>>>>>>> source: 4702e8911fe0 - shelve: changes to '[mq]: second.patch'
333 +>>>>>>> source: 4702e8911fe0 - shelve: changes to '[mq]: second.patch'
334 diff --git a/b/b b/b.rename/b
334 diff --git a/b/b b/b.rename/b
335 rename from b/b
335 rename from b/b
336 rename to b.rename/b
336 rename to b.rename/b
337 diff --git a/c b/c.copy
337 diff --git a/c b/c.copy
338 copy from c
338 copy from c
339 copy to c.copy
339 copy to c.copy
340 $ hg resolve -l
340 $ hg resolve -l
341 U a/a
341 U a/a
342
342
343 $ hg shelve
343 $ hg shelve
344 abort: unshelve already in progress
344 abort: unshelve already in progress
345 (use 'hg unshelve --continue' or 'hg unshelve --abort')
345 (use 'hg unshelve --continue' or 'hg unshelve --abort')
346 [255]
346 [255]
347
347
348 abort the unshelve and be happy
348 abort the unshelve and be happy
349
349
350 $ hg status
350 $ hg status
351 M a/a
351 M a/a
352 M b.rename/b
352 M b.rename/b
353 M c.copy
353 M c.copy
354 R b/b
354 R b/b
355 ? a/a.orig
355 ? a/a.orig
356 $ hg unshelve -a
356 $ hg unshelve -a
357 rebase aborted
357 rebase aborted
358 unshelve of 'default' aborted
358 unshelve of 'default' aborted
359 $ hg heads -q
359 $ hg heads -q
360 3:2e69b451d1ea
360 3:2e69b451d1ea
361 $ hg parents
361 $ hg parents
362 changeset: 3:2e69b451d1ea
362 changeset: 3:2e69b451d1ea
363 tag: tip
363 tag: tip
364 user: test
364 user: test
365 date: Thu Jan 01 00:00:00 1970 +0000
365 date: Thu Jan 01 00:00:00 1970 +0000
366 summary: second
366 summary: second
367
367
368 $ hg resolve -l
368 $ hg resolve -l
369 $ hg status
369 $ hg status
370 A foo/foo
370 A foo/foo
371 ? a/a.orig
371 ? a/a.orig
372
372
373 try to continue with no unshelve underway
373 try to continue with no unshelve underway
374
374
375 $ hg unshelve -c
375 $ hg unshelve -c
376 abort: no unshelve operation underway
376 abort: no unshelve operation underway
377 [255]
377 [255]
378 $ hg status
378 $ hg status
379 A foo/foo
379 A foo/foo
380 ? a/a.orig
380 ? a/a.orig
381
381
382 redo the unshelve to get a conflict
382 redo the unshelve to get a conflict
383
383
384 $ hg unshelve -q
384 $ hg unshelve -q
385 warning: conflicts during merge.
385 warning: conflicts during merge.
386 merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
386 merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
387 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
387 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
388 [1]
388 [1]
389
389
390 attempt to continue
390 attempt to continue
391
391
392 $ hg unshelve -c
392 $ hg unshelve -c
393 abort: unresolved conflicts, can't continue
393 abort: unresolved conflicts, can't continue
394 (see 'hg resolve', then 'hg unshelve --continue')
394 (see 'hg resolve', then 'hg unshelve --continue')
395 [255]
395 [255]
396
396
397 $ hg revert -r . a/a
397 $ hg revert -r . a/a
398 $ hg resolve -m a/a
398 $ hg resolve -m a/a
399 (no more unresolved files)
399 (no more unresolved files)
400
400
401 $ hg commit -m 'commit while unshelve in progress'
401 $ hg commit -m 'commit while unshelve in progress'
402 abort: unshelve already in progress
402 abort: unshelve already in progress
403 (use 'hg unshelve --continue' or 'hg unshelve --abort')
403 (use 'hg unshelve --continue' or 'hg unshelve --abort')
404 [255]
404 [255]
405
405
406 $ hg unshelve -c
406 $ hg unshelve -c
407 rebasing 5:4702e8911fe0 "changes to '[mq]: second.patch'" (tip)
407 rebasing 5:4702e8911fe0 "changes to '[mq]: second.patch'" (tip)
408 unshelve of 'default' complete
408 unshelve of 'default' complete
409
409
410 ensure the repo is as we hope
410 ensure the repo is as we hope
411
411
412 $ hg parents
412 $ hg parents
413 changeset: 3:2e69b451d1ea
413 changeset: 3:2e69b451d1ea
414 tag: tip
414 tag: tip
415 user: test
415 user: test
416 date: Thu Jan 01 00:00:00 1970 +0000
416 date: Thu Jan 01 00:00:00 1970 +0000
417 summary: second
417 summary: second
418
418
419 $ hg heads -q
419 $ hg heads -q
420 3:2e69b451d1ea
420 3:2e69b451d1ea
421
421
422 $ hg status -C
422 $ hg status -C
423 A b.rename/b
423 A b.rename/b
424 b/b
424 b/b
425 A c.copy
425 A c.copy
426 c
426 c
427 A foo/foo
427 A foo/foo
428 R b/b
428 R b/b
429 ? a/a.orig
429 ? a/a.orig
430
430
431 there should be no shelves left
431 there should be no shelves left
432
432
433 $ hg shelve -l
433 $ hg shelve -l
434
434
435 #if execbit
435 #if execbit
436
436
437 ensure that metadata-only changes are shelved
437 ensure that metadata-only changes are shelved
438
438
439 $ chmod +x a/a
439 $ chmod +x a/a
440 $ hg shelve -q -n execbit a/a
440 $ hg shelve -q -n execbit a/a
441 $ hg status a/a
441 $ hg status a/a
442 $ hg unshelve -q execbit
442 $ hg unshelve -q execbit
443 $ hg status a/a
443 $ hg status a/a
444 M a/a
444 M a/a
445 $ hg revert a/a
445 $ hg revert a/a
446
446
447 #endif
447 #endif
448
448
449 #if symlink
449 #if symlink
450
450
451 $ rm a/a
451 $ rm a/a
452 $ ln -s foo a/a
452 $ ln -s foo a/a
453 $ hg shelve -q -n symlink a/a
453 $ hg shelve -q -n symlink a/a
454 $ hg status a/a
454 $ hg status a/a
455 $ hg unshelve -q symlink
455 $ hg unshelve -q symlink
456 $ hg status a/a
456 $ hg status a/a
457 M a/a
457 M a/a
458 $ hg revert a/a
458 $ hg revert a/a
459
459
460 #endif
460 #endif
461
461
462 set up another conflict between a commit and a shelved change
462 set up another conflict between a commit and a shelved change
463
463
464 $ hg revert -q -C -a
464 $ hg revert -q -C -a
465 $ rm a/a.orig b.rename/b c.copy
465 $ rm a/a.orig b.rename/b c.copy
466 $ echo a >> a/a
466 $ echo a >> a/a
467 $ hg shelve -q
467 $ hg shelve -q
468 $ echo x >> a/a
468 $ echo x >> a/a
469 $ hg ci -m 'create conflict'
469 $ hg ci -m 'create conflict'
470 $ hg add foo/foo
470 $ hg add foo/foo
471
471
472 if we resolve a conflict while unshelving, the unshelve should succeed
472 if we resolve a conflict while unshelving, the unshelve should succeed
473
473
474 $ HGMERGE=true hg unshelve
474 $ HGMERGE=true hg unshelve
475 unshelving change 'default'
475 unshelving change 'default'
476 temporarily committing pending changes (restore with 'hg unshelve --abort')
476 temporarily committing pending changes (restore with 'hg unshelve --abort')
477 rebasing shelved changes
477 rebasing shelved changes
478 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
478 rebasing 6:c5e6910e7601 "changes to 'second'" (tip)
479 merging a/a
479 merging a/a
480 note: rebase of 6:c5e6910e7601 created no changes to commit
480 note: rebase of 6:c5e6910e7601 created no changes to commit
481 $ hg parents -q
481 $ hg parents -q
482 4:33f7f61e6c5e
482 4:33f7f61e6c5e
483 $ hg shelve -l
483 $ hg shelve -l
484 $ hg status
484 $ hg status
485 A foo/foo
485 A foo/foo
486 $ cat a/a
486 $ cat a/a
487 a
487 a
488 c
488 c
489 x
489 x
490
490
491 test keep and cleanup
491 test keep and cleanup
492
492
493 $ hg shelve
493 $ hg shelve
494 shelved as default
494 shelved as default
495 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
495 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
496 $ hg shelve --list
496 $ hg shelve --list
497 default (*) changes to 'create conflict' (glob)
497 default (*) changes to 'create conflict' (glob)
498 $ hg unshelve --keep
498 $ hg unshelve --keep
499 unshelving change 'default'
499 unshelving change 'default'
500 $ hg shelve --list
500 $ hg shelve --list
501 default (*) changes to 'create conflict' (glob)
501 default (*) changes to 'create conflict' (glob)
502 $ hg shelve --cleanup
502 $ hg shelve --cleanup
503 $ hg shelve --list
503 $ hg shelve --list
504
504
505 $ hg shelve --cleanup --delete
505 $ hg shelve --cleanup --delete
506 abort: options '--cleanup' and '--delete' may not be used together
506 abort: options '--cleanup' and '--delete' may not be used together
507 [255]
507 [255]
508 $ hg shelve --cleanup --patch
508 $ hg shelve --cleanup --patch
509 abort: options '--cleanup' and '--patch' may not be used together
509 abort: options '--cleanup' and '--patch' may not be used together
510 [255]
510 [255]
511 $ hg shelve --cleanup --message MESSAGE
511 $ hg shelve --cleanup --message MESSAGE
512 abort: options '--cleanup' and '--message' may not be used together
512 abort: options '--cleanup' and '--message' may not be used together
513 [255]
513 [255]
514
514
515 test bookmarks
515 test bookmarks
516
516
517 $ hg bookmark test
517 $ hg bookmark test
518 $ hg bookmark
518 $ hg bookmark
519 * test 4:33f7f61e6c5e
519 * test 4:33f7f61e6c5e
520 $ hg shelve
520 $ hg shelve
521 shelved as test
521 shelved as test
522 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
522 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
523 $ hg bookmark
523 $ hg bookmark
524 * test 4:33f7f61e6c5e
524 * test 4:33f7f61e6c5e
525 $ hg unshelve
525 $ hg unshelve
526 unshelving change 'test'
526 unshelving change 'test'
527 $ hg bookmark
527 $ hg bookmark
528 * test 4:33f7f61e6c5e
528 * test 4:33f7f61e6c5e
529
529
530 shelve should still work even if mq is disabled
530 shelve should still work even if mq is disabled
531
531
532 $ hg --config extensions.mq=! shelve
532 $ hg --config extensions.mq=! shelve
533 shelved as test
533 shelved as test
534 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
534 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
535 $ hg --config extensions.mq=! shelve --list
535 $ hg --config extensions.mq=! shelve --list
536 test (*) changes to 'create conflict' (glob)
536 test (*) changes to 'create conflict' (glob)
537 $ hg --config extensions.mq=! unshelve
537 $ hg --config extensions.mq=! unshelve
538 unshelving change 'test'
538 unshelving change 'test'
539
539
540 shelve should leave dirstate clean (issue4055)
540 shelve should leave dirstate clean (issue4055)
541
541
542 $ cd ..
542 $ cd ..
543 $ hg init shelverebase
543 $ hg init shelverebase
544 $ cd shelverebase
544 $ cd shelverebase
545 $ printf 'x\ny\n' > x
545 $ printf 'x\ny\n' > x
546 $ echo z > z
546 $ echo z > z
547 $ hg commit -Aqm xy
547 $ hg commit -Aqm xy
548 $ echo z >> x
548 $ echo z >> x
549 $ hg commit -Aqm z
549 $ hg commit -Aqm z
550 $ hg up 0
550 $ hg up 0
551 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
551 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
552 $ printf 'a\nx\ny\nz\n' > x
552 $ printf 'a\nx\ny\nz\n' > x
553 $ hg commit -Aqm xyz
553 $ hg commit -Aqm xyz
554 $ echo c >> z
554 $ echo c >> z
555 $ hg shelve
555 $ hg shelve
556 shelved as default
556 shelved as default
557 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 $ hg rebase -d 1 --config extensions.rebase=
558 $ hg rebase -d 1 --config extensions.rebase=
559 rebasing 2:323bfa07f744 "xyz" (tip)
559 rebasing 2:323bfa07f744 "xyz" (tip)
560 merging x
560 merging x
561 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
561 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
562 $ hg unshelve
562 $ hg unshelve
563 unshelving change 'default'
563 unshelving change 'default'
564 rebasing shelved changes
564 rebasing shelved changes
565 rebasing 4:b8fefe789ed0 "changes to 'xyz'" (tip)
565 rebasing 4:b8fefe789ed0 "changes to 'xyz'" (tip)
566 $ hg status
566 $ hg status
567 M z
567 M z
568
568
569 $ cd ..
569 $ cd ..
570
570
571 shelve should only unshelve pending changes (issue4068)
571 shelve should only unshelve pending changes (issue4068)
572
572
573 $ hg init onlypendingchanges
573 $ hg init onlypendingchanges
574 $ cd onlypendingchanges
574 $ cd onlypendingchanges
575 $ touch a
575 $ touch a
576 $ hg ci -Aqm a
576 $ hg ci -Aqm a
577 $ touch b
577 $ touch b
578 $ hg ci -Aqm b
578 $ hg ci -Aqm b
579 $ hg up -q 0
579 $ hg up -q 0
580 $ touch c
580 $ touch c
581 $ hg ci -Aqm c
581 $ hg ci -Aqm c
582
582
583 $ touch d
583 $ touch d
584 $ hg add d
584 $ hg add d
585 $ hg shelve
585 $ hg shelve
586 shelved as default
586 shelved as default
587 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
587 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
588 $ hg up -q 1
588 $ hg up -q 1
589 $ hg unshelve
589 $ hg unshelve
590 unshelving change 'default'
590 unshelving change 'default'
591 rebasing shelved changes
591 rebasing shelved changes
592 rebasing 3:0cae6656c016 "changes to 'c'" (tip)
592 rebasing 3:0cae6656c016 "changes to 'c'" (tip)
593 $ hg status
593 $ hg status
594 A d
594 A d
595
595
596 unshelve should work on an ancestor of the original commit
596 unshelve should work on an ancestor of the original commit
597
597
598 $ hg shelve
598 $ hg shelve
599 shelved as default
599 shelved as default
600 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
600 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
601 $ hg up 0
601 $ hg up 0
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 unshelve
603 $ hg unshelve
604 unshelving change 'default'
604 unshelving change 'default'
605 rebasing shelved changes
605 rebasing shelved changes
606 rebasing 3:be58f65f55fb "changes to 'b'" (tip)
606 rebasing 3:be58f65f55fb "changes to 'b'" (tip)
607 $ hg status
607 $ hg status
608 A d
608 A d
609
609
610 test bug 4073 we need to enable obsolete markers for it
610 test bug 4073 we need to enable obsolete markers for it
611
611
612 $ cat >> $HGRCPATH << EOF
612 $ cat >> $HGRCPATH << EOF
613 > [experimental]
613 > [experimental]
614 > evolution=createmarkers
614 > evolution=createmarkers
615 > EOF
615 > EOF
616 $ hg shelve
616 $ hg shelve
617 shelved as default
617 shelved as default
618 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
618 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
619 $ hg debugobsolete `hg --debug id -i -r 1`
619 $ hg debugobsolete `hg --debug id -i -r 1`
620 $ hg unshelve
620 $ hg unshelve
621 unshelving change 'default'
621 unshelving change 'default'
622
622
623 unshelve should leave unknown files alone (issue4113)
623 unshelve should leave unknown files alone (issue4113)
624
624
625 $ echo e > e
625 $ echo e > e
626 $ hg shelve
626 $ hg shelve
627 shelved as default
627 shelved as default
628 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
628 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
629 $ hg status
629 $ hg status
630 ? e
630 ? e
631 $ hg unshelve
631 $ hg unshelve
632 unshelving change 'default'
632 unshelving change 'default'
633 $ hg status
633 $ hg status
634 A d
634 A d
635 ? e
635 ? e
636 $ cat e
636 $ cat e
637 e
637 e
638
638
639 unshelve should keep a copy of unknown files
639 unshelve should keep a copy of unknown files
640
640
641 $ hg add e
641 $ hg add e
642 $ hg shelve
642 $ hg shelve
643 shelved as default
643 shelved as default
644 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
644 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
645 $ echo z > e
645 $ echo z > e
646 $ hg unshelve
646 $ hg unshelve
647 unshelving change 'default'
647 unshelving change 'default'
648 $ cat e
648 $ cat e
649 e
649 e
650 $ cat e.orig
650 $ cat e.orig
651 z
651 z
652
652
653
653
654 unshelve and conflicts with tracked and untracked files
654 unshelve and conflicts with tracked and untracked files
655
655
656 preparing:
656 preparing:
657
657
658 $ rm *.orig
658 $ rm *.orig
659 $ hg ci -qm 'commit stuff'
659 $ hg ci -qm 'commit stuff'
660 $ hg phase -p null:
660 $ hg phase -p null:
661
661
662 no other changes - no merge:
662 no other changes - no merge:
663
663
664 $ echo f > f
664 $ echo f > f
665 $ hg add f
665 $ hg add f
666 $ hg shelve
666 $ hg shelve
667 shelved as default
667 shelved as default
668 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
668 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
669 $ echo g > f
669 $ echo g > f
670 $ hg unshelve
670 $ hg unshelve
671 unshelving change 'default'
671 unshelving change 'default'
672 $ hg st
672 $ hg st
673 A f
673 A f
674 ? f.orig
674 ? f.orig
675 $ cat f
675 $ cat f
676 f
676 f
677 $ cat f.orig
677 $ cat f.orig
678 g
678 g
679
679
680 other uncommitted changes - merge:
680 other uncommitted changes - merge:
681
681
682 $ hg st
682 $ hg st
683 A f
683 A f
684 ? f.orig
684 ? f.orig
685 $ hg shelve
685 $ hg shelve
686 shelved as default
686 shelved as default
687 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
687 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
688 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
688 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
689 o 4 changes to 'commit stuff' shelve@localhost
689 o 4 changes to 'commit stuff' shelve@localhost
690 |
690 |
691 $ hg log -G --template '{rev} {desc|firstline} {author}'
691 $ hg log -G --template '{rev} {desc|firstline} {author}'
692 @ 3 commit stuff test
692 @ 3 commit stuff test
693 |
693 |
694 | o 2 c test
694 | o 2 c test
695 |/
695 |/
696 o 0 a test
696 o 0 a test
697
697
698 $ mv f.orig f
698 $ mv f.orig f
699 $ echo 1 > a
699 $ echo 1 > a
700 $ hg unshelve --date '1073741824 0'
700 $ hg unshelve --date '1073741824 0'
701 unshelving change 'default'
701 unshelving change 'default'
702 temporarily committing pending changes (restore with 'hg unshelve --abort')
702 temporarily committing pending changes (restore with 'hg unshelve --abort')
703 rebasing shelved changes
703 rebasing shelved changes
704 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
704 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
705 merging f
705 merging f
706 warning: conflicts during merge.
706 warning: conflicts during merge.
707 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
707 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
708 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
708 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
709 [1]
709 [1]
710 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
710 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
711 @ 5 changes to 'commit stuff' shelve@localhost 1970-01-01 00:00 +0000
711 @ 5 changes to 'commit stuff' shelve@localhost 1970-01-01 00:00 +0000
712 |
712 |
713 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
713 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
714 |/
714 |/
715 o 3 commit stuff test 1970-01-01 00:00 +0000
715 o 3 commit stuff test 1970-01-01 00:00 +0000
716 |
716 |
717 | o 2 c test 1970-01-01 00:00 +0000
717 | o 2 c test 1970-01-01 00:00 +0000
718 |/
718 |/
719 o 0 a test 1970-01-01 00:00 +0000
719 o 0 a test 1970-01-01 00:00 +0000
720
720
721 $ hg st
721 $ hg st
722 M f
722 M f
723 ? f.orig
723 ? f.orig
724 $ cat f
724 $ cat f
725 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
725 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
726 g
726 g
727 =======
727 =======
728 f
728 f
729 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
729 >>>>>>> source: 23b29cada8ba - shelve: changes to 'commit stuff'
730 $ cat f.orig
730 $ cat f.orig
731 g
731 g
732 $ hg unshelve --abort
732 $ hg unshelve --abort
733 rebase aborted
733 rebase aborted
734 unshelve of 'default' aborted
734 unshelve of 'default' aborted
735 $ hg st
735 $ hg st
736 M a
736 M a
737 ? f.orig
737 ? f.orig
738 $ cat f.orig
738 $ cat f.orig
739 g
739 g
740 $ hg unshelve
740 $ hg unshelve
741 unshelving change 'default'
741 unshelving change 'default'
742 temporarily committing pending changes (restore with 'hg unshelve --abort')
742 temporarily committing pending changes (restore with 'hg unshelve --abort')
743 rebasing shelved changes
743 rebasing shelved changes
744 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
744 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
745 $ hg st
745 $ hg st
746 M a
746 M a
747 A f
747 A f
748 ? f.orig
748 ? f.orig
749
749
750 other committed changes - merge:
750 other committed changes - merge:
751
751
752 $ hg shelve f
752 $ hg shelve f
753 shelved as default
753 shelved as default
754 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
754 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
755 $ hg ci a -m 'intermediate other change'
755 $ hg ci a -m 'intermediate other change'
756 $ mv f.orig f
756 $ mv f.orig f
757 $ hg unshelve
757 $ hg unshelve
758 unshelving change 'default'
758 unshelving change 'default'
759 rebasing shelved changes
759 rebasing shelved changes
760 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
760 rebasing 5:23b29cada8ba "changes to 'commit stuff'" (tip)
761 merging f
761 merging f
762 warning: conflicts during merge.
762 warning: conflicts during merge.
763 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
763 merging f incomplete! (edit conflicts, 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 unshelve
799 $ hg unshelve
800 unshelving change 'default'
800 unshelving change 'default'
801 rebasing shelved changes
801 rebasing shelved changes
802 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
802 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
803 merging a/a
803 merging a/a
804 warning: conflicts during merge.
804 warning: conflicts during merge.
805 merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
805 merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
806 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
806 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
807 [1]
807 [1]
808
808
809 Test that resolving all conflicts in one direction (so that the rebase
809 Test that resolving all conflicts in one direction (so that the rebase
810 is a no-op), works (issue4398)
810 is a no-op), works (issue4398)
811
811
812 $ hg revert -a -r .
812 $ hg revert -a -r .
813 reverting a/a (glob)
813 reverting a/a (glob)
814 $ hg resolve -m a/a
814 $ hg resolve -m a/a
815 (no more unresolved files)
815 (no more unresolved files)
816 $ hg unshelve -c
816 $ hg unshelve -c
817 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
817 rebasing 5:4b555fdb4e96 "changes to 'second'" (tip)
818 note: rebase of 5:4b555fdb4e96 created no changes to commit
818 note: rebase of 5:4b555fdb4e96 created no changes to commit
819 unshelve of 'default' complete
819 unshelve of 'default' complete
820 $ hg diff
820 $ hg diff
821 $ hg status
821 $ hg status
822 ? a/a.orig
822 ? a/a.orig
823 ? foo/foo
823 ? foo/foo
824 $ hg summary
824 $ hg summary
825 parent: 4:33f7f61e6c5e tip
825 parent: 4:33f7f61e6c5e tip
826 create conflict
826 create conflict
827 branch: default
827 branch: default
828 bookmarks: *test
828 bookmarks: *test
829 commit: 2 unknown (clean)
829 commit: 2 unknown (clean)
830 update: (current)
830 update: (current)
831 phases: 5 draft
831 phases: 5 draft
832
832
833 $ hg shelve --delete --stat
833 $ hg shelve --delete --stat
834 abort: options '--delete' and '--stat' may not be used together
834 abort: options '--delete' and '--stat' may not be used together
835 [255]
835 [255]
836 $ hg shelve --delete --name NAME
836 $ hg shelve --delete --name NAME
837 abort: options '--delete' and '--name' may not be used together
837 abort: options '--delete' and '--name' may not be used together
838 [255]
838 [255]
839
839
840 Test interactive shelve
840 Test interactive shelve
841 $ cat <<EOF >> $HGRCPATH
841 $ cat <<EOF >> $HGRCPATH
842 > [ui]
842 > [ui]
843 > interactive = true
843 > interactive = true
844 > EOF
844 > EOF
845 $ echo 'a' >> a/b
845 $ echo 'a' >> a/b
846 $ cat a/a >> a/b
846 $ cat a/a >> a/b
847 $ echo 'x' >> a/b
847 $ echo 'x' >> a/b
848 $ mv a/b a/a
848 $ mv a/b a/a
849 $ echo 'a' >> foo/foo
849 $ echo 'a' >> foo/foo
850 $ hg st
850 $ hg st
851 M a/a
851 M a/a
852 ? a/a.orig
852 ? a/a.orig
853 ? foo/foo
853 ? foo/foo
854 $ cat a/a
854 $ cat a/a
855 a
855 a
856 a
856 a
857 c
857 c
858 x
858 x
859 x
859 x
860 $ cat foo/foo
860 $ cat foo/foo
861 foo
861 foo
862 a
862 a
863 $ hg shelve --interactive --config ui.interactive=false
864 abort: running non-interactively
865 [255]
863 $ hg shelve --interactive << EOF
866 $ hg shelve --interactive << EOF
864 > y
867 > y
865 > y
868 > y
866 > n
869 > n
867 > EOF
870 > EOF
868 diff --git a/a/a b/a/a
871 diff --git a/a/a b/a/a
869 2 hunks, 2 lines changed
872 2 hunks, 2 lines changed
870 examine changes to 'a/a'? [Ynesfdaq?] y
873 examine changes to 'a/a'? [Ynesfdaq?] y
871
874
872 @@ -1,3 +1,4 @@
875 @@ -1,3 +1,4 @@
873 +a
876 +a
874 a
877 a
875 c
878 c
876 x
879 x
877 record change 1/2 to 'a/a'? [Ynesfdaq?] y
880 record change 1/2 to 'a/a'? [Ynesfdaq?] y
878
881
879 @@ -1,3 +2,4 @@
882 @@ -1,3 +2,4 @@
880 a
883 a
881 c
884 c
882 x
885 x
883 +x
886 +x
884 record change 2/2 to 'a/a'? [Ynesfdaq?] n
887 record change 2/2 to 'a/a'? [Ynesfdaq?] n
885
888
886 shelved as test
889 shelved as test
887 merging a/a
890 merging a/a
888 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
891 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
889 $ cat a/a
892 $ cat a/a
890 a
893 a
891 c
894 c
892 x
895 x
893 x
896 x
894 $ cat foo/foo
897 $ cat foo/foo
895 foo
898 foo
896 a
899 a
897 $ hg st
900 $ hg st
898 M a/a
901 M a/a
899 ? foo/foo
902 ? foo/foo
900 $ hg unshelve
903 $ hg unshelve
901 unshelving change 'test'
904 unshelving change 'test'
902 temporarily committing pending changes (restore with 'hg unshelve --abort')
905 temporarily committing pending changes (restore with 'hg unshelve --abort')
903 rebasing shelved changes
906 rebasing shelved changes
904 rebasing 6:65b5d1c34c34 "changes to 'create conflict'" (tip)
907 rebasing 6:65b5d1c34c34 "changes to 'create conflict'" (tip)
905 merging a/a
908 merging a/a
906 $ cat a/a
909 $ cat a/a
907 a
910 a
908 a
911 a
909 c
912 c
910 x
913 x
911 x
914 x
912
915
913 shelve --patch and shelve --stat should work with a single valid shelfname
916 shelve --patch and shelve --stat should work with a single valid shelfname
914
917
915 $ hg up --clean .
918 $ hg up --clean .
916 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
919 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
917 $ hg shelve --list
920 $ hg shelve --list
918 $ echo 'patch a' > shelf-patch-a
921 $ echo 'patch a' > shelf-patch-a
919 $ hg add shelf-patch-a
922 $ hg add shelf-patch-a
920 $ hg shelve
923 $ hg shelve
921 shelved as default
924 shelved as default
922 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
925 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
923 $ echo 'patch b' > shelf-patch-b
926 $ echo 'patch b' > shelf-patch-b
924 $ hg add shelf-patch-b
927 $ hg add shelf-patch-b
925 $ hg shelve
928 $ hg shelve
926 shelved as default-01
929 shelved as default-01
927 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
930 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
928 $ hg shelve --patch default default-01
931 $ hg shelve --patch default default-01
929 abort: --patch expects a single shelf
932 abort: --patch expects a single shelf
930 [255]
933 [255]
931 $ hg shelve --stat default default-01
934 $ hg shelve --stat default default-01
932 abort: --stat expects a single shelf
935 abort: --stat expects a single shelf
933 [255]
936 [255]
934 $ hg shelve --patch default
937 $ hg shelve --patch default
935 default (* ago) changes to 'create conflict' (glob)
938 default (* ago) changes to 'create conflict' (glob)
936
939
937 diff --git a/shelf-patch-a b/shelf-patch-a
940 diff --git a/shelf-patch-a b/shelf-patch-a
938 new file mode 100644
941 new file mode 100644
939 --- /dev/null
942 --- /dev/null
940 +++ b/shelf-patch-a
943 +++ b/shelf-patch-a
941 @@ -0,0 +1,1 @@
944 @@ -0,0 +1,1 @@
942 +patch a
945 +patch a
943 $ hg shelve --stat default
946 $ hg shelve --stat default
944 default (* ago) changes to 'create conflict' (glob)
947 default (* ago) changes to 'create conflict' (glob)
945 shelf-patch-a | 1 +
948 shelf-patch-a | 1 +
946 1 files changed, 1 insertions(+), 0 deletions(-)
949 1 files changed, 1 insertions(+), 0 deletions(-)
947 $ hg shelve --patch nonexistentshelf
950 $ hg shelve --patch nonexistentshelf
948 abort: cannot find shelf nonexistentshelf
951 abort: cannot find shelf nonexistentshelf
949 [255]
952 [255]
950 $ hg shelve --stat nonexistentshelf
953 $ hg shelve --stat nonexistentshelf
951 abort: cannot find shelf nonexistentshelf
954 abort: cannot find shelf nonexistentshelf
952 [255]
955 [255]
953
956
General Comments 0
You need to be logged in to leave comments. Login now