phpcs.xml.dist 0000666 00000001367 13436756440 0007374 0 ustar 00
prestissimo coding rules
src
tests
Please review this TODO comment: %s
3
.scrutinizer.yml 0000666 00000000153 13436756440 0007745 0 ustar 00 imports:
- php
filter:
excluded_paths:
- tests/*
tools:
external_code_coverage: true
LICENSE 0000666 00000002101 13436756440 0005563 0 ustar 00 The MIT License (MIT)
Copyright (c) 2015 Hiraku NAKANO
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md 0000666 00000007400 13436756440 0006044 0 ustar 00 prestissimo (composer plugin)
=================================
[![Build Status](https://travis-ci.org/hirak/prestissimo.svg?branch=master)](https://travis-ci.org/hirak/prestissimo)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/hirak/prestissimo/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/hirak/prestissimo/?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/hirak/prestissimo/badge.svg?branch=master)](https://coveralls.io/github/hirak/prestissimo?branch=master)
[![HHVM Status](http://hhvm.h4cc.de/badge/hirak/prestissimo.svg?style=flat)](http://hhvm.h4cc.de/package/hirak/prestissimo)
[![Latest Stable Version](https://poser.pugx.org/hirak/prestissimo/v/stable)](https://packagist.org/packages/hirak/prestissimo)
[![Total Downloads](https://poser.pugx.org/hirak/prestissimo/downloads)](https://packagist.org/packages/hirak/prestissimo)
[![License](https://poser.pugx.org/hirak/prestissimo/license)](https://packagist.org/packages/hirak/prestissimo)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/56ca0f9e-63a2-4e89-b5f8-e0cc39d0c38f/big.png)](https://insight.sensiolabs.com/projects/56ca0f9e-63a2-4e89-b5f8-e0cc39d0c38f)
[composer](https://getcomposer.org) parallel install plugin.
## Requirements
- composer `>=1.0.0` (includes dev-master)
- PHP `>=5.3`, (suggest `>=5.5`, because `curl_share_init`)
- ext-curl
## Install
```bash
$ composer global require "hirak/prestissimo:^0.3"
```
## Uninstall
```bash
$ composer global remove hirak/prestissimo
```
## Benchmark Example
288s -> 26s
```bash
$ composer create-project laravel/laravel laravel1 --no-progress --profile --prefer-dist
```
![laravel](https://cloud.githubusercontent.com/assets/835251/12534815/55071302-c2ad-11e5-96a4-72e2c8744d5f.gif)
## Config
### `prestissimo ^0.3.x`
Recognize composer's options. You don't need to set any special configuration.
- [config.capath](https://getcomposer.org/doc/06-config.md#capath)
- [config.cafile](https://getcomposer.org/doc/06-config.md#cafile)
### `prestissimo ^0.2.x`
in local `composer.json` or `~/.composer/config.json`
```json
{
...
"config": {
"prestissimo": {
"maxConnections": 6,
"minConnections": 3,
"verbose": false,
"insecure": false,
"cainfo": "/absolute/path/to/cacert.pem",
"userAgent": "Your Awesome User Agent",
"privatePackages": [
"myorg/private1", "myorg/private2", ...
]
}
}
...
}
```
### maxConnections (int)
* default: 6
Limit connections for parallel downloading.
### verbose (bool)
* default: false
`CURLOPT_VERBOSE` option.
### insecure (bool)
* default: false
If insecure is true, this plugin doesn't verify all https certs. (`CURLOPT_SSL_VERIFYPEER` is off)
You SHOULD NOT change this option.
### cainfo (string)
* default: "" (empty)
An absolute path to cacert.pem
### userAgent (string)
* default: "" (empty)
User Agent for downloading. `CURLOPT_USERAGENT` option.
If userAgent is empty, composer user agent is used.
### privatePackages (string[])
* default: empty
If you list packages in this option, the local redirector(api.github.com -> codeload.github.com) will be off.
## Composer authentication
It is also recommended to use [composer's authentication](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens)
as you may run into access errors otherwise due to request restriction for anonymous user for external services like github.
For github.com you can use an `auth.json` with an [oauth access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/) placed on your on the same level as your `composer.json`:
```json
{
"github-oauth": {
"github.com": "YOUR_GITHUB_ACCESS_TOKEN"
}
}
```
## License
MIT License. See the LICENSE file.
src/FetchException.php 0000666 00000000301 13436756440 0010766 0 ustar 00 disable();
}
// @codeCoverageIgnoreEnd
// load all classes
foreach (self::$pluginClasses as $class) {
class_exists(__NAMESPACE__ . '\\' . $class);
}
$this->io = $io;
$this->config = $composer->getConfig();
$this->package = $composer->getPackage();
foreach ($GLOBALS['argv'] as $arg) {
switch ($arg) {
case 'create-project':
case 'update':
case 'outdated':
case 'require':
$this->prefetchComposerRepositories();
break 2;
case 'install':
if (file_exists('composer.json') && !file_exists('composer.lock')) {
$this->prefetchComposerRepositories();
}
break 2;
}
}
}
public static function getSubscribedEvents()
{
return array(
CPlugin\PluginEvents::PRE_FILE_DOWNLOAD => 'onPreFileDownload',
// Script\ScriptEvents::POST_ROOT_PACKAGE_INSTALL => 'prefetchComposerRepositories',
// Installer\InstallerEvents::PRE_DEPENDENCIES_SOLVING => 'prefetchComposerRepositories',
Installer\InstallerEvents::POST_DEPENDENCIES_SOLVING => array(
array('onPostDependenciesSolving', PHP_INT_MAX),
),
);
}
/**
* Keep-Alived file downloader
*/
public function onPreFileDownload(CPlugin\PreFileDownloadEvent $ev)
{
if ($this->disabled) {
return;
}
$rfs = $ev->getRemoteFilesystem();
$curlrfs = new CurlRemoteFilesystem(
$this->io,
$this->config,
$rfs->getOptions()
);
$ev->setRemoteFilesystem($curlrfs);
}
public function prefetchComposerRepositories()
{
if ($this->disabled) {
return;
}
if ($this->cached) {
return;
}
$repos = $this->package->getRepositories();
foreach ($repos as $label => $repo) {
if (isset($repo['type']) && $repo['type'] === 'composer') {
$r = new ParallelizedComposerRepository($repo, $this->io, $this->config);
$r->prefetch();
}
}
$this->cached = true;
}
/**
* pre-fetch parallel by curl_multi
*/
public function onPostDependenciesSolving(Installer\InstallerEvent $ev)
{
if ($this->disabled) {
return;
}
$prefetcher = new Prefetcher;
$prefetcher->fetchAllFromOperations(
$this->io,
$this->config,
$ev->getOperations()
);
}
public function disable()
{
$this->disabled = true;
}
public function isDisabled()
{
return $this->disabled;
}
}
src/BaseRequest.php 0000666 00000016371 13436756440 0010317 0 ustar 00 string] */
private $headers = array();
private $capath;
private $cafile;
protected static $defaultCurlOptions = array();
private static $NSS_CIPHERS = array(
'rsa_3des_sha',
'rsa_des_sha',
'rsa_null_md5',
'rsa_null_sha',
'rsa_rc2_40_md5',
'rsa_rc4_128_md5',
'rsa_rc4_128_sha',
'rsa_rc4_40_md5',
'fips_des_sha',
'fips_3des_sha',
'rsa_des_56_sha',
'rsa_rc4_56_sha',
'rsa_aes_128_sha',
'rsa_aes_256_sha',
'rsa_aes_128_gcm_sha_256',
'dhe_rsa_aes_128_gcm_sha_256',
'ecdh_ecdsa_null_sha',
'ecdh_ecdsa_rc4_128_sha',
'ecdh_ecdsa_3des_sha',
'ecdh_ecdsa_aes_128_sha',
'ecdh_ecdsa_aes_256_sha',
'ecdhe_ecdsa_null_sha',
'ecdhe_ecdsa_rc4_128_sha',
'ecdhe_ecdsa_3des_sha',
'ecdhe_ecdsa_aes_128_sha',
'ecdhe_ecdsa_aes_256_sha',
'ecdh_rsa_null_sha',
'ecdh_rsa_128_sha',
'ecdh_rsa_3des_sha',
'ecdh_rsa_aes_128_sha',
'ecdh_rsa_aes_256_sha',
'echde_rsa_null',
'ecdhe_rsa_rc4_128_sha',
'ecdhe_rsa_3des_sha',
'ecdhe_rsa_aes_128_sha',
'ecdhe_rsa_aes_256_sha',
'ecdhe_ecdsa_aes_128_gcm_sha_256',
'ecdhe_rsa_aes_128_gcm_sha_256',
);
/**
* enable ECC cipher suites in cURL/NSS
* @codeCoverageIgnore
*/
public static function nssCiphers()
{
static $cache;
if (isset($cache)) {
return $cache;
}
$ver = curl_version();
if (preg_match('/^NSS.*Basic ECC$/', $ver['ssl_version'])) {
return $cache = implode(',', self::$NSS_CIPHERS);
}
return $cache = false;
}
protected function getProxy($url)
{
if (isset($_SERVER['no_proxy'])) {
$pattern = new Util\NoProxyPattern($_SERVER['no_proxy']);
if ($pattern->test($url)) {
return null;
}
}
foreach (array('https', 'http') as $scheme) {
if ($this->scheme === $scheme) {
$label = $scheme . '_proxy';
foreach (array(strtoupper($label), $label) as $l) {
if (isset($_SERVER[$l])) {
return $_SERVER[$l];
}
}
}
}
return null;
}
/**
* @param $io
* @param bool $useRedirector
* @param $githubDomains
* @param $gitlabDomains
*/
protected function setupAuthentication(IO\IOInterface $io, $useRedirector, array $githubDomains, array $gitlabDomains)
{
if (preg_match('/\.github\.com$/', $this->host)) {
$authKey = 'github.com';
if ($useRedirector) {
if ($this->host === 'api.github.com' && preg_match('%^/repos(/[^/]+/[^/]+/)zipball(.+)$%', $this->path, $_)) {
$this->host = 'codeload.github.com';
$this->path = $_[1] . 'legacy.zip' . $_[2];
}
}
} else {
$authKey = $this->host;
}
if (!$io->hasAuthentication($authKey)) {
if ($this->user || $this->pass) {
$io->setAuthentication($authKey, $this->user, $this->pass);
} else {
return;
}
}
$auth = $io->getAuthentication($authKey);
// is github
if (in_array($authKey, $githubDomains) && 'x-oauth-basic' === $auth['password']) {
$this->addParam('access_token', $auth['username']);
$this->user = $this->pass = null;
return;
}
// is gitlab
if (in_array($authKey, $gitlabDomains) && 'oauth2' === $auth['password']) {
$this->addHeader('authorization', 'Bearer ' . $auth['username']);
$this->user = $this->pass = null;
return;
}
// others, includes bitbucket
$this->user = $auth['username'];
$this->pass = $auth['password'];
}
/**
* @return array
*/
public function getCurlOptions()
{
$headers = array();
foreach ($this->headers as $key => $val) {
$headers[] = strtr(ucwords(strtr($key, '-', ' ')), ' ', '-') . ': ' . $val;
}
$url = $this->getURL();
$curlOpts = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_USERAGENT => ConfigFacade::getUserAgent(),
//CURLOPT_VERBOSE => true, //for debug
);
$curlOpts += static::$defaultCurlOptions;
// @codeCoverageIgnoreStart
if ($ciphers = $this->nssCiphers()) {
$curlOpts[CURLOPT_SSL_CIPHER_LIST] = $ciphers;
}
// @codeCoverageIgnoreEnd
if ($proxy = $this->getProxy($url)) {
$curlOpts[CURLOPT_PROXY] = $proxy;
}
if ($this->capath) {
$curlOpts[CURLOPT_CAPATH] = $this->capath;
}
if ($this->cafile) {
$curlOpts[CURLOPT_CAINFO] = $this->cafile;
}
return $curlOpts;
}
/**
* @return string
*/
public function getURL()
{
$url = self::ifOr($this->scheme, '', '://');
if ($this->user) {
$user = $this->user;
$user .= self::ifOr($this->pass, ':');
$url .= $user . '@';
}
$url .= self::ifOr($this->host);
$url .= self::ifOr($this->port, ':');
$url .= self::ifOr($this->path);
$url .= self::ifOr(http_build_query($this->query), '?');
return $url;
}
/**
* @return string user/pass/access_token masked url
*/
public function getMaskedURL()
{
$url = self::ifOr($this->scheme, '', '://');
$url .= self::ifOr($this->host);
$url .= self::ifOr($this->port, ':');
$url .= self::ifOr($this->path);
return $url;
}
/**
* @return string
*/
public function getOriginURL()
{
$url = self::ifOr($this->scheme, '', '://');
$url .= self::ifOr($this->host);
$url .= self::ifOr($this->port, ':');
return $url;
}
private static function ifOr($str, $pre = '', $post = '')
{
if ($str) {
return $pre . $str . $post;
}
return '';
}
/**
* @param string $url
*/
public function setURL($url)
{
$struct = parse_url($url);
foreach ($struct as $key => $val) {
if ($key === 'query') {
parse_str($val, $this->query);
} else {
$this->$key = $val;
}
}
}
public function addParam($key, $val)
{
$this->query[$key] = $val;
}
public function addHeader($key, $val)
{
$this->headers[strtolower($key)] = $val;
}
public function setCA($path = null, $file = null)
{
$this->capath = $path;
$this->cafile = $file;
}
}
src/CopyRequest.php 0000666 00000005020 13436756440 0010344 0 ustar 00 > */
private $fp;
private $success = false;
protected static $defaultCurlOptions = array(
CURLOPT_HTTPGET => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 20,
CURLOPT_ENCODING => '',
);
/**
* @param string $url
* @param string $destination
* @param bool $useRedirector
* @param IO\IOInterface $io
* @param Config $config
*/
public function __construct($url, $destination, $useRedirector, IO\IOInterface $io, Config $config)
{
$this->setURL($url);
$this->setDestination($destination);
$this->setCA($config->get('capath'), $config->get('cafile'));
$this->setupAuthentication($io, $useRedirector, $config->get('github-domains'), $config->get('gitlab-domains'));
}
public function __destruct()
{
if ($this->fp) {
fclose($this->fp);
}
if (!$this->success) {
if (file_exists($this->destination)) {
unlink($this->destination);
}
}
}
public function makeSuccess()
{
$this->success = true;
}
/**
* @return array
*/
public function getCurlOptions()
{
$curlOpts = parent::getCurlOptions();
$curlOpts[CURLOPT_FILE] = $this->fp;
return $curlOpts;
}
/**
* @param string
*/
public function setDestination($destination)
{
$this->destination = $destination;
if (is_dir($destination)) {
throw new FetchException(
'The file could not be written to ' . $destination . '. Directory exists.'
);
}
$this->createDir($destination);
$this->fp = fopen($destination, 'wb');
if (!$this->fp) {
throw new FetchException(
'The file could not be written to ' . $destination
);
}
}
private function createDir($fileName)
{
$targetdir = dirname($fileName);
if (!file_exists($targetdir)) {
if (!mkdir($targetdir, 0766, true)) {
throw new FetchException(
'The file could not be written to ' . $fileName
);
}
}
}
}
src/Share.php 0000666 00000001156 13436756440 0007131 0 ustar 00 providersUrl && isset($data['provider-includes'])) {
$includes = $data['provider-includes'];
$requests = array();
$cachedir = $this->config->get('cache-repo-dir');
$cacheBase = $cachedir . DIRECTORY_SEPARATOR . strtr($this->baseUrl, ':/', '--');
foreach ($includes as $include => $metadata) {
$url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
$cacheKey = str_replace(array('%hash%','$'), '', $include);
if ($this->cache->sha256($cacheKey) !== $metadata['sha256']) {
$dest = $cacheBase . DIRECTORY_SEPARATOR . str_replace('/', '-', $cacheKey);
$requests[] = new CopyRequest($url, $dest, false, $this->io, $this->config);
}
}
if ($requests) {
$prefetcher = new Prefetcher;
$prefetcher->fetchAll($this->io, $requests);
}
}
}
public function prefetch()
{
if (null === $this->providerListing) {
$this->preloadProviderListings($this->loadRootServerFile());
}
}
public function __debugInfo()
{
return array(
'url' => $this->url,
'repoConfig' => $this->repoConfig,
'options' => $this->options,
'baseUrl' => $this->baseUrl,
'notifyUrl' => $this->notifyUrl,
'searchUrl' => $this->searchUrl,
'hasProviders' => $this->hasProviders,
'providersUrl' => $this->providersUrl,
'lazyProvidersUrl' => $this->lazyProvidersUrl,
'providerListing' => $this->providerListing,
'providers' => $this->providers,
'providersByUid' => $this->providersByUid,
'rootAliases' => $this->rootAliases,
'allowSslDowngrade' => $this->allowSslDowngrade,
'sourceMirrors' => $this->sourceMirrors,
'distMirrors' => $this->distMirrors,
);
}
}
src/Prefetcher.php 0000666 00000006137 13436756440 0010162 0 ustar 00 setRequests($requests);
try {
do {
$multi->setupEventLoop();
$multi->wait();
$result = $multi->getFinishedResults();
$successCnt += $result['successCnt'];
$failureCnt += $result['failureCnt'];
foreach ($result['urls'] as $url) {
$io->writeError(" $successCnt/$totalCnt:\t$url");
}
} while ($multi->remain());
} catch (FetchException $e) {
// do nothing
}
$skippedCnt = $totalCnt - $successCnt - $failureCnt;
$io->writeError(" Finished: success: $successCnt, skipped: $skippedCnt, failure: $failureCnt, total: $totalCnt");
}
/**
* @param IO\IOInterface $io
* @param Config $config
* @param Operation\OperationInterface[] $ops
*/
public function fetchAllFromOperations(IO\IOInterface $io, Config $config, array $ops)
{
$cachedir = rtrim($config->get('cache-files-dir'), '\/');
$requests = array();
foreach ($ops as $op) {
switch ($op->getJobType()) {
case 'install':
$p = $op->getPackage();
break;
case 'update':
$p = $op->getTargetPackage();
break;
default:
continue 2;
}
$url = $this->getUrlFromPackage($p);
if (!$url) {
continue;
}
$destination = $cachedir . DIRECTORY_SEPARATOR . FileDownloaderDummy::getCacheKeyCompat($p, $url);
if (file_exists($destination)) {
continue;
}
$useRedirector = (bool)preg_match('%^(?:https|git)://github\.com%', $p->getSourceUrl());
try {
$request = new CopyRequest($url, $destination, $useRedirector, $io, $config);
$requests[] = $request;
} catch (FetchException $e) {
// do nothing
}
}
if (count($requests) > 0) {
$this->fetchAll($io, $requests);
}
}
private static function getUrlFromPackage(Package\PackageInterface $package)
{
$url = $package->getDistUrl();
if (!$url) {
return false;
}
if ($package->getDistMirrors()) {
$url = current($package->getDistUrls());
}
if (!parse_url($url, PHP_URL_HOST)) {
return false;
}
return $url;
}
}
src/CurlRemoteFilesystem.php 0000666 00000003027 13436756440 0012214 0 ustar 00 io = $io;
$this->config = $config;
$this->options = $options;
$this->disableTls = $disableTls;
parent::__construct($io, $config, $options, $disableTls);
}
/**
* @inheritDoc
*/
public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
{
$res = null;
try {
$this->req = new FetchRequest($fileUrl, $this->io, $this->config);
$res = $this->req->fetch();
} catch (\Exception $e) {
$this->io->writeError((string)$e);
}
if ($res) {
return $res;
} else {
return parent::getContents($originUrl, $fileUrl, $progress, $options);
}
}
public function getLastHeaders()
{
if ($this->req && ($headers = $this->req->getLastHeaders())) {
return $headers;
} else {
return parent::getLastHeaders();
}
}
public function __debugInfo()
{
return array();
}
}
src/FileDownloaderDummy.php 0000666 00000001365 13436756440 0012003 0 ustar 00 setAccessible(true);
$my = new self;
}
return $rgetCacheKey->invoke($my, $p, $processedUrl);
}
}
src/CurlMulti.php 0000666 00000010216 13436756440 0010004 0 ustar 00 */
private $mh;
/** @var resource[] */
private $unused = array();
/** @var resource[] */
private $using = array();
/** @var CopyRequest[] */
private $requests;
/** @var CopyRequest[] */
private $runningRequests;
/** @var bool */
private $permanent = true;
private $blackhole;
/**
* @param bool $permanent
*/
public function __construct($permanent = true)
{
static $mh_cache, $ch_cache;
if (!$permanent || !$mh_cache) {
$mh_cache = curl_multi_init();
$ch_cache = array();
for ($i = 0; $i < self::MAX_CONNECTIONS; ++$i) {
$ch = curl_init();
Share::setup($ch);
$ch_cache[] = $ch;
}
}
$this->mh = $mh_cache;
$this->unused = $ch_cache;
$this->permanent = $permanent;
// for PHP<5.5 @see getFinishedResults()
$this->blackhole = fopen('php://temp', 'wb');
}
/**
* @codeCoverageIgnore
*/
public function __destruct()
{
foreach ($this->using as $ch) {
curl_multi_remove_handle($this->mh, $ch);
$this->unused[] = $ch;
}
if ($this->permanent) {
return; //don't close connection
}
foreach ($this->unused as $ch) {
curl_close($ch);
}
curl_multi_close($this->mh);
}
/**
* @param CopyRequest[] $requests
*/
public function setRequests(array $requests)
{
$this->requests = $requests;
}
public function setupEventLoop()
{
while (count($this->unused) > 0 && count($this->requests) > 0) {
$request = array_pop($this->requests);
$ch = array_pop($this->unused);
$index = (int)$ch;
$this->using[$index] = $ch;
$this->runningRequests[$index] = $request;
curl_setopt_array($ch, $request->getCurlOptions());
curl_multi_add_handle($this->mh, $ch);
}
}
public function wait()
{
$expectRunning = count($this->using);
$running = 0;
$retryCnt = 0;
do {
do {
$stat = curl_multi_exec($this->mh, $running);
} while ($stat === CURLM_CALL_MULTI_PERFORM);
if (-1 === curl_multi_select($this->mh)) {
// @codeCoverageIgnoreStart
if ($retryCnt++ > 100) {
throw new FetchException('curl_multi_select failure');
}
// @codeCoverageIgnoreEnd
usleep(100000);
}
} while ($running > 0 && $running >= $expectRunning);
}
public function getFinishedResults()
{
$urls = array();
$successCnt = $failureCnt = 0;
do {
if ($raised = curl_multi_info_read($this->mh, $remains)) {
$ch = $raised['handle'];
$errno = curl_errno($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch);
curl_setopt($ch, CURLOPT_FILE, $this->blackhole); //release file pointer
$index = (int)$ch;
$request = $this->runningRequests[$index];
if (CURLE_OK === $errno && !$error && ('http' !== substr($info['url'], 0, 4) || 200 === $info['http_code'])) {
++$successCnt;
$request->makeSuccess();
$urls[] = $request->getMaskedURL();
} else {
++$failureCnt;
}
unset($this->using[$index], $this->runningRequests[$index], $request);
curl_multi_remove_handle($this->mh, $ch);
$this->unused[] = $ch;
}
} while ($remains > 0);
return compact('successCnt', 'failureCnt', 'urls');
}
public function remain()
{
return count($this->runningRequests) > 0;
}
}
src/ConfigFacade.php 0000666 00000001443 13436756440 0010357 0 ustar 00 true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 20,
CURLOPT_ENCODING => '',
CURLOPT_RETURNTRANSFER => true,
);
private $headers = array();
private $errno, $error, $info;
/**
* @param string $url
* @param IO\IOInterface $io
* @param Config $config
*/
public function __construct($url, IO\IOInterface $io, Config $config)
{
$this->setURL($url);
$this->setCA($config->get('capath'), $config->get('cafile'));
$this->setupAuthentication($io, false, $config->get('github-domains'), $config->get('gitlab-domains'));
}
public function getCurlOptions()
{
$curlOpts = parent::getCurlOptions();
$curlOpts[CURLOPT_RETURNTRANSFER] = true;
$curlOpts[CURLOPT_HEADERFUNCTION] = array($this, 'headerCallback');
return $curlOpts;
}
private static function getCurl($key)
{
static $curlCache = array();
if (isset($curlCache[$key])) {
return $curlCache[$key];
}
$ch = curl_init();
Share::setup($ch);
return $curlCache[$key] = $ch;
}
/**
* @return string|false
*/
public function fetch()
{
$ch = self::getCurl($this->getOriginURL());
curl_setopt_array($ch, $this->getCurlOptions());
$result = curl_exec($ch);
$this->errno = $errno = curl_errno($ch);
$this->error = curl_error($ch);
$this->info = $info = curl_getinfo($ch);
if ($errno === CURLE_OK && $info['http_code'] === 200) {
return $result;
} else {
return false;
}
}
public function getLastError()
{
if ($this->errno || $this->error) {
return array($this->errno, $this->error);
} else {
return array();
}
}
public function getLastHeaders()
{
return $this->headers;
}
public function headerCallback($ch, $headerString)
{
$len = strlen($headerString);
$this->headers[] = $headerString;
return $len;
}
}
.envrc 0000666 00000000032 13436756440 0005675 0 ustar 00 PATH_add ~/.php/7.0.6/bin
composer.json 0000666 00000002173 13436756440 0007311 0 ustar 00 {
"name": "hirak/prestissimo",
"description": "composer parallel install plugin",
"type": "composer-plugin",
"keywords": ["parallel", "install", "speedup"],
"authors": [
{
"name": "Hiraku NAKANO",
"email": "hiraku@tojiru.net"
}
],
"license": "MIT",
"require": {
"php": ">=5.3.2",
"ext-curl": "*",
"composer-plugin-api": "^1.0.0"
},
"require-dev": {
"composer/composer": "1.0.0",
"phpunit/phpunit": "^4.8",
"squizlabs/php_codesniffer": "^2.5"
},
"scripts": {
"test": "phpunit --colors=always",
"fasttest": "phpdbg -qrr vendor/bin/phpunit --colors=always",
"lint": "phpcs",
"fmt": "phpcbf",
"doc": "php bin/apigen.phar generate",
"metrics": "php bin/phpmetrics.phar --report-html=artifacts/metrics.html src/"
},
"autoload": {
"psr-4": {
"Hirak\\Prestissimo\\": "src/"
}
},
"extra": {
"class": "Hirak\\Prestissimo\\Plugin"
},
"config": {
"platform": {
"php": "5.3.29"
}
}
}
.travis.yml 0000666 00000001005 13436756440 0006671 0 ustar 00 language: php
sudo: false
php:
- '5.3'
- '5.4'
- '5.5'
- '5.6'
- '7.0'
- 'hhvm'
before_install:
# - composer self-update
- composer config -g repositories.packagist path $(pwd)
- composer global require 'hirak/prestissimo:@dev'
- composer config -g --unset repositories.packagist
install:
- composer install --no-progress --profile
script:
- composer test
after_success:
- php bin/ocular.phar code-coverage:upload --format=php-clover artifacts/clover.xml
- php bin/coveralls.phar -v
apigen.neon 0000666 00000000126 13436756440 0006707 0 ustar 00 # vim: set ft=yaml:
source: src/
destination: artifacts/api/
title: hirak\prestissimo
phpunit.xml.dist 0000666 00000001243 13436756440 0007737 0 ustar 00
src/
tests/unit/
tests/functional/
.coveralls.yml 0000666 00000000176 13436756440 0007363 0 ustar 00 service_name: travis-ci
# for php-coveralls
coverage_clover: artifacts/clover.xml
json_path: artifacts/coveralls-upload.json
composer.lock 0000666 00000165513 13436756440 0007300 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "007df97d440c2c3ffd72042d7c0bfdb3",
"content-hash": "cf91798f3a5d7ef14ec1bf6ce547e4a3",
"packages": [],
"packages-dev": [
{
"name": "composer/composer",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
"reference": "32df3aa8cdbdaa16df9491b5e672e81c87f94c78"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/composer/zipball/32df3aa8cdbdaa16df9491b5e672e81c87f94c78",
"reference": "32df3aa8cdbdaa16df9491b5e672e81c87f94c78",
"shasum": ""
},
"require": {
"composer/semver": "^1.0",
"composer/spdx-licenses": "^1.0",
"justinrainbow/json-schema": "^1.6",
"php": "^5.3.2 || ^7.0",
"seld/cli-prompt": "^1.0",
"seld/jsonlint": "^1.4",
"seld/phar-utils": "^1.0",
"symfony/console": "^2.5 || ^3.0",
"symfony/filesystem": "^2.5 || ^3.0",
"symfony/finder": "^2.2 || ^3.0",
"symfony/process": "^2.1 || ^3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5 || ^5.0.5",
"phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
},
"suggest": {
"ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
"ext-zip": "Enabling the zip extension allows you to unzip archives",
"ext-zlib": "Allow gzip compression of HTTP requests"
},
"bin": [
"bin/composer"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\": "src/Composer"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.",
"homepage": "https://getcomposer.org/",
"keywords": [
"autoload",
"dependency",
"package"
],
"time": "2016-04-05 12:27:26"
},
{
"name": "composer/semver",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "03c9de5aa25e7672c4ad251eeaba0c47a06c8b98"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/03c9de5aa25e7672c4ad251eeaba0c47a06c8b98",
"reference": "03c9de5aa25e7672c4ad251eeaba0c47a06c8b98",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5 || ^5.0.5",
"phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"time": "2016-06-02 09:04:51"
},
{
"name": "composer/spdx-licenses",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/composer/spdx-licenses.git",
"reference": "88c26372b1afac36d8db601cdf04ad8716f53d88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/88c26372b1afac36d8db601cdf04ad8716f53d88",
"reference": "88c26372b1afac36d8db601cdf04ad8716f53d88",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5 || ^5.0.5",
"phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Spdx\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "SPDX licenses list and validation library.",
"keywords": [
"license",
"spdx",
"validator"
],
"time": "2016-05-04 12:27:30"
},
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2015-06-14 21:17:01"
},
{
"name": "justinrainbow/json-schema",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/justinrainbow/json-schema.git",
"reference": "cc84765fb7317f6b07bd8ac78364747f95b86341"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/cc84765fb7317f6b07bd8ac78364747f95b86341",
"reference": "cc84765fb7317f6b07bd8ac78364747f95b86341",
"shasum": ""
},
"require": {
"php": ">=5.3.29"
},
"require-dev": {
"json-schema/json-schema-test-suite": "1.1.0",
"phpdocumentor/phpdocumentor": "~2",
"phpunit/phpunit": "~3.7"
},
"bin": [
"bin/validate-json"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-4": {
"JsonSchema\\": "src/JsonSchema/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Bruno Prieto Reis",
"email": "bruno.p.reis@gmail.com"
},
{
"name": "Justin Rainbow",
"email": "justin.rainbow@gmail.com"
},
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
},
{
"name": "Robert Schönthal",
"email": "seroscho@googlemail.com"
}
],
"description": "A library to validate a json schema.",
"homepage": "https://github.com/justinrainbow/json-schema",
"keywords": [
"json",
"schema"
],
"time": "2016-01-25 15:43:01"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03 12:10:50"
},
{
"name": "phpspec/prophecy",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
"reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "~2.0",
"sebastian/comparator": "~1.1",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"phpspec/phpspec": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.5.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2016-02-15 07:46:21"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"phpunit/php-file-iterator": "~1.3",
"phpunit/php-text-template": "~1.2",
"phpunit/php-token-stream": "~1.3",
"sebastian/environment": "^1.3.2",
"sebastian/version": "~1.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.2.1",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2015-10-06 15:47:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2015-06-21 13:08:43"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2015-06-21 13:50:34"
},
{
"name": "phpunit/php-timer",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4|~5"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2016-05-12 18:03:57"
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2015-09-15 10:49:45"
},
{
"name": "phpunit/phpunit",
"version": "4.8.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "fc1d8cd5b5de11625979125c5639347896ac2c74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74",
"reference": "fc1d8cd5b5de11625979125c5639347896ac2c74",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpspec/prophecy": "^1.3.1",
"phpunit/php-code-coverage": "~2.1",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.8.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2016-05-17 03:09:28"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2015-10-02 06:51:40"
},
{
"name": "sebastian/comparator",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2015-07-26 15:48:44"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2015-12-08 07:14:41"
},
{
"name": "sebastian/environment",
"version": "1.3.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2016-05-17 03:18:57"
},
{
"name": "sebastian/exporter",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "7ae5513327cb536431847bcc0c10edba2701064e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
"reference": "7ae5513327cb536431847bcc0c10edba2701064e",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2015-06-21 07:55:53"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/recursion-context",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2015-11-11 19:50:13"
},
{
"name": "sebastian/version",
"version": "1.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2015-06-21 13:59:46"
},
{
"name": "seld/cli-prompt",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/cli-prompt.git",
"reference": "8cbe10923cae5bcd7c5a713f6703fc4727c8c1b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/8cbe10923cae5bcd7c5a713f6703fc4727c8c1b4",
"reference": "8cbe10923cae5bcd7c5a713f6703fc4727c8c1b4",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Seld\\CliPrompt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type",
"keywords": [
"cli",
"console",
"hidden",
"input",
"prompt"
],
"time": "2016-04-18 09:31:41"
},
{
"name": "seld/jsonlint",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/jsonlint.git",
"reference": "66834d3e3566bb5798db7294619388786ae99394"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394",
"reference": "66834d3e3566bb5798db7294619388786ae99394",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0"
},
"bin": [
"bin/jsonlint"
],
"type": "library",
"autoload": {
"psr-4": {
"Seld\\JsonLint\\": "src/Seld/JsonLint/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "JSON Linter",
"keywords": [
"json",
"linter",
"parser",
"validator"
],
"time": "2015-11-21 02:21:41"
},
{
"name": "seld/phar-utils",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/phar-utils.git",
"reference": "7009b5139491975ef6486545a39f3e6dad5ac30a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a",
"reference": "7009b5139491975ef6486545a39f3e6dad5ac30a",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Seld\\PharUtils\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "PHAR file format utilities, for when PHP phars you up",
"keywords": [
"phra"
],
"time": "2015-10-13 18:44:15"
},
{
"name": "squizlabs/php_codesniffer",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
"reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"bin": [
"scripts/phpcs",
"scripts/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"classmap": [
"CodeSniffer.php",
"CodeSniffer/CLI.php",
"CodeSniffer/Exception.php",
"CodeSniffer/File.php",
"CodeSniffer/Fixer.php",
"CodeSniffer/Report.php",
"CodeSniffer/Reporting.php",
"CodeSniffer/Sniff.php",
"CodeSniffer/Tokens.php",
"CodeSniffer/Reports/",
"CodeSniffer/Tokenizers/",
"CodeSniffer/DocGenerators/",
"CodeSniffer/Standards/AbstractPatternSniff.php",
"CodeSniffer/Standards/AbstractScopeSniff.php",
"CodeSniffer/Standards/AbstractVariableSniff.php",
"CodeSniffer/Standards/IncorrectPatternException.php",
"CodeSniffer/Standards/Generic/Sniffs/",
"CodeSniffer/Standards/MySource/Sniffs/",
"CodeSniffer/Standards/PEAR/Sniffs/",
"CodeSniffer/Standards/PSR1/Sniffs/",
"CodeSniffer/Standards/PSR2/Sniffs/",
"CodeSniffer/Standards/Squiz/Sniffs/",
"CodeSniffer/Standards/Zend/Sniffs/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer",
"keywords": [
"phpcs",
"standards"
],
"time": "2016-05-30 22:24:32"
},
{
"name": "symfony/console",
"version": "v2.8.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "48221d3de4dc22d2cd57c97e8b9361821da86609"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/48221d3de4dc22d2cd57c97e8b9361821da86609",
"reference": "48221d3de4dc22d2cd57c97e8b9361821da86609",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/event-dispatcher": "~2.1|~3.0.0",
"symfony/process": "~2.1|~3.0.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2016-04-26 12:00:47"
},
{
"name": "symfony/filesystem",
"version": "v2.8.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "dee379131dceed90a429e951546b33edfe7dccbb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/dee379131dceed90a429e951546b33edfe7dccbb",
"reference": "dee379131dceed90a429e951546b33edfe7dccbb",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2016-04-12 18:01:21"
},
{
"name": "symfony/finder",
"version": "v2.8.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1",
"reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2016-03-10 10:53:53"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "dff51f72b0706335131b00a7f49606168c582594"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
"reference": "dff51f72b0706335131b00a7f49606168c582594",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2016-05-18 14:26:46"
},
{
"name": "symfony/process",
"version": "v2.8.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "1276bd9be89be039748cf753a2137f4ef149cd74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/1276bd9be89be039748cf753a2137f4ef149cd74",
"reference": "1276bd9be89be039748cf753a2137f4ef149cd74",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2016-04-14 15:22:22"
},
{
"name": "symfony/yaml",
"version": "v2.8.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "e4fbcc65f90909c999ac3b4dfa699ee6563a9940"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/e4fbcc65f90909c999ac3b4dfa699ee6563a9940",
"reference": "e4fbcc65f90909c999ac3b4dfa699ee6563a9940",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-03-29 19:00:15"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.3.2",
"ext-curl": "*"
},
"platform-dev": [],
"platform-overrides": {
"php": "5.3.29"
}
}
tests/unit/CurlMultiTest.php 0000666 00000004532 13436756440 0012202 0 ustar 00 iop = $this->prophesize('Composer\IO\IOInterface');
$this->configp = $configp = $this->prophesize('Composer\Config');
$configp->get('github-domains')->willReturn(array('github.com'));
$configp->get('gitlab-domains')->willReturn(array('gitlab.com'));
}
public function testRequestSuccess()
{
$tmpfile = tmpfile();
$reqp = $this->prophesize('Hirak\Prestissimo\CopyRequest');
$reqp->getCurlOptions()->willReturn(array(
CURLOPT_URL => 'file://' . __DIR__ . '/test.txt',
CURLOPT_FILE => $tmpfile,
));
$reqp->getMaskedURL()->willReturn('file://' . __DIR__ . '/test.txt');
$reqp->makeSuccess()->willReturn(null);
$requests = array($reqp->reveal());
$multi = new CurlMulti;
$multi->setRequests($requests);
do {
$multi->setupEventLoop();
$multi->wait();
$result = $multi->getFinishedResults();
$this->assertEquals(1, $result['successCnt']);
$this->assertEquals(0, $result['failureCnt']);
} while ($multi->remain());
rewind($tmpfile);
$content = stream_get_contents($tmpfile);
$this->assertEquals(file_get_contents(__DIR__ . '/test.txt'), $content);
}
public function testWait()
{
$tmpfile = tmpfile();
$reqp = $this->prophesize('Hirak\Prestissimo\CopyRequest');
$reqp->getCurlOptions()->willReturn(array(
CURLOPT_URL => 'file://uso800.txt',
CURLOPT_FILE => $tmpfile,
));
$reqp->getMaskedURL()->willReturn('file://uso800.txt');
$reqp->makeSuccess()->willReturn(null);
$requests = array($reqp->reveal());
$multi = new CurlMulti;
$multi->setRequests($requests);
do {
$multi->setupEventLoop();
$multi->wait();
$result = $multi->getFinishedResults();
$this->assertEquals(0, $result['successCnt']);
$this->assertEquals(1, $result['failureCnt']);
} while ($multi->remain());
rewind($tmpfile);
$content = stream_get_contents($tmpfile);
$this->assertEmpty($content);
}
}
tests/unit/CopyRequestTest.php 0000666 00000011671 13436756440 0012547 0 ustar 00 iop = $this->prophesize('Composer\IO\IOInterface');
$this->configp = $configp = $this->prophesize('Composer\Config');
$configp->get('capath')->willReturn(null);
$configp->get('cafile')->willReturn(null);
$configp->get('github-domains')->willReturn(array('github.com'));
$configp->get('gitlab-domains')->willReturn(array('gitlab.com'));
}
public function testConstruct()
{
$tmpfile = tempnam(sys_get_temp_dir(), 'composer_unit_test_');
$example = 'http://user:pass@example.com:80/p/a/t/h?a=b';
$this->iop->setAuthentication('example.com', 'user', 'pass')
->will(function ($args, $iop) {
$iop->getAuthentication($args[0])
->willReturn(array('username' => $args[1], 'password' => $args[2]));
})
->shouldBeCalled();
$this->iop->hasAuthentication(arg::type('string'))
->willReturn(false);
$req = new CopyRequest($example, $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
$this->assertEquals($example, $req->getURL());
}
public function testDirectoryExists()
{
$rand = sha1(mt_rand());
$tmpbase = sys_get_temp_dir();
$tmpdir = $tmpbase . DIRECTORY_SEPARATOR . $rand;
mkdir($tmpdir);
try {
// if is_dir(destination) then throws exception
$req = new CopyRequest('http://example.com/', $tmpdir, false, $this->iop->reveal(), $this->configp->reveal());
rmdir($tmpdir);
$this->fail('expectedException: \Hirak\Prestissimo\Prefetcher\FetchException');
} catch (\Exception $e) {
rmdir($tmpdir);
$this->assertInstanceOf('Hirak\Prestissimo\FetchException', $e);
$this->assertContains('Directory exists', $e->getMessage());
}
}
public function testDestruct()
{
$tmpfile = tempnam(sys_get_temp_dir(), 'composer_unit_test_');
$req = new CopyRequest('http://example.com/', $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
$this->assertFileExists($tmpfile);
// if $req->success === true ...
$req->makeSuccess();
unset($req);
// then tmpfile remain
$this->assertFileExists($tmpfile);
unlink($tmpfile);
$req = new CopyRequest('http://example.com/', $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
// if $req->success === false (default) ...
// $req->makeSuccess();
unset($req);
// then cleaned tmpfile automatically
$this->assertFileNotExists($tmpfile);
}
public function testGitHubRedirector()
{
$tmpfile = tempnam(sys_get_temp_dir(), 'composer_unit_test_');
$example = 'https://api.github.com/repos/vendor/name/zipball/aaaa?a=b';
$this->iop->hasAuthentication('github.com')->willReturn(true);
$this->iop->getAuthentication('github.com')->willReturn(array('username' => 'at', 'password' => 'x-oauth-basic'));
// user:pass -> query
$req = new CopyRequest($example, $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
$this->assertEquals("$example&access_token=at", $req->getURL());
// api.github.com -> codeload.github.com
$req = new CopyRequest($example, $tmpfile, true, $this->iop->reveal(), $this->configp->reveal());
$this->assertEquals('https://codeload.github.com/vendor/name/legacy.zip/aaaa?a=b&access_token=at', $req->getURL());
}
public function testGitLab()
{
$tmpfile = tempnam(sys_get_temp_dir(), 'composer_unit_test_');
$example = 'https://gitlab.com/p/a/t/h';
$this->iop->hasAuthentication('gitlab.com')->willReturn(true);
$this->iop->getAuthentication('gitlab.com')->willReturn(array('username' => 'at', 'password' => 'oauth2'));
$req = new CopyRequest($example, $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
$opts = $req->getCurlOptions();
$this->assertContains('Authorization: Bearer at', $opts[CURLOPT_HTTPHEADER]);
}
public function testProxy()
{
$serverBackup = $_SERVER;
$tmpfile = tempnam(sys_get_temp_dir(), 'composer_unit_test_');
$_SERVER['no_proxy'] = 'example.com';
$_SERVER['HTTP_PROXY'] = 'http://example.com:8080';
$req = new CopyRequest('http://localhost', $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
$this->assertArrayHasKey(CURLOPT_PROXY, $req->getCurlOptions());
$req = new CopyRequest('http://example.com', $tmpfile, false, $this->iop->reveal(), $this->configp->reveal());
$this->assertArrayNotHasKey(CURLOPT_PROXY, $req->getCurlOptions());
$_SERVER = $serverBackup;
}
}
tests/unit/ConfigFacadeTest.php 0000666 00000000424 13436756440 0012547 0 ustar 00 getUserAgent());
}
}
tests/unit/ShareTest.php 0000666 00000000362 13436756440 0011321 0 ustar 00 iop = $this->prophesize('Composer\IO\IOInterface');
$this->configp = $configp = $this->prophesize('Composer\Config');
$configp->get('cache-files-dir')
->willReturn('tests/workspace/');
$this->composerp = $composerp = $this->prophesize('Composer\Composer');
$packagep = $this->prophesize('Composer\Package\CompletePackageInterface');
$packagep->getRepositories()
->willReturn(array());
$composerp->getPackage()
->willReturn($packagep->reveal());
$composerp->getConfig()
->willReturn($this->configp->reveal());
$composerp->getPackage()
->willReturn($packagep->reveal());
}
public function testConstruct()
{
$plugin = new Plugin;
self::assertInstanceOf(__NAMESPACE__ . '\\Plugin', $plugin);
self::assertFalse($plugin->isDisabled());
}
public function testConstructWithEval()
{
// compatiblity with Composer\Plugin\PluginManager
$code = file_get_contents('src/Plugin.php');
$code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+(\S+)}mi', '$1class $2_composer_tmp1', $code);
eval('?' . '>' . $code);
$class = 'Hirak\\Prestissimo\\Plugin_composer_tmp1';
$plugin = new $class;
$plugin->activate($this->composerp->reveal(), $this->iop->reveal());
self::assertTrue($plugin->isDisabled());
}
public function testActivate()
{
$plugin = new Plugin;
$plugin->activate($this->composerp->reveal(), $this->iop->reveal());
self::assertTrue(class_exists('Hirak\Prestissimo\CopyRequest', false));
}
public function testGetSubscribedEvent()
{
self::assertInternalType('array', Plugin::getSubscribedEvents());
}
public function testOnPreDependenciesSolving()
{
$plugin = new Plugin;
$plugin->activate($this->composerp->reveal(), $this->iop->reveal());
$evp = $this->prophesize('Composer\Installer\InstallerEvent');
// on enabled
$plugin->prefetchComposerRepositories($evp->reveal());
// on disabled
$plugin->disable();
$evp = $this->prophesize('Composer\Installer\InstallerEvent');
$evp->getOperations()
->shouldNotBeCalled();
$plugin->prefetchComposerRepositories($evp->reveal());
}
public function testOnPostDependenciesSolving()
{
$plugin = new Plugin;
$plugin->activate($this->composerp->reveal(), $this->iop->reveal());
$evp = $this->prophesize('Composer\Installer\InstallerEvent');
$evp->getOperations()
->willReturn($this->createDummyOperations());
// on enabled
$plugin->onPostDependenciesSolving($evp->reveal());
// on disabled
$plugin->disable();
$evp = $this->prophesize('Composer\Installer\InstallerEvent');
$evp->getOperations()
->shouldNotBeCalled();
$plugin->onPostDependenciesSolving($evp->reveal());
}
private function createDummyOperations()
{
return array(
new Operation\InstallOperation(
new Package\Package('vendor/pkg1', '0.0.0', '0.0.0')
),
new Operation\UpdateOperation(
new Package\Package('vendor/pkg2', '0.0.0', '0.0.0'),
new Package\Package('vendor/pkg2', '0.0.1', '0.0.1')
),
new Operation\InstallOperation(
new Package\Package('vendor/pkg3', '0.0.0', '0.0.0')
),
);
}
}
tests/unit/PrefetcherTest.php 0000666 00000007441 13436756440 0012353 0 ustar 00 iop = $this->prophesize('Composer\IO\IOInterface');
$this->configp = $configp = $this->prophesize('Composer\Config');
$configp->get('github-domains')->willReturn(array('github.com'));
$configp->get('gitlab-domains')->willReturn(array('gitlab.com'));
$configp->get('cache-files-dir')->willReturn(sys_get_temp_dir());
}
public function testFetchAllOnFailure()
{
$reqp = $this->prophesize('Hirak\Prestissimo\CopyRequest');
$reqp->getCurlOptions()->willReturn(array(
CURLOPT_URL => 'file://uso800.txt',
CURLOPT_FILE => tmpfile(),
));
$this->iop->writeError(" Finished: success: 0, skipped: 0, failure: 1, total: 1")->shouldBeCalledTimes(1);
$fetcher = new Prefetcher;
$fetcher->fetchAll($this->iop->reveal(), array($reqp->reveal()));
}
public function testFetchAllOnSuccess()
{
$reqp = $this->prophesize('Hirak\Prestissimo\CopyRequest');
$reqp->getCurlOptions()->willReturn(array(
CURLOPT_URL => 'file://' . __DIR__ . '/test.txt',
CURLOPT_FILE => tmpfile(),
));
$reqp->makeSuccess()->willReturn(null);
$reqp->getMaskedURL()->willReturn('file://' . __DIR__ . '/test.txt');
$this->iop->writeError(arg::type('string'))->shouldBeCalled();
$fetcher = new Prefetcher;
$fetcher->fetchAll($this->iop->reveal(), array($reqp->reveal()));
}
public function testFetchAllFromOperationsWithNoOperations()
{
$opp = $this->prophesize('Composer\DependencyResolver\Operation\OperationInterface');
$opp->getJobType()->willReturn('remove');
$this->iop->writeError(arg::any())->shouldNotBeCalled();
$fetcher = new Prefetcher;
$fetcher->fetchAllFromOperations($this->iop->reveal(), $this->configp->reveal(), array($opp->reveal()));
}
private function createProphecies()
{
$opp = $this->prophesize('Composer\DependencyResolver\Operation\InstallOperation');
$opp->getJobType()->willReturn('install');
$pp = $this->prophesize('Composer\Package\PackageInterface');
return array($opp, $pp);
}
public function testFetchAllWithInstallOperation()
{
list($opp, $pp) = $this->createProphecies();
$pp->getName()->willReturn('acme/acme');
$pp->getDistType()->willReturn('composer');
$pp->getDistUrl()->willReturn('file://' . __DIR__ . '/test.txt');
$pp->getDistMirrors()->willReturn(array());
$pp->getSourceUrl()->shouldNotBeCalled();
$opp->getPackage()->willReturn($pp->reveal())->shouldBeCalled();
$fetcher = new Prefetcher;
$fetcher->fetchAllFromOperations($this->iop->reveal(), $this->configp->reveal(), array($opp->reveal()));
}
public function testFetchAllWithInstallButFileExists()
{
list($opp, $pp) = $this->createProphecies();
$pp->getName()->willReturn('');
$pp->getDistType()->willReturn('html');
$pp->getDistUrl()->willReturn('http://example.com/');
$pp->getDistMirrors()->willReturn(array());
$pp->getSourceUrl()->willReturn('git://uso800');
$path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . FileDownloaderDummy::getCacheKeyCompat($pp->reveal(), 'http://example.com/');
$fp = fopen($path, 'wb');
$opp->getPackage()->willReturn($pp->reveal())->shouldBeCalled();
$fetcher = new Prefetcher;
$fetcher->fetchAllFromOperations($this->iop->reveal(), $this->configp->reveal(), array($opp->reveal()));
fclose($fp);
unlink($path);
}
}
tests/unit/BaseRequestTest.php 0000666 00000002150 13436756440 0012477 0 ustar 00 setURL('http://www.example.com/');
self::assertEquals('http://www.example.com/', $req->getURL());
}
public function testGetMaskedURL()
{
$req = new BaseRequest;
$req->setURL('http://user:pass@example.com/p/a/t/h?token=opensesame');
self::assertEquals('http://example.com/p/a/t/h', $req->getMaskedURL());
}
public function testGetOriginURL()
{
$req = new BaseRequest;
$req->setURL('http://user:pass@example.com:1337/p/a/t/h?token=opensesame');
self::assertEquals('http://example.com:1337', $req->getOriginURL());
}
public function testCA()
{
$req = new BaseRequest;
$req->setURL('http://www.example.com/');
$req->setCA('path/to/capath', 'path/to/ca.pem');
$options = $req->getCurlOptions();
self::assertArrayHasKey(CURLOPT_CAPATH, $options);
self::assertArrayHasKey(CURLOPT_CAINFO, $options);
}
}
tests/unit/test.txt 0000666 00000000044 13436756440 0010423 0 ustar 00 Composer\Downloader\Prefetcher test
tests/bootstrap.php 0000666 00000015056 13436756440 0010463 0 ustar 00 $val) {
if ($val) {
$b[] = "$key:$val";
}
}
return implode("\t", $b);
};
$base = dirname(__DIR__) . '/';
$it = new AppendIterator;
$it->append(new ArrayIterator(get_declared_classes()));
$it->append(new ArrayIterator(get_declared_interfaces()));
if (function_exists('get_declared_traits')) {
$it->append(new ArrayIterator(get_declared_traits()));
}
foreach ($it as $class) {
$pathes = explode('\\', $class);
if ('Test' === substr($class, -4)
|| 'Spec' === substr($class, -4)
|| 'PHP_Token_' === substr($class, 0, 10)
|| 'Double' === $pathes[0]
|| in_array('Test', $pathes)
|| in_array('Spec', $pathes)
) {
continue;
}
$rc = new ReflectionClass($class);
if ($rc->isInternal()) {
continue;
}
if ($rc->isInterface()) {
$kind = 'i';
} elseif (method_exists($rc, 'isTrait')) {
if ($rc->isTrait()) {
$kind = 't';
} else {
$kind = 'c';
}
} else {
$kind = 'c';
}
$info = array(
'kind' => $kind,
'namespace' => $rc->getNamespaceName(),
);
$parent = $rc->getParentClass();
if ($parent) {
$info['inherits'] = $parent->getName();
}
$construct = $rc->getConstructor();
if ($construct) {
$params = array();
foreach ($construct->getParameters() as $rp) {
$class = $rp->getClass();
$param = '';
if ($class) {
$param .= $class->getName() . ' ';
} elseif ($rp->isArray()) {
$param .= 'array ';
}
$param .= '$' . $rp->getName();
$params[] = $param;
}
$info['constructor'] = '(' . implode(', ', $params) . ')';
}
if ($rc->isInternal()) {
$filename = '(ext-' . $rc->getExtensionName() . ')';
} else {
$filename = str_replace($base, '', $rc->getFileName());
}
fwrite($fp, implode("\t", array(
$rc->getShortName(),
$filename,
$rc->getStartLine() . ';"',
'',
)) . $build($info) . PHP_EOL);
// constants
foreach ($rc->getConstants() as $name => $value) {
$info = array(
'kind' => 'd',
'class' => $rc->getShortName(),
'namespace' => $rc->getNamespaceName(),
);
fwrite($fp, implode("\t", array(
$name,
$filename,
$rc->getStartLine() . ';"',
'',
)) . $build($info) . PHP_EOL);
}
// properties
foreach ($rc->getProperties(ReflectionProperty::IS_PUBLIC) as $rp) {
$info = array(
'kind' => 'p',
'class' => $rc->getShortName(),
'namespace' => $rc->getNamespaceName(),
'modifiers' => implode(' ', Reflection::getModifierNames($rp->getModifiers())),
);
fwrite($fp, implode("\t", array(
$rp->getName(),
$filename,
$rc->getStartLine() . ';"',
'',
)) . $build($info) . PHP_EOL);
}
// methods
foreach ($rc->getMethods(ReflectionMethod::IS_PUBLIC|ReflectionMethod::IS_PROTECTED) as $rm) {
if ('__' === substr($rm->getName(), 0, 2)) {
continue;
}
if (false === $rm->getStartLine()) {
continue;
}
$info = array(
'kind' => 'm',
'class' => $rc->getShortName(),
'namespace' => $rc->getNamespaceName(),
'modifiers' => implode(' ', Reflection::getModifierNames($rm->getModifiers())),
//'prototype' => .
);
$params = array();
foreach ($rm->getParameters() as $rp) {
$class = '';
if (PHP_VERSION > 50300) {
$class = $rp->getClass();
}
$param = '';
if ($class) {
$param = $class->getName() . ' ';
} elseif ($rp->isArray()) {
$param = 'array ';
}
$param .= '$' . $rp->getName();
if ($rp->isOptional() && $rm->isUserDefined()) {
$param .= '=' . json_encode($rp->getDefaultValue());
}
$params[] = $param;
}
$info['type'] = '(' . implode(', ', $params) . ')';
fwrite($fp, implode("\t", array(
$rm->getName(),
$filename,
$rm->getStartLine() . ';"',
'',
)) . $build($info) . PHP_EOL);
}
}
unset($it);
// functions
$funcs = get_defined_functions();
foreach ($funcs['internal'] as $func) {
$rf = new ReflectionFunction($func);
$info = array(
'kind' => 'f',
'namespace' => $rf->getNamespaceName(),
//'prototype' => .
);
$params = array();
foreach ($rf->getParameters() as $rp) {
$class = '';
if (!defined('HHVM_VERSION')) {
$class = $rp->getClass();
}
$param = '';
if ($class) {
$param = $class->getName() . ' ';
} elseif ($rp->isArray()) {
$param = 'array ';
}
$param .= '$' . $rp->getName();
if ($rp->isOptional() && $rf->isUserDefined()) {
$param .= '=' . json_encode($rp->getDefaultValue());
}
$params[] = $param;
}
$info['type'] = '(' . implode(', ', $params) . ')';
if ($rf->isInternal()) {
$filename = '(ext-' . $rf->getExtensionName() . ')';
} else {
$filename = str_replace($base, '', $rf->getFileName());
}
fwrite($fp, implode("\t", array(
$rf->getName(),
$filename,
$rf->getStartLine() . ';"',
'',
)) . $build($info) . PHP_EOL);
}
});
.gitignore 0000666 00000000152 13436756440 0006552 0 ustar 00 vendor/
node_modules/
npm-debug.log
phpunit.xml
phpcs.xml
phpdox.xml
artifacts
!artifacts/index.html
tags
.gitattributes 0000666 00000000141 13436756440 0007453 0 ustar 00 bin/ export-ignore
artifacts/ export-ignore
package.json export-ignore
gulpfile.js export-ignore