/**
  * {@inheritdoc}
  */
 public function accept(ActionInterface $action, Environment $environment)
 {
     if ($environment->getVcs() instanceof GitRepository) {
         $git = $environment->getVcs();
         $pathspecs = array_keys($this->paths);
         $status = $git->status()->getWorkTreeStatus();
         foreach ($status as $modifiedPathspec => $modifiedStatus) {
             foreach ($pathspecs as $pathspec) {
                 if (fnmatch($pathspec, $modifiedPathspec)) {
                     if ($modifiedStatus == 'M' && in_array('modified', $this->paths[$pathspec]) || $modifiedStatus == 'A' && in_array('added', $this->paths[$pathspec]) || $modifiedStatus == 'D' && in_array('deleted', $this->paths[$pathspec]) || $modifiedStatus == 'R' && in_array('renamed', $this->paths[$pathspec]) || $modifiedStatus == 'C' && in_array('copied', $this->paths[$pathspec]) || $modifiedStatus == 'U' && in_array('unmerged', $this->paths[$pathspec]) || $modifiedStatus == '?' && in_array('untracked', $this->paths[$pathspec]) || $modifiedStatus == 'M' && in_array('all', $this->paths[$pathspec]) && !in_array('-modified', $this->paths[$pathspec]) || $modifiedStatus == 'A' && in_array('all', $this->paths[$pathspec]) && !in_array('-added', $this->paths[$pathspec]) || $modifiedStatus == 'D' && in_array('all', $this->paths[$pathspec]) && !in_array('-deleted', $this->paths[$pathspec]) || $modifiedStatus == 'R' && in_array('all', $this->paths[$pathspec]) && !in_array('-renamed', $this->paths[$pathspec]) || $modifiedStatus == 'C' && in_array('all', $this->paths[$pathspec]) && !in_array('-copied', $this->paths[$pathspec]) || $modifiedStatus == 'U' && in_array('all', $this->paths[$pathspec]) && !in_array('-unmerged', $this->paths[$pathspec]) || $modifiedStatus == '?' && in_array('all', $this->paths[$pathspec]) && !in_array('-untracked', $this->paths[$pathspec])) {
                         return true;
                     }
                 }
             }
         }
         return false;
     }
     throw new \RuntimeException(sprintf('VCS type %s is not supported', get_class($environment->getVcs())));
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     /** @var HelperSet $helperSet */
     $helperSet = $this->getHelperSet();
     if (!$this->environment) {
         $this->environment = new Environment();
     }
     if (!$this->environment->hasApplication()) {
         $this->environment->setApplication($this->getApplication());
     }
     if (!$this->environment->hasConfiguration()) {
         if ($helperSet->has('ccabs:repositories:configuration')) {
             /** @var ConfigurationHelperInterface $helper */
             $helper = $helperSet->get('ccabs:repositories:configuration');
             $this->environment->setConfiguration($helper->getConfiguration($this->environment));
         } else {
             throw new \RuntimeException('Configuration is not provided');
         }
     }
     // TODO use a helper to get this instance
     if (!$this->environment->hasPlaceholderReplacer()) {
         $this->environment->setPlaceholderReplacer(new PlaceholderReplacer());
     }
     $this->environment->setInput($input);
     $this->environment->setOutput($output);
     if ($output instanceof ConsoleOutputInterface) {
         $this->environment->setErrorOutput($output->getErrorOutput());
     } else {
         $this->environment->setErrorOutput($output);
     }
     if ($input->hasOption('log') && $input->hasParameterOption('log')) {
         $logFile = $input->getOption('log');
         $logLevel = $input->getOption('log-level');
         $logger = new Logger('ccabs:repositories', array(new StreamHandler($logFile, $logLevel)));
         $this->environment->setLogger($logger);
     }
     $ownerName = $input->getOption('owner');
     $repositoryName = $input->getOption('repository');
     $providers = (array) $input->getOption('provider');
     if (count($providers)) {
         $compoundProvider = new CompoundProvider($this->environment);
         foreach ($this->environment->getConfiguration()->getProvider()->getProviders() as $provider) {
             if (in_array($provider->getName(), $providers)) {
                 $compoundProvider->addProvider($provider);
             }
         }
         $repositories = $compoundProvider->listAll();
     } else {
         $repositories = $this->environment->getConfiguration()->getProvider()->listAll();
     }
     if ($ownerName || $repositoryName) {
         $repositories = array_filter($repositories, function (Repository $repository) use($ownerName, $repositoryName) {
             return (!$ownerName || fnmatch($ownerName, $repository->getOwner())) && (!$repositoryName || fnmatch($repositoryName, $repository->getName()));
         });
     }
     $this->executeOn($repositories, $input, $output);
 }
 protected function buildRepositories($repositoryData, &$repositories = array())
 {
     // simple blacklist check
     if (in_array($repositoryData['name'], $this->blacklist)) {
         return array();
     }
     // extended blacklist check
     foreach ($this->blacklist as $blacklist) {
         if (fnmatch($blacklist, $repositoryData['name'])) {
             return array();
         }
     }
     $settings = array();
     foreach ($this->repositories as $pattern => $repositorySettings) {
         $matcher = new TagMatcher($pattern);
         if ($matcher->match($repositoryData['name'])) {
             $settings = array_merge_recursive($settings, $repositorySettings);
         }
     }
     if (empty($settings)) {
         return array();
     }
     if ($this->environment->hasLogger()) {
         $this->environment->getLogger()->debug(sprintf('[ccabs:repositories:bitbucket-provider] build repository versions for %s/%s', $repositoryData['owner'], $repositoryData['name']));
     }
     if ($this->environment->hasOutput() && $this->environment->getOutput()->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
         $this->environment->getOutput()->writeln(sprintf(' * <info>ccabs:repositories:bitbucket-provider</info> build repository versions for <comment>%s/%s</comment>', $repositoryData['owner'], $repositoryData['name']));
     }
     /** @var TagMatcher[] $branchMatchers */
     $branchMatchers = array();
     if (isset($settings['branches'])) {
         foreach ($settings['branches'] as $branchSyntax) {
             $branchMatchers[] = new TagMatcher($branchSyntax);
         }
     }
     /** @var TagMatcher[] $tagMatchers */
     $tagMatchers = array();
     if (isset($settings['tags'])) {
         foreach ($settings['tags'] as $tagSyntax) {
             $tagMatchers[] = new TagMatcher($tagSyntax);
         }
     }
     try {
         if (count($branchMatchers)) {
             $url = sprintf('repositories/%s/%s/branches', rawurlencode($repositoryData['owner']), rawurlencode($repositoryData['name']));
             $request = $this->getClient()->get($url);
             $response = $request->send();
             $branchesData = $response->json();
             if ($this->environment->hasLogger()) {
                 $this->environment->getLogger()->debug(sprintf('[ccabs:repositories:bitbucket-provider] found %d branches: %s', count($branchesData), implode(', ', array_keys($branchesData))));
             }
             if ($this->environment->hasOutput() && $this->environment->getOutput()->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
                 $this->environment->getOutput()->writeln(sprintf(' * <info>ccabs:repositories:bitbucket-provider</info> found %d branches: %s', count($branchesData), implode(', ', array_keys($branchesData))));
             }
             foreach ($branchMatchers as $branchMatcher) {
                 foreach ($branchesData as $branchName => $branchData) {
                     if ($branchMatcher->match($branchName)) {
                         $repository = $this->buildRepository($repositoryData, $branchName, $this->remoteName . '/' . $branchName, Repository::REF_BRANCH);
                         if ($repository) {
                             $repositories[] = $repository;
                         }
                     }
                 }
             }
         }
         if (count($tagMatchers)) {
             // tags cannot be directly added to $repositories, store them in a temporary array
             $tags = array();
             $url = sprintf('repositories/%s/%s/tags', rawurlencode($repositoryData['owner']), rawurlencode($repositoryData['name']));
             $request = $this->getClient()->get($url);
             $response = $request->send();
             $tagsData = $response->json();
             if ($this->environment->hasLogger()) {
                 $this->environment->getLogger()->debug(sprintf('[ccabs:repositories:bitbucket-provider] found %d tags: %s', count($tagsData), implode(', ', array_keys($tagsData))));
             }
             if ($this->environment->hasOutput() && $this->environment->getOutput()->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
                 $this->environment->getOutput()->writeln(sprintf(' * <info>ccabs:repositories:bitbucket-provider</info> found %d tags: %s', count($tagsData), implode(', ', array_keys($tagsData))));
             }
             foreach ($tagMatchers as $tagMatcher) {
                 foreach ($tagsData as $tagName => $tagData) {
                     if ($tagMatcher->match($tagName)) {
                         if (!empty($settings['tag']['min']) && call_user_func($this->tagCompareFunction, $settings['tag']['min'], $tagName) >= 0 || !empty($settings['tag']['max']) && call_user_func($this->tagCompareFunction, $settings['tag']['max'], $tagName) <= 0 || !empty($settings['tag']['ignore']) && in_array($tagName, (array) $settings['tag']['ignore'])) {
                             continue;
                         }
                         $repository = $this->buildRepository($repositoryData, $tagName, $tagName, Repository::REF_TAG);
                         if ($repository) {
                             $tags[$tagName] = $repository;
                         }
                     }
                 }
             }
             // sort tags
             uksort($tags, $this->tagCompareFunction);
             // invert sorting
             if ($this->tagSorting == 'desc') {
                 $tags = array_reverse($tags);
             }
             // limit tag count
             if ($this->tagLimit > 0) {
                 $tags = array_slice($tags, 0, $this->tagLimit);
             }
             // add remaining tags
             foreach ($tags as $repository) {
                 $repositories[] = $repository;
             }
         }
     } catch (BadResponseException $e) {
         if ($this->environment->hasLogger()) {
             $this->environment->getLogger()->debug(sprintf('[ccabs:repositories:github-provider] bad response from %s repository: %s', $repositoryData['full_name'], $e->getMessage()));
         }
         if ($this->environment->hasOutput() && $this->environment->getOutput()->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
             $this->environment->getOutput()->writeln(sprintf(' * <info>ccabs:repositories:github-provider</info> bad response from <comment>%s</comment> repository: %s', $repositoryData['full_name'], $e->getMessage()));
         }
     }
     return $repositories;
 }