##// END OF EJS Templates
py3: catch specific OSError subclasses instead of checking errno...
py3: catch specific OSError subclasses instead of checking errno On Python 3, the "not a directory" error is mapped to ENOTDIR instead of EINVAL. Therefore, catching the NotADirectoryError subclass is sufficient.

File last commit:

r50010:4c75f00b default
r50206:defc369d default
Show More
parsers.py
974 lines | 31.4 KiB | text/x-python | PythonLexer
Martin Geisler
pure Python implementation of parsers.c
r7700 # parsers.py - Python implementation of parsers.c
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2009 Olivia Mackall <olivia@selenic.com> and others
Martin Geisler
pure Python implementation of parsers.c
r7700 #
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.
Martin Geisler
pure Python implementation of parsers.c
r7700
Gregory Szorc
parsers: use absolute_import
r27339
Gregory Szorc
py3: use io.BytesIO directly...
r49728 import io
Simon Sapin
dirstate-v2: initial Python parser...
r49035 import stat
Gregory Szorc
parsers: use absolute_import
r27339 import struct
import zlib
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 from ..node import (
nullrev,
sha1nodeconstants,
)
Augie Fackler
parsers: move DirstateItem to attr.s...
r48366 from ..thirdparty import attr
revlog: move the nodemap into the index object (for pure)...
r43925 from .. import (
revlogv2: store version information in the docket only...
r48009 error,
revlog: move `offset_type` to `revlogutils`...
r48186 revlogutils,
revlog: move the nodemap into the index object (for pure)...
r43925 util,
)
Augie Fackler
formatting: blacken the codebase...
r43346
revlogutils: move the NodeMap class in a dedicated nodemap module...
r44486 from ..revlogutils import nodemap as nodemaputil
revlog: move the details of revlog "v1" index inside revlog.utils.constants...
r47616 from ..revlogutils import constants as revlog_constants
revlogutils: move the NodeMap class in a dedicated nodemap module...
r44486
Gregory Szorc
py3: use io.BytesIO directly...
r49728 stringio = io.BytesIO
Martin Geisler
pure Python implementation of parsers.c
r7700
Pulkit Goyal
parsers: alias long to int on Python 3
r31220
Martin Geisler
pure Python implementation of parsers.c
r7700 _pack = struct.pack
_unpack = struct.unpack
_compress = zlib.compress
_decompress = zlib.decompress
dirstate-entry: turn dirstate tuple into a real object (like in C)...
r48296
dirstate-entry: add a `from_p2` property...
r48303 # a special value used internally for `size` if the file come from the other parent
FROM_P2 = -2
dirstate-entry: `merged_removed` and `from_p2_removed` properties...
r48305 # a special value used internally for `size` if the file is modified/merged/added
NONNORMAL = -1
dirstate-item: use need_delay when packing dirstate...
r48329 # a special value used internally for `time` if the time is ambigeous
AMBIGUOUS_TIME = -1
Simon Sapin
dirstate-v2: initial Python parser...
r49035 # Bits of the `flags` byte inside a node in the file format
DIRSTATE_V2_WDIR_TRACKED = 1 << 0
DIRSTATE_V2_P1_TRACKED = 1 << 1
DIRSTATE_V2_P2_INFO = 1 << 2
dirstate-v2: reorder flag to group related one together...
r49085 DIRSTATE_V2_MODE_EXEC_PERM = 1 << 3
DIRSTATE_V2_MODE_IS_SYMLINK = 1 << 4
DIRSTATE_V2_HAS_FALLBACK_EXEC = 1 << 5
DIRSTATE_V2_FALLBACK_EXEC = 1 << 6
DIRSTATE_V2_HAS_FALLBACK_SYMLINK = 1 << 7
DIRSTATE_V2_FALLBACK_SYMLINK = 1 << 8
DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED = 1 << 9
DIRSTATE_V2_HAS_MODE_AND_SIZE = 1 << 10
DIRSTATE_V2_HAS_MTIME = 1 << 11
DIRSTATE_V2_MTIME_SECOND_AMBIGUOUS = 1 << 12
DIRSTATE_V2_DIRECTORY = 1 << 13
DIRSTATE_V2_ALL_UNKNOWN_RECORDED = 1 << 14
DIRSTATE_V2_ALL_IGNORED_RECORDED = 1 << 15
Simon Sapin
dirstate-v2: initial Python parser...
r49035
dirstate-entry: add a `from_p2` property...
r48303
dirstate-item: use an explicit __init__ function instead of the attrs one...
r48464 @attr.s(slots=True, init=False)
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class DirstateItem:
dirstate-entry: turn dirstate tuple into a real object (like in C)...
r48296 """represent a dirstate entry
dirstate-item: update the attribute documentation...
r48924 It hold multiple attributes
# about file tracking
- wc_tracked: is the file tracked by the working copy
- p1_tracked: is the file tracked in working copy first parent
dirstate-item: change the internal storage and constructor value...
r48950 - p2_info: the file has been involved in some merge operation. Either
because it was actually merged, or because the p2 version was
Simon Sapin
dirstate-v2: Document flags/mode/size/mtime fields of tree nodes...
r49002 ahead, or because some rename moved it there. In either case
dirstate-item: change the internal storage and constructor value...
r48950 `hg status` will want it displayed as modified.
dirstate-item: update the attribute documentation...
r48924
# about the file state expected from p1 manifest:
- mode: the file mode in p1
- size: the file size in p1
dirstate-item: change the internal storage and constructor value...
r48950 These value can be set to None, which mean we don't have a meaningful value
to compare with. Either because we don't really care about them as there
`status` is known without having to look at the disk or because we don't
know these right now and a full comparison will be needed to find out if
the file is clean.
dirstate-item: update the attribute documentation...
r48924 # about the file state on disk last time we saw it:
- mtime: the last known clean mtime for the file.
dirstate-item: change the internal storage and constructor value...
r48950 This value can be set to None if no cachable state exist. Either because we
do not care (see previous section) or because we could not cache something
yet.
dirstate: document the dirstatetuple content...
r48284 """
dirstate-item: keep the full information in memory (for pure form)...
r48739 _wc_tracked = attr.ib()
_p1_tracked = attr.ib()
dirstate-item: change the internal storage and constructor value...
r48950 _p2_info = attr.ib()
Augie Fackler
parsers: move DirstateItem to attr.s...
r48366 _mode = attr.ib()
_size = attr.ib()
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 _mtime_s = attr.ib()
_mtime_ns = attr.ib()
dirstate: add a concept of "fallback" flags to dirstate item...
r49068 _fallback_exec = attr.ib()
_fallback_symlink = attr.ib()
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 _mtime_second_ambiguous = attr.ib()
dirstate-entry: turn dirstate tuple into a real object (like in C)...
r48296
dirstate-item: feed more information to `__init__`...
r48706 def __init__(
self,
wc_tracked=False,
p1_tracked=False,
dirstate-item: change the internal storage and constructor value...
r48950 p2_info=False,
has_meaningful_data=True,
has_meaningful_mtime=True,
dirstate-item: feed more information to `__init__`...
r48706 parentfiledata=None,
dirstate: make DirstateItem constructor accept fallback value...
r49069 fallback_exec=None,
fallback_symlink=None,
dirstate-item: feed more information to `__init__`...
r48706 ):
dirstate-item: keep the full information in memory (for pure form)...
r48739 self._wc_tracked = wc_tracked
self._p1_tracked = p1_tracked
dirstate-item: change the internal storage and constructor value...
r48950 self._p2_info = p2_info
dirstate: make DirstateItem constructor accept fallback value...
r49069 self._fallback_exec = fallback_exec
self._fallback_symlink = fallback_symlink
dirstate: add a concept of "fallback" flags to dirstate item...
r49068
dirstate-item: change the internal storage and constructor value...
r48950 self._mode = None
self._size = None
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 self._mtime_s = None
self._mtime_ns = None
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 self._mtime_second_ambiguous = False
dirstate-item: keep the full information in memory (for pure form)...
r48739 if parentfiledata is None:
dirstate-item: change the internal storage and constructor value...
r48950 has_meaningful_mtime = False
has_meaningful_data = False
dirstate-item: allow mtime to be None in "parentdata"...
r49201 elif parentfiledata[2] is None:
has_meaningful_mtime = False
dirstate-item: change the internal storage and constructor value...
r48950 if has_meaningful_data:
dirstate-item: feed more information to `__init__`...
r48706 self._mode = parentfiledata[0]
self._size = parentfiledata[1]
dirstate-item: change the internal storage and constructor value...
r48950 if has_meaningful_mtime:
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 (
self._mtime_s,
self._mtime_ns,
self._mtime_second_ambiguous,
) = parentfiledata[2]
dirstate-item: use an explicit __init__ function instead of the attrs one...
r48464
dirstate-item: add a `from_v1_data` constructor...
r48465 @classmethod
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 def from_v2_data(cls, flags, size, mtime_s, mtime_ns):
Simon Sapin
dirstate-v2: initial Python parser...
r49035 """Build a new DirstateItem object from V2 data"""
has_mode_size = bool(flags & DIRSTATE_V2_HAS_MODE_AND_SIZE)
dirstate-v2: adjust the meaning of directory flags...
r49083 has_meaningful_mtime = bool(flags & DIRSTATE_V2_HAS_MTIME)
Simon Sapin
dirstate-v2: initial Python parser...
r49035 mode = None
Simon Sapin
dirstate-v2: adds a flag to mark a file as modified...
r49066
if flags & +DIRSTATE_V2_EXPECTED_STATE_IS_MODIFIED:
# we do not have support for this flag in the code yet,
# force a lookup for this file.
has_mode_size = False
has_meaningful_mtime = False
dirstate-v2: preserve the fallback values on disk...
r49070 fallback_exec = None
if flags & DIRSTATE_V2_HAS_FALLBACK_EXEC:
fallback_exec = flags & DIRSTATE_V2_FALLBACK_EXEC
fallback_symlink = None
if flags & DIRSTATE_V2_HAS_FALLBACK_SYMLINK:
fallback_symlink = flags & DIRSTATE_V2_FALLBACK_SYMLINK
Simon Sapin
dirstate-v2: initial Python parser...
r49035 if has_mode_size:
assert stat.S_IXUSR == 0o100
if flags & DIRSTATE_V2_MODE_EXEC_PERM:
mode = 0o755
else:
mode = 0o644
if flags & DIRSTATE_V2_MODE_IS_SYMLINK:
mode |= stat.S_IFLNK
else:
mode |= stat.S_IFREG
dirstate-item: make sure we load `mtime-second-ambiguous` from disk...
r49231
second_ambiguous = flags & DIRSTATE_V2_MTIME_SECOND_AMBIGUOUS
Simon Sapin
dirstate-v2: initial Python parser...
r49035 return cls(
wc_tracked=bool(flags & DIRSTATE_V2_WDIR_TRACKED),
p1_tracked=bool(flags & DIRSTATE_V2_P1_TRACKED),
p2_info=bool(flags & DIRSTATE_V2_P2_INFO),
has_meaningful_data=has_mode_size,
Simon Sapin
dirstate-v2: adds a flag to mark a file as modified...
r49066 has_meaningful_mtime=has_meaningful_mtime,
dirstate-item: make sure we load `mtime-second-ambiguous` from disk...
r49231 parentfiledata=(mode, size, (mtime_s, mtime_ns, second_ambiguous)),
dirstate-v2: preserve the fallback values on disk...
r49070 fallback_exec=fallback_exec,
fallback_symlink=fallback_symlink,
Simon Sapin
dirstate-v2: initial Python parser...
r49035 )
@classmethod
dirstate-item: add a `from_v1_data` constructor...
r48465 def from_v1_data(cls, state, mode, size, mtime):
"""Build a new DirstateItem object from V1 data
Since the dirstate-v1 format is frozen, the signature of this function
is not expected to change, unlike the __init__ one.
"""
dirstate-item: keep the full information in memory (for pure form)...
r48739 if state == b'm':
dirstate-item: replace call to new_merged...
r48966 return cls(wc_tracked=True, p1_tracked=True, p2_info=True)
dirstate-item: keep the full information in memory (for pure form)...
r48739 elif state == b'a':
dirstate-item: replace call to new_added...
r48968 return cls(wc_tracked=True)
dirstate-item: keep the full information in memory (for pure form)...
r48739 elif state == b'r':
if size == NONNORMAL:
dirstate-item: change the internal storage and constructor value...
r48950 p1_tracked = True
p2_info = True
dirstate-item: keep the full information in memory (for pure form)...
r48739 elif size == FROM_P2:
dirstate-item: change the internal storage and constructor value...
r48950 p1_tracked = False
p2_info = True
dirstate-item: keep the full information in memory (for pure form)...
r48739 else:
dirstate-item: change the internal storage and constructor value...
r48950 p1_tracked = True
p2_info = False
return cls(p1_tracked=p1_tracked, p2_info=p2_info)
dirstate-item: keep the full information in memory (for pure form)...
r48739 elif state == b'n':
if size == FROM_P2:
dirstate-item: replace call to new_from_p2...
r48970 return cls(wc_tracked=True, p2_info=True)
dirstate-item: keep the full information in memory (for pure form)...
r48739 elif size == NONNORMAL:
dirstate-item: replace call to new_possibly_dirty...
r48972 return cls(wc_tracked=True, p1_tracked=True)
dirstate-item: keep the full information in memory (for pure form)...
r48739 elif mtime == AMBIGUOUS_TIME:
dirstate-item: replace a call to new_normal...
r48974 return cls(
wc_tracked=True,
p1_tracked=True,
has_meaningful_mtime=False,
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 parentfiledata=(mode, size, (42, 0, False)),
dirstate-item: replace a call to new_normal...
r48974 )
dirstate-item: keep the full information in memory (for pure form)...
r48739 else:
dirstate-item: replace call to new_normal...
r48975 return cls(
wc_tracked=True,
p1_tracked=True,
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 parentfiledata=(mode, size, (mtime, 0, False)),
dirstate-item: replace call to new_normal...
r48975 )
dirstate-item: keep the full information in memory (for pure form)...
r48739 else:
raise RuntimeError(b'unknown state: %s' % state)
dirstate-item: add a `from_v1_data` constructor...
r48465
dirstate-item: add a `set_possibly_dirty` method...
r48466 def set_possibly_dirty(self):
"""Mark a file as "possibly dirty"
This means the next status call will have to actually check its content
to make sure it is correct.
"""
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 self._mtime_s = None
self._mtime_ns = None
dirstate-item: add a `set_possibly_dirty` method...
r48466
dirstate: introduce a `set_clean` method on dirstate's map and items...
r48788 def set_clean(self, mode, size, mtime):
"""mark a file as "clean" cancelling potential "possibly dirty call"
Note: this function is a descendant of `dirstate.normal` and is
currently expected to be call on "normal" entry only. There are not
reason for this to not change in the future as long as the ccode is
updated to preserve the proper state of the non-normal files.
"""
self._wc_tracked = True
self._p1_tracked = True
self._mode = mode
self._size = size
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 self._mtime_s, self._mtime_ns, self._mtime_second_ambiguous = mtime
dirstate: introduce a `set_clean` method on dirstate's map and items...
r48788
dirstate: introduce a set_tracked method on "map" and "item"...
r48804 def set_tracked(self):
"""mark a file as tracked in the working copy
This will ultimately be called by command like `hg add`.
"""
self._wc_tracked = True
dirstate-item: change the internal storage and constructor value...
r48950 # `set_tracked` is replacing various `normallookup` call. So we mark
# the files as needing lookup
dirstate: introduce a set_tracked method on "map" and "item"...
r48804 #
# Consider dropping this in the future in favor of something less broad.
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 self._mtime_s = None
self._mtime_ns = None
dirstate: introduce a set_tracked method on "map" and "item"...
r48804
dirstatemap: replace `removefile` by an explicit `entry.set_untracked()`...
r48701 def set_untracked(self):
"""mark a file as untracked in the working copy
This will ultimately be called by command like `hg remove`.
"""
dirstate-item: keep the full information in memory (for pure form)...
r48739 self._wc_tracked = False
self._mode = None
self._size = None
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 self._mtime_s = None
self._mtime_ns = None
dirstatemap: replace `removefile` by an explicit `entry.set_untracked()`...
r48701
dirstate: use a new `drop_merge_data` in `setparent`...
r48874 def drop_merge_data(self):
Raphaël Gomès
dirstate-item: add missing bit of docstring...
r50010 """remove all "merge-only" information from a DirstateItem
dirstate: use a new `drop_merge_data` in `setparent`...
r48874
This is to be call by the dirstatemap code when the second parent is dropped
"""
dirstate-item: change the internal storage and constructor value...
r48950 if self._p2_info:
self._p2_info = False
self._mode = None
self._size = None
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 self._mtime_s = None
self._mtime_ns = None
dirstate: use a new `drop_merge_data` in `setparent`...
r48874
dirstate-entry: add a `state` property (and use it)...
r48301 @property
dirstate-entry: add a `mode` property...
r48325 def mode(self):
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 return self._v1_mode()
dirstate-entry: add a `mode` property...
r48325
@property
dirstate-entry: add a `size` property...
r48326 def size(self):
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 return self._v1_size()
dirstate-entry: add a `size` property...
r48326
@property
dirstate-entry: add a `mtime` property...
r48327 def mtime(self):
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 return self._v1_mtime()
dirstate-entry: add a `mtime` property...
r48327
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 def mtime_likely_equal_to(self, other_mtime):
self_sec = self._mtime_s
if self_sec is None:
return False
self_ns = self._mtime_ns
dirstate-item: add a "second_ambiguous` flag in the mtime tuple...
r49227 other_sec, other_ns, second_ambiguous = other_mtime
dirstate-item: implement the comparison logic for mtime-second-ambiguous...
r49228 if self_sec != other_sec:
# seconds are different theses mtime are definitly not equal
return False
elif other_ns == 0 or self_ns == 0:
# at least one side as no nano-seconds information
if self._mtime_second_ambiguous:
# We cannot trust the mtime in this case
return False
else:
# the "seconds" value was reliable on its own. We are good to go.
return True
else:
# We have nano second information, let us use them !
return self_ns == other_ns
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079
dirstate-entry: add a `mtime` property...
r48327 @property
dirstate-entry: add a `state` property (and use it)...
r48301 def state(self):
"""
States are:
n normal
m needs merging
r marked for removal
a marked for addition
XXX This "state" is a bit obscure and mostly a direct expression of the
dirstatev1 format. It would make sense to ultimately deprecate it in
favor of the more "semantic" attributes.
"""
dirstate-item: use `any_tracked` more...
r48923 if not self.any_tracked:
dirstate-entry: use `?` for the state of entry without any tracking...
r48900 return b'?'
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 return self._v1_state()
dirstate-entry: add a `state` property (and use it)...
r48301
dirstate-entry: add a `merged` property...
r48302 @property
dirstate: add a concept of "fallback" flags to dirstate item...
r49068 def has_fallback_exec(self):
"""True if "fallback" information are available for the "exec" bit
Fallback information can be stored in the dirstate to keep track of
filesystem attribute tracked by Mercurial when the underlying file
system or operating system does not support that property, (e.g.
Windows).
Not all version of the dirstate on-disk storage support preserving this
information.
"""
return self._fallback_exec is not None
@property
def fallback_exec(self):
""" "fallback" information for the executable bit
True if the file should be considered executable when we cannot get
this information from the files system. False if it should be
considered non-executable.
See has_fallback_exec for details."""
return self._fallback_exec
@fallback_exec.setter
def set_fallback_exec(self, value):
"""control "fallback" executable bit
Set to:
- True if the file should be considered executable,
- False if the file should be considered non-executable,
- None if we do not have valid fallback data.
See has_fallback_exec for details."""
if value is None:
self._fallback_exec = None
else:
self._fallback_exec = bool(value)
@property
def has_fallback_symlink(self):
"""True if "fallback" information are available for symlink status
Fallback information can be stored in the dirstate to keep track of
filesystem attribute tracked by Mercurial when the underlying file
system or operating system does not support that property, (e.g.
Windows).
Not all version of the dirstate on-disk storage support preserving this
information."""
return self._fallback_symlink is not None
@property
def fallback_symlink(self):
""" "fallback" information for symlink status
True if the file should be considered executable when we cannot get
this information from the files system. False if it should be
considered non-executable.
See has_fallback_exec for details."""
return self._fallback_symlink
@fallback_symlink.setter
def set_fallback_symlink(self, value):
"""control "fallback" symlink status
Set to:
- True if the file should be considered a symlink,
- False if the file should be considered not a symlink,
- None if we do not have valid fallback data.
See has_fallback_symlink for details."""
if value is None:
self._fallback_symlink = None
else:
self._fallback_symlink = bool(value)
@property
dirstate-entry: add a `tracked` property...
r48320 def tracked(self):
"""True is the file is tracked in the working copy"""
dirstate-item: implement `tracked` in a simpler way...
r48740 return self._wc_tracked
dirstate-entry: add a `tracked` property...
r48320
@property
dirstate-item: introduce a `any_tracked` property...
r48899 def any_tracked(self):
"""True is the file is tracked anywhere (wc or parents)"""
dirstate-item: change the internal storage and constructor value...
r48950 return self._wc_tracked or self._p1_tracked or self._p2_info
dirstate-item: introduce a `any_tracked` property...
r48899
@property
dirstate-entry: add a `added` property...
r48315 def added(self):
"""True if the file has been added"""
dirstate-item: change the internal storage and constructor value...
r48950 return self._wc_tracked and not (self._p1_tracked or self._p2_info)
dirstate-entry: add a `added` property...
r48315
@property
dirstate-item: introduce a `maybe_clean` property...
r48898 def maybe_clean(self):
"""True if the file has a chance to be in the "clean" state"""
if not self._wc_tracked:
return False
dirstate-item: change the internal storage and constructor value...
r48950 elif not self._p1_tracked:
dirstate-item: introduce a `maybe_clean` property...
r48898 return False
dirstate-item: change the internal storage and constructor value...
r48950 elif self._p2_info:
dirstate-item: introduce a `maybe_clean` property...
r48898 return False
return True
@property
dirstate-item: introduce a `p1_tracked` property...
r48955 def p1_tracked(self):
"""True if the file is tracked in the first parent manifest"""
return self._p1_tracked
@property
dirstate-item: introduce a `p2_info` property that combine two others...
r48954 def p2_info(self):
"""True if the file needed to merge or apply any input from p2
See the class documentation for details.
"""
return self._wc_tracked and self._p2_info
@property
dirstate-entry: add a `removed` property...
r48304 def removed(self):
"""True if the file has been removed"""
dirstate-item: change the internal storage and constructor value...
r48950 return not self._wc_tracked and (self._p1_tracked or self._p2_info)
dirstate-entry: add a `removed` property...
r48304
Raphaël Gomès
dirstate-v2: Initial Python serializer...
r49036 def v2_data(self):
"""Returns (flags, mode, size, mtime) for v2 serialization"""
flags = 0
if self._wc_tracked:
flags |= DIRSTATE_V2_WDIR_TRACKED
if self._p1_tracked:
flags |= DIRSTATE_V2_P1_TRACKED
if self._p2_info:
flags |= DIRSTATE_V2_P2_INFO
Simon Sapin
dirstate-v2: Use attributes as intended instead of properties in v2_data()...
r49043 if self._mode is not None and self._size is not None:
Raphaël Gomès
dirstate-v2: Initial Python serializer...
r49036 flags |= DIRSTATE_V2_HAS_MODE_AND_SIZE
if self.mode & stat.S_IXUSR:
flags |= DIRSTATE_V2_MODE_EXEC_PERM
if stat.S_ISLNK(self.mode):
flags |= DIRSTATE_V2_MODE_IS_SYMLINK
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 if self._mtime_s is not None:
dirstate-v2: adjust the meaning of directory flags...
r49083 flags |= DIRSTATE_V2_HAS_MTIME
dirstate-item: make sure we set the mtime-second-ambiguous on v2 write...
r49230 if self._mtime_second_ambiguous:
flags |= DIRSTATE_V2_MTIME_SECOND_AMBIGUOUS
dirstate-v2: preserve the fallback values on disk...
r49070
if self._fallback_exec is not None:
flags |= DIRSTATE_V2_HAS_FALLBACK_EXEC
if self._fallback_exec:
flags |= DIRSTATE_V2_FALLBACK_EXEC
if self._fallback_symlink is not None:
flags |= DIRSTATE_V2_HAS_FALLBACK_SYMLINK
if self._fallback_symlink:
flags |= DIRSTATE_V2_FALLBACK_SYMLINK
dirstate-v2: adds two flag to track the presence of some unrecorded files...
r49067 # Note: we do not need to do anything regarding
# DIRSTATE_V2_ALL_UNKNOWN_RECORDED and DIRSTATE_V2_ALL_IGNORED_RECORDED
# since we never set _DIRSTATE_V2_HAS_DIRCTORY_MTIME
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 return (flags, self._size or 0, self._mtime_s or 0, self._mtime_ns or 0)
Raphaël Gomès
dirstate-v2: Initial Python serializer...
r49036
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 def _v1_state(self):
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298 """return a "state" suitable for v1 serialization"""
dirstate-item: change the internal storage and constructor value...
r48950 if not self.any_tracked:
dirstate-item: keep the full information in memory (for pure form)...
r48739 # the object has no state to record, this is -currently-
# unsupported
raise RuntimeError('untracked item')
dirstate-item: implement v1_state with higher level block...
r48748 elif self.removed:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return b'r'
dirstate-item: replace another usage of `merged`...
r48964 elif self._p1_tracked and self._p2_info:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return b'm'
dirstate-item: implement v1_state with higher level block...
r48748 elif self.added:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return b'a'
dirstate-item: implement v1_state with higher level block...
r48748 else:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return b'n'
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 def _v1_mode(self):
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298 """return a "mode" suitable for v1 serialization"""
dirstate-item: keep the full information in memory (for pure form)...
r48739 return self._mode if self._mode is not None else 0
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 def _v1_size(self):
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298 """return a "size" suitable for v1 serialization"""
dirstate-item: use `any_tracked` more...
r48923 if not self.any_tracked:
dirstate-item: keep the full information in memory (for pure form)...
r48739 # the object has no state to record, this is -currently-
# unsupported
raise RuntimeError('untracked item')
dirstate-item: change the internal storage and constructor value...
r48950 elif self.removed and self._p1_tracked and self._p2_info:
dirstate-item: implement `v1_size` with higher level block...
r48749 return NONNORMAL
dirstate-item: directly use `p2_info` in `v1_size`...
r48961 elif self._p2_info:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return FROM_P2
dirstate-item: implement `v1_size` with higher level block...
r48749 elif self.removed:
return 0
elif self.added:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return NONNORMAL
dirstate-item: change the internal storage and constructor value...
r48950 elif self._size is None:
return NONNORMAL
dirstate-item: implement `v1_size` with higher level block...
r48749 else:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return self._size
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 def _v1_mtime(self):
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298 """return a "mtime" suitable for v1 serialization"""
dirstate-item: use `any_tracked` more...
r48923 if not self.any_tracked:
dirstate-item: keep the full information in memory (for pure form)...
r48739 # the object has no state to record, this is -currently-
# unsupported
raise RuntimeError('untracked item')
dirstate-item: implement `v1_mtime` with higher level block...
r48750 elif self.removed:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return 0
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 elif self._mtime_s is None:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return AMBIGUOUS_TIME
dirstate-item: change the internal storage and constructor value...
r48950 elif self._p2_info:
dirstate-item: keep the full information in memory (for pure form)...
r48739 return AMBIGUOUS_TIME
dirstate-item: change the internal storage and constructor value...
r48950 elif not self._p1_tracked:
dirstate-item: implement `v1_mtime` with higher level block...
r48750 return AMBIGUOUS_TIME
dirstate-item: ignore mtime to write v1 when `mtime-second-ambiguous` is set...
r49229 elif self._mtime_second_ambiguous:
return AMBIGUOUS_TIME
dirstate-item: keep the full information in memory (for pure form)...
r48739 else:
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 return self._mtime_s
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298
Augie Fackler
formatting: blacken the codebase...
r43346
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def gettype(q):
return int(q & 0xFFFF)
Matt Mackall
pure/parsers: fix circular imports, import mercurial modules properly
r7945
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class BaseIndexObject:
revlog: signal which revlog index are compatible with Rust...
r48042 # Can I be passed to an algorithme implemented in Rust ?
rust_ext_compat = 0
Raphaël Gomès
pure-parsers: document index class constants...
r47380 # Format of an index entry according to Python's `struct` language
revlog: directly use the Struct object for related operation...
r47619 index_format = revlog_constants.INDEX_ENTRY_V1
Raphaël Gomès
pure-parsers: document index class constants...
r47380 # Size of a C unsigned long long int, platform independent
big_int_size = struct.calcsize(b'>Q')
# Size of a C long int, platform independent
int_size = struct.calcsize(b'>i')
# An empty index entry, used as a default value to be overridden, or nullrev
revlog: add a "data compression mode" entry in the index tuple...
r48023 null_item = (
0,
0,
0,
-1,
-1,
-1,
-1,
sha1nodeconstants.nullid,
0,
0,
revlog_constants.COMP_MODE_INLINE,
revlog: introduce a compression mode for sidedata in the revlog index...
r48030 revlog_constants.COMP_MODE_INLINE,
rank: add a "rank" value to the revlog-entry tuple...
r49330 revlog_constants.RANK_UNKNOWN,
revlog: add a "data compression mode" entry in the index tuple...
r48023 )
Raphaël Gomès
revlog: prepare pure parser for being overloaded...
r47136
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 @util.propertycache
def entry_size(self):
return self.index_format.size
revlog: move the nodemap into the index object (for pure)...
r43925 @util.propertycache
revlog: deprecate direct `nodemap` access...
r43974 def _nodemap(self):
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 nodemap = nodemaputil.NodeMap({sha1nodeconstants.nullid: nullrev})
revlog: move the nodemap into the index object (for pure)...
r43925 for r in range(0, len(self)):
n = self[r][7]
nodemap[n] = r
return nodemap
index: add a `has_node` method (API)...
r43934 def has_node(self, node):
"""return True if the node exist in the index"""
revlog: deprecate direct `nodemap` access...
r43974 return node in self._nodemap
index: add a `has_node` method (API)...
r43934
index: add a `rev` method (API)...
r43952 def rev(self, node):
"""return a revision for a node
If the node is unknown, raise a RevlogError"""
revlog: deprecate direct `nodemap` access...
r43974 return self._nodemap[node]
index: add a `rev` method (API)...
r43952
index: add a `get_rev` method (API)...
r43954 def get_rev(self, node):
"""return a revision for a node
If the node is unknown, return None"""
revlog: deprecate direct `nodemap` access...
r43974 return self._nodemap.get(node)
index: add a `get_rev` method (API)...
r43954
revlog: deal with nodemap deletion within the index...
r43933 def _stripnodes(self, start):
revlog: deprecate direct `nodemap` access...
r43974 if '_nodemap' in vars(self):
revlog: deal with nodemap deletion within the index...
r43933 for r in range(start, len(self)):
n = self[r][7]
revlog: deprecate direct `nodemap` access...
r43974 del self._nodemap[n]
revlog: deal with nodemap deletion within the index...
r43933
revlog: move the nodemap into the index object (for pure)...
r43925 def clearcaches(self):
revlog: deprecate direct `nodemap` access...
r43974 self.__dict__.pop('_nodemap', None)
revlog: move the nodemap into the index object (for pure)...
r43925
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def __len__(self):
Martin von Zweigbergk
index: don't include nullid in len()...
r38887 return self._lgt + len(self._extra)
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133
Martin von Zweigbergk
index: replace insert(-1, e) method by append(e) method...
r38886 def append(self, tup):
revlog: deprecate direct `nodemap` access...
r43974 if '_nodemap' in vars(self):
self._nodemap[tup[7]] = len(self)
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 data = self._pack_entry(len(self), tup)
Joerg Sonnenberger
revlog: store new index entries as binary...
r46548 self._extra.append(data)
Matt Mackall
pure/parsers: fix circular imports, import mercurial modules properly
r7945
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 def _pack_entry(self, rev, entry):
revlog: always "append" full size tuple...
r47914 assert entry[8] == 0
assert entry[9] == 0
return self.index_format.pack(*entry[:8])
Martin von Zweigbergk
index: rename _fix_index() since it no longer fixes the index...
r39251 def _check_index(self, i):
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if not isinstance(i, int):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise TypeError(b"expecting int indexes")
Martin von Zweigbergk
index: don't include nullid in boundary check in pure code...
r39250 if i < 0 or i >= len(self):
revlog: add some information about the revision we cannot find...
r49327 raise IndexError(i)
Matt Mackall
pure/parsers: fix circular imports, import mercurial modules properly
r7945
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def __getitem__(self, i):
Augie Fackler
parsers: adjust pure-python version to mimic a3dacabd476b...
r39082 if i == -1:
Raphaël Gomès
revlog: prepare pure parser for being overloaded...
r47136 return self.null_item
Martin von Zweigbergk
index: rename _fix_index() since it no longer fixes the index...
r39251 self._check_index(i)
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if i >= self._lgt:
Joerg Sonnenberger
revlog: store new index entries as binary...
r46548 data = self._extra[i - self._lgt]
else:
index = self._calculate_index(i)
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 data = self._data[index : index + self.entry_size]
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 r = self._unpack_entry(i, data)
Joerg Sonnenberger
revlog: store new index entries as binary...
r46548 if self._lgt and i == 0:
revlog: move `offset_type` to `revlogutils`...
r48186 offset = revlogutils.offset_type(0, gettype(r[0]))
r = (offset,) + r[1:]
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 return r
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 def _unpack_entry(self, rev, data):
revlog: make the index always return the same tuple...
r47913 r = self.index_format.unpack(data)
revlog: introduce a compression mode for sidedata in the revlog index...
r48030 r = r + (
0,
0,
revlog_constants.COMP_MODE_INLINE,
revlog_constants.COMP_MODE_INLINE,
rank: add a "rank" value to the revlog-entry tuple...
r49330 revlog_constants.RANK_UNKNOWN,
revlog: introduce a compression mode for sidedata in the revlog index...
r48030 )
revlog: make the index always return the same tuple...
r47913 return r
revlog: have an explicit "pack_header" method...
r47811 def pack_header(self, header):
"""pack header information as binary"""
v_fmt = revlog_constants.INDEX_HEADER
return v_fmt.pack(header)
def entry_binary(self, rev):
revlog: add a `entry_binary` method on index...
r47808 """return the raw binary string representing a revision"""
entry = self[rev]
revlog: make the index always return the same tuple...
r47913 p = revlog_constants.INDEX_ENTRY_V1.pack(*entry[:8])
revlog: add a `entry_binary` method on index...
r47808 if rev == 0:
revlog: have an explicit "pack_header" method...
r47811 p = p[revlog_constants.INDEX_HEADER.size :]
revlog: add a `entry_binary` method on index...
r47808 return p
Augie Fackler
formatting: blacken the codebase...
r43346
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 class IndexObject(BaseIndexObject):
def __init__(self, data):
revlog: add a `entry_binary` method on index...
r47808 assert len(data) % self.entry_size == 0, (
len(data),
self.entry_size,
len(data) % self.entry_size,
)
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 self._data = data
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 self._lgt = len(data) // self.entry_size
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 self._extra = []
def _calculate_index(self, i):
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 return i * self.entry_size
Matt Mackall
revlog: remove lazy index
r13253
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def __delitem__(self, i):
Alex Gaynor
style: always use `x is not None` instead of `not x is None`...
r34332 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b"deleting slices only supports a:-1 with step 1")
Martin von Zweigbergk
index: rename _fix_index() since it no longer fixes the index...
r39251 i = i.start
self._check_index(i)
revlog: deal with nodemap deletion within the index...
r43933 self._stripnodes(i)
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if i < self._lgt:
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 self._data = self._data[: i * self.entry_size]
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 self._lgt = i
self._extra = []
else:
Augie Fackler
formatting: blacken the codebase...
r43346 self._extra = self._extra[: i - self._lgt]
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133
nodemap: add a (python) index class for persistent nodemap testing...
r44794 class PersistentNodeMapIndexObject(IndexObject):
"""a Debug oriented class to test persistent nodemap
We need a simple python object to test API and higher level behavior. See
the Rust implementation for more serious usage. This should be used only
through the dedicated `devel.persistent-nodemap` config.
"""
nodemap: add a optional `nodemap_add_full` method on indexes...
r44795 def nodemap_data_all(self):
"""Return bytes containing a full serialization of a nodemap
The nodemap should be valid for the full set of revisions in the
index."""
return nodemaputil.persistent_data(self)
nodemap: introduce append-only incremental update of the persistent data...
r44805 def nodemap_data_incremental(self):
"""Return bytes containing a incremental update to persistent nodemap
This containst the data for an append-only update of the data provided
in the last call to `update_nodemap_data`.
"""
if self._nm_root is None:
return None
nodemap: double check the source docket when doing incremental update...
r44809 docket = self._nm_docket
nodemap: track the total and unused amount of data in the rawdata file...
r44808 changed, data = nodemaputil.update_persistent_data(
nodemap: double check the source docket when doing incremental update...
r44809 self, self._nm_root, self._nm_max_idx, self._nm_docket.tip_rev
nodemap: introduce append-only incremental update of the persistent data...
r44805 )
nodemap: double check the source docket when doing incremental update...
r44809
self._nm_root = self._nm_max_idx = self._nm_docket = None
return docket, changed, data
nodemap: introduce append-only incremental update of the persistent data...
r44805
nodemap: track the maximum revision tracked in the nodemap...
r44807 def update_nodemap_data(self, docket, nm_data):
"""provide full block of persisted binary data for a nodemap
nodemap: provide the on disk data to indexes who support it...
r44801
The data are expected to come from disk. See `nodemap_data_all` for a
produceur of such data."""
if nm_data is not None:
nodemap: introduce append-only incremental update of the persistent data...
r44805 self._nm_root, self._nm_max_idx = nodemaputil.parse_data(nm_data)
if self._nm_root:
nodemap: double check the source docket when doing incremental update...
r44809 self._nm_docket = docket
nodemap: introduce append-only incremental update of the persistent data...
r44805 else:
nodemap: double check the source docket when doing incremental update...
r44809 self._nm_root = self._nm_max_idx = self._nm_docket = None
nodemap: provide the on disk data to indexes who support it...
r44801
nodemap: add a (python) index class for persistent nodemap testing...
r44794
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 class InlinedIndexObject(BaseIndexObject):
def __init__(self, data, inline=0):
self._data = data
self._lgt = self._inline_scan(None)
self._inline_scan(self._lgt)
self._extra = []
Martin Geisler
pure Python implementation of parsers.c
r7700
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def _inline_scan(self, lgt):
off = 0
if lgt is not None:
self._offsets = [0] * lgt
count = 0
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 while off <= len(self._data) - self.entry_size:
Raphaël Gomès
revlog: prepare pure parser for being overloaded...
r47136 start = off + self.big_int_size
Augie Fackler
formatting: blacken the codebase...
r43346 (s,) = struct.unpack(
Raphaël Gomès
revlog: prepare pure parser for being overloaded...
r47136 b'>i',
self._data[start : start + self.int_size],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if lgt is not None:
self._offsets[count] = off
count += 1
revlog: replace revlog._io.size with a new revlog.index.entry_size...
r47736 off += self.entry_size + s
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if off != len(self._data):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b"corrupted data")
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 return count
Augie Fackler
pure parsers: properly detect corrupt index files...
r14421
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def __delitem__(self, i):
Alex Gaynor
style: always use `x is not None` instead of `not x is None`...
r34332 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b"deleting slices only supports a:-1 with step 1")
Martin von Zweigbergk
index: rename _fix_index() since it no longer fixes the index...
r39251 i = i.start
self._check_index(i)
revlog: deal with nodemap deletion within the index...
r43933 self._stripnodes(i)
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if i < self._lgt:
self._offsets = self._offsets[:i]
self._lgt = i
self._extra = []
else:
Augie Fackler
formatting: blacken the codebase...
r43346 self._extra = self._extra[: i - self._lgt]
Martin Geisler
pure Python implementation of parsers.c
r7700
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 def _calculate_index(self, i):
return self._offsets[i]
Martin Geisler
pure Python implementation of parsers.c
r7700
Augie Fackler
formatting: blacken the codebase...
r43346
pacien
revlog: register changelogv2 C implementation in parsers...
r49618 def parse_index2(data, inline, format=revlog_constants.REVLOGV1):
if format == revlog_constants.CHANGELOGV2:
return parse_index_cl_v2(data)
Maciej Fijalkowski
pure: write a really lazy version of pure indexObject...
r29133 if not inline:
pacien
revlog: register changelogv2 C implementation in parsers...
r49618 if format == revlog_constants.REVLOGV2:
cls = IndexObject2
else:
cls = IndexObject
Raphaël Gomès
revlog: introduce v2 format...
r47438 return cls(data), None
revlogv2: drop the code related to inlined revlogv2...
r48036 cls = InlinedIndexObject
Raphaël Gomès
revlog: introduce v2 format...
r47438 return cls(data, inline), (0, data)
changelogv2: use a dedicated on disk format for changelogv2...
r48044 def parse_index_cl_v2(data):
return IndexChangelogV2(data), None
revlogv2: drop the code related to inlined revlogv2...
r48036 class IndexObject2(IndexObject):
revlog: directly use the Struct object for related operation...
r47619 index_format = revlog_constants.INDEX_ENTRY_V2
Raphaël Gomès
revlog: introduce v2 format...
r47438
Raphaël Gomès
sidedata: enable sidedata computers to optionally rewrite flags...
r47844 def replace_sidedata_info(
revlog: compress sidedata when doing "post-pull" sidedata update...
r48033 self,
rev,
sidedata_offset,
sidedata_length,
offset_flags,
compression_mode,
Raphaël Gomès
sidedata: enable sidedata computers to optionally rewrite flags...
r47844 ):
Raphaël Gomès
revlog-index: add `replace_sidedata_info` method...
r47451 """
Replace an existing index entry's sidedata offset and length with new
ones.
This cannot be used outside of the context of sidedata rewriting,
revlog: use `rev` instead of `i` in replace_sidedata_info...
r48017 inside the transaction that creates the revision `rev`.
Raphaël Gomès
revlog-index: add `replace_sidedata_info` method...
r47451 """
revlog: use `rev` instead of `i` in replace_sidedata_info...
r48017 if rev < 0:
Raphaël Gomès
revlog-index: add `replace_sidedata_info` method...
r47451 raise KeyError
revlog: use `rev` instead of `i` in replace_sidedata_info...
r48017 self._check_index(rev)
revlog: simplify the replace_sidedata_info code...
r48018 if rev < self._lgt:
Raphaël Gomès
revlog-index: add `replace_sidedata_info` method...
r47451 msg = b"cannot rewrite entries outside of this transaction"
raise KeyError(msg)
revlog: simplify the replace_sidedata_info code...
r48018 else:
entry = list(self[rev])
entry[0] = offset_flags
entry[8] = sidedata_offset
entry[9] = sidedata_length
revlog: compress sidedata when doing "post-pull" sidedata update...
r48033 entry[11] = compression_mode
revlog: simplify the replace_sidedata_info code...
r48018 entry = tuple(entry)
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 new = self._pack_entry(rev, entry)
revlog: simplify the replace_sidedata_info code...
r48018 self._extra[rev - self._lgt] = new
Raphaël Gomès
revlog-index: add `replace_sidedata_info` method...
r47451
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 def _unpack_entry(self, rev, data):
revlog: introduce a compression mode for sidedata in the revlog index...
r48030 data = self.index_format.unpack(data)
entry = data[:10]
data_comp = data[10] & 3
sidedata_comp = (data[10] & (3 << 2)) >> 2
rank: add a "rank" value to the revlog-entry tuple...
r49330 return entry + (data_comp, sidedata_comp, revlog_constants.RANK_UNKNOWN)
revlog: make the index always return the same tuple...
r47913
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 def _pack_entry(self, rev, entry):
revlog: introduce a compression mode for sidedata in the revlog index...
r48030 data = entry[:10]
data_comp = entry[10] & 3
sidedata_comp = (entry[11] & 3) << 2
data += (data_comp | sidedata_comp,)
return self.index_format.pack(*data)
revlog: always "append" full size tuple...
r47914
revlog: have an explicit "pack_header" method...
r47811 def entry_binary(self, rev):
revlog: add a `entry_binary` method on index...
r47808 """return the raw binary string representing a revision"""
entry = self[rev]
revlog: pass around the `rev` we deal with when packing/unpacking entry...
r48041 return self._pack_entry(rev, entry)
revlog: add a `entry_binary` method on index...
r47808
revlogv2: store version information in the docket only...
r48009 def pack_header(self, header):
"""pack header information as binary"""
msg = 'version header should go in the docket, not the index: %d'
msg %= header
raise error.ProgrammingError(msg)
Raphaël Gomès
revlog: introduce v2 format...
r47438
changelogv2: use a dedicated on disk format for changelogv2...
r48044 class IndexChangelogV2(IndexObject2):
index_format = revlog_constants.INDEX_ENTRY_CL_V2
rank: actually persist revision's rank in changelog-v2...
r49331 null_item = (
IndexObject2.null_item[: revlog_constants.ENTRY_RANK]
+ (0,) # rank of null is 0
+ IndexObject2.null_item[revlog_constants.ENTRY_RANK :]
)
changelogv2: use a dedicated on disk format for changelogv2...
r48044 def _unpack_entry(self, rev, data, r=True):
items = self.index_format.unpack(data)
changelog-v2: use helper constant in the code to pack/unpack entries...
r49328 return (
items[revlog_constants.INDEX_ENTRY_V2_IDX_OFFSET],
items[revlog_constants.INDEX_ENTRY_V2_IDX_COMPRESSED_LENGTH],
items[revlog_constants.INDEX_ENTRY_V2_IDX_UNCOMPRESSED_LENGTH],
rev,
rev,
items[revlog_constants.INDEX_ENTRY_V2_IDX_PARENT_1],
items[revlog_constants.INDEX_ENTRY_V2_IDX_PARENT_2],
items[revlog_constants.INDEX_ENTRY_V2_IDX_NODEID],
items[revlog_constants.INDEX_ENTRY_V2_IDX_SIDEDATA_OFFSET],
items[
revlog_constants.INDEX_ENTRY_V2_IDX_SIDEDATA_COMPRESSED_LENGTH
],
items[revlog_constants.INDEX_ENTRY_V2_IDX_COMPRESSION_MODE] & 3,
(items[revlog_constants.INDEX_ENTRY_V2_IDX_COMPRESSION_MODE] >> 2)
& 3,
rank: actually persist revision's rank in changelog-v2...
r49331 items[revlog_constants.INDEX_ENTRY_V2_IDX_RANK],
changelog-v2: use helper constant in the code to pack/unpack entries...
r49328 )
changelogv2: use a dedicated on disk format for changelogv2...
r48044
def _pack_entry(self, rev, entry):
changelog-v2: use helper constant in the code to pack/unpack entries...
r49328
base = entry[revlog_constants.ENTRY_DELTA_BASE]
link_rev = entry[revlog_constants.ENTRY_LINK_REV]
assert base == rev, (base, rev)
assert link_rev == rev, (link_rev, rev)
data = (
entry[revlog_constants.ENTRY_DATA_OFFSET],
entry[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH],
entry[revlog_constants.ENTRY_DATA_UNCOMPRESSED_LENGTH],
entry[revlog_constants.ENTRY_PARENT_1],
entry[revlog_constants.ENTRY_PARENT_2],
entry[revlog_constants.ENTRY_NODE_ID],
entry[revlog_constants.ENTRY_SIDEDATA_OFFSET],
entry[revlog_constants.ENTRY_SIDEDATA_COMPRESSED_LENGTH],
entry[revlog_constants.ENTRY_DATA_COMPRESSION_MODE] & 3
| (entry[revlog_constants.ENTRY_SIDEDATA_COMPRESSION_MODE] & 3)
<< 2,
rank: actually persist revision's rank in changelog-v2...
r49331 entry[revlog_constants.ENTRY_RANK],
changelog-v2: use helper constant in the code to pack/unpack entries...
r49328 )
changelogv2: use a dedicated on disk format for changelogv2...
r48044 return self.index_format.pack(*data)
nodemap: add a (python) index class for persistent nodemap testing...
r44794 def parse_index_devel_nodemap(data, inline):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """like parse_index2, but alway return a PersistentNodeMapIndexObject"""
nodemap: add a (python) index class for persistent nodemap testing...
r44794 return PersistentNodeMapIndexObject(data), None
Martin Geisler
pure Python implementation of parsers.c
r7700 def parse_dirstate(dmap, copymap, st):
Augie Fackler
formatting: blacken the codebase...
r43346 parents = [st[:20], st[20:40]]
Mads Kiilerich
fix wording and not-completely-trivial spelling errors and bad docstrings
r17425 # dereference fields so they will be local in loop
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 format = b">cllll"
Matt Mackall
pure/parsers: fix circular imports, import mercurial modules properly
r7945 e_size = struct.calcsize(format)
Martin Geisler
pure Python implementation of parsers.c
r7700 pos1 = 40
l = len(st)
# the inner loop
while pos1 < l:
pos2 = pos1 + e_size
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 e = _unpack(b">cllll", st[pos1:pos2]) # a literal here is faster
Martin Geisler
pure Python implementation of parsers.c
r7700 pos1 = pos2 + e[4]
f = st[pos2:pos1]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'\0' in f:
f, c = f.split(b'\0')
Martin Geisler
pure Python implementation of parsers.c
r7700 copymap[f] = c
dirstate-item: add a `from_v1_data` constructor...
r48465 dmap[f] = DirstateItem.from_v1_data(*e[:4])
Martin Geisler
pure Python implementation of parsers.c
r7700 return parents
Siddharth Agarwal
dirstate: move pure python dirstate packing to pure/parsers.py
r18567
Augie Fackler
formatting: blacken the codebase...
r43346
dirstate: remove need_delay logic...
r49221 def pack_dirstate(dmap, copymap, pl):
timeless
pycompat: switch to util.stringio for py3 compat
r28861 cs = stringio()
Siddharth Agarwal
dirstate: move pure python dirstate packing to pure/parsers.py
r18567 write = cs.write
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 write(b"".join(pl))
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for f, e in dmap.items():
Siddharth Agarwal
dirstate: move pure python dirstate packing to pure/parsers.py
r18567 if f in copymap:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = b"%s\0%s" % (f, copymap[f])
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298 e = _pack(
b">cllll",
Raphaël Gomès
dirstate: remove v1_* methods from Python/C/Rust shared API...
r49920 e._v1_state(),
e._v1_mode(),
e._v1_size(),
e._v1_mtime(),
dirstate-entry: introduce dedicated accessors for v1 serialization...
r48298 len(f),
)
Siddharth Agarwal
dirstate: move pure python dirstate packing to pure/parsers.py
r18567 write(e)
write(f)
return cs.getvalue()