##// END OF EJS Templates
dirstate: update backup functions to take full backup filename...
dirstate: update backup functions to take full backup filename Update the dirstate functions so that the caller supplies the full backup filename rather than just a prefix and suffix. The localrepo code was already hard-coding the fact that the backup name must be (exactly prefix + "dirstate" + suffix): it relied on this in _journalfiles() and undofiles(). Making the caller responsible for specifying the full backup name removes the need for the localrepo code to assume that dirstate._filename is always "dirstate". Differential Revision: https://phab.mercurial-scm.org/D68

File last commit:

r33440:ec306bc6 default
r33440:ec306bc6 default
Show More
localrepo.py
2246 lines | 85.3 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
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1...
r29341 import hashlib
Gregory Szorc
localrepo: use absolute_import
r27522 import inspect
import os
import random
import time
import weakref
from .i18n import _
from .node import (
hex,
nullid,
short,
)
from . import (
bookmarks,
branchmap,
bundle2,
changegroup,
changelog,
Pierre-Yves David
color: initialize color for the localrepo ui...
r31111 color,
Gregory Szorc
localrepo: use absolute_import
r27522 context,
dirstate,
Augie Fackler
localrepo: refer to dirstateguard by its new name
r30492 dirstateguard,
Gregory Szorc
localrepo: use absolute_import
r27522 encoding,
error,
exchange,
extensions,
filelog,
hook,
lock as lockmod,
manifest,
match as matchmod,
merge as mergemod,
Augie Fackler
localrepo: refer to checkunresolved by its new name
r30496 mergeutil,
Gregory Szorc
localrepo: use absolute_import
r27522 namespaces,
obsolete,
pathutil,
peer,
phases,
pushkey,
Augie Fackler
localrepo: ensure transaction id is fully bytes on py3
r31508 pycompat,
Gregory Szorc
localrepo: use absolute_import
r27522 repoview,
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: use absolute_import
r27522 store,
subrepo,
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 )
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()
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
"""
def __get__(self, repo, type=None):
Martijn Pieters
scmutil: allow access to filecache descriptor on class...
r29373 if repo is None:
return self
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 return super(_basefilecache, self).__get__(repo.unfiltered(), type)
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014 def __set__(self, repo, value):
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 return super(_basefilecache, self).__set__(repo.unfiltered(), value)
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014 def __delete__(self, repo):
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 return super(_basefilecache, self).__delete__(repo.unfiltered())
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 class repofilecache(_basefilecache):
"""filecache for files in .hg but outside of .hg/store"""
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:
_cachedfiles.add((path, 'plain'))
FUJIWARA Katsunori
localrepo: factor out base of filecache annotation class...
r33173 def join(self, obj, fname):
return obj.vfs.join(fname)
class storecache(_basefilecache):
Idan Kamara
filecache: refactor path join logic to a function...
r16198 """filecache for files in the store"""
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:
_cachedfiles.add((path, ''))
Idan Kamara
filecache: refactor path join logic to a function...
r16198 def join(self, obj, fname):
return obj.sjoin(fname)
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
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
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())
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"""
def wrapper(repo, *args, **kwargs):
return orig(repo.unfiltered(), *args, **kwargs)
return wrapper
Martin von Zweigbergk
cleanup: use set literals...
r32291 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
'unbundle'}
legacycaps = moderncaps.union({'changegroupsubset'})
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
class localpeer(peer.peerrepository):
'''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):
if caps is None:
caps = moderncaps.copy()
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 peer.peerrepository.__init__(self)
Kevin Bullock
filtering: rename filters to their antonyms...
r18382 self._repo = repo.filtered('served')
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 self.ui = repo.ui
self._caps = repo._restrictcapabilities(caps)
self.requirements = repo.requirements
self.supportedformats = repo.supportedformats
def close(self):
self._repo.close()
def _capabilities(self):
return self._caps
def local(self):
return self._repo
Sune Foldager
peer: introduce canpush and improve error message
r17193 def canpush(self):
return True
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def url(self):
return self._repo.url()
def lookup(self, key):
return self._repo.lookup(key)
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
def heads(self):
Pierre-Yves David
clfilter: drop extra filtering in localpeer...
r18279 return self._repo.heads()
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def known(self, nodes):
return self._repo.known(nodes)
Pierre-Yves David
localpeer: propagate bundlecaps in getbundle call...
r20953 def getbundle(self, source, heads=None, common=None, bundlecaps=None,
Martin von Zweigbergk
localrepo.getbundle: drop unused 'format' argument...
r24639 **kwargs):
Gregory Szorc
exchange: refactor APIs to obtain bundle data (API)...
r30187 chunks = exchange.getbundlechunks(self._repo, source, heads=heads,
common=common, bundlecaps=bundlecaps,
**kwargs)
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:
return changegroup.getunbundler('01', cb, None)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
# TODO We might want to move the next two calls into legacypeer and add
# unbundle instead.
Pierre-Yves David
localrepo: add unbundle support...
r20969 def unbundle(self, cg, heads, url):
"""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:
cg = exchange.readbundle(self.ui, cg, None)
ret = exchange.unbundle(self._repo, cg, heads, 'push', url)
if util.safehasattr(ret, 'getchunks'):
# 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:
Pierre-Yves David
bundle2: gracefully handle PushRaced error during unbundle...
r21186 raise error.ResponseError(_('push failed:'), str(exc))
Pierre-Yves David
localrepo: add unbundle support...
r20969
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def lock(self):
return self._repo.lock()
def pushkey(self, namespace, key, old, new):
return self._repo.pushkey(namespace, key, old, new)
def listkeys(self, namespace):
return self._repo.listkeys(namespace)
def debugwireargs(self, one, two, three=None, four=None, five=None):
'''used to test argument passing over the wire'''
return "%s %s %s %s %s" % (one, two, three, four, five)
class locallegacypeer(localpeer):
'''peer extension which implements legacy methods too; used for tests with
restricted capabilities'''
def __init__(self, repo):
Pierre-Yves David
localrepo: rename capability set to lower case....
r20776 localpeer.__init__(self, repo, caps=legacycaps)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def branches(self, nodes):
return self._repo.branches(nodes)
def between(self, pairs):
return self._repo.between(pairs)
def changegroup(self, basenodes, source):
Pierre-Yves David
localrepo: move the changegroup method in changegroup module...
r20931 return changegroup.changegroup(self._repo, basenodes, source)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def changegroupsubset(self, bases, heads, source):
Pierre-Yves David
localrepo: move the changegroupsubset method in changegroup module...
r20927 return changegroup.changegroupsubset(self._repo, bases, heads, source)
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
Gregory Szorc
revlog: skeleton support for version 2 revlogs...
r32697 # Increment the sub-version when the revlog v2 format changes to lock out old
# clients.
REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 class localrepository(object):
Gregory Szorc
localrepo: reformat set literals...
r32315 supportedformats = {
'revlogv1',
'generaldelta',
'treemanifest',
'manifestv2',
Gregory Szorc
revlog: skeleton support for version 2 revlogs...
r32697 REVLOGV2_REQUIREMENT,
Gregory Szorc
localrepo: reformat set literals...
r32315 }
_basesupported = supportedformats | {
'store',
'fncache',
'shared',
'relshared',
'dotencode',
}
openerreqs = {
'revlogv1',
'generaldelta',
'treemanifest',
'manifestv2',
}
Bryan O'Sullivan
localrepo: make requirements and openerreqs mutable by subclasses...
r17137
FUJIWARA Katsunori
localrepo: invoke only feature setup functions for enabled extensions...
r19928 # a list of (ui, featureset) functions.
# only functions defined in module of enabled extensions are invoked
FUJIWARA Katsunori
localrepo: make supported features manageable in each repositories individually...
r19778 featuresetupfuncs = set()
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.
'hgrc',
'requires',
# XXX cache is a complicatged business someone
# should investigate this in depth at some point
'cache/',
# XXX shouldn't be dirstate covered by the wlock?
'dirstate',
# 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
'bisect.state',
}
Pulkit Goyal
localrepository: remove None as default value of path argument in __init__()...
r30571 def __init__(self, baseui, path, create=False):
Drew Gottlieb
localrepo: eliminate local requirements var in init...
r24918 self.requirements = set()
Gregory Szorc
localrepo: move filtername to __init__...
r32730 self.filtername = None
Ryan McElroy
localrepo: improve vfs documentation...
r31536 # wvfs: rooted at the repository root, used to access the working copy
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.localrepo'...
r31231 self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
Ryan McElroy
localrepo: improve vfs documentation...
r31536 # vfs: rooted at .hg, used to access repo files outside of .hg/store
Pierre-Yves David
localrepo: add some comment about role of various vfs object...
r31144 self.vfs = None
Ryan McElroy
localrepo: improve vfs documentation...
r31536 # svfs: usually rooted at .hg/store, used to access repository history
# If this is a shared repository, this vfs may point to another
# repository's .hg/store directory.
Pierre-Yves David
localrepo: add some comment about role of various vfs object...
r31144 self.svfs = None
FUJIWARA Katsunori
localrepo: use path expansion API via vfs...
r17157 self.root = self.wvfs.base
FUJIWARA Katsunori
localrepo: use "self.wvfs.join()" instead of "os.path.join()"...
r17158 self.path = self.wvfs.join(".hg")
Benoit Boissinot
move code around
r3850 self.origroot = path
auditor: add simple comment about repo.auditor and al...
r33254 # These auditor are not used by the vfs,
# only used when writing this comment: basectx.match
Augie Fackler
pathutil: tease out a new library to break an import cycle from canonpath use
r20033 self.auditor = pathutil.pathauditor(self.root, self._checknested)
Pierre-Yves David
localrepo: add a second auditor without file system check...
r27233 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
realfs=False)
Matt Mackall
repo: set up ui and extensions earlier
r8797 self.baseui = baseui
self.ui = baseui.copy()
Simon Heimberg
localrepo: prevent to copy repo local config, copy baseui instead...
r20082 self.ui.copy = baseui.copy # prevent copying repo configuration
Boris Feld
repovfs: add a ward to check if locks are properly taken...
r33436 self.vfs = vfsmod.vfs(self.path)
if (self.ui.configbool('devel', 'all-warnings') or
self.ui.configbool('devel', 'check-locks')):
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 = []
Matt Mackall
repo: set up ui and extensions earlier
r8797 try:
Pierre-Yves David
localrepo: directly use repo.vfs.join...
r31319 self.ui.readconfig(self.vfs.join("hgrc"), self.root)
Jun Wu
localrepo: move extension loading to a separate method...
r30989 self._loadextensions()
Matt Mackall
repo: set up ui and extensions earlier
r8797 except IOError:
pass
mpm@selenic.com
Break apart hg.py...
r1089
FUJIWARA Katsunori
localrepo: make supported features manageable in each repositories individually...
r19778 if self.featuresetupfuncs:
self.supported = set(self._basesupported) # use private copy
FUJIWARA Katsunori
localrepo: invoke only feature setup functions for enabled extensions...
r19928 extmods = set(m.__name__ for n, m
in extensions.extensions(self.ui))
FUJIWARA Katsunori
localrepo: make supported features manageable in each repositories individually...
r19778 for setupfunc in self.featuresetupfuncs:
FUJIWARA Katsunori
localrepo: invoke only feature setup functions for enabled extensions...
r19928 if setupfunc.__module__ in extmods:
setupfunc(self.ui, self.supported)
FUJIWARA Katsunori
localrepo: make supported features manageable in each repositories individually...
r19778 else:
self.supported = self._basesupported
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
Gregory Szorc
localrepo: experimental support for non-zlib revlog compression...
r30818 # Add compression engines.
for name in util.compengines:
engine = util.compengines[name]
if engine.revlogheader():
self.supported.add('exp-compression-%s' % name)
FUJIWARA Katsunori
localrepo: use file API via vfs while ensuring repository directory...
r17161 if not self.vfs.isdir():
Benoit Boissinot
localrepo: move the repo creation code, fail if the repo exists
r3035 if create:
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 self.requirements = newreporequirements(self)
Gregory Szorc
localrepo: isolate requirements determination from side effects...
r28163
if not self.wvfs.exists():
self.wvfs.makedirs()
self.vfs.makedir(notindexed=True)
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 if 'store' in self.requirements:
Gregory Szorc
localrepo: isolate requirements determination from side effects...
r28163 self.vfs.mkdir("store")
# create an invalid changelog
self.vfs.append(
"00changelog.i",
'\0\0\0\2' # represents revlogv2
' dummy changelog to prevent using the old repo layout'
)
Benoit Boissinot
localrepo: move the repo creation code, fail if the repo exists
r3035 else:
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("repository %s not found") % path)
Benoit Boissinot
localrepo: move the repo creation code, fail if the repo exists
r3035 elif create:
Matt Mackall
error: move repo errors...
r7637 raise error.RepoError(_("repository %s already exists") % path)
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 else:
try:
Drew Gottlieb
localrepo: eliminate local requirements var in init...
r24918 self.requirements = scmutil.readrequires(
self.vfs, self.supported)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Benoit Boissinot
add "requires" file to the repo, specifying the requirements
r3851 if inst.errno != errno.ENOENT:
raise
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
repo: add internal support for sharing store directories...
r8799 self.sharedpath = self.path
try:
Dan Villiom Podlaski Christiansen
share: add --relative flag to store a relative path to the source...
r31133 sharedpath = self.vfs.read("sharedpath").rstrip('\n')
if 'relshared' in self.requirements:
sharedpath = self.vfs.join(sharedpath)
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.localrepo'...
r31231 vfs = vfsmod.vfs(sharedpath, realpath=True)
FUJIWARA Katsunori
localrepo: use vfs instead of "os.path.*" in sharedpath checking...
r18946 s = vfs.base
if not vfs.exists():
Matt Mackall
repo: add internal support for sharing store directories...
r8799 raise error.RepoError(
Dongsheng Song
Fix warning: Seen unexpected token "%"
r8908 _('.hg/sharedpath points to nonexistent directory %s') % s)
Matt Mackall
repo: add internal support for sharing store directories...
r8799 self.sharedpath = s
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Matt Mackall
repo: add internal support for sharing store directories...
r8799 if inst.errno != errno.ENOENT:
raise
Drew Gottlieb
localrepo: eliminate local requirements var in init...
r24918 self.store = store.store(
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.localrepo'...
r31231 self.requirements, self.sharedpath, vfsmod.vfs)
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
FUJIWARA Katsunori
localrepo: use "vfs" constructor/field for initialization around "store"
r17654 self.vfs.createmode = self.store.createmode
Boris Feld
reposvfs: add a ward to check if locks are properly taken...
r33437 if (self.ui.configbool('devel', 'all-warnings') or
self.ui.configbool('devel', 'check-locks')):
if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs
self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
else: # standard vfs
self.svfs.audit = self._getsvfsward(self.svfs.audit)
Drew Gottlieb
localrepo: make _applyrequirements more specific...
r24915 self._applyopenerreqs()
Sune Foldager
localrepo: factor out requirement application and write
r12295 if create:
self._writerequirements()
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
Pierre-Yves David
branchmap: enable caching for filtered version too...
r18189 self._branchcaches = {}
Durham Goode
revbranchcache: move out of branchmap onto localrepo...
r24373 self._revbranchcache = None
Matt Mackall
unify encode/decode filter routines
r4004 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 = []
Gregory Szorc
localrepo: cache types for filtered repos (issue5043)...
r33389 # Cache of types representing filtered repos.
self._filteredrepotypes = weakref.WeakKeyDictionary()
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 = {}
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)
def checkvfs(path, mode=None):
ret = origfunc(path, mode=mode)
repo = rref()
if (repo is None
or not util.safehasattr(repo, '_wlockref')
or not util.safehasattr(repo, '_lockref')):
return
if mode in (None, 'r', 'rb'):
return
if path.startswith(repo.path):
# truncate name relative to the repository (.hg)
path = path[len(repo.path) + 1:]
if path.startswith('journal.'):
# journal is covered by 'lock'
if repo._currentlock(repo._lockref) is None:
repo.ui.develwarn('write with no lock: "%s"' % path,
stacklevel=2)
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
repo.ui.develwarn('write with no wlock: "%s"' % path,
stacklevel=2)
return ret
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)
def checksvfs(path, mode=None):
ret = origfunc(path, mode=mode)
repo = rref()
if repo is None or not util.safehasattr(repo, '_lockref'):
return
if mode in (None, 'r', 'rb'):
return
if path.startswith(repo.sharedpath):
# truncate name relative to the repository (.hg)
path = path[len(repo.sharedpath) + 1:]
if repo._currentlock(repo._lockref) is None:
repo.ui.develwarn('write with no lock: "%s"' % path,
stacklevel=3)
return ret
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()
Jun Wu
localrepo: move extension loading to a separate method...
r30989 def _loadextensions(self):
extensions.loadall(self.ui)
Durham Goode
revbranchcache: write cache even during read operations...
r24378 def _writecaches(self):
if self._revbranchcache:
self._revbranchcache.write()
Peter Arrenbrecht
peer: introduce real peer classes...
r17192
def _restrictcapabilities(self, caps):
Pierre-Yves David
bundle2: advertise bundle2 by default...
r24696 if self.ui.configbool('experimental', 'bundle2-advertise', True):
Pierre-Yves David
bundle2: allow pulling changegroups using bundle2...
r20955 caps = set(caps)
Pierre-Yves David
bundle2: introduce a `getrepocaps` to retrieve the bundle2 caps of a repo...
r22342 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self))
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 caps.add('bundle2=' + urlreq.quote(capsblob))
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 return caps
Drew Gottlieb
localrepo: make _applyrequirements more specific...
r24915 def _applyopenerreqs(self):
self.svfs.options = dict((r, 1) for r in self.requirements
Bryan O'Sullivan
localrepo: make requirements and openerreqs mutable by subclasses...
r17137 if r in self.openerreqs)
Matt Mackall
localrepo: mark format options
r25839 # experimental config: format.chunkcachesize
Brodie Rao
revlog: allow tuning of the chunk cache size (via format.chunkcachesize)...
r20180 chunkcachesize = self.ui.configint('format', 'chunkcachesize')
if chunkcachesize is not None:
Angel Ezquerra
localrepo: remove all internal uses of localrepo.sopener...
r23853 self.svfs.options['chunkcachesize'] = chunkcachesize
Matt Mackall
localrepo: mark format options
r25839 # experimental config: format.maxchainlen
Augie Fackler
localrepo: rename revlog.maxchainlen to format.maxchainlen...
r23256 maxchainlen = self.ui.configint('format', 'maxchainlen')
Mateusz Kwapich
revlog: add config variable for limiting delta-chain length...
r23255 if maxchainlen is not None:
Angel Ezquerra
localrepo: remove all internal uses of localrepo.sopener...
r23853 self.svfs.options['maxchainlen'] = maxchainlen
Matt Mackall
localrepo: mark format options
r25839 # experimental config: format.manifestcachesize
Durham Goode
manifest: make lru size configurable...
r24033 manifestcachesize = self.ui.configint('format', 'manifestcachesize')
if manifestcachesize is not None:
self.svfs.options['manifestcachesize'] = manifestcachesize
Durham Goode
revlog: add an aggressivemergedelta option...
r26118 # experimental config: format.aggressivemergedeltas
aggressivemergedeltas = self.ui.configbool('format',
configitems: register the 'format.aggressivemergedeltas' config
r33232 'aggressivemergedeltas')
Durham Goode
revlog: add an aggressivemergedelta option...
r26118 self.svfs.options['aggressivemergedeltas'] = aggressivemergedeltas
Pierre-Yves David
format: introduce 'format.usegeneraldelta`...
r26907 self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui)
revlog: add an experimental option to mitigated delta issues (issue5480)...
r33202 chainspan = self.ui.configbytes('experimental', 'maxdeltachainspan', -1)
if 0 <= chainspan:
self.svfs.options['maxdeltachainspan'] = chainspan
Sune Foldager
localrepo: factor out requirement application and write
r12295
Gregory Szorc
localrepo: experimental support for non-zlib revlog compression...
r30818 for r in self.requirements:
if r.startswith('exp-compression-'):
self.svfs.options['compengine'] = r[len('exp-compression-'):]
Gregory Szorc
revlog: skeleton support for version 2 revlogs...
r32697 # TODO move "revlogv2" to openerreqs once finalized.
if REVLOGV2_REQUIREMENT in self.requirements:
self.svfs.options['revlogv2'] = True
Sune Foldager
localrepo: factor out requirement application and write
r12295 def _writerequirements(self):
Drew Gottlieb
requires: move requires file writing func from localrepo to scmutil...
r24934 scmutil.writerequires(self.vfs, self.requirements)
Sune Foldager
localrepo: factor out requirement application and write
r12295
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
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:
FUJIWARA Katsunori
windows: use normalized path to check repository nesting...
r15722 prefix = '/'.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)
return sub.checknested(subpath[len(prefix) + 1:])
else:
parts.pop()
return False
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 def peer(self):
return localpeer(self) # not cached to avoid reference cycle
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
Pierre-Yves David
clfilter: add actual repo filtering mechanism...
r18100 def filtered(self, name):
"""Return a filtered version of a repository"""
Gregory Szorc
localrepo: cache types for filtered repos (issue5043)...
r33389 # Python <3.4 easily leaks types via __mro__. See
# https://bugs.python.org/issue17950. We cache dynamically
# created types so this method doesn't leak on every
# invocation.
key = self.unfiltered().__class__
if key not in self._filteredrepotypes:
# Build a new type with the repoview mixin and the base
# class of this repo. Give it a name containing the
# filter name to aid debugging.
bases = (repoview.repoview, key)
Martin von Zweigbergk
py3: make localrepo filtered repo cache work on py3...
r33403 cls = type(r'%sfilteredrepo' % name, bases, {})
Gregory Szorc
localrepo: cache types for filtered repos (issue5043)...
r33389 self._filteredrepotypes[key] = cls
return self._filteredrepotypes[key](self, name)
Pierre-Yves David
clfilter: add actual repo filtering mechanism...
r18100
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 @repofilecache('bookmarks', 'bookmarks.current')
Matt Mackall
bookmarks: move property methods into localrepo
r13355 def _bookmarks(self):
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 return bookmarks.bmstore(self)
Matt Mackall
bookmarks: move property methods into localrepo
r13355
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
Yuya Nishihara
localrepo: recreate phasecache if changelog was modified (issue4855)...
r26405 # _phaserevs and _phasesets depend on changelog. what we need is to
# call _phasecache.invalidate() if '00changelog.i' was changed, but it
# can't be easily expressed in filecache mechanism.
@storecache('phaseroots', '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
Pierre-Yves.David@ens-lyon.org
obsolete: introduction of obsolete markers...
r17070 @storecache('obsstore')
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
Idan Kamara
filecache: refactor path join logic to a function...
r16198 @storecache('00changelog.i')
Matt Mackall
localrepo: use propertycache
r8260 def changelog(self):
Gregory Szorc
changelog: load pending file directly...
r32292 return changelog.changelog(self.svfs,
trypending=txnutil.mayhavepending(self.root))
Matt Mackall
localrepo: use propertycache
r8260
Durham Goode
manifest: move manifest creation to a helper function...
r30218 def _constructmanifest(self):
# This is a temporary function while we migrate from manifest to
# manifestlog. It allows bundlerepo and unionrepo to intercept the
# manifest creation.
Durham Goode
manifest: delete manifest.manifest class...
r30377 return manifest.manifestrevlog(self.svfs)
Matt Mackall
localrepo: use propertycache
r8260
Durham Goode
manifest: make manifestlog a storecache...
r30219 @storecache('00manifest.i')
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 def manifestlog(self):
Durham Goode
manifest: use property instead of field for manifest revlog storage...
r29826 return manifest.manifestlog(self.svfs, self)
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825
Pierre-Yves David
clfilter: ensure that filecache on localrepo is unfiltered...
r18014 @repofilecache('dirstate')
Matt Mackall
localrepo: use propertycache
r8260 def dirstate(self):
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 sparsematchfn = lambda: sparse.matcher(self)
Siddharth Agarwal
localrepo: move dirstate validate function to class scope...
r26155 return dirstate.dirstate(self.vfs, self.ui, self.root,
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 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
self.ui.warn(_("warning: ignoring unknown"
" working parent %s!\n") % short(node))
return nullid
Vadim Gelfer
support hooks written in python....
r2155
Matt Mackall
use repo[changeid] to get a changectx
r6747 def __getitem__(self, changeid):
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)
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
Eric Sumner
localrepo.__getitem__: add slicing support...
r23630 return [context.changectx(self, i)
for i in xrange(*changeid.indices(len(self)))
if i not in self.changelog.filteredrevs]
Yuya Nishihara
localrepo: map integer and hex wdir identifiers to workingctx...
r32658 try:
return context.changectx(self, changeid)
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
error.LookupError is raised if an ambiguous node specified.
"""
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
Alexander Solovyov
localrepo: support 'rev in repo' syntax
r9924 except error.RepoLookupError:
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):
return len(self.changelog)
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
Returns a revset.abstractsmartset, which is a list-like interface
Gregory Szorc
localrepo: improve docstring for revset methods...
r27071 that contains integer revisions.
'''
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 expr = revsetlang.formatspec(expr, *args)
Matt Mackall
localrepo: add revs helper method
r15403 m = revset.match(None, expr)
Yuya Nishihara
revset: make match function initiate query from full set by default...
r24114 return m(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 '''
if user:
Jun Wu
revset: make repo.anyrevs accept customized alias override (API)...
r33336 m = revset.matchany(self.ui, specs, repo=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):
return 'file:' + self.root
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
for k, v in tags.iteritems():
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 try:
# ignore tags to unknown nodes
self.changelog.rev(v)
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
mpm@selenic.com
Break apart hg.py...
r1089
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
tagtypes = dict((tag, '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 = {}
Greg Ward
localrepo: improve readability of _findtags(), readtags() (issue548)....
r9147 for (name, (node, hist)) in alltags.iteritems():
if node != nullid:
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 tags[encoding.tolocal(name)] = node
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 tags['tip'] = self.changelog.tip()
Greg Ward
tags: support 'instant' tag retrieval (issue548)...
r9152 tagtypes = dict([(encoding.tolocal(name), value)
for (name, value) in tagtypes.iteritems()])
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 = []
for t, n in self.tags().iteritems():
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 = {}
Matt Mackall
tags: defer tag validation until repo.tags() is called...
r16371 for t, n in self._tagscache.tags.iteritems():
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936 nodetagscache.setdefault(n, []).append(t)
for tags in nodetagscache.itervalues():
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"""
David Soria Parra
context: add method to return all bookmarks pointing to a node
r13384 marks = []
for bookmark, n in self._bookmarks.iteritems():
if n == node:
marks.append(bookmark)
return sorted(marks)
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'''
Pierre-Yves David
branchmap: enable caching for filtered version too...
r18189 branchmap.updatecache(self)
return self._branchcaches[self.filtername]
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:
raise error.RepoLookupError(_("unknown branch '%s'") % branch)
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):
Matt Mackall
localrepo: lookup now goes through context
r16378 return self[key].node()
mpm@selenic.com
Break apart hg.py...
r1089
Steve Losh
commands: add more robust support for 'hg log -b' (issue2078)...
r10960 def lookupbranch(self, key, remote=None):
repo = remote or self
if key in repo.branchmap():
return key
repo = (remote and remote.local()) and remote or self
return repo[key].branch()
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
nm = cl.nodemap
filtered = cl.filteredrevs
Pierre-Yves David
phases: make secret changeset undiscoverable in all case...
r15889 result = []
for n in nodes:
r = nm.get(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
return self.ui.configbool('phases', 'publish', True, 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
return not self.filtered('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:
return 'store'
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
def file(self, f):
Thomas Arendsen Hein
Cleanup of indentation, spacing, newlines, strings and line length
r1615 if f[0] == '/':
f = f[1:]
Angel Ezquerra
localrepo: remove all internal uses of localrepo.sopener...
r23853 return filelog.filelog(self.svfs, f)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
context: avoid using None for working parent
r6739 def changectx(self, changeid):
Matt Mackall
use repo[changeid] to get a changectx
r6747 return self[changeid]
Matt Mackall
merge: use new working context object in update
r3218
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 def setparents(self, p1, p2=nullid):
Augie Fackler
localrepo: migrate to context manager for changing dirstate parents
r32350 with self.dirstate.parentchange():
copies = self.dirstate.setparents(p1, p2)
pctx = self[p1]
if copies:
# Adjust copy records, the dirstate cannot do it, it
# requires access to parents manifests. Preserve them
# only for entries added to first parent.
for f in copies:
if f not in pctx and copies[f] in pctx:
self.dirstate.copy(copies[f], f)
if p2 == nullid:
for f, s in sorted(self.dirstate.copies().items()):
if f not in pctx and s not in pctx:
self.dirstate.copy(None, f)
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551
Matt Mackall
Add context helper functions to localrepo
r2564 def filectx(self, path, changeid=None, fileid=None):
"""changeid can be a changeset revision, node, or tag.
fileid can be a file revision or node."""
return context.filectx(self, path, changeid, fileid)
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):
Matt Mackall
unify encode/decode filter routines
r4004 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):
Mads Kiilerich
Make it possible to disable filtering for a pattern....
r7226 if cmd == '!':
continue
Benoit Boissinot
style: use consistent variable names (*mod) with imports which would shadow
r10651 mf = matchmod.match(self.root, '', [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
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 for name, filterfn in self._datafilters.iteritems():
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
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 params = cmd[len(name):].lstrip()
Patrick Mezard
Register data filters in a localrepo instead of util...
r5966 break
if not fn:
Jesse Glick
Provide better context for custom Python encode/decode filters....
r5967 fn = lambda s, c, **kwargs: util.filter(s, c)
# Wrap old filters not supporting keyword arguments
if not inspect.getargspec(fn)[2]:
oldfn = fn
fn = lambda s, c, **kwargs: oldfn(s, c)
Jesse Glick
Strip filter name from command before passing to filter function....
r6066 l.append((mf, fn, params))
Matt Mackall
unify encode/decode filter routines
r4004 self.filterpats[filter] = l
Nicolas Dumazet
localrepo: have _loadfilter return the loaded filter patterns
r12706 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):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
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):
return self._loadfilter('encode')
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):
return self._loadfilter('decode')
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
Gregory Szorc
localrepo: support background closing for wwrite()...
r28198 def wwrite(self, filename, data, flags, backgroundclose=False):
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)
Matt Mackall
util: set_flags shouldn't know about repo flag formats
r6877 if '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:
Gregory Szorc
localrepo: support background closing for wwrite()...
r28198 self.wvfs.write(filename, data, backgroundclose=backgroundclose)
Matt Mackall
util: set_flags shouldn't know about repo flag formats
r6877 if 'x' in flags:
FUJIWARA Katsunori
localrepo: use "vfs.setflags()" instead of "util.setflags()"
r18951 self.wvfs.setflags(filename, False, True)
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):
Pierre-Yves David
devel: rename 'all' to 'all-warnings' (BC)...
r25290 if (self.ui.configbool('devel', 'all-warnings')
Pierre-Yves David
devel: also warn about transaction started without a lock...
r24388 or self.ui.configbool('devel', 'check-locks')):
Pierre-Yves David
develwarn: use the lock helper in local repo...
r29705 if self._currentlock(self._lockref) is None:
Jun Wu
localrepo: use ProgrammingError...
r30574 raise error.ProgrammingError('transaction requires locking')
Pierre-Yves David
localrepo: add a currenttransaction method...
r23379 tr = self.currenttransaction()
if tr is not None:
Henrik Stuart
transaction: support multiple, separate transactions...
r8072 return tr.nest()
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
FUJIWARA Katsunori
localrepo: use "vfs.exists()" instead of "os.path.exists()"
r18947 if self.svfs.exists("journal"):
Matt Mackall
many, many trivial check-code fixups
r10282 raise error.RepoError(
Johan Bjork
journal: set Abort hint when failing due to an abandoned transaction
r21274 _("abandoned transaction found"),
hint=_("run 'hg recover' to clean up transaction"))
Matt Mackall
transactions: don't show a backtrace when journal exists...
r5865
FUJIWARA Katsunori
transaction: separate calculating TXNID from creating transaction object...
r25267 idbase = "%.40f#%f" % (random.random(), time.time())
Augie Fackler
localrepo: use node.hex instead of awkward .encode('latin1')...
r31523 ha = hex(hashlib.sha1(idbase).digest())
Augie Fackler
localrepo: ensure transaction id is fully bytes on py3
r31508 txnid = 'TXN:' + ha
FUJIWARA Katsunori
localrepo: pass hook argument txnid to pretxnopen hooks...
r25268 self.hook('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
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 vfsmap = {'plain': self.vfs} # 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
shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags',
False)
if desc != 'strip' and shouldtracktags:
oldheads = self.changelog.headrevs()
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:
Pierre-Yves David
track-tags: introduce first bits of tags tracking during transaction...
r31994 tr2.hookargs['tag_moved'] = '1'
Pierre-Yves David
track-tags: write all tag changes to a file...
r31996 with repo.vfs('changes/tags.changes', 'w',
atomictemp=True) as changesfile:
# 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)
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)
FUJIWARA Katsunori
hook: centralize passing HG_PENDING to external hook process...
r26751 reporef().hook('pretxnclose', throw=True,
Augie Fackler
localrepo: turn hook kwargs back into strs before calling hook...
r31509 txnname=desc, **pycompat.strkwargs(tr.hookargs))
FUJIWARA Katsunori
localrepo: execute appropriate actions for dirstate at releasing transaction...
r26577 def releasefn(tr, success):
repo = reporef()
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
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 repo.dirstate.restorebackup(None, '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)
Siddharth Agarwal
localrepo: kill off sopener (API)...
r25667 tr = transaction.transaction(rp, self.svfs, vfsmap,
FUJIWARA Katsunori
transaction: take journal file path relative to vfs to use file API via vfs
r20087 "journal",
Pierre-Yves David
transaction: pass the name of the "undo" journal to the transaction...
r23903 "undo",
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 aftertrans(renames),
Pierre-Yves David
hook: add a generic hook right before we commit a transaction...
r24284 self.store.createmode,
FUJIWARA Katsunori
localrepo: execute appropriate actions for dirstate at releasing transaction...
r26577 validator=validate,
FUJIWARA Katsunori
transaction: avoid file stat ambiguity only for files in blacklist...
r33278 releasefn=releasefn,
checkambigfiles=_cachedfiles)
Pierre-Yves David
transaction: track newly introduced revisions...
r32262 tr.changes['revs'] = set()
transaction: track new obsmarkers in the 'changes' mapping...
r33248 tr.changes['obsmarkers'] = set()
Pierre-Yves David
transaction: introduce a transaction ID, to be available to all hooks...
r24740
FUJIWARA Katsunori
transaction: separate calculating TXNID from creating transaction object...
r25267 tr.hookargs['txnid'] = txnid
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.
tr.addfinalize('flush-fncache', self.store.write)
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
Pierre-Yves David
hook: add a generic hook after transaction has been closed...
r24282 def hook():
reporef().hook('txnclose', throw=False, txnname=desc,
Augie Fackler
localrepo: turn hook kwargs back into strs before calling hook...
r31509 **pycompat.strkwargs(hookargs))
Pierre-Yves David
hook: add a generic hook after transaction has been closed...
r24282 reporef()._afterlock(hook)
tr.addfinalize('txnclose-hook', txnclosehook)
cache: make the cache updated callback easily accessible to extension...
r32332 tr.addpostclose('warms-cache', self._buildcacheupdater(tr))
Pierre-Yves David
hooks: add a 'txnabort' hook...
r24792 def txnaborthook(tr2):
"""To be run if transaction is aborted
"""
reporef().hook('txnabort', throw=False, txnname=desc,
**tr2.hookargs)
tr.addabort('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.
tr.addpostclose('refresh-filecachestats', self._refreshfilecachestats)
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 self._transref = weakref.ref(tr)
return tr
Idan Kamara
localrepo: refactor retrieving of journal/undo files paths...
r16236 def _journalfiles(self):
FUJIWARA Katsunori
localrepo: use "vfs.rename()" instead of "util.rename()"...
r18952 return ((self.svfs, 'journal'),
(self.vfs, 'journal.dirstate'),
(self.vfs, 'journal.branch'),
(self.vfs, 'journal.desc'),
(self.vfs, 'journal.bookmarks'),
(self.svfs, 'journal.phaseroots'))
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):
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 self.dirstate.savebackup(None, 'journal.dirstate')
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 self.vfs.write("journal.branch",
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 encoding.fromlocal(self.dirstate.branch()))
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 self.vfs.write("journal.desc",
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 "%d\n%s\n" % (len(self), desc))
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 self.vfs.write("journal.bookmarks",
self.vfs.tryread("bookmarks"))
Angel Ezquerra
localrepo: remove all internal uses of localrepo.sopener...
r23853 self.svfs.write("journal.phaseroots",
self.svfs.tryread("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():
FUJIWARA Katsunori
localrepo: use "vfs.exists()" instead of "os.path.exists()"
r18947 if self.svfs.exists("journal"):
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.ui.status(_("rolling back interrupted transaction\n"))
Angel Ezquerra
localrepo: remove all internal uses of localrepo.sopener...
r23853 vfsmap = {'': self.svfs,
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 'plain': self.vfs,}
Angel Ezquerra
localrepo: remove all internal uses of localrepo.sopener...
r23853 transaction.rollback(self.svfs, vfsmap, "journal",
FUJIWARA Katsunori
transaction: avoid file stat ambiguity only for files in blacklist...
r33278 self.ui.warn,
checkambigfiles=_cachedfiles)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.invalidate()
return True
else:
self.ui.warn(_("no interrupted transaction available\n"))
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()
FUJIWARA Katsunori
localrepo: use "vfs.exists()" instead of "os.path.exists()"
r18947 if self.svfs.exists("undo"):
Augie Fackler
localrepo: refer to dirstateguard by its new name
r30492 dsguard = dirstateguard.dirstateguard(self, '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:
self.ui.warn(_("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
Pierre-Yves David
clfilter: rename `unfilteredmeth` to `unfilteredmethod`...
r18016 @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:
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 args = self.vfs.read('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:
Pulkit Goyal
py3: use '%d' instead of '%s' for integers...
r32895 msg = (_('repository tip rolled back to revision %d'
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 ' (undo %s: %s)\n')
% (oldtip, desc, detail))
else:
Pulkit Goyal
py3: use '%d' instead of '%s' for integers...
r32895 msg = (_('repository tip rolled back to revision %d'
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 ' (undo %s)\n')
% (oldtip, desc))
Greg Ward
rollback: improve readability; clarify that the return value is an int.
r15097 except IOError:
Greg Ward
rollback: refactor for readability; cosmetics....
r15130 msg = _('rolling back unknown transaction\n')
Greg Ward
rollback: avoid unsafe rollback when not at tip (issue2998)...
r15183 desc = None
if not force and self['.'] != self['tip'] and desc == 'commit':
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Greg Ward
rollback: avoid unsafe rollback when not at tip (issue2998)...
r15183 _('rollback of last commit while not checked out '
Matt Mackall
rollback: use a hint for force
r15187 'may lose data'), hint=_('use -f to force'))
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()
Pierre-Yves David
rollback: have an empty entry for the vfsmap in rollback...
r23902 vfsmap = {'plain': self.vfs, '': self.svfs}
FUJIWARA Katsunori
transaction: avoid file stat ambiguity only for files in blacklist...
r33278 transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn,
checkambigfiles=_cachedfiles)
FUJIWARA Katsunori
localrepo: use "vfs.exists()" instead of "os.path.exists()"
r18947 if self.vfs.exists('undo.bookmarks'):
FUJIWARA Katsunori
localrepo: make restoring from backup at rollback avoid ambiguity of file stat...
r29352 self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
FUJIWARA Katsunori
localrepo: use "vfs.exists()" instead of "os.path.exists()"
r18947 if self.svfs.exists('undo.phaseroots'):
FUJIWARA Katsunori
localrepo: make restoring from backup at rollback avoid ambiguity of file stat...
r29352 self.svfs.rename('undo.phaseroots', '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
parentgone = (parents[0] not in self.changelog.nodemap or
parents[1] not in self.changelog.nodemap)
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()
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 self.dirstate.restorebackup(None, 'undo.dirstate')
Greg Ward
rollback: only restore dirstate and branch when appropriate....
r15131 try:
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 branch = self.vfs.read('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:
ui.warn(_('named branch could not be reset: '
'current branch is still \'%s\'\n')
% self.dirstate.branch())
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:
ui.status(_('working directory now based on '
'revisions %d and %d\n') % parents)
else:
ui.status(_('working directory now based on '
'revision %d\n') % parents)
Siddharth Agarwal
localrepo: switch to mergestate.clean()...
r26989 mergemod.mergestate.clean(self, self['.'].node())
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)
def updater(tr):
repo = reporef()
repo.updatecaches(tr)
return updater
Pierre-Yves David
caches: introduce a function to warm cache...
r32263 @unfilteredmethod
Pierre-Yves David
caches: call 'repo.updatecache()' in 'repo.destroyed()'...
r32264 def updatecaches(self, tr=None):
"""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.
"""
if tr is not None and tr.hookargs.get('source') == '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
Pierre-Yves David
caches: call 'repo.updatecache()' in 'repo.destroyed()'...
r32264 if tr is None or tr.changes['revs']:
# updating the unfiltered branchmap should refresh all the others,
Pierre-Yves David
caches: move the 'updating the branch cache' message in 'updatecaches'...
r32267 self.ui.debug('updating the branch cache\n')
Pierre-Yves David
caches: introduce a function to warm cache...
r32263 branchmap.updatecache(self.filtered('served'))
Benoit Boissinot
strip: invalidate all caches after stripping (fixes issue1951)...
r10547 def invalidatecaches(self):
Idan Kamara
localrepo: delete _phaserev when invalidating caches
r15988
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 if '_tagscache' in vars(self):
# can't use delattr on proxy
del self.__dict__['_tagscache']
Idan Kamara
localrepo: unify tag related info into a tagscache class
r14936
Pierre-Yves David
branchmap: enable caching for filtered version too...
r18189 self.unfiltered()._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)
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).'''
Pierre-Yves David
clfilter: add a propertycache that must be unfiltered...
r18013 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
Pierre-Yves David
clfilter: ensure cache invalidation is done on the main unfiltered repo...
r17997 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).
'''
Mads Kiilerich
spelling: fix some minor issues found by spell checker
r18644 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()
if k == 'dirstate':
continue
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():
if k == 'dirstate' or k not in self.__dict__:
continue
ce.refresh()
Siddharth Agarwal
localrepo: allow creating inherited locks...
r26439 def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc,
Siddharth Agarwal
localrepo: prevent wlock from being inherited when a transaction is running...
r26499 inheritchecker=None, parentenvvar=None):
Siddharth Agarwal
localrepo: allow creating inherited locks...
r26439 parentlock = None
Siddharth Agarwal
localrepo: add a note about parentenvvar...
r26472 # the contents of parentenvvar are used by the underlying lock to
# determine whether it can be inherited
Siddharth Agarwal
localrepo: allow creating inherited locks...
r26439 if parentenvvar is not None:
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 1 of 5)...
r30634 parentlock = encoding.environ.get(parentenvvar)
mpm@selenic.com
Break apart hg.py...
r1089 try:
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 l = lockmod.lock(vfs, lockname, 0, releasefn=releasefn,
Siddharth Agarwal
localrepo: allow creating inherited locks...
r26439 acquirefn=acquirefn, desc=desc,
Siddharth Agarwal
localrepo: prevent wlock from being inherited when a transaction is running...
r26499 inheritchecker=inheritchecker,
Siddharth Agarwal
localrepo: allow creating inherited locks...
r26439 parentlock=parentlock)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LockHeld as inst:
Benoit Boissinot
add localrepo.wlock for protecting the dirstate...
r1531 if not wait:
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 raise
Mark Ignacio
lock: show more detail for new-style locks in lock waiting message (issue4752)...
r29883 # show more details for new-style locks
if ':' in inst.locker:
host, pid = inst.locker.split(":", 1)
self.ui.warn(
_("waiting for lock on %s held by process %r "
"on host %r\n") % (desc, pid, host))
else:
self.ui.warn(_("waiting for lock on %s held by %r\n") %
(desc, inst.locker))
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 # default to 600 seconds timeout
FUJIWARA Katsunori
lock: take both vfs and lock file path relative to vfs to access via vfs...
r20091 l = lockmod.lock(vfs, lockname,
FUJIWARA Katsunori
localrepo: import "lock" module as "lockmod" for readability...
r20088 int(self.ui.config("ui", "timeout", "600")),
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 releasefn=releasefn, acquirefn=acquirefn,
desc=desc)
Mads Kiilerich
localrepo: give a sigh of relief when getting lock after waiting for it...
r20380 self.ui.warn(_("got lock after %s seconds\n") % l.delay)
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
else: # no lock have been found.
Mads Kiilerich
tag: run commit hook when lock is released (issue3344)
r16680 callback()
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
Yuya Nishihara
localrepo: refresh filecache stats only if transaction finished successfully...
r26251 l = self._lock(self.svfs, "lock", wait, None,
Adrian Buehlmann
fncachestore: defer updating the fncache file to a single file open...
r13391 self.invalidate, _('repository %s') % self.origroot)
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
Siddharth Agarwal
localrepo: prevent wlock from being inherited when a transaction is running...
r26499 def _wlockchecktransaction(self):
if self.currenttransaction() is not None:
raise error.LockInheritanceContractViolation(
'wlock cannot be inherited in the middle of a transaction')
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.
Pierre-Yves David
devel: rename 'all' to 'all-warnings' (BC)...
r25290 if wait and (self.ui.configbool('devel', 'all-warnings')
Pierre-Yves David
wlock: do not warn for non-wait locking...
r24750 or self.ui.configbool('devel', 'check-locks')):
Pierre-Yves David
develwarn: use the lock helper in local repo...
r29705 if self._currentlock(self._lockref) is not None:
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629 self.ui.develwarn('"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
Idan Kamara
localrepo: drop unnecessary check on wlock unlock...
r18318 self._filecache['dirstate'].refresh()
Idan Kamara
localrepo: decorate dirstate() with filecache...
r14930
FUJIWARA Katsunori
lock: take both vfs and lock file path relative to vfs to access via vfs...
r20091 l = self._lock(self.vfs, "wlock", wait, unlock,
Idan Kamara
localrepo: decorate dirstate() with filecache...
r14930 self.invalidatedirstate, _('working directory of %s') %
Siddharth Agarwal
localrepo: prevent wlock from being inherited when a transaction is running...
r26499 self.origroot,
inheritchecker=self._wlockchecktransaction,
parentenvvar='HG_WLOCK_LOCKER')
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)
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292 """
Matt Mackall
commit: unify file-level commit code
r3294 commit an individual file as part of a larger transaction
"""
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 fname = fctx.path()
fparent1 = manifest1.get(fname, nullid)
Matt Mackall
commit: catch changed exec bit on files from p1 (issue4382)
r22492 fparent2 = manifest2.get(fname, nullid)
Mads Kiilerich
localrepo: reuse commit of parent filectx entries without rehashing...
r24394 if isinstance(fctx, context.filectx):
node = fctx.filenode()
if node in [fparent1, fparent2]:
self.ui.debug('reusing %s filelog entry\n' % fname)
Mateusz Kwapich
localrepo: prevent executable-bit only changes from being lost on amend...
r29181 if manifest1.flags(fname) != fctx.flags():
changelist.append(fname)
Mads Kiilerich
localrepo: reuse commit of parent filectx entries without rehashing...
r24394 return node
Matt Mackall
Refactor excessive merge detection, add test
r1716
Mads Kiilerich
localrepo: reuse commit of parent filectx entries without rehashing...
r24394 flog = self.file(fname)
Matt Mackall
merge: remember rename copies and parents properly on commit...
r3292 meta = {}
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 copy = fctx.renamed()
if copy and copy[0] != fname:
Alexis S. L. Carvalho
filecommit: don't forget the local parent on a merge with a local rename
r4058 # Mark the new revision of this file as a copy of another
Thomas Arendsen Hein
Removed trailing whitespace and tabs from python files
r4516 # file. This copy data will effectively act as a parent
# of this new revision. If this is a merge, the first
Alexis S. L. Carvalho
filecommit: don't forget the local parent on a merge with a local rename
r4058 # parent will be the nullid (meaning "look up the copy data")
# and the second one will be the other parent. For example:
#
# 0 --- 1 --- 3 rev1 changes file foo
# \ / rev2 renames foo to bar and changes it
# \- 2 -/ rev3 should have bar with all changes and
# should record that bar descends from
# bar in rev2 and foo in rev1
#
# this allows this merge to succeed:
#
# 0 --- 1 --- 3 rev4 reverts the content change from rev2
# \ / merging rev3 and rev4 should use bar@rev2
# \- 2 --- 4 as the merge base
#
Matt Mackall
commit: simplify file copy logic
r6874
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 cfname = copy[0]
crev = manifest1.get(cfname)
newfparent = fparent2
Matt Mackall
commit: simplify file copy logic
r6874
if manifest2: # branch merge
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 if fparent2 == nullid or crev is None: # copied on remote side
if cfname in manifest2:
crev = manifest2[cfname]
newfparent = fparent1
Matt Mackall
commit: simplify file copy logic
r6874
Ryan McElroy
commit: remove reverse search for copy source when not in parent (issue4476)...
r23929 # Here, we used to search backwards through history to try to find
# where the file copy came from if the source of a copy was not in
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 # the parent directory. However, this doesn't actually make sense to
Ryan McElroy
commit: remove reverse search for copy source when not in parent (issue4476)...
r23929 # do (what does a copy from something not in your working copy even
# mean?) and it causes bugs (eg, issue4476). Instead, we will warn
# the user that copy information was dropped, so if they didn't
# expect this outcome it can be fixed, but this is the correct
# behavior in this circumstance.
Matt Mackall
add a fix for issue 1175...
r6875
Matt Mackall
commit: search both parents for missing copy revision (issue2484)...
r13000 if crev:
self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
meta["copy"] = cfname
meta["copyrev"] = hex(crev)
fparent1, fparent2 = nullid, newfparent
else:
self.ui.warn(_("warning: can't find ancestor for '%s' "
"copied from '%s'!\n") % (fname, cfname))
Mads Kiilerich
localrepo: commit: avoid calling expensive ancestor function when p1 is nullrev
r20556 elif fparent1 == nullid:
fparent1, fparent2 = fparent2, nullid
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 elif fparent2 != nullid:
Matt Mackall
Refactor excessive merge detection, add test
r1716 # is one parent an ancestor of the other?
Mads Kiilerich
localrepo: use commonancestorsheads for checking linear heritage in file commit...
r21106 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
Mads Kiilerich
commit: use revlog.commonancestors instead of .ancestor...
r20987 if fparent1 in fparentancestors:
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 fparent1, fparent2 = fparent2, nullid
Mads Kiilerich
commit: use revlog.commonancestors instead of .ancestor...
r20987 elif fparent2 in fparentancestors:
Martijn Pieters
localrepo: Refactor var names in filecommit to improve readability.
r8244 fparent2 = nullid
Matt Mackall
Refactor excessive merge detection, add test
r1716
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 # is the file changed?
Mads Kiilerich
localrepo: reuse commit of parent filectx entries without rehashing...
r24394 text = fctx.data()
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
changelist.append(fname)
return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
# are just the flags changed during merge?
Matt Mackall
commit: catch changed exec bit on files from p1 (issue4382)
r22492 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
Matt Mackall
filecommit: swallow some bits from _commitctx, add _
r8401 changelist.append(fname)
return fparent1
Matt Mackall
Refactor excessive merge detection, add test
r1716
timeless
localrepo: refactor commit argument check as checkcommitpatterns
r28813 def checkcommitpatterns(self, wctx, vdirs, 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)
if f == '.' or f in matched or f in wctx.substate:
continue
if f in status.deleted:
fail(f, _('file not found!'))
if f in vdirs: # visited directory
d = f + '/'
for mf in matched:
if mf.startswith(d):
break
else:
fail(f, _("no match under directory!"))
elif f not in self.dirstate:
fail(f, _("file not tracked!"))
Pierre-Yves David
clfilter: rename `unfilteredmeth` to `unfilteredmethod`...
r18016 @unfilteredmethod
Matt Mackall
commit: drop the now-unused files parameter
r8706 def commit(self, text="", user=None, date=None, match=None, force=False,
Pierre-Yves David
commit: remove a mutable default argument...
r26322 editor=False, 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):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort('%s: %s' % (f, msg))
Matt Mackall
commit: move some setup outside the lock
r8715
if not match:
Benoit Boissinot
style: use consistent variable names (*mod) with imports which would shadow
r10651 match = matchmod.always(self.root, '')
Matt Mackall
commit: move some setup outside the lock
r8715
if not force:
vdirs = []
Siddharth Agarwal
localrepo.commit: hook into match.explicitdir
r19138 match.explicitdir = vdirs.append
Matt Mackall
commit: move some setup outside the lock
r8715 match.bad = fail
Laurent Charignon
localrepo: put bookmark move following commit in one transaction...
r26998 wlock = lock = tr = None
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
Laurent Charignon
localrepo: put bookmark move following commit in one transaction...
r26998 wlock = self.wlock()
FUJIWARA Katsunori
commit: make commit acquire store lock before processing for consistency...
r27291 lock = self.lock() # for recent changelog (see issue4368)
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():
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot partially commit a merge '
Matt Mackall
remove deprecated rawcommit
r8397 '(do not specify files or patterns)'))
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:
Martin von Zweigbergk
localrepo: access status fields by name rather than index
r22928 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
subs = []
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 commitsubs = set()
newstate = wctx.substate.copy()
# only manage subrepos and .hgsubstate if .hgsub is present
Matt Mackall
subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844)...
r14536 if '.hgsub' in wctx:
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 # we'll decide whether to track this ourselves, thanks
Martin von Zweigbergk
localrepo: access status fields by name rather than index
r22928 for c in status.modified, status.added, status.removed:
FUJIWARA Katsunori
localrepo: omit ".hgsubstate" also from "added" files...
r20827 if '.hgsubstate' in c:
c.remove('.hgsubstate')
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073
# compare current state to last committed state
# build new substate based on last committed state
oldstate = wctx.p1().substate
for s in sorted(newstate.keys()):
if not match(s):
# ignore working copy, use old state if present
if s in oldstate:
newstate[s] = oldstate[s]
continue
if not force:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 _("commit with new subrepo %s excluded") % s)
FUJIWARA Katsunori
subrepo: add dirtyreason to centralize composing dirty reason message...
r24470 dirtyreason = wctx.sub(s).dirtyreason(True)
if dirtyreason:
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 if not self.ui.configbool('ui', 'commitsubrepos'):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(dirtyreason,
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 hint=_("use --subrepos for recursive commit"))
subs.append(s)
commitsubs.add(s)
else:
bs = wctx.sub(s).basestate()
newstate[s] = (newstate[s][0], bs, newstate[s][2])
if oldstate.get(s, (None, None, None))[1] != bs:
subs.append(s)
# check for removed subrepos
Matt Mackall
subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844)...
r14536 for p in wctx.parents():
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073 r = [s for s in p.substate if s not in newstate]
subs += [s for s in r if match(s)]
if subs:
Matt Mackall
subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844)...
r14536 if (not match('.hgsub') and
'.hgsub' in (wctx.modified() + wctx.added())):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Matt Mackall
subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844)...
r14536 _("can't commit subrepos without .hgsub"))
Martin von Zweigbergk
localrepo: access status fields by name rather than index
r22928 status.modified.insert(0, '.hgsubstate')
Matt Mackall
subrepo: rewrite handling of subrepo state at commit (issue2403)...
r16073
Martin von Zweigbergk
localrepo: access status fields by name rather than index
r22928 elif '.hgsub' in status.removed:
Matt Mackall
subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844)...
r14536 # clean up .hgsubstate when .hgsub is removed
if ('.hgsubstate' in wctx and
Martin von Zweigbergk
localrepo: access status fields by name rather than index
r22928 '.hgsubstate' not in (status.modified + status.added +
status.removed)):
status.removed.insert(0, '.hgsubstate')
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:
self.checkcommitpatterns(wctx, vdirs, match, status, fail)
Matt Mackall
commit: move explicit file checking into repo.commit
r8709
FUJIWARA Katsunori
context: add workingcommitctx for exact context to be committed...
r23710 cctx = context.workingcommitctx(self, status,
text, user, date, extra)
David Schleimer
localrepo: create context used for actual commit earlier...
r18659
Matt Mackall
commit: mark internal-only option
r25840 # internal config: ui.allowemptycommit
Pierre-Yves David
commit: no longer allow empty commit with the 'force' argument (API)...
r25021 allowemptycommit = (wctx.branch() != wctx.p1().branch()
Durham Goode
commit: add ui.allowemptycommit config option...
r25018 or extra.get('close') or merge or cctx.files()
or self.ui.configbool('ui', 'allowemptycommit'))
Durham Goode
commit: move empty commit condition to a new line...
r25017 if not allowemptycommit:
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():
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("cannot commit merge with missing files"))
Patrick Mezard
commit: abort on merge with missing files...
r16536
Siddharth Agarwal
localrepo.commit: switch to mergestate.read()...
r26996 ms = mergemod.mergestate.read(self)
Augie Fackler
localrepo: refer to checkunresolved by its new name
r30496 mergeutil.checkunresolved(ms)
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)
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 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:
for s in sorted(commitsubs):
Edouard Gomez
subrepo: print paths relative to upper repo root for push/pull/commit...
r11112 sub = wctx.sub(s)
self.ui.status(_('committing subrepository %s\n') %
Mads Kiilerich
subrepo: rename relpath to subrelpath and introduce reporelpath
r12752 subrepo.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)
subrepo.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()
hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 try:
Brodie Rao
cleanup: eradicate long lines
r16683 self.hook("precommit", throw=True, parent1=hookp1,
parent2=hookp2)
Laurent Charignon
localrepo: put bookmark move following commit in one transaction...
r26998 tr = self.transaction('commit')
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 ret = self.commitctx(cctx, True)
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 except: # re-raises
Greg Ward
commit: if relevant, tell user their commit message was saved....
r9935 if edited:
self.ui.write(
_('note: commit message saved in %s\n') % msgfn)
raise
Matt Mackall
bookmarks: move commit action into core
r13357 # update bookmarks, dirstate and mergestate
David Soria Parra
bookmarks: delete divergent bookmarks on merge
r16706 bookmarks.update(self, [p1, p2], ret)
David Schleimer
commit: factor out post-commit cleanup into workingctx...
r18661 cctx.markcommitted(ret)
Matt Mackall
commit: tidy up mergestate slightly
r8503 ms.reset()
Laurent Charignon
localrepo: put bookmark move following commit in one transaction...
r26998 tr.close()
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710 finally:
Laurent Charignon
localrepo: put bookmark move following commit in one transaction...
r26998 lockmod.release(tr, lock, wlock)
Patrick Mezard
localrepo: extract _commitctx() from commit()...
r6710
Mads Kiilerich
tag: run commit hook when lock is released (issue3344)
r16680 def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
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):
Pierre-Yves David
hook: protect commit hooks against stripping of temporary commit (issue4422)...
r23129 self.hook("commit", node=node, parent1=parent1,
parent2=parent2)
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
Matt Mackall
commit: move editor outside transaction...
r8496 def commitctx(self, ctx, error=False):
Patrick Mezard
context: improve memctx documentation
r7077 """Add a new revision to current repository.
Matt Mackall
commit: combine _commitctx and commitctx, drop unused force argument
r8410 Revision information is passed via the context argument.
Patrick Mezard
context: improve memctx documentation
r7077 """
Patrick Mezard
context: add memctx for memory commits
r6715
Martin von Zweigbergk
commit: remove dead initialization of 'lock'...
r22908 tr = None
Matt Mackall
commitctx: use contexts more fully
r8414 p1, p2 = ctx.p1(), ctx.p2()
Matt Mackall
commitctx: eliminate some variables
r8412 user = ctx.user()
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
commit: move lots of commitctx outside of the repo lock
r8411 lock = self.lock()
try:
Steve Borho
localrepo: add desc parameter to transaction...
r10881 tr = self.transaction("commit")
Matt Mackall
transactions: avoid late tear-down (issue641)...
r4970 trp = weakref.proxy(tr)
mpm@selenic.com
Break apart hg.py...
r1089
Mateusz Kwapich
localrepo: make it possible to reuse manifest when commiting context...
r30566 if ctx.manifestnode():
# reuse an existing manifest revision
mn = ctx.manifestnode()
files = ctx.files()
elif ctx.files():
Durham Goode
manifest: remove manifest.add and add memmfctx.write...
r30345 m1ctx = p1.manifestctx()
m2ctx = p2.manifestctx()
mctx = m1ctx.copy()
m = mctx.read()
m1 = m1ctx.read()
m2 = m2ctx.read()
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162
# check in files
Martin von Zweigbergk
commit: update file nodeid and flags in the same place...
r22910 added = []
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 changed = []
Martin von Zweigbergk
commit: reduce scope of 'removed' variable...
r22907 removed = list(ctx.removed())
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 linkrev = len(self)
Mads Kiilerich
localrepo: show headline notes in commitctx before showing filenames...
r23749 self.ui.note(_("committing files:\n"))
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 for f in sorted(ctx.modified() + ctx.added()):
self.ui.note(f + "\n")
try:
fctx = ctx[f]
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 if fctx is None:
removed.append(f)
else:
Martin von Zweigbergk
commit: update file nodeid and flags in the same place...
r22910 added.append(f)
m[f] = self._filecommit(fctx, m1, m2, linkrev,
trp, changed)
Augie Fackler
manifest: rename ambiguously-named set to setflag...
r22942 m.setflag(f, fctx.flags())
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as inst:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.ui.warn(_("trouble committing %s!\n") % f)
raise
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 errcode = getattr(inst, 'errno', errno.ENOENT)
if error or errcode and errcode != errno.ENOENT:
self.ui.warn(_("trouble committing %s!\n") % f)
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 raise
mpm@selenic.com
Break apart hg.py...
r1089
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 # update manifest
Mads Kiilerich
localrepo: show headline notes in commitctx before showing filenames...
r23749 self.ui.note(_("committing manifest\n"))
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 removed = [f for f in sorted(removed) if f in m1 or f in m2]
Martin von Zweigbergk
commit: use separate variable for p1 manifest and new manifest...
r22909 drop = [f for f in removed if f in m]
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 for f in drop:
Martin von Zweigbergk
commit: use separate variable for p1 manifest and new manifest...
r22909 del m[f]
Durham Goode
manifest: remove manifest.add and add memmfctx.write...
r30345 mn = mctx.write(trp, linkrev,
p1.manifestnode(), p2.manifestnode(),
added, drop)
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 files = changed + removed
else:
mn = p1.manifestnode()
files = []
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
commit: move description trimming into changelog
r8499 # update changelog
Mads Kiilerich
localrepo: show headline notes in commitctx before showing filenames...
r23749 self.ui.note(_("committing changelog\n"))
Pierre-Yves David
changelog: handle writepending in the transaction...
r23203 self.changelog.delayupdate(tr)
Peter Arrenbrecht
localrepo: reuse parent manifest in commitctx if no files have changed...
r14162 n = self.changelog.add(mn, files, ctx.description(),
Matt Mackall
commit: move description trimming into changelog
r8499 trp, p1.node(), p2.node(),
Matt Mackall
commitctx: eliminate some variables
r8412 user, ctx.date(), ctx.extra().copy())
Sune Foldager
run commit and update hooks after command completion (issue1827)...
r10492 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
FUJIWARA Katsunori
hook: centralize passing HG_PENDING to external hook process...
r26751 parent2=xp2)
Pierre-Yves David
Add a phases.new-commit option to control minimal phase of new commit...
r15706 # set the new commit is proper phase
FUJIWARA Katsunori
subrepo: check phase of state in each subrepositories before committing...
r20176 targetphase = subrepo.newcommitphase(self.ui, ctx)
Pierre-Yves David
Add a phases.new-commit option to control minimal phase of new commit...
r15706 if targetphase:
# retract boundary do not alter parent changeset.
# if a parent have higher the resulting phase will
# be compliant anyway
#
# if minimal phase was 0 we don't need to retract anything
Pierre-Yves David
phase: add a transaction argument to retractboundary...
r22070 phases.retractboundary(self, tr, targetphase, [n])
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 tr.close()
return n
finally:
Ronny Pfannschmidt
make transactions work on non-refcounted python implementations
r11230 if tr:
tr.release()
Matt Mackall
commit: push repo lock down into _commitctx
r8405 lock.release()
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.
if '_phasecache' in vars(self):
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
Matt Mackall
walk: remove cmdutil.walk
r6585 def walk(self, match, node=None):
Matt Mackall
improve walk docstrings
r3532 '''
walk recursively through the directory tree or a given
changeset, finding all files matched by the match
function
'''
Augie Fackler
localrepo: mark walk convenience method as deprecated (API)
r32364 self.ui.deprecwarn('use repo[node].walk instead of repo.walk', '4.3')
Matt Mackall
context: add walk method
r6764 return self[node].walk(match)
Matt Mackall
improve walk docstrings
r3532
Matt Mackall
status: use contexts
r6769 def status(self, node1='.', node2=None, match=None,
Martin Geisler
status: recurse into subrepositories with --subrepos/-S flag
r12166 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)'''
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()
Eric Hopper
Add option to heads to show only heads for current branch.
r4648 if branch not in branches:
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.
"""
pass
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)
hookargs['namespace'] = namespace
hookargs['key'] = key
hookargs['old'] = old
hookargs['new'] = new
self.hook('prepushkey', throw=True, **hookargs)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.HookAbort as exc:
Pierre-Yves David
pushkey: gracefully handle prepushkey hook failure (issue4455)...
r23416 self.ui.write_err(_("pushkey-abort: %s\n") % exc)
if exc.hint:
self.ui.write_err(_("(%s)\n") % exc.hint)
return False
Pierre-Yves David
pushkey: add more verbose debug output regarding pushkey...
r17293 self.ui.debug('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)
Pierre-Yves David
pushkey: run hook after the lock release...
r23648 def runhook():
self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
ret=ret)
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):
Brodie Rao
pushkey: add hooks for pushkey/listkeys
r14102 self.hook('prelistkeys', throw=True, namespace=namespace)
Pierre-Yves David
pushkey: add more verbose debug output regarding pushkey...
r17293 self.ui.debug('listing keys for "%s"\n' % namespace)
Brodie Rao
pushkey: add hooks for pushkey/listkeys
r14102 values = pushkey.list(self, namespace)
self.hook('listkeys', namespace=namespace, values=values)
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'''
Peter Arrenbrecht
wireproto: add test for new optional arg missing on server...
r14048 return "%s %s %s %s %s" % (one, two, three, four, five)
Matt Mackall
pushkey: add localrepo support
r11368
Patrick Mezard
localrepo: add savecommitmessage() to write last-message.txt
r14529 def savecommitmessage(self, text):
Angel Ezquerra
localrepo: remove all internal uses of localrepo.opener...
r23852 fp = self.vfs('last-message.txt', 'wb')
Patrick Mezard
localrepo: add savecommitmessage() to write last-message.txt
r14529 try:
fp.write(text)
finally:
fp.close()
Mads Kiilerich
check-code: there must also be whitespace between ')' and operator...
r18054 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]
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)
Alain Leufroy
localrepo: do not complain about missing journal files
r16441 except OSError: # journal file does not yet exist
pass
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 return a
Alexander Solovyov
fix bookmarks rollback behavior...
r14266 def undoname(fn):
base, name = os.path.split(fn)
assert name.startswith('journal')
return os.path.join(base, name.replace('journal', 'undo', 1))
Vadim Gelfer
clean up hg.py: move repo constructor code into each repo module
r2740 def instance(ui, path, create):
Mads Kiilerich
util: rename the util.localpath that uses url to urllocalpath (issue2875)...
r14825 return localrepository(ui, util.urllocalpath(path), create)
Thomas Arendsen Hein
Whitespace/Tab cleanup
r3223
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
def newreporequirements(repo):
"""Determine the set of requirements for a new local repository.
Extensions can wrap this function to specify custom requirements for
new repositories.
"""
ui = repo.ui
Martin von Zweigbergk
cleanup: use set literals...
r32291 requirements = {'revlogv1'}
configitems: register the 'format.usestore' config
r33244 if ui.configbool('format', 'usestore'):
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 requirements.add('store')
configitems: register the 'format.usefncache' config
r33242 if ui.configbool('format', 'usefncache'):
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 requirements.add('fncache')
configitems: register the 'format.dotencode' config
r33234 if ui.configbool('format', 'dotencode'):
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 requirements.add('dotencode')
Gregory Szorc
localrepo: experimental support for non-zlib revlog compression...
r30818 compengine = ui.config('experimental', 'format.compression', 'zlib')
if compengine not in util.compengines:
raise error.Abort(_('compression engine %s defined by '
'experimental.format.compression not available') %
compengine,
hint=_('run "hg debuginstall" to list available '
'compression engines'))
# zlib is the historical default and doesn't need an explicit requirement.
if compengine != 'zlib':
requirements.add('exp-compression-%s' % compengine)
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 if scmutil.gdinitconfig(ui):
requirements.add('generaldelta')
if ui.configbool('experimental', 'treemanifest', False):
requirements.add('treemanifest')
if ui.configbool('experimental', 'manifestv2', False):
requirements.add('manifestv2')
Gregory Szorc
revlog: skeleton support for version 2 revlogs...
r32697 revlogv2 = ui.config('experimental', 'revlogv2')
if revlogv2 == 'enable-unstable-format-and-corrupt-my-data':
requirements.remove('revlogv1')
# generaldelta is implied by revlogv2.
requirements.discard('generaldelta')
requirements.add(REVLOGV2_REQUIREMENT)
Gregory Szorc
localrepo: move new repo requirements into standalone function (API)...
r28164 return requirements