Merge pull request #1177 from sandermarechal/stream-context
Allow setting stream context optionspull/1182/merge
commit
b3077bc4bc
|
@ -504,8 +504,10 @@ ignored.
|
||||||
The following repository types are supported:
|
The following repository types are supported:
|
||||||
|
|
||||||
* **composer:** A composer repository is simply a `packages.json` file served
|
* **composer:** A composer repository is simply a `packages.json` file served
|
||||||
via HTTP, that contains a list of `composer.json` objects with additional
|
via the network (HTTP, FTP, SSH), that contains a list of `composer.json`
|
||||||
`dist` and/or `source` information.
|
objects with additional `dist` and/or `source` information. The `packages.json`
|
||||||
|
file is loaded using a PHP stream. You can set extra options on that stream
|
||||||
|
using the `options` parameter.
|
||||||
* **vcs:** The version control system repository can fetch packages from git,
|
* **vcs:** The version control system repository can fetch packages from git,
|
||||||
svn and hg repositories.
|
svn and hg repositories.
|
||||||
* **pear:** With this you can import any pear repository into your composer
|
* **pear:** With this you can import any pear repository into your composer
|
||||||
|
@ -524,6 +526,15 @@ Example:
|
||||||
"type": "composer",
|
"type": "composer",
|
||||||
"url": "http://packages.example.com"
|
"url": "http://packages.example.com"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "composer",
|
||||||
|
"url": "https://packages.example.com",
|
||||||
|
"options": {
|
||||||
|
"ssl": {
|
||||||
|
"verify_peer": "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://github.com/Seldaek/monolog"
|
"url": "https://github.com/Seldaek/monolog"
|
||||||
|
|
|
@ -148,6 +148,13 @@ hash changed.
|
||||||
This field is optional. You probably don't need it for your own custom
|
This field is optional. You probably don't need it for your own custom
|
||||||
repository.
|
repository.
|
||||||
|
|
||||||
|
#### stream options
|
||||||
|
|
||||||
|
The `packages.json` file is loaded using a PHP stream. You can set extra options
|
||||||
|
on that stream using the `options` parameter. You can set any valid PHP stream
|
||||||
|
context option. See [Context options and parameters](http://nl3.php.net/manual/en/context.php)
|
||||||
|
for more information.
|
||||||
|
|
||||||
### VCS
|
### VCS
|
||||||
|
|
||||||
VCS stands for version control system. This includes versioning systems like
|
VCS stands for version control system. This includes versioning systems like
|
||||||
|
|
|
@ -85,3 +85,43 @@ itself.
|
||||||
"company/package3": "dev-master"
|
"company/package3": "dev-master"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
To secure your private repository you can host it over SSH or SSL using a client
|
||||||
|
certificate. In your project you can use the `options` parameter to specify the
|
||||||
|
connection options for the server.
|
||||||
|
|
||||||
|
Example using a custom repository using SSH (requires the SSH2 PECL extension):
|
||||||
|
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "composer",
|
||||||
|
"url": "ssh2.sftp://example.org",
|
||||||
|
"options": {
|
||||||
|
"ssh2": {
|
||||||
|
"username": "composer",
|
||||||
|
"pubkey_file": "/home/composer/.ssh/id_rsa.pub",
|
||||||
|
"privkey_file": "/home/composer/.ssh/id_rsa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Example using HTTP over SSL using a client certificate:
|
||||||
|
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "composer",
|
||||||
|
"url": "https://example.org",
|
||||||
|
"options": {
|
||||||
|
"ssl": {
|
||||||
|
"cert_file": "/home/composer/.ssl/composer.pem",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ use Composer\Util\RemoteFilesystem;
|
||||||
class ComposerRepository extends ArrayRepository implements NotifiableRepositoryInterface, StreamableRepositoryInterface
|
class ComposerRepository extends ArrayRepository implements NotifiableRepositoryInterface, StreamableRepositoryInterface
|
||||||
{
|
{
|
||||||
protected $config;
|
protected $config;
|
||||||
|
protected $options;
|
||||||
protected $url;
|
protected $url;
|
||||||
protected $io;
|
protected $io;
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
@ -37,7 +38,7 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
|
||||||
|
|
||||||
public function __construct(array $repoConfig, IOInterface $io, Config $config)
|
public function __construct(array $repoConfig, IOInterface $io, Config $config)
|
||||||
{
|
{
|
||||||
if (!preg_match('{^\w+://}', $repoConfig['url'])) {
|
if (!preg_match('{^[\w.]+://}', $repoConfig['url'])) {
|
||||||
// assume http as the default protocol
|
// assume http as the default protocol
|
||||||
$repoConfig['url'] = 'http://'.$repoConfig['url'];
|
$repoConfig['url'] = 'http://'.$repoConfig['url'];
|
||||||
}
|
}
|
||||||
|
@ -46,7 +47,12 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
|
||||||
throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
|
throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isset($repoConfig['options'])) {
|
||||||
|
$repoConfig['options'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
$this->options = $repoConfig['options'];
|
||||||
$this->url = $repoConfig['url'];
|
$this->url = $repoConfig['url'];
|
||||||
$this->io = $io;
|
$this->io = $io;
|
||||||
$this->cache = new Cache($io, $config->get('home').'/cache/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url));
|
$this->cache = new Cache($io, $config->get('home').'/cache/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url));
|
||||||
|
@ -199,7 +205,7 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository
|
||||||
$jsonUrl = $this->url . '/packages.json';
|
$jsonUrl = $this->url . '/packages.json';
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = new JsonFile($jsonUrl, new RemoteFilesystem($this->io));
|
$json = new JsonFile($jsonUrl, new RemoteFilesystem($this->io, $this->options));
|
||||||
$data = $json->read();
|
$data = $json->read();
|
||||||
|
|
||||||
if (!empty($data['notify'])) {
|
if (!empty($data['notify'])) {
|
||||||
|
|
|
@ -30,15 +30,17 @@ class RemoteFilesystem
|
||||||
private $result;
|
private $result;
|
||||||
private $progress;
|
private $progress;
|
||||||
private $lastProgress;
|
private $lastProgress;
|
||||||
|
private $options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param IOInterface $io The IO instance
|
* @param IOInterface $io The IO instance
|
||||||
*/
|
*/
|
||||||
public function __construct(IOInterface $io)
|
public function __construct(IOInterface $io, $options = array())
|
||||||
{
|
{
|
||||||
$this->io = $io;
|
$this->io = $io;
|
||||||
|
$this->options = $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,6 +243,8 @@ class RemoteFilesystem
|
||||||
$options['http']['header'] .= "Authorization: Basic $authStr\r\n";
|
$options['http']['header'] .= "Authorization: Basic $authStr\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$options = array_replace_recursive($options, $this->options);
|
||||||
|
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,23 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertContains('Authorization: Basic', $options['http']['header']);
|
$this->assertContains('Authorization: Basic', $options['http']['header']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetOptionsForUrlWithStreamOptions()
|
||||||
|
{
|
||||||
|
$io = $this->getMock('Composer\IO\IOInterface');
|
||||||
|
$io
|
||||||
|
->expects($this->once())
|
||||||
|
->method('hasAuthorization')
|
||||||
|
->will($this->returnValue(true))
|
||||||
|
;
|
||||||
|
|
||||||
|
$streamOptions = array('ssl' => array(
|
||||||
|
'allow_self_signed' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$res = $this->callGetOptionsForUrl($io, array('https://example.org'), $streamOptions);
|
||||||
|
$this->assertTrue(isset($res['ssl']) && isset($res['ssl']['allow_self_signed']) && true === $res['ssl']['allow_self_signed'], 'getOptions must return an array with a allow_self_signed set to true');
|
||||||
|
}
|
||||||
|
|
||||||
public function testCallbackGetFileSize()
|
public function testCallbackGetFileSize()
|
||||||
{
|
{
|
||||||
$fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
|
$fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
|
||||||
|
@ -102,9 +119,9 @@ class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase
|
||||||
unlink($file);
|
unlink($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function callGetOptionsForUrl($io, array $args = array())
|
protected function callGetOptionsForUrl($io, array $args = array(), array $options = array())
|
||||||
{
|
{
|
||||||
$fs = new RemoteFilesystem($io);
|
$fs = new RemoteFilesystem($io, $options);
|
||||||
$ref = new \ReflectionMethod($fs, 'getOptionsForUrl');
|
$ref = new \ReflectionMethod($fs, 'getOptionsForUrl');
|
||||||
$ref->setAccessible(true);
|
$ref->setAccessible(true);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue