Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/git/index/typ.py: 72%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

87 statements  

1# This module is part of GitPython and is released under the 

2# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/ 

3 

4"""Additional types used by the index.""" 

5 

6__all__ = ["BlobFilter", "BaseIndexEntry", "IndexEntry", "StageType"] 

7 

8from binascii import b2a_hex 

9from pathlib import Path 

10 

11from git.objects import Blob 

12 

13from .util import pack, unpack 

14 

15# typing ---------------------------------------------------------------------- 

16 

17from typing import NamedTuple, Sequence, TYPE_CHECKING, Tuple, Union, cast 

18 

19from git.types import PathLike 

20 

21if TYPE_CHECKING: 

22 from git.repo import Repo 

23 

24StageType = int 

25 

26# --------------------------------------------------------------------------------- 

27 

28# { Invariants 

29CE_NAMEMASK = 0x0FFF 

30CE_STAGEMASK = 0x3000 

31CE_EXTENDED = 0x4000 

32CE_VALID = 0x8000 

33CE_STAGESHIFT = 12 

34 

35CE_EXT_SKIP_WORKTREE = 0x4000 

36CE_EXT_INTENT_TO_ADD = 0x2000 

37 

38# } END invariants 

39 

40 

41class BlobFilter: 

42 """Predicate to be used by 

43 :meth:`IndexFile.iter_blobs <git.index.base.IndexFile.iter_blobs>` allowing to 

44 filter only return blobs which match the given list of directories or files. 

45 

46 The given paths are given relative to the repository. 

47 """ 

48 

49 __slots__ = ("paths",) 

50 

51 def __init__(self, paths: Sequence[PathLike]) -> None: 

52 """ 

53 :param paths: 

54 Tuple or list of paths which are either pointing to directories or to files 

55 relative to the current repository. 

56 """ 

57 self.paths = paths 

58 

59 def __call__(self, stage_blob: Tuple[StageType, Blob]) -> bool: 

60 blob_pathlike: PathLike = stage_blob[1].path 

61 blob_path: Path = blob_pathlike if isinstance(blob_pathlike, Path) else Path(blob_pathlike) 

62 for pathlike in self.paths: 

63 path: Path = pathlike if isinstance(pathlike, Path) else Path(pathlike) 

64 # TODO: Change to use `PosixPath.is_relative_to` once Python 3.8 is no 

65 # longer supported. 

66 filter_parts = path.parts 

67 blob_parts = blob_path.parts 

68 if len(filter_parts) > len(blob_parts): 

69 continue 

70 if all(i == j for i, j in zip(filter_parts, blob_parts)): 

71 return True 

72 return False 

73 

74 

75class BaseIndexEntryHelper(NamedTuple): 

76 """Typed named tuple to provide named attribute access for :class:`BaseIndexEntry`. 

77 

78 This is needed to allow overriding ``__new__`` in child class to preserve backwards 

79 compatibility. 

80 """ 

81 

82 mode: int 

83 binsha: bytes 

84 flags: int 

85 path: PathLike 

86 ctime_bytes: bytes = pack(">LL", 0, 0) 

87 mtime_bytes: bytes = pack(">LL", 0, 0) 

88 dev: int = 0 

89 inode: int = 0 

90 uid: int = 0 

91 gid: int = 0 

92 size: int = 0 

93 # version 3 extended flags, only when (flags & CE_EXTENDED) is set 

94 extended_flags: int = 0 

95 

96 

97class BaseIndexEntry(BaseIndexEntryHelper): 

98 R"""Small brother of an index entry which can be created to describe changes 

99 done to the index in which case plenty of additional information is not required. 

100 

101 As the first 4 data members match exactly to the :class:`IndexEntry` type, methods 

102 expecting a :class:`BaseIndexEntry` can also handle full :class:`IndexEntry`\s even 

103 if they use numeric indices for performance reasons. 

104 """ 

105 

106 def __new__( 

107 cls, 

108 inp_tuple: Union[ 

109 Tuple[int, bytes, int, PathLike], 

110 Tuple[int, bytes, int, PathLike, bytes, bytes, int, int, int, int, int, int], 

111 ], 

112 ) -> "BaseIndexEntry": 

