##// END OF EJS Templates
pyoxidizer: produce working Python 3 Windows installers (issue6366)...
pyoxidizer: produce working Python 3 Windows installers (issue6366) While we've had code to produce Python 3 Windows installers with PyOxidizer, we haven't been advertising them on the web site due to a bug in making TLS connections and issues around resource handling. This commit upgrades our PyOxidizer install and configuration to use a recent Git commit of PyOxidizer. This new version of PyOxidizer contains a *ton* of changes, improvements, and bug fixes. Notably, Windows shared distributions now mostly "just work" and the TLS bug and random problems with Python extension modules in the standard library go away. And Python has been upgraded from 3.7 to 3.8.6. The price we pay for this upgrade is a ton of backwards incompatible changes to Starlark. I applied this commit (the overall series actually) on stable to produce Windows installers for Mercurial 5.5.2, which I published shortly before submitting this commit for review. In order to get the stable branch working, I decided to take a less aggressive approach to Python resource management. Previously, we were attempting to load all Python modules from memory and were performing some hacks to copy Mercurial's non-module resources into additional directories in Starlark. This commit implements a resource callback function in Starlark (a new feature since PyOxidizer 0.7) to dynamically assign standard library resources to in-memory loading and all other resources to filesystem loading. This means that Mercurial's files and all the other packages we ship in the Windows installers (e.g. certifi and pygments) are loaded from the filesystem instead of from memory. This avoids issues due to lack of __file__ and enables us to ship a working Python 3 installer on Windows. The end state of the install layout after this patch is not ideal for @: we still copy resource files like templates and help text to directories next to the hg.exe executable. There is code in @ to use importlib.resources to load these files and we could likely remove these copies once this lands on @. But for now, the install layout mimics what we've shipped for seemingly forever and is backwards compatible. It allows us to achieve the milestone of working Python 3 Windows installers and gets us a giant step closer to deleting Python 2. Differential Revision: https://phab.mercurial-scm.org/D9148

File last commit:

