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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# 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
import objects
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.
See the properties for a mapping between names and tuple indices.
"""
@property
def path(self):
return self[0]
@property
def ctime(self):
"""
Returns
Tuple(int_time_seconds_since_epoch, int_nano_seconds) of the
file's creation time
"""
return struct.unpack(">LL", self[1])
@property
def mtime(self):
"""
See ctime property, but returns modification time
"""
return struct.unpack(">LL", self[2])
@property
def dev(self):
return self[3]
@property
def inode(self):
return self[4]
@property
def mode(self):
return self[5]
@property
def uid(self):
return self[6]
@property
def gid(self):
return self[7]
@property
def data_size(self):
return self[8]
@property
def sha(self):
return self[9]
@property
def path_size(self):
return self[10]
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" )
|