Skip to content

Commit 50a9920

Browse files
committed
Added initial version of the index reading from file - IndexEntry interface is to be improved though, writing needs to be implemented as well
1 parent 4a534eb commit 50a9920

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-2
lines changed

lib/git/index.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,109 @@
77
Module containing Index implementation, allowing to perform all kinds of index
88
manipulations such as querying and merging.
99
"""
10+
import struct
11+
import binascii
12+
import mmap
13+
14+
class IndexEntry(tuple):
15+
"""
16+
Allows convenient access to IndexEntry data without completely unpacking it.
17+
18+
Attributes usully accessed often are cached in the tuple whereas others are
19+
unpacked on demand.
20+
"""
1021

1122
class Index(object):
1223
"""
1324
Implements an Index that can be manipulated using a native implementation in
14-
order to safe git command function calls wherever possible.
25+
order to save git command function calls wherever possible.
1526
1627
It provides custom merging facilities and to create custom commits.
1728
"""
29+
__slots__ = ( "version", "entries" )
30+
31+
def __init__(self, stream = None):
32+
"""
33+
Initialize this Index instance, optionally from the given ``stream``
34+
35+
Note
36+
Reading is based on the dulwich project.
37+
"""
38+
self.entries = dict()
39+
self.version = -1
40+
if stream is not None:
41+
self._read_from_stream(stream)
42+
43+
def _read_entry(self, stream):
44+
"""Return: One entry of the given stream"""
45+
beginoffset = stream.tell()
46+
ctime = struct.unpack(">8s", stream.read(8))[0]
47+
mtime = struct.unpack(">8s", stream.read(8))[0]
48+
(dev, ino, mode, uid, gid, size, sha, flags) = \
49+
struct.unpack(">LLLLLL20sH", stream.read(20 + 4 * 6 + 2))
50+
path_size = flags & 0x0fff
51+
path = stream.read(path_size)
52+
53+
real_size = ((stream.tell() - beginoffset + 8) & ~7)
54+
data = stream.read((beginoffset + real_size) - stream.tell())
55+
return IndexEntry((path, ctime, mtime, dev, ino, mode, uid, gid, size,
56+
binascii.hexlify(sha), path_size))
57+
58+
59+
def _read_header(self, stream):
60+
"""Return tuple(version_long, num_entries) from the given stream"""
61+
type_id = stream.read(4)
62+
if type_id != "DIRC":
63+
raise AssertionError("Invalid index file header: %r" % type_id)
64+
version, num_entries = struct.unpack(">LL", stream.read(4 * 2))
65+
assert version in (1, 2)
66+
return version, num_entries
67+
68+
def _read_from_stream(self, stream):
69+
"""
70+
Initialize this instance with index values read from the given stream
71+
"""
72+
self.version, num_entries = self._read_header(stream)
73+
self.entries = dict()
74+
count = 0
75+
while count < num_entries:
76+
entry = self._read_entry(stream)
77+
self.entries[entry[0]] = entry[1:]
78+
count += 1
79+
# END for each entry
80+
81+
@classmethod
82+
def from_file(cls, file_path):
83+
"""
84+
Returns
85+
Index instance as recreated from the given stream.
86+
87+
``file_pa ``
88+
File path pointing to git index file
89+
"""
90+
fp = open(file_path, "r")
91+
92+
# try memory map for speed
93+
stream = fp
94+
try:
95+
stream = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)
96+
except Exception:
97+
pass
98+
# END memory mapping
99+
100+
try:
101+
return cls(stream)
102+
finally:
103+
fp.close()
104+
105+
def write(self, stream):
106+
"""
107+
Write the current state to the given stream
108+
109+
``stream``
110+
File-like object
111+
112+
Returns
113+
self
114+
"""
115+
raise NotImplementedError( "TODO" )

test/fixtures/index

160 KB
Binary file not shown.

test/git/test_index.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ def setUpAll(cls):
1414
cls.repo = Repo(GIT_REPO)
1515

1616
def test_base(self):
17-
self.fail("TODO")
17+
index = Index.from_file(fixture_path("index"))
18+
assert index.entries
19+
assert index.version > 0

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy