|
7 | 7 | Module containing Index implementation, allowing to perform all kinds of index
|
8 | 8 | manipulations such as querying and merging.
|
9 | 9 | """
|
| 10 | +importstruct |
| 11 | +importbinascii |
| 12 | +importmmap |
| 13 | + |
| 14 | +classIndexEntry(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 | +""" |
10 | 21 |
|
11 | 22 | classIndex(object):
|
12 | 23 | """
|
13 | 24 | Implements an Index that can be manipulated using a native implementation in
|
14 |
| -order tosafe git command function calls wherever possible. |
| 25 | +order tosave git command function calls wherever possible. |
15 | 26 |
|
16 | 27 | It provides custom merging facilities and to create custom commits.
|
17 | 28 | """
|
| 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 | +ifstreamisnotNone: |
| 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 | +returnIndexEntry((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 | +iftype_id!="DIRC": |
| 63 | +raiseAssertionError("Invalid index file header: %r"%type_id) |
| 64 | +version,num_entries=struct.unpack(">LL",stream.read(4*2)) |
| 65 | +assertversionin (1,2) |
| 66 | +returnversion,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 | +whilecount<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 | +deffrom_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 | +exceptException: |
| 97 | +pass |
| 98 | +# END memory mapping |
| 99 | + |
| 100 | +try: |
| 101 | +returncls(stream) |
| 102 | +finally: |
| 103 | +fp.close() |
| 104 | + |
| 105 | +defwrite(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 | +raiseNotImplementedError("TODO" ) |