<commit_before><?php declare(strict_types=1);

namespace Symplify\MonorepoBuilder\Split;

use ERROR;
use Nette\Utils\Strings;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\Process;
use Symplify\MonorepoBuilder\Split\Exception\PackageToRepositorySplitException;
use Symplify\MonorepoBuilder\Split\Process\ProcessFactory;
use Symplify\MonorepoBuilder\Split\Process\SplitProcessInfo;
use Symplify\MonorepoBuilder\Split\Process\SplitProcessInfoFactory;
use Symplify\PackageBuilder\FileSystem\FileSystemGuard;

final class PackageToRepositorySplitter
{
    /**
     * @var SymfonyStyle
     */
    private $symfonyStyle;

    /**
     * @var Process[]
     */
    private $activeProcesses = [];

    /**
     * @var SplitProcessInfo[]
     */
    private $processInfos = [];

    /**
     * @var FileSystemGuard
     */
    private $fileSystemGuard;

    /**
     * @var ProcessFactory
     */
    private $processFactory;

    /**
     * @var SplitProcessInfoFactory
     */
    private $splitProcessInfoFactory;

    public function __construct(
        SymfonyStyle $symfonyStyle,
        FileSystemGuard $fileSystemGuard,
        ProcessFactory $processFactory,
        SplitProcessInfoFactory $splitProcessInfoFactory
    ) {
        $this->symfonyStyle = $symfonyStyle;
        $this->fileSystemGuard = $fileSystemGuard;
        $this->processFactory = $processFactory;
        $this->splitProcessInfoFactory = $splitProcessInfoFactory;
    }

    /**
     * @param mixed[] $splitConfig
     */
    public function splitDirectoriesToRepositories(array $splitConfig, string $rootDirectory, bool $isVerbose): void
    {
        $theMostRecentTag = $this->getMostRecentTag($rootDirectory);

        foreach ($splitConfig as $localSubdirectory => $remoteRepository) {
            $this->fileSystemGuard->ensureDirectoryExists($localSubdirectory);

            $process = $this->processFactory->createSubsplit(
                $theMostRecentTag,
                $localSubdirectory,
                $remoteRepository,
                $isVerbose
            );
            $this->symfonyStyle->note('Running: ' . $process->getCommandLine());
            $process->start();

            $this->activeProcesses[] = $process;

            $this->processInfos[] = $this->splitProcessInfoFactory->createFromProcessLocalDirectoryAndRemoteRepository(
                $process,
                $localSubdirectory,
                $remoteRepository
            );
        }

        $this->symfonyStyle->success(sprintf('Running %d jobs asynchronously', count($this->activeProcesses)));

        while (count($this->activeProcesses)) {
            foreach ($this->activeProcesses as $i => $runningProcess) {
                if (! $runningProcess->isRunning()) {
                    unset($this->activeProcesses[$i]);
                }
            }

            // check every second
            sleep(1);
        }

        $this->reportFinishedProcesses();
    }

    private function getMostRecentTag(string $cwd): string
    {
        $process = new Process('git tag -l --sort=committerdate', $cwd);
        $process->run();
        $tags = $process->getOutput();
        $tagList = explode(PHP_EOL, trim($tags));

        return (string) array_pop($tagList);
    }

    private function reportFinishedProcesses(): void
    {
        foreach ($this->processInfos as $processInfo) {
            $process = $processInfo->getProcess();
            if (! $process->isSuccessful()) {
                throw new PackageToRepositorySplitException($process->getErrorOutput());
            }

            $output = $process->getOutput();
            if (Strings::contains($output, ERROR::class)) {
                throw new PackageToRepositorySplitException($output);
            }

            $this->symfonyStyle->success(sprintf(
                'Push of "%s" directory to "%s" repository was successful: %s',
                $processInfo->getLocalDirectory(),
                $processInfo->getRemoteRepository(),
                $output
            ));
        }
    }
}<commit_msg>errors should be thrown by return code<commit_after><?php declare(strict_types=1);

