summaryrefslogtreecommitdiff
path: root/lib/git/objects/tree.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git/objects/tree.py')
-rw-r--r--lib/git/objects/tree.py60
1 files changed, 34 insertions, 26 deletions
diff --git a/lib/git/objects/tree.py b/lib/git/objects/tree.py
index abfa9622..27bd84d0 100644
--- a/lib/git/objects/tree.py
+++ b/lib/git/objects/tree.py
@@ -8,6 +8,7 @@ import os
import blob
import base
import binascii
+import git.diff as diff
def sha_to_hex(sha):
"""Takes a string and returns the hex of the sha within"""
@@ -15,7 +16,7 @@ def sha_to_hex(sha):
assert len(hexsha) == 40, "Incorrect length of sha1 string: %d" % hexsha
return hexsha
-class Tree(base.IndexObject):
+class Tree(base.IndexObject, diff.Diffable):
"""
Tress represent a ordered list of Blobs and other Trees. Hence it can be
accessed like a list.
@@ -37,13 +38,14 @@ class Tree(base.IndexObject):
__slots__ = "_cache"
# using ascii codes for comparison
- ascii_commit_id = (0x31 << 4) + 0x36
- ascii_blob_id = (0x31 << 4) + 0x30
- ascii_tree_id = (0x34 << 4) + 0x30
+ commit_id = 016
+ blob_id = 010
+ symlink_id = 012
+ tree_id = 040
- def __init__(self, repo, id, mode=0, path=None):
- super(Tree, self).__init__(repo, id, mode, path)
+ def __init__(self, repo, sha, mode=0, path=None):
+ super(Tree, self).__init__(repo, sha, mode, path)
def _set_cache_(self, attr):
if attr == "_cache":
@@ -87,8 +89,8 @@ class Tree(base.IndexObject):
mode = 0
mode_boundary = i + 6
- # keep it ascii - we compare against the respective values
- type_id = (ord(data[i])<<4) + ord(data[i+1])
+ # read type
+ type_id = ((ord(data[i])-ord_zero)<<3) + (ord(data[i+1])-ord_zero)
i += 2
while data[i] != ' ':
@@ -108,18 +110,20 @@ class Tree(base.IndexObject):
i += 1
# END while not reached NULL
name = data[ns:i]
+ path = os.path.join(self.path, name)
# byte is NULL, get next 20
i += 1
sha = data[i:i+20]
i = i + 20
+ mode |= type_id<<12
hexsha = sha_to_hex(sha)
- if type_id == self.ascii_blob_id:
- yield blob.Blob(self.repo, hexsha, mode, name)
- elif type_id == self.ascii_tree_id:
- yield Tree(self.repo, hexsha, mode, name)
- elif type_id == self.ascii_commit_id:
+ if type_id == self.blob_id or type_id == self.symlink_id:
+ yield blob.Blob(self.repo, hexsha, mode, path)
+ elif type_id == self.tree_id:
+ yield Tree(self.repo, hexsha, mode, path)
+ elif type_id == self.commit_id:
# todo
yield None
else:
@@ -148,29 +152,28 @@ class Tree(base.IndexObject):
def __repr__(self):
- return '<git.Tree "%s">' % self.id
+ return '<git.Tree "%s">' % self.sha
@classmethod
- def _iter_recursive(cls, repo, tree, cur_depth, max_depth, predicate ):
+ def _iter_recursive(cls, repo, tree, cur_depth, max_depth, predicate, prune ):
for obj in tree:
- # adjust path to be complete
- obj.path = os.path.join(tree.path, obj.path)
- if not predicate(obj):
- continue
- yield obj
- if obj.type == "tree" and ( max_depth < 0 or cur_depth+1 <= max_depth ):
- for recursive_obj in cls._iter_recursive( repo, obj, cur_depth+1, max_depth, predicate ):
+ if predicate(obj):
+ yield obj
+ if obj.type == "tree" and ( max_depth < 0 or cur_depth+1 <= max_depth ) and not prune(obj):
+ for recursive_obj in cls._iter_recursive( repo, obj, cur_depth+1, max_depth, predicate, prune ):
yield recursive_obj
# END for each recursive object
# END if we may enter recursion
# END for each object
- def traverse(self, max_depth=-1, predicate = lambda i: True):
+ def traverse(self, max_depth=-1, predicate = lambda i: True, prune = lambda t: False):
"""
Returns
+
Iterator to traverse the tree recursively up to the given level.
- The iterator returns Blob and Tree objects
+ The iterator returns Blob and Tree objects with paths relative to their
+ repository.
``max_depth``
@@ -181,8 +184,13 @@ class Tree(base.IndexObject):
``predicate``
If predicate(item) returns True, item will be returned by iterator
+
+ ``prune``
+
+ If prune(tree) returns True, the traversal will not continue into the
+ given tree object.
"""
- return self._iter_recursive( self.repo, self, 0, max_depth, predicate )
+ return self._iter_recursive( self.repo, self, 0, max_depth, predicate, prune )
@property
def trees(self):
@@ -218,7 +226,7 @@ class Tree(base.IndexObject):
if isinstance(item, basestring):
# compatability
for obj in self._cache:
- if obj.path == item:
+ if obj.name == item:
return obj
# END for each obj
raise KeyError( "Blob or Tree named %s not found" % item )