# index.py # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php """ Module containing Index implementation, allowing to perform all kinds of index manipulations such as querying and merging. """ import struct import binascii import mmap class IndexEntry(tuple): """ Allows convenient access to IndexEntry data without completely unpacking it. Attributes usully accessed often are cached in the tuple whereas others are unpacked on demand. """ class Index(object): """ Implements an Index that can be manipulated using a native implementation in order to save git command function calls wherever possible. It provides custom merging facilities and to create custom commits. """ __slots__ = ( "version", "entries" ) def __init__(self, stream = None): """ Initialize this Index instance, optionally from the given ``stream`` Note Reading is based on the dulwich project. """ self.entries = dict() self.version = -1 if stream is not None: self._read_from_stream(stream) def _read_entry(self, stream): """Return: One entry of the given stream""" beginoffset = stream.tell() ctime = struct.unpack(">8s", stream.read(8))[0] mtime = struct.unpack(">8s", stream.read(8))[0] (dev, ino, mode, uid, gid, size, sha, flags) = \ struct.unpack(">LLLLLL20sH", stream.read(20 + 4 * 6 + 2)) path_size = flags & 0x0fff path = stream.read(path_size) real_size = ((stream.tell() - beginoffset + 8) & ~7) data = stream.read((beginoffset + real_size) - stream.tell()) return IndexEntry((path, ctime, mtime, dev, ino, mode, uid, gid, size, binascii.hexlify(sha), path_size)) def _read_header(self, stream): """Return tuple(version_long, num_entries) from the given stream""" type_id = stream.read(4) if type_id != "DIRC": raise AssertionError("Invalid index file header: %r" % type_id) version, num_entries = struct.unpack(">LL", stream.read(4 * 2)) assert version in (1, 2) return version, num_entries def _read_from_stream(self, stream): """ Initialize this instance with index values read from the given stream """ self.version, num_entries = self._read_header(stream) self.entries = dict() count = 0 while count < num_entries: entry = self._read_entry(stream) self.entries[entry[0]] = entry[1:] count += 1 # END for each entry @classmethod def from_file(cls, file_path): """ Returns Index instance as recreated from the given stream. ``file_pa `` File path pointing to git index file """ fp = open(file_path, "r") # try memory map for speed stream = fp try: stream = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) except Exception: pass # END memory mapping try: return cls(stream) finally: fp.close() def write(self, stream): """ Write the current state to the given stream ``stream`` File-like object Returns self """ raise NotImplementedError( "TODO" )