##// END OF EJS Templates
auto-upgrade: add a test case with no permission to lock the repository...
auto-upgrade: add a test case with no permission to lock the repository This show the current behavior when the repository is unlockable. The current behavior is to abort, which is probably not great. Now that we have a proper test, we can think about the behavior we want in a later changeset. Differential Revision: https://phab.mercurial-scm.org/D12615

File last commit:

r49801:642e31cb default
r50091:1c233af9 default
Show More
shelve.py
1188 lines | 38.0 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".
"""
import collections
import errno
import itertools
import stat
from .i18n import _
Joerg Sonnenberger
node: import symbols explicitly...
r46729 from .node import (
bin,
hex,
nullrev,
)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 from . import (
bookmarks,
bundle2,
changegroup,
cmdutil,
discovery,
error,
exchange,
hg,
lock as lockmod,
mdiff,
merge,
Augie Fackler
mergestate: split out merge state handling code from main merge module...
r45383 mergestate as mergestatemod,
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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
# 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
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class ShelfDir:
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 def __init__(self, repo, for_backups=False):
if for_backups:
self.vfs = vfsmod.vfs(repo.vfs.join(backupdir))
else:
self.vfs = vfsmod.vfs(repo.vfs.join(shelvedir))
def get(self, name):
return Shelf(self.vfs, name)
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 def listshelves(self):
"""return all shelves in repo as list of (time, name)"""
try:
names = self.vfs.listdir()
except OSError as err:
if err.errno != errno.ENOENT:
raise
return []
info = []
seen = set()
for filename in names:
name = filename.rsplit(b'.', 1)[0]
if name in seen:
continue
seen.add(name)
shelf = self.get(name)
if not shelf.exists():
continue
mtime = shelf.mtime()
info.append((mtime, name))
return sorted(info, reverse=True)
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class Shelf:
Martin von Zweigbergk
shelve: introduce class representing a shelf...
r46991 """Represents a shelf, including possibly multiple files storing it.
Old shelves will have a .patch and a .hg file. Newer shelves will
also have a .shelve file. This class abstracts away some of the
differences and lets you work with the shelf as a whole.
"""
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 def __init__(self, vfs, name):
self.vfs = vfs
Martin von Zweigbergk
shelve: introduce class representing a shelf...
r46991 self.name = name
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009
Martin von Zweigbergk
shelve: introduce class representing a shelf...
r46991 def exists(self):
Martin von Zweigbergk
shelve: inline ".patch" constant now that it's only used in the Shelf class...
r47012 return self.vfs.exists(self.name + b'.patch') and self.vfs.exists(
self.name + b'.hg'
)
Martin von Zweigbergk
shelve: introduce class representing a shelf...
r46991
Martin von Zweigbergk
shelve: move method for getting stat (mtime) to new shelf class...
r46998 def mtime(self):
Martin von Zweigbergk
shelve: inline ".patch" constant now that it's only used in the Shelf class...
r47012 return self.vfs.stat(self.name + b'.patch')[stat.ST_MTIME]
Martin von Zweigbergk
shelve: move method for getting stat (mtime) to new shelf class...
r46998
Martin von Zweigbergk
shelve: move method for writing .shelve to new shelf class...
r46992 def writeinfo(self, info):
scmutil.simplekeyvaluefile(self.vfs, self.name + b'.shelve').write(info)
Martin von Zweigbergk
shelve: teach new shelf class to check if .shelve file exists...
r47004 def hasinfo(self):
return self.vfs.exists(self.name + b'.shelve')
Martin von Zweigbergk
shelve: move method for reading .shelve file to new shelf class...
r46993 def readinfo(self):
return scmutil.simplekeyvaluefile(
self.vfs, self.name + b'.shelve'
).read()
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 def writebundle(self, repo, bases, node):
cgversion = changegroup.safeversion(repo)
Martin von Zweigbergk
shelve: move method for writing bundle to new shelf class...
r46994 if cgversion == b'01':
btype = b'HG10BZ'
compression = None
else:
btype = b'HG20'
compression = b'BZ'
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 repo = repo.unfiltered()
Martin von Zweigbergk
shelve: move method for writing bundle to new shelf class...
r46994
outgoing = discovery.outgoing(
repo, missingroots=bases, ancestorsof=[node]
)
cg = changegroup.makechangegroup(repo, outgoing, cgversion, b'shelve')
bundle_filename = self.vfs.join(self.name + b'.hg')
bundle2.writebundle(
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 repo.ui,
Martin von Zweigbergk
shelve: move method for writing bundle to new shelf class...
r46994 cg,
bundle_filename,
btype,
self.vfs,
compression=compression,
)
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 def applybundle(self, repo, tr):
Martin von Zweigbergk
shelve: move method for reading .hg to new shelf class...
r46995 filename = self.name + b'.hg'
fp = self.vfs(filename)
try:
targetphase = phases.internal
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 if not phases.supportinternal(repo):
Martin von Zweigbergk
shelve: move method for reading .hg to new shelf class...
r46995 targetphase = phases.secret
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 gen = exchange.readbundle(repo.ui, fp, filename, self.vfs)
pretip = repo[b'tip']
Martin von Zweigbergk
shelve: move method for reading .hg to new shelf class...
r46995 bundle2.applybundle(
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 repo,
Martin von Zweigbergk
shelve: move method for reading .hg to new shelf class...
r46995 gen,
tr,
source=b'unshelve',
url=b'bundle:' + self.vfs.join(filename),
targetphase=targetphase,
)
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 shelvectx = repo[b'tip']
Martin von Zweigbergk
shelve: move method for reading .hg to new shelf class...
r46995 if pretip == shelvectx:
shelverev = tr.changes[b'revduplicates'][-1]
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 shelvectx = repo[shelverev]
Martin von Zweigbergk
shelve: move method for reading .hg to new shelf class...
r46995 return shelvectx
finally:
fp.close()
Martin von Zweigbergk
shelve: move function for opening .patch file to new shelf class...
r46996 def open_patch(self, mode=b'rb'):
return self.vfs(self.name + b'.patch', mode)
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 def _backupfilename(self, backupvfs, filename):
Martin von Zweigbergk
shelve: move method for creating backup to new shelf class...
r47003 def gennames(base):
yield base
base, ext = base.rsplit(b'.', 1)
for i in itertools.count(1):
yield b'%s-%d.%s' % (base, i, ext)
for n in gennames(filename):
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 if not backupvfs.exists(n):
return backupvfs.join(n)
Martin von Zweigbergk
shelve: move method for creating backup to new shelf class...
r47003
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 def movetobackup(self, backupvfs):
if not backupvfs.isdir():
backupvfs.makedir()
Martin von Zweigbergk
shelve: move method for creating backup to new shelf class...
r47003 for suffix in shelvefileextensions:
filename = self.name + b'.' + suffix
if self.vfs.exists(filename):
util.rename(
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 self.vfs.join(filename),
self._backupfilename(backupvfs, filename),
Martin von Zweigbergk
shelve: move method for creating backup to new shelf class...
r47003 )
Martin von Zweigbergk
shelve: add a method for deleting shelf to new shelf class...
r47013 def delete(self):
for ext in shelvefileextensions:
self.vfs.tryunlink(self.name + b'.' + ext)
Martin von Zweigbergk
shelve: introduce class representing a shelf...
r46991
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class shelvedstate:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 """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:
Joerg Sonnenberger
node: import symbols explicitly...
r46729 d[b'originalwctx'] = bin(d[b'originalwctx'])
d[b'pendingctx'] = bin(d[b'pendingctx'])
d[b'parents'] = [bin(h) for h in d[b'parents'].split(b' ')]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 d[b'nodestoremove'] = [
Joerg Sonnenberger
node: import symbols explicitly...
r46729 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:
Matt Harbison
shelve: fix conversion of exceptions to strings flagged by pytype...
r47386 raise error.CorruptedState(stringutil.forcebytestr(err))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
@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:
Matt Harbison
shelve: fix conversion of exceptions to strings flagged by pytype...
r47386 raise error.CorruptedState(stringutil.forcebytestr(err))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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,
Joerg Sonnenberger
node: import symbols explicitly...
r46729 b"originalwctx": hex(originalwctx.node()),
b"pendingctx": hex(pendingctx.node()),
b"parents": b' '.join([hex(p) for p in repo.dirstate.parents()]),
b"nodestoremove": b' '.join([hex(n) for n in nodestoremove]),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 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):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 maxbackups = repo.ui.configint(b'shelve', b'maxbackups')
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 backup_dir = ShelfDir(repo, for_backups=True)
hgfiles = backup_dir.listshelves()
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if maxbackups > 0 and maxbackups < len(hgfiles):
Martin von Zweigbergk
shelve: use listshelves() in cleanupoldbackups()...
r47011 bordermtime = hgfiles[maxbackups - 1][0]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 else:
bordermtime = None
Martin von Zweigbergk
shelve: use listshelves() in cleanupoldbackups()...
r47011 for mtime, name in 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
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 backup_dir.get(name).delete()
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):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """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:
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 if ShelfDir(repo).get(name).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:
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 shelf_dir = ShelfDir(repo)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 for n in gennames():
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 if not shelf_dir.get(n).exists():
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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()"""
Joerg Sonnenberger
node: import symbols explicitly...
r46729 seen = {nullrev}
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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):
Joerg Sonnenberger
node: import symbols explicitly...
r46729 info = {b'node': hex(node)}
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 shelf = ShelfDir(repo).get(name)
Martin von Zweigbergk
shelve: extract some repeated creation of shelf instances to variables...
r47005 shelf.writeinfo(info)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 bases = list(mutableancestors(repo[node]))
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 shelf.writebundle(repo, bases, node)
Martin von Zweigbergk
shelve: extract some repeated creation of shelf instances to variables...
r47005 with shelf.open_patch(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()
Joerg Sonnenberger
refactor: prefer checks against nullrev over nullid...
r47601 if parent.rev() != nullrev:
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())
Martin von Zweigbergk
shelve: clear merge state after partial shelve...
r46464 ms = mergestatemod.mergestate.read(repo)
if not ms.unresolvedcount():
ms.reset()
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():
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 shelf_dir = ShelfDir(repo)
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 for _mtime, name in shelf_dir.listshelves():
shelf_dir.get(name).movetobackup(backupvfs)
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 deletecmd(ui, repo, pats):
"""subcommand that deletes a specific shelve"""
if not pats:
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(_(b'no shelved changes specified!'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 with repo.wlock():
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
Matt Harbison
shelve: fix a missing variable in the exception handler for delete...
r44123 for name in pats:
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 shelf = ShelfDir(repo).get(name)
Martin von Zweigbergk
shelve: extract some repeated creation of shelf instances to variables...
r47005 if not shelf.exists():
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(
_(b"shelved change '%s' not found") % name
)
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 shelf.movetobackup(backupvfs)
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 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')
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 shelf_dir = ShelfDir(repo)
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 for mtime, name in shelf_dir.listshelves():
Martin von Zweigbergk
shelve: make listshelves() return shelf names instead of filenames...
r46999 if pats and name not in pats:
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 continue
Martin von Zweigbergk
shelve: make listshelves() return shelf names instead of filenames...
r46999 ui.write(name, 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
Martin von Zweigbergk
shelve: make listshelves() return shelf names instead of filenames...
r46999 ui.write(b' ' * (16 - len(name)))
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
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 with shelf_dir.get(name).open_patch() 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"""
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 shelf_dir = ShelfDir(repo)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if len(pats) == 0:
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 shelves = shelf_dir.listshelves()
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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]
Martin von Zweigbergk
shelve: make listshelves() return shelf names instead of filenames...
r46999 pats = [name]
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
for shelfname in pats:
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 if not shelf_dir.get(shelfname).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)
Martin von Zweigbergk
merge: introduce a clean_update() for that use-case...
r44743 merge.clean_update(state.pendingctx)
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())
Martin von Zweigbergk
revert: remove dangerous `parents` argument from `cmdutil.revert()`...
r45935 cmdutil.revert(ui, repo, shelvectx)
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 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'):
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 backupvfs = vfsmod.vfs(repo.vfs.join(backupdir))
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 ShelfDir(repo).get(name).movetobackup(backupvfs)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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)
Augie Fackler
mergestate: split out merge state handling code from main merge module...
r45383 ms = mergestatemod.mergestate.read(repo)
Augie Fackler
cleanup: use mergestate.unresolvedcount() instead of bool(list(unresolved()))...
r47070 if ms.unresolvedcount():
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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():
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 repo.setparents(state.pendingctx.node(), repo.nullid)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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():
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 repo.setparents(state.parents[0], repo.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:
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]
Martin von Zweigbergk
merge: replace calls to hg.updaterepo() by merge.update()...
r46151 merge.update(pendingctx)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 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
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 shelf = ShelfDir(repo).get(basename)
Martin von Zweigbergk
shelve: extract some repeated creation of shelf instances to variables...
r47005 if shelf.hasinfo():
node = shelf.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}):
Martin von Zweigbergk
shelve: replace repo instance in Shelf class by vfs instance...
r47009 shelvectx = shelf.applybundle(repo, 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:
Joerg Sonnenberger
node: import symbols explicitly...
r46729 info = {b'node': hex(shelvectx.node())}
Martin von Zweigbergk
shelve: extract some repeated creation of shelf instances to variables...
r47005 shelf.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,
Martin von Zweigbergk
shelve: attempt to make merge labels more helpful...
r49438 labels=[
b'working-copy',
b'shelved change',
b'parent of shelved change',
],
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,
)
Daniel Ploch
error: normalize "unresolved conflicts" error messages with a custom class...
r45711 raise error.ConflictResolutionRequired(b'unshelve')
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
with repo.dirstate.parentchange():
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 repo.setparents(tmpwctx.node(), repo.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:
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]
Martin von Zweigbergk
merge: replace calls to hg.updaterepo() by merge.update()...
r46151 merge.update(tmpwctx)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
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
Martin von Zweigbergk
shelve: split up dounshelve() in unshelvecmd() and _dounshelve()...
r45086 def unshelvecmd(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'):
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(
_(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:
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(_(b'cannot use both abort and continue'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if shelved:
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
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:
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(
_(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:
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(_(b'can only unshelve one change at a time'))
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 elif not shelved:
Martin von Zweigbergk
shelve: move listshelves() to new ShelfDir class, so caller need not pass vfs...
r47015 shelved = ShelfDir(repo).listshelves()
Navaneeth Suresh
shelve: move shelve extension to core...
r42744 if not shelved:
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.StateError(_(b'no shelved changes to apply!'))
Martin von Zweigbergk
shelve: make listshelves() return shelf names instead of filenames...
r46999 basename = shelved[0][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]
Martin von Zweigbergk
shelve: also create class representing whole directory of shelves...
r47014 if not ShelfDir(repo).get(basename).exists():
Martin von Zweigbergk
shelve: raise more specific errors...
r46990 raise error.InputError(_(b"shelved change '%s' not found") % basename)
Navaneeth Suresh
shelve: move shelve extension to core...
r42744
Martin von Zweigbergk
shelve: split up dounshelve() in unshelvecmd() and _dounshelve()...
r45086 return _dounshelve(ui, repo, basename, opts)
def _dounshelve(ui, repo, basename, opts):
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)