Skip to content

Commit dba71a0

Browse files
committed
Initial version of objects. The submodule implementation is left in git-python for now as it requires plenty of additional features which are currently only available via the git command
1 parent 7c4d3d6 commit dba71a0

15 files changed

+1910
-0
lines changed

gitdb/object/__init__.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Import all submodules main classes into the package space
3+
"""
4+
import inspect
5+
6+
from base import *
7+
from tag import *
8+
from blob import *
9+
from commit import *
10+
from tree import *
11+
from submodule import *
12+
13+
__all__ = [ name for name, obj in locals().items()
14+
if not (name.startswith('_') or inspect.ismodule(obj)) ]

gitdb/object/base.py

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# base.py
2+
# Copyright (C) 2008, 2009 Michael Trier ([email protected]) 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
6+
from util import get_object_type_by_name
7+
from gitdb.util import (
8+
hex_to_bin,
9+
bin_to_hex,
10+
basename,
11+
LazyMixin,
12+
join_path_native,
13+
stream_copy
14+
)
15+
16+
from gitdb.typ import ObjectType
17+
18+
_assertion_msg_format = "Created object %r whose python type %r disagrees with the acutal git object type %r"
19+
20+
__all__ = ("Object", "IndexObject")
21+
22+
class Object(LazyMixin):
23+
"""Implements an Object which may be Blobs, Trees, Commits and Tags"""
24+
NULL_HEX_SHA = '0'*40
25+
NULL_BIN_SHA = '\0'*20
26+
27+
TYPES = (ObjectType.blob, ObjectType.tree, ObjectType.commit, ObjectType.tag)
28+
__slots__ = ("odb", "binsha", "size" )
29+
30+
type = None # to be set by subclass
31+
type_id = None # to be set by subclass
32+
33+
def __init__(self, odb, binsha):
34+
"""Initialize an object by identifying it by its binary sha.
35+
All keyword arguments will be set on demand if None.
36+
37+
:param odb: repository this object is located in
38+
39+
:param binsha: 20 byte SHA1"""
40+
super(Object,self).__init__()
41+
self.odb = odb
42+
self.binsha = binsha
43+
assert len(binsha) == 20, "Require 20 byte binary sha, got %r, len = %i" % (binsha, len(binsha))
44+
45+
@classmethod
46+
def new(cls, odb, id):
47+
"""
48+
:return: New Object instance of a type appropriate to the object type behind
49+
id. The id of the newly created object will be a binsha even though
50+
the input id may have been a Reference or Rev-Spec
51+
52+
:param id: reference, rev-spec, or hexsha
53+
54+
:note: This cannot be a __new__ method as it would always call __init__
55+
with the input id which is not necessarily a binsha."""
56+
return odb.rev_parse(str(id))
57+
58+
@classmethod
59+
def new_from_sha(cls, odb, sha1):
60+
"""
61+
:return: new object instance of a type appropriate to represent the given
62+
binary sha1
63+
:param sha1: 20 byte binary sha1"""
64+
if sha1 == cls.NULL_BIN_SHA:
65+
# the NULL binsha is always the root commit
66+
return get_object_type_by_name('commit')(odb, sha1)
67+
#END handle special case
68+
oinfo = odb.odb.info(sha1)
69+
inst = get_object_type_by_name(oinfo.type)(odb, oinfo.binsha)
70+
inst.size = oinfo.size
71+
return inst
72+
73+
def _set_cache_(self, attr):
74+
"""Retrieve object information"""
75+
if attr == "size":
76+
oinfo = self.odb.odb.info(self.binsha)
77+
self.size = oinfo.size
78+
# assert oinfo.type == self.type, _assertion_msg_format % (self.binsha, oinfo.type, self.type)
79+
else:
80+
super(Object,self)._set_cache_(attr)
81+
82+
def __eq__(self, other):
83+
""":return: True if the objects have the same SHA1"""
84+
return self.binsha == other.binsha
85+
86+
def __ne__(self, other):
87+
""":return: True if the objects do not have the same SHA1 """
88+
return self.binsha != other.binsha
89+
90+
def __hash__(self):
91+
""":return: Hash of our id allowing objects to be used in dicts and sets"""
92+
return hash(self.binsha)
93+
94+
def __str__(self):
95+
""":return: string of our SHA1 as understood by all git commands"""
96+
return bin_to_hex(self.binsha)
97+
98+
def __repr__(self):
99+
""":return: string with pythonic representation of our object"""
100+
return '<git.%s "%s">' % (self.__class__.__name__, self.hexsha)
101+
102+
@property
103+
def hexsha(self):
104+
""":return: 40 byte hex version of our 20 byte binary sha"""
105+
return bin_to_hex(self.binsha)
106+
107+
@property
108+
def data_stream(self):
109+
""" :return: File Object compatible stream to the uncompressed raw data of the object
110+
:note: returned streams must be read in order"""
111+
return self.odb.odb.stream(self.binsha)
112+
113+
def stream_data(self, ostream):
114+
"""Writes our data directly to the given output stream
115+
:param ostream: File object compatible stream object.
116+
:return: self"""
117+
istream = self.odb.odb.stream(self.binsha)
118+
stream_copy(istream, ostream)
119+
return self
120+
121+
122+
class IndexObject(Object):
123+
"""Base for all objects that can be part of the index file , namely Tree, Blob and
124+
SubModule objects"""
125+
__slots__ = ("path", "mode")
126+
127+
# for compatability with iterable lists
128+
_id_attribute_ = 'path'
129+
130+
def __init__(self, odb, binsha, mode=None, path=None):
131+
"""Initialize a newly instanced IndexObject
132+
:param odb: is the Repo we are located in
133+
:param binsha: 20 byte sha1
134+
:param mode: is the stat compatible file mode as int, use the stat module
135+
to evaluate the infomration
136+
:param path:
137+
is the path to the file in the file system, relative to the git repository root, i.e.
138+
file.ext or folder/other.ext
139+
:note:
140+
Path may not be set of the index object has been created directly as it cannot
141+
be retrieved without knowing the parent tree."""
142+
super(IndexObject, self).__init__(odb, binsha)
143+
if mode is not None:
144+
self.mode = mode
145+
if path is not None:
146+
self.path = path
147+
148+
def __hash__(self):
149+
""":return:
150+
Hash of our path as index items are uniquely identifyable by path, not
151+
by their data !"""
152+
return hash(self.path)
153+
154+
def _set_cache_(self, attr):
155+
if attr in IndexObject.__slots__:
156+
# they cannot be retrieved lateron ( not without searching for them )
157+
raise AttributeError( "path and mode attributes must have been set during %s object creation" % type(self).__name__ )
158+
else:
159+
super(IndexObject, self)._set_cache_(attr)
160+
# END hanlde slot attribute
161+
162+
@property
163+
def name(self):
164+
""":return: Name portion of the path, effectively being the basename"""
165+
return basename(self.path)
166+
167+
@property
168+
def abspath(self):
169+
"""
170+
:return:
171+
Absolute path to this index object in the file system ( as opposed to the
172+
.path field which is a path relative to the git repository ).
173+
174+
The returned path will be native to the system and contains '\' on windows. """
175+
return join_path_native(self.odb.working_tree_dir, self.path)
176+

gitdb/object/blob.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# blob.py
2+
# Copyright (C) 2008, 2009 Michael Trier ([email protected]) 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
6+
7+
from mimetypes import guess_type
8+
from gitdb.typ import ObjectType
9+
import base
10+
11+
__all__ = ('Blob', )
12+
13+
class Blob(base.IndexObject):
14+
"""A Blob encapsulates a git blob object"""
15+
DEFAULT_MIME_TYPE = "text/plain"
16+
type = ObjectType.blob
17+
type_id = ObjectType.blob_id
18+
19+
# valid blob modes
20+
executable_mode = 0100755
21+
file_mode = 0100644
22+
link_mode = 0120000
23+
24+
__slots__ = tuple()
25+
26+
@property
27+
def mime_type(self):
28+
"""
29+
:return: String describing the mime type of this file (based on the filename)
30+
:note: Defaults to 'text/plain' in case the actual file type is unknown. """
31+
guesses = None
32+
if self.path:
33+
guesses = guess_type(self.path)
34+
return guesses and guesses[0] or self.DEFAULT_MIME_TYPE

0 commit comments

Comments
 (0)