<commit_before><?php

namespace uuf6429\ElderBrother\Vcs\Adapter;

use Symfony\Component\Process\Process;
use uuf6429\ElderBrother\Event\Git as GitEvent;

class Git extends Adapter
{
    /**
     * @var string|null
     */
    protected $hookPath;

    /**
     * {@inheritdoc}
     */
    public function isAvailable()
    {
        return is_dir($this->getHookPath());
    }

    /**
     * {@inheritdoc}
     */
    public function isInstalled()
    {
        return file_exists($this->getInstallLockFile());
    }

    /**
     * {@inheritdoc}
     */
    public function install()
    {
        $hookFiles = $this->getHookFiles();

        // create install lock
        fclose(fopen($this->getInstallLockFile(), 'x'));

        foreach ($hookFiles as $event => $file) {
            // back up existing hook
            if (file_exists($file)) {
                if (!rename($file, $file . '.bak')) {
                    throw new \RuntimeException("Could not back up hook file: $file");
                }
            }

            // create new hook file
            if (!file_put_contents(
                $file,
                sprintf(
                    '#!/bin/sh%sphp -f %s -- run -e %s%s',
                    PHP_EOL,
                    escapeshellarg(str_replace(PROJECT_ROOT, '', ELDER_BROTHER_BIN)),
                    escapeshellarg($event),
                    PHP_EOL
                )
            )) {
                throw new \RuntimeException("Could not create hook file: $file");
            }
            if (!chmod($file, 0755)) {
                throw new \RuntimeException("Could not make hook file executable: $file");
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function uninstall()
    {
        $hookFiles = $this->getHookFiles();

        foreach ($hookFiles as $file) {
            // remove hook file
            if (!unlink($file)) {
                throw new \RuntimeException("Could not remove hook file: $file");
            }

            // restore backed up hook
            if (file_exists($file . '.bak')) {
                if (!rename($file . '.bak', $file) || !chmod($file, 0755)) {
                    throw new \RuntimeException("Could not properly restore hook file: $file");
                }
            }
        }

        // remove install lock
        unlink($this->getInstallLockFile());
    }

    /**
     * @return string
     */
    protected function getHookPath()
    {
        if (!$this->hookPath) {
            $process = new Process('git rev-parse --git-dir', PROJECT_ROOT);
            $process->run();

            if (!$process->isSuccessful()) {
                $this->logger->warning(
                    sprintf(
                        "Failed to retrieve git project root:\n$ %s (exit: %d)\n> %s",
                        $process->getCommandLine(),
                        $process->getExitCode(),
                        implode("\n> ", explode(PHP_EOL, $process->getOutput()))
                    )
                );
            } else {
                $this->hookPath = realpath(trim($process->getOutput())) . '/hooks/';
            }
        }

        return $this->hookPath;
    }

    /**
     * @return string
     */<commit_msg>Properly detect composer root (#34)<commit_after><?php

namespace uuf6429\ElderBrother\Vcs\Adapter;

use Symfony\Component\Process\Process;
use uuf6429\ElderBrother\Event\Git as GitEvent;

class Git extends Adapter
{
    /**
     * @var string|null
     */
    protected $gitDir;

    /**
     * {@inheritdoc}
     */
    public function isAvailable()
    {
        return is_dir($this->getHookPath());
    }

    /**
     * {@inheritdoc}
     */
    public function isInstalled()
    {
        return file_exists($this->getInstallLockFile());
    }

    /**
     * {@inheritdoc}
     */
    public function install()
    {
        $hookFiles = $this->getHookFiles();

        // create install lock
        fclose(fopen($this->getInstallLockFile(), 'x'));

        foreach ($hookFiles as $event => $file) {
            // back up existing hook
            if (file_exists($file)) {
                if (!rename($file, $file . '.bak')) {
                    throw new \RuntimeException("Could not back up hook file: $file");
                }
            }

            // create new hook file
            if (!file_put_contents(
                $file,
                sprintf(
                    '#!/bin/sh%sphp -f %s -- run -e %s%s',
                    PHP_EOL,
                    escapeshellarg(str_replace($this->getGitDir(), '', ELDER_BROTHER_BIN)),
                    escapeshellarg($event),
                    PHP_EOL
                )
            )) {
                throw new \RuntimeException("Could not create hook file: $file");
            }
            if (!chmod($file, 0755)) {
                throw new \RuntimeException("Could not make hook file executable: $file");
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function uninstall()
    {
        $hookFiles = $this->getHookFiles();

        foreach ($hookFiles as $file) {
            // remove hook file
            if (!unlink($file)) {
                throw new \RuntimeException("Could not remove hook file: $file");
            }

            // restore backed up hook
            if (file_exists($file . '.bak')) {
                if (!rename($file . '.bak', $file) || !chmod($file, 0755)) {
                    throw new \RuntimeException("Could not properly restore hook file: $file");
                }
            }
        }

        // remove install lock
        unlink($this->getInstallLockFile());
    }

    /**
     * @return string
     */
    protected function getGitDir()
    {
        if (!$this->gitDir) {
            $process = new Process('git rev-parse --git-dir', PROJECT_ROOT);
            $process->run();

            if (!$process->isSuccessful()) {
                $this->logger->warning(
                    sprintf(
                        "Failed to retrieve git project root:\n$ %s (exit: %d)\n> %s",
                        $process->getCommandLine(),
                        $process->getExitCode(),
                        implode("\n> ", explode(PHP_EOL, $process->getOutput()))
                    )
                );
            } else {
                $this->gitDir = realpath(trim($process->getOutput())) . '/';
            }
        }

        return $this->gitDir;
    }

    /**
     * @return string
     */
    protected function getHookPath()
    {
        return $this->getGitDir() . 'hooks/';
    }

    /**
     * @return string
     */
{'fraction_non_alphanumeric': 0.13650030066145522, 'fraction_numerical': 0.005111244738424534, 'mean_word_length': 1.3718360071301248, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 45, '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': '5612189', 'n_tokens_mistral': 1879, 'n_tokens_neox': 1773, 'n_words': 397}