diff options
-rw-r--r-- | git/index/fun.py | 17 | ||||
-rw-r--r-- | git/index/typ.py | 81 |
2 files changed, 38 insertions, 60 deletions
diff --git a/git/index/fun.py b/git/index/fun.py index 3b963a2b..49e3f2c5 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -57,6 +57,7 @@ from git.types import PathLike if TYPE_CHECKING: from .base import IndexFile + from git.db import GitCmdObjectDB from git.objects.tree import TreeCacheTup # from git.objects.fun import EntryTupOrNone @@ -149,15 +150,15 @@ def write_cache(entries: Sequence[Union[BaseIndexEntry, 'IndexEntry']], stream: # body for entry in entries: beginoffset = tell() - write(entry[4]) # ctime - write(entry[5]) # mtime - path_str: str = entry[3] + write(entry.ctime_bytes) # ctime + write(entry.mtime_bytes) # mtime + path_str = str(entry.path) path: bytes = force_bytes(path_str, encoding=defenc) plen = len(path) & CE_NAMEMASK # path length - assert plen == len(path), "Path %s too long to fit into index" % entry[3] - flags = plen | (entry[2] & CE_NAMEMASK_INV) # clear possible previous values - write(pack(">LLLLLL20sH", entry[6], entry[7], entry[0], - entry[8], entry[9], entry[10], entry[1], flags)) + assert plen == len(path), "Path %s too long to fit into index" % entry.path + flags = plen | (entry.flags & CE_NAMEMASK_INV) # clear possible previous values + write(pack(">LLLLLL20sH", entry.dev, entry.inode, entry.mode, + entry.uid, entry.gid, entry.size, entry.binsha, flags)) write(path) real_size = ((tell() - beginoffset + 8) & ~7) write(b"\0" * ((beginoffset + real_size) - tell())) @@ -311,7 +312,7 @@ def _tree_entry_to_baseindexentry(tree_entry: 'TreeCacheTup', stage: int) -> Bas return BaseIndexEntry((tree_entry[1], tree_entry[0], stage << CE_STAGESHIFT, tree_entry[2])) -def aggressive_tree_merge(odb, tree_shas: Sequence[bytes]) -> List[BaseIndexEntry]: +def aggressive_tree_merge(odb: 'GitCmdObjectDB', tree_shas: Sequence[bytes]) -> List[BaseIndexEntry]: """ :return: list of BaseIndexEntries representing the aggressive merge of the given trees. All valid entries are on stage 0, whereas the conflicting ones are left diff --git a/git/index/typ.py b/git/index/typ.py index bb1a0384..5b2ad5f6 100644 --- a/git/index/typ.py +++ b/git/index/typ.py @@ -11,7 +11,7 @@ from git.objects import Blob # typing ---------------------------------------------------------------------- -from typing import (List, Sequence, TYPE_CHECKING, Tuple, cast) +from typing import (NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast) from git.types import PathLike @@ -59,7 +59,23 @@ class BlobFilter(object): return False -class BaseIndexEntry(tuple): +class BaseIndexEntryHelper(NamedTuple): + """Typed namedtuple to provide named attribute access for BaseIndexEntry. + Needed to allow overriding __new__ in child class to preserve backwards compat.""" + 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): """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. @@ -68,6 +84,12 @@ class BaseIndexEntry(tuple): expecting a BaseIndexEntry can also handle full IndexEntries 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) @@ -75,19 +97,9 @@ class BaseIndexEntry(tuple): return "(%o, %s, %i, %s)" % (self.mode, self.hexsha, self.stage, self.path) @property - def mode(self) -> int: - """ File Mode, compatible to stat module constants """ - return self[0] - - @property - def binsha(self) -> bytes: - """binary sha of the blob """ - return self[1] - - @property def hexsha(self) -> str: """hex version of our sha""" - return b2a_hex(self[1]).decode('ascii') + return b2a_hex(self.binsha).decode('ascii') @property def stage(self) -> int: @@ -100,17 +112,7 @@ class BaseIndexEntry(tuple): :note: For more information, see http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html """ - return (self[2] & CE_STAGEMASK) >> CE_STAGESHIFT - - @property - def path(self) -> str: - """:return: our path relative to the repository working tree root""" - return self[3] - - @property - def flags(self) -> List[str]: - """:return: flags stored with this entry""" - return self[2] + return (self.flags & CE_STAGEMASK) >> CE_STAGESHIFT @classmethod def from_blob(cls, blob: Blob, stage: int = 0) -> 'BaseIndexEntry': @@ -136,40 +138,15 @@ class IndexEntry(BaseIndexEntry): :return: Tuple(int_time_seconds_since_epoch, int_nano_seconds) of the file's creation time""" - return cast(Tuple[int, int], unpack(">LL", self[4])) + return cast(Tuple[int, int], unpack(">LL", self.ctime_bytes)) @property def mtime(self) -> Tuple[int, int]: """See ctime property, but returns modification time """ - return cast(Tuple[int, int], unpack(">LL", self[5])) - - @property - def dev(self) -> int: - """ Device ID """ - return self[6] - - @property - def inode(self) -> int: - """ Inode ID """ - return self[7] - - @property - def uid(self) -> int: - """ User ID """ - return self[8] - - @property - def gid(self) -> int: - """ Group ID """ - return self[9] - - @property - def size(self) -> int: - """:return: Uncompressed size of the blob """ - return self[10] + return cast(Tuple[int, int], unpack(">LL", self.mtime_bytes)) @classmethod - def from_base(cls, base): + def from_base(cls, base: 'BaseIndexEntry') -> 'IndexEntry': """ :return: Minimal entry as created from the given BaseIndexEntry instance. |