Spaces:
Paused
Paused
| # This module is part of GitPython and is released under the | |
| # 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/ | |
| """Additional types used by the index.""" | |
| __all__ = ["BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType"] | |
| from binascii import b2a_hex | |
| from pathlib import Path | |
| from git.objects import Blob | |
| from .util import pack, unpack | |
| # typing ---------------------------------------------------------------------- | |
| from typing import NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast | |
| from git.types import PathLike | |
| if TYPE_CHECKING: | |
| from git.repo import Repo | |
| StageType = int | |
| # --------------------------------------------------------------------------------- | |
| # { Invariants | |
| CE_NAMEMASK = 0x0FFF | |
| CE_STAGEMASK = 0x3000 | |
| CE_EXTENDED = 0x4000 | |
| CE_VALID = 0x8000 | |
| CE_STAGESHIFT = 12 | |
| # } END invariants | |
| class BlobFilter: | |
| """Predicate to be used by | |
| :meth:`IndexFile.iter_blobs <git.index.base.IndexFile.iter_blobs>` allowing to | |
| filter only return blobs which match the given list of directories or files. | |
| The given paths are given relative to the repository. | |
| """ | |
| __slots__ = ("paths",) | |
| def __init__(self, paths: Sequence[PathLike]) -> None: | |
| """ | |
| :param paths: | |
| Tuple or list of paths which are either pointing to directories or to files | |
| relative to the current repository. | |
| """ | |
| self.paths = paths | |
| def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: | |
| blob_pathlike: PathLike = stage_blob[1].path | |
| blob_path: Path = blob_pathlike if isinstance(blob_pathlike, Path) else Path(blob_pathlike) | |
| for pathlike in self.paths: | |
| path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) | |
| # TODO: Change to use `PosixPath.is_relative_to` once Python 3.8 is no | |
| # longer supported. | |
| filter_parts = path.parts | |
| blob_parts = blob_path.parts | |
| if len(filter_parts) > len(blob_parts): | |
| continue | |
| if all(i == j for i, j in zip(filter_parts, blob_parts)): | |
| return True | |
| return False | |
| class BaseIndexEntryHelper(NamedTuple): | |
| """Typed named tuple to provide named attribute access for :class:`BaseIndexEntry`. | |
| This is needed to allow overriding ``__new__`` in child class to preserve backwards | |
| compatibility. | |
| """ | |
| mode: int | |
| binsha: bytes | |
| flags: int | |
| path: PathLike | |
| ctime_bytes: bytes = pack(">LL", 0, 0) | |
| mtime_bytes: bytes = pack(">LL", 0, 0) | |
| dev: int = 0 | |
| inode: int = 0 | |
| uid: int = 0 | |
| gid: int = 0 | |
| size: int = 0 | |
| class BaseIndexEntry(BaseIndexEntryHelper): | |
| R"""Small brother of an index entry which can be created to describe changes | |
| done to the index in which case plenty of additional information is not required. | |
| As the first 4 data members match exactly to the :class:`IndexEntry` type, methods | |
| expecting a :class:`BaseIndexEntry` can also handle full :class:`IndexEntry`\s even | |
| if they use numeric indices for performance reasons. | |
| """ | |
| def __new__( | |
| cls, | |
| inp_tuple: Union[ | |
| Tuple[int, bytes, int, PathLike], | |
| Tuple[int, bytes, int, PathLike, bytes, bytes, int, int, int, int, int], | |
| ], | |
| ) -> "BaseIndexEntry": | |
| """Override ``__new__`` to allow construction from a tuple for backwards | |
| compatibility.""" | |
| return super().__new__(cls, *inp_tuple) | |
| def __str__(self) -> str: | |
| return "%o %s %i\t%s" % (self.mode, self.hexsha, self.stage, self.path) | |
| def __repr__(self) -> str: | |
| return "(%o, %s, %i, %s)" % (self.mode, self.hexsha, self.stage, self.path) | |
| def hexsha(self) -> str: | |
| """hex version of our sha""" | |
| return b2a_hex(self.binsha).decode("ascii") | |
| def stage(self) -> int: | |
| """Stage of the entry, either: | |
| * 0 = default stage | |
| * 1 = stage before a merge or common ancestor entry in case of a 3 way merge | |
| * 2 = stage of entries from the 'left' side of the merge | |
| * 3 = stage of entries from the 'right' side of the merge | |
| :note: | |
| For more information, see :manpage:`git-read-tree(1)`. | |
| """ | |
| return (self.flags & CE_STAGEMASK) >> CE_STAGESHIFT | |
| def from_blob(cls, blob: Blob, stage: int = 0) -> "BaseIndexEntry": | |
| """:return: Fully equipped BaseIndexEntry at the given stage""" | |
| return cls((blob.mode, blob.binsha, stage << CE_STAGESHIFT, blob.path)) | |
| def to_blob(self, repo: "Repo") -> Blob: | |
| """:return: Blob using the information of this index entry""" | |
| return Blob(repo, self.binsha, self.mode, self.path) | |
| class IndexEntry(BaseIndexEntry): | |
| """Allows convenient access to index entry data as defined in | |
| :class:`BaseIndexEntry` without completely unpacking it. | |
| Attributes usually accessed often are cached in the tuple whereas others are | |
| unpacked on demand. | |
| See the properties for a mapping between names and tuple indices. | |
| """ | |
| def ctime(self) -> Tuple[int, int]: | |
| """ | |
| :return: | |
| Tuple(int_time_seconds_since_epoch, int_nano_seconds) of the | |
| file's creation time | |
| """ | |
| return cast(Tuple[int, int], unpack(">LL", self.ctime_bytes)) | |
| def mtime(self) -> Tuple[int, int]: | |
| """See :attr:`ctime` property, but returns modification time.""" | |
| return cast(Tuple[int, int], unpack(">LL", self.mtime_bytes)) | |
| def from_base(cls, base: "BaseIndexEntry") -> "IndexEntry": | |
| """ | |
| :return: | |
| Minimal entry as created from the given :class:`BaseIndexEntry` instance. | |
| Missing values will be set to null-like values. | |
| :param base: | |
| Instance of type :class:`BaseIndexEntry`. | |
| """ | |
| time = pack(">LL", 0, 0) | |
| return IndexEntry((base.mode, base.binsha, base.flags, base.path, time, time, 0, 0, 0, 0, 0)) | |
| def from_blob(cls, blob: Blob, stage: int = 0) -> "IndexEntry": | |
| """:return: Minimal entry resembling the given blob object""" | |
| time = pack(">LL", 0, 0) | |
| return IndexEntry( | |
| ( | |
| blob.mode, | |
| blob.binsha, | |
| stage << CE_STAGESHIFT, | |
| blob.path, | |
| time, | |
| time, | |
| 0, | |
| 0, | |
| 0, | |
| 0, | |
| blob.size, | |
| ) | |
| ) | |