code: def _read_tree(self, path):
      
  
      path = self._fixup_dot_relative(path)
  
      tree = self._trees.get(path)
      if tree:
        return tree
      tree = {}
      object_type, tree_data = self._read_object_from_repo(rev=self.rev, relpath=path)
      assert object_type == b'tree'
      # The tree data here is (mode ' ' filename \0 20-byte-sha)*
      # It's transformed to a list of byte chars to allow iteration.
      # See http://python-future.org/compatible_idioms.html#byte-string-literals.
      tree_data = [bytes([b]) for b in tree_data]
      i = 0
      while i < len(tree_data):
        start = i
        while tree_data[i] != b' ':
          i += 1
        mode = b''.join(tree_data[start:i])
        i += 1  # skip space
        start = i
        while tree_data[i] != NUL:
          i += 1
        name = b''.join(tree_data[start:i])
        sha = b''.join(tree_data[i + 1:i + 1 + GIT_HASH_LENGTH])
        sha_hex = binascii.hexlify(sha)
        i += 1 + GIT_HASH_LENGTH
        if mode == b'120000':
          tree[name] = self.Symlink(name, sha_hex)
        elif mode == b'40000':
          tree[name] = self.Dir(name, sha_hex)
        else:
          tree[name] = self.File(name, sha_hex)
      self._trees[path] = tree
      return tree
docs: Given a revision and path, parse the tree data out of git cat-file output.
  
      :returns: a dict from filename -> [list of Symlink, Dir, and File objects]