import os
from stat import S_IFDIR, S_IFREG, S_IFLNK
from pygit2 import (
    GIT_FILEMODE_TREE, GIT_FILEMODE_BLOB, GIT_FILEMODE_BLOB_EXECUTABLE,
    GIT_FILEMODE_LINK
)

from log import log
from .view import View


class CommitView(View):

    def __init__(self, *args, **kwargs):
        super(CommitView, self).__init__(*args, **kwargs)
        self.commit = self.repo.revparse_single(self.commit_sha1)

    def _get_git_object_type(self, tree, entry_name):
        for e in tree:
            if e.name == entry_name:
                return e.filemode
            elif e.filemode == GIT_FILEMODE_TREE:
                return self._get_git_object_type(self.repo[e.id], entry_name)

    def _get_blob_content(self, tree, blob_name):
        """
        Returns the content of a Blob object with the name <blob_name>.

        :param tree: a commit tree or a simple tree
        :param blob_name: the name of the blob that is being searched for
        :type blob_name: str
        :returns: the content of the blob with the name <blob_name>
        :rtype: str
        """
        for node in tree:
            if node.name == blob_name:
                return self.repo[node.id].data
            elif node.filemode == GIT_FILEMODE_TREE:
                return self._get_blob_content(self.repo[node.id], blob_name)


    def readlink(self, path):
        obj_name = os.path.split(path)[1]
        return self._get_blob_content(self.commit.tree, obj_name)

    def getattr(self, path, fh=None):
        '''
        Returns a dictionary with keys identical to the stat C structure of
        stat(2).

        st_atime, st_mtime and st_ctime should be floats.

        NOTE: There is an incombatibility between Linux and Mac OS X
        concerning st_nlink of directories. Mac OS X counts all files inside
        the directory, while Linux counts only the subdirectories.
        '''

        """
        TODO:
            * Use the rights provided at mount point.
        """
        if path and path != '/':
            obj_name = os.path.split(path)[1]
            obj_type = self._get_git_object_type(self.commit.tree, obj_name)
            if obj_type == GIT_FILEMODE_LINK:
                return dict(st_mode=(S_IFLNK | 0644))
            if obj_type == GIT_FILEMODE_BLOB or\
               obj_type == GIT_FILEMODE_BLOB_EXECUTABLE:
                return dict(st_mode=(S_IFREG | 0644))
            elif obj_type == GIT_FILEMODE_TREE:
                return dict(st_mode=(S_IFDIR | 0755), st_nlink=2)
        return dict(st_mode=(S_IFDIR | 0755), st_nlink=2)

    def opendir(self, path):
        return 0

    def releasedir(self, path, fi):
        pass

    def access(self, path, amode):
        log.info('%s %s', path, amode)
        return 0

    def _get_commit_subtree(self, tree, subtree_name):
        """
        Retrievs from the repo the Tree object with the name <subtree_name>.

        :param tree: a pygit2.Tree instance
        :param subtree_name: the name of the tree that is being searched for.
        :type subtree_name: str
        :returns: a pygit2.Tree instance representig the tree that is was
            searched for.
        """
        for node in tree:
            if node.filemode == GIT_FILEMODE_TREE:
                if node.name == subtree_name:
                    return self.repo[node.id]
                else:
                    return self._get_commit_subtree(self.repo[node.id],
                                                    subtree_name)

    def _get_dir_entries(self, name):
        dir_entries = []
        dir_tree = self.commit.tree

        # If the relative_path is not empty, fetch the git tree corresponding
        # to the directory that we are in.
        tree_name = os.path.split(self.relative_path)[1]
        if tree_name:
            subtree = self._get_commit_subtree(self.commit.tree, tree_name)
            dir_tree = subtree

        [dir_entries.append(entry) for entry in dir_tree]

        return dir_entries

    def readdir(self, path, fh):
        dir_entries = ['.', '..']
        dir_tree = self.commit.tree

        # If the relative_path is not empty, fetch the git tree corresponding
        # to the directory that we are in.
        tree_name = os.path.split(self.relative_path)[1]
        if tree_name:
            subtree = self._get_commit_subtree(self.commit.tree, tree_name)
            dir_tree = subtree

        [dir_entries.append(entry.name) for entry in dir_tree]
        # [dir_entries.append(entry.name) for entry in self.dir_entries]
        return dir_entries


@@ -46,16 +46,41 @@
 S_IFLNK%0A
+from errno import ENOENT%0A
 from pyg
@@ -92,16 +92,16 @@
 mport (%0A
-
     GIT_
@@ -187,16 +187,45 @@
 E_LINK%0A)
+%0Afrom fuse import FuseOSError
 %0A%0Afrom l
@@ -387,16 +387,34 @@
 kwargs)%0A
+%0A        try:%0A    
         
@@ -470,16 +470,79 @@
 it_sha1)
+%0A        except KeyError:%0A            raise FuseOSError(ENOENT)
 %0A%0A    de
@@ -2849,27 +2849,152 @@
 fo('
-%25s %25s', path, amode
+ACCESS')%0A        log.info('PATH: %25s', path)%0A        log.info('RELATIVE_PATH: %25s', self.relative_path)%0A        log.info('COMMIT: %25s', self.commit
 )%0A  
@@ -4274,24 +4274,110 @@
  path, fh):%0A
+        log.info('READDIR')%0A        log.info('RELATIVE_PATH: %25s', self.relative_path)%0A
         dir_

Add try/except clause, to handle bad paths when initializing a commit view.