index.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # index.py -- File parser/write for the git index file
  2. # Copryight (C) 2008 Jelmer Vernooij <jelmer@samba.org>
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; version 2
  6. # of the License or (at your opinion) any later version of the license.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  16. # MA 02110-1301, USA.
  17. """Parser for the git index file format."""
  18. import struct
  19. def read_cache_time(f):
  20. return struct.unpack(">LL", f.read(8))
  21. def write_cache_time(f, t):
  22. f.write(struct.pack(">LL", *t))
  23. def read_cache_entry(f):
  24. beginoffset = f.tell()
  25. ctime = read_cache_time(f)
  26. mtime = read_cache_time(f)
  27. (ino, dev, mode, uid, gid, size, sha, flags, ) = \
  28. struct.unpack(">LLLLLL20sH", f.read(20 + 4 * 6 + 2))
  29. name = ""
  30. char = ord(f.read(1))
  31. while char != 0:
  32. name += chr(char)
  33. char = ord(f.read(1))
  34. # Padding:
  35. real_size = ((f.tell() - beginoffset + 8) & ~7)
  36. f.seek(beginoffset + real_size)
  37. return (name, ctime, mtime, ino, dev, mode, uid, gid, size, sha, flags)
  38. def write_cache_entry(f, entry):
  39. beginoffset = f.tell()
  40. (name, ctime, mtime, ino, dev, mode, uid, gid, size, sha, flags) = entry
  41. write_cache_time(f, ctime)
  42. write_cache_time(f, mtime)
  43. f.write(struct.pack(">LLLLLL20sH", ino, dev, mode, uid, gid, size, sha, flags))
  44. f.write(name)
  45. f.write(chr(0))
  46. real_size = ((f.tell() - beginoffset + 8) & ~7)
  47. f.write(chr(0) * (f.tell() - (beginoffset + real_size)))
  48. return
  49. def read_index(f):
  50. assert f.read(4) == "DIRC"
  51. (version, num_entries) = struct.unpack(">LL", f.read(4 * 2))
  52. assert version in (1, 2)
  53. for i in range(num_entries):
  54. yield read_cache_entry(f)
  55. def write_index(f, entries):
  56. f.write("DIRC")
  57. f.write(struct.pack(">LL", 2, len(entries)))
  58. for x in entries:
  59. write_cache_entry(f, x)
  60. class Index(object):
  61. def __init__(self, filename):
  62. self._entries = []
  63. f = open(filename, 'r')
  64. self._byname = {}
  65. try:
  66. for x in read_index(f):
  67. self._entries.append(x)
  68. self._byname[x[0]] = x
  69. finally:
  70. f.close()
  71. def __len__(self):
  72. return len(self._entries)
  73. def items(self):
  74. return list(self._entries)
  75. def __iter__(self):
  76. return iter(self._entries)
  77. def __getitem__(self, name):
  78. return self._byname[name]