##// END OF EJS Templates
graft: let caller pass in overlayworkingctx to merge.graft()...
graft: let caller pass in overlayworkingctx to merge.graft() Passing in a different `wctx` than `repo[None]` is useful because it allows the caller to decide to not touch the working directory. Differential Revision: https://phab.mercurial-scm.org/D8026

File last commit:

r44433:414cb20e default
r44671:916e3ed0 default
Show More
shelve.py
1183 lines | 38.9 KiB | text/x-python | PythonLexer
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # shelve.py - save/restore working directory state
#
# Copyright 2013 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""save and restore changes to the working directory
The "hg shelve" command saves changes made to the working directory
and reverts those changes, resetting the working directory to a clean
state.
Later on, the "hg unshelve" command restores the changes saved by "hg
shelve". Changes can be restored even after updating to a different
parent, in which case Mercurial's merge machinery will resolve any
conflicts if necessary.
You can have more than one shelved change outstanding at a time; each
shelved change has a distinct name. For details, see the help for "hg
shelve".
"""
from __future__ import absolute_import
import collections
import errno
import itertools
import stat
from .i18n import _
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from .pycompat import open
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 from . import (
bookmarks,
bundle2,
bundlerepo,
changegroup,
cmdutil,
discovery,
error,
exchange,
hg,
lock as lockmod,
mdiff,
merge,
node as nodemod,
patch,
phases,
pycompat,
repair,
scmutil,
templatefilters,
util,
vfs as vfsmod,
)
from .utils import (
dateutil,
stringutil,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 backupdir = b'shelve-backup'
shelvedir = b'shelved'
shelvefileextensions = [b'hg', b'patch', b'shelve']
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # universal extension is present in all types of shelves
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 patchextension = b'patch'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
# we never need the user, so we use a
# generic user for all shelve operations
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shelveuser = b'shelve@localhost'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 class shelvedfile(object):
"""Helper for the file storing a single shelve
Handles common functions on shelve files (.hg/.patch) using
the vfs layer"""
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def __init__(self, repo, name, filetype=None):
self.repo = repo
self.name = name
self.vfs = vfsmod.vfs(repo.vfs.join(shelvedir))
self.backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
self.ui = self.repo.ui
if filetype:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.fname = name + b'.' + filetype
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 else:
self.fname = name
def exists(self):
return self.vfs.exists(self.fname)
def filename(self):
return self.vfs.join(self.fname)
def backupfilename(self):
def gennames(base):
yield base
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 base, ext = base.rsplit(b'.', 1)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for i in itertools.count(1):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'%s-%d.%s' % (base, i, ext)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
name = self.backupvfs.join(self.fname)
for n in gennames(name):
if not self.backupvfs.exists(n):
return n
def movetobackup(self):
if not self.backupvfs.isdir():
self.backupvfs.makedir()
util.rename(self.filename(), self.backupfilename())
def stat(self):
return self.vfs.stat(self.fname)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def opener(self, mode=b'rb'):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 try:
return self.vfs(self.fname, mode)
except IOError as err:
if err.errno != errno.ENOENT:
raise
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"shelved change '%s' not found") % self.name)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
def applybundle(self, tr):
fp = self.opener()
try:
targetphase = phases.internal
if not phases.supportinternal(self.repo):
targetphase = phases.secret
gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pretip = self.repo[b'tip']
Augie Fackler
formatting: blacken the codebase...
r43346 bundle2.applybundle(
self.repo,
gen,
tr,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 source=b'unshelve',
url=b'bundle:' + self.vfs.join(self.fname),
Augie Fackler
formatting: blacken the codebase...
r43346 targetphase=targetphase,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shelvectx = self.repo[b'tip']
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if pretip == shelvectx:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shelverev = tr.changes[b'revduplicates'][-1]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 shelvectx = self.repo[shelverev]
return shelvectx
finally:
fp.close()
def bundlerepo(self):
path = self.vfs.join(self.fname)
Augie Fackler
formatting: blacken the codebase...
r43346 return bundlerepo.instance(
Matt Harbison
shelve: add the missing `create` parameter to the bundlerepo constructor...
r44124 self.repo.baseui, b'bundle://%s+%s' % (self.repo.root, path), False
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
def writebundle(self, bases, node):
cgversion = changegroup.safeversion(self.repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cgversion == b'01':
btype = b'HG10BZ'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 compression = None
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 btype = b'HG20'
compression = b'BZ'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
repo = self.repo.unfiltered()
Augie Fackler
formatting: blacken the codebase...
r43346 outgoing = discovery.outgoing(
repo, missingroots=bases, missingheads=[node]
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cg = changegroup.makechangegroup(repo, outgoing, cgversion, b'shelve')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346 bundle2.writebundle(
self.ui, cg, self.fname, btype, self.vfs, compression=compression
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
def writeinfo(self, info):
scmutil.simplekeyvaluefile(self.vfs, self.fname).write(info)
def readinfo(self):
return scmutil.simplekeyvaluefile(self.vfs, self.fname).read()
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 class shelvedstate(object):
"""Handle persistence during unshelving operations.
Handles saving and restoring a shelved state. Ensures that different
versions of a shelved state are possible and handles them appropriately.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 _version = 2
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _filename = b'shelvedstate'
_keep = b'keep'
_nokeep = b'nokeep'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # colon is essential to differentiate from a real bookmark name
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _noactivebook = b':no-active-bookmark'
_interactive = b'interactive'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
@classmethod
def _verifyandtransform(cls, d):
"""Some basic shelvestate syntactic verification and transformation"""
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 d[b'originalwctx'] = nodemod.bin(d[b'originalwctx'])
d[b'pendingctx'] = nodemod.bin(d[b'pendingctx'])
d[b'parents'] = [nodemod.bin(h) for h in d[b'parents'].split(b' ')]
d[b'nodestoremove'] = [
nodemod.bin(h) for h in d[b'nodestoremove'].split(b' ')
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 except (ValueError, TypeError, KeyError) as err:
raise error.CorruptedState(pycompat.bytestr(err))
@classmethod
def _getversion(cls, repo):
"""Read version information from shelvestate file"""
fp = repo.vfs(cls._filename)
try:
version = int(fp.readline().strip())
except ValueError as err:
raise error.CorruptedState(pycompat.bytestr(err))
finally:
fp.close()
return version
@classmethod
def _readold(cls, repo):
"""Read the old position-based version of a shelvestate file"""
# Order is important, because old shelvestate file uses it
# to detemine values of fields (i.g. name is on the second line,
# originalwctx is on the third and so forth). Please do not change.
Augie Fackler
formatting: blacken the codebase...
r43346 keys = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'version',
b'name',
b'originalwctx',
b'pendingctx',
b'parents',
b'nodestoremove',
b'branchtorestore',
b'keep',
b'activebook',
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # this is executed only seldomly, so it is not a big deal
# that we open this file twice
fp = repo.vfs(cls._filename)
d = {}
try:
for key in keys:
d[key] = fp.readline().strip()
finally:
fp.close()
return d
@classmethod
def load(cls, repo):
version = cls._getversion(repo)
if version < cls._version:
d = cls._readold(repo)
elif version == cls._version:
Augie Fackler
formatting: blacken the codebase...
r43346 d = scmutil.simplekeyvaluefile(repo.vfs, cls._filename).read(
firstlinenonkeyval=True
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'this version of shelve is incompatible '
b'with the version used in this repo'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
cls._verifyandtransform(d)
try:
obj = cls()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 obj.name = d[b'name']
obj.wctx = repo[d[b'originalwctx']]
obj.pendingctx = repo[d[b'pendingctx']]
obj.parents = d[b'parents']
obj.nodestoremove = d[b'nodestoremove']
obj.branchtorestore = d.get(b'branchtorestore', b'')
obj.keep = d.get(b'keep') == cls._keep
obj.activebookmark = b''
if d.get(b'activebook', b'') != cls._noactivebook:
obj.activebookmark = d.get(b'activebook', b'')
obj.interactive = d.get(b'interactive') == cls._interactive
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 except (error.RepoLookupError, KeyError) as err:
raise error.CorruptedState(pycompat.bytestr(err))
return obj
@classmethod
Augie Fackler
formatting: blacken the codebase...
r43346 def save(
cls,
repo,
name,
originalwctx,
pendingctx,
nodestoremove,
branchtorestore,
keep=False,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 activebook=b'',
Augie Fackler
formatting: blacken the codebase...
r43346 interactive=False,
):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 info = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"name": name,
b"originalwctx": nodemod.hex(originalwctx.node()),
b"pendingctx": nodemod.hex(pendingctx.node()),
b"parents": b' '.join(
Augie Fackler
formatting: blacken the codebase...
r43346 [nodemod.hex(p) for p in repo.dirstate.parents()]
),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"nodestoremove": b' '.join(
[nodemod.hex(n) for n in nodestoremove]
),
b"branchtorestore": branchtorestore,
b"keep": cls._keep if keep else cls._nokeep,
b"activebook": activebook or cls._noactivebook,
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 }
Navaneeth Suresh
unshelve: store information about interactive mode in shelvedstate...
r42889 if interactive:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info[b'interactive'] = cls._interactive
Augie Fackler
formatting: blacken the codebase...
r43346 scmutil.simplekeyvaluefile(repo.vfs, cls._filename).write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info, firstline=(b"%d" % cls._version)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
@classmethod
def clear(cls, repo):
repo.vfs.unlinkpath(cls._filename, ignoremissing=True)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def cleanupoldbackups(repo):
vfs = vfsmod.vfs(repo.vfs.join(backupdir))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 maxbackups = repo.ui.configint(b'shelve', b'maxbackups')
hgfiles = [f for f in vfs.listdir() if f.endswith(b'.' + patchextension)]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 hgfiles = sorted([(vfs.stat(f)[stat.ST_MTIME], f) for f in hgfiles])
if maxbackups > 0 and maxbackups < len(hgfiles):
bordermtime = hgfiles[-maxbackups][0]
else:
bordermtime = None
Augie Fackler
formatting: blacken the codebase...
r43346 for mtime, f in hgfiles[: len(hgfiles) - maxbackups]:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if mtime == bordermtime:
# keep it, because timestamp can't decide exact order of backups
continue
Augie Fackler
formatting: blacken the codebase...
r43346 base = f[: -(1 + len(patchextension))]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for ext in shelvefileextensions:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 vfs.tryunlink(base + b'.' + ext)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _backupactivebookmark(repo):
activebookmark = repo._activebookmark
if activebookmark:
bookmarks.deactivate(repo)
return activebookmark
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _restoreactivebookmark(repo, mark):
if mark:
bookmarks.activate(repo, mark)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _aborttransaction(repo, tr):
'''Abort current transaction for shelve/unshelve, but keep dirstate
'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dirstatebackupname = b'dirstate.shelve'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 repo.dirstate.savebackup(tr, dirstatebackupname)
tr.abort()
repo.dirstate.restorebackup(None, dirstatebackupname)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def getshelvename(repo, parent, opts):
"""Decide on the name this shelve is going to have"""
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def gennames():
yield label
for i in itertools.count(1):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'%s-%02d' % (label, i)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 name = opts.get(b'name')
label = repo._activebookmark or parent.branch() or b'default'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # slashes aren't allowed in filenames, therefore we rename it
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 label = label.replace(b'/', b'_')
label = label.replace(b'\\', b'_')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # filenames must not start with '.' as it should not be hidden
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if label.startswith(b'.'):
label = label.replace(b'.', b'_', 1)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
if name:
if shelvedfile(repo, name, patchextension).exists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 e = _(b"a shelved change named '%s' already exists") % name
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 raise error.Abort(e)
# ensure we are not creating a subdirectory or a hidden file
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'/' in name or b'\\' in name:
raise error.Abort(
_(b'shelved change names can not contain slashes')
)
if name.startswith(b'.'):
raise error.Abort(_(b"shelved change names can not start with '.'"))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
else:
for n in gennames():
if not shelvedfile(repo, n, patchextension).exists():
name = n
break
return name
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def mutableancestors(ctx):
"""return all mutable ancestors for ctx (included)
Much faster than the revset ancestors(ctx) & draft()"""
seen = {nodemod.nullrev}
visit = collections.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)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def getcommitfunc(extra, interactive, editor=False):
def commitfunc(ui, repo, message, match, opts):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hasmq = util.safehasattr(repo, b'mq')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if hasmq:
saved, repo.mq.checkapplied = repo.mq.checkapplied, False
targetphase = phases.internal
if not phases.supportinternal(repo):
targetphase = phases.secret
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'phases', b'new-commit'): targetphase}
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 try:
editor_ = False
if editor:
Augie Fackler
formatting: blacken the codebase...
r43346 editor_ = cmdutil.getcommiteditor(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 editform=b'shelve.shelve', **pycompat.strkwargs(opts)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 with repo.ui.configoverride(overrides):
Augie Fackler
formatting: blacken the codebase...
r43346 return repo.commit(
message,
shelveuser,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 opts.get(b'date'),
Augie Fackler
formatting: blacken the codebase...
r43346 match,
editor=editor_,
extra=extra,
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 finally:
if hasmq:
repo.mq.checkapplied = saved
def interactivecommitfunc(ui, repo, *pats, **opts):
opts = pycompat.byteskwargs(opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 match = scmutil.match(repo[b'.'], pats, {})
message = opts[b'message']
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 return commitfunc(ui, repo, message, match, opts)
return interactivecommitfunc if interactive else commitfunc
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _nothingtoshelvemessaging(ui, repo, pats, opts):
stat = repo.status(match=scmutil.match(repo[None], pats, opts))
if stat.deleted:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"nothing changed (%d missing files, see 'hg status')\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % len(stat.deleted)
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b"nothing changed\n"))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _shelvecreatedcommit(repo, node, name, match):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info = {b'node': nodemod.hex(node)}
shelvedfile(repo, name, b'shelve').writeinfo(info)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 bases = list(mutableancestors(repo[node]))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shelvedfile(repo, name, b'hg').writebundle(bases, node)
with shelvedfile(repo, name, patchextension).opener(b'wb') as fp:
Augie Fackler
formatting: blacken the codebase...
r43346 cmdutil.exportfile(
repo, [node], fp, opts=mdiff.diffopts(git=True), match=match
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
def _includeunknownfiles(repo, pats, opts, extra):
Augie Fackler
formatting: blacken the codebase...
r43346 s = repo.status(match=scmutil.match(repo[None], pats, opts), unknown=True)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if s.unknown:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra[b'shelve_unknown'] = b'\0'.join(s.unknown)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 repo[None].add(s.unknown)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _finishshelve(repo, tr):
if phases.supportinternal(repo):
tr.close()
else:
_aborttransaction(repo, tr)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def createcmd(ui, repo, pats, opts):
"""subcommand that creates a new shelve"""
with repo.wlock():
cmdutil.checkunfinished(repo)
return _docreatecmd(ui, repo, pats, opts)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _docreatecmd(ui, repo, pats, opts):
wctx = repo[None]
parents = wctx.parents()
parent = parents[0]
origbranch = wctx.branch()
if parent.node() != nodemod.nullid:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc = b"changes to: %s" % parent.description().split(b'\n', 1)[0]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc = b'(changes in empty repository)'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not opts.get(b'message'):
opts[b'message'] = desc
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
lock = tr = activebookmark = None
try:
lock = repo.lock()
# use an uncommitted transaction to generate the bundle to avoid
# pull races. ensure we don't print the abort message to stderr.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr = repo.transaction(b'shelve', report=lambda x: None)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 interactive = opts.get(b'interactive', False)
includeunknown = opts.get(b'unknown', False) and not opts.get(
b'addremove', False
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
name = getshelvename(repo, parent, opts)
activebookmark = _backupactivebookmark(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra = {b'internal': b'shelve'}
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if includeunknown:
_includeunknownfiles(repo, pats, opts, extra)
if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts):
# In non-bare shelve we don't store newly created branch
# at bundled commit
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.dirstate.setbranch(repo[b'.'].branch())
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
commitfunc = getcommitfunc(extra, interactive, editor=True)
if not interactive:
node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
else:
Augie Fackler
formatting: blacken the codebase...
r43346 node = cmdutil.dorecord(
ui,
repo,
commitfunc,
None,
False,
cmdutil.recordfilter,
*pats,
**pycompat.strkwargs(opts)
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if not node:
_nothingtoshelvemessaging(ui, repo, pats, opts)
return 1
# Create a matcher so that prefetch doesn't attempt to fetch
# the entire repository pointlessly, and as an optimisation
# for movedirstate, if needed.
match = scmutil.matchfiles(repo, repo[node].files())
_shelvecreatedcommit(repo, node, name, match)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'shelved as %s\n') % name)
if opts[b'keep']:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 with repo.dirstate.parentchange():
scmutil.movedirstate(repo, parent, match)
else:
hg.update(repo, parent.node())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if origbranch != repo[b'.'].branch() and not _isbareshelve(pats, opts):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 repo.dirstate.setbranch(origbranch)
_finishshelve(repo, tr)
finally:
_restoreactivebookmark(repo, activebookmark)
lockmod.release(tr, lock)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _isbareshelve(pats, opts):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
not pats
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 and not opts.get(b'interactive', False)
and not opts.get(b'include', False)
and not opts.get(b'exclude', False)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
def _iswctxonnewbranch(repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return repo[None].branch() != repo[b'.'].branch()
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def cleanupcmd(ui, repo):
"""subcommand that deletes all shelves"""
with repo.wlock():
for (name, _type) in repo.vfs.readdir(shelvedir):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 suffix = name.rsplit(b'.', 1)[-1]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if suffix in shelvefileextensions:
shelvedfile(repo, name).movetobackup()
cleanupoldbackups(repo)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def deletecmd(ui, repo, pats):
"""subcommand that deletes a specific shelve"""
if not pats:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'no shelved changes specified!'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 with repo.wlock():
Matt Harbison
shelve: fix a missing variable in the exception handler for delete...
r44123 for name in pats:
try:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for suffix in shelvefileextensions:
shfile = shelvedfile(repo, name, suffix)
# patch file is necessary, as it should
# be present for any kind of shelve,
# but the .hg file is optional as in future we
# will add obsolete shelve with does not create a
# bundle
if shfile.exists() or suffix == patchextension:
shfile.movetobackup()
Matt Harbison
shelve: fix a missing variable in the exception handler for delete...
r44123 except OSError as err:
if err.errno != errno.ENOENT:
raise
raise error.Abort(_(b"shelved change '%s' not found") % name)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 cleanupoldbackups(repo)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def listshelves(repo):
"""return all shelves in repo as list of (time, filename)"""
try:
names = repo.vfs.readdir(shelvedir)
except OSError as err:
if err.errno != errno.ENOENT:
raise
return []
info = []
for (name, _type) in names:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pfx, sfx = name.rsplit(b'.', 1)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if not pfx or sfx != patchextension:
continue
st = shelvedfile(repo, name).stat()
info.append((st[stat.ST_MTIME], shelvedfile(repo, pfx).filename()))
return sorted(info, reverse=True)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def listcmd(ui, repo, pats, opts):
"""subcommand that displays the list of shelves"""
pats = set(pats)
width = 80
if not ui.plain():
width = ui.termwidth()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 namelabel = b'shelve.newest'
ui.pager(b'shelve')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for mtime, name in listshelves(repo):
sname = util.split(name)[1]
if pats and sname not in pats:
continue
ui.write(sname, label=namelabel)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 namelabel = b'shelve.name'
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if ui.quiet:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b'\n')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b' ' * (16 - len(sname)))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 used = 16
date = dateutil.makedate(mtime)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 age = b'(%s)' % templatefilters.age(date, abbrev=True)
ui.write(age, label=b'shelve.age')
ui.write(b' ' * (12 - len(age)))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 used += 12
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(name + b'.' + patchextension, b'rb') as fp:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 while True:
line = fp.readline()
if not line:
break
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not line.startswith(b'#'):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 desc = line.rstrip()
if ui.formatted():
desc = stringutil.ellipsis(desc, width - used)
ui.write(desc)
break
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b'\n')
if not (opts[b'patch'] or opts[b'stat']):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 continue
difflines = fp.readlines()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b'patch']:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for chunk, label in patch.difflabel(iter, difflines):
ui.write(chunk, label=label)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b'stat']:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for chunk, label in patch.diffstatui(difflines, width=width):
ui.write(chunk, label=label)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def patchcmds(ui, repo, pats, opts):
"""subcommand that displays shelves"""
if len(pats) == 0:
shelves = listshelves(repo)
if not shelves:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"there are no shelves to show"))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 mtime, name = shelves[0]
sname = util.split(name)[1]
pats = [sname]
for shelfname in pats:
if not shelvedfile(repo, shelfname, patchextension).exists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"cannot find shelf %s") % shelfname)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
listcmd(ui, repo, pats, opts)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def checkparents(repo, state):
"""check parent while resuming an unshelve"""
if state.parents != repo.dirstate.parents():
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'working directory parents do not match unshelve state')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Taapas Agrawal
abort: added support for unshelve...
r42802 def _loadshelvedstate(ui, repo, opts):
try:
state = shelvedstate.load(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'keep') is None:
opts[b'keep'] = state.keep
Taapas Agrawal
abort: added support for unshelve...
r42802 except IOError as err:
if err.errno != errno.ENOENT:
raise
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmdutil.wrongtooltocontinue(repo, _(b'unshelve'))
Taapas Agrawal
abort: added support for unshelve...
r42802 except error.CorruptedState as err:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(pycompat.bytestr(err) + b'\n')
if opts.get(b'continue'):
msg = _(b'corrupted shelved state file')
Augie Fackler
formatting: blacken the codebase...
r43346 hint = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'please run hg unshelve --abort to abort unshelve '
b'operation'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Taapas Agrawal
abort: added support for unshelve...
r42802 raise error.Abort(msg, hint=hint)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif opts.get(b'abort'):
Taapas Agrawal
abort: added support for unshelve...
r42802 shelvedstate.clear(repo)
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'could not read shelved state file, your '
b'working copy may be in an unexpected state\n'
b'please update to some commit\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Taapas Agrawal
abort: added support for unshelve...
r42802 return state
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
abort: added support for unshelve...
r42802 def unshelveabort(ui, repo, state):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 """subcommand that abort an in-progress unshelve"""
with repo.lock():
try:
checkparents(repo, state)
merge.update(repo, state.pendingctx, branchmerge=False, force=True)
Augie Fackler
formatting: blacken the codebase...
r43346 if state.activebookmark and state.activebookmark in repo._bookmarks:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 bookmarks.activate(repo, state.activebookmark)
mergefiles(ui, repo, state.wctx, state.pendingctx)
if not phases.supportinternal(repo):
Augie Fackler
formatting: blacken the codebase...
r43346 repair.strip(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui, repo, state.nodestoremove, backup=False, topic=b'shelve'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 finally:
shelvedstate.clear(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.warn(_(b"unshelve of '%s' aborted\n") % state.name)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
abort: added support for unshelve...
r42802 def hgabortunshelve(ui, repo):
"""logic to abort unshelve using 'hg abort"""
with repo.wlock():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state = _loadshelvedstate(ui, repo, {b'abort': True})
Taapas Agrawal
abort: added support for unshelve...
r42802 return unshelveabort(ui, repo, state)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def mergefiles(ui, repo, wctx, shelvectx):
"""updates to wctx and merges the changes from shelvectx into the
dirstate."""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with ui.configoverride({(b'ui', b'quiet'): True}):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 hg.update(repo, wctx.node())
ui.pushbuffer(True)
cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents())
ui.popbuffer()
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def restorebranch(ui, repo, branchtorestore):
if branchtorestore and branchtorestore != repo.dirstate.branch():
repo.dirstate.setbranch(branchtorestore)
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'marked working directory as branch %s\n') % branchtorestore
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
def unshelvecleanup(ui, repo, name, opts):
"""remove related files after an unshelve"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not opts.get(b'keep'):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for filetype in shelvefileextensions:
shfile = shelvedfile(repo, name, filetype)
if shfile.exists():
shfile.movetobackup()
cleanupoldbackups(repo)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
unshelve: store information about interactive mode in shelvedstate...
r42889 def unshelvecontinue(ui, repo, state, opts):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 """subcommand to continue an in-progress unshelve"""
# We're finishing off a merge. First parent is our original
# parent, second is the temporary "fake" commit we're unshelving.
Navaneeth Suresh
unshelve: store information about interactive mode in shelvedstate...
r42889 interactive = state.interactive
basename = state.name
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 with repo.lock():
checkparents(repo, state)
ms = merge.mergestate.read(repo)
if list(ms.unresolved()):
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"unresolved conflicts, can't continue"),
hint=_(b"see 'hg resolve', then 'hg unshelve --continue'"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
shelvectx = repo[state.parents[1]]
pendingctx = state.pendingctx
with repo.dirstate.parentchange():
repo.setparents(state.pendingctx.node(), nodemod.nullid)
repo.dirstate.write(repo.currenttransaction())
targetphase = phases.internal
if not phases.supportinternal(repo):
targetphase = phases.secret
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'phases', b'new-commit'): targetphase}
with repo.ui.configoverride(overrides, b'unshelve'):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 with repo.dirstate.parentchange():
repo.setparents(state.parents[0], nodemod.nullid)
Augie Fackler
formatting: blacken the codebase...
r43346 newnode, ispartialunshelve = _createunshelvectx(
ui, repo, shelvectx, basename, interactive, opts
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
if newnode is None:
# If it ended up being a no-op commit, then the normal
# merge state clean-up path doesn't happen, so do it
# here. Fix issue5494
merge.mergestate.clean(repo)
shelvectx = state.pendingctx
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'note: unshelved changes already existed '
b'in the working copy\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 ui.status(msg)
else:
# only strip the shelvectx if we produced one
state.nodestoremove.append(newnode)
shelvectx = repo[newnode]
hg.updaterepo(repo, pendingctx.node(), overwrite=False)
mergefiles(ui, repo, state.wctx, shelvectx)
restorebranch(ui, repo, state.branchtorestore)
Navaneeth Suresh
unshelve: handle stripping changesets on interactive mode...
r42930 if not phases.supportinternal(repo):
Augie Fackler
formatting: blacken the codebase...
r43346 repair.strip(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui, repo, state.nodestoremove, backup=False, topic=b'shelve'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
unshelve: delete shelvedstate after a successful unshelve --continue...
r42931 shelvedstate.clear(repo)
Navaneeth Suresh
unshelve: add interactive mode...
r42835 if not ispartialunshelve:
unshelvecleanup(ui, repo, state.name, opts)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 _restoreactivebookmark(repo, state.activebookmark)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b"unshelve of '%s' complete\n") % state.name)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
continue: added support for unshelve...
r42833 def hgcontinueunshelve(ui, repo):
"""logic to resume unshelve using 'hg continue'"""
with repo.wlock():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state = _loadshelvedstate(ui, repo, {b'continue': True})
return unshelvecontinue(ui, repo, state, {b'keep': state.keep})
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
continue: added support for unshelve...
r42833
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _commitworkingcopychanges(ui, repo, opts, tmpwctx):
"""Temporarily commit working copy changes before moving unshelve commit"""
# Store pending changes in a commit and remember added in case a shelve
# contains unknown files that are part of the pending change
s = repo.status()
addedbefore = frozenset(s.added)
if not (s.modified or s.added or s.removed):
return tmpwctx, addedbefore
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"temporarily committing pending changes "
b"(restore with 'hg unshelve --abort')\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra = {b'internal': b'shelve'}
Augie Fackler
formatting: blacken the codebase...
r43346 commitfunc = getcommitfunc(extra=extra, interactive=False, editor=False)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 tempopts = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tempopts[b'message'] = b"pending changes temporary commit"
tempopts[b'date'] = opts.get(b'date')
with ui.configoverride({(b'ui', b'quiet'): True}):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
tmpwctx = repo[node]
return tmpwctx, addedbefore
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _unshelverestorecommit(ui, repo, tr, basename):
"""Recreate commit in the repository during the unshelve"""
repo = repo.unfiltered()
node = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if shelvedfile(repo, basename, b'shelve').exists():
node = shelvedfile(repo, basename, b'shelve').readinfo()[b'node']
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if node is None or node not in repo:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with ui.configoverride({(b'ui', b'quiet'): True}):
shelvectx = shelvedfile(repo, basename, b'hg').applybundle(tr)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 # We might not strip the unbundled changeset, so we should keep track of
# the unshelve node in case we need to reuse it (eg: unshelve --keep)
if node is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 info = {b'node': nodemod.hex(shelvectx.node())}
shelvedfile(repo, basename, b'shelve').writeinfo(info)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 else:
shelvectx = repo[node]
return repo, shelvectx
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
unshelve: unify logic around creating an unshelve changeset...
r42886 def _createunshelvectx(ui, repo, shelvectx, basename, interactive, opts):
"""Handles the creation of unshelve commit and updates the shelve if it
was partially unshelved.
If interactive is:
* False: Commits all the changes in the working directory.
* True: Prompts the user to select changes to unshelve and commit them.
Update the shelve with remaining changes.
Returns the node of the new commit formed and a bool indicating whether
the shelve was partially unshelved.Creates a commit ctx to unshelve
interactively or non-interactively.
The user might want to unshelve certain changes only from the stored
shelve in interactive. So, we would create two commits. One with requested
changes to unshelve at that time and the latter is shelved for future.
Here, we return both the newnode which is created interactively and a
bool to know whether the shelve is partly done or completely done.
Navaneeth Suresh
unshelve: add interactive mode...
r42835 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 opts[b'message'] = shelvectx.description()
opts[b'interactive-unshelve'] = True
Navaneeth Suresh
unshelve: add interactive mode...
r42835 pats = []
Navaneeth Suresh
unshelve: unify logic around creating an unshelve changeset...
r42886 if not interactive:
Augie Fackler
formatting: blacken the codebase...
r43346 newnode = repo.commit(
text=shelvectx.description(),
extra=shelvectx.extra(),
user=shelvectx.user(),
date=shelvectx.date(),
)
Navaneeth Suresh
unshelve: unify logic around creating an unshelve changeset...
r42886 return newnode, False
Augie Fackler
formatting: blacken the codebase...
r43346 commitfunc = getcommitfunc(shelvectx.extra(), interactive=True, editor=True)
newnode = cmdutil.dorecord(
ui,
repo,
commitfunc,
None,
False,
cmdutil.recordfilter,
*pats,
**pycompat.strkwargs(opts)
)
snode = repo.commit(
text=shelvectx.description(),
extra=shelvectx.extra(),
user=shelvectx.user(),
)
Navaneeth Suresh
unshelve: add interactive mode...
r42835 if snode:
Navaneeth Suresh
unshelve: create a matcher only if required on creating unshelve ctx...
r42888 m = scmutil.matchfiles(repo, repo[snode].files())
Navaneeth Suresh
unshelve: add interactive mode...
r42835 _shelvecreatedcommit(repo, snode, basename, m)
return newnode, bool(snode)
Augie Fackler
formatting: blacken the codebase...
r43346
def _rebaserestoredcommit(
ui,
repo,
opts,
tr,
oldtiprev,
basename,
pctx,
tmpwctx,
shelvectx,
branchtorestore,
activebookmark,
):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 """Rebase restored commit from its original location to a destination"""
# If the shelve is not immediately on top of the commit
# we'll be merging with, rebase it to be on top.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 interactive = opts.get(b'interactive')
Navaneeth Suresh
unshelve: add interactive mode...
r42835 if tmpwctx.node() == shelvectx.p1().node() and not interactive:
# We won't skip on interactive mode because, the user might want to
# unshelve certain changes only.
return shelvectx, False
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
overrides = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'ui', b'forcemerge'): opts.get(b'tool', b''),
(b'phases', b'new-commit'): phases.secret,
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 }
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with repo.ui.configoverride(overrides, b'unshelve'):
ui.status(_(b'rebasing shelved changes\n'))
Augie Fackler
formatting: blacken the codebase...
r43346 stats = merge.graft(
repo,
shelvectx,
shelvectx.p1(),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels=[b'shelve', b'working-copy'],
Augie Fackler
formatting: blacken the codebase...
r43346 keepconflictparent=True,
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if stats.unresolvedcount:
tr.close()
Augie Fackler
formatting: blacken the codebase...
r43346 nodestoremove = [
repo.changelog.node(rev)
for rev in pycompat.xrange(oldtiprev, len(repo))
]
shelvedstate.save(
repo,
basename,
pctx,
tmpwctx,
nodestoremove,
branchtorestore,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 opts.get(b'keep'),
Augie Fackler
formatting: blacken the codebase...
r43346 activebookmark,
interactive,
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 raise error.InterventionRequired(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"unresolved conflicts (see 'hg resolve', then "
b"'hg unshelve --continue')"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
with repo.dirstate.parentchange():
repo.setparents(tmpwctx.node(), nodemod.nullid)
Augie Fackler
formatting: blacken the codebase...
r43346 newnode, ispartialunshelve = _createunshelvectx(
ui, repo, shelvectx, basename, interactive, opts
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
if newnode is None:
# If it ended up being a no-op commit, then the normal
# merge state clean-up path doesn't happen, so do it
# here. Fix issue5494
merge.mergestate.clean(repo)
shelvectx = tmpwctx
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'note: unshelved changes already existed '
b'in the working copy\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 ui.status(msg)
else:
shelvectx = repo[newnode]
hg.updaterepo(repo, tmpwctx.node(), False)
Navaneeth Suresh
unshelve: add interactive mode...
r42835 return shelvectx, ispartialunshelve
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _forgetunknownfiles(repo, shelvectx, addedbefore):
# Forget any files that were unknown before the shelve, unknown before
# unshelve started, but are now added.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shelveunknown = shelvectx.extra().get(b'shelve_unknown')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if not shelveunknown:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shelveunknown = frozenset(shelveunknown.split(b'\0'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 addedafter = frozenset(repo.status().added)
toforget = (addedafter & shelveunknown) - addedbefore
repo[None].forget(toforget)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _finishunshelve(repo, oldtiprev, tr, activebookmark):
_restoreactivebookmark(repo, activebookmark)
# The transaction aborting will strip all the commits for us,
# but it doesn't update the inmemory structures, so addchangegroup
# hooks still fire and try to operate on the missing commits.
# Clean up manually to prevent this.
repo.unfiltered().changelog.strip(oldtiprev, tr)
_aborttransaction(repo, tr)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 def _checkunshelveuntrackedproblems(ui, repo, shelvectx):
"""Check potential problems which may result from working
copy having untracked changes."""
wcdeleted = set(repo.status().deleted)
shelvetouched = set(shelvectx.files())
intersection = wcdeleted.intersection(shelvetouched)
if intersection:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 m = _(b"shelved change touches missing files")
hint = _(b"run hg status to see which files are missing")
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 raise error.Abort(m, hint=hint)
Augie Fackler
formatting: blacken the codebase...
r43346
Navaneeth Suresh
unshelve: rename _dounshelve() to dounshelve()...
r42763 def dounshelve(ui, repo, *shelved, **opts):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 opts = pycompat.byteskwargs(opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 abortf = opts.get(b'abort')
continuef = opts.get(b'continue')
interactive = opts.get(b'interactive')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if not abortf and not continuef:
cmdutil.checkunfinished(repo)
shelved = list(shelved)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b"name"):
shelved.append(opts[b"name"])
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if interactive and opts.get(b'keep'):
raise error.Abort(_(b'--keep on --interactive is not yet supported'))
Navaneeth Suresh
unshelve: store information about interactive mode in shelvedstate...
r42889 if abortf or continuef:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if abortf and continuef:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot use both abort and continue'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if shelved:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cannot combine abort/continue with '
b'naming a shelved change'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if abortf and opts.get(b'tool', False):
ui.warn(_(b'tool option will be ignored\n'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Taapas Agrawal
abort: added support for unshelve...
r42802 state = _loadshelvedstate(ui, repo, opts)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if abortf:
Taapas Agrawal
abort: added support for unshelve...
r42802 return unshelveabort(ui, repo, state)
Navaneeth Suresh
unshelve: add abort on using continue and interactive together...
r42893 elif continuef and interactive:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot use both continue and interactive'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 elif continuef:
return unshelvecontinue(ui, repo, state, opts)
elif len(shelved) > 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'can only unshelve one change at a time'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 elif not shelved:
shelved = listshelves(repo)
if not shelved:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'no shelved changes to apply!'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 basename = util.split(shelved[0][1])[1]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b"unshelving change '%s'\n") % basename)
Navaneeth Suresh
unshelve: store information about interactive mode in shelvedstate...
r42889 else:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 basename = shelved[0]
if not shelvedfile(repo, basename, patchextension).exists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"shelved change '%s' not found") % basename)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
repo = repo.unfiltered()
lock = tr = None
try:
lock = repo.lock()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr = repo.transaction(b'unshelve', report=lambda x: None)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 oldtiprev = len(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pctx = repo[b'.']
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 tmpwctx = pctx
# The goal is to have a commit structure like so:
# ...-> 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 pctx.
activebookmark = _backupactivebookmark(repo)
Augie Fackler
formatting: blacken the codebase...
r43346 tmpwctx, addedbefore = _commitworkingcopychanges(
ui, repo, opts, tmpwctx
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
_checkunshelveuntrackedproblems(ui, repo, shelvectx)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 branchtorestore = b''
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if shelvectx.branch() != shelvectx.p1().branch():
branchtorestore = shelvectx.branch()
Augie Fackler
formatting: blacken the codebase...
r43346 shelvectx, ispartialunshelve = _rebaserestoredcommit(
ui,
repo,
opts,
tr,
oldtiprev,
basename,
pctx,
tmpwctx,
shelvectx,
branchtorestore,
activebookmark,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
with ui.configoverride(overrides, b'unshelve'):
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 mergefiles(ui, repo, pctx, shelvectx)
restorebranch(ui, repo, branchtorestore)
Navaneeth Suresh
unshelve: clear shelvedstate and _finishunshelve() on partial unshelve...
r42932 shelvedstate.clear(repo)
_finishunshelve(repo, oldtiprev, tr, activebookmark)
Navaneeth Suresh
unshelve: forget unknown files after a partial unshelve...
r42961 _forgetunknownfiles(repo, shelvectx, addedbefore)
Navaneeth Suresh
unshelve: add interactive mode...
r42835 if not ispartialunshelve:
unshelvecleanup(ui, repo, basename, opts)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 finally:
if tr:
tr.release()
lockmod.release(lock)