--- a/hgext/shelve.py Tue Apr 15 03:21:59 2014 +0900
+++ b/hgext/shelve.py Thu Apr 17 19:36:17 2014 -0400
@@ -22,10 +22,10 @@
"""
from mercurial.i18n import _
-from mercurial.node import nullid, bin, hex
-from mercurial import changegroup, cmdutil, scmutil, phases
+from mercurial.node import nullid, nullrev, bin, hex
+from mercurial import changegroup, cmdutil, scmutil, phases, commands
from mercurial import error, hg, mdiff, merge, patch, repair, util
-from mercurial import templatefilters
+from mercurial import templatefilters, changegroup, exchange
from mercurial import lock as lockmod
from hgext import rebase
import errno
@@ -68,6 +68,18 @@
raise
raise util.Abort(_("shelved change '%s' not found") % self.name)
+ def applybundle(self):
+ fp = self.opener()
+ try:
+ gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
+ changegroup.addchangegroup(self.repo, gen, 'unshelve',
+ 'bundle:' + self.vfs.join(self.fname))
+ finally:
+ fp.close()
+
+ def writebundle(self, cg):
+ changegroup.writebundle(cg, self.fname, 'HG10UN', self.vfs)
+
class shelvedstate(object):
"""Handle persistence during unshelving operations.
@@ -122,22 +134,21 @@
"""subcommand that creates a new shelve"""
def publicancestors(ctx):
- """Compute the heads of the public ancestors of a commit.
+ """Compute the public ancestors of a commit.
- Much faster than the revset heads(ancestors(ctx) - draft())"""
- seen = set()
+ Much faster than the revset ancestors(ctx) & draft()"""
+ seen = set([nullrev])
visit = util.deque()
visit.append(ctx)
while visit:
ctx = visit.popleft()
+ yield ctx.node()
for parent in ctx.parents():
rev = parent.rev()
if rev not in seen:
seen.add(rev)
if parent.mutable():
visit.append(parent)
- else:
- yield parent.node()
wctx = repo[None]
parents = wctx.parents()
@@ -173,9 +184,9 @@
repo.mq.checkapplied = saved
if parent.node() != nullid:
- desc = parent.description().split('\n', 1)[0]
+ desc = "changes to '%s'" % parent.description().split('\n', 1)[0]
else:
- desc = '(empty repository)'
+ desc = '(changes in empty repository)'
if not opts['message']:
opts['message'] = desc
@@ -228,9 +239,8 @@
fp.write('\0'.join(shelvedfiles))
bases = list(publicancestors(repo[node]))
- cg = repo.changegroupsubset(bases, [node], 'shelve')
- changegroup.writebundle(cg, shelvedfile(repo, name, 'hg').filename(),
- 'HG10UN')
+ cg = changegroup.changegroupsubset(repo, bases, [node], 'shelve')
+ shelvedfile(repo, name, 'hg').writebundle(cg)
cmdutil.export(repo, [node],
fp=shelvedfile(repo, name, 'patch').opener('wb'),
opts=mdiff.diffopts(git=True))
@@ -459,7 +469,9 @@
('c', 'continue', None,
_('continue an incomplete unshelve operation')),
('', 'keep', None,
- _('keep shelve after unshelving'))],
+ _('keep shelve after unshelving')),
+ ('', 'date', '',
+ _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
_('hg unshelve [SHELVED]'))
def unshelve(ui, repo, *shelved, **opts):
"""restore a shelved change to the working directory
@@ -518,6 +530,7 @@
if not shelvedfile(repo, basename, 'files').exists():
raise util.Abort(_("shelved change '%s' not found") % basename)
+ oldquiet = ui.quiet
wlock = lock = tr = None
try:
lock = repo.lock()
@@ -526,17 +539,19 @@
tr = repo.transaction('unshelve', report=lambda x: None)
oldtiprev = len(repo)
- wctx = repo['.']
- tmpwctx = wctx
+ pctx = repo['.']
+ tmpwctx = pctx
# The goal is to have a commit structure like so:
- # ...-> wctx -> tmpwctx -> shelvectx
+ # ...-> pctx -> tmpwctx -> shelvectx
# where tmpwctx is an optional commit with the user's pending changes
# and shelvectx is the unshelved changes. Then we merge it all down
- # to the original wctx.
+ # to the original pctx.
# Store pending changes in a commit
m, a, r, d = repo.status()[:4]
if m or a or r or d:
+ ui.status(_("temporarily committing pending changes "
+ "(restore with 'hg unshelve --abort')\n"))
def commitfunc(ui, repo, message, match, opts):
hasmq = util.safehasattr(repo, 'mq')
if hasmq:
@@ -551,28 +566,24 @@
tempopts = {}
tempopts['message'] = "pending changes temporary commit"
- oldquiet = ui.quiet
- try:
- ui.quiet = True
- node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
- finally:
- ui.quiet = oldquiet
+ tempopts['date'] = opts.get('date')
+ ui.quiet = True
+ node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
tmpwctx = repo[node]
- try:
- fp = shelvedfile(repo, basename, 'hg').opener()
- gen = changegroup.readbundle(fp, fp.name)
- repo.addchangegroup(gen, 'unshelve', 'bundle:' + fp.name)
- nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)]
- phases.retractboundary(repo, phases.secret, nodes)
- finally:
- fp.close()
+ ui.quiet = True
+ shelvedfile(repo, basename, 'hg').applybundle()
+ nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)]
+ phases.retractboundary(repo, phases.secret, nodes)
+
+ ui.quiet = oldquiet
shelvectx = repo['tip']
# If the shelve is not immediately on top of the commit
# we'll be merging with, rebase it to be on top.
if tmpwctx.node() != shelvectx.parents()[0].node():
+ ui.status(_('rebasing shelved changes\n'))
try:
rebase.rebase(ui, repo, **{
'rev' : [shelvectx.rev()],
@@ -584,7 +595,7 @@
stripnodes = [repo.changelog.node(rev)
for rev in xrange(oldtiprev, len(repo))]
- shelvedstate.save(repo, basename, wctx, tmpwctx, stripnodes)
+ shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
util.rename(repo.join('rebasestate'),
repo.join('unshelverebasestate'))
@@ -599,7 +610,7 @@
# rebase was a no-op, so it produced no child commit
shelvectx = tmpwctx
- mergefiles(ui, repo, wctx, shelvectx)
+ mergefiles(ui, repo, pctx, shelvectx)
shelvedstate.clear(repo)
# The transaction aborting will strip all the commits for us,
@@ -610,6 +621,7 @@
unshelvecleanup(ui, repo, basename, opts)
finally:
+ ui.quiet = oldquiet
if tr:
tr.release()
lockmod.release(lock, wlock)
@@ -632,8 +644,8 @@
('p', 'patch', None,
_('show patch')),
('', 'stat', None,
- _('output diffstat-style summary of changes'))],
- _('hg shelve'))
+ _('output diffstat-style summary of changes'))] + commands.walkopts,
+ _('hg shelve [OPTION]... [FILE]...'))
def shelvecmd(ui, repo, *pats, **opts):
'''save and set aside changes from the working directory