1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# 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" )
|