# Buggy code
def file_list(self, tgt_env):
    """
    Get file list for the target environment using pygit2
    """

    def _traverse(tree, blobs, prefix):
        """
        Traverse through a pygit2 Tree object recursively, accumulating all
        the file paths and symlink info in the "blobs" dict
        """
        for entry in iter(tree):
            obj = self.repo[entry.oid]
            if isinstance(obj, pygit2.Blob):
                repo_path = os.path.join(prefix, entry.name)
                blobs.setdefault("files", []).append(repo_path)
                if stat.S_ISLNK(tree[entry.name].filemode):
                    link_tgt = self.repo[tree[entry.name].oid].data
                    blobs.setdefault("symlinks", {})[repo_path] = link_tgt
            elif isinstance(obj, pygit2.Tree):
                _traverse(obj, blobs, os.path.join(prefix, entry.name))

    files = set()
    symlinks = {}
    tree = self.get_tree(tgt_env)
    if not tree:
        # Not found, return empty objects
        return files, symlinks
    if self.root:
        try:
            # This might need to be changed to account for a root that
            # spans more than one directory
            oid = tree[self.root].oid
            tree = self.repo[oid]
        except KeyError:
            return files, symlinks
        if not isinstance(tree, pygit2.Tree):
            return files, symlinks
        relpath = lambda path: os.path.relpath(path, self.root)
    else:
        relpath = lambda path: path
    blobs = {}
    if len(tree):
        _traverse(tree, blobs, self.root)
    add_mountpoint = lambda path: os.path.join(self.mountpoint, path)
    for repo_path in blobs.get("files", []):
        files.add(add_mountpoint(relpath(repo_path)))
    for repo_path, link_tgt in six.iteritems(blobs.get("symlinks", {})):
        symlinks[add_mountpoint(relpath(repo_path))] = link_tgt
    return files, symlinks


# Traceback (KeyError)
2015-12-11 17:28:20,418 [salt.master      ][ERROR   ][1255] Error in function _file_list:
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/salt/master.py", line 1379, in run_func
ret = getattr(self, func)(load)
File "/usr/lib/python2.7/dist-packages/salt/fileserver/__init__.py", line 607, in file_list
ret.update(self.servers[fstr](load))
File "/usr/lib/python2.7/dist-packages/salt/fileserver/gitfs.py", line 180, in file_list
return gitfs.file_list(load)
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 2308, in file_list
return self._file_lists(load, 'files')
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 2285, in _file_lists
repo_files, repo_symlinks = repo.file_list(load['saltenv'])
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 1017, in file_list
_traverse(tree, blobs, self.root)
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 994, in _traverse
_traverse(obj, blobs, os.path.join(prefix, entry.name))
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 994, in _traverse
_traverse(obj, blobs, os.path.join(prefix, entry.name))
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 994, in _traverse
_traverse(obj, blobs, os.path.join(prefix, entry.name))
File "/usr/lib/python2.7/dist-packages/salt/utils/gitfs.py", line 986, in _traverse
obj = self.repo[entry.oid]
File "/usr/local/lib/python2.7/dist-packages/pygit2/repository.py", line 99, in __getitem__
raise KeyError(key)
KeyError: f16c3f1b33223c7ab82744fb00e6bbc3f48ce61b

# Fixed code
def file_list(self, tgt_env):
    """
    Get file list for the target environment using pygit2
    """

    def _traverse(tree, blobs, prefix):
        """
        Traverse through a pygit2 Tree object recursively, accumulating all
        the file paths and symlink info in the "blobs" dict
        """
        for entry in iter(tree):
            if entry.oid not in self.repo:
                # Entry is a submodule, skip it
                continue
            obj = self.repo[entry.oid]
            if isinstance(obj, pygit2.Blob):
                repo_path = os.path.join(prefix, entry.name)
                blobs.setdefault("files", []).append(repo_path)
                if stat.S_ISLNK(tree[entry.name].filemode):
                    link_tgt = self.repo[tree[entry.name].oid].data
                    blobs.setdefault("symlinks", {})[repo_path] = link_tgt
            elif isinstance(obj, pygit2.Tree):
                _traverse(obj, blobs, os.path.join(prefix, entry.name))

    files = set()
    symlinks = {}
    tree = self.get_tree(tgt_env)
    if not tree:
        # Not found, return empty objects
        return files, symlinks
    if self.root:
        try:
            # This might need to be changed to account for a root that
            # spans more than one directory
            oid = tree[self.root].oid
            tree = self.repo[oid]
        except KeyError:
            return files, symlinks
        if not isinstance(tree, pygit2.Tree):
            return files, symlinks
        relpath = lambda path: os.path.relpath(path, self.root)
    else:
        relpath = lambda path: path
    blobs = {}
    if len(tree):
        _traverse(tree, blobs, self.root)
    add_mountpoint = lambda path: os.path.join(self.mountpoint, path)
    for repo_path in blobs.get("files", []):
        files.add(add_mountpoint(relpath(repo_path)))
    for repo_path, link_tgt in six.iteritems(blobs.get("symlinks", {})):
        symlinks[add_mountpoint(relpath(repo_path))] = link_tgt
    return files, symlinks