r46092:9b16bb3b default
r46277:57b5452a default
Show More
localrepo.py
3552 lines | 126.1 KiB | text/x-python | PythonLexer
mpm@selenic.com
Break apart hg.py...
r1089 # localrepo.py - read/write repository class for mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Break apart hg.py...
r1089 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Gregory Szorc
localrepo: use absolute_import
r27522
from __future__ import absolute_import
import errno
Augie Fackler
localrepo: use functools.wraps() in unfilteredmethod decorator...
r45987 import functools
Gregory Szorc
localrepo: use absolute_import
r27522 import os
import random
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648 import sys
Gregory Szorc
localrepo: use absolute_import
r27522 import time
import weakref
from .i18n import _
from .node import (
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 bin,
Gregory Szorc
localrepo: use absolute_import
r27522 hex,
nullid,
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 nullrev,
Gregory Szorc
localrepo: use absolute_import
r27522 short,
)
Gregory Szorc
py3: manually import pycompat.delattr where it is needed...
r43360 from .pycompat import (
delattr,
getattr,
)
Gregory Szorc
localrepo: use absolute_import
r27522 from . import (
bookmarks,
branchmap,
bundle2,
changegroup,
Pierre-Yves David
color: initialize color for the localrepo ui...
r31111 color,
commitctx: extract the function in a dedicated module...
r45759 commit,
Gregory Szorc
localrepo: use absolute_import
r27522 context,
dirstate,
Augie Fackler
localrepo: refer to dirstateguard by its new name
r30492 dirstateguard,
Durham Goode
changegroup: replace changegroupsubset with makechangegroup...
r34099 discovery,
Gregory Szorc
localrepo: use absolute_import
r27522 encoding,
error,
exchange,
extensions,
filelog,
hook,
lock as lockmod,
match as matchmod,
Augie Fackler
mergestate: split out merge state handling code from main merge module...
r45383 mergestate as mergestatemod,
Augie Fackler
localrepo: refer to checkunresolved by its new name
r30496 mergeutil,
Gregory Szorc
localrepo: use absolute_import
r27522 namespaces,
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489 narrowspec,
Gregory Szorc
localrepo: use absolute_import
r27522 obsolete,
pathutil,
phases,
pushkey,
Augie Fackler
localrepo: ensure transaction id is fully bytes on py3
r31508 pycompat,
config: add a function in `rcutil` to abstract HGRCSKIPREPO...
r44727 rcutil,
Gregory Szorc
localrepo: use absolute_import
r27522 repoview,
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirements as requirementsmod,
Gregory Szorc
localrepo: use absolute_import
r27522 revset,
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 revsetlang,
Gregory Szorc
localrepo: use absolute_import
r27522 scmutil,
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 sparse,
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 store as storemod,
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subrepoutil,
Gregory Szorc
localrepo: use absolute_import
r27522 tags as tagsmod,
transaction,
FUJIWARA Katsunori
localrepo: check HG_PENDING strictly...
r31054 txnutil,
Gregory Szorc
localrepo: use absolute_import
r27522 util,
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.localrepo'...
r31231 vfs as vfsmod,
Gregory Szorc
localrepo: use absolute_import
r27522 )
Pulkit Goyal
interfaces: create a new folder for interfaces and move repository.py in it...
r43078
from .interfaces import (
repository,
Pulkit Goyal
interfaceutil: move to interfaces/...
r43079 util as interfaceutil,
Pulkit Goyal
interfaces: create a new folder for interfaces and move repository.py in it...
r43078 )
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
Augie Fackler
core: migrate uses of hashlib.sha1 to hashutil.sha1...
r44517 hashutil,
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 procutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
)
Gregory Szorc
localrepo: use absolute_import
r27522
Augie Fackler
formatting: blacken the codebase...
r43346 from .revlogutils import constants as revlogconst
Boris Feld
sparse-revlog: set max delta chain length to on thousand...
r39542
Gregory Szorc
localrepo: use absolute_import
r27522 release = lockmod.release
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109
FUJIWARA Katsunori
localrepo: store path and vfs location of cached properties...
r33277 # set of (path, vfs-location) tuples. vfs-location is:
# - 'plain for vfs relative paths
# - '' for svfs relative paths
_cachedfiles = set()
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 class _basefilecache(scmutil.filecache):
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014 """All filecache usage on repo are done for logic that should be unfiltered
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014 def __get__(self, repo, type=None):
Martijn Pieters
scmutil: allow access to filecache descriptor on class...
r29373 if repo is None:
return self
Yuya Nishihara
filecache: unimplement __set__() and __delete__() (API)...
r40454 # proxy to unfiltered __dict__ since filtered repo has no entry
Yuya Nishihara
filecache: use try-except for faster __dict__ lookup...
r40453 unfi = repo.unfiltered()
try:
return unfi.__dict__[self.sname]
except KeyError:
pass
return super(_basefilecache, self).__get__(unfi, type)
Yuya Nishihara
filecache: unimplement __set__() and __delete__() (API)...
r40454
def set(self, repo, value):
return super(_basefilecache, self).set(repo.unfiltered(), value)
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 class repofilecache(_basefilecache):
"""filecache for files in .hg but outside of .hg/store"""
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
localrepo: store path and vfs location of cached properties...
r33277 def __init__(self, *paths):
super(repofilecache, self).__init__(*paths)
for path in paths:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _cachedfiles.add((path, b'plain'))
FUJIWARA Katsunori
localrepo: store path and vfs location of cached properties...
r33277
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 def join(self, obj, fname):
return obj.vfs.join(fname)
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 class storecache(_basefilecache):
Idan Kamara
filecache: refactor path join logic to a function...
r16198 """filecache for files in the store"""
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
localrepo: store path and vfs location of cached properties...
r33277 def __init__(self, *paths):
super(storecache, self).__init__(*paths)
for path in paths:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _cachedfiles.add((path, b''))
FUJIWARA Katsunori
localrepo: store path and vfs location of cached properties...
r33277
Idan Kamara
filecache: refactor path join logic to a function...
r16198 def join(self, obj, fname):
return obj.sjoin(fname)
Augie Fackler
formatting: blacken the codebase...
r43346
localrepo: grab mixedrepostorecache class from 526750cdd02d...
r42539 class mixedrepostorecache(_basefilecache):
"""filecache for a mix files in .hg/store and outside"""
Augie Fackler
formatting: blacken the codebase...
r43346
localrepo: grab mixedrepostorecache class from 526750cdd02d...
r42539 def __init__(self, *pathsandlocations):
# scmutil.filecache only uses the path for passing back into our
# join(), so we can safely pass a list of paths and locations
super(mixedrepostorecache, self).__init__(*pathsandlocations)
Martin von Zweigbergk
mixedrepostorecache: fix a silly redundant updating of set...
r42632 _cachedfiles.update(pathsandlocations)
localrepo: grab mixedrepostorecache class from 526750cdd02d...
r42539
def join(self, obj, fnameandlocation):
fname, location = fnameandlocation
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if location == b'plain':
localrepo: grab mixedrepostorecache class from 526750cdd02d...
r42539 return obj.vfs.join(fname)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if location != b'':
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unexpected location: %s' % location
Augie Fackler
formatting: blacken the codebase...
r43346 )
localrepo: grab mixedrepostorecache class from 526750cdd02d...
r42539 return obj.sjoin(fname)
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
localrepo: add isfilecached to check filecache-ed property is already cached...
r33382 def isfilecached(repo, name):
"""check if a repo has already cached "name" filecache-ed property
This returns (cachedobj-or-None, iscached) tuple.
"""
cacheentry = repo.unfiltered()._filecache.get(name, None)
if not cacheentry:
return None, False
return cacheentry.obj, True
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
localrepo: remove a couple of local type aliases...
r29104 class unfilteredpropertycache(util.propertycache):
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 """propertycache that apply to unfiltered repo only"""
def __get__(self, repo, type=None):
Pierre-Yves David
repoview: have unfilteredpropertycache using the underlying cache...
r19846 unfi = repo.unfiltered()
if unfi is repo:
return super(unfilteredpropertycache, self).__get__(unfi)
return getattr(unfi, self.name)
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
localrepo: remove a couple of local type aliases...
r29104 class filteredpropertycache(util.propertycache):
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 """propertycache that must take filtering in account"""
def cachevalue(self, obj, value):
object.__setattr__(obj, self.name, value)
def hasunfilteredcache(repo, name):
Mads Kiilerich
spelling: fix some minor issues found by spell checker
r18644 """check if a repo has an unfilteredpropertycache value for <name>"""
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 return name in vars(repo.unfiltered())
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
clfilter: rename `unfilteredmeth` to `unfilteredmethod`...
r18016 def unfilteredmethod(orig):
Pierre-Yves David
clfilter: introduce an `unfilteredmethod` decorator...
r17994 """decorate method that always need to be run on unfiltered version"""
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
localrepo: use functools.wraps() in unfilteredmethod decorator...
r45987 @functools.wraps(orig)
Pierre-Yves David
clfilter: introduce an `unfilteredmethod` decorator...
r17994 def wrapper(repo, *args, **kwargs):
return orig(repo.unfiltered(), *args, **kwargs)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
clfilter: introduce an `unfilteredmethod` decorator...
r17994 return wrapper
Augie Fackler
formatting: blacken the codebase...
r43346
moderncaps = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'lookup',
b'branchmap',
b'pushkey',
b'known',
b'getbundle',
b'unbundle',
Augie Fackler
formatting: blacken the codebase...
r43346 }
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 legacycaps = moderncaps.union({b'changegroupsubset'})
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
interfaceutil: module to stub out zope.interface...
r37828 @interfaceutil.implementer(repository.ipeercommandexecutor)
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648 class localcommandexecutor(object):
def __init__(self, peer):
self._peer = peer
self._sent = False
self._closed = False
def __enter__(self):
return self
def __exit__(self, exctype, excvalue, exctb):
self.close()
def callcommand(self, command, args):
if self._sent:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'callcommand() cannot be used after sendcommands()'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648
if self._closed:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'callcommand() cannot be used after close()'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648
# We don't need to support anything fancy. Just call the named
# method on the peer and return a resolved future.
fn = getattr(self._peer, pycompat.sysstr(command))
f = pycompat.futures.Future()
try:
Augie Fackler
localrepo: add some overlooked strkwargs love for py3...
r37688 result = fn(**pycompat.strkwargs(args))
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648 except Exception:
Augie Fackler
py3: paper over differences in future exception handling...
r37687 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648 else:
f.set_result(result)
return f
def sendcommands(self):
self._sent = True
def close(self):
self._closed = True
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
interfaceutil: module to stub out zope.interface...
r37828 @interfaceutil.implementer(repository.ipeercommands)
Gregory Szorc
localrepo: use peer interfaces...
r33802 class localpeer(repository.peer):
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 '''peer for a local repo; reflects only the most recent API'''
Pierre-Yves David
localrepo: don't use mutable default argument value...
r31412 def __init__(self, repo, caps=None):
Gregory Szorc
localrepo: use peer interfaces...
r33802 super(localpeer, self).__init__()
Pierre-Yves David
localrepo: don't use mutable default argument value...
r31412 if caps is None:
caps = moderncaps.copy()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._repo = repo.filtered(b'served')
Gregory Szorc
peer: make ui an attribute...
r37337 self.ui = repo.ui
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 self._caps = repo._restrictcapabilities(caps)
Gregory Szorc
localrepo: use peer interfaces...
r33802 # Begin of _basepeer interface.
def url(self):
return self._repo.url()
def local(self):
return self._repo
def peer(self):
return self
def canpush(self):
return True
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def close(self):
self._repo.close()
Gregory Szorc
localrepo: use peer interfaces...
r33802 # End of _basepeer interface.
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
localrepo: use peer interfaces...
r33802 # Begin of _basewirecommands interface.
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def branchmap(self):
Pierre-Yves David
clfilter: drop extra filtering in localpeer...
r18279 return self._repo.branchmap()
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
localrepo: use peer interfaces...
r33802 def capabilities(self):
return self._caps
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
wireproto: properly call clonebundles command...
r37667 def clonebundles(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._repo.tryread(b'clonebundles.manifest')
Gregory Szorc
wireproto: properly call clonebundles command...
r37667
Gregory Szorc
localrepo: use peer interfaces...
r33802 def debugwireargs(self, one, two, three=None, four=None, five=None):
"""Used to test argument passing over the wire"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"%s %s %s %s %s" % (
Augie Fackler
formatting: blacken the codebase...
r43346 one,
two,
pycompat.bytestr(three),
pycompat.bytestr(four),
pycompat.bytestr(five),
)
def getbundle(
self, source, heads=None, common=None, bundlecaps=None, **kwargs
):
chunks = exchange.getbundlechunks(
self._repo,
source,
heads=heads,
common=common,
bundlecaps=bundlecaps,
**kwargs
)[1]
Gregory Szorc
exchange: refactor APIs to obtain bundle data (API)...
r30187 cb = util.chunkbuffer(chunks)
Martin von Zweigbergk
localrepo: reuse exchange.bundle2requested()...
r32149 if exchange.bundle2requested(bundlecaps):
Pierre-Yves David
bundle2: return a stream from exchange.getbundle...
r21068 # When requesting a bundle2, getbundle returns a stream to make the
# wire level function happier. We need to build a proper object
# from it in local peer.
Gregory Szorc
exchange: refactor APIs to obtain bundle data (API)...
r30187 return bundle2.getunbundler(self.ui, cb)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return changegroup.getunbundler(b'01', cb, None)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
localrepo: use peer interfaces...
r33802 def heads(self):
return self._repo.heads()
def known(self, nodes):
return self._repo.known(nodes)
def listkeys(self, namespace):
return self._repo.listkeys(namespace)
def lookup(self, key):
return self._repo.lookup(key)
def pushkey(self, namespace, key, old, new):
return self._repo.pushkey(namespace, key, old, new)
def stream_out(self):
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 raise error.Abort(_(b'cannot perform stream clone against local peer'))
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
wireproto: use command executor for unbundle...
r37664 def unbundle(self, bundle, heads, url):
Pierre-Yves David
localrepo: add unbundle support...
r20969 """apply a bundle on a repo
This function handles the repo locking itself."""
try:
Pierre-Yves David
bundle2: add on more layer of exception catching in localrepo.unbundle...
r24798 try:
Gregory Szorc
wireproto: use command executor for unbundle...
r37664 bundle = exchange.readbundle(self.ui, bundle, None)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ret = exchange.unbundle(self._repo, bundle, heads, b'push', url)
if util.safehasattr(ret, b'getchunks'):
Pierre-Yves David
bundle2: add on more layer of exception catching in localrepo.unbundle...
r24798 # This is a bundle20 object, turn it into an unbundler.
# This little dance should be dropped eventually when the
# API is finally improved.
stream = util.chunkbuffer(ret.getchunks())
ret = bundle2.getunbundler(self.ui, stream)
return ret
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except Exception as exc:
Pierre-Yves David
bundle2-localpeer: properly propagate the server output on error (issue4594)...
r24799 # If the exception contains output salvaged from a bundle2
# reply, we need to make sure it is printed before continuing
# to fail. So we build a bundle2 with such output and consume
# it directly.
#
# This is not very elegant but allows a "simple" solution for
# issue4594
output = getattr(exc, '_bundle2salvagedoutput', ())
if output:
bundler = bundle2.bundle20(self._repo.ui)
for out in output:
bundler.addpart(out)
stream = util.chunkbuffer(bundler.getchunks())
b = bundle2.getunbundler(self.ui, stream)
bundle2.processbundle(self._repo, b)
Pierre-Yves David
bundle2: add on more layer of exception catching in localrepo.unbundle...
r24798 raise
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.PushRaced as exc:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ResponseError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'push failed:'), stringutil.forcebytestr(exc)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
localrepo: add unbundle support...
r20969
Gregory Szorc
localrepo: use peer interfaces...
r33802 # End of _basewirecommands interface.
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
localrepo: use peer interfaces...
r33802 # Begin of peer interface.
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
wireproto: implement command executor interface for version 1 peers...
r37648 def commandexecutor(self):
return localcommandexecutor(self)
Gregory Szorc
localrepo: use peer interfaces...
r33802 # End of peer interface.
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
interfaceutil: module to stub out zope.interface...
r37828 @interfaceutil.implementer(repository.ipeerlegacycommands)
Gregory Szorc
wireproto: convert legacy commands to command executor...
r37653 class locallegacypeer(localpeer):
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 '''peer extension which implements legacy methods too; used for tests with
restricted capabilities'''
def __init__(self, repo):
Gregory Szorc
localrepo: use peer interfaces...
r33802 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
# Begin of baselegacywirecommands interface.
def between(self, pairs):
return self._repo.between(pairs)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def branches(self, nodes):
return self._repo.branches(nodes)
Gregory Szorc
wireproto: convert legacy commands to command executor...
r37653 def changegroup(self, nodes, source):
Augie Fackler
formatting: blacken the codebase...
r43346 outgoing = discovery.outgoing(
Manuel Jacob
discovery: change users of `outgoing.missingheads` to `outgoing.ancestorsof`...
r45704 self._repo, missingroots=nodes, ancestorsof=self._repo.heads()
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def changegroupsubset(self, bases, heads, source):
Augie Fackler
formatting: blacken the codebase...
r43346 outgoing = discovery.outgoing(
Manuel Jacob
discovery: change users of `outgoing.missingheads` to `outgoing.ancestorsof`...
r45704 self._repo, missingroots=bases, ancestorsof=heads
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
localrepo: use peer interfaces...
r33802 # End of baselegacywirecommands interface.
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: move featuresetupfuncs out of localrepository class (API)...
r37153 # Functions receiving (ui, features) that extensions can register to impact
# the ability to load repositories with custom requirements. Only
# functions defined in loaded extensions are called.
#
# The function receives a set of requirement strings that the repository
# is capable of opening. Functions will typically add elements to the
# set to reflect that the extension knows how to handle that requirements.
featuresetupfuncs = set()
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
localrepo: refactor logic to calculate sharedvfs in separate fn...
r45912 def _getsharedvfs(hgvfs, requirements):
""" returns the vfs object pointing to root of shared source
repo for a shared repository
hgvfs is vfs pointing at .hg/ of current repo (shared one)
requirements is a set of requirements of current repo (shared one)
"""
# The ``shared`` or ``relshared`` requirements indicate the
# store lives in the path contained in the ``.hg/sharedpath`` file.
# This is an absolute path for ``shared`` and relative to
# ``.hg/`` for ``relshared``.
sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
Pulkit Goyal
requirements: introduce constants for `shared` and `relshared` requirements...
r45946 if requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements:
Pulkit Goyal
localrepo: refactor logic to calculate sharedvfs in separate fn...
r45912 sharedpath = hgvfs.join(sharedpath)
sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
if not sharedvfs.exists():
raise error.RepoError(
_(b'.hg/sharedpath points to nonexistent directory %s')
% sharedvfs.base
)
return sharedvfs
Pulkit Goyal
localrepo: refactor `.hg/requires` reading logic in separate function...
r45913 def _readrequires(vfs, allowmissing):
""" reads the require file present at root of this vfs
and return a set of requirements
If allowmissing is True, we suppress ENOENT if raised"""
# requires file contains a newline-delimited list of
# features/capabilities the opener (us) must have in order to use
# the repository. This file was introduced in Mercurial 0.9.2,
# which means very old repositories may not have one. We assume
# a missing file translates to no requirements.
try:
requirements = set(vfs.read(b'requires').splitlines())
except IOError as e:
if not (allowmissing and e.errno == errno.ENOENT):
raise
requirements = set()
return requirements
Gregory Szorc
localrepo: copy ui in makelocalrepository()...
r39725 def makelocalrepository(baseui, path, intents=None):
Gregory Szorc
localrepo: create new function for instantiating a local repo object...
r39723 """Create a local repository object.
Given arguments needed to construct a local repository, this function
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 performs various early repository loading functionality (such as
reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
the repository can be opened, derives a type suitable for representing
that repository, and returns an instance of it.
Gregory Szorc
localrepo: create new function for instantiating a local repo object...
r39723
The returned object conforms to the ``repository.completelocalrepository``
interface.
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800
The repository type is derived by calling a series of factory functions
for each aspect/interface of the final repository. These are defined by
``REPO_INTERFACES``.
Each factory function is called to produce a type implementing a specific
interface. The cumulative list of returned types will be combined into a
new type and that type will be instantiated to represent the local
repository.
The factory functions each receive various state that may be consulted
as part of deriving a type.
Extensions should wrap these factory functions to customize repository type
creation. Note that an extension's wrapped function may be called even if
that extension is not loaded for the repo being constructed. Extensions
should check if their ``__name__`` appears in the
``extensionmodulenames`` set passed to the factory function and no-op if
not.
Gregory Szorc
localrepo: create new function for instantiating a local repo object...
r39723 """
Gregory Szorc
localrepo: copy ui in makelocalrepository()...
r39725 ui = baseui.copy()
# Prevent copying repo configuration.
ui.copy = baseui.copy
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724 # Working directory VFS rooted at repository root.
wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
# Main VFS for .hg/ directory.
hgpath = wdirvfs.join(b'.hg')
hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
Pulkit Goyal
localrepo: refactor logic to calculate sharedvfs in separate fn...
r45912 # Whether this repository is shared one or not
shared = False
# If this repository is shared, vfs pointing to shared repo
sharedvfs = None
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724
Gregory Szorc
localrepo: check for .hg/ directory in makelocalrepository()...
r39727 # The .hg/ path should exist and should be a directory. All other
# cases are errors.
if not hgvfs.isdir():
try:
hgvfs.stat()
except OSError as e:
if e.errno != errno.ENOENT:
raise
Gregory Szorc
localrepo: handle ValueError during repository opening...
r45469 except ValueError as e:
# Can be raised on Python 3.8 when path is invalid.
raise error.Abort(
_(b'invalid path %s: %s') % (path, pycompat.bytestr(e))
)
Gregory Szorc
localrepo: check for .hg/ directory in makelocalrepository()...
r39727
raise error.RepoError(_(b'repository %s not found') % path)
Pulkit Goyal
localrepo: refactor `.hg/requires` reading logic in separate function...
r45913 requirements = _readrequires(hgvfs, True)
Pulkit Goyal
share: introduce config option to store requires in .hg/store...
r46055 shared = (
requirementsmod.SHARED_REQUIREMENT in requirements
or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
)
if shared:
sharedvfs = _getsharedvfs(hgvfs, requirements)
# if .hg/requires contains the sharesafe requirement, it means
# there exists a `.hg/store/requires` too and we should read it
# NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
# is present. We never write SHARESAFE_REQUIREMENT for a repo if store
# is not present, refer checkrequirementscompat() for that
if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
if shared:
# This is a shared repo
storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
else:
storevfs = vfsmod.vfs(hgvfs.join(b'store'))
requirements |= _readrequires(storevfs, False)
Gregory Szorc
localrepo: read requirements file in makelocalrepository()...
r39728
Gregory Szorc
localrepo: load extensions in makelocalrepository()...
r39726 # The .hg/hgrc file may load extensions or contain config options
# that influence repository construction. Attempt to load it and
# process any new extensions that it may have pulled in.
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057 if loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs):
Gregory Szorc
localrepo: automatically load lfs extension when required (BC)...
r39888 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
Gregory Szorc
localrepo: load extensions in makelocalrepository()...
r39726 extensions.loadall(ui)
Yuya Nishihara
extensions: add "uipopulate" hook, called per instance, not per process...
r40760 extensions.populateui(ui)
Gregory Szorc
localrepo: load extensions in makelocalrepository()...
r39726
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 # Set of module names of extensions loaded for this repository.
extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 supportedrequirements = gathersupportedrequirements(ui)
Gregory Szorc
localrepo: move requirements reasonability testing to own function...
r39731
# We first validate the requirements are known.
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 ensurerequirementsrecognized(requirements, supportedrequirements)
Gregory Szorc
localrepo: move requirements reasonability testing to own function...
r39731 # Then we validate that the known set is reasonable to use together.
ensurerequirementscompatible(ui, requirements)
Gregory Szorc
localrepo: document and test bug around opening shared repos...
r39732 # TODO there are unhandled edge cases related to opening repositories with
# shared storage. If storage is shared, we should also test for requirements
# compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
# that repo, as that repo may load extensions needed to open it. This is a
# bit complicated because we don't want the other hgrc to overwrite settings
# in this hgrc.
#
# This bug is somewhat mitigated by the fact that we copy the .hg/requires
# file when sharing repos. But if a requirement is added after the share is
# performed, thereby introducing a new requirement for the opener, we may
# will not see that and could encounter a run-time error interacting with
# that shared store since it has an unknown-to-us requirement.
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 # At this point, we know we should be capable of opening the repository.
# Now get on with doing that.
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 features = set()
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 # The "store" part of the repository holds versioned data. How it is
Pulkit Goyal
localrepo: refactor logic to calculate sharedvfs in separate fn...
r45912 # accessed is determined by various requirements. If `shared` or
# `relshared` requirements are present, this indicates current repository
# is a share and store exists in path mentioned in `.hg/sharedpath`
if shared:
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 storebasepath = sharedvfs.base
cachepath = sharedvfs.join(b'cache')
Pulkit Goyal
localrepo: refactor logic to calculate sharedvfs in separate fn...
r45912 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 else:
storebasepath = hgvfs.base
cachepath = hgvfs.join(b'cache')
Boris Feld
repo: add a `wcachevfs` to access the `.hg/wcache/` directory...
r40826 wcachepath = hgvfs.join(b'wcache')
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 # The store has changed over time and the exact layout is dictated by
# requirements. The store interface abstracts differences across all
# of them.
Augie Fackler
formatting: blacken the codebase...
r43346 store = makestore(
requirements,
storebasepath,
lambda base: vfsmod.vfs(base, cacheaudited=True),
)
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 hgvfs.createmode = store.createmode
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 storevfs = store.vfs
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 # The cache vfs is used to manage cache files.
cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
cachevfs.createmode = store.createmode
Boris Feld
repo: add a `wcachevfs` to access the `.hg/wcache/` directory...
r40826 # The cache vfs is used to manage cache files related to the working copy
wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
wcachevfs.createmode = store.createmode
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 # Now resolve the type for the repository object. We do this by repeatedly
# calling a factory function to produces types for specific aspects of the
# repo's operation. The aggregate returned types are used as base classes
# for a dynamically-derived type, which will represent our new repository.
bases = []
extrastate = {}
for iface, fn in REPO_INTERFACES:
# We pass all potentially useful state to give extensions tons of
# flexibility.
Augie Fackler
formatting: blacken the codebase...
r43346 typ = fn()(
ui=ui,
intents=intents,
requirements=requirements,
features=features,
wdirvfs=wdirvfs,
hgvfs=hgvfs,
store=store,
storevfs=storevfs,
storeoptions=storevfs.options,
cachevfs=cachevfs,
wcachevfs=wcachevfs,
extensionmodulenames=extensionmodulenames,
extrastate=extrastate,
baseclasses=bases,
)
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800
if not isinstance(typ, type):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unable to construct type for %s' % iface
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800
bases.append(typ)
# type() allows you to use characters in type names that wouldn't be
# recognized as Python symbols in source code. We abuse that to add
# rich information about our constructed repo.
Augie Fackler
formatting: blacken the codebase...
r43346 name = pycompat.sysstr(
b'derivedrepo:%s<%s>' % (wdirvfs.base, b','.join(sorted(requirements)))
)
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800
cls = type(name, tuple(bases), {})
return cls(
Gregory Szorc
localrepo: copy ui in makelocalrepository()...
r39725 baseui=baseui,
ui=ui,
origroot=path,
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724 wdirvfs=wdirvfs,
hgvfs=hgvfs,
Gregory Szorc
localrepo: read requirements file in makelocalrepository()...
r39728 requirements=requirements,
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 supportedrequirements=supportedrequirements,
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 sharedpath=storebasepath,
store=store,
cachevfs=cachevfs,
Boris Feld
repo: add a `wcachevfs` to access the `.hg/wcache/` directory...
r40826 wcachevfs=wcachevfs,
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 features=features,
Augie Fackler
formatting: blacken the codebase...
r43346 intents=intents,
)
Gregory Szorc
localrepo: create new function for instantiating a local repo object...
r39723
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None):
Gregory Szorc
localrepo: extract loading of hgrc files to standalone function...
r40571 """Load hgrc files/content into a ui instance.
This is called during repository opening to load any additional
config files or settings relevant to the current repository.
Returns a bool indicating whether any additional configs were loaded.
Extensions should monkeypatch this function to modify how per-repo
configs are loaded. For example, an extension may wish to pull in
configs from alternate files or sources.
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057
sharedvfs is vfs object pointing to source repo if the current one is a
shared one
Gregory Szorc
localrepo: extract loading of hgrc files to standalone function...
r40571 """
config: add a function in `rcutil` to abstract HGRCSKIPREPO...
r44727 if not rcutil.use_repo_hgrc():
hgrc: introduce HGRCSKIPREPO to skip reading the repository's hgrc...
r44583 return False
Pulkit Goyal
localrepo: load the share source .hg/hgrc also in share-safe mode (API)...
r46057
# first load config from shared source if we has to
if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs:
try:
ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base)
except IOError:
pass
Gregory Szorc
localrepo: extract loading of hgrc files to standalone function...
r40571 try:
ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
return True
except IOError:
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: automatically load lfs extension when required (BC)...
r39888 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
"""Perform additional actions after .hg/hgrc is loaded.
This function is called during repository loading immediately after
the .hg/hgrc file is loaded and before per-repo extensions are loaded.
The function can be used to validate configs, automatically add
options (including extensions) based on requirements, etc.
"""
# Map of requirements to list of extensions to load automatically when
# requirement is present.
autoextensions = {
Augie Fackler
localrepo: add git extension to autoextensions list...
r44966 b'git': [b'git'],
Gregory Szorc
largefiles: automatically load largefiles extension when required (BC)...
r39890 b'largefiles': [b'largefiles'],
Gregory Szorc
localrepo: automatically load lfs extension when required (BC)...
r39888 b'lfs': [b'lfs'],
}
for requirement, names in sorted(autoextensions.items()):
if requirement not in requirements:
continue
for name in names:
if not ui.hasconfig(b'extensions', name):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.setconfig(b'extensions', name, b'', source=b'autoload')
Gregory Szorc
localrepo: automatically load lfs extension when required (BC)...
r39888
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 def gathersupportedrequirements(ui):
"""Determine the complete set of recognized requirements."""
# Start with all requirements supported by this file.
supported = set(localrepository._basesupported)
# Execute ``featuresetupfuncs`` entries if they belong to an extension
# relevant to this ui instance.
modules = {m.__name__ for n, m in extensions.extensions(ui)}
for fn in featuresetupfuncs:
if fn.__module__ in modules:
fn(ui, supported)
# Add derived requirements from registered compression engines.
for name in util.compengines:
engine = util.compengines[name]
compression: only declare revlog support for available engine...
r42304 if engine.available() and engine.revlogheader():
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 supported.add(b'exp-compression-%s' % name)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if engine.name() == b'zstd':
compression: introduce an official `zstd-revlog` requirement...
r42305 supported.add(b'revlog-compression-zstd')
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729
return supported
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 def ensurerequirementsrecognized(requirements, supported):
"""Validate that a set of local requirements is recognized.
Receives a set of requirements. Raises an ``error.RepoError`` if there
exists any requirement in that set that currently loaded code doesn't
recognize.
Returns a set of supported requirements.
"""
missing = set()
for requirement in requirements:
if requirement in supported:
continue
if not requirement or not requirement[0:1].isalnum():
raise error.RequirementError(_(b'.hg/requires file is corrupt'))
missing.add(requirement)
if missing:
raise error.RequirementError(
Augie Fackler
formatting: blacken the codebase...
r43346 _(b'repository requires features unknown to this Mercurial: %s')
% b' '.join(sorted(missing)),
hint=_(
b'see https://mercurial-scm.org/wiki/MissingRequirement '
b'for more information'
),
)
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729
Gregory Szorc
localrepo: move requirements reasonability testing to own function...
r39731 def ensurerequirementscompatible(ui, requirements):
"""Validates that a set of recognized requirements is mutually compatible.
Some requirements may not be compatible with others or require
config options that aren't enabled. This function is called during
repository opening to ensure that the set of requirements needed
to open a repository is sane and compatible with config options.
Extensions can monkeypatch this function to perform additional
checking.
``error.RepoError`` should be raised on failure.
"""
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if (
requirementsmod.SPARSE_REQUIREMENT in requirements
and not sparse.enabled
):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.RepoError(
_(
b'repository is using sparse feature but '
b'sparse is not enabled; enable the '
b'"sparse" extensions to access'
)
)
Gregory Szorc
localrepo: move requirements reasonability testing to own function...
r39731
Gregory Szorc
localrepo: move store() from store module...
r39734 def makestore(requirements, path, vfstype):
"""Construct a storage object for a repository."""
if b'store' in requirements:
if b'fncache' in requirements:
Augie Fackler
formatting: blacken the codebase...
r43346 return storemod.fncachestore(
path, vfstype, b'dotencode' in requirements
)
Gregory Szorc
localrepo: move store() from store module...
r39734
return storemod.encodedstore(path, vfstype)
return storemod.basicstore(path, vfstype)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 def resolvestorevfsoptions(ui, requirements, features):
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 """Resolve the options to pass to the store vfs opener.
The returned dict is used to influence behavior of the storage layer.
"""
options = {}
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 options[b'treemanifest'] = True
# experimental config: format.manifestcachesize
manifestcachesize = ui.configint(b'format', b'manifestcachesize')
if manifestcachesize is not None:
options[b'manifestcachesize'] = manifestcachesize
# In the absence of another requirement superseding a revlog-related
# requirement, we have to assume the repo is using revlog version 0.
# This revlog format is super old and we don't bother trying to parse
# opener options for it because those options wouldn't do anything
# meaningful on such old repos.
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 if (
b'revlogv1' in requirements
or requirementsmod.REVLOGV2_REQUIREMENT in requirements
):
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
Augie Fackler
formatting: blacken the codebase...
r43346 else: # explicitly mark repo as using revlogv0
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 options[b'revlogv0'] = True
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 if requirementsmod.COPIESSDC_REQUIREMENT in requirements:
sidedatacopies: write copies information in sidedata when applicable...
r43412 options[b'copies-storage'] = b'changeset-sidedata'
else:
writecopiesto = ui.config(b'experimental', b'copies.write-to')
copiesextramode = (b'changeset-only', b'compatibility')
if writecopiesto in copiesextramode:
options[b'copies-storage'] = b'extra'
copies: prepare changelog for more copies storage mode...
r43296
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 return options
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 def resolverevlogstorevfsoptions(ui, requirements, features):
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 """Resolve opener options specific to revlogs."""
options = {}
Matt Harbison
revlog: allow flag processors to be applied via store options...
r40303 options[b'flagprocessors'] = {}
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736
if b'revlogv1' in requirements:
options[b'revlogv1'] = True
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 if requirementsmod.REVLOGV2_REQUIREMENT in requirements:
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 options[b'revlogv2'] = True
if b'generaldelta' in requirements:
options[b'generaldelta'] = True
# experimental config: format.chunkcachesize
chunkcachesize = ui.configint(b'format', b'chunkcachesize')
if chunkcachesize is not None:
options[b'chunkcachesize'] = chunkcachesize
Augie Fackler
formatting: blacken the codebase...
r43346 deltabothparents = ui.configbool(
b'storage', b'revlog.optimize-delta-parent-choice'
)
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 options[b'deltabothparents'] = deltabothparents
storage: introduce a `revlog.reuse-external-delta` config...
r41985 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
lazydeltabase = False
if lazydelta:
Augie Fackler
formatting: blacken the codebase...
r43346 lazydeltabase = ui.configbool(
b'storage', b'revlog.reuse-external-delta-parent'
)
storage: introduce a `revlog.reuse-external-delta-parent` config...
r41984 if lazydeltabase is None:
lazydeltabase = not scmutil.gddeltaconfig(ui)
storage: introduce a `revlog.reuse-external-delta` config...
r41985 options[b'lazydelta'] = lazydelta
storage: introduce a `revlog.reuse-external-delta-parent` config...
r41984 options[b'lazydeltabase'] = lazydeltabase
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736
chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
if 0 <= chainspan:
options[b'maxdeltachainspan'] = chainspan
Augie Fackler
formatting: blacken the codebase...
r43346 mmapindexthreshold = ui.configbytes(b'experimental', b'mmapindexthreshold')
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 if mmapindexthreshold is not None:
options[b'mmapindexthreshold'] = mmapindexthreshold
withsparseread = ui.configbool(b'experimental', b'sparse-read')
Augie Fackler
formatting: blacken the codebase...
r43346 srdensitythres = float(
ui.config(b'experimental', b'sparse-read.density-threshold')
)
srmingapsize = ui.configbytes(b'experimental', b'sparse-read.min-gap-size')
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 options[b'with-sparse-read'] = withsparseread
options[b'sparse-read-density-threshold'] = srdensitythres
options[b'sparse-read-min-gap-size'] = srmingapsize
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 sparserevlog = requirementsmod.SPARSEREVLOG_REQUIREMENT in requirements
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 options[b'sparse-revlog'] = sparserevlog
if sparserevlog:
options[b'generaldelta'] = True
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 sidedata = requirementsmod.SIDEDATA_REQUIREMENT in requirements
sidedata: introduce a new requirement to protect the feature...
r43298 options[b'side-data'] = sidedata
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 maxchainlen = None
if sparserevlog:
maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
# experimental config: format.maxchainlen
maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
if maxchainlen is not None:
options[b'maxchainlen'] = maxchainlen
for r in requirements:
compression: introduce an official `zstd-revlog` requirement...
r42305 # we allow multiple compression engine requirement to co-exist because
# strickly speaking, revlog seems to support mixed compression style.
#
# The compression used for new entries will be "the last one"
prefix = r.startswith
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
options[b'compengine'] = r.split(b'-', 2)[2]
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736
compression: introduce a `storage.revlog.zlib.level` configuration...
r42210 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
if options[b'zlib.level'] is not None:
if not (0 <= options[b'zlib.level'] <= 9):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'invalid value for `storage.revlog.zlib.level` config: %d')
compression: introduce a `storage.revlog.zlib.level` configuration...
r42210 raise error.Abort(msg % options[b'zlib.level'])
compression: introduce a `storage.revlog.zstd.level` configuration...
r42211 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
if options[b'zstd.level'] is not None:
if not (0 <= options[b'zstd.level'] <= 22):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
compression: introduce a `storage.revlog.zstd.level` configuration...
r42211 raise error.Abort(msg % options[b'zstd.level'])
compression: introduce a `storage.revlog.zlib.level` configuration...
r42210
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirementsmod.NARROW_REQUIREMENT in requirements:
Gregory Szorc
localrepo: enable ellipsis flag on revlogs when repo is narrow...
r39806 options[b'enableellipsis'] = True
Matt Harbison
py3: byteify some `ui.configbool()` parameters...
r44495 if ui.configbool(b'experimental', b'rust.index'):
Georges Racinet
rust-index: add a `experimental.rust.index` option to use the wrapper...
r44466 options[b'rust.index'] = True
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 if requirementsmod.NODEMAP_REQUIREMENT in requirements:
nodemap: drop the 'exp-' prefix for internal opener option...
r45296 options[b'persistent-nodemap'] = True
nodemap: move the option for mmap usage to storage.revlog.nodemap.mmap...
r45299 if ui.configbool(b'storage', b'revlog.nodemap.mmap'):
nodemap: drop the 'exp-' prefix for internal opener option...
r45296 options[b'persistent-nodemap.mmap'] = True
nodemap: move the mode option to storage.revlog.nodemap.mode...
r45300 epnm = ui.config(b'storage', b'revlog.nodemap.mode')
nodemap: drop the 'exp-' prefix for internal opener option...
r45296 options[b'persistent-nodemap.mode'] = epnm
nodemap: add a (python) index class for persistent nodemap testing...
r44794 if ui.configbool(b'devel', b'persistent-nodemap'):
options[b'devel-force-nodemap'] = True
Georges Racinet
rust-index: add a `experimental.rust.index` option to use the wrapper...
r44466
Gregory Szorc
localrepo: extract resolving of opener options to standalone functions...
r39736 return options
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 def makemain(**kwargs):
"""Produce a type conforming to ``ilocalrepositorymain``."""
return localrepository
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
class revlogfilestorage(object):
"""File storage when using revlogs."""
def file(self, path):
if path[0] == b'/':
path = path[1:]
return filelog.filelog(self.svfs, path)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
filelog: custom filelog to be used with narrow repos...
r39801 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
class revlognarrowfilestorage(object):
"""File storage when using revlogs and narrow files."""
def file(self, path):
if path[0] == b'/':
path = path[1:]
Martin von Zweigbergk
narrow: extract repo property for store narrowmatcher...
r41266 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
Gregory Szorc
filelog: custom filelog to be used with narrow repos...
r39801
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 def makefilestorage(requirements, features, **kwargs):
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
Gregory Szorc
localrepo: add repository feature when repo can be stream cloned...
r40063 features.add(repository.REPO_FEATURE_STREAM_CLONE)
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirementsmod.NARROW_REQUIREMENT in requirements:
Gregory Szorc
filelog: custom filelog to be used with narrow repos...
r39801 return revlognarrowfilestorage
else:
return revlogfilestorage
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 # List of repository interfaces and factory functions for them. Each
# will be called in order during ``makelocalrepository()`` to iteratively
Gregory Szorc
localrepo: capture repo interface factory functions as lambas...
r40030 # derive the final type for a local repository instance. We capture the
# function as a lambda so we don't hold a reference and the module-level
# functions can be wrapped.
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 REPO_INTERFACES = [
Gregory Szorc
localrepo: capture repo interface factory functions as lambas...
r40030 (repository.ilocalrepositorymain, lambda: makemain),
(repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 ]
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 @interfaceutil.implementer(repository.ilocalrepositorymain)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 class localrepository(object):
Gregory Szorc
localrepo: iteratively derive local repository type...
r39800 """Main class for representing local repositories.
All local repositories are instances of this class.
Constructed on its own, instances of this class are not usable as
repository objects. To obtain a usable repository object, call
``hg.repository()``, ``localrepo.instance()``, or
``localrepo.makelocalrepository()``. The latter is the lowest-level.
``instance()`` adds support for creating new repositories.
``hg.repository()`` adds more extension integration, including calling
``reposetup()``. Generally speaking, ``hg.repository()`` should be
used.
"""
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 # obsolete experimental requirements:
# - manifestv2: An experimental new manifest format that allowed
# for stem compression of long paths. Experiment ended up not
# being successful (repository sizes went up due to worse delta
# chains), and the code was deleted in 4.6.
Gregory Szorc
localrepo: reformat set literals...
r32315 supportedformats = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'revlogv1',
b'generaldelta',
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirementsmod.TREEMANIFEST_REQUIREMENT,
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 requirementsmod.COPIESSDC_REQUIREMENT,
requirementsmod.REVLOGV2_REQUIREMENT,
requirementsmod.SIDEDATA_REQUIREMENT,
requirementsmod.SPARSEREVLOG_REQUIREMENT,
requirementsmod.NODEMAP_REQUIREMENT,
Martin von Zweigbergk
bookmarks: keep bookmarks in .hg/store if new config set...
r42512 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
Pulkit Goyal
share: introduce config option to store requires in .hg/store...
r46055 requirementsmod.SHARESAFE_REQUIREMENT,
Gregory Szorc
localrepo: reformat set literals...
r32315 }
_basesupported = supportedformats | {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'store',
b'fncache',
Pulkit Goyal
requirements: introduce constants for `shared` and `relshared` requirements...
r45946 requirementsmod.SHARED_REQUIREMENT,
requirementsmod.RELATIVE_SHARED_REQUIREMENT,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'dotencode',
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirementsmod.SPARSE_REQUIREMENT,
requirementsmod.INTERNAL_PHASE_REQUIREMENT,
Gregory Szorc
localrepo: reformat set literals...
r32315 }
Bryan O'Sullivan
localrepo: make requirements and openerreqs mutable by subclasses...
r17137
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 # list of prefix for file which can be written without 'wlock'
# Extensions should extend this list when needed
_wlockfreeprefix = {
# We migh consider requiring 'wlock' for the next
# two, but pretty much all the existing code assume
# wlock is not needed so we keep them excluded for
# now.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'hgrc',
b'requires',
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 # XXX cache is a complicatged business someone
# should investigate this in depth at some point
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cache/',
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 # XXX shouldn't be dirstate covered by the wlock?
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'dirstate',
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 # XXX bisect was still a bit too messy at the time
# this changeset was introduced. Someone should fix
# the remainig bit and drop this line
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'bisect.state',
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 }
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self,
baseui,
ui,
origroot,
wdirvfs,
hgvfs,
requirements,
supportedrequirements,
sharedpath,
store,
cachevfs,
wcachevfs,
features,
intents=None,
):
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 """Create a new local repository instance.
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
or ``localrepo.makelocalrepository()`` for obtaining a new repository
object.
Arguments:
baseui
Gregory Szorc
localrepo: copy ui in makelocalrepository()...
r39725 ``ui.ui`` instance that ``ui`` argument was based off of.
ui
``ui.ui`` instance for use by the repository.
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724
origroot
``bytes`` path to working directory root of this repository.
wdirvfs
``vfs.vfs`` rooted at the working directory.
hgvfs
``vfs.vfs`` rooted at .hg/
Gregory Szorc
localrepo: read requirements file in makelocalrepository()...
r39728 requirements
``set`` of bytestrings representing repository opening requirements.
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 supportedrequirements
``set`` of bytestrings representing repository requirements that we
know how to open. May be a supetset of ``requirements``.
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 sharedpath
``bytes`` Defining path to storage base directory. Points to a
``.hg/`` directory somewhere.
store
``store.basicstore`` (or derived) instance providing access to
versioned storage.
cachevfs
``vfs.vfs`` used for cache files.
Boris Feld
repo: add a `wcachevfs` to access the `.hg/wcache/` directory...
r40826 wcachevfs
``vfs.vfs`` used for cache files related to the working copy.
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 features
``set`` of bytestrings defining features/capabilities of this
instance.
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724 intents
``set`` of system strings indicating what this repo will be used
for.
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 """
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724 self.baseui = baseui
Gregory Szorc
localrepo: copy ui in makelocalrepository()...
r39725 self.ui = ui
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724 self.origroot = origroot
# vfs rooted at working directory.
self.wvfs = wdirvfs
self.root = wdirvfs.base
# vfs rooted at .hg/. Used to access most non-store paths.
self.vfs = hgvfs
self.path = hgvfs.base
Gregory Szorc
localrepo: validate supported requirements in makelocalrepository()...
r39729 self.requirements = requirements
self.supported = supportedrequirements
Gregory Szorc
localrepo: resolve store and cachevfs in makelocalrepository()...
r39733 self.sharedpath = sharedpath
self.store = store
self.cachevfs = cachevfs
Boris Feld
repo: add a `wcachevfs` to access the `.hg/wcache/` directory...
r40826 self.wcachevfs = wcachevfs
Gregory Szorc
localrepo: define "features" on repository instances (API)...
r39886 self.features = features
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
Gregory Szorc
localrepo: move filtername to __init__...
r32730 self.filtername = None
Gregory Szorc
localrepo: move some vfs initialization out of __init__...
r39724
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
b'devel', b'check-locks'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 self.vfs.audit = self._getvfsward(self.vfs.audit)
Pierre-Yves David
phases: mechanism to allow extension to alter initial computation of phase...
r15922 # A list of callback to shape the phase if no data were found.
# Callback are in the form: func(repo, roots) --> processed root.
# This list it to be filled by extension during repo setup
self._phasedefaults = []
mpm@selenic.com
Break apart hg.py...
r1089
Pierre-Yves David
color: initialize color for the localrepo ui...
r31111 color.setup(self.ui)
FUJIWARA Katsunori
localrepo: make supported features manageable in each repositories individually...
r19778
Adrian Buehlmann
introduce store classes...
r6840 self.spath = self.store.path
FUJIWARA Katsunori
localrepo: use "vfs" constructor/field for initialization around "store"
r17654 self.svfs = self.store.vfs
Adrian Buehlmann
introduce store classes...
r6840 self.sjoin = self.store.join
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
b'devel', b'check-locks'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(self.svfs, b'vfs'): # this is filtervfs
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
Augie Fackler
formatting: blacken the codebase...
r43346 else: # standard vfs
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 self.svfs.audit = self._getsvfsward(self.svfs.audit)
Benoit Boissinot
move code around
r3850
Siddharth Agarwal
localrepo: move dirstate validate function to class scope...
r26155 self._dirstatevalidatewarned = False
Greg Ward
localrepo: rename in-memory tag cache instance attributes (issue548)....
r9146
Martijn Pieters
branchmap: encapsulate cache updating in the map itself...
r41764 self._branchcaches = branchmap.BranchMapCache()
Durham Goode
revbranchcache: move out of branchmap onto localrepo...
r24373 self._revbranchcache = None
Gregory Szorc
localrepo: make filterpats private (API)...
r37155 self._filterpats = {}
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 self._datafilters = {}
Matt Mackall
Use a weakref for recursive transactions
r4916 self._transref = self._lockref = self._wlockref = None
mpm@selenic.com
Break apart hg.py...
r1089
Idan Kamara
localrepo: add a cache with stat info for files under .hg/
r14929 # A cache for various files under .hg/ that tracks file changes,
# (used by the filecache decorator)
#
# Maps a property name to its util.filecacheentry
self._filecache = {}
Pierre-Yves David
clfilter: add a cache on repo for set of revision to filter for a given set....
r18101 # hold sets of revision to be filtered
# should be cleared when something might have changed the filter value:
# - new changesets,
# - phase change,
# - new obsolescence marker,
# - working directory parent change,
# - bookmark changes
self.filteredrevcache = {}
Siddharth Agarwal
workingctx: add a way for extensions to run code at status fixup time...
r32814 # post-dirstate-status hooks
self._postdsstatus = []
Sean Farley
namespaces: add bookmarks to the names data structure...
r23558 # generic mapping between names and nodes
Ryan McElroy
namespaces: remove weakref; always pass in repo...
r23561 self.names = namespaces.namespaces()
Sean Farley
namespaces: add bookmarks to the names data structure...
r23558
Gregory Szorc
localrepo: add sparse caches...
r33302 # Key to signature value.
self._sparsesignaturecache = {}
# Signature to cached matcher instance.
self._sparsematchercache = {}
repoview: introduce a `experimental.extra-filter-revs` config...
r42417 self._extrafilterid = repoview.extrafilter(ui)
sidedatacopies: write copies information in sidedata when applicable...
r43412 self.filecopiesmode = None
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
sidedatacopies: write copies information in sidedata when applicable...
r43412 self.filecopiesmode = b'changeset-sidedata'
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 def _getvfsward(self, origfunc):
"""build a ward for self.vfs"""
rref = weakref.ref(self)
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 def checkvfs(path, mode=None):
ret = origfunc(path, mode=mode)
repo = rref()
Augie Fackler
formatting: blacken the codebase...
r43346 if (
repo is None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or not util.safehasattr(repo, b'_wlockref')
or not util.safehasattr(repo, b'_lockref')
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if mode in (None, b'r', b'rb'):
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 return
if path.startswith(repo.path):
# truncate name relative to the repository (.hg)
Augie Fackler
formatting: blacken the codebase...
r43346 path = path[len(repo.path) + 1 :]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if path.startswith(b'cache/'):
msg = b'accessing cache with vfs instead of cachevfs: "%s"'
repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs")
Martin von Zweigbergk
locks: expect repo lock, not wlock, when writing to .hg/strip-backup/...
r45554 # path prefixes covered by 'lock'
Pulkit Goyal
localrepo: warn if we are writing to cache without a lock...
r46003 vfs_path_prefixes = (
b'journal.',
b'undo.',
b'strip-backup/',
b'cache/',
)
Martin von Zweigbergk
locks: expect repo lock, not wlock, when writing to .hg/strip-backup/...
r45554 if any(path.startswith(prefix) for prefix in vfs_path_prefixes):
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 if repo._currentlock(repo._lockref) is None:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.develwarn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'write with no lock: "%s"' % path,
Augie Fackler
formatting: blacken the codebase...
r43346 stacklevel=3,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 config=b'check-locks',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 elif repo._currentlock(repo._wlockref) is None:
# rest of vfs files are covered by 'wlock'
#
# exclude special files
for prefix in self._wlockfreeprefix:
if path.startswith(prefix):
return
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.develwarn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'write with no wlock: "%s"' % path,
Augie Fackler
formatting: blacken the codebase...
r43346 stacklevel=3,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 config=b'check-locks',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 return ret
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 return checkvfs
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 def _getsvfsward(self, origfunc):
"""build a ward for self.svfs"""
rref = weakref.ref(self)
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 def checksvfs(path, mode=None):
ret = origfunc(path, mode=mode)
repo = rref()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo is None or not util.safehasattr(repo, b'_lockref'):
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if mode in (None, b'r', b'rb'):
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 return
if path.startswith(repo.sharedpath):
# truncate name relative to the repository (.hg)
Augie Fackler
formatting: blacken the codebase...
r43346 path = path[len(repo.sharedpath) + 1 :]
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 if repo._currentlock(repo._lockref) is None:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.develwarn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'write with no lock: "%s"' % path, stacklevel=4
Augie Fackler
formatting: blacken the codebase...
r43346 )
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 return ret
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 return checksvfs
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def close(self):
Durham Goode
revbranchcache: write cache even during read operations...
r24378 self._writecaches()
def _writecaches(self):
if self._revbranchcache:
self._revbranchcache.write()
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def _restrictcapabilities(self, caps):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.ui.configbool(b'experimental', b'bundle2-advertise'):
Pierre-Yves David
bundle2: allow pulling changegroups using bundle2...
r20955 caps = set(caps)
Augie Fackler
formatting: blacken the codebase...
r43346 capsblob = bundle2.encodecaps(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bundle2.getrepocaps(self, role=b'client')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 caps.add(b'bundle2=' + urlreq.quote(capsblob))
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 return caps
Yuya Nishihara
localrepo: do not cache auditor/nofsauditor which would make reference cycle...
r39348 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
# self -> auditor -> self._checknested -> self
@property
def auditor(self):
# This is only used by context.workingctx.match in order to
# detect files in subrepos.
return pathutil.pathauditor(self.root, callback=self._checknested)
@property
def nofsauditor(self):
# This is only used by context.basectx.match in order to detect
# files in subrepos.
Augie Fackler
formatting: blacken the codebase...
r43346 return pathutil.pathauditor(
self.root, callback=self._checknested, realfs=False, cached=True
)
Yuya Nishihara
localrepo: do not cache auditor/nofsauditor which would make reference cycle...
r39348
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162 def _checknested(self, path):
"""Determine if path is a legal nested repository."""
if not path.startswith(self.root):
return False
Augie Fackler
formatting: blacken the codebase...
r43346 subpath = path[len(self.root) + 1 :]
FUJIWARA Katsunori
windows: use normalized path to check repository nesting...
r15722 normsubpath = util.pconvert(subpath)
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162
# XXX: Checking against the current working copy is wrong in
# the sense that it can reject things like
#
# $ hg cat -r 10 sub/x.txt
#
# if sub/ is no longer a subrepository in the working copy
# parent revision.
#
# However, it can of course also allow things that would have
# been rejected before, such as the above cat command if sub/
# is a subrepository now, but was a normal directory before.
# The old path auditor would have rejected by mistake since it
# panics when it sees sub/.hg/.
#
Martin Geisler
localrepo: check nested repos against working directory...
r12174 # All in all, checking against the working copy seems sensible
# since we want to prevent access to nested repositories on
# the filesystem *now*.
ctx = self[None]
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162 parts = util.splitpath(subpath)
while parts:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix = b'/'.join(parts)
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162 if prefix in ctx.substate:
FUJIWARA Katsunori
windows: use normalized path to check repository nesting...
r15722 if prefix == normsubpath:
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162 return True
else:
sub = ctx.sub(prefix)
Augie Fackler
formatting: blacken the codebase...
r43346 return sub.checknested(subpath[len(prefix) + 1 :])
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162 else:
parts.pop()
return False
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def peer(self):
Augie Fackler
formatting: blacken the codebase...
r43346 return localpeer(self) # not cached to avoid reference cycle
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Pierre-Yves David
clfilter: introduce an "unfiltered" method on localrepo...
r17993 def unfiltered(self):
"""Return unfiltered version of the repository
Mads Kiilerich
spelling: fix some minor issues found by spell checker
r18644 Intended to be overwritten by filtered repo."""
Pierre-Yves David
clfilter: introduce an "unfiltered" method on localrepo...
r17993 return self
Pulkit Goyal
repoview: add visibilityexceptions as an optional argument to repo.filtered()...
r35508 def filtered(self, name, visibilityexceptions=None):
repoview: improve documentation for `repo.filtered` method...
r42274 """Return a filtered version of a repository
The `name` parameter is the identifier of the requested view. This
will return a repoview object set "exactly" to the specified view.
This function does not apply recursive filtering to a repository. For
example calling `repo.filtered("served")` will return a repoview using
the "served" view, regardless of the initial view used by `repo`.
In other word, there is always only one level of `repoview` "filtering".
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._extrafilterid is not None and b'%' not in name:
name = name + b'%' + self._extrafilterid
repoview: introduce a `experimental.extra-filter-revs` config...
r42417
Yuya Nishihara
repoview: extract a factory function of proxy class...
r35248 cls = repoview.newtype(self.unfiltered().__class__)
Pulkit Goyal
repoview: add visibilityexceptions as an optional argument to repo.filtered()...
r35508 return cls(self, name, visibilityexceptions)
Pierre-Yves David
clfilter: add actual repo filtering mechanism...
r18100
Augie Fackler
formatting: blacken the codebase...
r43346 @mixedrepostorecache(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'bookmarks', b'plain'),
(b'bookmarks.current', b'plain'),
(b'bookmarks', b''),
(b'00changelog.i', b''),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
bookmarks: move property methods into localrepo
r13355 def _bookmarks(self):
bookmarks: actual fix for race condition deleting bookmark...
r42903 # Since the multiple files involved in the transaction cannot be
# written atomically (with current repository format), there is a race
# condition here.
#
# 1) changelog content A is read
# 2) outside transaction update changelog to content B
# 3) outside transaction update bookmark file referring to content B
# 4) bookmarks file content is read and filtered against changelog-A
#
# When this happens, bookmarks against nodes missing from A are dropped.
#
# Having this happening during read is not great, but it become worse
# when this happen during write because the bookmarks to the "unknown"
# nodes will be dropped for good. However, writes happen within locks.
# This locking makes it possible to have a race free consistent read.
# For this purpose data read from disc before locking are
# "invalidated" right after the locks are taken. This invalidations are
# "light", the `filecache` mechanism keep the data in memory and will
# reuse them if the underlying files did not changed. Not parsing the
# same data multiple times helps performances.
#
# Unfortunately in the case describe above, the files tracked by the
# bookmarks file cache might not have changed, but the in-memory
# content is still "wrong" because we used an older changelog content
# to process the on-disk data. So after locking, the changelog would be
# refreshed but `_bookmarks` would be preserved.
# Adding `00changelog.i` to the list of tracked file is not
# enough, because at the time we build the content for `_bookmarks` in
# (4), the changelog file has already diverged from the content used
# for loading `changelog` in (1)
#
# To prevent the issue, we force the changelog to be explicitly
# reloaded while computing `_bookmarks`. The data race can still happen
# without the lock (with a narrower window), but it would no longer go
# undetected during the lock time refresh.
#
# The new schedule is as follow
#
# 1) filecache logic detect that `_bookmarks` needs to be computed
# 2) cachestat for `bookmarks` and `changelog` are captured (for book)
# 3) We force `changelog` filecache to be tested
# 4) cachestat for `changelog` are captured (for changelog)
# 5) `_bookmarks` is computed and cached
#
# The step in (3) ensure we have a changelog at least as recent as the
# cache stat computed in (1). As a result at locking time:
# * if the changelog did not changed since (1) -> we can reuse the data
# * otherwise -> the bookmarks get refreshed.
self._refreshchangelog()
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 return bookmarks.bmstore(self)
Matt Mackall
bookmarks: move property methods into localrepo
r13355
localrepo: introduce a `_refreshchangelog` method...
r42710 def _refreshchangelog(self):
"""make sure the in memory changelog match the on-disk one"""
Gregory Szorc
localrepo: use str for lookup in vars()...
r43732 if 'changelog' in vars(self) and self.currenttransaction() is None:
localrepo: introduce a `_refreshchangelog` method...
r42710 del self.changelog
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 @property
Ryan McElroy
bookmarks: rename bookmarkcurrent to activebookmark (API)...
r24947 def _activebookmark(self):
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 return self._bookmarks.active
Martin Geisler
localrepo: add auditor attribute which knows about subrepos
r12162
Joerg Sonnenberger
phases: drop the list with phase of each rev, always comput phase sets...
r35310 # _phasesets depend on changelog. what we need is to call
# _phasecache.invalidate() if '00changelog.i' was changed, but it
Yuya Nishihara
localrepo: recreate phasecache if changelog was modified (issue4855)...
r26405 # can't be easily expressed in filecache mechanism.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @storecache(b'phaseroots', b'00changelog.i')
Patrick Mezard
phases: introduce phasecache...
r16657 def _phasecache(self):
return phases.phasecache(self, self._phasedefaults)
Pierre-Yves David
phases: add a cache allowing to know in which phase a changeset is
r15420
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @storecache(b'obsstore')
Pierre-Yves.David@ens-lyon.org
obsolete: introduction of obsolete markers...
r17070 def obsstore(self):
Gregory Szorc
obsolete: move obsstore creation logic from localrepo...
r32729 return obsolete.makestore(self.ui, self)
Pierre-Yves.David@ens-lyon.org
obsolete: introduction of obsolete markers...
r17070
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @storecache(b'00changelog.i')
Matt Mackall
localrepo: use propertycache
r8260 def changelog(self):
dirstate: make sure the dirstate is loaded before the changelog (issue6303)...
r45359 # load dirstate before changelog to avoid race see issue6303
self.dirstate.prefetch_parents()
Augie Fackler
localrepo: push manifestlog and changelog construction code into store...
r43175 return self.store.changelog(txnutil.mayhavepending(self.root))
Matt Mackall
localrepo: use propertycache
r8260
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @storecache(b'00manifest.i')
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 def manifestlog(self):
Augie Fackler
localrepo: push manifestlog and changelog construction code into store...
r43175 return self.store.manifestlog(self, self._storenarrowmatch)
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @repofilecache(b'dirstate')
Matt Mackall
localrepo: use propertycache
r8260 def dirstate(self):
Kyle Lippincott
narrow: only wrap dirstate functions once, instead of per-reposetup...
r38142 return self._makedirstate()
def _makedirstate(self):
Kyle Lippincott
localrepo: add docstring to _makedirstate to make it less likely to be removed...
r38147 """Extension point for wrapping the dirstate per-repo."""
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 sparsematchfn = lambda: sparse.matcher(self)
Augie Fackler
formatting: blacken the codebase...
r43346 return dirstate.dirstate(
self.vfs, self.ui, self.root, self._dirstatevalidate, sparsematchfn
)
Matt Mackall
dirstate: warn on invalid parents rather than aborting...
r13032
Siddharth Agarwal
localrepo: move dirstate validate function to class scope...
r26155 def _dirstatevalidate(self, node):
try:
self.changelog.rev(node)
return node
except error.LookupError:
if not self._dirstatevalidatewarned:
self._dirstatevalidatewarned = True
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.warn(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"warning: ignoring unknown working parent %s!\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % short(node)
)
Siddharth Agarwal
localrepo: move dirstate validate function to class scope...
r26155 return nullid
Vadim Gelfer
support hooks written in python....
r2155
Martin von Zweigbergk
narrow: move .hg/narrowspec to .hg/store/narrowspec (BC)...
r38908 @storecache(narrowspec.FILENAME)
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489 def narrowpats(self):
"""matcher patterns for this repository's narrowspec
A tuple of (includes, excludes).
"""
Martin von Zweigbergk
narrow: remove hack to read narowspec from shared .hg directory...
r39794 return narrowspec.load(self)
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489
Martin von Zweigbergk
narrow: move .hg/narrowspec to .hg/store/narrowspec (BC)...
r38908 @storecache(narrowspec.FILENAME)
Martin von Zweigbergk
narrow: extract repo property for store narrowmatcher...
r41266 def _storenarrowmatch(self):
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 return matchmod.always()
Martin von Zweigbergk
narrow: extract repo property for store narrowmatcher...
r41266 include, exclude = self.narrowpats
return narrowspec.match(self.root, include=include, exclude=exclude)
@storecache(narrowspec.FILENAME)
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489 def _narrowmatch(self):
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 return matchmod.always()
Martin von Zweigbergk
narrow: detect if narrowspec was changed in a different share...
r41072 narrowspec.checkworkingcopynarrowspec(self)
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489 include, exclude = self.narrowpats
return narrowspec.match(self.root, include=include, exclude=exclude)
Martin von Zweigbergk
narrow: allow repo.narrowmatch(match) to include exact matches from "match"...
r40122 def narrowmatch(self, match=None, includeexact=False):
Martin von Zweigbergk
localrepo: allow narrowmatch() to accept matcher to intersect with...
r40118 """matcher corresponding the the repo's narrowspec
If `match` is given, then that will be intersected with the narrow
matcher.
Martin von Zweigbergk
narrow: allow repo.narrowmatch(match) to include exact matches from "match"...
r40122
If `includeexact` is True, then any exact matches from `match` will
be included even if they're outside the narrowspec.
Martin von Zweigbergk
localrepo: allow narrowmatch() to accept matcher to intersect with...
r40118 """
if match:
Martin von Zweigbergk
narrow: allow repo.narrowmatch(match) to include exact matches from "match"...
r40122 if includeexact and not self._narrowmatch.always():
# do not exclude explicitly-specified paths so that they can
# be warned later on
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 em = matchmod.exact(match.files())
Martin von Zweigbergk
narrow: allow repo.narrowmatch(match) to include exact matches from "match"...
r40122 nm = matchmod.unionmatcher([self._narrowmatch, em])
return matchmod.intersectmatchers(match, nm)
Martin von Zweigbergk
localrepo: allow narrowmatch() to accept matcher to intersect with...
r40118 return matchmod.intersectmatchers(match, self._narrowmatch)
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489 return self._narrowmatch
def setnarrowpats(self, newincludes, newexcludes):
Yuya Nishihara
narrow: remove hack to write narrowspec to shared .hg directory...
r39593 narrowspec.save(self, newincludes, newexcludes)
Martin von Zweigbergk
narrow: move narrowmatch-related methods to localrepo...
r36489 self.invalidate(clearfilecache=True)
localrepo: also fastpath access to working copy parents when possible...
r44563 @unfilteredpropertycache
def _quick_access_changeid_null(self):
return {
b'null': (nullrev, nullid),
nullrev: (nullrev, nullid),
nullid: (nullrev, nullid),
}
@unfilteredpropertycache
def _quick_access_changeid_wc(self):
# also fast path access to the working copy parents
# however, only do it for filter that ensure wc is visible.
Kyle Lippincott
repo: avoid copying/updating a dict on every `repo.__getitem__`...
r46036 quick = self._quick_access_changeid_null.copy()
localrepo: also fastpath access to working copy parents when possible...
r44563 cl = self.unfiltered().changelog
for node in self.dirstate.parents():
if node == nullid:
continue
rev = cl.index.get_rev(node)
if rev is None:
# unknown working copy parent case:
#
# skip the fast path and let higher code deal with it
continue
pair = (rev, node)
quick[rev] = pair
quick[node] = pair
localrepo: also fast past the parents of working copies parents...
r44566 # also add the parents of the parents
for r in cl.parentrevs(rev):
if r == nullrev:
continue
n = cl.node(r)
pair = (r, n)
quick[r] = pair
quick[n] = pair
localrepo: fastpath access to "."...
r44564 p1node = self.dirstate.p1()
if p1node != nullid:
quick[b'.'] = quick[p1node]
localrepo: also fastpath access to working copy parents when possible...
r44563 return quick
@unfilteredmethod
def _quick_access_changeid_invalidate(self):
if '_quick_access_changeid_wc' in vars(self):
del self.__dict__['_quick_access_changeid_wc']
@property
localrepo: introduce a `_quick_access_changeid` property...
r44204 def _quick_access_changeid(self):
"""an helper dictionnary for __getitem__ calls
This contains a list of symbol we can recognise right away without
further processing.
"""
localrepo: also fastpath access to working copy parents when possible...
r44563 if self.filtername in repoview.filter_has_wc:
Kyle Lippincott
repo: avoid copying/updating a dict on every `repo.__getitem__`...
r46036 return self._quick_access_changeid_wc
return self._quick_access_changeid_null
localrepo: introduce a `_quick_access_changeid` property...
r44204
Matt Mackall
use repo[changeid] to get a changectx
r6747 def __getitem__(self, changeid):
localrepo: add some basic comment for block in __getitem__...
r44189 # dealing with special cases
Yuya Nishihara
localrepo: map integer and hex wdir identifiers to workingctx...
r32658 if changeid is None:
Matt Mackall
use repo[changeid] to get a changectx
r6747 return context.workingctx(self)
Martin von Zweigbergk
context: move reuse of context object to repo.__getitem__ (API)...
r37191 if isinstance(changeid, context.basectx):
return changeid
localrepo: add some basic comment for block in __getitem__...
r44189
# dealing with multiple revisions
Eric Sumner
localrepo.__getitem__: add slicing support...
r23630 if isinstance(changeid, slice):
Yuya Nishihara
localrepo: map integer and hex wdir identifiers to workingctx...
r32658 # wdirrev isn't contiguous so the slice shouldn't include it
Augie Fackler
formatting: blacken the codebase...
r43346 return [
self[i]
for i in pycompat.xrange(*changeid.indices(len(self)))
if i not in self.changelog.filteredrevs
]
localrepo: add some basic comment for block in __getitem__...
r44189
localrepo: extract handling of some special value in __getitem__...
r44190 # dealing with some special values
localrepo: introduce a `_quick_access_changeid` property...
r44204 quick_access = self._quick_access_changeid.get(changeid)
if quick_access is not None:
rev, node = quick_access
return context.changectx(self, rev, node, maybe_filtered=False)
localrepo: extract handling of some special value in __getitem__...
r44191 if changeid == b'tip':
node = self.changelog.tip()
rev = self.changelog.rev(node)
return context.changectx(self, rev, node)
localrepo: add some basic comment for block in __getitem__...
r44189 # dealing with arbitrary values
Yuya Nishihara
localrepo: map integer and hex wdir identifiers to workingctx...
r32658 try:
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 if isinstance(changeid, int):
node = self.changelog.node(changeid)
rev = changeid
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif changeid == b'.':
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 # this is a hack to delay/avoid loading obsmarkers
# when we know that '.' won't be hidden
node = self.dirstate.p1()
rev = self.unfiltered().changelog.rev(node)
elif len(changeid) == 20:
try:
node = changeid
rev = self.changelog.rev(changeid)
except error.FilteredLookupError:
Augie Fackler
formatting: blacken the codebase...
r43346 changeid = hex(changeid) # for the error message
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 raise
except LookupError:
# check if it might have come from damaged dirstate
#
# XXX we could avoid the unfiltered if we had a recognizable
# exception for filtered changeset access
Augie Fackler
formatting: blacken the codebase...
r43346 if (
self.local()
and changeid in self.unfiltered().dirstate.parents()
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"working directory has unknown parent '%s'!")
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 raise error.Abort(msg % short(changeid))
Augie Fackler
formatting: blacken the codebase...
r43346 changeid = hex(changeid) # for the error message
Martin von Zweigbergk
repo: remove the last few "pass" statements in localrepo.__getitem__...
r40099 raise
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994
elif len(changeid) == 40:
Martin von Zweigbergk
repo: remove the last few "pass" statements in localrepo.__getitem__...
r40099 node = bin(changeid)
rev = self.changelog.rev(node)
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 else:
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"unsupported changeid '%s' of type %s"
Manuel Jacob
py3: use pycompat.bytestr() instead of pycompat.sysstr()...
r44109 % (changeid, pycompat.bytestr(type(changeid)))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994
Martin von Zweigbergk
repo: create changectx in a single place in localrepo.__getitem__...
r40100 return context.changectx(self, rev, node)
Martin von Zweigbergk
context: move logic from changectx.__init__ to localrepo.__getitem__ (API)...
r39994 except (error.FilteredIndexError, error.FilteredLookupError):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.FilteredRepoLookupError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"filtered revision '%s'") % pycompat.bytestr(changeid)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
repo: remove the last few "pass" statements in localrepo.__getitem__...
r40099 except (IndexError, LookupError):
Augie Fackler
localrepo: ensure we properly %-format int in exception throw...
r40389 raise error.RepoLookupError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"unknown revision '%s'") % pycompat.bytestr(changeid)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
localrepo: map integer and hex wdir identifiers to workingctx...
r32658 except error.WdirUnsupported:
return context.workingctx(self)
Matt Mackall
use repo[changeid] to get a changectx
r6747
Alexander Solovyov
localrepo: support 'rev in repo' syntax
r9924 def __contains__(self, changeid):
Yuya Nishihara
localrepo: document that __contains__() may raise LookupError
r32481 """True if the given changeid exists
Martin von Zweigbergk
revlog: use specialized exception for ambiguous prefix lookup...
r38877 error.AmbiguousPrefixLookupError is raised if an ambiguous node
specified.
Yuya Nishihara
localrepo: document that __contains__() may raise LookupError
r32481 """
Alexander Solovyov
localrepo: support 'rev in repo' syntax
r9924 try:
Yuya Nishihara
localrepo: extend "changeid in repo" to return True for workingctx revision...
r24320 self[changeid]
return True
Yuya Nishihara
context: translate FilteredIndex/LookupError at repo[changeid] (API)...
r37815 except error.RepoLookupError:
Alexander Solovyov
localrepo: support 'rev in repo' syntax
r9924 return False
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 def __nonzero__(self):
return True
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 def __len__(self):
Yuya Nishihara
localrepo: micro-optimize __len__() to bypass repoview...
r35754 # no need to pay the cost of repoview.changelog
unfi = self.unfiltered()
return len(unfi.changelog)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750
def __iter__(self):
Pierre-Yves David
clfilter: remove usage of `range` in favor of iteration over changelog...
r17675 return iter(self.changelog)
Vadim Gelfer
support hooks written in python....
r2155
Matt Mackall
localrepo: add revs helper method
r15403 def revs(self, expr, *args):
Gregory Szorc
localrepo: improve docstring for revset methods...
r27071 '''Find revisions matching a revset.
The revset is specified as a string ``expr`` that may contain
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 %-formatting to escape certain types. See ``revsetlang.formatspec``.
Gregory Szorc
localrepo: improve docstring for revset methods...
r27071
Gregory Szorc
scmutil: improve documentation of revset APIs...
r29417 Revset aliases from the configuration are not expanded. To expand
Yuya Nishihara
scmutil: proxy revrange() through repo to break import cycles...
r31025 user aliases, consider calling ``scmutil.revrange()`` or
``repo.anyrevs([expr], user=True)``.
Gregory Szorc
scmutil: improve documentation of revset APIs...
r29417
Matt Harbison
doc: fix references to `revset.abstractsmartset`...
r44532 Returns a smartset.abstractsmartset, which is a list-like interface
Gregory Szorc
localrepo: improve docstring for revset methods...
r27071 that contains integer revisions.
'''
Boris Feld
revset: introduce an API that avoids `formatspec` input serialization...
r41258 tree = revsetlang.spectree(expr, *args)
return revset.makematcher(tree)(self)
Matt Mackall
localrepo: add revs helper method
r15403
Matt Mackall
localrepo: add set method to iterate over a given revset...
r14902 def set(self, expr, *args):
Gregory Szorc
localrepo: improve docstring for revset methods...
r27071 '''Find revisions matching a revset and emit changectx instances.
This is a convenience wrapper around ``revs()`` that iterates the
result and is a generator of changectx instances.
Gregory Szorc
scmutil: improve documentation of revset APIs...
r29417
Revset aliases from the configuration are not expanded. To expand
user aliases, consider calling ``scmutil.revrange()``.
Matt Mackall
localrepo: add set method to iterate over a given revset...
r14902 '''
Matt Mackall
localrepo: add revs helper method
r15403 for r in self.revs(expr, *args):
Matt Mackall
localrepo: add set method to iterate over a given revset...
r14902 yield self[r]
Jun Wu
revset: make repo.anyrevs accept customized alias override (API)...
r33336 def anyrevs(self, specs, user=False, localalias=None):
Yuya Nishihara
scmutil: proxy revrange() through repo to break import cycles...
r31025 '''Find revisions matching one of the given revsets.
Revset aliases from the configuration are not expanded by default. To
Jun Wu
revset: make repo.anyrevs accept customized alias override (API)...
r33336 expand user aliases, specify ``user=True``. To provide some local
definitions overriding user aliases, set ``localalias`` to
``{name: definitionstring}``.
Yuya Nishihara
scmutil: proxy revrange() through repo to break import cycles...
r31025 '''
localrepo: recognize trivial "null" queries in `anyrev`...
r44197 if specs == [b'null']:
return revset.baseset([nullrev])
localrepo: recognize trivial request for '.'...
r44565 if specs == [b'.']:
quick_data = self._quick_access_changeid.get(b'.')
if quick_data is not None:
return revset.baseset([quick_data[0]])
Yuya Nishihara
scmutil: proxy revrange() through repo to break import cycles...
r31025 if user:
Augie Fackler
formatting: blacken the codebase...
r43346 m = revset.matchany(
self.ui,
specs,
lookup=revset.lookupfn(self),
localalias=localalias,
)
Yuya Nishihara
scmutil: proxy revrange() through repo to break import cycles...
r31025 else:
Jun Wu
revset: make repo.anyrevs accept customized alias override (API)...
r33336 m = revset.matchany(None, specs, localalias=localalias)
Yuya Nishihara
scmutil: proxy revrange() through repo to break import cycles...
r31025 return m(self)
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 def url(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'file:' + self.root
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673
Vadim Gelfer
make hook code nicer....
r1718 def hook(self, name, throw=False, **args):
Gregory Szorc
localrepo: document localrepo.hook()
r21866 """Call a hook, passing this repo instance.
This a convenience method to aid invoking hooks. Extensions likely
won't call this unless they have registered a custom hook or are
replacing code that is expected to call a hook.
"""
Matt Mackall
hooks: separate hook code into a separate module
r4622 return hook.hook(self.ui, self, name, throw, **args)
mpm@selenic.com
Break apart hg.py...
r1089
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 @filteredpropertycache
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 def _tagscache(self):
Brodie Rao
cleanup: eradicate long lines
r16683 '''Returns a tagscache object that contains various tags related
caches.'''
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936
# This simplifies its cache management by having one decorated
# function (this one) and the rest simply fetch things from it.
class tagscache(object):
def __init__(self):
# These two define the set of tags for this repository. tags
# maps tag name to node; tagtypes maps tag name to 'global' or
# 'local'. (Global tags are defined by .hgtags across all
# heads, and local tags are defined in .hg/localtags.)
# They constitute the in-memory cache of tags.
self.tags = self.tagtypes = None
self.nodetagscache = self.tagslist = None
cache = tagscache()
cache.tags, cache.tagtypes = self._findtags()
return cache
mpm@selenic.com
Break apart hg.py...
r1089 def tags(self):
'''return a mapping of tag to node'''
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 t = {}
Pierre-Yves David
clfilter: do not use tags cache if there are filtered changesets...
r17715 if self.changelog.filteredrevs:
tags, tt = self._findtags()
else:
tags = self._tagscache.tags
Boris Feld
tags: cache `repo.changelog` access when checking tags nodes...
r40776 rev = self.changelog.rev
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for k, v in pycompat.iteritems(tags):
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 try:
# ignore tags to unknown nodes
Boris Feld
tags: cache `repo.changelog` access when checking tags nodes...
r40776 rev(v)
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 t[k] = v
Bryan O'Sullivan
parsers: strictly check for 20-byte hashes where they're required
r16679 except (error.LookupError, ValueError):
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 pass
return t
Matt Mackall
Refactor tags code to prepare for improving the algorithm
r4210
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 def _findtags(self):
'''Do the hard work of finding tags. Return a pair of dicts
(tags, tagtypes) where tags maps tag name to node, and tagtypes
maps tag name to a string like \'global\' or \'local\'.
Subclasses or extensions are free to add their own tags, but
should be aware that the returned dicts will be retained for the
duration of the localrepo object.'''
# XXX what tagtype should subclasses/extensions use? Currently
# mq and bookmarks add tags, but do not set the tagtype at all.
# Should each extension invent its own tag type? Should there
# be one tagtype for all such "virtual" tags? Or is the status
# quo fine?
Matt Mackall
Refactor tags code to prepare for improving the algorithm
r4210
Pierre-Yves David
tags: only return 'alltags' in 'findglobaltags'...
r31709 # map tag name to (node, hist)
alltags = tagsmod.findglobaltags(self.ui, self)
# map tag name to tag type
Augie Fackler
cleanup: run pyupgrade on our source tree to clean up varying things...
r44937 tagtypes = {tag: b'global' for tag in alltags}
Pierre-Yves David
tags: do not feed dictionaries to 'findglobaltags'...
r31706
Benoit Boissinot
style: use consistent variable names (*mod) with imports which would shadow
r10651 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
Osku Salerma
Properly check tag's existence as a local/global tag when removing it.
r5657
Greg Ward
tags: support 'instant' tag retrieval (issue548)...
r9152 # Build the return dicts. Have to re-encode tag names because
# the tags module always uses UTF-8 (in order not to lose info
# writing to the cache), but the rest of Mercurial wants them in
# local encoding.
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 tags = {}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for (name, (node, hist)) in pycompat.iteritems(alltags):
Greg Ward
localrepo: improve readability of _findtags(), readtags() (issue548)....
r9147 if node != nullid:
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 tags[encoding.tolocal(name)] = node
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tags[b'tip'] = self.changelog.tip()
Augie Fackler
cleanup: run pyupgrade on our source tree to clean up varying things...
r44937 tagtypes = {
encoding.tolocal(name): value
for (name, value) in pycompat.iteritems(tagtypes)
}
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 return (tags, tagtypes)
mpm@selenic.com
Break apart hg.py...
r1089
Osku Salerma
Properly check tag's existence as a local/global tag when removing it.
r5657 def tagtype(self, tagname):
'''
return the type of the given tag. result can be:
'local' : a local tag
'global' : a global tag
None : tag does not exist
'''
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 return self._tagscache.tagtypes.get(tagname)
Osku Salerma
Properly check tag's existence as a local/global tag when removing it.
r5657
mpm@selenic.com
Break apart hg.py...
r1089 def tagslist(self):
'''return a list of tags ordered by revision'''
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 if not self._tagscache.tagslist:
l = []
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for t, n in pycompat.iteritems(self.tags()):
Mads Kiilerich
cleanup: fix some list comprehension redefinitions of existing vars...
r22201 l.append((self.changelog.rev(n), t, n))
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
return self._tagscache.tagslist
mpm@selenic.com
Break apart hg.py...
r1089
def nodetags(self, node):
'''return the tags associated with a node'''
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 if not self._tagscache.nodetagscache:
nodetagscache = {}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for t, n in pycompat.iteritems(self._tagscache.tags):
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 nodetagscache.setdefault(n, []).append(t)
Gregory Szorc
py3: define and use pycompat.itervalues()...
r43374 for tags in pycompat.itervalues(nodetagscache):
Eric Eisner
tags: return tags in sorted order...
r11047 tags.sort()
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 self._tagscache.nodetagscache = nodetagscache
return self._tagscache.nodetagscache.get(node, [])
mpm@selenic.com
Break apart hg.py...
r1089
David Soria Parra
context: add method to return all bookmarks pointing to a node
r13384 def nodebookmarks(self, node):
Augie Fackler
localrepo: document nodebookmarks
r27166 """return the list of bookmarks pointing to the specified node"""
Yuya Nishihara
bookmarks: extract function that looks up bookmark names by node
r37867 return self._bookmarks.names(node)
David Soria Parra
context: add method to return all bookmarks pointing to a node
r13384
Georg Brandl
localrepo: introduce method for explicit branch cache update...
r12066 def branchmap(self):
Mads Kiilerich
help: branch names primarily denote the tipmost unclosed branch head...
r20245 '''returns a dictionary {branch: [branchheads]} with branchheads
ordered by increasing revision number'''
Martijn Pieters
branchmap: encapsulate cache updating in the map itself...
r41764 return self._branchcaches[self]
Pierre-Yves David
clfilter: do not use branchmap cache if there are filtered changesets...
r17714
Durham Goode
revbranchcache: move out of branchmap onto localrepo...
r24373 @unfilteredmethod
def revbranchcache(self):
if not self._revbranchcache:
self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
return self._revbranchcache
Sean Farley
localrepo: add ignoremissing parameter to branchtip...
r23775 def branchtip(self, branch, ignoremissing=False):
'''return the tip node for a given branch
If ignoremissing is True, then this method will not raise an error.
This is helpful for callers that only expect None for a missing branch
(e.g. namespace).
'''
Brodie Rao
localrepo: refactor repo.branchtip() to use repo.branchmap().branchtip()
r20187 try:
return self.branchmap().branchtip(branch)
except KeyError:
Sean Farley
localrepo: add ignoremissing parameter to branchtip...
r23775 if not ignoremissing:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
Sean Farley
localrepo: add ignoremissing parameter to branchtip...
r23775 else:
pass
Brodie Rao
localrepo: add branchtip() method for faster single-branch lookups...
r16719
mpm@selenic.com
Break apart hg.py...
r1089 def lookup(self, key):
Martin von Zweigbergk
localrepo: don't allow lookup of working directory revision...
r42248 node = scmutil.revsymbol(self, key).node()
if node is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoLookupError(_(b"unknown revision '%s'") % key)
Martin von Zweigbergk
localrepo: don't allow lookup of working directory revision...
r42248 return node
mpm@selenic.com
Break apart hg.py...
r1089
Martin von Zweigbergk
localrepo: drop "remote" argument from lookupbranch() (API)...
r37369 def lookupbranch(self, key):
Pulkit Goyal
branchcache: introduce hasbranch()...
r42171 if self.branchmap().hasbranch(key):
Steve Losh
commands: add more robust support for 'hg log -b' (issue2078)...
r10960 return key
Martin von Zweigbergk
localrepo: use revsymbol in lookupbranch() too...
r37370 return scmutil.revsymbol(self, key).branch()
Steve Losh
commands: add more robust support for 'hg log -b' (issue2078)...
r10960
Peter Arrenbrecht
wireproto: add known([id]) function...
r13723 def known(self, nodes):
Pierre-Yves David
discovery: properly filter changeset in 'peer.known' (issue4982)...
r27319 cl = self.changelog
index: use `index.get_rev` in `localrepo.known`...
r43955 get_rev = cl.index.get_rev
Pierre-Yves David
discovery: properly filter changeset in 'peer.known' (issue4982)...
r27319 filtered = cl.filteredrevs
Pierre-Yves David
phases: make secret changeset undiscoverable in all case...
r15889 result = []
for n in nodes:
index: use `index.get_rev` in `localrepo.known`...
r43955 r = get_rev(n)
Pierre-Yves David
discovery: properly filter changeset in 'peer.known' (issue4982)...
r27319 resp = not (r is None or r in filtered)
Pierre-Yves David
phases: make secret changeset undiscoverable in all case...
r15889 result.append(resp)
return result
Peter Arrenbrecht
wireproto: add known([id]) function...
r13723
mpm@selenic.com
Break apart hg.py...
r1089 def local(self):
Matt Mackall
localrepo: local() returns self...
r14603 return self
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
publishing: add helper method to localrepo
r25623 def publishing(self):
Matt Mackall
publishing: unconditionally trust publishing flag...
r25625 # it's safe (and desirable) to trust the publish flag unconditionally
# so that we don't finalize changes shared between users via ssh or nfs
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self.ui.configbool(b'phases', b'publish', untrusted=True)
Matt Mackall
publishing: add helper method to localrepo
r25623
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def cancopy(self):
Pierre-Yves David
clone: do not turn hidden changeset public on publishing clone (issue3935)...
r20332 # so statichttprepo's override of local() works
if not self.local():
return False
Matt Mackall
publishing: use new helper method
r25624 if not self.publishing():
Pierre-Yves David
clone: do not turn hidden changeset public on publishing clone (issue3935)...
r20332 return True
# if publishing we can't copy if there is filtered content
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return not self.filtered(b'visible').changelog.filteredrevs
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Angel Ezquerra
localrepo: introduce shared method to check if a repository is shared...
r23666 def shared(self):
'''the type of shared repository (None if not shared)'''
if self.sharedpath != self.path:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'store'
Angel Ezquerra
localrepo: introduce shared method to check if a repository is shared...
r23666 return None
Angel Ezquerra
localrepo: make it possible to pass multiple path elements to join and wjoin...
r22362 def wjoin(self, f, *insidef):
Angel Ezquerra
localrepo: use vfs.reljoin rather than os.path.join in the localrepository class...
r23714 return self.vfs.reljoin(self.root, f, *insidef)
mpm@selenic.com
Break apart hg.py...
r1089
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 def setparents(self, p1, p2=nullid):
Martin von Zweigbergk
workingctx: move setparents() logic from localrepo to mirror overlayworkingctx...
r44504 self[None].setparents(p1, p2)
localrepo: also fastpath access to working copy parents when possible...
r44563 self._quick_access_changeid_invalidate()
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551
Martin von Zweigbergk
context: avoid using a context object as a changeid...
r37189 def filectx(self, path, changeid=None, fileid=None, changectx=None):
Yuya Nishihara
localrepo: correct docstring of filectx()...
r40754 """changeid must be a changeset revision, if specified.
Matt Mackall
Add context helper functions to localrepo
r2564 fileid can be a file revision or node."""
Augie Fackler
formatting: blacken the codebase...
r43346 return context.filectx(
self, path, changeid, fileid, changectx=changectx
)
Matt Mackall
Add context helper functions to localrepo
r2564
mpm@selenic.com
Break apart hg.py...
r1089 def getcwd(self):
return self.dirstate.getcwd()
Alexis S. L. Carvalho
Add dirstate.pathto and localrepo.pathto....
r4525 def pathto(self, f, cwd=None):
return self.dirstate.pathto(f, cwd)
Nicolas Dumazet
localrepo: refactor filter computation...
r11698 def _loadfilter(self, filter):
Gregory Szorc
localrepo: make filterpats private (API)...
r37155 if filter not in self._filterpats:
mpm@selenic.com
Add file encoding/decoding support
r1258 l = []
Matt Mackall
unify encode/decode filter routines
r4004 for pat, cmd in self.ui.configitems(filter):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cmd == b'!':
Mads Kiilerich
Make it possible to disable filtering for a pattern....
r7226 continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mf = matchmod.match(self.root, b'', [pat])
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 fn = None
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 params = cmd
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for name, filterfn in pycompat.iteritems(self._datafilters):
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210 if cmd.startswith(name):
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 fn = filterfn
Augie Fackler
formatting: blacken the codebase...
r43346 params = cmd[len(name) :].lstrip()
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 break
if not fn:
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 fn = lambda s, c, **kwargs: procutil.filter(s, c)
Mads Kiilerich
localrepo: debug log of filter name when filtering through a function
r43472 fn.__name__ = 'commandfilter'
Jesse Glick
Provide better context for custom Python encode/decode filters....
r5967 # Wrap old filters not supporting keyword arguments
Augie Fackler
py3: introduce and use pycompat.getargspec...
r36196 if not pycompat.getargspec(fn)[2]:
Jesse Glick
Provide better context for custom Python encode/decode filters....
r5967 oldfn = fn
Mads Kiilerich
localrepo: fix variable binding in handling of old filters...
r43473 fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c)
Mads Kiilerich
localrepo: debug log of filter name when filtering through a function
r43472 fn.__name__ = 'compat-' + oldfn.__name__
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 l.append((mf, fn, params))
Gregory Szorc
localrepo: make filterpats private (API)...
r37155 self._filterpats[filter] = l
return self._filterpats[filter]
mpm@selenic.com
Add file encoding/decoding support
r1258
Nicolas Dumazet
localrepo: load filter patterns outside of _filter
r12707 def _filter(self, filterpats, filename, data):
for mf, fn, cmd in filterpats:
mpm@selenic.com
Add file encoding/decoding support
r1258 if mf(filename):
Mads Kiilerich
localrepo: debug log of filter name when filtering through a function
r43472 self.ui.debug(
b"filtering %s through %s\n"
% (filename, cmd or pycompat.sysbytes(fn.__name__))
)
Jesse Glick
Provide better context for custom Python encode/decode filters....
r5967 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
mpm@selenic.com
Add file encoding/decoding support
r1258 break
return data
mpm@selenic.com
Break apart hg.py...
r1089
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 @unfilteredpropertycache
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708 def _encodefilterpats(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._loadfilter(b'encode')
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 @unfilteredpropertycache
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708 def _decodefilterpats(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._loadfilter(b'decode')
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 def adddatafilter(self, name, filter):
self._datafilters[name] = filter
Matt Mackall
unify encode/decode filter routines
r4004 def wread(self, filename):
Pierre-Yves David
localrepo: use self.wvfs.islink directly...
r31428 if self.wvfs.islink(filename):
FUJIWARA Katsunori
localrepo: use "vfs.readlink()" instead of "os.readlink()"
r18950 data = self.wvfs.readlink(filename)
Matt Mackall
unify encode/decode filter routines
r4004 else:
Angel Ezquerra
localrepo: remove all internal uses of localrepo.wopener...
r23854 data = self.wvfs.read(filename)
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708 return self._filter(self._encodefilterpats, filename, data)
mpm@selenic.com
Add file encoding/decoding support
r1258
Boris Feld
write: add the possibility to pass keyword argument from batchget to vfs...
r35743 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
FUJIWARA Katsunori
revert: apply normallookup on reverted file if size isn't changed (issue4583)...
r24843 """write ``data`` into ``filename`` in the working directory
This returns length of written (maybe decoded) data.
"""
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708 data = self._filter(self._decodefilterpats, filename, data)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'l' in flags:
Angel Ezquerra
localrepo: remove all internal uses of localrepo.wopener...
r23854 self.wvfs.symlink(data, filename)
Matt Mackall
util: set_flags shouldn't know about repo flag formats
r6877 else:
Augie Fackler
formatting: blacken the codebase...
r43346 self.wvfs.write(
filename, data, backgroundclose=backgroundclose, **kwargs
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'x' in flags:
FUJIWARA Katsunori
localrepo: use "vfs.setflags()" instead of "util.setflags()"
r18951 self.wvfs.setflags(filename, False, True)
Boris Feld
atomicupdate: add an experimental option to use atomictemp when updating...
r35744 else:
self.wvfs.setflags(filename, False, False)
FUJIWARA Katsunori
revert: apply normallookup on reverted file if size isn't changed (issue4583)...
r24843 return len(data)
mpm@selenic.com
Add file encoding/decoding support
r1258
Matt Mackall
replace filehandle version of wwrite with wwritedata
r4005 def wwritedata(self, filename, data):
Nicolas Dumazet
localrepo: use propertycaches to access encode/decode filters
r12708 return self._filter(self._decodefilterpats, filename, data)
mpm@selenic.com
Break apart hg.py...
r1089
Pierre-Yves David
localrepo: add a currenttransaction method...
r23379 def currenttransaction(self):
"""return the current transaction or None if non exists"""
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if self._transref:
tr = self._transref()
else:
tr = None
Henrik Stuart
transaction: support multiple, separate transactions...
r8072 if tr and tr.running():
Pierre-Yves David
localrepo: add a currenttransaction method...
r23379 return tr
return None
def transaction(self, desc, report=None):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
b'devel', b'check-locks'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Pierre-Yves David
develwarn: use the lock helper in local repo...
r29705 if self._currentlock(self._lockref) is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ProgrammingError(b'transaction requires locking')
Pierre-Yves David
localrepo: add a currenttransaction method...
r23379 tr = self.currenttransaction()
if tr is not None:
Martin von Zweigbergk
transaction: add a name and a __repr__ implementation (API)...
r36837 return tr.nest(name=desc)
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806
Matt Mackall
transactions: don't show a backtrace when journal exists...
r5865 # abort here if the journal already exists
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.svfs.exists(b"journal"):
Matt Mackall
many, many trivial check-code fixups
r10282 raise error.RepoError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"abandoned transaction found"),
hint=_(b"run 'hg recover' to clean up transaction"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
transactions: don't show a backtrace when journal exists...
r5865
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 idbase = b"%.40f#%f" % (random.random(), time.time())
Augie Fackler
core: migrate uses of hashlib.sha1 to hashutil.sha1...
r44517 ha = hex(hashutil.sha1(idbase).digest())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 txnid = b'TXN:' + ha
self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
Pierre-Yves David
hook: have a generic hook for transaction opening...
r24281
Idan Kamara
localrepo: refactor retrieving of journal/undo files paths...
r16236 self._writejournal(desc)
FUJIWARA Katsunori
localrepo: use "vfs.rename()" instead of "util.rename()"...
r18952 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if report:
rp = report
else:
rp = self.ui.warn
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
Pierre-Yves David
hook: add a generic hook right before we commit a transaction...
r24284 # we must avoid cyclic reference between repo and transaction.
reporef = weakref.ref(self)
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 # Code to track tag movement
#
# Since tags are all handled as file content, it is actually quite hard
# to track these movement from a code perspective. So we fallback to a
# tracking at the repository level. One could envision to track changes
# to the '.hgtags' file through changegroup apply but that fails to
# cope with case where transaction expose new heads without changegroup
# being involved (eg: phase movement).
#
# For now, We gate the feature behind a flag since this likely comes
# with performance impacts. The current code run more often than needed
# and do not use caches as much as it could. The current focus is on
# the behavior of the feature so we disable it by default. The flag
# will be removed when we are happy with the performance impact.
Pierre-Yves David
track-tags: write all tag changes to a file...
r31996 #
# Once this feature is no longer experimental move the following
# documentation to the appropriate help section:
#
# The ``HG_TAG_MOVED`` variable will be set if the transaction touched
# tags (new or changed or deleted tags). In addition the details of
# these changes are made available in a file at:
# ``REPOROOT/.hg/changes/tags.changes``.
# Make sure you check for HG_TAG_MOVED before reading that file as it
# might exist from a previous transaction even if no tag were touched
# in this one. Changes are recorded in a line base format::
#
# <action> <hex-node> <tag-name>\n
#
# Actions are defined as follow:
# "-R": tag is removed,
# "+A": tag is added,
# "-M": tag is moved (old value),
# "+M": tag is moved (new value),
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 tracktags = lambda x: None
# experimental config: experimental.hook-track-tags
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shouldtracktags = self.ui.configbool(
b'experimental', b'hook-track-tags'
)
if desc != b'strip' and shouldtracktags:
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 oldheads = self.changelog.headrevs()
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 def tracktags(tr2):
repo = reporef()
oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
newheads = repo.changelog.headrevs()
newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
# notes: we compare lists here.
# As we do it only once buiding set would not be cheaper
Pierre-Yves David
track-tags: compute the actual differences between tags pre/post transaction...
r31995 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
if changes:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr2.hookargs[b'tag_moved'] = b'1'
Augie Fackler
formatting: blacken the codebase...
r43346 with repo.vfs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'changes/tags.changes', b'w', atomictemp=True
Augie Fackler
formatting: blacken the codebase...
r43346 ) as changesfile:
Pierre-Yves David
track-tags: write all tag changes to a file...
r31996 # note: we do not register the file to the transaction
# because we needs it to still exist on the transaction
# is close (for txnclose hooks)
tagsmod.writediff(changesfile, changes)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 def validate(tr2):
Pierre-Yves David
hook: add a generic hook right before we commit a transaction...
r24284 """will run pre-closing hooks"""
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 # XXX the transaction API is a bit lacking here so we take a hacky
# path for now
#
# We cannot add this as a "pending" hooks since the 'tr.hookargs'
# dict is copied before these run. In addition we needs the data
# available to in memory hooks too.
#
# Moreover, we also need to make sure this runs before txnclose
# hooks and there is no "pending" mechanism that would execute
# logic only if hooks are about to run.
#
# Fixing this limitation of the transaction is also needed to track
# other families of changes (bookmarks, phases, obsolescence).
#
# This will have to be fixed before we remove the experimental
# gating.
tracktags(tr2)
Boris Feld
bookmark: add a dedicated pretxnclose-bookmark hook...
r34710 repo = reporef()
singlehead: introduce special handling of closed heads...
r43239
Georges Racinet
singlehead: making config item a bool again...
r44133 singleheadopt = (b'experimental', b'single-head-per-branch')
singlehead = repo.ui.configbool(*singleheadopt)
singlehead: introduce special handling of closed heads...
r43239 if singlehead:
Georges Racinet
singlehead: making config item a bool again...
r44133 singleheadsub = repo.ui.configsuboptions(*singleheadopt)[1]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 accountclosed = singleheadsub.get(
b"account-closed-heads", False
)
singlehead: introduce special handling of closed heads...
r43239 scmutil.enforcesinglehead(repo, tr2, desc, accountclosed)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if hook.hashook(repo.ui, b'pretxnclose-bookmark'):
for name, (old, new) in sorted(
tr.changes[b'bookmarks'].items()
):
Boris Feld
bookmark: add a dedicated pretxnclose-bookmark hook...
r34710 args = tr.hookargs.copy()
args.update(bookmarks.preparehookargs(name, old, new))
Augie Fackler
formatting: blacken the codebase...
r43346 repo.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pretxnclose-bookmark',
Augie Fackler
formatting: blacken the codebase...
r43346 throw=True,
**pycompat.strkwargs(args)
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if hook.hashook(repo.ui, b'pretxnclose-phase'):
Boris Feld
phase: add a dedicated pretxnclose-phase hook...
r34712 cl = repo.unfiltered().changelog
Joerg Sonnenberger
transactions: convert changes['phases'] to list of ranges...
r45036 for revs, (old, new) in tr.changes[b'phases']:
for rev in revs:
args = tr.hookargs.copy()
node = hex(cl.node(rev))
args.update(phases.preparehookargs(node, old, new))
repo.hook(
b'pretxnclose-phase',
throw=True,
**pycompat.strkwargs(args)
)
Augie Fackler
formatting: blacken the codebase...
r43346
repo.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pretxnclose', throw=True, **pycompat.strkwargs(tr.hookargs)
Augie Fackler
formatting: blacken the codebase...
r43346 )
FUJIWARA Katsunori
localrepo: execute appropriate actions for dirstate at releasing transaction...
r26577 def releasefn(tr, success):
repo = reporef()
Martin von Zweigbergk
transaction: leave unfinished without crashing when not properly released...
r42894 if repo is None:
# If the repo has been GC'd (and this release function is being
# called from transaction.__del__), there's not much we can do,
# so just leave the unfinished transaction there and let the
# user run `hg recover`.
return
FUJIWARA Katsunori
localrepo: execute appropriate actions for dirstate at releasing transaction...
r26577 if success:
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 # this should be explicitly invoked here, because
# in-memory changes aren't written out at closing
# transaction, if tr.addfilegenerator (via
# dirstate.write or so) isn't invoked while
# transaction running
FUJIWARA Katsunori
dirstate: make dirstate.write() callers pass transaction object to it...
r26748 repo.dirstate.write(None)
FUJIWARA Katsunori
localrepo: execute appropriate actions for dirstate at releasing transaction...
r26577 else:
# discard all changes (including ones already written
# out) in this transaction
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 narrowspec.restorebackup(self, b'journal.narrowspec')
narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
repo.dirstate.restorebackup(None, b'journal.dirstate')
Pierre-Yves David
hook: add a generic hook right before we commit a transaction...
r24284
FUJIWARA Katsunori
localrepo: discard objects in _filecache at transaction failure (issue4876)...
r26831 repo.invalidate(clearfilecache=True)
Augie Fackler
formatting: blacken the codebase...
r43346 tr = transaction.transaction(
rp,
self.svfs,
vfsmap,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"journal",
b"undo",
Augie Fackler
formatting: blacken the codebase...
r43346 aftertrans(renames),
self.store.createmode,
validator=validate,
releasefn=releasefn,
checkambigfiles=_cachedfiles,
name=desc,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.changes[b'origrepolen'] = len(self)
tr.changes[b'obsmarkers'] = set()
Joerg Sonnenberger
transactions: convert changes['phases'] to list of ranges...
r45036 tr.changes[b'phases'] = []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.changes[b'bookmarks'] = {}
tr.hookargs[b'txnid'] = txnid
tr.hookargs[b'txnname'] = desc
Joerg Sonnenberger
hooks: provide access to transaction changes for internal hooks...
r45350 tr.hookargs[b'changes'] = tr.changes
Pierre-Yves David
fncache: document the fact fncache is outdate at hook run time...
r23511 # note: writing the fncache only during finalize mean that the file is
# outdated when running hooks. As fncache is used for streaming clone,
# this is not expected to break anything that happen during the hooks.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.addfinalize(b'flush-fncache', self.store.write)
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
hook: add a generic hook after transaction has been closed...
r24282 def txnclosehook(tr2):
"""To be run if transaction is successful, will schedule a hook run
"""
Gregory Szorc
localrepo: don't reference transaction from hook closure (issue5043)...
r27907 # Don't reference tr2 in hook() so we don't hold a reference.
# This reduces memory consumption when there are multiple
# transactions per lock. This can likely go away if issue5045
# fixes the function accumulation.
hookargs = tr2.hookargs
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 def hookfunc(unused_success):
Boris Feld
bookmark: add a dedicated txnclose-bookmark hook...
r34709 repo = reporef()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if hook.hashook(repo.ui, b'txnclose-bookmark'):
bmchanges = sorted(tr.changes[b'bookmarks'].items())
Boris Feld
bookmark: add a dedicated txnclose-bookmark hook...
r34709 for name, (old, new) in bmchanges:
args = tr.hookargs.copy()
args.update(bookmarks.preparehookargs(name, old, new))
Augie Fackler
formatting: blacken the codebase...
r43346 repo.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'txnclose-bookmark',
Augie Fackler
formatting: blacken the codebase...
r43346 throw=False,
**pycompat.strkwargs(args)
)
Boris Feld
bookmark: add a dedicated txnclose-bookmark hook...
r34709
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if hook.hashook(repo.ui, b'txnclose-phase'):
Boris Feld
phase: add a dedicated txnclose-phase hook...
r34711 cl = repo.unfiltered().changelog
Joerg Sonnenberger
transactions: convert changes['phases'] to list of ranges...
r45036 phasemv = sorted(
tr.changes[b'phases'], key=lambda r: r[0][0]
)
for revs, (old, new) in phasemv:
for rev in revs:
args = tr.hookargs.copy()
node = hex(cl.node(rev))
args.update(phases.preparehookargs(node, old, new))
repo.hook(
b'txnclose-phase',
throw=False,
**pycompat.strkwargs(args)
)
Augie Fackler
formatting: blacken the codebase...
r43346
repo.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'txnclose', throw=False, **pycompat.strkwargs(hookargs)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Boris Feld
bookmark: add a dedicated txnclose-bookmark hook...
r34709 reporef()._afterlock(hookfunc)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.addfinalize(b'txnclose-hook', txnclosehook)
Martin von Zweigbergk
localrepo: run cache-warming transaction callback before report callback...
r35767 # Include a leading "-" to make it happen before the transaction summary
# reports registered via scmutil.registersummarycallback() whose names
# are 00-txnreport etc. That way, the caches will be warm when the
# callbacks run.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr))
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
hooks: add a 'txnabort' hook...
r24792 def txnaborthook(tr2):
"""To be run if transaction is aborted
"""
Augie Fackler
formatting: blacken the codebase...
r43346 reporef().hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.addabort(b'txnabort-hook', txnaborthook)
Yuya Nishihara
localrepo: refresh filecache stats only if transaction finished successfully...
r26251 # avoid eager cache invalidation. in-memory data should be identical
# to stored data if transaction has no error.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats)
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 self._transref = weakref.ref(tr)
Boris Feld
transaction-summary: display the summary for all transactions...
r33541 scmutil.registersummarycallback(self, tr, desc)
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 return tr
Idan Kamara
localrepo: refactor retrieving of journal/undo files paths...
r16236 def _journalfiles(self):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (self.svfs, b'journal'),
(self.svfs, b'journal.narrowspec'),
(self.vfs, b'journal.narrowspec.dirstate'),
(self.vfs, b'journal.dirstate'),
(self.vfs, b'journal.branch'),
(self.vfs, b'journal.desc'),
(bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
(self.svfs, b'journal.phaseroots'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Idan Kamara
localrepo: refactor retrieving of journal/undo files paths...
r16236
def undofiles(self):
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
Idan Kamara
localrepo: refactor retrieving of journal/undo files paths...
r16236
transaction: run _writejournal unfiltered...
r32452 @unfilteredmethod
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 def _writejournal(self, desc):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.dirstate.savebackup(None, b'journal.dirstate')
narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
narrowspec.savebackup(self, b'journal.narrowspec')
Augie Fackler
formatting: blacken the codebase...
r43346 self.vfs.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
Martin von Zweigbergk
bookmarks: keep bookmarks in .hg/store if new config set...
r42512 bookmarksvfs = bookmarks.bookmarksvfs(self)
Augie Fackler
formatting: blacken the codebase...
r43346 bookmarksvfs.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks")
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots"))
Alexander Solovyov
fix bookmarks rollback behavior...
r14266
mpm@selenic.com
Break apart hg.py...
r1089 def recover(self):
Bryan O'Sullivan
with: use context manager in localrepo recover
r27846 with self.lock():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.svfs.exists(b"journal"):
self.ui.status(_(b"rolling back interrupted transaction\n"))
Augie Fackler
formatting: blacken the codebase...
r43346 vfsmap = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'': self.svfs,
b'plain': self.vfs,
Augie Fackler
formatting: blacken the codebase...
r43346 }
transaction.rollback(
self.svfs,
vfsmap,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"journal",
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.warn,
checkambigfiles=_cachedfiles,
)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.invalidate()
return True
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.warn(_(b"no interrupted transaction available\n"))
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 return False
mpm@selenic.com
Break apart hg.py...
r1089
Greg Ward
rollback: avoid unsafe rollback when not at tip (issue2998)...
r15183 def rollback(self, dryrun=False, force=False):
FUJIWARA Katsunori
localrepo: restore dirstate to one before rollbacking if not parent-gone...
r26631 wlock = lock = dsguard = None
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
mason@suse.com
Allow callers to pass in the dirstate lock in most localrepo.py funcs....
r1712 wlock = self.wlock()
Eric Hopper
Fix hg import --exact bug that hangs hg on failure.
r4438 lock = self.lock()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.svfs.exists(b"undo"):
dsguard = dirstateguard.dirstateguard(self, b'rollback')
FUJIWARA Katsunori
localrepo: restore dirstate to one before rollbacking if not parent-gone...
r26631
return self._rollback(dryrun, force, dsguard)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.warn(_(b"no rollback information available\n"))
Matt Mackall
commands: initial audit of exit codes...
r11177 return 1
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 finally:
FUJIWARA Katsunori
localrepo: restore dirstate to one before rollbacking if not parent-gone...
r26631 release(dsguard, lock, wlock)
mpm@selenic.com
Break apart hg.py...
r1089
Augie Fackler
formatting: blacken the codebase...
r43346 @unfilteredmethod # Until we get smarter cache management
FUJIWARA Katsunori
localrepo: restore dirstate to one before rollbacking if not parent-gone...
r26631 def _rollback(self, dryrun, force, dsguard):
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 ui = self.ui
Greg Ward
rollback: improve readability; clarify that the return value is an int.
r15097 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args = self.vfs.read(b'undo.desc').splitlines()
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 (oldlen, desc, detail) = (int(args[0]), args[1], None)
if len(args) >= 3:
detail = args[2]
oldtip = oldlen - 1
if detail and ui.verbose:
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'repository tip rolled back to revision %d'
b' (undo %s: %s)\n'
Augie Fackler
formatting: blacken the codebase...
r43346 ) % (oldtip, desc, detail)
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 else:
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'repository tip rolled back to revision %d (undo %s)\n'
Augie Fackler
formatting: blacken the codebase...
r43346 ) % (oldtip, desc)
Greg Ward
rollback: improve readability; clarify that the return value is an int.
r15097 except IOError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'rolling back unknown transaction\n')
Greg Ward
rollback: avoid unsafe rollback when not at tip (issue2998)...
r15183 desc = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'rollback of last commit while not checked out '
b'may lose data'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hint=_(b'use -f to force'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Greg Ward
rollback: avoid unsafe rollback when not at tip (issue2998)...
r15183
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 ui.status(msg)
Greg Ward
rollback: improve readability; clarify that the return value is an int.
r15097 if dryrun:
return 0
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131
parents = self.dirstate.parents()
Idan Kamara
localrepo: introduce destroying function
r18310 self.destroying()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 vfsmap = {b'plain': self.vfs, b'': self.svfs}
Augie Fackler
formatting: blacken the codebase...
r43346 transaction.rollback(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.svfs, vfsmap, b'undo', ui.warn, checkambigfiles=_cachedfiles
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
bookmarks: keep bookmarks in .hg/store if new config set...
r42512 bookmarksvfs = bookmarks.bookmarksvfs(self)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if bookmarksvfs.exists(b'undo.bookmarks'):
bookmarksvfs.rename(
b'undo.bookmarks', b'bookmarks', checkambig=True
)
if self.svfs.exists(b'undo.phaseroots'):
self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
Greg Ward
rollback: improve readability; clarify that the return value is an int.
r15097 self.invalidate()
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131
index: use `index.has_node` in `repo._rollback`...
r43937 has_node = self.changelog.index.has_node
parentgone = any(not has_node(p) for p in parents)
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131 if parentgone:
FUJIWARA Katsunori
localrepo: restore dirstate to one before rollbacking if not parent-gone...
r26631 # prevent dirstateguard from overwriting already restored one
dsguard.close()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 narrowspec.restorebackup(self, b'undo.narrowspec')
narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
self.dirstate.restorebackup(None, b'undo.dirstate')
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 branch = self.vfs.read(b'undo.branch')
Sune Foldager
rollback: write dirstate branch with correct encoding
r17360 self.dirstate.setbranch(encoding.tolocal(branch))
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131 except IOError:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'named branch could not be reset: '
b'current branch is still \'%s\'\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% self.dirstate.branch()
)
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131
Augie Fackler
commands: inline definition of localrepo.parents() and drop the method (API)...
r27167 parents = tuple([p.rev() for p in self[None].parents()])
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131 if len(parents) > 1:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(
b'working directory now based on '
b'revisions %d and %d\n'
)
Augie Fackler
formatting: blacken the codebase...
r43346 % parents
)
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131 else:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'working directory now based on revision %d\n') % parents
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
mergestate: make some callers not pass pointless node argument...
r46062 mergestatemod.mergestate.clean(self)
Matt Mackall
rollback: clear resolve state (issue4593)
r24784
Joshua Redstone
strip: incrementally update the branchheads cache after a strip...
r17013 # TODO: if we know which new heads may result from this rollback, pass
# them to destroy(), which will prevent the branchhead cache from being
# invalidated.
Greg Ward
rollback: always call destroyed() (regression from 1.9)...
r15604 self.destroyed()
Greg Ward
rollback: improve readability; clarify that the return value is an int.
r15097 return 0
cache: make the cache updated callback easily accessible to extension...
r32332 def _buildcacheupdater(self, newtransaction):
"""called during transaction to build the callback updating cache
Lives on the repository to help extension who might want to augment
this logic. For this purpose, the created transaction is passed to the
method.
"""
# we must avoid cyclic reference between repo and transaction.
reporef = weakref.ref(self)
Augie Fackler
formatting: blacken the codebase...
r43346
cache: make the cache updated callback easily accessible to extension...
r32332 def updater(tr):
repo = reporef()
repo.updatecaches(tr)
Augie Fackler
formatting: blacken the codebase...
r43346
cache: make the cache updated callback easily accessible to extension...
r32332 return updater
Pierre-Yves David
caches: introduce a function to warm cache...
r32263 @unfilteredmethod
Boris Feld
debugupdatecache: also warm rev branch cache...
r36970 def updatecaches(self, tr=None, full=False):
Pierre-Yves David
caches: call 'repo.updatecache()' in 'repo.destroyed()'...
r32264 """warm appropriate caches
If this function is called after a transaction closed. The transaction
will be available in the 'tr' argument. This can be used to selectively
update caches relevant to the changes in that transaction.
Boris Feld
debugupdatecache: also warm rev branch cache...
r36970
If 'full' is set, make sure all caches the function knows about have
up-to-date data. Even the ones usually loaded more lazily.
Pierre-Yves David
caches: call 'repo.updatecache()' in 'repo.destroyed()'...
r32264 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if tr is not None and tr.hookargs.get(b'source') == b'strip':
Pierre-Yves David
caches: introduce a function to warm cache...
r32263 # During strip, many caches are invalid but
# later call to `destroyed` will refresh them.
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if tr is None or tr.changes[b'origrepolen'] < len(self):
Martijn Pieters
branchmap: encapsulate cache updating in the map itself...
r41764 # accessing the 'ser ved' branchmap should refresh all the others,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.debug(b'updating the branch cache\n')
self.filtered(b'served').branchmap()
self.filtered(b'served.hidden').branchmap()
Pierre-Yves David
caches: introduce a function to warm cache...
r32263
Boris Feld
debugupdatecache: also warm rev branch cache...
r36970 if full:
updatecaches: also warm revbranchcache for filtered revisions...
r42099 unfi = self.unfiltered()
nodemap: warm the persistent nodemap on disk with debugupdatecache...
r44932
self.changelog.update_caches(transaction=tr)
nodemap: also warm manifest nodemap with other caches...
r45291 self.manifestlog.update_caches(transaction=tr)
nodemap: warm the persistent nodemap on disk with debugupdatecache...
r44932
updatecaches: also warm revbranchcache for filtered revisions...
r42099 rbc = unfi.revbranchcache()
for r in unfi.changelog:
Boris Feld
debugupdatecache: also warm rev branch cache...
r36970 rbc.branchinfo(r)
rbc.write()
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 # ensure the working copy parents are in the manifestfulltextcache
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for ctx in self[b'.'].parents():
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 ctx.manifest() # accessing the manifest is enough
updatecaches: also warm hgtagsfnodescache...
r42424 # accessing fnode cache warms the cache
tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
updatecaches: also warm the tags caches...
r42100 # accessing tags warm the cache
self.tags()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.filtered(b'served').tags()
updatecaches: also warm the tags caches...
r42100
Kyle Lippincott
branchmap: explicitly warm+write all subsets of the branchmap caches...
r42940 # The `full` arg is documented as updating even the lazily-loaded
# caches immediately, so we're forcing a write to cause these caches
# to be warmed up even if they haven't explicitly been requested
# yet (if they've never been used by hg, they won't ever have been
# written, even if they're a subset of another kind of cache that
# *has* been used).
for filt in repoview.filtertable.keys():
filtered = self.filtered(filt)
filtered.branchmap().write(filtered)
Benoit Boissinot
strip: invalidate all caches after stripping (fixes issue1951)...
r10547 def invalidatecaches(self):
Idan Kamara
localrepo: delete _phaserev when invalidating caches
r15988
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if '_tagscache' in vars(self):
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 # can't use delattr on proxy
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 del self.__dict__['_tagscache']
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936
Martijn Pieters
branchmap: encapsulate cache updating in the map itself...
r41764 self._branchcaches.clear()
Pierre-Yves David
cache: group obscache and revsfiltercache invalidation in a single function...
r18105 self.invalidatevolatilesets()
Gregory Szorc
localrepo: add sparse caches...
r33302 self._sparsesignaturecache.clear()
Pierre-Yves David
cache: group obscache and revsfiltercache invalidation in a single function...
r18105
def invalidatevolatilesets(self):
self.filteredrevcache.clear()
Pierre-Yves David
obsolete: introduce caches for all meaningful sets...
r17469 obsolete.clearobscaches(self)
localrepo: also fastpath access to working copy parents when possible...
r44563 self._quick_access_changeid_invalidate()
Benoit Boissinot
revalidate revlog data after locking the repo (issue132)
r1784
Idan Kamara
localrepo: decorate dirstate() with filecache...
r14930 def invalidatedirstate(self):
'''Invalidates the dirstate, causing the next call to dirstate
to check if it was modified since the last time it was read,
rereading it if it has.
This is different to dirstate.invalidate() that it doesn't always
rereads the dirstate. Use dirstate.invalidate() if you want to
explicitly read the dirstate again (i.e. restoring it to a previous
known good state).'''
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if hasunfilteredcache(self, 'dirstate'):
Idan Kamara
dirstate: add filecache support
r16200 for k in self.dirstate._filecache:
try:
delattr(self.dirstate, k)
except AttributeError:
pass
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 delattr(self.unfiltered(), 'dirstate')
Idan Kamara
localrepo: decorate dirstate() with filecache...
r14930
FUJIWARA Katsunori
localrepo: discard objects in _filecache at transaction failure (issue4876)...
r26831 def invalidate(self, clearfilecache=False):
FUJIWARA Katsunori
localrepo: make invalidate avoid invalidating store inside transaction (API)...
r29918 '''Invalidates both store and non-store parts other than dirstate
If a transaction is running, invalidation of store is omitted,
because discarding in-memory changes might cause inconsistency
(e.g. incomplete fncache causes unintentional failure, but
redundant one doesn't).
'''
Augie Fackler
formatting: blacken the codebase...
r43346 unfiltered = self.unfiltered() # all file caches are stored unfiltered
Augie Fackler
localrepo: forcibly copy list of filecache keys...
r31510 for k in list(self._filecache.keys()):
Idan Kamara
localrepo: make invalidate() walk _filecache
r14935 # dirstate is invalidated separately in invalidatedirstate()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if k == b'dirstate':
Idan Kamara
localrepo: make invalidate() walk _filecache
r14935 continue
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 k == b'changelog'
Augie Fackler
formatting: blacken the codebase...
r43346 and self.currenttransaction()
and self.changelog._delayed
):
Martin von Zweigbergk
repo: skip invalidation of changelog if it has 'delayed' changes (API)...
r33672 # The changelog object may store unwritten revisions. We don't
# want to lose them.
# TODO: Solve the problem instead of working around it.
continue
Idan Kamara
localrepo: make invalidate() walk _filecache
r14935
FUJIWARA Katsunori
localrepo: discard objects in _filecache at transaction failure (issue4876)...
r26831 if clearfilecache:
del self._filecache[k]
Idan Kamara
localrepo: make invalidate() walk _filecache
r14935 try:
Pierre-Yves David
clfilter: ensure cache invalidation is done on the main unfiltered repo...
r17997 delattr(unfiltered, k)
Idan Kamara
localrepo: make invalidate() walk _filecache
r14935 except AttributeError:
pass
Benoit Boissinot
strip: invalidate all caches after stripping (fixes issue1951)...
r10547 self.invalidatecaches()
FUJIWARA Katsunori
localrepo: make invalidate avoid invalidating store inside transaction (API)...
r29918 if not self.currenttransaction():
# TODO: Changing contents of store outside transaction
# causes inconsistency. We should make in-memory store
# changes detectable, and abort if changed.
self.store.invalidatecaches()
Benoit Boissinot
strip: invalidate all caches after stripping (fixes issue1951)...
r10547
Yuya Nishihara
localrepo: add hook point to invalidate everything on each command-server run...
r20627 def invalidateall(self):
'''Fully invalidates both store and non-store parts, causing the
subsequent operation to reread any outside changes.'''
# extension should hook this to invalidate its caches
self.invalidate()
self.invalidatedirstate()
FUJIWARA Katsunori
localrepo: make _refreshfilecachestats unfiltered method to refresh correctly...
r29920 @unfilteredmethod
Yuya Nishihara
localrepo: refresh filecache stats only if transaction finished successfully...
r26251 def _refreshfilecachestats(self, tr):
Yuya Nishihara
localrepo: move closure of lock release to class...
r26250 """Reload stats of cached files so that they are flagged as valid"""
for k, ce in self._filecache.items():
Augie Fackler
localrepo: consistently use native str when __dict__ is involved...
r35857 k = pycompat.sysstr(k)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if k == 'dirstate' or k not in self.__dict__:
Yuya Nishihara
localrepo: move closure of lock release to class...
r26250 continue
ce.refresh()
Augie Fackler
formatting: blacken the codebase...
r43346 def _lock(
Martin von Zweigbergk
locking: remove support for inheriting locks in subprocess...
r46092 self, vfs, lockname, wait, releasefn, acquirefn, desc,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 timeout = 0
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 warntimeout = 0
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 if wait:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 timeout = self.ui.configint(b"ui", b"timeout")
warntimeout = self.ui.configint(b"ui", b"timeout.warn")
Yuya Nishihara
lock: add internal config to not replace signal handlers while locking...
r38157 # internal config: ui.signal-safe-lock
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 signalsafe = self.ui.configbool(b'ui', b'signal-safe-lock')
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209
Augie Fackler
formatting: blacken the codebase...
r43346 l = lockmod.trylock(
self.ui,
vfs,
lockname,
timeout,
warntimeout,
releasefn=releasefn,
acquirefn=acquirefn,
desc=desc,
signalsafe=signalsafe,
)
Benoit Boissinot
localrepo: refactor the locking functions
r1751 return l
Matt Mackall
localrepo: rename _postrelease to _afterlock
r15587 def _afterlock(self, callback):
Pierre-Yves David
afterlock: add the callback to the top level lock (issue4608)...
r24821 """add a callback to be run when the repository is fully unlocked
Pierre-Yves David
lock: add mechanism to register post release callback
r15583
Pierre-Yves David
afterlock: add the callback to the top level lock (issue4608)...
r24821 The callback will be executed when the outermost lock is released
(with wlock being higher level than 'lock')."""
for ref in (self._wlockref, self._lockref):
l = ref and ref()
if l and l.held:
l.postrelease.append(callback)
break
Augie Fackler
formatting: blacken the codebase...
r43346 else: # no lock have been found.
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 callback(True)
Pierre-Yves David
lock: add mechanism to register post release callback
r15583
Matt Mackall
repo locks: use True/False
r4914 def lock(self, wait=True):
Greg Ward
localrepo: document the locking scheme a little better...
r9309 '''Lock the repository store (.hg/store) and return a weak reference
to the lock. Use this before modifying the store (e.g. committing or
Pierre-Yves David
lock: update the docstring with order information...
r24746 stripping). If you are opening a transaction, get a lock as well.)
If both 'lock' and 'wlock' must be acquired, ensure you always acquires
'wlock' first to avoid a dead-lock hazard.'''
Pierre-Yves David
develwarn: use the lock helper in local repo...
r29705 l = self._currentlock(self._lockref)
if l is not None:
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 l.lock()
return l
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917
Augie Fackler
formatting: blacken the codebase...
r43346 l = self._lock(
vfs=self.svfs,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lockname=b"lock",
Augie Fackler
formatting: blacken the codebase...
r43346 wait=wait,
releasefn=None,
acquirefn=self.invalidate,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc=_(b'repository %s') % self.origroot,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 self._lockref = weakref.ref(l)
return l
Benoit Boissinot
localrepo: refactor the locking functions
r1751
Matt Mackall
repo locks: use True/False
r4914 def wlock(self, wait=True):
Greg Ward
localrepo: document the locking scheme a little better...
r9309 '''Lock the non-store parts of the repository (everything under
.hg except .hg/store) and return a weak reference to the lock.
Pierre-Yves David
lock: update the docstring with order information...
r24746
Use this before modifying files in .hg.
If both 'lock' and 'wlock' must be acquired, ensure you always acquires
'wlock' first to avoid a dead-lock hazard.'''
Pierre-Yves David
wlock: only issue devel warning when actually acquiring the lock...
r24744 l = self._wlockref and self._wlockref()
if l is not None and l.held:
l.lock()
return l
Mads Kiilerich
spelling: trivial spell checking
r26781 # We do not need to check for non-waiting lock acquisition. Such
Pierre-Yves David
wlock: do not warn for non-wait locking...
r24750 # acquisition would not cause dead-lock as they would just fail.
Augie Fackler
formatting: blacken the codebase...
r43346 if wait and (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.configbool(b'devel', b'all-warnings')
or self.ui.configbool(b'devel', b'check-locks')
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Pierre-Yves David
develwarn: use the lock helper in local repo...
r29705 if self._currentlock(self._lockref) is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.develwarn(b'"wlock" acquired after "lock"')
Benoit Boissinot
add localrepo.wlock for protecting the dirstate...
r1531
Idan Kamara
localrepo: decorate dirstate() with filecache...
r14930 def unlock():
Durham Goode
dirstate: add begin/endparentchange to dirstate...
r22404 if self.dirstate.pendingparentchange():
self.dirstate.invalidate()
else:
FUJIWARA Katsunori
dirstate: make dirstate.write() callers pass transaction object to it...
r26748 self.dirstate.write(None)
Durham Goode
dirstate: add begin/endparentchange to dirstate...
r22404
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._filecache[b'dirstate'].refresh()
Idan Kamara
localrepo: decorate dirstate() with filecache...
r14930
Augie Fackler
formatting: blacken the codebase...
r43346 l = self._lock(
self.vfs,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"wlock",
Augie Fackler
formatting: blacken the codebase...
r43346 wait,
unlock,
self.invalidatedirstate,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'working directory of %s') % self.origroot,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 self._wlockref = weakref.ref(l)
return l
Benoit Boissinot
add localrepo.wlock for protecting the dirstate...
r1531
Siddharth Agarwal
localrepo: add a way to get the current lock if it's held...
r26488 def _currentlock(self, lockref):
"""Returns the lock if it's held, or None if it's not."""
if lockref is None:
return None
l = lockref()
if l is None or not l.held:
return None
return l
Siddharth Agarwal
localrepo: add a way to get the current wlock if it's held...
r26489 def currentwlock(self):
"""Returns the wlock if it's held, or None if it's not."""
return self._currentlock(self._wlockref)
Martin von Zweigbergk
commit: drop unused "vdirs" argument from repo.checkcommitpatterns()...
r44111 def checkcommitpatterns(self, wctx, match, status, fail):
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 """check for commit arguments that aren't committable"""
timeless
localrepo: drop force check from checkcommitpatterns...
r28814 if match.isexact() or match.prefix():
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813 matched = set(status.modified + status.added + status.removed)
for f in match.files():
f = self.dirstate.normalize(f)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if f == b'.' or f in matched or f in wctx.substate:
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813 continue
if f in status.deleted:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fail(f, _(b'file not found!'))
Martin von Zweigbergk
commit: rewrite check for `hg ci <path>` being a directory...
r44110 # Is it a directory that exists or used to exist?
if self.wvfs.isdir(f) or wctx.p1().hasdir(f):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 d = f + b'/'
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813 for mf in matched:
if mf.startswith(d):
break
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fail(f, _(b"no match under directory!"))
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813 elif f not in self.dirstate:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fail(f, _(b"file not tracked!"))
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813
Pierre-Yves David
clfilter: rename `unfilteredmeth` to `unfilteredmethod`...
r18016 @unfilteredmethod
Augie Fackler
formatting: blacken the codebase...
r43346 def commit(
self,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 text=b"",
Augie Fackler
formatting: blacken the codebase...
r43346 user=None,
date=None,
match=None,
force=False,
Matt Harbison
commit: change default `editor` parameter to None...
r44475 editor=None,
Augie Fackler
formatting: blacken the codebase...
r43346 extra=None,
):
Benoit Boissinot
localrepo: update commit*() docstrings
r8515 """Add a new revision to current repository.
Matt Mackall
commit: drop the now-unused files parameter
r8706 Revision information is gathered from the working directory,
match can be used to filter the committed files. If editor is
supplied, it is called to get a commit message.
Benoit Boissinot
localrepo: update commit*() docstrings
r8515 """
Pierre-Yves David
commit: remove a mutable default argument...
r26322 if extra is None:
extra = {}
Matt Mackall
commit: move explicit file checking into repo.commit
r8709
Matt Mackall
commit: move some setup outside the lock
r8715 def fail(f, msg):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(b'%s: %s' % (f, msg))
Matt Mackall
commit: move some setup outside the lock
r8715
if not match:
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 match = matchmod.always()
Matt Mackall
commit: move some setup outside the lock
r8715
if not force:
match.bad = fail
Martin von Zweigbergk
localrepo: use context manager for locks in commit()...
r41399 # lock() for recent changelog (see issue4368)
with self.wlock(), self.lock():
Matt Mackall
commit: recurse into subrepositories
r8813 wctx = self[None]
Benoit Boissinot
localrepo.commit: use explicit variables, avoid creating new contexts
r10970 merge = len(wctx.parents()) > 1
mpm@selenic.com
Break apart hg.py...
r1089
Martin von Zweigbergk
match: remove ispartial()...
r32312 if not force and merge and not match.always():
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cannot partially commit a merge '
b'(do not specify files or patterns)'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Patrick Mezard
localrepo: replace dirstate by workingfilectx in filecommit()
r6706
Martin von Zweigbergk
localrepo: access status fields by name rather than index
r22928 status = self.status(match=match, clean=force)
Matt Mackall
commit: drop the now-unused files parameter
r8706 if force:
Augie Fackler
formatting: blacken the codebase...
r43346 status.modified.extend(
status.clean
) # mq may commit clean files
Benoit Boissinot
localrepo: factor commit and rawcommit...
r3621
Matt Mackall
commit: recurse into subrepositories
r8813 # check subrepos
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subs, commitsubs, newstate = subrepoutil.precommit(
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui, wctx, status, match, force=force
)
Matt Mackall
commit: recurse into subrepositories
r8813
Matt Mackall
commit: move explicit file checking into repo.commit
r8709 # make sure all explicit patterns are matched
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813 if not force:
Martin von Zweigbergk
commit: drop unused "vdirs" argument from repo.checkcommitpatterns()...
r44111 self.checkcommitpatterns(wctx, match, status, fail)
Matt Mackall
commit: move explicit file checking into repo.commit
r8709
Augie Fackler
formatting: blacken the codebase...
r43346 cctx = context.workingcommitctx(
self, status, text, user, date, extra
)
David Schleimer
localrepo: create context used for actual commit earlier...
r18659
Augie Fackler
mergestate: split out merge state handling code from main merge module...
r45383 ms = mergestatemod.mergestate.read(self)
Martin von Zweigbergk
commit: error out on unresolved files even if commit would be empty...
r44889 mergeutil.checkunresolved(ms)
Matt Mackall
commit: mark internal-only option
r25840 # internal config: ui.allowemptycommit
Manuel Jacob
commit: factor out empty commit check to `basectx.isempty()`...
r45648 if cctx.isempty() and not self.ui.configbool(
b'ui', b'allowemptycommit'
):
Martin von Zweigbergk
commit: print debug message when clearing dirstate and wdir clean...
r44929 self.ui.debug(b'nothing to commit, clearing merge state\n')
Martin von Zweigbergk
commit: clear resolved mergestate even if working copy is clean...
r44919 ms.reset()
Matt Mackall
commit: move 'nothing changed' test into commit()
r8404 return None
David Schleimer
localrepo: use workingctx for validation in commit...
r18660 if merge and cctx.deleted():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"cannot commit merge with missing files"))
Patrick Mezard
commit: abort on merge with missing files...
r16536
Matt Mackall
commit: move editor outside transaction...
r8496 if editor:
Matt Mackall
commit: report modified subrepos in commit editor
r8994 cctx._text = editor(self, cctx, subs)
Augie Fackler
formatting: blacken the codebase...
r43346 edited = text != cctx._text
Matt Mackall
commit: recurse into subrepositories
r8813
FUJIWARA Katsunori
localrepo: save manually edited commit message as soon as possible...
r20765 # Save commit message in case this transaction gets rolled back
# (e.g. by a pretxncommit hook). Leave the content alone on
# the assumption that the user will use the same editor again.
msgfn = self.savecommitmessage(cctx._text)
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 # commit subs and write new state
if subs:
Martin von Zweigbergk
commit: respect ui.relative-paths...
r41837 uipathfn = scmutil.getuipathfn(self)
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 for s in sorted(commitsubs):
Edouard Gomez
subrepo: print paths relative to upper repo root for push/pull/commit...
r11112 sub = wctx.sub(s)
Augie Fackler
formatting: blacken the codebase...
r43346 self.ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'committing subrepository %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % uipathfn(subrepoutil.subrelpath(sub))
)
Edouard Gomez
subrepo: print paths relative to upper repo root for push/pull/commit...
r11112 sr = sub.commit(cctx._text, user, date)
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 newstate[s] = (newstate[s][0], sr)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subrepoutil.writestate(self, newstate)
Matt Mackall
commit: recurse into subrepositories
r8813
Benoit Boissinot
localrepo.commit: use explicit variables, avoid creating new contexts
r10970 p1, p2 = self.dirstate.parents()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or b'')
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 try:
Augie Fackler
formatting: blacken the codebase...
r43346 self.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"precommit", throw=True, parent1=hookp1, parent2=hookp2
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with self.transaction(b'commit'):
Martin von Zweigbergk
localrepo: use context manager for transaction in commit()...
r41398 ret = self.commitctx(cctx, True)
# update bookmarks, dirstate and mergestate
bookmarks.update(self, [p1, p2], ret)
cctx.markcommitted(ret)
ms.reset()
Augie Fackler
formatting: blacken the codebase...
r43346 except: # re-raises
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 if edited:
self.ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'note: commit message saved in %s\n') % msgfn
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
commit: tell user what to do with .hg/last-message.txt...
r45227 self.ui.write(
_(
b"note: use 'hg commit --logfile "
b".hg/last-message.txt --edit' to reuse it\n"
)
)
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 raise
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 def commithook(unused_success):
Pierre-Yves David
hook: protect commit hooks against stripping of temporary commit (issue4422)...
r23129 # hack for command that use a temporary commit (eg: histedit)
# temporary commit got stripped before hook release
FUJIWARA Katsunori
localrepo: use changelog.hasnode instead of self.__contains__...
r24992 if self.changelog.hasnode(ret):
Augie Fackler
formatting: blacken the codebase...
r43346 self.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mads Kiilerich
tag: run commit hook when lock is released (issue3344)
r16680 self._afterlock(commithook)
Sune Foldager
run commit and update hooks after command completion (issue1827)...
r10492 return ret
Pierre-Yves David
clfilter: rename `unfilteredmeth` to `unfilteredmethod`...
r18016 @unfilteredmethod
Valentin Gatien-Baron
convert: add a config option to help doing identity hg->hg conversion...
r42839 def commitctx(self, ctx, error=False, origctx=None):
commitctx: extract the function in a dedicated module...
r45759 return commit.commitctx(self, ctx, error=error, origctx=origctx)
mpm@selenic.com
Break apart hg.py...
r1089
Pierre-Yves David
clfilter: rename `unfilteredmeth` to `unfilteredmethod`...
r18016 @unfilteredmethod
Idan Kamara
localrepo: introduce destroying function
r18310 def destroying(self):
'''Inform the repository that nodes are about to be destroyed.
Intended for use by strip and rollback, so there's a common
place for anything that has to be done before destroying history.
This is mostly useful for saving state that is in memory and waiting
to be flushed when the current lock is released. Because a call to
destroyed is imminent, the repo will be invalidated causing those
changes to stay in memory (waiting for the next unlock), or vanish
completely.
'''
Idan Kamara
localrepo: write the phasecache when destroying nodes
r18312 # When using the same lock to commit and strip, the phasecache is left
# dirty after committing. Then when we strip, the repo is invalidated,
# causing those changes to disappear.
Martin von Zweigbergk
py3: don't use bytes with vars() or __dict__...
r43744 if '_phasecache' in vars(self):
Idan Kamara
localrepo: write the phasecache when destroying nodes
r18312 self._phasecache.write()
Idan Kamara
localrepo: introduce destroying function
r18310 @unfilteredmethod
Pierre-Yves David
destroyed: drop complex branchcache rebuilt logic...
r18395 def destroyed(self):
Greg Ward
localrepo: add destroyed() method for strip/rollback to use (issue548).
r9150 '''Inform the repository that nodes have been destroyed.
Intended for use by strip and rollback, so there's a common
Joshua Redstone
strip: incrementally update the branchheads cache after a strip...
r17013 place for anything that has to be done after destroying history.
'''
Idan Kamara
localrepo: filter unknown nodes from the phasecache on destroyed...
r18221 # When one tries to:
# 1) destroy nodes thus calling this method (e.g. strip)
# 2) use phasecache somewhere (e.g. commit)
#
# then 2) will fail because the phasecache contains nodes that were
# removed. We can either remove phasecache from the filecache,
# causing it to reload next time it is accessed, or simply filter
# the removed nodes now and write the updated cache.
Idan Kamara
localrepo: always write the filtered phasecache when nodes are destroyed (issue3827)...
r18757 self._phasecache.filterunknown(self)
self._phasecache.write()
Idan Kamara
localrepo: filter unknown nodes from the phasecache on destroyed...
r18221
Pierre-Yves David
caches: call 'repo.updatecache()' in 'repo.destroyed()'...
r32264 # refresh all repository caches
self.updatecaches()
Pierre-Yves David
destroyed: filter unknown before computing branchcache...
r18223
Greg Ward
tags: implement persistent tag caching (issue548)....
r9151 # Ensure the persistent tag cache is updated. Doing it now
# means that the tag cache only has to worry about destroyed
# heads immediately after a strip/rollback. That in turn
# guarantees that "cachetip == currenttip" (comparing both rev
# and node) always means no nodes have been added or destroyed.
# XXX this is suboptimal when qrefresh'ing: we strip the current
# head, refresh the tag cache, then immediately add a new head.
# But I think doing it this way is necessary for the "instant
# tag cache retrieval" case to work.
Idan Kamara
destroyed: keep the filecache in sync with __dict__ (issue3335) (issue3693) (issue3743)...
r18313 self.invalidate()
Idan Kamara
localrepo: clear the filecache on _rollback() and destroyed()...
r17324
Augie Fackler
formatting: blacken the codebase...
r43346 def status(
self,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 node1=b'.',
Augie Fackler
formatting: blacken the codebase...
r43346 node2=None,
match=None,
ignored=False,
clean=False,
unknown=False,
listsubrepos=False,
):
Sean Farley
localrepo: replace status method with a shim...
r21596 '''a convenience method that calls node1.status(node2)'''
Augie Fackler
formatting: blacken the codebase...
r43346 return self[node1].status(
node2, match, ignored, clean, unknown, listsubrepos
)
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661
Siddharth Agarwal
workingctx: add a way for extensions to run code at status fixup time...
r32814 def addpostdsstatus(self, ps):
"""Add a callback to run within the wlock, at the point at which status
fixups happen.
On status completion, callback(wctx, status) will be called with the
wlock held, unless the dirstate has changed from underneath or the wlock
couldn't be grabbed.
Callbacks should not capture and use a cached copy of the dirstate --
it might change in the meanwhile. Instead, they should access the
dirstate via wctx.repo().dirstate.
This list is emptied out after each status run -- extensions should
make sure it adds to this list each time dirstate.status is called.
Extensions should also make sure they don't call this for statuses
that don't involve the dirstate.
"""
# The list is located here for uniqueness reasons -- it is actually
# managed by the workingctx, but that isn't unique per-repo.
self._postdsstatus.append(ps)
def postdsstatus(self):
"""Used by workingctx to get the list of post-dirstate-status hooks."""
return self._postdsstatus
def clearpostdsstatus(self):
"""Used by workingctx to clear post-dirstate-status hooks."""
del self._postdsstatus[:]
John Mulligan
localrepo: remove 'closed' argument to heads(...) function...
r8796 def heads(self, start=None):
Stanislau Hlebik
localrepo: avoid unnecessary conversion from node to rev...
r30875 if start is None:
Stanislau Hlebik
localrepo: cache self.changelog in local variable...
r30905 cl = self.changelog
Stanislau Hlebik
localrepo: avoid unnecessary sorting...
r30906 headrevs = reversed(cl.headrevs())
Stanislau Hlebik
localrepo: cache self.changelog in local variable...
r30905 return [cl.node(rev) for rev in headrevs]
Stanislau Hlebik
localrepo: avoid unnecessary conversion from node to rev...
r30875
Benoit Boissinot
add a -r/--rev option to heads to show only heads descendant from rev
r1550 heads = self.changelog.heads(start)
# sort the output in rev descending order
Thomas Arendsen Hein
coding style: fix gratuitous whitespace after Python keywords
r13075 return sorted(heads, key=self.changelog.rev, reverse=True)
mpm@selenic.com
Break apart hg.py...
r1089
John Mulligan
localrepo: set heads and branchheads to be closed=False by default...
r8694 def branchheads(self, branch=None, start=None, closed=False):
Sune Foldager
localrepo: fix bugs in branchheads and add docstring...
r9475 '''return a (possibly filtered) list of heads for the given branch
Heads are returned in topological order, from newest to oldest.
If branch is None, use the dirstate branch.
If start is not None, return only heads reachable from start.
If closed is True, return heads that are marked as closed as well.
'''
Matt Mackall
use repo[changeid] to get a changectx
r6747 if branch is None:
branch = self[None].branch()
Benoit Boissinot
localrepo/branchcache: remove lbranchmap(), convert users to use utf-8 names...
r9675 branches = self.branchmap()
Pulkit Goyal
branchcache: introduce hasbranch()...
r42171 if not branches.hasbranch(branch):
Eric Hopper
Add option to heads to show only heads for current branch.
r4648 return []
John Mulligan
store all heads of a branch in the branch cache...
r7654 # the cache returns heads ordered lowest to highest
Brodie Rao
localrepo: refactor repo.branchheads() to use repo.branchmap().branchheads()
r20189 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
Eric Hopper
Add option to heads to show only heads for current branch.
r4648 if start is not None:
John Mulligan
store all heads of a branch in the branch cache...
r7654 # filter out the heads that cannot be reached from startrev
Sune Foldager
localrepo: fix bugs in branchheads and add docstring...
r9475 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
bheads = [h for h in bheads if h in fbheads]
John Mulligan
store all heads of a branch in the branch cache...
r7654 return bheads
Eric Hopper
Add option to heads to show only heads for current branch.
r4648
mpm@selenic.com
Break apart hg.py...
r1089 def branches(self, nodes):
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 if not nodes:
nodes = [self.changelog.tip()]
mpm@selenic.com
Break apart hg.py...
r1089 b = []
for n in nodes:
t = n
Martin Geisler
check-code: flag 0/1 used as constant Boolean expression
r14494 while True:
mpm@selenic.com
Break apart hg.py...
r1089 p = self.changelog.parents(n)
if p[1] != nullid or p[0] == nullid:
b.append((t, n, p[0], p[1]))
break
n = p[0]
return b
def between(self, pairs):
r = []
for top, bottom in pairs:
n, l, i = top, [], 0
f = 1
Matt Mackall
wire protocol: avoid infinite loop (issue1483)
r7708 while n != bottom and n != nullid:
mpm@selenic.com
Break apart hg.py...
r1089 p = self.changelog.parents(n)[0]
if i == f:
l.append(n)
f = f * 2
n = p
i += 1
r.append(l)
return r
Pierre-Yves David
push: pass a `pushoperation` object to localrepo.checkpush...
r20924 def checkpush(self, pushop):
Patrick Mezard
mq: factor out push conditions checks...
r13327 """Extensions can override this function if additional checks have
to be performed before pushing, or call it if they override push
command.
"""
FUJIWARA Katsunori
localrepo: introduce "prepushoutgoinghooks" to extend outgoing check easily...
r21043 @unfilteredpropertycache
def prepushoutgoinghooks(self):
Mads Kiilerich
localrepo: refactor prepushoutgoinghook to take a pushop...
r28876 """Return util.hooks consists of a pushop with repo, remote, outgoing
methods, which are called before pushing changesets.
FUJIWARA Katsunori
localrepo: introduce "prepushoutgoinghooks" to extend outgoing check easily...
r21043 """
return util.hooks()
Matt Mackall
pushkey: add localrepo support
r11368 def pushkey(self, namespace, key, old, new):
Pierre-Yves David
pushkey: gracefully handle prepushkey hook failure (issue4455)...
r23416 try:
Pierre-Yves David
pushkey: use hook arguments from transaction when one exists...
r24824 tr = self.currenttransaction()
hookargs = {}
if tr is not None:
hookargs.update(tr.hookargs)
Pulkit Goyal
py3: fix handling of keyword arguments at more places...
r36418 hookargs = pycompat.strkwargs(hookargs)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 hookargs['namespace'] = namespace
hookargs['key'] = key
hookargs['old'] = old
hookargs['new'] = new
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.hook(b'prepushkey', throw=True, **hookargs)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.HookAbort as exc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write_err(_(b"pushkey-abort: %s\n") % exc)
Pierre-Yves David
pushkey: gracefully handle prepushkey hook failure (issue4455)...
r23416 if exc.hint:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.write_err(_(b"(%s)\n") % exc.hint)
Pierre-Yves David
pushkey: gracefully handle prepushkey hook failure (issue4455)...
r23416 return False
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key))
Brodie Rao
pushkey: add hooks for pushkey/listkeys
r14102 ret = pushkey.push(self, namespace, key, old, new)
Augie Fackler
formatting: blacken the codebase...
r43346
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 def runhook(unused_success):
Augie Fackler
formatting: blacken the codebase...
r43346 self.hook(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pushkey',
Augie Fackler
formatting: blacken the codebase...
r43346 namespace=namespace,
key=key,
old=old,
new=new,
ret=ret,
)
Pierre-Yves David
pushkey: run hook after the lock release...
r23648 self._afterlock(runhook)
Brodie Rao
pushkey: add hooks for pushkey/listkeys
r14102 return ret
Matt Mackall
pushkey: add localrepo support
r11368
def listkeys(self, namespace):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.hook(b'prelistkeys', throw=True, namespace=namespace)
self.ui.debug(b'listing keys for "%s"\n' % namespace)
Brodie Rao
pushkey: add hooks for pushkey/listkeys
r14102 values = pushkey.list(self, namespace)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.hook(b'listkeys', namespace=namespace, values=values)
Brodie Rao
pushkey: add hooks for pushkey/listkeys
r14102 return values
Matt Mackall
pushkey: add localrepo support
r11368
Peter Arrenbrecht
wireproto: add test for new optional arg missing on server...
r14048 def debugwireargs(self, one, two, three=None, four=None, five=None):
Peter Arrenbrecht
debug: add debugwireargs to test argument passing over the wire...
r13720 '''used to test argument passing over the wire'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"%s %s %s %s %s" % (
Augie Fackler
formatting: blacken the codebase...
r43346 one,
two,
pycompat.bytestr(three),
pycompat.bytestr(four),
pycompat.bytestr(five),
)
Matt Mackall
pushkey: add localrepo support
r11368
Patrick Mezard
localrepo: add savecommitmessage() to write last-message.txt
r14529 def savecommitmessage(self, text):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fp = self.vfs(b'last-message.txt', b'wb')
Patrick Mezard
localrepo: add savecommitmessage() to write last-message.txt
r14529 try:
fp.write(text)
finally:
fp.close()
Augie Fackler
formatting: blacken the codebase...
r43346 return self.pathto(fp.name[len(self.root) + 1 :])
Patrick Mezard
localrepo: add savecommitmessage() to write last-message.txt
r14529
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 # used to avoid circular references so destructors work
Benoit Boissinot
localrepo: change aftertrans to be independant of the store path
r3790 def aftertrans(files):
renamefiles = [tuple(t) for t in files]
Augie Fackler
formatting: blacken the codebase...
r43346
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 def a():
FUJIWARA Katsunori
localrepo: use "vfs.rename()" instead of "util.rename()"...
r18952 for vfs, src, dest in renamefiles:
Ryan McElroy
localrepo: use tryunlink
r31550 # if src and dest refer to a same file, vfs.rename is a no-op,
# leaving both src and dest on disk. delete dest to make sure
# the rename couldn't be such a no-op.
vfs.tryunlink(dest)
Jun Wu
localrepo: handle rename with hardlinks properly...
r31209 try:
FUJIWARA Katsunori
localrepo: use "vfs.rename()" instead of "util.rename()"...
r18952 vfs.rename(src, dest)
Augie Fackler
formatting: blacken the codebase...
r43346 except OSError: # journal file does not yet exist
Alain Leufroy
localrepo: do not complain about missing journal files
r16441 pass
Augie Fackler
formatting: blacken the codebase...
r43346
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 return a
Augie Fackler
formatting: blacken the codebase...
r43346
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 def undoname(fn):
base, name = os.path.split(fn)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert name.startswith(b'journal')
return os.path.join(base, name.replace(b'journal', b'undo', 1))
Alexander Solovyov
fix bookmarks rollback behavior...
r14266
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585 def instance(ui, path, create, intents=None, createopts=None):
Martin von Zweigbergk
localrepo: use urllocalpath() for path to create repo too...
r39627 localpath = util.urllocalpath(path)
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 if create:
Martin von Zweigbergk
localrepo: use urllocalpath() for path to create repo too...
r39627 createrepository(ui, localpath, createopts=createopts)
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
Gregory Szorc
localrepo: create new function for instantiating a local repo object...
r39723 return makelocalrepository(ui, localpath, intents=intents)
Thomas Arendsen Hein
Whitespace/Tab cleanup
r3223
Augie Fackler
formatting: blacken the codebase...
r43346
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740 def islocal(path):
return True
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032 def defaultcreateopts(ui, createopts=None):
"""Populate the default creation options for a repository.
A dictionary of explicitly requested creation options can be passed
in. Missing keys will be populated.
"""
createopts = dict(createopts or {})
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'backend' not in createopts:
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032 # experimental config: storage.new-repo-backend
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 createopts[b'backend'] = ui.config(b'storage', b'new-repo-backend')
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032
return createopts
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032 def newreporequirements(ui, createopts):
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 """Determine the set of requirements for a new local repository.
Extensions can wrap this function to specify custom requirements for
new repositories.
"""
Gregory Szorc
localrepo: support shared repo creation...
r39884 # If the repo is being created from a shared repository, we copy
# its requirements.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'sharedrepo' in createopts:
requirements = set(createopts[b'sharedrepo'].requirements)
if createopts.get(b'sharedrelative'):
Pulkit Goyal
requirements: introduce constants for `shared` and `relshared` requirements...
r45946 requirements.add(requirementsmod.RELATIVE_SHARED_REQUIREMENT)
Gregory Szorc
localrepo: support shared repo creation...
r39884 else:
Pulkit Goyal
requirements: introduce constants for `shared` and `relshared` requirements...
r45946 requirements.add(requirementsmod.SHARED_REQUIREMENT)
Gregory Szorc
localrepo: support shared repo creation...
r39884
return requirements
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'backend' not in createopts:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'backend key not present in createopts; '
b'was defaultcreateopts() called?'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if createopts[b'backend'] != b'revlogv1':
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unable to determine repository requirements for '
b'storage backend: %s'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 % createopts[b'backend']
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 requirements = {b'revlogv1'}
if ui.configbool(b'format', b'usestore'):
requirements.add(b'store')
if ui.configbool(b'format', b'usefncache'):
requirements.add(b'fncache')
if ui.configbool(b'format', b'dotencode'):
requirements.add(b'dotencode')
revlog-compression: update the config to be a list...
r44866 compengines = ui.configlist(b'format', b'revlog-compression')
for compengine in compengines:
if compengine in util.compengines:
break
else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
revlog-compression: update the config to be a list...
r44866 b'compression engines %s defined by '
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'format.revlog-compression not available'
Augie Fackler
formatting: blacken the codebase...
r43346 )
revlog-compression: update the config to be a list...
r44866 % b', '.join(b'"%s"' % e for e in compengines),
Augie Fackler
formatting: blacken the codebase...
r43346 hint=_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'run "hg debuginstall" to list available '
b'compression engines'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
Gregory Szorc
localrepo: experimental support for non-zlib revlog compression...
r30818
# zlib is the historical default and doesn't need an explicit requirement.
revlog-compression: update the config to be a list...
r44866 if compengine == b'zstd':
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 requirements.add(b'revlog-compression-zstd')
elif compengine != b'zlib':
requirements.add(b'exp-compression-%s' % compengine)
Gregory Szorc
localrepo: experimental support for non-zlib revlog compression...
r30818
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 if scmutil.gdinitconfig(ui):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 requirements.add(b'generaldelta')
if ui.configbool(b'format', b'sparse-revlog'):
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 requirements.add(requirementsmod.SPARSEREVLOG_REQUIREMENT)
sidedata: introduce a new requirement to protect the feature...
r43298
sidedata: rename the configuration option to `exp-use-side-data`...
r43437 # experimental config: format.exp-use-side-data
if ui.configbool(b'format', b'exp-use-side-data'):
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
sidedatacopies: add a new requirement for storing copies into sidedata...
r43407 # experimental config: format.exp-use-copies-side-data-changeset
if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'):
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
requirements.add(requirementsmod.COPIESSDC_REQUIREMENT)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.configbool(b'experimental', b'treemanifest'):
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347
revlogv2 = ui.config(b'experimental', b'revlogv2')
if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
requirements.remove(b'revlogv1')
Gregory Szorc
revlog: skeleton support for version 2 revlogs...
r32697 # generaldelta is implied by revlogv2.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 requirements.discard(b'generaldelta')
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
Boris Feld
phases: add a repository requirement about internal phase...
r39334 # experimental config: format.internal-phase
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.configbool(b'format', b'internal-phase'):
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347
if createopts.get(b'narrowfiles'):
Pulkit Goyal
requirements: introduce new requirements related module...
r45932 requirements.add(requirementsmod.NARROW_REQUIREMENT)
Gregory Szorc
localrepo: add requirement when narrow files creation option present...
r39587
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if createopts.get(b'lfs'):
requirements.add(b'lfs')
if ui.configbool(b'format', b'bookmarks-in-store'):
Martin von Zweigbergk
bookmarks: keep bookmarks in .hg/store if new config set...
r42512 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
nodemap: move the main switch to the `format` section...
r45297 if ui.configbool(b'format', b'use-persistent-nodemap'):
Pulkit Goyal
localrepo: move requirements constant to requirements module...
r45933 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
nodemap: gate the feature behind a new requirement...
r45295
Pulkit Goyal
share: introduce config option to store requires in .hg/store...
r46055 # if share-safe is enabled, let's create the new repository with the new
# requirement
if ui.configbool(b'format', b'exp-share-safe'):
requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 return requirements
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
localrepo: only use 'bookmarksinstore' requirement if we have 'store'...
r45857 def checkrequirementscompat(ui, requirements):
""" Checks compatibility of repository requirements enabled and disabled.
Returns a set of requirements which needs to be dropped because dependend
requirements are not enabled. Also warns users about it """
dropped = set()
if b'store' not in requirements:
if bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT in requirements:
ui.warn(
_(
b'ignoring enabled \'format.bookmarks-in-store\' config '
b'beacuse it is incompatible with disabled '
b'\'format.usestore\' config\n'
)
)
dropped.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
Pulkit Goyal
requirements: introduce constants for `shared` and `relshared` requirements...
r45946 if (
requirementsmod.SHARED_REQUIREMENT in requirements
or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
):
Pulkit Goyal
localrepo: abort creating a shared repo if the source does not have store...
r45858 raise error.Abort(
_(
b"cannot create shared repository as source was created"
b" with 'format.usestore' config disabled"
)
)
Pulkit Goyal
share: introduce config option to store requires in .hg/store...
r46055 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
ui.warn(
_(
b"ignoring enabled 'format.exp-share-safe' config because "
b"it is incompatible with disabled 'format.usestore'"
b" config\n"
)
)
dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
Pulkit Goyal
localrepo: only use 'bookmarksinstore' requirement if we have 'store'...
r45857 return dropped
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585 def filterknowncreateopts(ui, createopts):
"""Filters a dict of repo creation options against options that are known.
Receives a dict of repo creation options and returns a dict of those
options that we don't know how to handle.
This function is called as part of repository creation. If the
returned dict contains any items, repository creation will not
be allowed, as it means there was a request to create a repository
with options not recognized by loaded code.
Extensions can wrap this function to filter out creation options
they know how to handle.
"""
Gregory Szorc
localrepo: support shared repo creation...
r39884 known = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'backend',
b'lfs',
b'narrowfiles',
b'sharedrepo',
b'sharedrelative',
b'shareditems',
b'shallowfilestore',
Gregory Szorc
localrepo: support shared repo creation...
r39884 }
Gregory Szorc
localrepo: add requirement when narrow files creation option present...
r39587
return {k: v for k, v in createopts.items() if k not in known}
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
localrepo: move check for existing repo into createrepository()...
r39626 def createrepository(ui, path, createopts=None):
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 """Create a new repository in a vfs.
Martin von Zweigbergk
localrepo: move check for existing repo into createrepository()...
r39626 ``path`` path to the new repo's working directory.
Martin von Zweigbergk
localrepo: fix a mixmatched arg name in createrepository() docstring...
r39616 ``createopts`` options for the new repository.
Gregory Szorc
localrepo: support shared repo creation...
r39884
The following keys for ``createopts`` are recognized:
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032 backend
The storage backend to use.
Matt Harbison
lfs: autoload the extension when cloning from repo with lfs enabled...
r40360 lfs
Repository will be created with ``lfs`` requirement. The lfs extension
will automatically be loaded when the repository is accessed.
Gregory Szorc
localrepo: support shared repo creation...
r39884 narrowfiles
Set up repository to support narrow file storage.
sharedrepo
Repository object from which storage should be shared.
sharedrelative
Boolean indicating if the path to the shared repo should be
stored as relative. By default, the pointer to the "parent" repo
is stored as an absolute path.
Gregory Szorc
localrepo: support writing shared file (API)...
r39885 shareditems
Set of items to share to the new repository (in addition to storage).
Gregory Szorc
localrepo: support marking repos as having shallow file storage...
r40426 shallowfilestore
Indicates that storage for files should be shallow (not all ancestor
revisions are known).
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 """
Gregory Szorc
localrepo: define storage backend in creation options (API)...
r40032 createopts = defaultcreateopts(ui, createopts=createopts)
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585
unknownopts = filterknowncreateopts(ui, createopts)
if not isinstance(unknownopts, dict):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'filterknowncreateopts() did not return a dict'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585
if unknownopts:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unable to create repository because of unknown '
b'creation option: %s'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 % b', '.join(sorted(unknownopts)),
hint=_(b'is a required extension not loaded?'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hg: allow extra arguments to be passed to repo creation (API)...
r39585
requirements = newreporequirements(ui, createopts=createopts)
Pulkit Goyal
localrepo: only use 'bookmarksinstore' requirement if we have 'store'...
r45857 requirements -= checkrequirementscompat(ui, requirements)
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
Martin von Zweigbergk
localrepo: move check for existing repo into createrepository()...
r39626 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
Martin von Zweigbergk
localrepo: move check for existing repo into createrepository()...
r39626 if hgvfs.exists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoError(_(b'repository %s already exists') % path)
if b'sharedrepo' in createopts:
sharedpath = createopts[b'sharedrepo'].sharedpath
if createopts.get(b'sharedrelative'):
Gregory Szorc
localrepo: support shared repo creation...
r39884 try:
sharedpath = os.path.relpath(sharedpath, hgvfs.base)
except (IOError, ValueError) as e:
# ValueError is raised on Windows if the drive letters differ
# on each path.
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'cannot calculate relative path'),
Augie Fackler
formatting: blacken the codebase...
r43346 hint=stringutil.forcebytestr(e),
)
Gregory Szorc
localrepo: support shared repo creation...
r39884
Gregory Szorc
localrepo: validate directories before creating any...
r39883 if not wdirvfs.exists():
wdirvfs.makedirs()
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 hgvfs.makedir(notindexed=True)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'sharedrepo' not in createopts:
Boris Feld
cache: create `cache` directory at init time...
r40824 hgvfs.mkdir(b'cache')
Boris Feld
cache: create `wcache` directory at init time...
r40825 hgvfs.mkdir(b'wcache')
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'store' in requirements and b'sharedrepo' not in createopts:
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 hgvfs.mkdir(b'store')
# We create an invalid changelog outside the store so very old
# Mercurial versions (which didn't know about the requirements
# file) encounter an error on reading the changelog. This
# effectively locks out old clients and prevents them from
# mucking with a repo in an unknown format.
#
# The revlog header has version 2, which won't be recognized by
# such old clients.
Augie Fackler
formatting: blacken the codebase...
r43346 hgvfs.append(
b'00changelog.i',
b'\0\0\0\2 dummy changelog to prevent using the old repo '
b'layout',
)
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584
Pulkit Goyal
share: introduce config option to store requires in .hg/store...
r46055 # Filter the requirements into working copy and store ones
wcreq, storereq = scmutil.filterrequirements(requirements)
# write working copy ones
scmutil.writerequires(hgvfs, wcreq)
# If there are store requirements and the current repository
# is not a shared one, write stored requirements
# For new shared repository, we don't need to write the store
# requirements as they are already present in store requires
if storereq and b'sharedrepo' not in createopts:
storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
scmutil.writerequires(storevfs, storereq)
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642
Gregory Szorc
localrepo: support shared repo creation...
r39884 # Write out file telling readers where to find the shared store.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'sharedrepo' in createopts:
Gregory Szorc
localrepo: support shared repo creation...
r39884 hgvfs.write(b'sharedpath', sharedpath)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if createopts.get(b'shareditems'):
shared = b'\n'.join(sorted(createopts[b'shareditems'])) + b'\n'
Gregory Szorc
localrepo: support writing shared file (API)...
r39885 hgvfs.write(b'shared', shared)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642 def poisonrepository(repo):
"""Poison a repository instance so it can no longer be used."""
# Perform any cleanup on the instance.
repo.close()
# Our strategy is to replace the type of the object with one that
# has all attribute lookups result in error.
#
# But we have to allow the close() method because some constructors
# of repos call close() on repo references.
class poisonedrepository(object):
def __getattribute__(self, item):
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if item == 'close':
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642 return object.__getattribute__(self, item)
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ProgrammingError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'repo instances should not be used after unshare'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
hg: don't reuse repo instance after unshare()...
r39642
def close(self):
pass
# We may have a repoview, which intercepts __setattr__. So be sure
# we operate at the lowest level possible.
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 object.__setattr__(repo, '__class__', poisonedrepository)