您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

316 行
7.8KB

  1. # Copyright (C) 2010, 2011 Sebastian Thiel (byronimo@gmail.com) and contributors
  2. #
  3. # This module is part of GitDB and is released under
  4. # the New BSD License: http://www.opensource.org/licenses/bsd-license.php
  5. """Module with basic data structures - they are designed to be lightweight and fast"""
  6. from gitdb.util import bin_to_hex
  7. from gitdb.fun import (
  8. type_id_to_type_map,
  9. type_to_type_id_map
  10. )
  11. __all__ = ('OInfo', 'OPackInfo', 'ODeltaPackInfo',
  12. 'OStream', 'OPackStream', 'ODeltaPackStream',
  13. 'IStream', 'InvalidOInfo', 'InvalidOStream')
  14. #{ ODB Bases
  15. class OInfo(tuple):
  16. """Carries information about an object in an ODB, providing information
  17. about the binary sha of the object, the type_string as well as the uncompressed size
  18. in bytes.
  19. It can be accessed using tuple notation and using attribute access notation::
  20. assert dbi[0] == dbi.binsha
  21. assert dbi[1] == dbi.type
  22. assert dbi[2] == dbi.size
  23. The type is designed to be as lightweight as possible."""
  24. __slots__ = tuple()
  25. def __new__(cls, sha, type, size):
  26. return tuple.__new__(cls, (sha, type, size))
  27. def __init__(self, *args):
  28. tuple.__init__(self)
  29. #{ Interface
  30. @property
  31. def binsha(self):
  32. """:return: our sha as binary, 20 bytes"""
  33. return self[0]
  34. @property
  35. def hexsha(self):
  36. """:return: our sha, hex encoded, 40 bytes"""
  37. return bin_to_hex(self[0])
  38. @property
  39. def type(self):
  40. return self[1]
  41. @property
  42. def type_id(self):
  43. return type_to_type_id_map[self[1]]
  44. @property
  45. def size(self):
  46. return self[2]
  47. #} END interface
  48. class OPackInfo(tuple):
  49. """As OInfo, but provides a type_id property to retrieve the numerical type id, and
  50. does not include a sha.
  51. Additionally, the pack_offset is the absolute offset into the packfile at which
  52. all object information is located. The data_offset property points to the absolute
  53. location in the pack at which that actual data stream can be found."""
  54. __slots__ = tuple()
  55. def __new__(cls, packoffset, type, size):
  56. return tuple.__new__(cls, (packoffset, type, size))
  57. def __init__(self, *args):
  58. tuple.__init__(self)
  59. #{ Interface
  60. @property
  61. def pack_offset(self):
  62. return self[0]
  63. @property
  64. def type(self):
  65. return type_id_to_type_map[self[1]]
  66. @property
  67. def type_id(self):
  68. return self[1]
  69. @property
  70. def size(self):
  71. return self[2]
  72. #} END interface
  73. class ODeltaPackInfo(OPackInfo):
  74. """Adds delta specific information,
  75. Either the 20 byte sha which points to some object in the database,
  76. or the negative offset from the pack_offset, so that pack_offset - delta_info yields
  77. the pack offset of the base object"""
  78. __slots__ = tuple()
  79. def __new__(cls, packoffset, type, size, delta_info):
  80. return tuple.__new__(cls, (packoffset, type, size, delta_info))
  81. #{ Interface
  82. @property
  83. def delta_info(self):
  84. return self[3]
  85. #} END interface
  86. class OStream(OInfo):
  87. """Base for object streams retrieved from the database, providing additional
  88. information about the stream.
  89. Generally, ODB streams are read-only as objects are immutable"""
  90. __slots__ = tuple()
  91. def __new__(cls, sha, type, size, stream, *args, **kwargs):
  92. """Helps with the initialization of subclasses"""
  93. return tuple.__new__(cls, (sha, type, size, stream))
  94. def __init__(self, *args, **kwargs):
  95. tuple.__init__(self)
  96. #{ Stream Reader Interface
  97. def read(self, size=-1):
  98. return self[3].read(size)
  99. @property
  100. def stream(self):
  101. return self[3]
  102. #} END stream reader interface
  103. class ODeltaStream(OStream):
  104. """Uses size info of its stream, delaying reads"""
  105. def __new__(cls, sha, type, size, stream, *args, **kwargs):
  106. """Helps with the initialization of subclasses"""
  107. return tuple.__new__(cls, (sha, type, size, stream))
  108. #{ Stream Reader Interface
  109. @property
  110. def size(self):
  111. return self[3].size
  112. #} END stream reader interface
  113. class OPackStream(OPackInfo):
  114. """Next to pack object information, a stream outputting an undeltified base object
  115. is provided"""
  116. __slots__ = tuple()
  117. def __new__(cls, packoffset, type, size, stream, *args):
  118. """Helps with the initialization of subclasses"""
  119. return tuple.__new__(cls, (packoffset, type, size, stream))
  120. #{ Stream Reader Interface
  121. def read(self, size=-1):
  122. return self[3].read(size)
  123. @property
  124. def stream(self):
  125. return self[3]
  126. #} END stream reader interface
  127. class ODeltaPackStream(ODeltaPackInfo):
  128. """Provides a stream outputting the uncompressed offset delta information"""
  129. __slots__ = tuple()
  130. def __new__(cls, packoffset, type, size, delta_info, stream):
  131. return tuple.__new__(cls, (packoffset, type, size, delta_info, stream))
  132. #{ Stream Reader Interface
  133. def read(self, size=-1):
  134. return self[4].read(size)
  135. @property
  136. def stream(self):
  137. return self[4]
  138. #} END stream reader interface
  139. class IStream(list):
  140. """Represents an input content stream to be fed into the ODB. It is mutable to allow
  141. the ODB to record information about the operations outcome right in this instance.
  142. It provides interfaces for the OStream and a StreamReader to allow the instance
  143. to blend in without prior conversion.
  144. The only method your content stream must support is 'read'"""
  145. __slots__ = tuple()
  146. def __new__(cls, type, size, stream, sha=None):
  147. return list.__new__(cls, (sha, type, size, stream, None))
  148. def __init__(self, type, size, stream, sha=None):
  149. list.__init__(self, (sha, type, size, stream, None))
  150. #{ Interface
  151. @property
  152. def hexsha(self):
  153. """:return: our sha, hex encoded, 40 bytes"""
  154. return bin_to_hex(self[0])
  155. def _error(self):
  156. """:return: the error that occurred when processing the stream, or None"""
  157. return self[4]
  158. def _set_error(self, exc):
  159. """Set this input stream to the given exc, may be None to reset the error"""
  160. self[4] = exc
  161. error = property(_error, _set_error)
  162. #} END interface
  163. #{ Stream Reader Interface
  164. def read(self, size=-1):
  165. """Implements a simple stream reader interface, passing the read call on
  166. to our internal stream"""
  167. return self[3].read(size)
  168. #} END stream reader interface
  169. #{ interface
  170. def _set_binsha(self, binsha):
  171. self[0] = binsha
  172. def _binsha(self):
  173. return self[0]
  174. binsha = property(_binsha, _set_binsha)
  175. def _type(self):
  176. return self[1]
  177. def _set_type(self, type):
  178. self[1] = type
  179. type = property(_type, _set_type)
  180. def _size(self):
  181. return self[2]
  182. def _set_size(self, size):
  183. self[2] = size
  184. size = property(_size, _set_size)
  185. def _stream(self):
  186. return self[3]
  187. def _set_stream(self, stream):
  188. self[3] = stream
  189. stream = property(_stream, _set_stream)
  190. #} END odb info interface
  191. class InvalidOInfo(tuple):
  192. """Carries information about a sha identifying an object which is invalid in
  193. the queried database. The exception attribute provides more information about
  194. the cause of the issue"""
  195. __slots__ = tuple()
  196. def __new__(cls, sha, exc):
  197. return tuple.__new__(cls, (sha, exc))
  198. def __init__(self, sha, exc):
  199. tuple.__init__(self, (sha, exc))
  200. @property
  201. def binsha(self):
  202. return self[0]
  203. @property
  204. def hexsha(self):
  205. return bin_to_hex(self[0])
  206. @property
  207. def error(self):
  208. """:return: exception instance explaining the failure"""
  209. return self[1]
  210. class InvalidOStream(InvalidOInfo):
  211. """Carries information about an invalid ODB stream"""
  212. __slots__ = tuple()
  213. #} END ODB Bases