/**
  * @param string $file
  *
  * @return Configuration
  */
 public function parseConfiguration(Environment $environment, $file)
 {
     if (!is_file($file)) {
         throw new \InvalidArgumentException(sprintf('File %s does not exist', $file));
     }
     $configuration = new Configuration();
     $parser = new Yaml();
     $array = $parser->parse($file);
     if (!isset($array['config'])) {
         throw new IncompleteConfigurationException('Mandatory configuration field "config" missing');
     }
     if (!isset($array['config']['storage'])) {
         throw new IncompleteConfigurationException('Mandatory configuration field "config.storage" missing');
     }
     if (!isset($array['providers'])) {
         throw new IncompleteConfigurationException('Mandatory configuration field "providers" missing');
     }
     $configuration->setStoragePath($array['config']['storage']);
     if (isset($array['config']['directory-scheme'])) {
         $configuration->setDirectoryScheme($array['config']['directory-scheme']);
     }
     $compoundProvider = new CompoundProvider($environment);
     $configuration->setProvider($compoundProvider);
     foreach ($array['providers'] as $providerName => $providerConfiguration) {
         if (!isset($providerConfiguration['type'])) {
             throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].type" missing', $providerName));
         }
         switch ($providerConfiguration['type']) {
             case 'bitbucket':
                 if (!isset($providerConfiguration['owner'])) {
                     throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].owner" missing', $providerName));
                 }
                 $provider = new BitBucketProvider($environment, $providerName, $providerConfiguration['owner']);
                 if (isset($providerConfiguration['remote'])) {
                     $provider->setRemoteName($providerConfiguration['remote']);
                 }
                 if (isset($providerConfiguration['repositories'])) {
                     $provider->setRepositories($providerConfiguration['repositories']);
                 }
                 if (isset($providerConfiguration['tag'])) {
                     if (isset($providerConfiguration['tag']['sorting'])) {
                         $provider->setTagSorting($providerConfiguration['tag']['sorting']);
                     }
                     if (isset($providerConfiguration['tag']['compareFunction'])) {
                         $provider->setTagCompareFunction($providerConfiguration['tag']['compareFunction']);
                     }
                     if (isset($providerConfiguration['tag']['limit'])) {
                         $provider->setTagLimit($providerConfiguration['tag']['limit']);
                     }
                 }
                 if (isset($providerConfiguration['auth'])) {
                     if (!isset($providerConfiguration['auth']['type'])) {
                         throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.type" missing', $providerName));
                     }
                     switch ($providerConfiguration['auth']['type']) {
                         case 'basic':
                             if (!isset($providerConfiguration['auth']['username'])) {
                                 throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.username" missing', $providerName));
                             }
                             if (!isset($providerConfiguration['auth']['password'])) {
                                 throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.password" missing', $providerName));
                             }
                             $auth = new BasicAuth($providerConfiguration['auth']['username'], $providerConfiguration['auth']['password']);
                             $provider->setAuthentication($auth);
                             break;
                         default:
                             throw new InvalidConfigurationException(sprintf('Authentication type "%s" is not supported by bitbucket', $providerConfiguration['type']));
                     }
                 }
                 if (isset($providerConfiguration['blacklist'])) {
                     $provider->setBlacklist((array) $providerConfiguration['blacklist']);
                 }
                 $compoundProvider->addProvider($provider);
                 break;
             case 'github':
                 if (!isset($providerConfiguration['owner'])) {
                     throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].owner" missing', $providerName));
                 }
                 $provider = new GithubProvider($environment, $providerName, $providerConfiguration['owner']);
                 if (isset($providerConfiguration['remote'])) {
                     $provider->setRemoteName($providerConfiguration['remote']);
                 }
                 if (isset($providerConfiguration['repositories'])) {
                     $provider->setRepositories($providerConfiguration['repositories']);
                 }
                 if (isset($providerConfiguration['tag'])) {
                     if (isset($providerConfiguration['tag']['sorting'])) {
                         $provider->setTagSorting($providerConfiguration['tag']['sorting']);
                     }
                     if (isset($providerConfiguration['tag']['compareFunction'])) {
                         $provider->setTagCompareFunction($providerConfiguration['tag']['compareFunction']);
                     }
                     if (isset($providerConfiguration['tag']['limit'])) {
                         $provider->setTagLimit($providerConfiguration['tag']['limit']);
                     }
                 }
                 if (isset($providerConfiguration['auth'])) {
                     if (!isset($providerConfiguration['auth']['type'])) {
                         throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.type" missing', $providerName));
                     }
                     switch ($providerConfiguration['auth']['type']) {
                         case 'basic':
                             if (!isset($providerConfiguration['auth']['username'])) {
                                 throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.username" missing', $providerName));
                             }
                             if (!isset($providerConfiguration['auth']['password'])) {
                                 throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.password" missing', $providerName));
                             }
                             $auth = new BasicAuth($providerConfiguration['auth']['username'], $providerConfiguration['auth']['password']);
                             $provider->setAuthentication($auth);
                             break;
                         case 'accessToken':
                             if (!isset($providerConfiguration['auth']['accessToken'])) {
                                 throw new IncompleteConfigurationException(sprintf('Mandatory configuration field "providers[%s].auth.accessToken" missing', $providerName));
                             }
                             $auth = new AccessTokenAuth($providerConfiguration['auth']['accessToken']);
                             $provider->setAuthentication($auth);
                             break;
                         default:
                             throw new InvalidConfigurationException(sprintf('Authentication type "%s" is not supported by github', $providerConfiguration['type']));
                     }
                 }
                 if (isset($providerConfiguration['blacklist'])) {
                     $provider->setBlacklist((array) $providerConfiguration['blacklist']);
                 }
                 $compoundProvider->addProvider($provider);
                 break;
             case 'git':
             case 'svn':
             case 'hg':
                 $provider = new VcsProvider($environment, $providerName);
                 if (isset($providerConfiguration['remote'])) {
                     $provider->setRemoteName($providerConfiguration['remote']);
                 }
                 if (isset($providerConfiguration['owner'])) {
                     $provider->setRepositoryOwner($providerConfiguration['owner']);
                 }
                 if (isset($providerConfiguration['name'])) {
                     $provider->setRepositoryName($providerConfiguration['name']);
                 }
                 $provider->setVcsType($providerConfiguration['type']);
                 if (isset($providerConfiguration['readUrl'])) {
                     $provider->setRepositoryReadUrl($providerConfiguration['readUrl']);
                 }
                 if (isset($providerConfiguration['writeUrl'])) {
                     $provider->setRepositoryWriteUrl($providerConfiguration['writeUrl']);
                     $provider->setRepositoryReadonly(false);
                 } else {
                     $provider->setRepositoryReadonly(true);
                 }
                 if (isset($providerConfiguration['webUrl'])) {
                     $provider->setRepositoryWebUrl($providerConfiguration['webUrl']);
                 }
                 if (isset($providerConfiguration['ref'])) {
                     $provider->setRepositoryRef($providerConfiguration['ref']);
                     $provider->setRepositoryRealRef($providerConfiguration['realRef']);
                 }
                 if (isset($providerConfiguration['realRef'])) {
                     $provider->setRepositoryRealRef($providerConfiguration['realRef']);
                 }
                 if (isset($providerConfiguration['refType'])) {
                     $provider->setRepositoryRefType($providerConfiguration['refType']);
                 } else {
                     $provider->setRepositoryRefType('commit');
                 }
                 $compoundProvider->addProvider($provider);
                 break;
             default:
                 throw new InvalidConfigurationException(sprintf('Provider type "%s" is not supported', $providerConfiguration['type']));
         }
     }
     if (isset($array['pre'])) {
         $compoundAction = new CompoundAction();
         $configuration->setPreAction($compoundAction);
         foreach ($array['pre'] as $action) {
             $action = (array) $action;
             $action = $this->parseAction($action);
             if ($action) {
                 $compoundAction->addAction($action);
             }
         }
     }
     if (isset($array['actions'])) {
         $compoundAction = new CompoundAction();
         $configuration->setAction($compoundAction);
         foreach ($array['actions'] as $action) {
             $action = (array) $action;
             $action = $this->parseAction($action);
             if ($action) {
                 $compoundAction->addAction($action);
             }
         }
     }
     if (isset($array['post'])) {
         $compoundAction = new CompoundAction();
         $configuration->setPostAction($compoundAction);
         foreach ($array['post'] as $action) {
             $action = (array) $action;
             $action = $this->parseAction($action);
             if ($action) {
                 $compoundAction->addAction($action);
             }
         }
     }
     if (isset($array['variables'])) {
         $configuration->setVariables($array['variables']);
     }
     return $configuration;
 }