/** * {@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]; }
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']); }
/** * 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); }
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); }
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 . ')'); }
/** * {@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; }
/** * {@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]; }
/** * {@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]; }
/** * 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']); }
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]; }
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; }
/** * 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)); } }
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); }
/** * {@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]; }
/** * {@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; }
/** * {@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]; }
/** * {@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']); }
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'); }
/** * @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); } }
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; }