##// END OF EJS Templates
interfaces: make all methods on any repository Protocol class abstract...
interfaces: make all methods on any repository Protocol class abstract These were converted to Protocol classes before it was known there would be a benefit to making them abstract. See cdd4bc69bfc1 and db6efd74cf14. The one exception here is the `peer` class, which is meant to provide a default implementation, not be a standalone interface.

File last commit:

r53392:6412dcec default
r53396:9358d786 default
Show More
manifest.py
2747 lines | 90.6 KiB | text/x-python | PythonLexer
mpm@selenic.com
Break apart hg.py...
r1089 # manifest.py - manifest revision class for mercurial
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@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.
mpm@selenic.com
Break apart hg.py...
r1089
Matt Harbison
typing: add `from __future__ import annotations` to most files...
r52756 from __future__ import annotations
Gregory Szorc
manifest: use absolute_import
r27502
import heapq
Augie Fackler
manifest: use itertools.chain() instead of + for Python 3 compat...
r32536 import itertools
Gregory Szorc
manifest: use absolute_import
r27502 import struct
Matt Harbison
manifest: delay import of `typing.ByteString` for py 3.14 support (issue6940)...
r53224 import typing
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 import weakref
Gregory Szorc
manifest: use absolute_import
r27502
manifest: adds some type things for manifestdict.added...
r52658 from typing import (
manifest: add many type annotations to the manifest module...
r52667 Callable,
manifest: introduce a `read_any_fast_delta` method...
r52668 Collection,
manifest: add many type annotations to the manifest module...
r52667 Dict,
manifest: adds some type things for manifestdict.added...
r52658 Iterable,
manifest: add many type annotations to the manifest module...
r52667 Iterator,
List,
Optional,
Set,
Tuple,
Union,
cast,
manifest: adds some type things for manifestdict.added...
r52658 )
Gregory Szorc
manifest: use absolute_import
r27502 from .i18n import _
Augie Fackler
manifest: use node.hex instead of .encode('hex')...
r31530 from .node import (
bin,
hex,
Gregory Szorc
manifest: don't go through revlog to access node symbols...
r39352 nullrev,
Augie Fackler
manifest: use node.hex instead of .encode('hex')...
r31530 )
Gregory Szorc
manifest: use absolute_import
r27502 from . import (
Kyle Lippincott
py3: __repr__ needs to return str, not bytes...
r44742 encoding,
Gregory Szorc
manifest: use absolute_import
r27502 error,
Augie Fackler
manifest: rewrite filesnotin to not make superfluous manifest copies...
r44768 match as matchmod,
Gregory Szorc
manifest: use absolute_import
r27502 mdiff,
utils: move the `dirs` definition in pathutil (API)...
r43923 pathutil,
Yuya Nishihara
parsers: switch to policy importer...
r32372 policy,
Yuya Nishihara
py3: remove b'' from error message of disallowed filename
r38353 pycompat,
Gregory Szorc
manifest: use absolute_import
r27502 revlog,
util,
)
Pulkit Goyal
interfaces: create a new folder for interfaces and move repository.py in it...
r43078 from .interfaces import (
repository,
Gregory Szorc
repository: define manifest interfaces...
r38549 )
revlog: introduce an explicit tracking of what the revlog is about...
r47838 from .revlogutils import (
constants as revlog_constants,
)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Harbison
manifest: delay import of `typing.ByteString` for py 3.14 support (issue6940)...
r53224 if typing.TYPE_CHECKING:
from typing import (
ByteString,
)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 parsers = policy.importmod('parsers')
Drew Gottlieb
manifest: add dirs() to manifestdict...
r24322 propertycache = util.propertycache
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
Matt Harbison
tests: demonstrate broken manifest generation with the pure module...
r42568 # Allow tests to more easily test the alternate path in manifestdict.fastdelta()
FASTDELTA_TEXTDIFF_THRESHOLD = 1000
Augie Fackler
formatting: blacken the codebase...
r43346
manifest: add many type annotations to the manifest module...
r52667 def _parse(nodelen, data: bytes):
Martin von Zweigbergk
manifest: extract method for parsing manifest...
r24524 # This method does a little bit of excessive-looking
# precondition checking. This is so that the behavior of this
# class exactly matches its C counterpart to try and help
# prevent surprise breakage for anyone that develops against
# the pure version.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if data and data[-1:] != b'\n':
raise ValueError(b'Manifest did not end in a newline.')
Martin von Zweigbergk
manifest: extract method for parsing manifest...
r24524 prev = None
for l in data.splitlines():
if prev is not None and prev > l:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b'Manifest lines not in sorted order.')
Martin von Zweigbergk
manifest: extract method for parsing manifest...
r24524 prev = l
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f, n = l.split(b'\0')
Augie Fackler
manifest: remove a final 40-byte assumption from pure-python parser...
r45200 nl = len(n)
Joerg Sonnenberger
manifest: use the same logic for handling flags in _parse as elsewhere...
r45679 flags = n[-1:]
if flags in _manifestflags:
n = n[:-1]
nl -= 1
Martin von Zweigbergk
manifest: extract method for parsing manifest...
r24524 else:
Joerg Sonnenberger
manifest: use the same logic for handling flags in _parse as elsewhere...
r45679 flags = b''
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 if nl != 2 * nodelen:
Joerg Sonnenberger
manifest: use the same logic for handling flags in _parse as elsewhere...
r45679 raise ValueError(b'Invalid manifest line')
yield f, bin(n), flags
Martin von Zweigbergk
manifest: extract method for parsing manifest...
r24524
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 def _text(it):
Martin von Zweigbergk
manifest: extract method for creating manifest text...
r24525 files = []
lines = []
for f, n, fl in it:
files.append(f)
# if this is changed to support newlines in filenames,
# be sure to check the templates/ dir again (especially *-raw.tmpl)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lines.append(b"%s\0%s%s\n" % (f, hex(n), fl))
Martin von Zweigbergk
manifest: extract method for creating manifest text...
r24525
_checkforbidden(files)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''.join(lines)
Martin von Zweigbergk
manifest: extract method for creating manifest text...
r24525
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class lazymanifestiter:
manifest: add many type annotations to the manifest module...
r52667 def __init__(self, lm: '_LazyManifest') -> None:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.pos = 0
self.lm = lm
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def __iter__(self) -> 'lazymanifestiter':
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return self
Augie Fackler
manifest: move parsing functions up in file...
r24223
manifest: add many type annotations to the manifest module...
r52667 def next(self) -> bytes:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 try:
data, pos = self.lm._get(self.pos)
except IndexError:
raise StopIteration
if pos == -1:
manifest: add many type annotations to the manifest module...
r52667 assert isinstance(data, tuple)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.pos += 1
return data[0]
manifest: add many type annotations to the manifest module...
r52667 assert isinstance(data, bytes)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.pos += 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 zeropos = data.find(b'\x00', pos)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return data[pos:zeropos]
Augie Fackler
manifest: do parsing inside manifestdict contstructor...
r24224
Augie Fackler
manifest: add __next__ methods for Python 3...
r31364 __next__ = next
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class lazymanifestiterentries:
manifest: add many type annotations to the manifest module...
r52667 def __init__(self, lm: '_LazyManifest') -> None:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.lm = lm
self.pos = 0
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def __iter__(self) -> 'lazymanifestiterentries':
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return self
manifest: add many type annotations to the manifest module...
r52667 def next(self) -> Tuple[bytes, bytes, bytes]:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 try:
data, pos = self.lm._get(self.pos)
except IndexError:
raise StopIteration
if pos == -1:
manifest: add many type annotations to the manifest module...
r52667 assert isinstance(data, tuple)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.pos += 1
return data
manifest: add many type annotations to the manifest module...
r52667 assert isinstance(data, bytes)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 zeropos = data.find(b'\x00', pos)
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 nlpos = data.find(b'\n', pos)
if zeropos == -1 or nlpos == -1 or nlpos < zeropos:
raise error.StorageError(b'Invalid manifest line')
flags = data[nlpos - 1 : nlpos]
if flags in _manifestflags:
hlen = nlpos - zeropos - 2
else:
hlen = nlpos - zeropos - 1
flags = b''
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 if hlen != 2 * self.lm._nodelen:
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 raise error.StorageError(b'Invalid manifest line')
hashval = unhexlify(
data, self.lm.extrainfo[self.pos], zeropos + 1, hlen
)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.pos += 1
return (data[pos:zeropos], hashval, flags)
Augie Fackler
manifest: add __next__ methods for Python 3...
r31364 __next__ = next
Augie Fackler
formatting: blacken the codebase...
r43346
manifest: type and fix unhexlify...
r52657 def unhexlify(data: bytes, extra: int, pos, length: int):
Augie Fackler
formatting: blacken the codebase...
r43346 s = bin(data[pos : pos + length])
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if extra:
manifest: type and fix unhexlify...
r52657 s += bytes([extra & 0xFF])
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return s
Augie Fackler
formatting: blacken the codebase...
r43346
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 def _cmp(a, b):
return (a > b) - (a < b)
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 _manifestflags = {b'', b'l', b't', b'x'}
manifest: expose a version of the Class without interface decorator...
r52661 class _LazyManifest:
Matt Harbison
manifest: add some documentation to _lazymanifest python code...
r42570 """A pure python manifest backed by a byte string. It is supplimented with
internal lists as it is modified, until it is compacted back to a pure byte
string.
``data`` is the initial manifest data.
``positions`` is a list of offsets, one per manifest entry. Positive
values are offsets into ``data``, negative values are offsets into the
``extradata`` list. When an entry is removed, its entry is dropped from
``positions``. The values are encoded such that when walking the list and
indexing into ``data`` or ``extradata`` as appropriate, the entries are
sorted by filename.
``extradata`` is a list of (key, hash, flags) for entries that were added or
modified since the manifest was created or compacted.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
def __init__(
self,
manifest: add many type annotations to the manifest module...
r52667 nodelen: int,
data: bytes,
Augie Fackler
formatting: blacken the codebase...
r43346 positions=None,
extrainfo=None,
extradata=None,
manifest: add many type annotations to the manifest module...
r52667 hasremovals: bool = False,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 self._nodelen = nodelen
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if positions is None:
self.positions = self.findlines(data)
self.extrainfo = [0] * len(self.positions)
self.data = data
self.extradata = []
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569 self.hasremovals = False
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 else:
self.positions = positions[:]
self.extrainfo = extrainfo[:]
self.extradata = extradata[:]
self.data = data
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569 self.hasremovals = hasremovals
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042
manifest: add many type annotations to the manifest module...
r52667 def findlines(self, data: bytes) -> List[int]:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if not data:
return []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pos = data.find(b"\n")
if pos == -1 or data[-1:] != b'\n':
raise ValueError(b"Manifest did not end in a newline.")
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 positions = [0]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prev = data[: data.find(b'\x00')]
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 while pos < len(data) - 1 and pos != -1:
positions.append(pos + 1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nexts = data[pos + 1 : data.find(b'\x00', pos + 1)]
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if nexts < prev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b"Manifest lines not in sorted order.")
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 prev = nexts
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pos = data.find(b"\n", pos + 1)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return positions
manifest: add many type annotations to the manifest module...
r52667 def _get(
self, index: int
) -> Tuple[Union[bytes, Tuple[bytes, bytes, bytes]], int]:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 # get the position encoded in pos:
# positive number is an index in 'data'
# negative number is in extrapieces
pos = self.positions[index]
if pos >= 0:
return self.data, pos
return self.extradata[-pos - 1], -1
manifest: add many type annotations to the manifest module...
r52667 def _getkey(self, pos) -> bytes:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if pos >= 0:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self.data[pos : self.data.find(b'\x00', pos + 1)]
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return self.extradata[-pos - 1][0]
manifest: add many type annotations to the manifest module...
r52667 def bsearch(self, key: bytes) -> int:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 first = 0
last = len(self.positions) - 1
while first <= last:
Augie Fackler
formatting: blacken the codebase...
r43346 midpoint = (first + last) // 2
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 nextpos = self.positions[midpoint]
candidate = self._getkey(nextpos)
r = _cmp(key, candidate)
if r == 0:
return midpoint
else:
if r < 0:
last = midpoint - 1
else:
first = midpoint + 1
return -1
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def bsearch2(self, key: bytes) -> Tuple[int, bool]:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 # same as the above, but will always return the position
# done for performance reasons
first = 0
last = len(self.positions) - 1
while first <= last:
Augie Fackler
formatting: blacken the codebase...
r43346 midpoint = (first + last) // 2
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 nextpos = self.positions[midpoint]
candidate = self._getkey(nextpos)
r = _cmp(key, candidate)
if r == 0:
return (midpoint, True)
else:
if r < 0:
last = midpoint - 1
else:
first = midpoint + 1
return (first, False)
manifest: add many type annotations to the manifest module...
r52667 def __contains__(self, key: bytes) -> bool:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return self.bsearch(key) != -1
manifest: add many type annotations to the manifest module...
r52667 def __getitem__(self, key: bytes) -> Tuple[bytes, bytes]:
Augie Fackler
manifest: ensure paths are bytes (not str) in pure parser
r31367 if not isinstance(key, bytes):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise TypeError(b"getitem: manifest keys must be a bytes.")
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 needle = self.bsearch(key)
if needle == -1:
raise KeyError
data, pos = self._get(needle)
if pos == -1:
manifest: add many type annotations to the manifest module...
r52667 assert isinstance(data, tuple)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return (data[1], data[2])
manifest: add many type annotations to the manifest module...
r52667
assert isinstance(data, bytes)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 zeropos = data.find(b'\x00', pos)
Augie Fackler
manifest: remove a final 40-byte assumption from pure-python parser...
r45200 nlpos = data.find(b'\n', zeropos)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 assert 0 <= needle <= len(self.positions)
assert len(self.extrainfo) == len(self.positions)
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 if zeropos == -1 or nlpos == -1 or nlpos < zeropos:
raise error.StorageError(b'Invalid manifest line')
Augie Fackler
manifest: remove a final 40-byte assumption from pure-python parser...
r45200 hlen = nlpos - zeropos - 1
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 flags = data[nlpos - 1 : nlpos]
if flags in _manifestflags:
Augie Fackler
manifest: remove a final 40-byte assumption from pure-python parser...
r45200 hlen -= 1
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 else:
flags = b''
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 if hlen != 2 * self._nodelen:
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 raise error.StorageError(b'Invalid manifest line')
Augie Fackler
manifest: remove a final 40-byte assumption from pure-python parser...
r45200 hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return (hashval, flags)
manifest: add many type annotations to the manifest module...
r52667 def __delitem__(self, key: bytes) -> None:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 needle, found = self.bsearch2(key)
if not found:
raise KeyError
cur = self.positions[needle]
Augie Fackler
formatting: blacken the codebase...
r43346 self.positions = self.positions[:needle] + self.positions[needle + 1 :]
self.extrainfo = self.extrainfo[:needle] + self.extrainfo[needle + 1 :]
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if cur >= 0:
Matt Harbison
manifest: add some documentation to _lazymanifest python code...
r42570 # This does NOT unsort the list as far as the search functions are
# concerned, as they only examine lines mapped by self.positions.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.data = self.data[:cur] + b'\x00' + self.data[cur + 1 :]
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569 self.hasremovals = True
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042
manifest: add many type annotations to the manifest module...
r52667 def __setitem__(self, key: bytes, value: Tuple[bytes, bytes]):
Augie Fackler
manifest: refer to bytestrings as bytes, not str...
r31531 if not isinstance(key, bytes):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise TypeError(b"setitem: manifest keys must be a byte string.")
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if not isinstance(value, tuple) or len(value) != 2:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise TypeError(
b"Manifest values must be a tuple of (node, flags)."
)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 hashval = value[0]
Joerg Sonnenberger
manifest: kill one more instance of the old merge hash hack...
r45779 if not isinstance(hashval, bytes) or len(hashval) not in (20, 32):
Augie Fackler
manifest: fix yet another 20-byte-hash assumption...
r45195 raise TypeError(b"node must be a 20-byte or 32-byte byte string")
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 flags = value[1]
Augie Fackler
manifest: refer to bytestrings as bytes, not str...
r31531 if not isinstance(flags, bytes) or len(flags) > 1:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise TypeError(b"flags must a 0 or 1 byte string, got %r", flags)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 needle, found = self.bsearch2(key)
if found:
# put the item
pos = self.positions[needle]
if pos < 0:
self.extradata[-pos - 1] = (key, hashval, value[1])
else:
# just don't bother
self.extradata.append((key, hashval, value[1]))
self.positions[needle] = -len(self.extradata)
else:
# not found, put it in with extra positions
self.extradata.append((key, hashval, value[1]))
Augie Fackler
formatting: blacken the codebase...
r43346 self.positions = (
self.positions[:needle]
+ [-len(self.extradata)]
+ self.positions[needle:]
)
self.extrainfo = (
self.extrainfo[:needle] + [0] + self.extrainfo[needle:]
)
Martin von Zweigbergk
lazymanifest: make __iter__ generate filenames, not 3-tuples...
r24298
manifest: add many type annotations to the manifest module...
r52667 def copy(self) -> '_LazyManifest':
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 # XXX call _compact like in C?
Augie Fackler
formatting: blacken the codebase...
r43346 return _lazymanifest(
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 self._nodelen,
Augie Fackler
formatting: blacken the codebase...
r43346 self.data,
self.positions,
self.extrainfo,
self.extradata,
self.hasremovals,
)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042
manifest: add many type annotations to the manifest module...
r52667 def _compact(self) -> None:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 # hopefully not called TOO often
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569 if len(self.extradata) == 0 and not self.hasremovals:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return
l = []
i = 0
offset = 0
self.extrainfo = [0] * len(self.positions)
while i < len(self.positions):
if self.positions[i] >= 0:
cur = self.positions[i]
last_cut = cur
Matt Harbison
manifest: add some documentation to _lazymanifest python code...
r42570
# Collect all contiguous entries in the buffer at the current
# offset, breaking out only for added/modified items held in
# extradata, or a deleted line prior to the next position.
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 while True:
self.positions[i] = offset
i += 1
if i == len(self.positions) or self.positions[i] < 0:
break
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569
# A removed file has no positions[] entry, but does have an
# overwritten first byte. Break out and find the end of the
# current good entry/entries if there is a removed file
# before the next position.
Augie Fackler
formatting: blacken the codebase...
r43346 if (
self.hasremovals
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 and self.data.find(b'\n\x00', cur, self.positions[i])
Augie Fackler
formatting: blacken the codebase...
r43346 != -1
):
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569 break
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 offset += self.positions[i] - cur
cur = self.positions[i]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 end_cut = self.data.find(b'\n', cur)
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if end_cut != -1:
end_cut += 1
offset += end_cut - cur
l.append(self.data[last_cut:end_cut])
else:
while i < len(self.positions) and self.positions[i] < 0:
cur = self.positions[i]
t = self.extradata[-cur - 1]
l.append(self._pack(t))
self.positions[i] = offset
Augie Fackler
manifest: fix another pure-parsing 20-byte assumption...
r45194 # Hashes are either 20 bytes (old sha1s) or 32
# bytes (new non-sha1).
hlen = 20
if len(t[1]) > 25:
hlen = 32
if len(t[1]) > hlen:
self.extrainfo[i] = ord(t[1][hlen + 1])
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 offset += len(l[-1])
i += 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.data = b''.join(l)
Matt Harbison
manifest: avoid corruption by dropping removed files with pure (issue5801)...
r42569 self.hasremovals = False
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self.extradata = []
manifest: add many type annotations to the manifest module...
r52667 def _pack(self, d: Tuple[bytes, bytes, bytes]) -> bytes:
Augie Fackler
manifest: remove a 20-byte-hash assumption from pure manifest parsing...
r45191 n = d[1]
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 assert len(n) in (20, 32)
Augie Fackler
manifest: remove a 20-byte-hash assumption from pure manifest parsing...
r45191 return d[0] + b'\x00' + hex(n) + d[2] + b'\n'
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042
manifest: add many type annotations to the manifest module...
r52667 def text(self) -> ByteString:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 self._compact()
return self.data
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def diff(
self, m2: '_LazyManifest', clean: bool = False
) -> Dict[
bytes,
Optional[
Tuple[Tuple[Optional[bytes], bytes], Tuple[Optional[bytes], bytes]]
],
]:
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 '''Finds changes between the current manifest and m2.'''
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 # XXX think whether efficiency matters here
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 diff = {}
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 for fn, e1, flags in self.iterentries():
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 if fn not in m2:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diff[fn] = (e1, flags), (None, b'')
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 else:
e2 = m2[fn]
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 if (e1, flags) != e2:
diff[fn] = (e1, flags), e2
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 elif clean:
diff[fn] = None
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 for fn, e2, flags in m2.iterentries():
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 if fn not in self:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 diff[fn] = (None, b''), (e2, flags)
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
return diff
manifest: add many type annotations to the manifest module...
r52667 def iterentries(self) -> lazymanifestiterentries:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return lazymanifestiterentries(self)
manifest: add many type annotations to the manifest module...
r52667 def iterkeys(self) -> lazymanifestiter:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return lazymanifestiter(self)
manifest: add many type annotations to the manifest module...
r52667 def __iter__(self) -> lazymanifestiter:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return lazymanifestiter(self)
manifest: add many type annotations to the manifest module...
r52667 def __len__(self) -> int:
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 return len(self.positions)
manifest: add many type annotations to the manifest module...
r52667 def filtercopy(self, filterfn: Callable[[bytes], bool]) -> '_LazyManifest':
Maciej Fijalkowski
lazymanifest: write a more efficient, pypy friendly version of lazymanifest
r30042 # XXX should be optimized
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 c = _lazymanifest(self._nodelen, b'')
Martin von Zweigbergk
lazymanifest: make __iter__ generate filenames, not 3-tuples...
r24298 for f, n, fl in self.iterentries():
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 if filterfn(f):
c[f] = n, fl
return c
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
manifest: use custom C implementation of lazymanifest...
r24226 try:
_lazymanifest = parsers.lazymanifest
except AttributeError:
manifest: expose a version of the Class without interface decorator...
r52661 _lazymanifest = _LazyManifest
Augie Fackler
manifest: use custom C implementation of lazymanifest...
r24226
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
manifest: subclass the new `repository.imanifestdict` Protocol class...
r53392 class manifestdict(repository.imanifestdict):
manifest: add many type annotations to the manifest module...
r52667 def __init__(self, nodelen: int, data: ByteString = b''):
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 self._nodelen = nodelen
self._lm = _lazymanifest(nodelen, data)
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def __getitem__(self, key: bytes) -> bytes:
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 return self._lm[key][0]
manifest: add many type annotations to the manifest module...
r52667 def find(self, key: bytes) -> Tuple[bytes, bytes]:
Martin von Zweigbergk
manifest: don't let find() look inside manifestdict...
r24277 return self._lm[key]
manifest: add many type annotations to the manifest module...
r52667 def __len__(self) -> int:
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 return len(self._lm)
manifest: add many type annotations to the manifest module...
r52667 def __nonzero__(self) -> bool:
Durham Goode
manifest: add __nonzero__ method...
r30331 # nonzero is covered by the __len__ function, but implementing it here
# makes it easier for extensions to override.
return len(self._lm) != 0
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 __bool__ = __nonzero__
manifest: add many type annotations to the manifest module...
r52667 def set(self, key: bytes, node: bytes, flags: bytes) -> None:
Arseniy Alekseyev
commit: set whole manifest entries at once (node with its associated flags)...
r52651 self._lm[key] = node, flags
manifest: add many type annotations to the manifest module...
r52667 def __setitem__(self, key: bytes, node: bytes) -> None:
Augie Fackler
manifest: remove optional default= argument on flags(path)...
r44725 self._lm[key] = node, self.flags(key)
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def __contains__(self, key: bytes) -> bool:
Pulkit Goyal
py3: return False early while checking whether None is a key in lazymanifest...
r34347 if key is None:
return False
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 return key in self._lm
Matt Harbison
typing: correct a type hint in `mercurial.manifest`...
r52694 def __delitem__(self, key: bytes) -> None:
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 del self._lm[key]
manifest: add many type annotations to the manifest module...
r52667 def __iter__(self) -> Iterator[bytes]:
Martin von Zweigbergk
lazymanifest: make __iter__ generate filenames, not 3-tuples...
r24298 return self._lm.__iter__()
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def iterkeys(self) -> Iterator[bytes]:
Martin von Zweigbergk
lazymanifest: add iterkeys() method...
r24295 return self._lm.iterkeys()
manifest: add many type annotations to the manifest module...
r52667 def keys(self) -> List[bytes]:
Martin von Zweigbergk
lazymanifest: add iterkeys() method...
r24295 return list(self.iterkeys())
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225
manifest: add many type annotations to the manifest module...
r52667 def filesnotin(self, m2, match=None) -> Set[bytes]:
Martin von Zweigbergk
copies: move code into new manifestdict.filesnotin() method...
r24184 '''Set of files in this manifest that are not in the other'''
Augie Fackler
manifest: rewrite filesnotin to not make superfluous manifest copies...
r44768 if match is not None:
match = matchmod.badmatch(match, lambda path, msg: None)
sm2 = set(m2.walk(match))
return {f for f in self.walk(match) if f not in sm2}
return {f for f in self if f not in m2}
Martin von Zweigbergk
copies: move code into new manifestdict.filesnotin() method...
r24184
Drew Gottlieb
manifest: add dirs() to manifestdict...
r24322 @propertycache
manifest: add many type annotations to the manifest module...
r52667 def _dirs(self) -> pathutil.dirs:
utils: move the `dirs` definition in pathutil (API)...
r43923 return pathutil.dirs(self)
Drew Gottlieb
manifest: add dirs() to manifestdict...
r24322
manifest: add many type annotations to the manifest module...
r52667 def dirs(self) -> pathutil.dirs:
Drew Gottlieb
manifest: add dirs() to manifestdict...
r24322 return self._dirs
manifest: add many type annotations to the manifest module...
r52667 def hasdir(self, dir: bytes) -> bool:
Drew Gottlieb
manifest: add manifestdict.hasdir() method...
r24324 return dir in self._dirs
manifest: add many type annotations to the manifest module...
r52667 def _filesfastpath(self, match: matchmod.basematcher) -> bool:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Checks whether we can correctly and quickly iterate over matcher
files instead of over manifest files."""
Martin von Zweigbergk
manifestdict: extract condition for _intersectfiles() and use for walk()...
r24685 files = match.files()
Augie Fackler
formatting: blacken the codebase...
r43346 return len(files) < 100 and (
match.isexact()
or (match.prefix() and all(fn in self for fn in files))
)
Martin von Zweigbergk
manifestdict: extract condition for _intersectfiles() and use for walk()...
r24685
manifest: add many type annotations to the manifest module...
r52667 def walk(self, match: matchmod.basematcher) -> Iterator[bytes]:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Generates matching file names.
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646
Equivalent to manifest.matches(match).iterkeys(), but without creating
an entirely new manifest.
It also reports nonexistent files by marking them bad with match.bad().
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Martin von Zweigbergk
manifest.walk: special-case match.always() for speed...
r24683 if match.always():
for f in iter(self):
yield f
return
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 fset = set(match.files())
# avoid the entire walk if we're only looking for specific files
Martin von Zweigbergk
manifestdict: extract condition for _intersectfiles() and use for walk()...
r24685 if self._filesfastpath(match):
Martin von Zweigbergk
manifest.walk: join nested if-conditions...
r24667 for fn in sorted(fset):
Augie Fackler
manifest: fix _very_ subtle bug with exact matchers passed to walk()...
r44741 if fn in self:
yield fn
Martin von Zweigbergk
manifest.walk: use return instead of StopIteration in generator...
r24682 return
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646
for fn in self:
if fn in fset:
# specified pattern is the exact name
fset.remove(fn)
if match(fn):
yield fn
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 # for dirstate.walk, files=[''] means "walk the whole tree".
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 # follow that here, too
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fset.discard(b'')
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646
for fn in sorted(fset):
if not self.hasdir(fn):
match.bad(fn, None)
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def _matches(self, match: matchmod.basematcher) -> 'manifestdict':
Martin von Zweigbergk
manifest: add matches() method...
r23305 '''generate a new manifest filtered by the match argument'''
if match.always():
return self.copy()
Martin von Zweigbergk
manifestdict: extract condition for _intersectfiles() and use for walk()...
r24685 if self._filesfastpath(match):
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 m = manifestdict(self._nodelen)
Martin von Zweigbergk
manifestdict: inline _intersectfiles()...
r24666 lm = self._lm
for fn in match.files():
if fn in lm:
m._lm[fn] = lm[fn]
return m
Martin von Zweigbergk
manifest: add matches() method...
r23305
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 m = manifestdict(self._nodelen)
Martin von Zweigbergk
manifestdict.matches: avoid name 'lm' for a not-lazymanifest
r24664 m._lm = self._lm.filtercopy(match)
return m
Martin von Zweigbergk
manifest: add matches() method...
r23305
manifest: add many type annotations to the manifest module...
r52667 def diff(
self,
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 m2: 'manifestdict',
manifest: add many type annotations to the manifest module...
r52667 match: Optional[matchmod.basematcher] = None,
clean: bool = False,
) -> Dict[
bytes,
Optional[
Tuple[Tuple[Optional[bytes], bytes], Tuple[Optional[bytes], bytes]]
],
]:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Finds changes between the current manifest and m2.
Augie Fackler
manifest: add optional recording of clean entries to diff...
r23756
Args:
m2: the manifest to which this manifest should be compared.
clean: if true, include files unchanged between these manifests
with a None value in the returned dictionary.
The result is returned as a dict with filename as key and
values of the form ((n1,fl1),(n2,fl2)), where n1/n2 is the
nodeid in the current/other manifest and fl1/fl2 is the flag
in the current/other manifest. Where the file does not exist,
the nodeid will be None and the flags will be the empty
string.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Durham Goode
manifest: add match argument to diff and filesnotin...
r31255 if match:
Augie Fackler
manifest: move matches method to be outside the interface...
r44826 m1 = self._matches(match)
m2 = m2._matches(match)
Durham Goode
manifest: add match argument to diff and filesnotin...
r31255 return m1.diff(m2, clean=clean)
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 return self._lm.diff(m2._lm, clean)
manifest: add many type annotations to the manifest module...
r52667 def setflag(self, key: bytes, flag: bytes) -> None:
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 if flag not in _manifestflags:
raise TypeError(b"Invalid manifest flag set.")
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 self._lm[key] = self[key], flag
manifest: add many type annotations to the manifest module...
r52667 def get(self, key: bytes, default=None) -> Optional[bytes]:
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 try:
return self._lm[key][0]
except KeyError:
return default
Martin von Zweigbergk
manifest: for diff(), only iterate over files, not flags...
r22965
manifest: add many type annotations to the manifest module...
r52667 def flags(self, key: bytes) -> bytes:
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 try:
return self._lm[key][1]
except KeyError:
Augie Fackler
manifest: remove optional default= argument on flags(path)...
r44725 return b''
Martin von Zweigbergk
manifest: for diff(), only iterate over files, not flags...
r22965
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def copy(self) -> 'manifestdict':
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 c = manifestdict(self._nodelen)
Augie Fackler
manifest: split manifestdict into high-level and low-level logic...
r24225 c._lm = self._lm.copy()
return c
manifest: add many type annotations to the manifest module...
r52667 def items(self) -> Iterator[Tuple[bytes, bytes]]:
Martin von Zweigbergk
lazymanifest: make __iter__ generate filenames, not 3-tuples...
r24298 return (x[:2] for x in self._lm.iterentries())
Matt Mackall
Add manifestflags class
r2831
manifest: add many type annotations to the manifest module...
r52667 def iteritems(self) -> Iterator[Tuple[bytes, bytes]]:
Augie Fackler
manifest: just duplicate the definition of items as iteritems...
r38679 return (x[:2] for x in self._lm.iterentries())
Augie Fackler
cleanup: rename all iteritems methods to items and add iteritems alias...
r32550
manifest: add many type annotations to the manifest module...
r52667 def iterentries(self) -> Iterator[Tuple[bytes, bytes, bytes]]:
Martin von Zweigbergk
verify: check directory manifests...
r28203 return self._lm.iterentries()
manifest: add many type annotations to the manifest module...
r52667 def text(self) -> ByteString:
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 # most likely uses native version
return self._lm.text()
Augie Fackler
manifest: move checkforbidden to module-level...
r22408
manifest: add many type annotations to the manifest module...
r52667 def fastdelta(
self, base: ByteString, changes: Iterable[Tuple[bytes, bool]]
) -> Tuple[ByteString, ByteString]:
Martin von Zweigbergk
manifest: update comment to be about bytearray...
r31787 """Given a base manifest text as a bytearray and a list of changes
Augie Fackler
manifest: add fastdelta method to manifestdict...
r22931 relative to that text, compute a delta that can be used by revlog.
"""
delta = []
dstart = None
dend = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dline = [b""]
Augie Fackler
manifest: add fastdelta method to manifestdict...
r22931 start = 0
# zero copy representation of base as a buffer
addbuf = util.buffer(base)
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 changes = list(changes)
Matt Harbison
tests: demonstrate broken manifest generation with the pure module...
r42568 if len(changes) < FASTDELTA_TEXTDIFF_THRESHOLD:
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 # start with a readonly loop that finds the offset of
# each line and creates the deltas
for f, todelete in changes:
# bs will either be the index of the item or the insert point
start, end = _msearch(addbuf, f, start)
if not todelete:
h, fl = self._lm[f]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 l = b"%s\0%s%s\n" % (f, hex(h), fl)
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 else:
if start == end:
# item we want to delete was not found, error out
raise AssertionError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"failed to remove %s from manifest") % f
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 l = b""
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 if dstart is not None and dstart <= start and dend >= start:
if dend < end:
dend = end
if l:
dline.append(l)
else:
if dstart is not None:
manifest: use tuple for `delta` in `fastdelta`...
r52662 delta.append((dstart, dend, b"".join(dline)))
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 dstart = start
Augie Fackler
manifest: add fastdelta method to manifestdict...
r22931 dend = end
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 dline = [l]
Augie Fackler
manifest: add fastdelta method to manifestdict...
r22931
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 if dstart is not None:
manifest: use tuple for `delta` in `fastdelta`...
r52662 delta.append((dstart, dend, b"".join(dline)))
Durham Goode
manifest: skip fastdelta if the change is large...
r26871 # apply the delta to the base, and get a delta for addrevision
deltatext, arraytext = _addlistdelta(base, delta)
else:
# For large changes, it's much cheaper to just build the text and
# diff it.
Augie Fackler
py3: use bytearray() instead of array('c', ...) constructions...
r31346 arraytext = bytearray(self.text())
deltatext = mdiff.textdiff(
Augie Fackler
formatting: blacken the codebase...
r43346 util.buffer(base), util.buffer(arraytext)
)
Durham Goode
manifest: skip fastdelta if the change is large...
r26871
Augie Fackler
manifest: add fastdelta method to manifestdict...
r22931 return arraytext, deltatext
Augie Fackler
formatting: blacken the codebase...
r43346
manifest: add many type annotations to the manifest module...
r52667 def _msearch(
m: ByteString, s: bytes, lo: int = 0, hi: Optional[int] = None
) -> Tuple[int, int]:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """return a tuple (start, end) that says where to find s within m.
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930
If the string is found m[start:end] are the line containing
that string. If start == end the string was not found and
they indicate the proper sorted insertion point.
manifest: add many type annotations to the manifest module...
r52667 """
def advance(i: int, c: bytes):
Augie Fackler
formatting: blacken the codebase...
r43346 while i < lenm and m[i : i + 1] != c:
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 i += 1
return i
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 if not s:
return (lo, lo)
lenm = len(m)
if not hi:
hi = lenm
while lo < hi:
mid = (lo + hi) // 2
start = mid
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 while start > 0 and m[start - 1 : start] != b'\n':
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 start -= 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 end = advance(start, b'\0')
Yuya Nishihara
py3: fix manifestdict.fastdelta() to be compatible with memoryview...
r31650 if bytes(m[start:end]) < s:
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 # we know that after the null there are 40 bytes of sha1
# this translates to the bisect lo = mid + 1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lo = advance(end + 40, b'\n') + 1
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 else:
# this translates to the bisect hi = mid
hi = start
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 end = advance(lo, b'\0')
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 found = m[lo:end]
if s == found:
# we know that after the null there are 40 bytes of sha1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 end = advance(end + 40, b'\n')
Augie Fackler
manifest: move _search to module level and rename to _msearch...
r22930 return (lo, end + 1)
else:
return (lo, lo)
Augie Fackler
formatting: blacken the codebase...
r43346
manifest: add many type annotations to the manifest module...
r52667 def _checkforbidden(l: Iterable[bytes]) -> None:
Augie Fackler
manifest: move checkforbidden to module-level...
r22408 """Check filenames for illegal characters."""
for f in l:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'\n' in f or b'\r' in f:
Gregory Szorc
global: replace most uses of RevlogError with StorageError (API)...
r39813 raise error.StorageError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"'\\n' and '\\r' disallowed in filenames: %r")
Augie Fackler
formatting: blacken the codebase...
r43346 % pycompat.bytestr(f)
)
Augie Fackler
manifest: move checkforbidden to module-level...
r22408
Augie Fackler
manifest: move addlistdelta to module-level...
r22409 # apply the changes collected during the bisect loop to our addlist
# return a delta suitable for addrevision
manifest: add many type annotations to the manifest module...
r52667 def _addlistdelta(
addlist: ByteString,
x: Iterable[Tuple[int, int, bytes]],
) -> Tuple[bytes, ByteString]:
Augie Fackler
manifest: move addlistdelta to module-level...
r22409 # for large addlist arrays, building a new array is cheaper
# than repeatedly modifying the existing one
currentposition = 0
Augie Fackler
py3: use bytearray() instead of array('c', ...) constructions...
r31346 newaddlist = bytearray()
Augie Fackler
manifest: move addlistdelta to module-level...
r22409
for start, end, content in x:
newaddlist += addlist[currentposition:start]
if content:
Augie Fackler
py3: use bytearray() instead of array('c', ...) constructions...
r31346 newaddlist += bytearray(content)
Augie Fackler
manifest: move addlistdelta to module-level...
r22409
currentposition = end
newaddlist += addlist[currentposition:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 deltatext = b"".join(
struct.pack(b">lll", start, end, len(content)) + content
Augie Fackler
formatting: blacken the codebase...
r43346 for start, end, content in x
)
Augie Fackler
manifest: move addlistdelta to module-level...
r22409 return deltatext, newaddlist
Augie Fackler
formatting: blacken the codebase...
r43346
manifest: add many type annotations to the manifest module...
r52667 def _splittopdir(f: bytes) -> Tuple[bytes, bytes]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'/' in f:
dir, subpath = f.split(b'/', 1)
return dir + b'/', subpath
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'', f
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 _noop = lambda s: None
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 class treemanifest: # (repository.imanifestdict)
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719 _dir: bytes
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 _dirs: Dict[bytes, 'treemanifest']
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719 _dirty: bool
_files: Dict[bytes, bytes]
_flags: Dict[bytes, bytes]
manifest: add many type annotations to the manifest module...
r52667 def __init__(self, nodeconstants, dir: bytes = b'', text: bytes = b''):
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403 self._dir = dir
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self.nodeconstants = nodeconstants
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 self._node = self.nodeconstants.nullid
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 self._nodelen = self.nodeconstants.nodelen
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 self._loadfunc = _noop
self._copyfunc = _noop
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 self._dirty = False
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719 self._dirs = {}
manifest: add many type annotations to the manifest module...
r52667 self._lazydirs: Dict[
bytes,
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 Tuple[bytes, Callable[[bytes, bytes], 'treemanifest'], bool],
manifest: add many type annotations to the manifest module...
r52667 ] = {}
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 # Using _lazymanifest here is a little slower than plain old dicts
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719 self._files = {}
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 self._flags = {}
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 if text:
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 def readsubtree(subdir, subm):
Augie Fackler
formatting: blacken the codebase...
r43346 raise AssertionError(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'treemanifest constructor only accepts flat manifests'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 self.parse(text, readsubtree)
Augie Fackler
formatting: blacken the codebase...
r43346 self._dirty = True # Mark flat manifest dirty after parsing
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def _subpath(self, path: bytes) -> bytes:
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403 return self._dir + path
manifest: add many type annotations to the manifest module...
r52667 def _loadalllazy(self) -> None:
spectral
treemanifests: store whether a lazydirs entry needs copied after materializing...
r40075 selfdirs = self._dirs
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 subpath = self._subpath
Gregory Szorc
manifest: remove pycompat.iteritems()...
r49781 for d, (node, readsubtree, docopy) in self._lazydirs.items():
spectral
treemanifests: store whether a lazydirs entry needs copied after materializing...
r40075 if docopy:
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 selfdirs[d] = readsubtree(subpath(d), node).copy()
spectral
treemanifests: store whether a lazydirs entry needs copied after materializing...
r40075 else:
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 selfdirs[d] = readsubtree(subpath(d), node)
manifest: clear `_lazydirs` in place in `_loadalllazy`...
r52663 self._lazydirs.clear()
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
manifest: add many type annotations to the manifest module...
r52667 def _loadlazy(self, d: bytes) -> None:
spectral
treemanifests: make _loadlazy tolerate item not on _lazydirs...
r40017 v = self._lazydirs.get(d)
manifest: use explicit None checking in `_loadlazy`...
r52664 if v is not None:
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 node, readsubtree, docopy = v
spectral
treemanifests: store whether a lazydirs entry needs copied after materializing...
r40075 if docopy:
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 self._dirs[d] = readsubtree(self._subpath(d), node).copy()
spectral
treemanifests: store whether a lazydirs entry needs copied after materializing...
r40075 else:
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 self._dirs[d] = readsubtree(self._subpath(d), node)
spectral
treemanifests: make _loadlazy tolerate item not on _lazydirs...
r40017 del self._lazydirs[d]
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
manifest: add many type annotations to the manifest module...
r52667 def _loadchildrensetlazy(
self, visit: Union[Set[bytes], bytes]
) -> Optional[Set[bytes]]:
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 if not visit:
return None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if visit == b'all' or visit == b'this':
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 self._loadalllazy()
return None
manifest: add many type annotations to the manifest module...
r52667 visit = cast(Set[bytes], visit)
spectral
treemanifests: make _loadchildrensetlazy just call _loadlazy...
r40018 loadlazy = self._loadlazy
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 for k in visit:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 loadlazy(k + b'/')
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 return visit
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def _loaddifflazy(self, t1: 'treemanifest', t2: 'treemanifest'):
spectral
treemanifests: extract _loaddifflazy from _diff, use in _filesnotin...
r40074 """load items in t1 and t2 if they're needed for diffing.
The criteria currently is:
- if it's not present in _lazydirs in either t1 or t2, load it in the
other (it may already be loaded or it may not exist, doesn't matter)
- if it's present in _lazydirs in both, compare the nodeid; if it
differs, load it in both
"""
toloadlazy = []
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, v1 in t1._lazydirs.items():
spectral
treemanifests: extract _loaddifflazy from _diff, use in _filesnotin...
r40074 v2 = t2._lazydirs.get(d)
manifest: use explicit None checking in `_loaddifflazy`...
r52665 if v2 is None or v2[0] != v1[0]:
spectral
treemanifests: extract _loaddifflazy from _diff, use in _filesnotin...
r40074 toloadlazy.append(d)
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, v1 in t2._lazydirs.items():
spectral
treemanifests: extract _loaddifflazy from _diff, use in _filesnotin...
r40074 if d not in t1._lazydirs:
toloadlazy.append(d)
for d in toloadlazy:
t1._loadlazy(d)
t2._loadlazy(d)
manifest: add many type annotations to the manifest module...
r52667 def __len__(self) -> int:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 size = len(self._files)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 self._loadalllazy()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 for m in self._dirs.values():
size += m.__len__()
return size
manifest: add many type annotations to the manifest module...
r52667 def __nonzero__(self) -> bool:
# Faster than "__len__() != 0" since it avoids loading sub-manifests
Martin von Zweigbergk
treemanifest: add an optimized __nonzero__()...
r36192 return not self._isempty()
__bool__ = __nonzero__
manifest: add many type annotations to the manifest module...
r52667 def _isempty(self) -> bool:
Augie Fackler
formatting: blacken the codebase...
r43346 self._load() # for consistency; already loaded by all callers
Kyle Lippincott
treemanifest: attempt to avoid loading all lazily-loaded subdirs in _isempty...
r39552 # See if we can skip loading everything.
Augie Fackler
formatting: blacken the codebase...
r43346 if self._files or (
self._dirs and any(not m._isempty() for m in self._dirs.values())
):
Kyle Lippincott
treemanifest: attempt to avoid loading all lazily-loaded subdirs in _isempty...
r39552 return False
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 self._loadalllazy()
Augie Fackler
formatting: blacken the codebase...
r43346 return not self._dirs or all(m._isempty() for m in self._dirs.values())
Drew Gottlieb
treemanifest: add treemanifest._isempty()...
r24551
Kyle Lippincott
py3: __repr__ needs to return str, not bytes...
r44742 @encoding.strmethod
manifest: add many type annotations to the manifest module...
r52667 def __repr__(self) -> bytes:
formatting: run black version 19.10b0 on the codebase...
r43663 return (
Kyle Lippincott
py3: __repr__ needs to return str, not bytes...
r44742 b'<treemanifest dir=%s, node=%s, loaded=%r, dirty=%r at 0x%x>'
formatting: run black version 19.10b0 on the codebase...
r43663 % (
self._dir,
hex(self._node),
bool(self._loadfunc is _noop),
self._dirty,
id(self),
)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091
manifest: add many type annotations to the manifest module...
r52667 def dir(self) -> bytes:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """The directory that this tree manifest represents, including a
trailing '/'. Empty string for the repo root directory."""
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 return self._dir
manifest: add many type annotations to the manifest module...
r52667 def node(self) -> bytes:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """This node of this instance. nullid for unsaved instances. Should
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 be updated when the instance is read or written from a revlog.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 assert not self._dirty
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 return self._node
manifest: add many type annotations to the manifest module...
r52667 def setnode(self, node: bytes) -> None:
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 self._node = node
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 self._dirty = False
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403
manifest: add many type annotations to the manifest module...
r52667 def iterentries(
self,
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 ) -> Iterator[Tuple[bytes, Union[bytes, 'treemanifest'], bytes]]:
Martin von Zweigbergk
treemanifest: implement iterentries()...
r28206 self._load()
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 self._loadalllazy()
Augie Fackler
formatting: blacken the codebase...
r43346 for p, n in sorted(
itertools.chain(self._dirs.items(), self._files.items())
):
Martin von Zweigbergk
treemanifest: implement iterentries()...
r28206 if p in self._files:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield self._subpath(p), n, self._flags.get(p, b'')
Martin von Zweigbergk
treemanifest: implement iterentries()...
r28206 else:
for x in n.iterentries():
yield x
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def items(self) -> Iterator[Tuple[bytes, Union[bytes, 'treemanifest']]]:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 self._loadalllazy()
Augie Fackler
formatting: blacken the codebase...
r43346 for p, n in sorted(
itertools.chain(self._dirs.items(), self._files.items())
):
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if p in self._files:
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403 yield self._subpath(p), n
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 else:
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for f, sn in n.items():
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403 yield f, sn
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Augie Fackler
cleanup: rename all iteritems methods to items and add iteritems alias...
r32550 iteritems = items
manifest: add many type annotations to the manifest module...
r52667 def iterkeys(self) -> Iterator[bytes]:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 self._loadalllazy()
Augie Fackler
manifest: use itertools.chain() instead of + for Python 3 compat...
r32536 for p in sorted(itertools.chain(self._dirs, self._files)):
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if p in self._files:
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403 yield self._subpath(p)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 else:
Pulkit Goyal
py3: don't use dict.iterkeys()...
r35604 for f in self._dirs[p]:
Martin von Zweigbergk
treemanifest: store directory path in treemanifest nodes...
r24403 yield f
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def keys(self) -> List[bytes]:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return list(self.iterkeys())
manifest: add many type annotations to the manifest module...
r52667 def __iter__(self) -> Iterator[bytes]:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return self.iterkeys()
manifest: add many type annotations to the manifest module...
r52667 def __contains__(self, f: bytes) -> bool:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if f is None:
return False
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if dir not in self._dirs:
return False
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return self._dirs[dir].__contains__(subpath)
else:
return f in self._files
manifest: add many type annotations to the manifest module...
r52667 def get(self, f: bytes, default: Optional[bytes] = None) -> Optional[bytes]:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if dir not in self._dirs:
return default
return self._dirs[dir].get(subpath, default)
else:
return self._files.get(f, default)
manifest: add many type annotations to the manifest module...
r52667 def __getitem__(self, f: bytes) -> bytes:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return self._dirs[dir].__getitem__(subpath)
else:
return self._files[f]
manifest: add many type annotations to the manifest module...
r52667 def flags(self, f: bytes) -> bytes:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if dir not in self._dirs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return self._dirs[dir].flags(subpath)
else:
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 if f in self._lazydirs or f in self._dirs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
return self._flags.get(f, b'')
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def find(self, f: bytes) -> Tuple[bytes, bytes]:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return self._dirs[dir].find(subpath)
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._files[f], self._flags.get(f, b'')
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def __delitem__(self, f: bytes) -> None:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
spectral
treemanifest: introduce lazy loading of subdirs...
r39551
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 self._dirs[dir].__delitem__(subpath)
# If the directory is now empty, remove it
Drew Gottlieb
treemanifest: add treemanifest._isempty()...
r24551 if self._dirs[dir]._isempty():
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 del self._dirs[dir]
else:
del self._files[f]
if f in self._flags:
del self._flags[f]
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 self._dirty = True
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def set(self, f: bytes, node: bytes, flags: bytes) -> None:
Arseniy Alekseyev
commit: set whole manifest entries at once (node with its associated flags)...
r52651 """Set both the node and the flags for path f."""
assert node is not None
if flags not in _manifestflags:
raise TypeError(b"Invalid manifest flag set.")
self._load()
dir, subpath = _splittopdir(f)
if dir:
self._loadlazy(dir)
if dir not in self._dirs:
self._dirs[dir] = treemanifest(
self.nodeconstants, self._subpath(dir)
)
self._dirs[dir].set(subpath, node, flags)
else:
assert len(node) in (20, 32)
self._files[f] = node
self._flags[f] = flags
self._dirty = True
manifest: add many type annotations to the manifest module...
r52667 def __setitem__(self, f: bytes, n: bytes) -> None:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 assert n is not None
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if dir not in self._dirs:
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self._dirs[dir] = treemanifest(
self.nodeconstants, self._subpath(dir)
)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 self._dirs[dir].__setitem__(subpath, n)
else:
Augie Fackler
manifest: teach treemanifest about long hashes...
r45193 # manifest nodes are either 20 bytes or 32 bytes,
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 # depending on the hash in use. Assert this as historically
# sometimes extra bytes were added.
assert len(n) in (20, 32)
self._files[f] = n
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 self._dirty = True
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def _load(self) -> None:
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 if self._loadfunc is not _noop:
lf, self._loadfunc = self._loadfunc, _noop
lf(self)
elif self._copyfunc is not _noop:
cf, self._copyfunc = self._copyfunc, _noop
cf(self)
manifest: add many type annotations to the manifest module...
r52667 def setflag(self, f: bytes, flags: bytes) -> None:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 """Set the flags (symlink, executable) for path f."""
Joerg Sonnenberger
manifest: tigher manifest parsing and flag use...
r45678 if flags not in _manifestflags:
raise TypeError(b"Invalid manifest flag set.")
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 dir, subpath = _splittopdir(f)
if dir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(dir)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 if dir not in self._dirs:
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self._dirs[dir] = treemanifest(
self.nodeconstants, self._subpath(dir)
)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 self._dirs[dir].setflag(subpath, flags)
else:
self._flags[f] = flags
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 self._dirty = True
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def copy(self) -> 'treemanifest':
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 copy = treemanifest(self.nodeconstants, self._dir)
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 copy._node = self._node
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 copy._dirty = self._dirty
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 if self._copyfunc is _noop:
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 def _copyfunc(s):
self._load()
Augie Fackler
formatting: blacken the codebase...
r43346 s._lazydirs = {
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 d: (n, r, True) for d, (n, r, c) in self._lazydirs.items()
Augie Fackler
formatting: blacken the codebase...
r43346 }
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 sdirs = s._dirs
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, v in self._dirs.items():
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 sdirs[d] = v.copy()
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 s._files = dict.copy(self._files)
s._flags = dict.copy(self._flags)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 if self._loadfunc is _noop:
_copyfunc(copy)
else:
copy._copyfunc = _copyfunc
else:
copy._copyfunc = self._copyfunc
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return copy
manifest: add many type annotations to the manifest module...
r52667 def filesnotin(
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 self, m2: 'treemanifest', match: Optional[matchmod.basematcher] = None
manifest: add many type annotations to the manifest module...
r52667 ) -> Set[bytes]:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 '''Set of files in this manifest that are not in the other'''
Kyle Lippincott
treemanifest: avoid unnecessary copies/processing when using alwaysmatcher...
r39553 if match and not match.always():
Augie Fackler
manifest: move matches method to be outside the interface...
r44826 m1 = self._matches(match)
m2 = m2._matches(match)
Durham Goode
manifest: add match argument to diff and filesnotin...
r31255 return m1.filesnotin(m2)
Martin von Zweigbergk
treemanifest: make filesnotin() faster...
r24405 files = set()
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
treemanifest: make filesnotin() faster...
r24405 def _filesnotin(t1, t2):
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 if t1._node == t2._node and not t1._dirty and not t2._dirty:
return
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 t1._load()
t2._load()
spectral
treemanifests: extract _loaddifflazy from _diff, use in _filesnotin...
r40074 self._loaddifflazy(t1, t2)
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, m1 in t1._dirs.items():
Martin von Zweigbergk
treemanifest: make filesnotin() faster...
r24405 if d in t2._dirs:
m2 = t2._dirs[d]
_filesnotin(m1, m2)
else:
files.update(m1.iterkeys())
Augie Fackler
manifest: correct the one use of iterkeys() on a dict...
r36314 for fn in t1._files:
Martin von Zweigbergk
treemanifest: make filesnotin() faster...
r24405 if fn not in t2._files:
files.add(t1._subpath(fn))
_filesnotin(self, m2)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return files
@propertycache
manifest: add many type annotations to the manifest module...
r52667 def _alldirs(self) -> pathutil.dirs:
utils: move the `dirs` definition in pathutil (API)...
r43923 return pathutil.dirs(self)
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def dirs(self) -> pathutil.dirs:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 return self._alldirs
manifest: add many type annotations to the manifest module...
r52667 def hasdir(self, dir: bytes) -> bool:
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: make hasdir() faster...
r24406 topdir, subdir = _splittopdir(dir)
if topdir:
spectral
treemanifests: skip extraneous check for item before calling _loadlazy...
r40019 self._loadlazy(topdir)
Martin von Zweigbergk
treemanifest: make hasdir() faster...
r24406 if topdir in self._dirs:
return self._dirs[topdir].hasdir(subdir)
return False
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dirslash = dir + b'/'
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 return dirslash in self._dirs or dirslash in self._lazydirs
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def walk(self, match: matchmod.basematcher) -> Iterator[bytes]:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Generates matching file names.
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646
It also reports nonexistent files by marking them bad with match.bad().
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Martin von Zweigbergk
manifest.walk: special-case match.always() for speed...
r24683 if match.always():
for f in iter(self):
yield f
return
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 fset = set(match.files())
Drew Gottlieb
treemanifest: refactor treemanifest.walk()...
r24647 for fn in self._walk(match):
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 if fn in fset:
# specified pattern is the exact name
fset.remove(fn)
Drew Gottlieb
treemanifest: refactor treemanifest.walk()...
r24647 yield fn
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 # for dirstate.walk, files=[''] means "walk the whole tree".
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646 # follow that here, too
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fset.discard(b'')
Drew Gottlieb
manifest: move changectx.walk() to manifests...
r24646
for fn in sorted(fset):
if not self.hasdir(fn):
match.bad(fn, None)
manifest: add many type annotations to the manifest module...
r52667 def _walk(self, match: matchmod.basematcher) -> Iterator[bytes]:
Drew Gottlieb
match: remove unnecessary optimization where visitdir() returns 'all'...
r25188 '''Recursively generates matching file names for walk().'''
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 visit = match.visitchildrenset(self._dir[:-1])
Kyle Lippincott
treemanifest: use visitchildrenset when doing a walk...
r39558 if not visit:
Drew Gottlieb
match: remove unnecessary optimization where visitdir() returns 'all'...
r25188 return
Drew Gottlieb
treemanifest: refactor treemanifest.walk()...
r24647
# yield this dir's files and walk its submanifests
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Kyle Lippincott
treemanifest: use visitchildrenset when doing a walk...
r39558 visit = self._loadchildrensetlazy(visit)
Augie Fackler
manifest: use list(dict) instead of dict.keys() to get a list of keys...
r36315 for p in sorted(list(self._dirs) + list(self._files)):
Drew Gottlieb
treemanifest: refactor treemanifest.walk()...
r24647 if p in self._files:
fullp = self._subpath(p)
if match(fullp):
yield fullp
else:
Kyle Lippincott
treemanifest: use visitchildrenset when doing a walk...
r39558 if not visit or p[:-1] in visit:
for f in self._dirs[p]._walk(match):
yield f
Drew Gottlieb
treemanifest: refactor treemanifest.walk()...
r24647
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def _matches(self, match: matchmod.basematcher) -> 'treemanifest':
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """recursively generate a new manifest filtered by the match argument."""
Augie Fackler
manifest: move matches method to be outside the interface...
r44826 if match.always():
return self.copy()
return self._matches_inner(match)
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def _matches_inner(self, match: matchmod.basematcher) -> 'treemanifest':
Augie Fackler
manifest: move matches method to be outside the interface...
r44826 if match.always():
return self.copy()
Martin von Zweigbergk
treemanifest: don't iterate entire matching submanifests on match()...
r27343
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 visit = match.visitchildrenset(self._dir[:-1])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if visit == b'all':
Martin von Zweigbergk
treemanifest: don't iterate entire matching submanifests on match()...
r27343 return self.copy()
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 ret = treemanifest(self.nodeconstants, self._dir)
Martin von Zweigbergk
treemanifest: don't iterate entire matching submanifests on match()...
r27343 if not visit:
Drew Gottlieb
match: remove unnecessary optimization where visitdir() returns 'all'...
r25188 return ret
Drew Gottlieb
treemanifest: make treemanifest.matches() faster...
r24552
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Drew Gottlieb
treemanifest: make treemanifest.matches() faster...
r24552 for fn in self._files:
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 # While visitchildrenset *usually* lists only subdirs, this is
# actually up to the matcher and may have some files in the set().
# If visit == 'this', we should obviously look at the files in this
# directory; if visit is a set, and fn is in it, we should inspect
# fn (but no need to inspect things not in the set).
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if visit != b'this' and fn not in visit:
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 continue
Drew Gottlieb
treemanifest: make treemanifest.matches() faster...
r24552 fullp = self._subpath(fn)
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 # visitchildrenset isn't perfect, we still need to call the regular
# matcher code to further filter results.
Drew Gottlieb
treemanifest: make treemanifest.matches() faster...
r24552 if not match(fullp):
continue
ret._files[fn] = self._files[fn]
if fn in self._flags:
ret._flags[fn] = self._flags[fn]
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 visit = self._loadchildrensetlazy(visit)
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for dir, subm in self._dirs.items():
Kyle Lippincott
treemanifest: use visitchildrenset when filtering a manifest to a matcher...
r39557 if visit and dir[:-1] not in visit:
continue
Augie Fackler
manifest: move matches method to be outside the interface...
r44826 m = subm._matches_inner(match)
Drew Gottlieb
treemanifest: make treemanifest.matches() faster...
r24552 if not m._isempty():
ret._dirs[dir] = m
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 if not ret._isempty():
ret._dirty = True
Drew Gottlieb
treemanifest: make treemanifest.matches() faster...
r24552 return ret
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def fastdelta(
self, base: ByteString, changes: Iterable[Tuple[bytes, bool]]
) -> ByteString:
Augie Fackler
manifest: introduce new exception to signal unavailability of fastdelta()...
r45154 raise FastdeltaUnavailable()
manifest: add many type annotations to the manifest module...
r52667 def diff(
self,
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 m2: 'treemanifest',
manifest: add many type annotations to the manifest module...
r52667 match: Optional[matchmod.basematcher] = None,
clean: bool = False,
) -> Dict[
bytes,
Optional[
Tuple[Tuple[Optional[bytes], bytes], Tuple[Optional[bytes], bytes]]
],
]:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Finds changes between the current manifest and m2.
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Args:
m2: the manifest to which this manifest should be compared.
clean: if true, include files unchanged between these manifests
with a None value in the returned dictionary.
The result is returned as a dict with filename as key and
values of the form ((n1,fl1),(n2,fl2)), where n1/n2 is the
nodeid in the current/other manifest and fl1/fl2 is the flag
in the current/other manifest. Where the file does not exist,
the nodeid will be None and the flags will be the empty
string.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Kyle Lippincott
treemanifest: avoid unnecessary copies/processing when using alwaysmatcher...
r39553 if match and not match.always():
Augie Fackler
manifest: move matches method to be outside the interface...
r44826 m1 = self._matches(match)
m2 = m2._matches(match)
Durham Goode
manifest: add match argument to diff and filesnotin...
r31255 return m1.diff(m2, clean=clean)
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 result = {}
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 emptytree = treemanifest(self.nodeconstants)
Pulkit Goyal
manifest: convert a recursive function to iterative one using stacks...
r41188
def _iterativediff(t1, t2, stack):
"""compares two tree manifests and append new tree-manifests which
needs to be compared to stack"""
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 if t1._node == t2._node and not t1._dirty and not t2._dirty:
return
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 t1._load()
t2._load()
spectral
treemanifests: extract _loaddifflazy from _diff, use in _filesnotin...
r40074 self._loaddifflazy(t1, t2)
spectral
treemanifests: remove _loadalllazy in _diff()...
r40020
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, m1 in t1._dirs.items():
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 m2 = t2._dirs.get(d, emptytree)
Pulkit Goyal
manifest: convert a recursive function to iterative one using stacks...
r41188 stack.append((m1, m2))
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, m2 in t2._dirs.items():
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 if d not in t1._dirs:
Pulkit Goyal
manifest: convert a recursive function to iterative one using stacks...
r41188 stack.append((emptytree, m2))
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for fn, n1 in t1._files.items():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fl1 = t1._flags.get(fn, b'')
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 n2 = t2._files.get(fn, None)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fl2 = t2._flags.get(fn, b'')
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 if n1 != n2 or fl1 != fl2:
result[t1._subpath(fn)] = ((n1, fl1), (n2, fl2))
elif clean:
result[t1._subpath(fn)] = None
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for fn, n2 in t2._files.items():
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 if fn not in t1._files:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fl2 = t2._flags.get(fn, b'')
result[t2._subpath(fn)] = ((None, b''), (n2, fl2))
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Pulkit Goyal
manifest: convert a recursive function to iterative one using stacks...
r41188 stackls = []
_iterativediff(self, m2, stackls)
while stackls:
t1, t2 = stackls.pop()
# stackls is populated in the function call
_iterativediff(t1, t2, stackls)
Martin von Zweigbergk
treemanifest: make diff() faster...
r24404 return result
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def unmodifiedsince(self, m2: 'treemanifest') -> bool:
Martin von Zweigbergk
treemanifest: speed up commit using dirty flag...
r25221 return not self._dirty and not m2._dirty and self._node == m2._node
manifest: add many type annotations to the manifest module...
r52667 def parse(
self,
text: bytes,
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 readsubtree: Callable[[bytes, bytes], 'treemanifest'],
manifest: add many type annotations to the manifest module...
r52667 ) -> None:
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 selflazy = self._lazydirs
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 for f, n, fl in _parse(self._nodelen, text):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if fl == b't':
f = f + b'/'
spectral
treemanifests: store whether a lazydirs entry needs copied after materializing...
r40075 # False below means "doesn't need to be copied" and can use the
# cached value from readsubtree directly.
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 selflazy[f] = (n, readsubtree, False)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif b'/' in f:
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 # This is a flat manifest, so use __setitem__ and setflag rather
# than assigning directly to _files and _flags, so we can
# assign a path in a subdirectory, and to mark dirty (compared
# to nullid).
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 self[f] = n
if fl:
self.setflag(f, fl)
Martin von Zweigbergk
treemanifest: speed up diff by keeping track of dirty nodes...
r25220 else:
# Assigning to _files and _flags avoids marking as dirty,
# and should be a little faster.
self._files[f] = n
if fl:
self._flags[f] = fl
Martin von Zweigbergk
treemanifest: extract parse method from constructor...
r24781
manifest: add many type annotations to the manifest module...
r52667 def text(self) -> ByteString:
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401 """Get the full data of this manifest as a bytestring."""
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 return _text(self.iterentries())
Martin von Zweigbergk
treemanifest: create treemanifest class...
r24401
manifest: add many type annotations to the manifest module...
r52667 def dirtext(self) -> ByteString:
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 """Get the full data of this directory as a bytestring. Make sure that
any submanifests have been written first, so their nodeids are correct.
"""
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222 self._load()
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 flags = self.flags
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 lazydirs = [(d[:-1], v[0], b't') for d, v in self._lazydirs.items()]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dirs = [(d[:-1], self._dirs[d]._node, b't') for d in self._dirs]
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 files = [(f, self._files[f], flags(f)) for f in self._files]
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 return _text(sorted(dirs + files + lazydirs))
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091
manifest: add many type annotations to the manifest module...
r52667 def read(
self,
gettext: Callable[[], ByteString],
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 readsubtree: Callable[[bytes, bytes], 'treemanifest'],
manifest: add many type annotations to the manifest module...
r52667 ) -> None:
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 def _load_for_read(s):
s.parse(gettext(), readsubtree)
s._dirty = False
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
treemanifest: rework lazy-copying code (issue4840)...
r26402 self._loadfunc = _load_for_read
Martin von Zweigbergk
treemanifest: lazily load manifests...
r25222
manifest: add many type annotations to the manifest module...
r52667 def writesubtrees(
self,
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 m1: 'treemanifest',
m2: 'treemanifest',
manifest: add many type annotations to the manifest module...
r52667 writesubtree: Callable[
[
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 Callable[['treemanifest'], None],
manifest: add many type annotations to the manifest module...
r52667 bytes,
bytes,
matchmod.basematcher,
],
None,
],
match: matchmod.basematcher,
) -> None:
Augie Fackler
formatting: blacken the codebase...
r43346 self._load() # for consistency; should never have any effect here
Durham Goode
manifest: call m1.load and m2.load before writing a subtree...
r29888 m1._load()
m2._load()
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 emptytree = treemanifest(self.nodeconstants)
Augie Fackler
formatting: blacken the codebase...
r43346
Kyle Lippincott
treemanifest: avoid loading everything just to get their nodeid...
r39554 def getnode(m, d):
ld = m._lazydirs.get(d)
if ld:
Kyle Lippincott
treemanifest: stop storing full path for each item in manifest._lazydirs...
r46711 return ld[0]
manifest: help pytype to understant `writesubtrees`'s `getnode` type...
r52666 tree = m._dirs.get(d, emptytree)
assert tree is not None # helps pytype
return tree._node
Kyle Lippincott
treemanifest: avoid loading everything just to get their nodeid...
r39554
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 # let's skip investigating things that `match` says we do not need.
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 visit = match.visitchildrenset(self._dir[:-1])
spectral
treemanifests: remove _loadalllazy when doing copies...
r40076 visit = self._loadchildrensetlazy(visit)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if visit == b'this' or visit == b'all':
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 visit = None
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, subm in self._dirs.items():
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 if visit and d[:-1] not in visit:
continue
Kyle Lippincott
treemanifest: avoid loading everything just to get their nodeid...
r39554 subp1 = getnode(m1, d)
subp2 = getnode(m2, d)
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if subp1 == self.nodeconstants.nullid:
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091 subp1, subp2 = subp2, subp1
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 writesubtree(subm, subp1, subp2, match)
Martin von Zweigbergk
treemanifest: store submanifest revlog per directory...
r25091
manifest: add many type annotations to the manifest module...
r52667 def walksubtrees(
self, matcher: Optional[matchmod.basematcher] = None
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 ) -> Iterator['treemanifest']:
Durham Goode
treemanifest: add walksubtrees api...
r31876 """Returns an iterator of the subtrees of this manifest, including this
manifest itself.
If `matcher` is provided, it only returns subtrees that match.
"""
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 if matcher and not matcher.visitdir(self._dir[:-1]):
Durham Goode
treemanifest: add walksubtrees api...
r31876 return
if not matcher or matcher(self._dir[:-1]):
yield self
self._load()
spectral
treemanifest: introduce lazy loading of subdirs...
r39551 # OPT: use visitchildrenset to avoid loading everything.
self._loadalllazy()
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for d, subm in self._dirs.items():
Durham Goode
treemanifest: add walksubtrees api...
r31876 for subtree in subm.walksubtrees(matcher=matcher):
yield subtree
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 class manifestfulltextcache(util.lrucachedict):
"""File-backed LRU cache for the manifest cache
File consists of entries, up to EOF:
- 20 bytes node, 4 bytes length, <length> manifest data
These are written in reverse cache order (oldest to newest).
"""
manifestcache: abstract the filename in a class attribute...
r42128
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _file = b'manifestfulltextcache'
manifestcache: abstract the filename in a class attribute...
r42128
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 def __init__(self, max):
super(manifestfulltextcache, self).__init__(max)
self._dirty = False
self._read = False
self._opener = None
def read(self):
if self._read or self._opener is None:
return
try:
manifestcache: abstract the filename in a class attribute...
r42128 with self._opener(self._file) as fp:
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 set = super(manifestfulltextcache, self).__setitem__
# ignore trailing data, this is a cache, corruption is skipped
while True:
Augie Fackler
manifest: leave a TODO where we may have more work for sha1 portability...
r45202 # TODO do we need to do work here for sha1 portability?
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 node = fp.read(20)
if len(node) < 20:
break
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 size = struct.unpack(b'>L', fp.read(4))[0]
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 except struct.error:
break
value = bytearray(fp.read(size))
if len(value) != size:
break
set(node, value)
except IOError:
# the file is allowed to be missing
pass
self._read = True
self._dirty = False
def write(self):
if not self._dirty or self._opener is None:
return
# rotate backwards to the first used node
manifest-cache: ignore IOError while writing...
r45335 try:
with self._opener(
self._file, b'w', atomictemp=True, checkambig=True
) as fp:
node = self._head.prev
while True:
if node.key in self._cache:
fp.write(node.key)
fp.write(struct.pack(b'>L', len(node.value)))
fp.write(node.value)
if node is self._head:
break
node = node.prev
except IOError:
# We could not write the cache (eg: permission error)
# the content can be missing.
#
# We could try harder and see if we could recreate a wcache
# directory were we coudl write too.
#
# XXX the error pass silently, having some way to issue an error
# log `ui.log` would be nice.
pass
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803
def __len__(self):
if not self._read:
self.read()
return super(manifestfulltextcache, self).__len__()
def __contains__(self, k):
if not self._read:
self.read()
return super(manifestfulltextcache, self).__contains__(k)
def __iter__(self):
if not self._read:
self.read()
return super(manifestfulltextcache, self).__iter__()
def __getitem__(self, k):
if not self._read:
self.read()
# the cache lru order can change on read
setdirty = self._cache.get(k) is not self._head
value = super(manifestfulltextcache, self).__getitem__(k)
if setdirty:
self._dirty = True
return value
def __setitem__(self, k, v):
if not self._read:
self.read()
super(manifestfulltextcache, self).__setitem__(k, v)
self._dirty = True
def __delitem__(self, k):
if not self._read:
self.read()
super(manifestfulltextcache, self).__delitem__(k)
self._dirty = True
def get(self, k, default=None):
if not self._read:
self.read()
return super(manifestfulltextcache, self).get(k, default=default)
def clear(self, clear_persisted_data=False):
super(manifestfulltextcache, self).clear()
if clear_persisted_data:
self._dirty = True
self.write()
self._read = False
Augie Fackler
formatting: blacken the codebase...
r43346
revlog: add the option to track the expected compression upper bound...
r42662 # and upper bound of what we expect from compression
# (real live value seems to be "3")
deltas: set estimated compression upper bound to "3x" instead of "10x"...
r42669 MAXCOMPRESSION = 3
revlog: add the option to track the expected compression upper bound...
r42662
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
manifest: introduce new exception to signal unavailability of fastdelta()...
r45154 class FastdeltaUnavailable(Exception):
"""Exception raised when fastdelta isn't usable on a manifest."""
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestrevlog`...
r52962 class manifestrevlog: # (repository.imanifeststorage)
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """A revlog that stores manifest texts. This is responsible for caching the
Durham Goode
manifest: make manifest derive from manifestrevlog...
r29824 full-text manifest contents.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: blacken the codebase...
r43346
def __init__(
self,
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 nodeconstants,
Augie Fackler
formatting: blacken the codebase...
r43346 opener,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tree=b'',
Augie Fackler
formatting: blacken the codebase...
r43346 dirlogcache=None,
treemanifest=False,
):
Durham Goode
manifest: allow specifying the revlog filename...
r31151 """Constructs a new manifest revlog
`indexfile` - used by extensions to have two manifests at once, like
when transitioning between flatmanifeset and treemanifests.
Durham Goode
treemanifest: allow manifestrevlog to take an explicit treemanifest arg...
r32252
`treemanifest` - used to indicate this is a tree manifest revlog. Opener
options can also be used to make this a tree manifest revlog. The opener
option takes precedence, so if it is set to True, we ignore whatever
value is passed in to the constructor.
Durham Goode
manifest: allow specifying the revlog filename...
r31151 """
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self.nodeconstants = nodeconstants
Durham Goode
manifest: make manifest derive from manifestrevlog...
r29824 # During normal operations, we expect to deal with not more than four
# revs at a time (such as during commit --amend). When rebasing large
# stacks of commits, the number can go up, hence the config knob below.
cachesize = 4
Durham Goode
treemanifest: allow manifestrevlog to take an explicit treemanifest arg...
r32252 optiontreemanifest = False
manifest: align some vfs option access on the fact we might not have options...
r52659 persistentnodemap = False
Durham Goode
manifest: make manifest derive from manifestrevlog...
r29824 opts = getattr(opener, 'options', None)
if opts is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachesize = opts.get(b'manifestcachesize', cachesize)
optiontreemanifest = opts.get(b'treemanifest', False)
manifest: align some vfs option access on the fact we might not have options...
r52659 persistentnodemap = opts.get(b'persistent-nodemap', False)
Durham Goode
manifest: move revlog specific options from manifest to manifestrevlog...
r29940
Durham Goode
treemanifest: allow manifestrevlog to take an explicit treemanifest arg...
r32252 self._treeondisk = optiontreemanifest or treemanifest
Durham Goode
manifest: move revlog specific options from manifest to manifestrevlog...
r29940
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 self._fulltextcache = manifestfulltextcache(cachesize)
Durham Goode
manifest: make manifest derive from manifestrevlog...
r29824
Gregory Szorc
manifest: rename dir argument and attribute to tree...
r39279 if tree:
manifest: improve error message in case for tree manifest...
r50101 assert self._treeondisk, (tree, b'opts is %r' % opts)
Durham Goode
manifest: allow specifying the revlog filename...
r31151
revlog: use a "radix" to address revlog...
r47921 radix = b'00manifest'
if tree:
radix = b"meta/" + tree + radix
Durham Goode
manifest: allow specifying the revlog filename...
r31151
Gregory Szorc
manifest: make tree a public attribute...
r39351 self.tree = tree
Durham Goode
manifest: move dirlog up to manifestrevlog...
r29941 # The dirlogcache is kept on the root manifest log
Gregory Szorc
manifest: rename dir argument and attribute to tree...
r39279 if tree:
Durham Goode
manifest: move dirlog up to manifestrevlog...
r29941 self._dirlogcache = dirlogcache
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._dirlogcache = {b'': self}
Durham Goode
manifest: move revlog specific options from manifest to manifestrevlog...
r29940
Augie Fackler
formatting: blacken the codebase...
r43346 self._revlog = revlog.revlog(
opener,
revlog: introduce an explicit tracking of what the revlog is about...
r47838 target=(revlog_constants.KIND_MANIFESTLOG, self.tree),
revlog: use a "radix" to address revlog...
r47921 radix=radix,
Augie Fackler
formatting: blacken the codebase...
r43346 # only root indexfile is cached
checkambig=not bool(tree),
mmaplargeindex=True,
upperboundcomp=MAXCOMPRESSION,
manifest: align some vfs option access on the fact we might not have options...
r52659 persistentnodemap=persistentnodemap,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350
self.index = self._revlog.index
Durham Goode
manifest: move revlog specific options from manifest to manifestrevlog...
r29940
revlog: add a `get_revlog` method...
r51530 def get_revlog(self):
"""return an actual revlog instance if any
This exist because a lot of code leverage the fact the underlying
storage is a revlog for optimization, so giving simple way to access
the revlog instance helps such code.
"""
return self._revlog
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 def _setupmanifestcachehooks(self, repo):
"""Persist the manifestfulltextcache on lock release"""
safehasattr: drop usage in favor of hasattr...
r51821 if not hasattr(repo, '_wlockref'):
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 return
manifestcache: use `wcache` directory for manifest cache...
r42131 self._fulltextcache._opener = repo.wcachevfs
manifestcache: protect write with `wlock` instead of `lock`...
r42130 if repo._currentlock(repo._wlockref) is None:
manifestcache: skip setup earlier if we don't have the lock...
r42127 return
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 reporef = weakref.ref(repo)
manifestrevlogref = weakref.ref(self)
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 def persistmanifestcache(success):
# Repo is in an unknown state, do not persist.
if not success:
return
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 repo = reporef()
self = manifestrevlogref()
if repo is None or self is None:
return
Gregory Szorc
manifest: use public API for obtaining storage object...
r39356 if repo.manifestlog.getstorage(b'') is not self:
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 # there's a different manifest in play now, abort
return
self._fulltextcache.write()
manifestcache: skip setup earlier if we don't have the lock...
r42127 repo._afterlock(persistmanifestcache)
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803
Durham Goode
manifest: make manifest derive from manifestrevlog...
r29824 @property
def fulltextcache(self):
return self._fulltextcache
Matt Harbison
revlog: make `clearcaches()` signature consistent with ManifestRevlog...
r52765 def clearcaches(self, clear_persisted_data: bool = False) -> None:
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350 self._revlog.clearcaches()
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 self._fulltextcache.clear(clear_persisted_data=clear_persisted_data)
Gregory Szorc
manifest: make tree a public attribute...
r39351 self._dirlogcache = {self.tree: self}
Durham Goode
manifest: move dirlog up to manifestrevlog...
r29941
Augie Fackler
manifest: clean up dirlog() to take a d parameter to avoid shadowing dir()...
r36112 def dirlog(self, d):
if d:
Durham Goode
manifest: move dirlog up to manifestrevlog...
r29941 assert self._treeondisk
Augie Fackler
manifest: clean up dirlog() to take a d parameter to avoid shadowing dir()...
r36112 if d not in self._dirlogcache:
Augie Fackler
formatting: blacken the codebase...
r43346 mfrevlog = manifestrevlog(
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self.nodeconstants,
self.opener,
d,
self._dirlogcache,
treemanifest=self._treeondisk,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
manifest: clean up dirlog() to take a d parameter to avoid shadowing dir()...
r36112 self._dirlogcache[d] = mfrevlog
return self._dirlogcache[d]
Durham Goode
manifest: make manifest derive from manifestrevlog...
r29824
Augie Fackler
formatting: blacken the codebase...
r43346 def add(
self,
m,
transaction,
link,
p1,
p2,
manifest: add many type annotations to the manifest module...
r52667 added: Iterable[bytes],
removed: Iterable[bytes],
Augie Fackler
formatting: blacken the codebase...
r43346 readtree=None,
match=None,
):
commitctx: document the manifest writing function...
r45626 """add some manifest entry in to the manifest log
input:
m: the manifest dict we want to store
transaction: the open transaction
p1: manifest-node of p1
p2: manifest-node of p2
added: file added/changed compared to parent
removed: file removed compared to parent
tree manifest input:
readtree: a function to read a subtree
match: a filematcher for the subpart of the tree manifest
"""
Augie Fackler
manifest: introduce new exception to signal unavailability of fastdelta()...
r45154 try:
if p1 not in self.fulltextcache:
raise FastdeltaUnavailable()
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 # If our first parent is in the manifest cache, we can
# compute a delta here using properties we know about the
# manifest up-front, which may save time later for the
# revlog layer.
_checkforbidden(added)
# combine the changed lists into one sorted iterator
Augie Fackler
formatting: blacken the codebase...
r43346 work = heapq.merge(
[(x, False) for x in sorted(added)],
[(x, True) for x in sorted(removed)],
)
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961
arraytext, deltatext = m.fastdelta(self.fulltextcache[p1], work)
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350 cachedelta = self._revlog.rev(p1), deltatext
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 text = util.buffer(arraytext)
Joerg Sonnenberger
revlog: change addrevision to return the new revision, not node...
r47258 rev = self._revlog.addrevision(
Augie Fackler
formatting: blacken the codebase...
r43346 text, transaction, link, p1, p2, cachedelta
)
Joerg Sonnenberger
revlog: change addrevision to return the new revision, not node...
r47258 n = self._revlog.node(rev)
Augie Fackler
manifest: introduce new exception to signal unavailability of fastdelta()...
r45154 except FastdeltaUnavailable:
# The first parent manifest isn't already loaded or the
# manifest implementation doesn't support fastdelta, so
# we'll just encode a fulltext of the manifest and pass
# that through to the revlog layer, and let it handle the
# delta process.
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 if self._treeondisk:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert readtree, b"readtree must be set for treemanifest writes"
assert match, b"match must be specified for treemanifest writes"
Gregory Szorc
manifest: make tree a public attribute...
r39351 m1 = readtree(self.tree, p1)
m2 = readtree(self.tree, p2)
Augie Fackler
formatting: blacken the codebase...
r43346 n = self._addtree(
m, transaction, link, m1, m2, readtree, match=match
)
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 arraytext = None
else:
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 text = m.text()
Joerg Sonnenberger
revlog: change addrevision to return the new revision, not node...
r47258 rev = self._revlog.addrevision(text, transaction, link, p1, p2)
n = self._revlog.node(rev)
Augie Fackler
py3: use bytearray() instead of array('c', ...) constructions...
r31346 arraytext = bytearray(text)
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961
Martin von Zweigbergk
manifest: don't store None in fulltextcache...
r30209 if arraytext is not None:
self.fulltextcache[n] = arraytext
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961
return n
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 def _addtree(self, m, transaction, link, m1, m2, readtree, match):
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 # If the manifest is unchanged compared to one parent,
# don't write a new revision
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.tree != b'' and (
m.unmodifiedsince(m1) or m.unmodifiedsince(m2)
):
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 return m.node()
Augie Fackler
formatting: blacken the codebase...
r43346
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 def writesubtree(subm, subp1, subp2, match):
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 sublog = self.dirlog(subm.dir())
Augie Fackler
formatting: blacken the codebase...
r43346 sublog.add(
subm,
transaction,
link,
subp1,
subp2,
None,
None,
readtree=readtree,
match=match,
)
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 m.writesubtrees(m1, m2, writesubtree, match)
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 text = m.dirtext()
Durham Goode
treemanifest: make node reuse match flat manifest behavior...
r31294 n = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.tree != b'':
Durham Goode
treemanifest: make node reuse match flat manifest behavior...
r31294 # Double-check whether contents are unchanged to one parent
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 if text == m1.dirtext():
Durham Goode
treemanifest: make node reuse match flat manifest behavior...
r31294 n = m1.node()
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 elif text == m2.dirtext():
Durham Goode
treemanifest: make node reuse match flat manifest behavior...
r31294 n = m2.node()
if not n:
Joerg Sonnenberger
revlog: change addrevision to return the new revision, not node...
r47258 rev = self._revlog.addrevision(
Augie Fackler
formatting: blacken the codebase...
r43346 text, transaction, link, m1.node(), m2.node()
)
Joerg Sonnenberger
revlog: change addrevision to return the new revision, not node...
r47258 n = self._revlog.node(rev)
Durham Goode
treemanifest: make node reuse match flat manifest behavior...
r31294
Durham Goode
manifest: move manifest.add onto manifestrevlog...
r29961 # Save nodeid so parent manifest can calculate its nodeid
m.setnode(n)
return n
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350 def __len__(self):
return len(self._revlog)
def __iter__(self):
return self._revlog.__iter__()
def rev(self, node):
return self._revlog.rev(node)
def node(self, rev):
return self._revlog.node(rev)
def lookup(self, value):
return self._revlog.lookup(value)
def parentrevs(self, rev):
return self._revlog.parentrevs(rev)
def parents(self, node):
return self._revlog.parents(node)
def linkrev(self, rev):
return self._revlog.linkrev(rev)
def checksize(self):
return self._revlog.checksize()
revlog: drop the df argument to `revision`...
r51915 def revision(self, node):
return self._revlog.revision(node)
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350
revlog: drop the df argument to `rawdata`...
r51916 def rawdata(self, node):
return self._revlog.rawdata(node)
rawdata: forward `rawdata` call on `manifestlog`...
r42949
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350 def revdiff(self, rev1, rev2):
return self._revlog.revdiff(rev1, rev2)
def cmp(self, node, text):
return self._revlog.cmp(node, text)
def deltaparent(self, rev):
return self._revlog.deltaparent(rev)
Augie Fackler
formatting: blacken the codebase...
r43346 def emitrevisions(
self,
nodes,
nodesorder=None,
revisiondata=False,
assumehaveparentrevisions=False,
deltamode=repository.CG_DELTAMODE_STD,
Raphaël Gomès
changegroupv4: add sidedata helpers...
r47449 sidedata_helpers=None,
debug: add an option to display statistic about a bundling operation...
r50505 debug_info=None,
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Gregory Szorc
revlog: new API to emit revision data...
r39898 return self._revlog.emitrevisions(
Augie Fackler
formatting: blacken the codebase...
r43346 nodes,
nodesorder=nodesorder,
revisiondata=revisiondata,
Gregory Szorc
revlog: new API to emit revision data...
r39898 assumehaveparentrevisions=assumehaveparentrevisions,
Augie Fackler
formatting: blacken the codebase...
r43346 deltamode=deltamode,
Raphaël Gomès
changegroupv4: add sidedata helpers...
r47449 sidedata_helpers=sidedata_helpers,
debug: add an option to display statistic about a bundling operation...
r50505 debug_info=debug_info,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
revlog: new API to emit revision data...
r39898
Joerg Sonnenberger
revlog: extend addgroup() with callback for duplicates...
r46373 def addgroup(
self,
deltas,
linkmapper,
transaction,
Joerg Sonnenberger
revlog: decouple caching from addrevision callback for addgroup...
r47085 alwayscache=False,
Joerg Sonnenberger
revlog: extend addgroup() with callback for duplicates...
r46373 addrevisioncb=None,
duplicaterevisioncb=None,
debug: add an option to display statistic about a unbundling operation...
r50506 debug_info=None,
changegroup: add `delta_base_reuse_policy` argument...
r50660 delta_base_reuse_policy=None,
Joerg Sonnenberger
revlog: extend addgroup() with callback for duplicates...
r46373 ):
Augie Fackler
formatting: blacken the codebase...
r43346 return self._revlog.addgroup(
Joerg Sonnenberger
revlog: extend addgroup() with callback for duplicates...
r46373 deltas,
linkmapper,
transaction,
Joerg Sonnenberger
revlog: decouple caching from addrevision callback for addgroup...
r47085 alwayscache=alwayscache,
Joerg Sonnenberger
revlog: extend addgroup() with callback for duplicates...
r46373 addrevisioncb=addrevisioncb,
duplicaterevisioncb=duplicaterevisioncb,
debug: add an option to display statistic about a unbundling operation...
r50506 debug_info=debug_info,
changegroup: add `delta_base_reuse_policy` argument...
r50660 delta_base_reuse_policy=delta_base_reuse_policy,
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350
Gregory Szorc
manifest: add rawsize() proxy (API)...
r39894 def rawsize(self, rev):
return self._revlog.rawsize(rev)
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350 def getstrippoint(self, minlink):
return self._revlog.getstrippoint(minlink)
def strip(self, minlink, transaction):
return self._revlog.strip(minlink, transaction)
def files(self):
return self._revlog.files()
def clone(self, tr, destrevlog, **kwargs):
if not isinstance(destrevlog, manifestrevlog):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ProgrammingError(b'expected manifestrevlog to clone()')
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350
return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
Augie Fackler
formatting: blacken the codebase...
r43346 def storageinfo(
self,
exclusivefiles=False,
sharedfiles=False,
revisionscount=False,
trackedsize=False,
storedsize=False,
):
Gregory Szorc
revlog: add method for obtaining storage info (API)...
r39905 return self._revlog.storageinfo(
Augie Fackler
formatting: blacken the codebase...
r43346 exclusivefiles=exclusivefiles,
sharedfiles=sharedfiles,
revisionscount=revisionscount,
trackedsize=trackedsize,
storedsize=storedsize,
)
Gregory Szorc
revlog: add method for obtaining storage info (API)...
r39905
Gregory Szorc
manifest: proxy to revlog instance instead of inheriting...
r39350 @property
def opener(self):
return self._revlog.opener
@opener.setter
def opener(self, value):
self._revlog.opener = value
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifestctx`...
r52967 # TODO: drop this in favor of repository.imanifestrevisionstored?
AnyManifestCtx = Union['manifestctx', 'treemanifestctx']
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 # TODO: drop this in favor of repository.imanifestdict
AnyManifestDict = Union[manifestdict, treemanifest]
manifest: add many type annotations to the manifest module...
r52667
Matt Harbison
manifest: subclass the new `repository.imanifestlog` Protocol class...
r53381 class manifestlog(repository.imanifestlog):
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 """A collection class representing the collection of manifest snapshots
referenced by commits in the repository.
In this situation, 'manifest' refers to the abstract concept of a snapshot
of the list of files in the given commit. Consumers of the output of this
class do not care about the implementation details of the actual manifests
they receive (i.e. tree or flat or lazily loaded, etc)."""
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
manifest: accept narrowmatch into constructor instead of getting from repo...
r41067 def __init__(self, opener, repo, rootstore, narrowmatch):
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self.nodeconstants = repo.nodeconstants
Durham Goode
manifest: move treeinmem onto manifestlog...
r29959 usetreemanifest = False
Durham Goode
manifest: make manifestlog use it's own cache...
r30372 cachesize = 4
Durham Goode
manifest: move treeinmem onto manifestlog...
r29959
opts = getattr(opener, 'options', None)
if opts is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 usetreemanifest = opts.get(b'treemanifest', usetreemanifest)
cachesize = opts.get(b'manifestcachesize', cachesize)
Gregory Szorc
manifest: rename manifestlog._treeinmem to ._treemanifests...
r39281
self._treemanifests = usetreemanifest
Durham Goode
manifest: move treeinmem onto manifestlog...
r29959
Gregory Szorc
localrepo: pass root manifest into manifestlog.__init__...
r39799 self._rootstore = rootstore
Gregory Szorc
manifest: rename manifestlog._revlog to _rootstore...
r39357 self._rootstore._setupmanifestcachehooks(repo)
Martin von Zweigbergk
manifest: accept narrowmatch into constructor instead of getting from repo...
r41067 self._narrowmatch = narrowmatch
Durham Goode
manifest: make manifestlog a storecache...
r30219
Durham Goode
manifest: change manifestlog mancache to be directory based...
r30292 # A cache of the manifestctx or treemanifestctx for each directory
self._dirmancache = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._dirmancache[b''] = util.lrucachedict(cachesize)
Durham Goode
manifest: change manifestlog mancache to be directory based...
r30292
Gregory Szorc
manifest: make cachesize a private attribute...
r38529 self._cachesize = cachesize
Durham Goode
manifest: use property instead of field for manifest revlog storage...
r29826
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 def __getitem__(self, node):
Durham Goode
manifest: throw LookupError if node not in revlog...
r30290 """Retrieves the manifest instance for the given node. Throws a
LookupError if not found.
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self.get(b'', node)
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825
manifest: add a read_delta_new_entries method...
r52678 @property
def narrowed(self):
return not (self._narrowmatch is None or self._narrowmatch.always())
manifest: add many type annotations to the manifest module...
r52667 def get(
self, tree: bytes, node: bytes, verify: bool = True
) -> AnyManifestCtx:
Durham Goode
manifest: add manifestlog.get to obtain subdirectory instances...
r30291 """Retrieves the manifest instance for the given node. Throws a
LookupError if not found.
Durham Goode
manifest: make revlog verification optional...
r30403
`verify` - if True an exception will be thrown if the node is not in
the revlog
Durham Goode
manifest: add manifestlog.get to obtain subdirectory instances...
r30291 """
Gregory Szorc
manifest: rename dir to tree to avoid shadowing built-in...
r39271 if node in self._dirmancache.get(tree, ()):
return self._dirmancache[tree][node]
Durham Goode
manifest: change manifestlog mancache to be directory based...
r30292
Martin von Zweigbergk
narrow: move manifestlog overrides to core...
r37392 if not self._narrowmatch.always():
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 if not self._narrowmatch.visitdir(tree[:-1]):
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 return excludeddirmanifestctx(self.nodeconstants, tree, node)
Gregory Szorc
manifest: rename dir to tree to avoid shadowing built-in...
r39271 if tree:
Gregory Szorc
manifest: rename manifestlog._revlog to _rootstore...
r39357 if self._rootstore._treeondisk:
Durham Goode
manifest: make revlog verification optional...
r30403 if verify:
Gregory Szorc
manifest: use rev() instead of nodemap.__contains__...
r39282 # Side-effect is LookupError is raised if node doesn't
# exist.
self.getstorage(tree).rev(node)
Gregory Szorc
manifest: rename dir to tree to avoid shadowing built-in...
r39271 m = treemanifestctx(self, tree, node)
Durham Goode
manifest: add manifestlog.get to obtain subdirectory instances...
r30291 else:
raise error.Abort(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"cannot ask for manifest directory '%s' in a flat "
b"manifest"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% tree
)
Durham Goode
manifest: add treemanifestctx class...
r29907 else:
Durham Goode
manifest: make revlog verification optional...
r30403 if verify:
Gregory Szorc
manifest: use rev() instead of nodemap.__contains__...
r39282 # Side-effect is LookupError is raised if node doesn't exist.
Gregory Szorc
manifest: rename manifestlog._revlog to _rootstore...
r39357 self._rootstore.rev(node)
Gregory Szorc
manifest: use rev() instead of nodemap.__contains__...
r39282
Gregory Szorc
manifest: rename manifestlog._treeinmem to ._treemanifests...
r39281 if self._treemanifests:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 m = treemanifestctx(self, b'', node)
Durham Goode
manifest: add manifestlog.get to obtain subdirectory instances...
r30291 else:
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 m = manifestctx(self, node)
Durham Goode
manifest: change manifestlog mancache to be directory based...
r30292
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if node != self.nodeconstants.nullid:
Gregory Szorc
manifest: rename dir to tree to avoid shadowing built-in...
r39271 mancache = self._dirmancache.get(tree)
Durham Goode
manifest: change manifestlog mancache to be directory based...
r30292 if not mancache:
Gregory Szorc
manifest: make cachesize a private attribute...
r38529 mancache = util.lrucachedict(self._cachesize)
Gregory Szorc
manifest: rename dir to tree to avoid shadowing built-in...
r39271 self._dirmancache[tree] = mancache
Durham Goode
manifest: change manifestlog mancache to be directory based...
r30292 mancache[node] = m
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 return m
Gregory Szorc
manifest: add getstorage() to manifestlog and use it globally...
r39280 def getstorage(self, tree):
Gregory Szorc
manifest: rename manifestlog._revlog to _rootstore...
r39357 return self._rootstore.dirlog(tree)
Gregory Szorc
manifest: add getstorage() to manifestlog and use it globally...
r39280
manifest: add many type annotations to the manifest module...
r52667 def clearcaches(self, clear_persisted_data: bool = False) -> None:
Durham Goode
manifest: move clearcaches to manifestlog...
r30370 self._dirmancache.clear()
Gregory Szorc
manifest: rename manifestlog._revlog to _rootstore...
r39357 self._rootstore.clearcaches(clear_persisted_data=clear_persisted_data)
Durham Goode
manifest: move clearcaches to manifestlog...
r30370
manifest: add many type annotations to the manifest module...
r52667 def rev(self, node) -> int:
Gregory Szorc
manifest: rename manifestlog._revlog to _rootstore...
r39357 return self._rootstore.rev(node)
Gregory Szorc
manifest: define and implement rev() on manifestlog...
r38573
manifest: add many type annotations to the manifest module...
r52667 def update_caches(self, transaction) -> None:
nodemap: also warm manifest nodemap with other caches...
r45291 return self._rootstore._revlog.update_caches(transaction=transaction)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
manifest: drop the CamelCase name for `manifest.memmanifestctx`...
r52964 class memmanifestctx: # (repository.imanifestrevisionwritable)
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 _manifestdict: manifestdict
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 def __init__(self, manifestlog):
self._manifestlog = manifestlog
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 self._manifestdict = manifestdict(manifestlog.nodeconstants.nodelen)
Durham Goode
manifest: introduce memmanifestctx and memtreemanifestctx...
r30342
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestrevlog`...
r52962 def _storage(self) -> manifestrevlog:
Gregory Szorc
manifest: use public API for obtaining storage object...
r39356 return self._manifestlog.getstorage(b'')
Durham Goode
manifest: remove manifest.add and add memmfctx.write...
r30345
Matt Harbison
manifest: drop the CamelCase name for `manifest.memmanifestctx`...
r52964 def copy(self) -> 'memmanifestctx':
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 memmf = memmanifestctx(self._manifestlog)
Durham Goode
manifest: add copy to mfctx classes...
r30343 memmf._manifestdict = self.read().copy()
return memmf
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def read(self) -> 'manifestdict':
Durham Goode
manifest: introduce memmanifestctx and memtreemanifestctx...
r30342 return self._manifestdict
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 def write(self, transaction, link, p1, p2, added, removed, match=None):
Augie Fackler
formatting: blacken the codebase...
r43346 return self._storage().add(
self._manifestdict,
transaction,
link,
p1,
p2,
added,
removed,
match=match,
)
Durham Goode
manifest: remove manifest.add and add memmfctx.write...
r30345
Matt Harbison
manifest: subclass the new `repository.imanifestrevisionstored` Protocol class...
r53374 class manifestctx(repository.imanifestrevisionstored):
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 """A class representing a single revision of a manifest, including its
contents, its parent revs, and its linkrev.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 _data: Optional[manifestdict]
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 def __init__(self, manifestlog, node):
self._manifestlog = manifestlog
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 self._data = None
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825
self._node = node
Durham Goode
manifest: add treemanifestctx class...
r29907
# TODO: We eventually want p1, p2, and linkrev exposed on this class,
# but let's add it later when something needs it and we can load it
# lazily.
Augie Fackler
formatting: blacken the codebase...
r43346 # self.p1, self.p2 = store.parents(node)
# rev = store.rev(node)
# self.linkrev = store.linkrev(rev)
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestrevlog`...
r52962 def _storage(self) -> 'manifestrevlog':
Gregory Szorc
manifest: use public API for obtaining storage object...
r39356 return self._manifestlog.getstorage(b'')
Durham Goode
manifestctx: add _revlog() function...
r30341
manifest: add many type annotations to the manifest module...
r52667 def node(self) -> bytes:
Durham Goode
manifest: introduce manifestlog and manifestctx classes...
r29825 return self._node
Matt Harbison
manifest: drop the CamelCase name for `manifest.memmanifestctx`...
r52964 def copy(self) -> memmanifestctx:
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 memmf = memmanifestctx(self._manifestlog)
Durham Goode
manifest: add copy to mfctx classes...
r30343 memmf._manifestdict = self.read().copy()
return memmf
Mateusz Kwapich
manifest: expose the parents() method
r30565 @propertycache
manifest: add many type annotations to the manifest module...
r52667 def parents(self) -> Tuple[bytes, bytes]:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 return self._storage().parents(self._node)
Mateusz Kwapich
manifest: expose the parents() method
r30565
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def read(self) -> 'manifestdict':
Durham Goode
manifest: check 'if x is None' instead of 'if not x'...
r31097 if self._data is None:
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 nc = self._manifestlog.nodeconstants
if self._node == nc.nullid:
self._data = manifestdict(nc.nodelen)
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 else:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store = self._storage()
Gregory Szorc
manifest: use fulltextcache instead of _fulltextcache...
r39358 if self._node in store.fulltextcache:
text = pycompat.bytestr(store.fulltextcache[self._node])
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 else:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 text = store.revision(self._node)
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 arraytext = bytearray(text)
Gregory Szorc
manifest: use fulltextcache instead of _fulltextcache...
r39358 store.fulltextcache[self._node] = arraytext
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 self._data = manifestdict(nc.nodelen, text)
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 return self._data
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def readfast(self, shallow: bool = False) -> 'manifestdict':
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Calls either readdelta or read, based on which would be less work.
Durham Goode
manifest: get rid of manifest.readshallowfast...
r30294 readdelta is called if the delta is against the p1, and therefore can be
read quickly.
If `shallow` is True, nothing changes since this is a flat manifest.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
manifest: deprecated readdelta and readfast...
r52681 util.nouideprecwarn(
b'"readfast" is deprecated use "read_any_fast_delta" or "read_delta_parents"',
b"6.9",
stacklevel=2,
)
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store = self._storage()
r = store.rev(self._node)
deltaparent = store.deltaparent(r)
if deltaparent != nullrev and deltaparent in store.parentrevs(r):
Durham Goode
manifest: adds manifestctx.readfast...
r29939 return self.readdelta()
return self.read()
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def readdelta(self, shallow: bool = False) -> 'manifestdict':
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Returns a manifest containing just the entries that are present
Durham Goode
manifest: remove manifest.readshallowdelta...
r30295 in this manifest, but not in its p1 manifest. This is efficient to read
if the revlog delta is already p1.
Changing the value of `shallow` has no effect on flat manifests.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
manifest: deprecated readdelta and readfast...
r52681 util.nouideprecwarn(
b'"readfast" is deprecated use "read_any_fast_delta" or "read_delta_new_entries"',
b"6.9",
stacklevel=2,
)
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store = self._storage()
r = store.rev(self._node)
d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 return manifestdict(store.nodeconstants.nodelen, d)
Durham Goode
manifest: add manifestctx.readdelta()...
r29938
manifest: introduce a `read_any_fast_delta` method...
r52668 def read_any_fast_delta(
self,
manifest: allow skipping valid_bases argument to `read_any_fast_delta`...
r52669 valid_bases: Optional[Collection[int]] = None,
manifest: introduce a `read_any_fast_delta` method...
r52668 *,
shallow: bool = False,
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 ) -> Tuple[Optional[int], manifestdict]:
manifest: introduce a `read_any_fast_delta` method...
r52668 """see `imanifestrevisionstored` documentation"""
store = self._storage()
r = store.rev(self._node)
deltaparent = store.deltaparent(r)
manifest: allow skipping valid_bases argument to `read_any_fast_delta`...
r52669 if valid_bases is None:
# make sure the next check is True
valid_bases = (deltaparent,)
manifest: introduce a `read_any_fast_delta` method...
r52668 if deltaparent != nullrev and deltaparent in valid_bases:
d = mdiff.patchtext(store.revdiff(deltaparent, r))
return (
deltaparent,
manifestdict(store.nodeconstants.nodelen, d),
)
return (None, self.read())
manifest: introduce a `read_delta_parents` method...
r52674 def read_delta_parents(
self,
*,
shallow: bool = False,
exact: bool = True,
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 ) -> manifestdict:
manifest: introduce a `read_delta_parents` method...
r52674 """see `interface.imanifestrevisionbase` documentations"""
store = self._storage()
r = store.rev(self._node)
deltaparent = store.deltaparent(r)
parents = [p for p in store.parentrevs(r) if p is not nullrev]
if not exact and deltaparent in parents:
d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
return manifestdict(store.nodeconstants.nodelen, d)
elif not exact or len(parents) == 0:
return self.read()
elif len(parents) == 1:
p = parents[0]
d = mdiff.patchtext(store.revdiff(p, r))
return manifestdict(store.nodeconstants.nodelen, d)
else:
p1, p2 = parents
d1 = mdiff.patchtext(store.revdiff(p1, r))
d2 = mdiff.patchtext(store.revdiff(p2, r))
d1 = manifestdict(store.nodeconstants.nodelen, d1)
d2 = manifestdict(store.nodeconstants.nodelen, d2)
md = manifestdict(store.nodeconstants.nodelen)
for f, new_node, new_flag in d1.iterentries():
if f not in d2:
continue
if new_node is not None:
md.set(f, new_node, new_flag)
return md
Matt Harbison
typing: (mostly) align the signatures of `imanifestrevisionstored` overrides...
r53371 def read_delta_new_entries(self, *, shallow: bool = False) -> manifestdict:
manifest: add a read_delta_new_entries method...
r52678 """see `interface.imanifestrevisionbase` documentations"""
# If we are using narrow, returning a delta against an arbitrary
# changeset might return file outside the narrowspec. This can create
# issue when running validation server side with strict security as
# push from low priviledge usage might be seen as adding new revision
# for files they cannot touch. So we are strict if narrow is involved.
if self._manifestlog.narrowed:
return self.read_delta_parents(shallow=shallow, exact=True)
store = self._storage()
r = store.rev(self._node)
d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
return manifestdict(store.nodeconstants.nodelen, d)
manifest: add many type annotations to the manifest module...
r52667 def find(self, key: bytes) -> Tuple[bytes, bytes]:
Durham Goode
manifest: remove manifest.find...
r30340 return self.read().find(key)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
manifest: subclass the new `imanifestrevisionwritable` Protocol class...
r53378 class memtreemanifestctx(repository.imanifestrevisionwritable):
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 _treemanifest: treemanifest
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def __init__(self, manifestlog, dir=b''):
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 self._manifestlog = manifestlog
Durham Goode
manifest: introduce memmanifestctx and memtreemanifestctx...
r30342 self._dir = dir
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self._treemanifest = treemanifest(manifestlog.nodeconstants)
Durham Goode
manifest: introduce memmanifestctx and memtreemanifestctx...
r30342
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestrevlog`...
r52962 def _storage(self) -> manifestrevlog:
Gregory Szorc
manifest: use public API for obtaining storage object...
r39356 return self._manifestlog.getstorage(b'')
Durham Goode
manifest: remove manifest.add and add memmfctx.write...
r30345
Matt Harbison
manifest: drop the CamelCase name for `manifest.memtreemanifestctx`...
r52966 def copy(self) -> 'memtreemanifestctx':
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 memmf = memtreemanifestctx(self._manifestlog, dir=self._dir)
Durham Goode
manifest: add copy to mfctx classes...
r30343 memmf._treemanifest = self._treemanifest.copy()
return memmf
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def read(self) -> 'treemanifest':
Durham Goode
manifest: introduce memmanifestctx and memtreemanifestctx...
r30342 return self._treemanifest
spectral
narrow: when writing treemanifests, skip inspecting directories outside narrow...
r39704 def write(self, transaction, link, p1, p2, added, removed, match=None):
Durham Goode
manifest: remove dependency on manifestrevlog being able to create trees...
r30368 def readtree(dir, node):
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 return self._manifestlog.get(dir, node).read()
Augie Fackler
formatting: blacken the codebase...
r43346
return self._storage().add(
self._treemanifest,
transaction,
link,
p1,
p2,
added,
removed,
readtree=readtree,
match=match,
)
Durham Goode
manifest: remove manifest.add and add memmfctx.write...
r30345
Matt Harbison
manifest: subclass the new `repository.imanifestrevisionstored` Protocol class...
r53374 class treemanifestctx(repository.imanifestrevisionstored):
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 _data: Optional[treemanifest]
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 def __init__(self, manifestlog, dir, node):
self._manifestlog = manifestlog
Durham Goode
manifest: add treemanifestctx class...
r29907 self._dir = dir
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 self._data = None
Durham Goode
manifest: add treemanifestctx class...
r29907
self._node = node
# TODO: Load p1/p2/linkrev lazily. They need to be lazily loaded so that
# we can instantiate treemanifestctx objects for directories we don't
# have on disk.
Augie Fackler
formatting: blacken the codebase...
r43346 # self.p1, self.p2 = store.parents(node)
# rev = store.rev(node)
# self.linkrev = store.linkrev(rev)
Durham Goode
manifest: add treemanifestctx class...
r29907
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestrevlog`...
r52962 def _storage(self) -> manifestrevlog:
Martin von Zweigbergk
narrow: move manifestrevlog overrides to core...
r37391 narrowmatch = self._manifestlog._narrowmatch
if not narrowmatch.always():
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 if not narrowmatch.visitdir(self._dir[:-1]):
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 return excludedmanifestrevlog(
self._manifestlog.nodeconstants, self._dir
)
Gregory Szorc
manifest: add getstorage() to manifestlog and use it globally...
r39280 return self._manifestlog.getstorage(self._dir)
Durham Goode
manifest: make treemanifestctx store the repo...
r30221
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def read(self) -> 'treemanifest':
Durham Goode
manifest: check 'if x is None' instead of 'if not x'...
r31097 if self._data is None:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store = self._storage()
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if self._node == self._manifestlog.nodeconstants.nullid:
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self._data = treemanifest(self._manifestlog.nodeconstants)
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 # TODO accessing non-public API
elif store._treeondisk:
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 m = treemanifest(self._manifestlog.nodeconstants, dir=self._dir)
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 def gettext():
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 return store.revision(self._node)
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 def readsubtree(dir, subm):
Durham Goode
manifest: change treemanifestctx to construct subtrees from the manifestlog...
r30404 # Set verify to False since we need to be able to create
# subtrees for trees that don't exist on disk.
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 return self._manifestlog.get(dir, subm, verify=False).read()
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926 m.read(gettext, readsubtree)
m.setnode(self._node)
self._data = m
else:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 if self._node in store.fulltextcache:
text = pycompat.bytestr(store.fulltextcache[self._node])
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 else:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 text = store.revision(self._node)
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 arraytext = bytearray(text)
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store.fulltextcache[self._node] = arraytext
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self._data = treemanifest(
self._manifestlog.nodeconstants, dir=self._dir, text=text
)
Durham Goode
manifest: change manifestctx to not inherit from manifestdict...
r29926
return self._data
Durham Goode
manifest: add treemanifestctx class...
r29907
manifest: add many type annotations to the manifest module...
r52667 def node(self) -> bytes:
Durham Goode
manifest: add treemanifestctx class...
r29907 return self._node
Matt Harbison
manifest: drop the CamelCase name for `manifest.memtreemanifestctx`...
r52966 def copy(self) -> 'memtreemanifestctx':
Durham Goode
manifest: remove _repo from manifestctx objects...
r31153 memmf = memtreemanifestctx(self._manifestlog, dir=self._dir)
Durham Goode
manifest: add copy to mfctx classes...
r30343 memmf._treemanifest = self.read().copy()
return memmf
Mateusz Kwapich
manifest: expose the parents() method
r30565 @propertycache
manifest: add many type annotations to the manifest module...
r52667 def parents(self) -> Tuple[bytes, bytes]:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 return self._storage().parents(self._node)
Mateusz Kwapich
manifest: expose the parents() method
r30565
manifest: add many type annotations to the manifest module...
r52667 def readdelta(self, shallow: bool = False) -> AnyManifestDict:
manifest: introduce a `read_any_fast_delta` method...
r52668 """see `imanifestrevisionstored` documentation"""
manifest: deprecated readdelta and readfast...
r52681 util.nouideprecwarn(
b'"readdelta" is deprecated use "read_any_fast_delta" or "read_delta_new_entries"',
b"6.9",
stacklevel=2,
)
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store = self._storage()
Augie Fackler
cleanup: say goodbye to manifestv2 format...
r36391 if shallow:
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 r = store.rev(self._node)
d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 return manifestdict(store.nodeconstants.nodelen, d)
Durham Goode
manifest: add shallow option to treemanifestctx.readdelta and readfast...
r30293 else:
# Need to perform a slow delta
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 r0 = store.deltaparent(store.rev(self._node))
m0 = self._manifestlog.get(self._dir, store.node(r0)).read()
Durham Goode
manifest: add shallow option to treemanifestctx.readdelta and readfast...
r30293 m1 = self.read()
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 md = treemanifest(self._manifestlog.nodeconstants, dir=self._dir)
Gregory Szorc
manifest: remove pycompat.iteritems()...
r49781 for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).items():
Durham Goode
manifest: add shallow option to treemanifestctx.readdelta and readfast...
r30293 if n1:
md[f] = n1
if fl1:
md.setflag(f, fl1)
return md
Durham Goode
manifest: add manifestctx.readdelta()...
r29938
manifest: introduce a `read_any_fast_delta` method...
r52668 def read_any_fast_delta(
self,
manifest: allow skipping valid_bases argument to `read_any_fast_delta`...
r52669 valid_bases: Optional[Collection[int]] = None,
manifest: introduce a `read_any_fast_delta` method...
r52668 *,
shallow: bool = False,
) -> Tuple[Optional[int], AnyManifestDict]:
"""see `imanifestrevisionstored` documentation"""
store = self._storage()
r = store.rev(self._node)
deltaparent = store.deltaparent(r)
manifest: allow skipping valid_bases argument to `read_any_fast_delta`...
r52669 if valid_bases is None:
# make sure the next check is True
valid_bases = (deltaparent,)
manifest: introduce a `read_any_fast_delta` method...
r52668 can_use_delta = deltaparent != nullrev and deltaparent in valid_bases
if shallow:
if can_use_delta:
return (deltaparent, self._read_storage_delta_shallow())
else:
d = store.revision(self._node)
return (None, manifestdict(store.nodeconstants.nodelen, d))
else:
# note: This use "slow_delta" here is cargo culted from the previous
# implementation. I am not sure it make sense since the goal here is to
# be fast, so why are we computing a delta? On the other hand, tree
# manifest delta as fairly "cheap" and allow for skipping whole part of
# the tree that a full read would access. So it might be a good idea.
#
# If we realize we don't need delta here, we should simply use:
#
# return (None, self.read())
if can_use_delta:
return (None, self._read_storage_slow_delta(base=deltaparent))
else:
parents = [
p
for p in store.parentrevs(r)
if p is not nullrev and p in valid_bases
]
if parents:
best_base = max(parents)
else:
best_base = max(valid_bases)
return (None, self._read_storage_slow_delta(base=best_base))
Matt Harbison
manifest: drop the CamelCase name for `manifest.manifestdict`...
r52960 def _read_storage_delta_shallow(self) -> manifestdict:
manifest: introduce a `read_any_fast_delta` method...
r52668 store = self._storage()
r = store.rev(self._node)
d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
return manifestdict(store.nodeconstants.nodelen, d)
Matt Harbison
manifest: drop the CamelCase name for `manifest.treemanifest`...
r52961 def _read_storage_slow_delta(self, base) -> 'treemanifest':
manifest: introduce a `read_any_fast_delta` method...
r52668 store = self._storage()
if base is None:
base = store.deltaparent(store.rev(self._node))
m0 = self._manifestlog.get(self._dir, store.node(base)).read()
m1 = self.read()
md = treemanifest(self._manifestlog.nodeconstants, dir=self._dir)
for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).items():
if n1:
md[f] = n1
if fl1:
md.setflag(f, fl1)
return md
manifest: introduce a `read_delta_parents` method...
r52674 def read_delta_parents(
self,
*,
shallow: bool = False,
exact: bool = True,
) -> AnyManifestDict:
"""see `interface.imanifestrevisionbase` documentations"""
store = self._storage()
r = store.rev(self._node)
parents = [p for p in store.parentrevs(r) if p is not nullrev]
if not exact:
return self.read_any_fast_delta(parents, shallow=shallow)[1]
elif len(parents) == 0:
if shallow:
d = store.revision(self._node)
return manifestdict(store.nodeconstants.nodelen, d)
else:
return self.read()
elif len(parents) == 1:
p = parents[0]
if shallow:
d = mdiff.patchtext(store.revdiff(p, r))
return manifestdict(store.nodeconstants.nodelen, d)
else:
return self._read_storage_slow_delta(base=p)
else:
p1, p2 = parents
if shallow:
d1 = mdiff.patchtext(store.revdiff(p1, r))
d2 = mdiff.patchtext(store.revdiff(p2, r))
d1 = manifestdict(store.nodeconstants.nodelen, d1)
d2 = manifestdict(store.nodeconstants.nodelen, d2)
md = manifestdict(store.nodeconstants.nodelen)
for f, new_node, new_flag in d1.iterentries():
if f not in d2:
continue
if new_node is not None:
md.set(f, new_node, new_flag)
return md
else:
m1 = self._manifestlog.get(self._dir, store.node(p1)).read()
m2 = self._manifestlog.get(self._dir, store.node(p2)).read()
mc = self.read()
d1 = m1.diff(mc)
d2 = m2.diff(mc)
md = treemanifest(
self._manifestlog.nodeconstants,
dir=self._dir,
)
for f, new_node, new_flag in d1.iterentries():
if f not in d2:
continue
if new_node is not None:
md.set(f, new_node, new_flag)
return md
manifest: add a read_delta_new_entries method...
r52678 def read_delta_new_entries(
self, *, shallow: bool = False
) -> AnyManifestDict:
"""see `interface.imanifestrevisionbase` documentations"""
# If we are using narrow, returning a delta against an arbitrary
# changeset might return file outside the narrowspec. This can create
# issue when running validation server side with strict security as
# push from low priviledge usage might be seen as adding new revision
# for files they cannot touch. So we are strict if narrow is involved.
if self._manifestlog.narrowed:
return self.read_delta_parents(shallow=shallow, exact=True)
# delegate to existing another existing method for simplicity
store = self._storage()
r = store.rev(self._node)
bases = (store.deltaparent(r),)
return self.read_any_fast_delta(bases, shallow=shallow)[1]
Matt Harbison
typing: (mostly) align the signatures of `imanifestrevisionstored` overrides...
r53371 def readfast(self, shallow: bool = False) -> AnyManifestDict:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Calls either readdelta or read, based on which would be less work.
Durham Goode
manifest: get rid of manifest.readshallowfast...
r30294 readdelta is called if the delta is against the p1, and therefore can be
read quickly.
If `shallow` is True, it only returns the entries from this manifest,
and not any submanifests.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
manifest: deprecated readdelta and readfast...
r52681 util.nouideprecwarn(
b'"readdelta" is deprecated use "read_any_fast_delta" or "read_delta_parents"',
b"6.9",
stacklevel=2,
)
Gregory Szorc
manifest: change terminology for storage in context classes...
r39353 store = self._storage()
r = store.rev(self._node)
deltaparent = store.deltaparent(r)
Augie Fackler
formatting: blacken the codebase...
r43346 if deltaparent != nullrev and deltaparent in store.parentrevs(r):
Durham Goode
manifest: add shallow option to treemanifestctx.readdelta and readfast...
r30293 return self.readdelta(shallow=shallow)
if shallow:
Joerg Sonnenberger
manifests: push down expected node length into the parser...
r47817 return manifestdict(
store.nodeconstants.nodelen, store.revision(self._node)
)
Durham Goode
manifest: add shallow option to treemanifestctx.readdelta and readfast...
r30293 else:
return self.read()
Durham Goode
manifest: adds manifestctx.readfast...
r29939
manifest: add many type annotations to the manifest module...
r52667 def find(self, key: bytes) -> Tuple[bytes, bytes]:
Durham Goode
manifest: remove manifest.find...
r30340 return self.read().find(key)
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390 class excludeddir(treemanifest):
"""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
formatting: blacken the codebase...
r43346
Matt Harbison
typing: lock in new pytype gains from making revlog related classes typeable...
r52719 _files: Dict[bytes, bytes]
_flags: Dict[bytes, bytes]
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 def __init__(self, nodeconstants, dir, node):
super(excludeddir, self).__init__(nodeconstants, dir)
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390 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/")
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._files[b''] = node
self._flags[b''] = b't'
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
# 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
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390 class excludeddirmanifestctx(treemanifestctx):
"""context wrapper for excludeddir - see that docstring for rationale"""
Augie Fackler
formatting: blacken the codebase...
r43346
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 def __init__(self, nodeconstants, dir, node):
self.nodeconstants = nodeconstants
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390 self._dir = dir
self._node = node
def read(self):
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 return excludeddir(self.nodeconstants, self._dir, self._node)
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
Matt Harbison
typing: (mostly) align the signatures of `imanifestrevisionstored` overrides...
r53371 def readfast(self, shallow: bool = False):
narrow: overwrite readfast in excludeddirmanifestctx...
r46864 # special version of readfast since we don't have underlying storage
return self.read()
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390 def write(self, *args):
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'attempt to write manifest from excluded dir %s' % self._dir
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
class excludedmanifestrevlog(manifestrevlog):
"""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.
"""
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 def __init__(self, nodeconstants, dir):
self.nodeconstants = nodeconstants
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390 self._dir = dir
def __len__(self):
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'attempt to get length of excluded dir %s' % self._dir
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
def rev(self, node):
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'attempt to get rev from excluded dir %s' % self._dir
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
def linkrev(self, node):
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'attempt to get linkrev from excluded dir %s' % self._dir
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
def node(self, rev):
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'attempt to get node from excluded dir %s' % self._dir
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
narrow: move excludeddir and related classes to core...
r37390
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