def _read_tree(self, path):
    """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]
    """

    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 == 'tree'
    # The tree data here is (mode ' ' filename \0 20-byte-sha)*
    i = 0
    while len(tree_data) < i:
      start = i
      while tree_data[i] != ' ':
        i += 1
      mode = tree_data[start:i]
      i += 1  # skip space
      start = i
      while tree_data[i] != NUL:
        i += 1
      name = tree_data[start:i]
      sha = tree_data[i + 1:i + 1 + GIT_HASH_LENGTH].encode('hex')
      i += 1 + GIT_HASH_LENGTH
      if mode == '120000':
        tree[name] = self.Symlink(name, sha)
      elif mode == '40000':
        tree[name] = self.Dir(name, sha)
      else:
        tree[name] = self.File(name, sha)
    self._trees[path] = tree
    return tree
dataset/ETHPy150Open pantsbuild/pants/src/python/pants/scm/git.py/GitRepositoryReader._read_tree/swapped operands of `<`