# coding: utf8
# Debian Contributors data mining on file systems
#
# Copyright (C) 2013--2014  Enrico Zini <enrico@debian.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
from ...types import Identifier
from .mine import Aggregate
import os
import os.path
import pwd
import datetime
import logging

log = logging.getLogger(__name__)

__all__ = ["Filesystem"]

class Filesystem:
    """
    Collect and aggregate contribution data from file inode information, and
    build contribution informations out of it
    """
    def __init__(self):
        self.contribs = Aggregate()

    def scan_file(self, pathname):
        """
        Add an information from the inode information of a file
        """
        self.scan_stat(os.stat(pathname))

    def scan_stat(self, st):
        """
        Add an information from a stat structure
        """
        self.contribs.add(st.st_uid, st.st_mtime)

    def scan_git_repo(self, gitdir):
        """
        Add information from refs files in the given git repo

        gitdir: pathname to the bare repository or the .git directory
        """
        for subdir in ("refs", "objects"):
            scanroot = os.path.join(gitdir, subdir)
            log.debug("git scanning at %s", scanroot)
            for root, dirs, files in os.walk(scanroot):
                for f in files:
                    self.scan_file(os.path.join(root, f))

    def scan_svn_repo(self, svnroot):
        """
        Add information from commits in the given svn repo

        svnroot: pathname to the svn repository root dir
        """
        scanroot = os.path.join(svnroot, "db/revs")
        for root, dirs, files in os.walk(scanroot):
            for f in files:
                self.scan_file(os.path.join(root, f))

    def scan_all_files(self, root):
        """
        Add information from commits in the given svn repo

        svnroot: pathname to the svn repository root dir
        """
        for dirpath, dirnames, fnames in os.walk(root):
            for fname in fnames:
                self.scan_file(os.path.join(dirpath, fname))

    def contributions(self):
        """
        Generate (ident, begin, end) contributions
        """
        for uid, stats in self.contribs.items():
            try:
                pw = pwd.getpwuid(uid)
                ident = Identifier("login", pw.pw_name)
                begin = datetime.date.fromtimestamp(stats[0])
                end = datetime.date.fromtimestamp(stats[1])
                yield ident, begin, end
            except KeyError:
                pass
