Beispiel #1
0
 /**
  * {@inheritDoc}
  */
 public function getComposerInformation($identifier)
 {
     if (!isset($this->infoCache[$identifier])) {
         preg_match('{^(.+?)(@\\d+)?$}', $identifier, $match);
         if (!empty($match[2])) {
             $identifier = $match[1];
             $rev = $match[2];
         } else {
             $rev = '';
         }
         $this->process->execute(sprintf('svn cat --non-interactive %s', escapeshellarg($this->baseUrl . $identifier . 'composer.json' . $rev)), $composer);
         if (!trim($composer)) {
             throw new \UnexpectedValueException('Failed to retrieve composer information for identifier ' . $identifier . ' in ' . $this->getUrl());
         }
         $composer = JsonFile::parseJson($composer);
         if (!isset($composer['time'])) {
             $this->process->execute(sprintf('svn info %s', escapeshellarg($this->baseUrl . $identifier . $rev)), $output);
             foreach ($this->process->splitLines($output) as $line) {
                 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
                     $date = new \DateTime($match[1]);
                     $composer['time'] = $date->format('Y-m-d H:i:s');
                     break;
                 }
             }
         }
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
Beispiel #2
0
 public function authorizeOAuthInteractively($originUrl, $message = null)
 {
     $attemptCounter = 0;
     $apiUrl = 'github.com' === $originUrl ? 'api.github.com' : $originUrl . '/api/v3';
     if ($message) {
         $this->io->write($message);
     }
     $this->io->write('The credentials will be swapped for an OAuth token stored in ' . $this->config->get('home') . '/config.json, your password will not be stored');
     $this->io->write('To revoke access to this token you can visit https://github.com/settings/applications');
     while ($attemptCounter++ < 5) {
         try {
             $username = $this->io->ask('Username: '******'Password: '******'Composer';
             if (0 === $this->process->execute('hostname', $output)) {
                 $appName .= ' on ' . trim($output);
             }
             $contents = JsonFile::parseJson($this->remoteFilesystem->getContents($originUrl, 'https://' . $apiUrl . '/authorizations', false, array('http' => array('method' => 'POST', 'follow_location' => false, 'header' => "Content-Type: application/json\r\n", 'content' => json_encode(array('scopes' => array('repo'), 'note' => $appName, 'note_url' => 'https://getcomposer.org/'))))));
         } catch (TransportException $e) {
             if (in_array($e->getCode(), array(403, 401))) {
                 $this->io->write('Invalid credentials.');
                 continue;
             }
             throw $e;
         }
         $this->io->setAuthentication($originUrl, $contents['token'], 'x-oauth-basic');
         $githubTokens = $this->config->get('github-oauth') ?: array();
         $githubTokens[$originUrl] = $contents['token'];
         $this->config->getConfigSource()->addConfigSetting('github-oauth', $githubTokens);
         return true;
     }
     throw new \RuntimeException("Invalid GitHub credentials 5 times in a row, aborting.");
 }
 public function testNotifyBatch()
 {
     $packagesBuilder = new PackagesBuilder(new NullOutput(), vfsStream::url('build'), array('notify-batch' => 'http://localhost:54715/notify', 'repositories' => array(array('type' => 'composer', 'url' => 'http://localhost:54715')), 'require' => array('vendor/name' => '*')), false);
     $packages = array($this->package);
     $packagesBuilder->dump($packages);
     $packagesJson = JsonFile::parseJson($this->root->getChild('build/packages.json')->getContent());
     $this->assertEquals('http://localhost:54715/notify', $packagesJson['notify-batch']);
 }
Beispiel #4
0
 /**
  * Get composer information.
  *
  * @param string          $resource
  * @param ProcessExecutor $process
  * @param string          $cmdGet
  * @param string          $cmdLog
  * @param string          $repoDir
  * @param string          $datetimePrefix
  *
  * @return array The composer
  */
 protected static function doGetComposerInformation($resource, ProcessExecutor $process, $cmdGet, $cmdLog, $repoDir, $datetimePrefix = '')
 {
     $process->execute($cmdGet, $composer, $repoDir);
     if (!trim($composer)) {
         return array('_nonexistent_package' => true);
     }
     $composer = JsonFile::parseJson($composer, $resource);
     return static::addComposerTime($composer, $process, $cmdLog, $repoDir, $datetimePrefix);
 }
Beispiel #5
0
 public function load($json)
 {
     if ($json instanceof JsonFile) {
         $config = $json->read();
     } elseif (file_exists($json)) {
         $config = JsonFile::parseJson(file_get_contents($json));
     } elseif (is_string($json)) {
         $config = JsonFile::parseJson($json);
     }
     return parent::load($config);
 }
Beispiel #6
0
 public function getLatest()
 {
     $protocol = extension_loaded('openssl') ? 'https' : 'http';
     $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
     foreach ($versions[$this->getChannel()] as $version) {
         if ($version['min-php'] <= PHP_VERSION_ID) {
             return $version;
         }
     }
     throw new \LogicException('There is no version of Composer available for your PHP version (' . PHP_VERSION . ')');
 }
Beispiel #7
0
 /**
  * {@inheritDoc}
  */
 public function getBranches()
 {
     if (null === $this->branches) {
         $resource = $this->getScheme() . '://bitbucket.org/api/1.0/repositories/' . $this->owner . '/' . $this->repository . '/branches';
         $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
         $this->branches = array();
         foreach ($branchData as $branch => $data) {
             $this->branches[$branch] = $data['raw_node'];
         }
     }
     return $this->branches;
 }
Beispiel #8
0
 /**
  * {@inheritDoc}
  */
 public function getComposerInformation($identifier)
 {
     if (!isset($this->infoCache[$identifier])) {
         $composer = $this->getContents($this->getScheme() . '://raw.github.com/' . $this->owner . '/' . $this->repository . '/' . $identifier . '/composer.json');
         if (!$composer) {
             throw new \UnexpectedValueException('Failed to retrieve composer information for identifier ' . $identifier . ' in ' . $this->getUrl());
         }
         $composer = JsonFile::parseJson($composer);
         if (!isset($composer['time'])) {
             $commit = json_decode($this->getContents($this->getScheme() . '://api.github.com/repos/' . $this->owner . '/' . $this->repository . '/commits/' . $identifier), true);
             $composer['time'] = $commit['commit']['committer']['date'];
         }
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
Beispiel #9
0
 /**
  * {@inheritDoc}
  */
 public function getComposerInformation($identifier)
 {
     if (!isset($this->infoCache[$identifier])) {
         $composer = $this->getContents($this->getScheme() . '://bitbucket.org/' . $this->owner . '/' . $this->repository . '/raw/' . $identifier . '/composer.json');
         if (!$composer) {
             throw new \UnexpectedValueException('Failed to retrieve composer information for identifier ' . $identifier . ' in ' . $this->getUrl());
         }
         $composer = JsonFile::parseJson($composer);
         if (!isset($composer['time'])) {
             $changeset = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/' . $this->owner . '/' . $this->repository . '/changesets/' . $identifier), true);
             $composer['time'] = $changeset['timestamp'];
         }
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
Beispiel #10
0
 /**
  * Gets content of composer information.
  *
  * @param string             $resource   The resource
  * @param string             $identifier The identifier
  * @param string             $scheme     The scheme
  * @param string             $owner      The owner
  * @param string             $repository The repository
  * @param VcsDriverInterface $driver     The vcs driver
  * @param string             $method     The method for get content
  *
  * @return array
  */
 protected static function getComposerContent($resource, $identifier, $scheme, $owner, $repository, $driver, $method)
 {
     try {
         $ref = new \ReflectionClass($driver);
         $meth = $ref->getMethod($method);
         $meth->setAccessible(true);
         $composer = $meth->invoke($driver, $resource);
     } catch (\Exception $e) {
         $composer = false;
     }
     if ($composer) {
         $composer = (array) JsonFile::parseJson((string) $composer, $resource);
         $composer = static::formatComposerContent($composer, $identifier, $scheme, $owner, $repository, $driver, $method);
         return $composer;
     }
     return array('_nonexistent_package' => true);
 }
 public function testNominalCase()
 {
     $arrayPackage = array("vendor/name" => array("1.0" => array("name" => "vendor/name", "version" => "1.0", "version_normalized" => "1.0.0.0", "type" => "library")));
     vfsStreamWrapper::register();
     $root = vfsStream::newDirectory('build');
     vfsStreamWrapper::setRoot($root);
     $packagesBuilder = new PackagesBuilder(new NullOutput(), vfsStream::url('build'), array('repositories' => array(array('type' => 'composer', 'url' => 'http://localhost:54715')), 'require' => array('vendor/name' => '*')), false);
     $packages = array(new Package('vendor/name', '1.0.0.0', '1.0'));
     $packagesBuilder->dump($packages);
     $packagesJson = JsonFile::parseJson($root->getChild('build/packages.json')->getContent());
     $tmpArray = array_keys($packagesJson['includes']);
     $includeJson = array_shift($tmpArray);
     $includeJsonFile = 'build/' . $includeJson;
     $this->assertTrue(is_file(vfsStream::url($includeJsonFile)));
     $packagesIncludeJson = JsonFile::parseJson($root->getChild($includeJsonFile)->getContent());
     $this->assertEquals($arrayPackage, $packagesIncludeJson['packages']);
 }
Beispiel #12
0
 public function getComposerInformation($identifier)
 {
     if (!isset($this->infoCache[$identifier])) {
         $this->process->execute(sprintf('hg cat -r %s composer.json', escapeshellarg($identifier)), $composer, $this->repoDir);
         if (!trim($composer)) {
             return;
         }
         $composer = JsonFile::parseJson($composer, $identifier);
         if (!isset($composer['time'])) {
             $this->process->execute(sprintf('hg log --template "{date|rfc3339date}" -r %s', escapeshellarg($identifier)), $output, $this->repoDir);
             $date = new \DateTime(trim($output), new \DateTimeZone('UTC'));
             $composer['time'] = $date->format('Y-m-d H:i:s');
         }
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
Beispiel #13
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $file = $input->getArgument('file');
     if (!file_exists($file)) {
         $output->writeln('<error>' . $file . ' not found.</error>');
         return 1;
     }
     if (!is_readable($file)) {
         $output->writeln('<error>' . $file . ' is not readable.</error>');
         return 1;
     }
     try {
         JsonFile::parseJson(file_get_contents($file));
     } catch (\Exception $e) {
         $output->writeln('<error>' . $e->getMessage() . '</error>');
         return 1;
     }
     $output->writeln('<info>' . $file . ' is valid</info>');
 }
 private function getComposerInformation(\SplFileInfo $file)
 {
     $zip = new \ZipArchive();
     $zip->open($file->getPathname());
     if (0 == $zip->numFiles) {
         return false;
     }
     $foundFileIndex = $zip->locateName('composer.json', \ZipArchive::FL_NODIR);
     if (false === $foundFileIndex) {
         return false;
     }
     $configurationFileName = $zip->getNameIndex($foundFileIndex);
     $composerFile = "zip://{$file->getPathname()}#{$configurationFileName}";
     $json = file_get_contents($composerFile);
     $package = JsonFile::parseJson($json, $composerFile);
     $package['dist'] = array('type' => 'zip', 'url' => $file->getRealPath(), 'reference' => $file->getBasename(), 'shasum' => sha1_file($file->getRealPath()));
     $package = $this->loader->load($package);
     return $package;
 }
 public function getIndex()
 {
     $defaults = Config::get('ComposerUI::defaults');
     $workingDir = Input::get('workingDir', $defaults['workingDir']);
     $realpath = realpath($workingDir);
     if ($realpath != $workingDir && $realpath != false) {
         return Redirect::to('composer?workingDir=' . urlencode($realpath));
     } else {
         $jsonComposer = null;
         if (file_exists($workingDir . DIRECTORY_SEPARATOR . 'composer.json')) {
             try {
                 $jsonComposer = JsonFile::parseJson(file_get_contents($workingDir . DIRECTORY_SEPARATOR . 'composer.json'));
             } catch (Exception $e) {
                 $jsonComposer = null;
             }
         }
         Session::put("ComposerUI.workingDir", $workingDir);
         return View::make('ComposerUI::home')->with(array('workingDir' => $workingDir, 'jsonComposer' => $jsonComposer));
     }
 }
 /**
  * @param  IOInterface $io
  * @param  Config      $config
  * @param  string      $repository
  * @param  bool        $allowFilesystem
  * @return array|mixed
  */
 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
 {
     if (0 === strpos($repository, 'http')) {
         $repoConfig = array('type' => 'composer', 'url' => $repository);
     } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
         $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
         $data = $json->read();
         if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
             $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
         } elseif ($allowFilesystem) {
             $repoConfig = array('type' => 'filesystem', 'json' => $json);
         } else {
             throw new \InvalidArgumentException("Invalid repository URL ({$repository}) given. This file does not contain a valid composer repository.");
         }
     } elseif ('{' === substr($repository, 0, 1)) {
         // assume it is a json object that makes a repo config
         $repoConfig = JsonFile::parseJson($repository);
     } else {
         throw new \InvalidArgumentException("Invalid repository url ({$repository}) given. Has to be a .json file, an http url or a JSON object.");
     }
     return $repoConfig;
 }
Beispiel #17
0
 /**
  * Initializes path repository.
  *
  * This method will basically read the folder and add the found package.
  */
 protected function initialize()
 {
     parent::initialize();
     foreach ($this->getUrlMatches() as $url) {
         $path = realpath($url) . DIRECTORY_SEPARATOR;
         $composerFilePath = $path . 'composer.json';
         if (!file_exists($composerFilePath)) {
             continue;
         }
         $json = file_get_contents($composerFilePath);
         $package = JsonFile::parseJson($json, $composerFilePath);
         $package['dist'] = array('type' => 'path', 'url' => $url, 'reference' => '');
         if (!isset($package['version'])) {
             $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master';
         }
         $output = '';
         if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
             $package['dist']['reference'] = trim($output);
         } else {
             $package['dist']['reference'] = Locker::getContentHash($json);
         }
         $package = $this->loader->load($package);
         $this->addPackage($package);
     }
     if (count($this->getPackages()) == 0) {
         throw new \RuntimeException(sprintf('No `composer.json` file found in any path repository in "%s"', $this->url));
     }
 }
Beispiel #18
0
 protected function fetchProject()
 {
     // we need to fetch the default branch from the api
     $resource = $this->getApiUrl();
     $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
 }
Beispiel #19
0
 /**
  * {@inheritDoc}
  */
 public function getComposerInformation($identifier)
 {
     $identifier = '/' . trim($identifier, '/') . '/';
     if ($res = $this->cache->read($identifier . '.json')) {
         $this->infoCache[$identifier] = JsonFile::parseJson($res);
     }
     if (!isset($this->infoCache[$identifier])) {
         preg_match('{^(.+?)(@\\d+)?/$}', $identifier, $match);
         if (!empty($match[2])) {
             $path = $match[1];
             $rev = $match[2];
         } else {
             $path = $identifier;
             $rev = '';
         }
         try {
             $resource = $path . 'composer.json';
             $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
             if (!trim($output)) {
                 return;
             }
         } catch (\RuntimeException $e) {
             throw new TransportException($e->getMessage());
         }
         $composer = JsonFile::parseJson($output, $this->baseUrl . $resource . $rev);
         if (!isset($composer['time'])) {
             $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
             foreach ($this->process->splitLines($output) as $line) {
                 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
                     $date = new \DateTime($match[1], new \DateTimeZone('UTC'));
                     $composer['time'] = $date->format('Y-m-d H:i:s');
                     break;
                 }
             }
         }
         $this->cache->write($identifier . '.json', json_encode($composer));
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
Beispiel #20
0
 /**
  * {@inheritDoc}
  */
 public function getComposerInformation($identifier)
 {
     if (!isset($this->infoCache[$identifier])) {
         $resource = sprintf('%s:composer.json', escapeshellarg($identifier));
         $this->process->execute(sprintf('git show %s', $resource), $composer, $this->repoDir);
         if (!trim($composer)) {
             return;
         }
         $composer = JsonFile::parseJson($composer, $resource);
         if (!isset($composer['time'])) {
             $this->process->execute(sprintf('git log -1 --format=%%at %s', escapeshellarg($identifier)), $output, $this->repoDir);
             $date = new \DateTime('@' . trim($output));
             $composer['time'] = $date->format('Y-m-d H:i:s');
         }
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
 private function expectParseException($text, $json)
 {
     try {
         JsonFile::parseJson($json);
         $this->fail();
     } catch (ParsingException $e) {
         $this->assertContains($text, $e->getMessage());
     }
 }
 protected function fetchFile($filename, $cacheKey = null, $sha256 = null)
 {
     if (null === $cacheKey) {
         $cacheKey = $filename;
         $filename = $this->baseUrl . '/' . $filename;
     }
     $retries = 3;
     while ($retries--) {
         try {
             $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
             if ($this->eventDispatcher) {
                 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
             }
             $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
             $json = $preFileDownloadEvent->getRemoteFilesystem()->getContents($hostname, $filename, false);
             if ($sha256 && $sha256 !== hash('sha256', $json)) {
                 if ($retries) {
                     usleep(100000);
                     continue;
                 }
                 // TODO use scarier wording once we know for sure it doesn't do false positives anymore
                 throw new RepositorySecurityException('The contents of ' . $filename . ' do not match its signature. This should indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.');
             }
             $data = JsonFile::parseJson($json, $filename);
             if ($cacheKey) {
                 $this->cache->write($cacheKey, $json);
             }
             break;
         } catch (\Exception $e) {
             if ($retries) {
                 usleep(100000);
                 continue;
             }
             if ($e instanceof RepositorySecurityException) {
                 throw $e;
             }
             if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
                 if (!$this->degradedMode) {
                     $this->io->write('<warning>' . $e->getMessage() . '</warning>');
                     $this->io->write('<warning>' . $this->url . ' could not be fully loaded, package information was loaded from the local cache and may be out of date</warning>');
                 }
                 $this->degradedMode = true;
                 $data = JsonFile::parseJson($contents, $this->cache->getRoot() . $cacheKey);
                 break;
             }
             throw $e;
         }
     }
     return $data;
 }
Beispiel #23
0
 /**
  * {@inheritDoc}
  */
 public function getComposerInformation($identifier)
 {
     if (!isset($this->infoCache[$identifier])) {
         $this->process->execute(sprintf('cd %s && git show %s:composer.json', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $composer);
         if (!trim($composer)) {
             throw new \UnexpectedValueException('Failed to retrieve composer information for identifier ' . $identifier . ' in ' . $this->getUrl());
         }
         $composer = JsonFile::parseJson($composer);
         if (!isset($composer['time'])) {
             $this->process->execute(sprintf('cd %s && git log -1 --format=%%at %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output);
             $date = new \DateTime('@' . trim($output));
             $composer['time'] = $date->format('Y-m-d H:i:s');
         }
         $this->infoCache[$identifier] = $composer;
     }
     return $this->infoCache[$identifier];
 }
Beispiel #24
0
 /**
  * {@inheritdoc}
  */
 public function getChangeDate($identifier)
 {
     if ($this->fallbackDriver) {
         return $this->fallbackDriver->getChangeDate($identifier);
     }
     $resource = $this->getScheme() . '://api.bitbucket.org/1.0/repositories/' . $this->owner . '/' . $this->repository . '/changesets/' . $identifier;
     $changeset = JsonFile::parseJson($this->getContents($resource), $resource);
     return new \DateTime($changeset['timestamp']);
 }
Beispiel #25
0
 private function createToken($originUrl, $otp = null)
 {
     if (null === $otp || !$this->io->hasAuthentication($originUrl)) {
         $username = $this->io->ask('Username: '******'Password: '******'Content-Type: application/json');
     if ($otp) {
         $headers[] = 'X-GitHub-OTP: ' . $otp;
     }
     $note = 'Composer';
     if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
         $note .= ' on ' . trim($output);
     }
     $note .= ' [' . date('YmdHis') . ']';
     $apiUrl = 'github.com' === $originUrl ? 'api.github.com' : $originUrl . '/api/v3';
     $json = $this->remoteFilesystem->getContents($originUrl, 'https://' . $apiUrl . '/authorizations', false, array('retry-auth-failure' => false, 'http' => array('method' => 'POST', 'follow_location' => false, 'header' => $headers, 'content' => json_encode(array('scopes' => array('repo'), 'note' => $note, 'note_url' => 'https://getcomposer.org/')))));
     $this->io->writeError('Token successfully created');
     return JsonFile::parseJson($json);
 }
 /**
  * {@inheritDoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Open file in editor
     if ($input->getOption('editor')) {
         $editor = escapeshellcmd(getenv('EDITOR'));
         if (!$editor) {
             if (Platform::isWindows()) {
                 $editor = 'notepad';
             } else {
                 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
                     if (exec('which ' . $candidate)) {
                         $editor = $candidate;
                         break;
                     }
                 }
             }
         }
         $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
         system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
         return 0;
     }
     if (!$input->getOption('global')) {
         $this->config->merge($this->configFile->read());
         $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
     }
     // List the configuration of the file settings
     if ($input->getOption('list')) {
         $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
         return 0;
     }
     $settingKey = $input->getArgument('setting-key');
     if (!$settingKey) {
         return 0;
     }
     // If the user enters in a config variable, parse it and save to file
     if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
         throw new \RuntimeException('You can not combine a setting value with --unset');
     }
     // show the value if no value is provided
     if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
         $data = $this->config->all();
         if (preg_match('/^repos?(?:itories)?(?:\\.(.+))?/', $settingKey, $matches)) {
             if (empty($matches[1])) {
                 $value = isset($data['repositories']) ? $data['repositories'] : array();
             } else {
                 if (!isset($data['repositories'][$matches[1]])) {
                     throw new \InvalidArgumentException('There is no ' . $matches[1] . ' repository defined');
                 }
                 $value = $data['repositories'][$matches[1]];
             }
         } elseif (strpos($settingKey, '.')) {
             $bits = explode('.', $settingKey);
             $data = $data['config'];
             $match = false;
             foreach ($bits as $bit) {
                 $key = isset($key) ? $key . '.' . $bit : $bit;
                 $match = false;
                 if (isset($data[$key])) {
                     $match = true;
                     $data = $data[$key];
                     unset($key);
                 }
             }
             if (!$match) {
                 throw new \RuntimeException($settingKey . ' is not defined.');
             }
             $value = $data;
         } elseif (isset($data['config'][$settingKey])) {
             $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
         } else {
             throw new \RuntimeException($settingKey . ' is not defined');
         }
         if (is_array($value)) {
             $value = json_encode($value);
         }
         $this->getIO()->write($value);
         return 0;
     }
     $values = $input->getArgument('setting-value');
     // what the user is trying to add/change
     $booleanValidator = function ($val) {
         return in_array($val, array('true', 'false', '1', '0'), true);
     };
     $booleanNormalizer = function ($val) {
         return $val !== 'false' && (bool) $val;
     };
     // handle config values
     $uniqueConfigValues = array('process-timeout' => array('is_numeric', 'intval'), 'use-include-path' => array($booleanValidator, $booleanNormalizer), 'preferred-install' => array(function ($val) {
         return in_array($val, array('auto', 'source', 'dist'), true);
     }, function ($val) {
         return $val;
     }), 'store-auths' => array(function ($val) {
         return in_array($val, array('true', 'false', 'prompt'), true);
     }, function ($val) {
         if ('prompt' === $val) {
             return 'prompt';
         }
         return $val !== 'false' && (bool) $val;
     }), 'notify-on-install' => array($booleanValidator, $booleanNormalizer), 'vendor-dir' => array('is_string', function ($val) {
         return $val;
     }), 'bin-dir' => array('is_string', function ($val) {
         return $val;
     }), 'archive-dir' => array('is_string', function ($val) {
         return $val;
     }), 'archive-format' => array('is_string', function ($val) {
         return $val;
     }), 'data-dir' => array('is_string', function ($val) {
         return $val;
     }), 'cache-dir' => array('is_string', function ($val) {
         return $val;
     }), 'cache-files-dir' => array('is_string', function ($val) {
         return $val;
     }), 'cache-repo-dir' => array('is_string', function ($val) {
         return $val;
     }), 'cache-vcs-dir' => array('is_string', function ($val) {
         return $val;
     }), 'cache-ttl' => array('is_numeric', 'intval'), 'cache-files-ttl' => array('is_numeric', 'intval'), 'cache-files-maxsize' => array(function ($val) {
         return preg_match('/^\\s*([0-9.]+)\\s*(?:([kmg])(?:i?b)?)?\\s*$/i', $val) > 0;
     }, function ($val) {
         return $val;
     }), 'bin-compat' => array(function ($val) {
         return in_array($val, array('auto', 'full'));
     }, function ($val) {
         return $val;
     }), 'discard-changes' => array(function ($val) {
         return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
     }, function ($val) {
         if ('stash' === $val) {
             return 'stash';
         }
         return $val !== 'false' && (bool) $val;
     }), 'autoloader-suffix' => array('is_string', function ($val) {
         return $val === 'null' ? null : $val;
     }), 'sort-packages' => array($booleanValidator, $booleanNormalizer), 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer), 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer), 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer), 'disable-tls' => array($booleanValidator, $booleanNormalizer), 'secure-http' => array($booleanValidator, $booleanNormalizer), 'cafile' => array(function ($val) {
         return file_exists($val) && is_readable($val);
     }, function ($val) {
         return $val === 'null' ? null : $val;
     }), 'capath' => array(function ($val) {
         return is_dir($val) && is_readable($val);
     }, function ($val) {
         return $val === 'null' ? null : $val;
     }), 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer));
     $multiConfigValues = array('github-protocols' => array(function ($vals) {
         if (!is_array($vals)) {
             return 'array expected';
         }
         foreach ($vals as $val) {
             if (!in_array($val, array('git', 'https', 'ssh'))) {
                 return 'valid protocols include: git, https, ssh';
             }
         }
         return true;
     }, function ($vals) {
         return $vals;
     }), 'github-domains' => array(function ($vals) {
         if (!is_array($vals)) {
             return 'array expected';
         }
         return true;
     }, function ($vals) {
         return $vals;
     }), 'gitlab-domains' => array(function ($vals) {
         if (!is_array($vals)) {
             return 'array expected';
         }
         return true;
     }, function ($vals) {
         return $vals;
     }));
     foreach ($uniqueConfigValues as $name => $callbacks) {
         if ($settingKey === $name) {
             if ($input->getOption('unset')) {
                 return $this->configSource->removeConfigSetting($settingKey);
             }
             list($validator, $normalizer) = $callbacks;
             if (1 !== count($values)) {
                 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
             }
             if (true !== ($validation = $validator($values[0]))) {
                 throw new \RuntimeException(sprintf('"%s" is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), $values[0]));
             }
             return $this->configSource->addConfigSetting($settingKey, $normalizer($values[0]));
         }
     }
     foreach ($multiConfigValues as $name => $callbacks) {
         if ($settingKey === $name) {
             if ($input->getOption('unset')) {
                 return $this->configSource->removeConfigSetting($settingKey);
             }
             list($validator, $normalizer) = $callbacks;
             if (true !== ($validation = $validator($values))) {
                 throw new \RuntimeException(sprintf('%s is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), json_encode($values)));
             }
             return $this->configSource->addConfigSetting($settingKey, $normalizer($values));
         }
     }
     // handle repositories
     if (preg_match('/^repos?(?:itories)?\\.(.+)/', $settingKey, $matches)) {
         if ($input->getOption('unset')) {
             return $this->configSource->removeRepository($matches[1]);
         }
         if (2 === count($values)) {
             return $this->configSource->addRepository($matches[1], array('type' => $values[0], 'url' => $values[1]));
         }
         if (1 === count($values)) {
             $value = strtolower($values[0]);
             if (true === $booleanValidator($value)) {
                 if (false === $booleanNormalizer($value)) {
                     return $this->configSource->addRepository($matches[1], false);
                 }
             } else {
                 $value = JsonFile::parseJson($values[0]);
                 return $this->configSource->addRepository($matches[1], $value);
             }
         }
         throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
     }
     // handle platform
     if (preg_match('/^platform\\.(.+)/', $settingKey, $matches)) {
         if ($input->getOption('unset')) {
             return $this->configSource->removeConfigSetting($settingKey);
         }
         return $this->configSource->addConfigSetting($settingKey, $values[0]);
     }
     // handle github-oauth
     if (preg_match('/^(github-oauth|gitlab-oauth|http-basic)\\.(.+)/', $settingKey, $matches)) {
         if ($input->getOption('unset')) {
             $this->authConfigSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
             $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
             return;
         }
         if ($matches[1] === 'github-oauth' || $matches[1] === 'gitlab-oauth') {
             if (1 !== count($values)) {
                 throw new \RuntimeException('Too many arguments, expected only one token');
             }
             $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
             $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], $values[0]);
         } elseif ($matches[1] === 'http-basic') {
             if (2 !== count($values)) {
                 throw new \RuntimeException('Expected two arguments (username, password), got ' . count($values));
             }
             $this->configSource->removeConfigSetting($matches[1] . '.' . $matches[2]);
             $this->authConfigSource->addConfigSetting($matches[1] . '.' . $matches[2], array('username' => $values[0], 'password' => $values[1]));
         }
         return;
     }
     throw new \InvalidArgumentException('Setting ' . $settingKey . ' does not exist or is not supported by this command');
 }
Beispiel #27
0
 /**
  * @param InputInterface $input The input instance
  * @param OutputInterface $output The output instance
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $verbose = $input->getOption('verbose');
     $configFile = $input->getArgument('file');
     $packagesFilter = $input->getArgument('packages');
     $repositoryUrl = $input->getOption('repository-url');
     $skipErrors = (bool) $input->getOption('skip-errors');
     if ($repositoryUrl !== null && count($packagesFilter) > 0) {
         throw new \InvalidArgumentException('The arguments "package" and "repository-url" can not be used together.');
     }
     // load auth.json authentication information and pass it to the io interface
     $io = $this->getIO();
     $io->loadConfiguration($this->getConfiguration());
     if (preg_match('{^https?://}i', $configFile)) {
         $rfs = new RemoteFilesystem($io);
         $contents = $rfs->getContents(parse_url($configFile, PHP_URL_HOST), $configFile, false);
         $config = JsonFile::parseJson($contents, $configFile);
     } else {
         $file = new JsonFile($configFile);
         if (!$file->exists()) {
             $output->writeln('<error>File not found: ' . $configFile . '</error>');
             return 1;
         }
         $config = $file->read();
     }
     // disable packagist by default
     unset(Config::$defaultRepositories['packagist']);
     if (!($outputDir = $input->getArgument('output-dir'))) {
         $outputDir = isset($config['output-dir']) ? $config['output-dir'] : null;
     }
     if (null === $outputDir) {
         throw new \InvalidArgumentException('The output dir must be specified as second argument or be configured inside ' . $input->getArgument('file'));
     }
     $composer = $this->getApplication()->getComposer(true, $config);
     $packageSelection = new PackageSelection($output, $outputDir, $config, $skipErrors);
     if ($repositoryUrl !== null) {
         $packageSelection->setRepositoryFilter($repositoryUrl);
     } else {
         $packageSelection->setPackagesFilter($packagesFilter);
     }
     $packages = $packageSelection->select($composer, $verbose);
     if (isset($config['archive']['directory'])) {
         $downloads = new ArchiveBuilder($output, $outputDir, $config, $skipErrors);
         $downloads->setComposer($composer);
         $downloads->dump($packages);
     }
     if ($packageSelection->hasFilterForPackages()) {
         // in case of an active package filter we need to load the dumped packages.json and merge the
         // updated packages in
         $oldPackages = $packageSelection->load();
         $packages += $oldPackages;
         ksort($packages);
     }
     $packagesBuilder = new PackagesBuilder($output, $outputDir, $config, $skipErrors);
     $packagesBuilder->dump($packages);
     if ($htmlView = !$input->getOption('no-html-output')) {
         $htmlView = !isset($config['output-html']) || $config['output-html'];
     }
     if ($htmlView) {
         $web = new WebBuilder($output, $outputDir, $config, $skipErrors);
         $web->setRootPackage($composer->getPackage());
         $web->dump($packages);
     }
 }
Beispiel #28
0
    public function getIntegrationTests()
    {
        $fixturesDir = realpath(__DIR__.'/Fixtures/installer/');
        $tests = array();

        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
            if (!preg_match('/\.test$/', $file)) {
                continue;
            }

            $test = file_get_contents($file->getRealpath());

            $content = '(?:.(?!--[A-Z]))+';
            $pattern = '{^
                --TEST--\s*(?P<test>.*?)\s*
                (?:--CONDITION--\s*(?P<condition>'.$content.'))?\s*
                --COMPOSER--\s*(?P<composer>'.$content.')\s*
                (?:--LOCK--\s*(?P<lock>'.$content.'))?\s*
                (?:--INSTALLED--\s*(?P<installed>'.$content.'))?\s*
                --RUN--\s*(?P<run>.*?)\s*
                (?:--EXPECT-LOCK--\s*(?P<expectLock>'.$content.'))?\s*
                (?:--EXPECT-OUTPUT--\s*(?P<expectOutput>'.$content.'))?\s*
                --EXPECT--\s*(?P<expect>.*?)\s*
            $}xs';

            $installed = array();
            $installedDev = array();
            $lock = array();
            $expectLock = array();

            if (preg_match($pattern, $test, $match)) {
                try {
                    $message = $match['test'];
                    $condition = !empty($match['condition']) ? $match['condition'] : null;
                    $composer = JsonFile::parseJson($match['composer']);
                    if (!empty($match['lock'])) {
                        $lock = JsonFile::parseJson($match['lock']);
                        if (!isset($lock['hash'])) {
                            $lock['hash'] = md5(json_encode($composer));
                        }
                    }
                    if (!empty($match['installed'])) {
                        $installed = JsonFile::parseJson($match['installed']);
                    }
                    $run = $match['run'];
                    if (!empty($match['expectLock'])) {
                        $expectLock = JsonFile::parseJson($match['expectLock']);
                    }
                    $expectOutput = $match['expectOutput'];
                    $expect = $match['expect'];
                } catch (\Exception $e) {
                    die(sprintf('Test "%s" is not valid: '.$e->getMessage(), str_replace($fixturesDir.'/', '', $file)));
                }
            } else {
                die(sprintf('Test "%s" is not valid, did not match the expected format.', str_replace($fixturesDir.'/', '', $file)));
            }

            $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $composer, $lock, $installed, $run, $expectLock, $expectOutput, $expect);
        }

        return $tests;
    }
 /**
  * Fetch root identifier from GitHub
  *
  * @throws TransportException
  */
 protected function fetchRootIdentifier()
 {
     $repoDataUrl = $this->getApiUrl() . '/repos/' . $this->owner . '/' . $this->repository;
     $repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
     if (null === $repoData && null !== $this->gitDriver) {
         return;
     }
     $this->owner = $repoData['owner']['login'];
     $this->repository = $repoData['name'];
     $this->isPrivate = !empty($repoData['private']);
     if (isset($repoData['default_branch'])) {
         $this->rootIdentifier = $repoData['default_branch'];
     } elseif (isset($repoData['master_branch'])) {
         $this->rootIdentifier = $repoData['master_branch'];
     } else {
         $this->rootIdentifier = 'master';
     }
     $this->hasIssues = !empty($repoData['has_issues']);
 }
 public function addMainKey($key, $content)
 {
     $decoded = JsonFile::parseJson($this->contents);
     $content = $this->format($content);
     // key exists already
     $regex = '{^(\\s*\\{\\s*(?:' . self::$JSON_STRING . '\\s*:\\s*' . self::$JSON_VALUE . '\\s*,\\s*)*?)' . '(' . preg_quote(JsonFile::encode($key)) . '\\s*:\\s*' . self::$JSON_VALUE . ')(.*)}s';
     if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
         // invalid match due to un-regexable content, abort
         if (!@json_decode('{' . $matches[2] . '}')) {
             return false;
         }
         $this->contents = $matches[1] . JsonFile::encode($key) . ': ' . $content . $matches[3];
         return true;
     }
     // append at the end of the file and keep whitespace
     if ($this->pregMatch('#[^{\\s](\\s*)\\}$#', $this->contents, $match)) {
         $this->contents = preg_replace('#' . $match[1] . '\\}$#', addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key) . ': ' . $content . $this->newline . '}', '\\'), $this->contents);
         return true;
     }
     // append at the end of the file
     $this->contents = preg_replace('#\\}$#', addcslashes($this->indent . JsonFile::encode($key) . ': ' . $content . $this->newline . '}', '\\'), $this->contents);
     return true;
 }