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