Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork966
Expand file tree
/
Copy pathbase.py
More file actions
301 lines (235 loc) · 10 KB
/
base.py
File metadata and controls
301 lines (235 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under the
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
__all__= ["Object","IndexObject"]
importos.pathasosp
importgitdb.typasdbtyp
fromgit.excimportWorkTreeRepositoryUnsupported
fromgit.utilimportLazyMixin,bin_to_hex,join_path_native,stream_copy
from .utilimportget_object_type_by_name
# typing ------------------------------------------------------------------
fromtypingimportAny,TYPE_CHECKING,Union
fromgit.typesimportAnyGitObject,GitObjectTypeString,PathLike
ifTYPE_CHECKING:
fromgitdb.baseimportOStream
fromgit.refs.referenceimportReference
fromgit.repoimportRepo
from .blobimportBlob
from .submodule.baseimportSubmodule
from .treeimportTree
IndexObjUnion=Union["Tree","Blob","Submodule"]
# --------------------------------------------------------------------------
classObject(LazyMixin):
"""Base class for classes representing git object types.
The following four leaf classes represent specific kinds of git objects:
* :class:`Blob <git.objects.blob.Blob>`
* :class:`Tree <git.objects.tree.Tree>`
* :class:`Commit <git.objects.commit.Commit>`
* :class:`TagObject <git.objects.tag.TagObject>`
See :manpage:`gitglossary(7)` on:
* "object": https://git-scm.com/docs/gitglossary#def_object
* "object type": https://git-scm.com/docs/gitglossary#def_object_type
* "blob": https://git-scm.com/docs/gitglossary#def_blob_object
* "tree object": https://git-scm.com/docs/gitglossary#def_tree_object
* "commit object": https://git-scm.com/docs/gitglossary#def_commit_object
* "tag object": https://git-scm.com/docs/gitglossary#def_tag_object
:note:
See the :class:`~git.types.AnyGitObject` union type of the four leaf subclasses
that represent actual git object types.
:note:
:class:`~git.objects.submodule.base.Submodule` is defined under the hierarchy
rooted at this :class:`Object` class, even though submodules are not really a
type of git object. (This also applies to its
:class:`~git.objects.submodule.root.RootModule` subclass.)
:note:
This :class:`Object` class should not be confused with :class:`object` (the root
of the class hierarchy in Python).
"""
NULL_HEX_SHA="0"*40
NULL_BIN_SHA=b"\0"*20
TYPES= (
dbtyp.str_blob_type,
dbtyp.str_tree_type,
dbtyp.str_commit_type,
dbtyp.str_tag_type,
)
__slots__= ("repo","binsha","size")
type:Union[GitObjectTypeString,None]=None
"""String identifying (a concrete :class:`Object` subtype for) a git object type.
The subtypes that this may name correspond to the kinds of git objects that exist,
i.e., the objects that may be present in a git repository.
:note:
Most subclasses represent specific types of git objects and override this class
attribute accordingly. This attribute is ``None`` in the :class:`Object` base
class, as well as the :class:`IndexObject` intermediate subclass, but never
``None`` in concrete leaf subclasses representing specific git object types.
:note:
See also :class:`~git.types.GitObjectTypeString`.
"""
def__init__(self,repo:"Repo",binsha:bytes)->None:
"""Initialize an object by identifying it by its binary sha.
All keyword arguments will be set on demand if ``None``.
:param repo:
Repository this object is located in.
:param binsha:
20 byte SHA1
"""
super().__init__()
self.repo=repo
self.binsha=binsha
assertlen(binsha)==20,"Require 20 byte binary sha, got %r, len = %i"% (
binsha,
len(binsha),
)
@classmethod
defnew(cls,repo:"Repo",id:Union[str,"Reference"])->AnyGitObject:
"""
:return:
New :class:`Object` instance of a type appropriate to the object type behind
`id`. The id of the newly created object will be a binsha even though the
input id may have been a :class:`~git.refs.reference.Reference` or rev-spec.
:param id:
:class:`~git.refs.reference.Reference`, rev-spec, or hexsha.
:note:
This cannot be a ``__new__`` method as it would always call :meth:`__init__`
with the input id which is not necessarily a binsha.
"""
returnrepo.rev_parse(str(id))
@classmethod
defnew_from_sha(cls,repo:"Repo",sha1:bytes)->AnyGitObject:
"""
:return:
New object instance of a type appropriate to represent the given binary sha1
:param sha1:
20 byte binary sha1.
"""
ifsha1==cls.NULL_BIN_SHA:
# The NULL binsha is always the root commit.
returnget_object_type_by_name(b"commit")(repo,sha1)
# END handle special case
oinfo=repo.odb.info(sha1)
inst=get_object_type_by_name(oinfo.type)(repo,oinfo.binsha)
inst.size=oinfo.size
returninst
def_set_cache_(self,attr:str)->None:
"""Retrieve object information."""
ifattr=="size":
oinfo=self.repo.odb.info(self.binsha)
self.size=oinfo.size# type: int
else:
super()._set_cache_(attr)
def__eq__(self,other:Any)->bool:
""":return: ``True`` if the objects have the same SHA1"""
ifnothasattr(other,"binsha"):
returnFalse
returnself.binsha==other.binsha
def__ne__(self,other:Any)->bool:
""":return: ``True`` if the objects do not have the same SHA1"""
ifnothasattr(other,"binsha"):
returnTrue
returnself.binsha!=other.binsha
def__hash__(self)->int:
""":return: Hash of our id allowing objects to be used in dicts and sets"""
returnhash(self.binsha)
def__str__(self)->str:
""":return: String of our SHA1 as understood by all git commands"""
returnself.hexsha
def__repr__(self)->str:
""":return: String with pythonic representation of our object"""
return'<git.%s "%s">'% (self.__class__.__name__,self.hexsha)
@property
defhexsha(self)->str:
""":return: 40 byte hex version of our 20 byte binary sha"""
# b2a_hex produces bytes.
returnbin_to_hex(self.binsha).decode("ascii")
@property
defdata_stream(self)->"OStream":
"""
:return:
File-object compatible stream to the uncompressed raw data of the object
:note:
Returned streams must be read in order.
"""
returnself.repo.odb.stream(self.binsha)
defstream_data(self,ostream:"OStream")->"Object":
"""Write our data directly to the given output stream.
:param ostream:
File-object compatible stream object.
:return:
self
"""
istream=self.repo.odb.stream(self.binsha)
stream_copy(istream,ostream)
returnself
classIndexObject(Object):
"""Base for all objects that can be part of the index file.
The classes representing git object types that can be part of the index file are
:class:`~git.objects.tree.Tree` and :class:`~git.objects.blob.Blob`. In addition,
:class:`~git.objects.submodule.base.Submodule`, which is not really a git object
type but can be part of an index file, is also a subclass.
"""
__slots__= ("path","mode")
# For compatibility with iterable lists.
_id_attribute_="path"
def__init__(
self,
repo:"Repo",
binsha:bytes,
mode:Union[None,int]=None,
path:Union[None,PathLike]=None,
)->None:
"""Initialize a newly instanced :class:`IndexObject`.
:param repo:
The :class:`~git.repo.base.Repo` we are located in.
:param binsha:
20 byte sha1.
:param mode:
The stat-compatible file mode as :class:`int`.
Use the :mod:`stat` module to evaluate the information.
:param path:
The path to the file in the file system, relative to the git repository
root, like ``file.ext`` or ``folder/other.ext``.
:note:
Path may not be set if the index object has been created directly, as it
cannot be retrieved without knowing the parent tree.
"""
super().__init__(repo,binsha)
ifmodeisnotNone:
self.mode=mode
ifpathisnotNone:
self.path=path
def__hash__(self)->int:
"""
:return:
Hash of our path as index items are uniquely identifiable by path, not by
their data!
"""
returnhash(self.path)
def_set_cache_(self,attr:str)->None:
ifattrinIndexObject.__slots__:
# They cannot be retrieved later on (not without searching for them).
raiseAttributeError(
"Attribute '%s' unset: path and mode attributes must have been set during %s object creation"
% (attr,type(self).__name__)
)
else:
super()._set_cache_(attr)
# END handle slot attribute
@property
defname(self)->str:
""":return: Name portion of the path, effectively being the basename"""
returnosp.basename(self.path)
@property
defabspath(self)->PathLike:
R"""
:return:
Absolute path to this index object in the file system (as opposed to the
:attr:`path` field which is a path relative to the git repository).
The returned path will be native to the system and contains ``\`` on
Windows.
"""
ifself.repo.working_tree_dirisnotNone:
returnjoin_path_native(self.repo.working_tree_dir,self.path)
else:
raiseWorkTreeRepositoryUnsupported("working_tree_dir was None or empty")