<commit_before>use std::path::PathBuf;
use std::path::Path;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};
use git2::{ADD_DEFAULT, STATUS_WT_NEW, STATUS_WT_MODIFIED, IndexMatchedPath};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;
use libimagutil::debug_result::*;

use vcs::git::result::Result;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::runtime::Runtime as GRuntime;

pub struct CreateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl CreateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> CreateHook {
        CreateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for CreateHook {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for CreateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_create"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for CreateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for CreateHook {

    /// The implementation of the CreateHook
    ///
    /// # Scope
    ///
    /// What this function has to do is _adding_ the new entry to the git index.
    /// After that, the UpdateHook will take care of committing the changes or new file.
    ///
    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;

        debug!("[GIT CREATE HOOK]: {:?}", id);

        let path = try!(id.into_pathbuf().map_err_into(GHEK::StoreIdHandlingError));

        let cfg = try!(
            self.runtime
                .config_value_or_err()
                .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't get Value object from config")
        );

        debug!("[GIT CREATE HOOK]: Ensuring branch checkout");
        try!(self
             .runtime
             .ensure_cfg_branch_is_checked_out()
             .map_err(Box::new)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));
        debug!("[GIT CREATE HOOK]: Branch checked out");

        debug!("[GIT CREATE HOOK]: Getting repository");
        let repo = try!(
            self.runtime
                .repository()
                .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Repository")
                .map_err_into(GHEK::RepositoryError)
                .map_err(|e| e.into())
        );
        debug!("[GIT CREATE HOOK]: Repository object fetched");

        let index = try!(repo.index().map_err_into(GHEK::RepositoryIndexFetchingError));

        let file_status = try!(
            repo.status_file(&path).map_err_into(GHEK::RepositoryFileStatusError)
        );

        let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 {
            if file_status.contains(STATUS_WT_MODIFIED) ||
                file_status.contains(STATUS_WT_NEW) {

                debug!("[GIT CREATE HOOK]: File is new or modified: {}", path.display());
                0
            } else {
                debug!("[GIT CREATE HOOK]: Ignoring file: {}", path.display());
                1
            }
        };

        try!(
            index.add_all(&[path], ADD_DEFAULT, Some(cb as &mut IndexMatchedPath))
                .map_err_into(GHEK::RepositoryPathAddingError)
        );

        index.write().map_err_into(GHEK::RepositoryIndexWritingError).map_err(|e| e.into())
    }

}
<commit_msg>Use MapIntoHookError for mapping into hook error<commit_after>use std::path::PathBuf;
use std::path::Path;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};
use git2::{ADD_DEFAULT, STATUS_WT_NEW, STATUS_WT_MODIFIED, IndexMatchedPath};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;
use libimagutil::debug_result::*;

use vcs::git::result::Result;
use vcs::git::error::MapIntoHookError;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::runtime::Runtime as GRuntime;

pub struct CreateHook {
    storepath: PathBuf,

    runtime: GRuntime,

    position: HookPosition,
}

impl CreateHook {

    pub fn new(storepath: PathBuf, p: HookPosition) -> CreateHook {
        CreateHook {
            runtime: GRuntime::new(&storepath),
            storepath: storepath,
            position: p,
        }
    }

}

impl Debug for CreateHook {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl Hook for CreateHook {

    fn name(&self) -> &'static str {
        "stdhook_git_create"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl HookDataAccessorProvider for CreateHook {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl StoreIdAccessor for CreateHook {

    /// The implementation of the CreateHook
    ///
    /// # Scope
    ///
    /// What this function has to do is _adding_ the new entry to the git index.
    /// After that, the UpdateHook will take care of committing the changes or new file.
    ///
    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;
        use vcs::git::error::MapIntoHookError;

        debug!("[GIT CREATE HOOK]: {:?}", id);

        let path = try!(
            id.clone()
            .into_pathbuf()
            .map_err_into(GHEK::StoreIdHandlingError)
            .map_into_hook_error()
        );

        let cfg = try!(
            self.runtime
                .config_value_or_err()
                .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't get Value object from config")
        );

        debug!("[GIT CREATE HOOK]: Ensuring branch checkout");
        try!(self.runtime.ensure_cfg_branch_is_checked_out());
        debug!("[GIT CREATE HOOK]: Branch checked out");

        debug!("[GIT CREATE HOOK]: Getting repository");
        let repo = try!(
            self.runtime
                .repository()
                .map_dbg_err_str("[GIT CREATE HOOK]: Couldn't fetch Repository")
                .map_err_into(GHEK::RepositoryError)
                .map_into_hook_error()
        );
        debug!("[GIT CREATE HOOK]: Repository object fetched");

        let mut index = try!(
            repo
                .index()
                .map_err_into(GHEK::RepositoryIndexFetchingError)
                .map_into_hook_error()
        );

        let file_status = try!(
            repo
                .status_file(&path)
                .map_err_into(GHEK::RepositoryFileStatusError)
                .map_into_hook_error()
        );

        let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 {
            if file_status.contains(STATUS_WT_MODIFIED) ||
                file_status.contains(STATUS_WT_NEW) {

                debug!("[GIT CREATE HOOK]: File is new or modified: {}", path.display());
                0
            } else {
                debug!("[GIT CREATE HOOK]: Ignoring file: {}", path.display());
                1
            }
        };

        try!(
            index.add_all(&[path], ADD_DEFAULT, Some(cb as &mut IndexMatchedPath))
                .map_err_into(GHEK::RepositoryPathAddingError)
                .map_into_hook_error()
        );

        index
            .write()
            .map_err_into(GHEK::RepositoryIndexWritingError)
            .map_into_hook_error()
    }

}

{'fraction_non_alphanumeric': 0.13124078365283337, 'fraction_numerical': 0.0016852749104697704, 'mean_word_length': 2.585725075528701, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6974609', 'n_tokens_mistral': 2951, 'n_tokens_neox': 2875, 'n_words': 639}