summaryrefslogtreecommitdiff
path: root/lib/git/index/fun.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git/index/fun.py')
-rw-r--r--lib/git/index/fun.py73
1 files changed, 66 insertions, 7 deletions
diff --git a/lib/git/index/fun.py b/lib/git/index/fun.py
index 2e653ea6..557941d5 100644
--- a/lib/git/index/fun.py
+++ b/lib/git/index/fun.py
@@ -2,6 +2,11 @@
Contains standalone functions to accompany the index implementation and make it
more versatile
"""
+from stat import S_IFDIR
+from cStringIO import StringIO
+
+from git.errors import UnmergedEntriesError
+from git.objects.fun import tree_to_stream
from git.utils import (
IndexFileSHA1Writer,
)
@@ -16,12 +21,11 @@ from util import (
unpack
)
-from binascii import (
- hexlify,
- unhexlify
- )
+from gitdb.base import IStream
+from gitdb.typ import str_tree_type
+from binascii import a2b_hex
-__all__ = ('write_cache', 'read_cache' )
+__all__ = ('write_cache', 'read_cache', 'write_tree_from_cache', 'entry_key' )
def write_cache_entry(entry, stream):
"""Write the given entry to the stream"""
@@ -34,7 +38,7 @@ def write_cache_entry(entry, stream):
assert plen == len(path), "Path %s too long to fit into index" % entry[3]
flags = plen | entry[2]
write(pack(">LLLLLL20sH", entry[6], entry[7], entry[0],
- entry[8], entry[9], entry[10], unhexlify(entry[1]), flags))
+ entry[8], entry[9], entry[10], entry[1], flags))
write(path)
real_size = ((stream.tell() - beginoffset + 8) & ~7)
write("\0" * ((beginoffset + real_size) - stream.tell()))
@@ -80,7 +84,7 @@ def read_entry(stream):
real_size = ((stream.tell() - beginoffset + 8) & ~7)
data = stream.read((beginoffset + real_size) - stream.tell())
- return IndexEntry((mode, hexlify(sha), flags, path, ctime, mtime, dev, ino, uid, gid, size))
+ return IndexEntry((mode, sha, flags, path, ctime, mtime, dev, ino, uid, gid, size))
def read_header(stream):
"""Return tuple(version_long, num_entries) from the given stream"""
@@ -136,3 +140,58 @@ def read_cache(stream):
return (version, entries, extension_data, content_sha)
+def write_tree_from_cache(entries, odb, sl, si=0):
+ """Create a tree from the given sorted list of entries and put the respective
+ trees into the given object database
+ :param entries: **sorted** list of IndexEntries
+ :param odb: object database to store the trees in
+ :param si: start index at which we should start creating subtrees
+ :param sl: slice indicating the range we should process on the entries list
+ :return: tuple(binsha, list(tree_entry, ...)) a tuple of a sha and a list of
+ tree entries being a tuple of hexsha, mode, name"""
+ tree_items = list()
+ ci = sl.start
+ end = sl.stop
+ while ci < end:
+ entry = entries[ci]
+ if entry.stage != 0:
+ raise UnmergedEntriesError(entry)
+ # END abort on unmerged
+ ci += 1
+ rbound = entry.path.find('/', si)
+ if rbound == -1:
+ # its not a tree
+ tree_items.append((entry.binsha, entry.mode, entry.path[si:]))
+ else:
+ # find common base range
+ base = entry.path[si:rbound]
+ xi = ci
+ while xi < end:
+ oentry = entries[xi]
+ xi += 1
+ orbound = oentry.path.find('/')
+ if orbound == -1 or oentry.path[si:orbound] != base:
+ break
+ # END abort on base mismatch
+ # END find common base
+
+ # enter recursion
+ # ci - 1 as we want to count our current item as well
+ sha, tree_entry_list = write_tree_from_cache(entries, odb, slice(ci-1, xi), rbound+1)
+ tree_items.append((sha, S_IFDIR, base))
+
+ # skip ahead
+ ci = xi
+ # END handle bounds
+ # END for each entry
+
+ # finally create the tree
+ sio = StringIO()
+ tree_to_stream(tree_items, sio.write)
+ sio.seek(0)
+
+ istream = odb.store(IStream(str_tree_type, len(sio.getvalue()), sio))
+ return (istream.binsha, tree_items)
+
+
+