Given a sha id of an object a pack index can tell you the location in the
packfile of that object if it has it.
+ """
+
+ def __eq__(self, other):
+ if not isinstance(other, PackIndex):
+ return False
+
+ for (name1, _, _), (name2, _, _) in izip(self.iterentries(),
+ other.iterentries()):
+ if name1 != name2:
+ return False
+ return True
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __len__(self):
+ """Return the number of entries in this pack index."""
+ raise NotImplementedError(self.__len__)
+
+ def __iter__(self):
+ """Iterate over the SHAs in this pack."""
+ raise NotImplementedError(self.__iter__)
+
+ def iterentries(self):
+ """Iterate over the entries in this pack index.
+
+ :return: iterator over tuples with object name, offset in packfile and
+ crc32 checksum.
+ """
+ raise NotImplementedError(self.iterentries)
+
+ def get_pack_checksum(self):
+ """Return the SHA1 checksum stored for the corresponding packfile.
+
+ :return: 20-byte binary digest
+ """
+ raise NotImplementedError(self.get_pack_checksum)
+
+ def object_index(self, sha):
+ """Return the index in to the corresponding packfile for the object.
+
+ Given the name of an object it will return the offset that object
+ lives at within the corresponding pack file. If the pack file doesn't
+ have the object then None will be returned.
+ """
+ if len(sha) == 40:
+ sha = hex_to_sha(sha)
+ return self._object_index(sha)
+
+ def _object_index(self, sha):
+ """See object_index.
+
+ :param sha: A *binary* SHA string. (20 characters long)_
+ """
+ raise NotImplementedError(self._object_index)
+
+
+class FilePackIndex(PackIndex):
+ """Pack index that is based on a file.
To do the loop it opens the file, and indexes first 256 4 byte groups
with the first byte of the sha id. The value in the four byte group indexed
self._contents, self._size = (contents, size)
def __eq__(self, other):
- if not isinstance(other, PackIndex):
+ # Quick optimization:
+ if isinstance(other, FilePackIndex) and self._fan_out_table != other._fan_out_table:
return False
- if self._fan_out_table != other._fan_out_table:
- return False
-
- for (name1, _, _), (name2, _, _) in izip(self.iterentries(),
- other.iterentries()):
- if name1 != name2:
- return False
- return True
-
- def __ne__(self, other):
- return not self.__eq__(other)
+ return super(FilePackIndex, self).__eq__(other)
def close(self):
self._file.close()
"""
return str(self._contents[-20:])
- def object_index(self, sha):
- """Return the index in to the corresponding packfile for the object.
-
- Given the name of an object it will return the offset that object
- lives at within the corresponding pack file. If the pack file doesn't
- have the object then None will be returned.
- """
- if len(sha) == 40:
- sha = hex_to_sha(sha)
- return self._object_index(sha)
-
def _object_index(self, sha):
"""See object_index.
return self._unpack_offset(i)
-class PackIndex1(PackIndex):
- """Version 1 Pack Index."""
+class PackIndex1(FilePackIndex):
+ """Version 1 Pack Index file."""
def __init__(self, filename, file=None, contents=None, size=None):
- PackIndex.__init__(self, filename, file, contents, size)
+ super(PackIndex1, self).__init__(filename, file, contents, size)
self.version = 1
self._fan_out_table = self._read_fan_out_table(0)
return None
-class PackIndex2(PackIndex):
- """Version 2 Pack Index."""
+class PackIndex2(FilePackIndex):
+ """Version 2 Pack Index file."""
def __init__(self, filename, file=None, contents=None, size=None):
- PackIndex.__init__(self, filename, file, contents, size)
+ super(PackIndex2, self).__init__(filename, file, contents, size)
assert self._contents[:4] == '\377tOc', "Not a v2 pack index file"
(self.version, ) = unpack_from(">L", self._contents, 4)
assert self.version == 2, "Version was %d" % self.version