Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/git/objects/base.py: 42%
89 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1# base.py
2# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3#
4# This module is part of GitPython and is released under
5# the BSD License: http://www.opensource.org/licenses/bsd-license.php
7from git.exc import WorkTreeRepositoryUnsupported
8from git.util import LazyMixin, join_path_native, stream_copy, bin_to_hex
10import gitdb.typ as dbtyp
11import os.path as osp
13from .util import get_object_type_by_name
16# typing ------------------------------------------------------------------
18from typing import Any, TYPE_CHECKING, Union
20from git.types import PathLike, Commit_ish, Lit_commit_ish
22if TYPE_CHECKING: 22 ↛ 23line 22 didn't jump to line 23, because the condition on line 22 was never true
23 from git.repo import Repo
24 from gitdb.base import OStream
25 from .tree import Tree
26 from .blob import Blob
27 from .submodule.base import Submodule
28 from git.refs.reference import Reference
30IndexObjUnion = Union["Tree", "Blob", "Submodule"]
32# --------------------------------------------------------------------------
35_assertion_msg_format = "Created object %r whose python type %r disagrees with the actual git object type %r"
37__all__ = ("Object", "IndexObject")
40class Object(LazyMixin):
42 """Implements an Object which may be Blobs, Trees, Commits and Tags"""
44 NULL_HEX_SHA = "0" * 40
45 NULL_BIN_SHA = b"\0" * 20
47 TYPES = (
48 dbtyp.str_blob_type,
49 dbtyp.str_tree_type,
50 dbtyp.str_commit_type,
51 dbtyp.str_tag_type,
52 )
53 __slots__ = ("repo", "binsha", "size")
54 type: Union[Lit_commit_ish, None] = None
56 def __init__(self, repo: "Repo", binsha: bytes):
57 """Initialize an object by identifying it by its binary sha.
58 All keyword arguments will be set on demand if None.
60 :param repo: repository this object is located in
62 :param binsha: 20 byte SHA1"""
63 super(Object, self).__init__()
64 self.repo = repo
65 self.binsha = binsha
66 assert len(binsha) == 20, "Require 20 byte binary sha, got %r, len = %i" % (
67 binsha,
68 len(binsha),
69 )
71 @classmethod
72 def new(cls, repo: "Repo", id: Union[str, "Reference"]) -> Commit_ish:
73 """
74 :return: New Object instance of a type appropriate to the object type behind
75 id. The id of the newly created object will be a binsha even though
76 the input id may have been a Reference or Rev-Spec
78 :param id: reference, rev-spec, or hexsha
80 :note: This cannot be a __new__ method as it would always call __init__
81 with the input id which is not necessarily a binsha."""
82 return repo.rev_parse(str(id))
84 @classmethod
85 def new_from_sha(cls, repo: "Repo", sha1: bytes) -> Commit_ish:
86 """
87 :return: new object instance of a type appropriate to represent the given
88 binary sha1
89 :param sha1: 20 byte binary sha1"""
90 if sha1 == cls.NULL_BIN_SHA:
91 # the NULL binsha is always the root commit
92 return get_object_type_by_name(b"commit")(repo, sha1)
93 # END handle special case
94 oinfo = repo.odb.info(sha1)
95 inst = get_object_type_by_name(oinfo.type)(repo, oinfo.binsha)
96 inst.size = oinfo.size
97 return inst
99 def _set_cache_(self, attr: str) -> None:
100 """Retrieve object information"""
101 if attr == "size":
102 oinfo = self.repo.odb.info(self.binsha)
103 self.size = oinfo.size # type: int
104 # assert oinfo.type == self.type, _assertion_msg_format % (self.binsha, oinfo.type, self.type)
105 else:
106 super(Object, self)._set_cache_(attr)
108 def __eq__(self, other: Any) -> bool:
109 """:return: True if the objects have the same SHA1"""
110 if not hasattr(other, "binsha"):
111 return False
112 return self.binsha == other.binsha
114 def __ne__(self, other: Any) -> bool:
115 """:return: True if the objects do not have the same SHA1"""
116 if not hasattr(other, "binsha"):
117 return True
118 return self.binsha != other.binsha
120 def __hash__(self) -> int:
121 """:return: Hash of our id allowing objects to be used in dicts and sets"""
122 return hash(self.binsha)
124 def __str__(self) -> str:
125 """:return: string of our SHA1 as understood by all git commands"""
126 return self.hexsha
128 def __repr__(self) -> str:
129 """:return: string with pythonic representation of our object"""
130 return '<git.%s "%s">' % (self.__class__.__name__, self.hexsha)
132 @property
133 def hexsha(self) -> str:
134 """:return: 40 byte hex version of our 20 byte binary sha"""
135 # b2a_hex produces bytes
136 return bin_to_hex(self.binsha).decode("ascii")
138 @property
139 def data_stream(self) -> "OStream":
140 """:return: File Object compatible stream to the uncompressed raw data of the object
141 :note: returned streams must be read in order"""
142 return self.repo.odb.stream(self.binsha)
144 def stream_data(self, ostream: "OStream") -> "Object":
145 """Writes our data directly to the given output stream
146 :param ostream: File object compatible stream object.
147 :return: self"""
148 istream = self.repo.odb.stream(self.binsha)
149 stream_copy(istream, ostream)
150 return self
153class IndexObject(Object):
155 """Base for all objects that can be part of the index file , namely Tree, Blob and
156 SubModule objects"""
158 __slots__ = ("path", "mode")
160 # for compatibility with iterable lists
161 _id_attribute_ = "path"
163 def __init__(
164 self,
165 repo: "Repo",
166 binsha: bytes,
167 mode: Union[None, int] = None,
168 path: Union[None, PathLike] = None,
169 ) -> None:
170 """Initialize a newly instanced IndexObject
172 :param repo: is the Repo we are located in
173 :param binsha: 20 byte sha1
174 :param mode:
175 is the stat compatible file mode as int, use the stat module
176 to evaluate the information
177 :param path:
178 is the path to the file in the file system, relative to the git repository root, i.e.
179 file.ext or folder/other.ext
180 :note:
181 Path may not be set of the index object has been created directly as it cannot
182 be retrieved without knowing the parent tree."""
183 super(IndexObject, self).__init__(repo, binsha)
184 if mode is not None:
185 self.mode = mode
186 if path is not None:
187 self.path = path
189 def __hash__(self) -> int:
190 """
191 :return:
192 Hash of our path as index items are uniquely identifiable by path, not
193 by their data !"""
194 return hash(self.path)
196 def _set_cache_(self, attr: str) -> None:
197 if attr in IndexObject.__slots__:
198 # they cannot be retrieved lateron ( not without searching for them )
199 raise AttributeError(
200 "Attribute '%s' unset: path and mode attributes must have been set during %s object creation"
201 % (attr, type(self).__name__)
202 )
203 else:
204 super(IndexObject, self)._set_cache_(attr)
205 # END handle slot attribute
207 @property
208 def name(self) -> str:
209 """:return: Name portion of the path, effectively being the basename"""
210 return osp.basename(self.path)
212 @property
213 def abspath(self) -> PathLike:
214 """
215 :return:
216 Absolute path to this index object in the file system ( as opposed to the
217 .path field which is a path relative to the git repository ).
219 The returned path will be native to the system and contains '\' on windows."""
220 if self.repo.working_tree_dir is not None:
221 return join_path_native(self.repo.working_tree_dir, self.path)
222 else:
223 raise WorkTreeRepositoryUnsupported("Working_tree_dir was None or empty")