namespace Symplify\MonorepoBuilder\Split;

use ERROR;
use Nette\Utils\Strings;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\Process;
use Symplify\MonorepoBuilder\Split\Exception\PackageToRepositorySplitException;
use Symplify\MonorepoBuilder\Split\Process\ProcessFactory;
use Symplify\MonorepoBuilder\Split\Process\SplitProcessInfo;
use Symplify\MonorepoBuilder\Split\Process\SplitProcessInfoFactory;
use Symplify\PackageBuilder\FileSystem\FileSystemGuard;

final class PackageToRepositorySplitter
{
    /**
     * @var SymfonyStyle
     */
    private $symfonyStyle;

    /**
     * @var Process[]
     */
    private $activeProcesses = [];

    /**
     * @var SplitProcessInfo[]
     */
    private $processInfos = [];

    /**
     * @var FileSystemGuard
     */
    private $fileSystemGuard;

    /**
     * @var ProcessFactory
     */
    private $processFactory;

    /**
     * @var SplitProcessInfoFactory
     */
    private $splitProcessInfoFactory;

    public function __construct(
        SymfonyStyle $symfonyStyle,
        FileSystemGuard $fileSystemGuard,
        ProcessFactory $processFactory,
        SplitProcessInfoFactory $splitProcessInfoFactory
    ) {
        $this->symfonyStyle = $symfonyStyle;
        $this->fileSystemGuard = $fileSystemGuard;
        $this->processFactory = $processFactory;
        $this->splitProcessInfoFactory = $splitProcessInfoFactory;
    }

    /**
     * @param mixed[] $splitConfig
     */
    public function splitDirectoriesToRepositories(array $splitConfig, string $rootDirectory, bool $isVerbose): void
    {
        $theMostRecentTag = $this->getMostRecentTag($rootDirectory);

        foreach ($splitConfig as $localSubdirectory => $remoteRepository) {
            $this->fileSystemGuard->ensureDirectoryExists($localSubdirectory);

            $process = $this->processFactory->createSubsplit(
                $theMostRecentTag,
                $localSubdirectory,
                $remoteRepository,
                $isVerbose
            );
            $this->symfonyStyle->note('Running: ' . $process->getCommandLine());
            $process->start();

            $this->activeProcesses[] = $process;

            $this->processInfos[] = $this->splitProcessInfoFactory->createFromProcessLocalDirectoryAndRemoteRepository(
                $process,
                $localSubdirectory,
                $remoteRepository
            );
        }

        $this->symfonyStyle->success(sprintf('Running %d jobs asynchronously', count($this->activeProcesses)));

        while (count($this->activeProcesses)) {
            foreach ($this->activeProcesses as $i => $runningProcess) {
                if (! $runningProcess->isRunning()) {
                    unset($this->activeProcesses[$i]);
                }
            }

            // check every second
            sleep(1);
        }

        $this->reportFinishedProcesses();
    }

    private function getMostRecentTag(string $cwd): string
    {
        $process = new Process('git tag -l --sort=committerdate', $cwd);
        $process->run();
        $tags = $process->getOutput();
        $tagList = explode(PHP_EOL, trim($tags));

        return (string) array_pop($tagList);
    }

    private function reportFinishedProcesses(): void
    {
        foreach ($this->processInfos as $processInfo) {
            $process = $processInfo->getProcess();
            if (! $process->isSuccessful()) {
                throw new PackageToRepositorySplitException($process->getErrorOutput());
            }

            $this->symfonyStyle->success(sprintf(
                'Push of "%s" directory to "%s" repository was successful: %s',
                $processInfo->getLocalDirectory(),
                $processInfo->getRemoteRepository(),
                $output
            ));
        }
    }
}
{'fraction_non_alphanumeric': 0.11602141167683307, 'fraction_numerical': 0.0004979459728619445, 'mean_word_length': 2.4042372881355933, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 78, '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': '4335274', 'n_tokens_mistral': 2152, 'n_tokens_neox': 2060, 'n_words': 362}