113 """Override ``__new__`` to allow construction from a tuple for backwards 

114 compatibility.""" 

115 return super().__new__(cls, *inp_tuple) 

116 

117 def __str__(self) -> str: 

118 return "%o %s %i\t%s" % (self.mode, self.hexsha, self.stage, self.path) 

119 

120 def __repr__(self) -> str: 

121 return "(%o, %s, %i, %s)" % (self.mode, self.hexsha, self.stage, self.path) 

122 

123 @property 

124 def hexsha(self) -> str: 

125 """hex version of our sha""" 

126 return b2a_hex(self.binsha).decode("ascii") 

127 

128 @property 

129 def stage(self) -> int: 

130 """Stage of the entry, either: 

131 

132 * 0 = default stage 

133 * 1 = stage before a merge or common ancestor entry in case of a 3 way merge 

134 * 2 = stage of entries from the 'left' side of the merge 

135 * 3 = stage of entries from the 'right' side of the merge 

136 

137 :note: 

138 For more information, see :manpage:`git-read-tree(1)`. 

139 """ 

140 return (self.flags & CE_STAGEMASK) >> CE_STAGESHIFT 

141 

142 @property 

143 def skip_worktree(self) -> bool: 

144 return (self.extended_flags & CE_EXT_SKIP_WORKTREE) > 0 

145 

146 @property 

147 def intent_to_add(self) -> bool: 

148 return (self.extended_flags & CE_EXT_INTENT_TO_ADD) > 0 

149 

150 @classmethod 

151 def from_blob(cls, blob: Blob, stage: int = 0) -> "BaseIndexEntry": 

152 """:return: Fully equipped BaseIndexEntry at the given stage""" 

153 return cls((blob.mode, blob.binsha, stage << CE_STAGESHIFT, blob.path)) 

154 

155 def to_blob(self, repo: "Repo") -> Blob: 

156 """:return: Blob using the information of this index entry""" 

157 return Blob(repo, self.binsha, self.mode, self.path) 

158 

159 

160class IndexEntry(BaseIndexEntry): 

161 """Allows convenient access to index entry data as defined in 

162 :class:`BaseIndexEntry` without completely unpacking it. 

163 

164 Attributes usually accessed often are cached in the tuple whereas others are 

165 unpacked on demand. 

166 

167 See the properties for a mapping between names and tuple indices. 

168 """ 

169 

170 @property 

171 def ctime(self) -> Tuple[int, int]: 

172 """ 

173 :return: 

174 Tuple(int_time_seconds_since_epoch, int_nano_seconds) of the 

175 file's creation time 

176 """ 

177 return cast(Tuple[int, int], unpack(">LL", self.ctime_bytes)) 

178 

179 @property 

180 def mtime(self) -> Tuple[int, int]: 

181 """See :attr:`ctime` property, but returns modification time.""" 

182 return cast(Tuple[int, int], unpack(">LL", self.mtime_bytes)) 

183 

184 @classmethod 

185 def from_base(cls, base: "BaseIndexEntry") -> "IndexEntry": 

186 """ 

187 :return: 

188 Minimal entry as created from the given :class:`BaseIndexEntry` instance. 

189 Missing values will be set to null-like values. 

190 

191 :param base: 

192 Instance of type :class:`BaseIndexEntry`. 

193 """ 

194 time = pack(">LL", 0, 0) 

195 return IndexEntry((base.mode, base.binsha, base.flags, base.path, time, time, 0, 0, 0, 0, 0)) 

196 

197 @classmethod 

198 def from_blob(cls, blob: Blob, stage: int = 0) -> "IndexEntry": 

199 """:return: Minimal entry resembling the given blob object""" 

200 time = pack(">LL", 0, 0) 

201 return IndexEntry( 

202 ( 

203 blob.mode, 

204 blob.binsha, 

205 stage << CE_STAGESHIFT, 

206 blob.path, 

207 time, 

208 time, 

209 0, 

210 0, 

211 0, 

212 0, 

213 blob.size, 

214 ) 

215 )