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