##// END OF EJS Templates
narrow: move narrowmatch-related methods to localrepo...
narrow: move narrowmatch-related methods to localrepo This patch makes it so localrepo.narrowmatch() and a few more are always available, which will let us simplify the use sites a bit. narrowmatch() will return an always-matcher in non-narrow repos (just like it did when it lived in the narrow extension). Differential Revision: https://phab.mercurial-scm.org/D2494

File last commit:

r36114:66b4ffe9 default
r36489:c28b6d60 default
Show More
narrowrevlog.py
187 lines | 7.2 KiB | text/x-python | PythonLexer
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 # narrowrevlog.py - revlog storing irrelevant nodes as "ellipsis" nodes
#
# Copyright 2017 Google, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from mercurial import (
Augie Fackler
narrowrevlog: replace AssertionError with ProgrammingError...
r36111 error,
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 manifest,
revlog,
util,
)
def readtransform(self, text):
return text, False
def writetransform(self, text):
return text, False
def rawtransform(self, text):
return False
Augie Fackler
narrow: move from ELLIPSIS_NODE_FLAG to revlog.REVIDX_ELLIPSIS...
r36107 revlog.addflagprocessor(revlog.REVIDX_ELLIPSIS,
Augie Fackler
narrow: assume addflagprocessor will always exist on revlog module...
r36100 (readtransform, writetransform, rawtransform))
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
def setup():
# We just wanted to add the flag processor, which is done at module
# load time.
pass
class excludeddir(manifest.treemanifest):
Augie Fackler
narrowrevlog: document excludeddir class and friends...
r36110 """Stand-in for a directory that is excluded from the repository.
With narrowing active on a repository that uses treemanifests,
some of the directory revlogs will be excluded from the resulting
clone. This is a huge storage win for clients, but means we need
some sort of pseudo-manifest to surface to internals so we can
detect a merge conflict outside the narrowspec. That's what this
class is: it stands in for a directory whose node is known, but
whose contents are unknown.
"""
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def __init__(self, dir, node):
super(excludeddir, self).__init__(dir)
self._node = node
# Add an empty file, which will be included by iterators and such,
# appearing as the directory itself (i.e. something like "dir/")
self._files[''] = node
self._flags[''] = 't'
# Manifests outside the narrowspec should never be modified, so avoid
# copying. This makes a noticeable difference when there are very many
# directories outside the narrowspec. Also, it makes sense for the copy to
# be of the same type as the original, which would not happen with the
# super type's copy().
def copy(self):
return self
class excludeddirmanifestctx(manifest.treemanifestctx):
Augie Fackler
narrowrevlog: document excludeddir class and friends...
r36110 """context wrapper for excludeddir - see that docstring for rationale"""
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def __init__(self, dir, node):
self._dir = dir
self._node = node
def read(self):
return excludeddir(self._dir, self._node)
def write(self, *args):
Augie Fackler
narrowrevlog: replace AssertionError with ProgrammingError...
r36111 raise error.ProgrammingError(
'attempt to write manifest from excluded dir %s' % self._dir)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
class excludedmanifestrevlog(manifest.manifestrevlog):
Augie Fackler
narrowrevlog: document excludeddir class and friends...
r36110 """Stand-in for excluded treemanifest revlogs.
When narrowing is active on a treemanifest repository, we'll have
references to directories we can't see due to the revlog being
skipped. This class exists to conform to the manifestrevlog
interface for those directories and proactively prevent writes to
outside the narrowspec.
"""
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 def __init__(self, dir):
self._dir = dir
def __len__(self):
Augie Fackler
narrowrevlog: replace AssertionError with ProgrammingError...
r36111 raise error.ProgrammingError(
'attempt to get length of excluded dir %s' % self._dir)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
def rev(self, node):
Augie Fackler
narrowrevlog: replace AssertionError with ProgrammingError...
r36111 raise error.ProgrammingError(
'attempt to get rev from excluded dir %s' % self._dir)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
def linkrev(self, node):
Augie Fackler
narrowrevlog: replace AssertionError with ProgrammingError...
r36111 raise error.ProgrammingError(
'attempt to get linkrev from excluded dir %s' % self._dir)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
def node(self, rev):
Augie Fackler
narrowrevlog: replace AssertionError with ProgrammingError...
r36111 raise error.ProgrammingError(
'attempt to get node from excluded dir %s' % self._dir)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096
def add(self, *args, **kwargs):
# We should never write entries in dirlogs outside the narrow clone.
# However, the method still gets called from writesubtree() in
# _addtree(), so we need to handle it. We should possibly make that
# avoid calling add() with a clean manifest (_dirty is always False
# in excludeddir instances).
pass
def makenarrowmanifestrevlog(mfrevlog, repo):
if util.safehasattr(mfrevlog, '_narrowed'):
return
class narrowmanifestrevlog(mfrevlog.__class__):
# This function is called via debug{revlog,index,data}, but also during
# at least some push operations. This will be used to wrap/exclude the
# child directories when using treemanifests.
Augie Fackler
manifest: clean up dirlog() to take a d parameter to avoid shadowing dir()...
r36112 def dirlog(self, d):
if d and not d.endswith('/'):
d = d + '/'
if not repo.narrowmatch().visitdir(d[:-1] or '.'):
return excludedmanifestrevlog(d)
result = super(narrowmanifestrevlog, self).dirlog(d)
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 makenarrowmanifestrevlog(result, repo)
return result
mfrevlog.__class__ = narrowmanifestrevlog
mfrevlog._narrowed = True
def makenarrowmanifestlog(mfl, repo):
class narrowmanifestlog(mfl.__class__):
def get(self, dir, node, verify=True):
if not repo.narrowmatch().visitdir(dir[:-1] or '.'):
return excludeddirmanifestctx(dir, node)
return super(narrowmanifestlog, self).get(dir, node, verify=verify)
mfl.__class__ = narrowmanifestlog
def makenarrowfilelog(fl, narrowmatch):
class narrowfilelog(fl.__class__):
def renamed(self, node):
Augie Fackler
narrowrevlog: add what little I can remember about rename filtering...
r36113 # Renames that come from outside the narrowspec are
# problematic at least for git-diffs, because we lack the
# base text for the rename. This logic was introduced in
# 3cd72b1 of narrowhg (authored by martinvonz, reviewed by
# adgar), but that revision doesn't have any additional
# commentary on what problems we can encounter.
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 m = super(narrowfilelog, self).renamed(node)
if m and not narrowmatch(m[0]):
return None
return m
def size(self, rev):
# We take advantage of the fact that remotefilelog
# lacks a node() method to just skip the
# rename-checking logic when on remotefilelog. This
# might be incorrect on other non-revlog-based storage
# engines, but for now this seems to be fine.
Augie Fackler
narrowrevlog: add a TODO around remotefilelog moving to core...
r36114 #
# TODO: when remotefilelog is in core, improve this to
# explicitly look for remotefilelog instead of cheating
# with a hasattr check.
Augie Fackler
narrow: import experimental extension from narrowhg revision cb51d673e9c5...
r36096 if util.safehasattr(self, 'node'):
node = self.node(rev)
# Because renamed() is overridden above to
# sometimes return None even if there is metadata
# in the revlog, size can be incorrect for
# copies/renames, so we need to make sure we call
# the super class's implementation of renamed()
# for the purpose of size calculation.
if super(narrowfilelog, self).renamed(node):
return len(self.read(node))
return super(narrowfilelog, self).size(rev)
def cmp(self, node, text):
different = super(narrowfilelog, self).cmp(node, text)
if different:
# Similar to size() above, if the file was copied from
# a file outside the narrowspec, the super class's
# would have returned True because we tricked it into
# thinking that the file was not renamed.
if super(narrowfilelog, self).renamed(node):
t2 = self.read(node)
return t2 != text
return different
fl.__class__ = narrowfilelog