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

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

77 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 

35# } END invariants 

36 

37 

38class BlobFilter: 

39 """Predicate to be used by 

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

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

42 

43 The given paths are given relative to the repository. 

44 """ 

45 

46 __slots__ = ("paths",) 

47 

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

49 """ 

50 :param paths: 

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

52 relative to the current repository. 

53 """ 

54 self.paths = paths 

55 

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

57 blob_pathlike: PathLike = stage_blob[1].path 

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

59 for pathlike in self.paths: 

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

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

62 # longer supported. 

63 filter_parts = path.parts 

64 blob_parts = blob_path.parts 

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

66 continue 

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

68 return True 

69 return False 

70 

71 

72class BaseIndexEntryHelper(NamedTuple): 

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

74 

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

76 compatibility. 

77 """ 

78 

79 mode: int 

80 binsha: bytes 

81 flags: int 

82 path: PathLike 

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

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

85 dev: int = 0 

86 inode: int = 0 

87 uid: int = 0 

88 gid: int = 0 

89 size: int = 0 

90 

91 

92class BaseIndexEntry(BaseIndexEntryHelper): 

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

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

95 

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

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

98 if they use numeric indices for performance reasons. 

99 """ 

100 

101 def __new__( 

102 cls, 

103 inp_tuple: Union[ 

104 Tuple[int, bytes, int, PathLike], 

105 Tuple[int, bytes, int, PathLike, bytes, bytes, int, int, int, int, int], 

106 ], 

107 ) -> "BaseIndexEntry": 

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

109 compatibility.""" 

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

111 

112 def __str__(self) -> str: 

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

114 

115 def __repr__(self) -> str: 

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

117 

118 @property 

119 def hexsha(self) -> str: 

120 """hex version of our sha""" 

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

122 

123 @property 

124 def stage(self) -> int: 

125 """Stage of the entry, either: 

126 

127 * 0 = default stage 

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

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

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

131 

132 :note: 

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

134 """ 

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

136 

137 @classmethod 

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

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

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

141 

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

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

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

145 

146 

147class IndexEntry(BaseIndexEntry): 

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

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

150 

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

152 unpacked on demand. 

153 

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

155 """ 

156 

157 @property 

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

159 """ 

160 :return: 

161 Tuple(int_time_seconds_since_epoch, int_nano_seconds) of the 

162 file's creation time 

163 """ 

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

165 

166 @property 

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

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

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

170 

171 @classmethod 

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

173 """ 

174 :return: 

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

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

177 

178 :param base: 

179 Instance of type :class:`BaseIndexEntry`. 

180 """ 

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

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

183 

184 @classmethod 

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

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

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

188 return IndexEntry( 

189 ( 

190 blob.mode, 

191 blob.binsha, 

192 stage << CE_STAGESHIFT, 

193 blob.path, 

194 time, 

195 time, 

196 0, 

197 0, 

198 0, 

199 0, 

200 blob.size, 

201 ) 

202 )