protected function execute(InputInterface $input, OutputInterface $output) { $cwd = getcwd() . '/' . $input->getOption('working-dir'); $timeout = (int) $input->getOption('timeout'); /** @var FormatterHelper $formatter */ $formatter = $this->getHelperSet()->get('formatter'); /** @var Config $config */ $config = new Config($cwd); try { if (!$config->read()) { $output->writeln('<fg=red>No previous config found, please run grenade:config</fg=red>'); return -1; } $output->writeln('<fg=yellow>Previous config found.</fg=yellow>'); $output->writeln('<fg=yellow>Loading existing config...</fg=yellow> <fg=green>done</fg=green>'); } catch (GrenadeRuntimeException $e) { $output->writeln('<fg=red>failed</fg=red>'); $output->writeln('<fg=red>An error occured while parsing .grenade.json file.</fg=red>'); return -1; } if (!file_exists($cwd . '/repositories')) { $output->writeln('<fg=yellow>Repositories folder does not exist, repositories should already be cloned.</fg=yellow>'); mkdir($cwd . '/repositories', 0755, true); } if (!file_exists($cwd . '/bundles')) { mkdir($cwd . '/bundles', 0755, true); } /** @var GitSubtreeProgressBarHelper $progressBarHelper */ $progressBarHelper = new GitSubtreeProgressBarHelper($output); foreach ($config->walkProjects() as $projectName => $projectRemote) { $repositoryPath = $cwd . '/repositories/' . $projectName; $originalGit = new Git($repositoryPath, $timeout); $bundleGit = new Git(null, $timeout); if (!file_exists($repositoryPath)) { $output->writeln(sprintf('<fg=green>Cloning <fg=cyan>%s</fg=cyan> repository.</fg=green>', $projectName)); $originalGit->setWorkingDirectory($cwd . '/repositories/'); $process = $originalGit->cloneRepository($projectRemote, $projectName); if (!$process->isSuccessful()) { throw new CommandFailureException($process); } $originalGit->setWorkingDirectory($repositoryPath); } else { $output->writeln(sprintf('<fg=green>Fetching <fg=cyan>%s</fg=cyan> repository.</fg=green>', $projectName)); $process = $originalGit->fetch(); if (!$process->isSuccessful()) { throw new CommandFailureException($process); } } foreach ($config->walkBundles($projectName) as $repositoryAlias => $repositoryConfig) { $output->writeln(sprintf('<fg=green>Analyzing bundle <fg=cyan>%s</fg=cyan>...</fg=green>', $repositoryConfig['name'])); foreach ($originalGit->branchList(false, true, 'origin') as $branchAlias => $branchName) { try { $process = $originalGit->revParse()->verify($branchName); if ($process->isSuccessful() && $config->compareBundleBranchHead($projectName, $repositoryAlias, $branchName, $process->getOutput())) { $output->writeln(sprintf(' <fg=green>Branch <fg=cyan>%s</fg=cyan> up to date, skipping...</fg=green>', $branchName)); continue; } $output->writeln(sprintf(' <fg=green>Exporting branch <fg=cyan>%s</fg=cyan>...</fg=green>', $branchName)); $process = $originalGit->revParse()->verify($this->derivedBranch($repositoryAlias, $branchAlias)); $bundleRepositoryPath = $cwd . '/bundles/' . $repositoryAlias; if (!$process->isSuccessful() || !file_exists($bundleRepositoryPath)) { $output->writeln(sprintf(' <fg=green>Splitting into a new <fg=cyan>%s</fg=cyan> branch.</fg=green>', $this->derivedBranch($repositoryAlias, $branchAlias))); $progressBarHelper->reset(); $process = $originalGit->subtree()->split($this->derivedBranch($repositoryAlias, $branchAlias), $repositoryConfig['path'], null, 'origin/' . $branchAlias, false, null, $progressBarHelper); $progressBarHelper->finish(); if ($progressBarHelper->updatesCount() <= 0) { $output->writeln(sprintf(' <fg=green>Fast-forward update for branch <fg=cyan>%s</fg=cyan>.</fg=green>', $branchAlias)); } else { if (!$process->isSuccessful()) { throw new CommandFailureException($process); } } $bundleGit->setWorkingDirectory($bundleRepositoryPath); if (!file_exists($bundleRepositoryPath)) { $output->writeln(sprintf(' <fg=green>Initializing git repository for <fg=cyan>%s</fg=cyan> bundle.</fg=green>', $repositoryConfig['name'])); mkdir($bundleRepositoryPath, 0755, true); $bundleGit->init(); } $output->writeln(sprintf(' <fg=green>Pulling branch <fg=cyan>%s</fg=cyan> in the bundle repository.</fg=green>', $this->derivedBranch($repositoryAlias, $branchAlias))); $bundleGit->pull($repositoryPath, $this->derivedBranch($repositoryAlias, $branchAlias)); } else { $output->writeln(sprintf(' <fg=green>Updating the <fg=cyan>%s</fg=cyan> bundle\'s code into the <fg=cyan>%s</fg=cyan> branch.</fg=green>', $repositoryConfig['name'], $this->derivedBranch($repositoryAlias, $branchAlias))); $progressBarHelper->reset(); $process = $originalGit->subtree()->push($bundleRepositoryPath, $this->derivedBranch($repositoryAlias, $branchAlias), $repositoryConfig['path'], $progressBarHelper); $progressBarHelper->finish(); if (!$process->isSuccessful()) { throw new CommandFailureException($process); } } $process = $originalGit->revParse()->verify($branchName); if ($process->isSuccessful()) { $config->updateBundleBranch($projectName, $repositoryAlias, $branchName, $process->getOutput()); } } catch (CommandFailureException $e) { $output->writeln($formatter->formatBlock(['An error occurred while exporting subtrees.', $e->__toString()], 'error')); } catch (RuntimeException $e) { $output->writeln($formatter->formatBlock(['An error occurred while exporting subtrees.', $e->__toString()], 'error')); } } } } $config->save(); return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $repository = $input->getArgument('project-repository'); $projectAlias = $input->getArgument('alias') ? $input->getArgument('alias') : basename($repository, '.git'); $cwd = $input->getOption('working-dir'); if (strpos($cwd, '/') !== 0 && strpos($cwd, ':') === false) { $cwd = getcwd() . '/' . $cwd; } $timeout = max(1, (int) $input->getOption('timeout')); if (!file_exists($cwd . '/repositories')) { mkdir($cwd . '/repositories', 0755, true); } if (!file_exists($cwd . '/bundles')) { mkdir($cwd . '/bundles', 0755, true); } $repositoryPath = $cwd . '/repositories/' . $projectAlias; $git = new Git($repositoryPath, $timeout); if (!file_exists($repositoryPath)) { $output->writeln(sprintf('<fg=green>Cloning <fg=cyan>%s</fg=cyan> from <fg=cyan>%s</fg=cyan>...</fg=green> ', $projectAlias, $repository)); $git->setWorkingDirectory($cwd . '/repositories/'); $git->cloneRepository($repository, $projectAlias); $git->setWorkingDirectory($repositoryPath); } else { $output->writeln(sprintf('<fg=green>Fetching <fg=cyan>%s</fg=cyan>...</fg=green> ', $projectAlias)); $git->fetch(); } /** @var QuestionHelper $question */ $question = $this->getHelperSet()->get('question'); /** @var Config $config */ $config = new Config($cwd); try { if (!$config->read()) { $output->writeln('<fg=red>No previous config found, initializing.</fg=red>'); } else { $output->writeln('<fg=yellow>Previous config found.</fg=yellow>'); $output->writeln('<fg=yellow>Loading existing config...</fg=yellow> <fg=green>done</fg=green>'); } } catch (GrenadeRuntimeException $e) { $output->writeln('<fg=red>failed</fg=red>'); $output->writeln('<fg=red>An error occured while parsing .grenade.json file.</fg=red>'); return -1; } $config->addProject($projectAlias, $repository); $codePath = null; $bundlesAutocomplete = []; if (($count = $config->repositoriesCount($projectAlias)) > 0) { if ($count == 1) { $output->writeln(sprintf('<fg=green>Found <fg=cyan>%d</fg=cyan> registered bundle:</fg=green> ', $count)); } else { $output->writeln(sprintf('<fg=green>Found <fg=cyan>%d</fg=cyan> registered bundles:</fg=green> ', $count)); } foreach ($config->walkBundles($projectAlias) as $childRepository) { $output->writeln(sprintf('<fg=green> - <fg=cyan>%s</fg=cyan></fg=green>', $childRepository['name'])); } } while (true) { if ($codePath !== null) { $change = 'no' !== $question->ask($input, $output, (new Question('<fg=green>Would you like to change bundles code path? [<fg=yellow>no</fg=yellow>]</fg=green> ', 'no'))->setAutocompleterValues(['yes', 'no'])); if ($change) { $codePath = null; } } if ($codePath === null) { while (true) { $codePath = $question->ask($input, $output, new Question('<fg=green>Enter bundles code path:</fg=green> ')); if (!file_exists($repositoryPath . '/' . $codePath)) { $output->writeln(sprintf('<fg=red>Directory <fg=cyan>%s</fg=cyan> does not exist, please enter a valid path.</fg=red>', $codePath)); continue; } $bundlesAutocomplete = array_filter(scandir($repositoryPath . '/' . $codePath), function ($bundleName) use($repositoryPath, $codePath) { if (strpos($bundleName, 'Bundle') === false || $bundleName === 'Bundle') { return false; } $bundleBootstrapFiles = array_filter(scandir($repositoryPath . '/' . $codePath . '/' . $bundleName), function ($fileName) use($bundleName) { return strpos($fileName, $bundleName . '.php') !== false; }); if (count($bundleBootstrapFiles) <= 0) { return false; } return true; }); if (count($bundlesAutocomplete) <= 0) { $output->writeln(sprintf('<fg=red>No bundles were found in path <fg=cyan>%s</fg=cyan></fg=red>', $codePath)); continue; } break; } } while (true) { $bundleName = $question->ask($input, $output, (new Question(sprintf('<fg=green>Enter the bundle name: </fg=green> ')))->setAutocompleterValues($bundlesAutocomplete)); if (!file_exists($repositoryPath . '/' . $codePath . '/' . $bundleName)) { $output->writeln(sprintf('<fg=red>Specified bundle <fg=cyan>%s</fg=cyan> does not exist</fg=red>', $bundleName)); continue; } $bundlesBootstrapFiles = array_filter(scandir($repositoryPath . '/' . $codePath . '/' . $bundleName), function ($item) use($bundleName) { return strpos($item, $bundleName . '.php') !== false; }); if (count($bundlesBootstrapFiles) <= 0) { $output->writeln(sprintf('<fg=red>Specified bundle <fg=cyan>%s</fg=cyan> doesn\'t seem to be an actual Symfony2 bundle</fg=red>', $bundleName)); continue; } $bundleFullName = basename(current($bundlesBootstrapFiles), '.php'); break; } $guessedBundleAlias = preg_replace_callback('/(^[A-Z]|[A-Z])/', function ($matches) { return (strlen($matches[1]) > 0 ? '-' : '') . strtolower($matches[1]); }, lcfirst($bundleFullName)); $bundleAlias = $question->ask($input, $output, (new Question(sprintf('<fg=green>Enter a bundle alias: [<fg=yellow>%s</fg=yellow>]</fg=green> ', $guessedBundleAlias)))->setAutocompleterValues([$guessedBundleAlias])); if (empty($bundleAlias)) { $bundleAlias = $guessedBundleAlias; } $isOrganization = 'no' !== $question->ask($input, $output, (new Question('<fg=green>Is remote repository owned by an organization? [<fg=yellow>no</fg=yellow>]</fg=green> ', 'no'))->setAutocompleterValues(['yes', 'no'])); if ($isOrganization) { $organizationName = $question->ask($input, $output, new Question('<fg=green>Enter organization name:</fg=green> ')); } else { $organizationName = null; } $remoteRepository = $question->ask($input, $output, new Question(sprintf('<fg=green>Enter remote repository name: [<fg=yellow>%s</fg=yellow>]</fg=green> ', $bundleAlias))); $config->addBundle($projectAlias, $bundleAlias, $bundleFullName, $codePath . '/' . $bundleName); if ($organizationName !== null) { $config->setBundleRemoteOrganization($projectAlias, $bundleAlias, $organizationName); } if ($remoteRepository !== null) { $config->setBundleRemoteRepository($projectAlias, $bundleAlias, $remoteRepository); } $continue = 'no' !== $question->ask($input, $output, (new Question('<fg=green>Would you like to add another bundle? [<fg=yellow>no</fg=yellow>]</fg=green> ', 'no'))->setAutocompleterValues(['yes', 'no'])); if (!$continue) { break; } } $config->save(); }