2011-11-03 18:22:38 +00:00
< ? php
2012-03-24 21:39:34 +00:00
/*
* This file is part of Composer .
*
* ( c ) Nils Adermann < naderman @ naderman . de >
* Jordi Boggiano < j . boggiano @ seld . be >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
2011-11-03 18:22:38 +00:00
namespace Composer\Repository ;
2012-03-08 20:59:02 +00:00
use Composer\Downloader\TransportException ;
2011-11-03 18:22:38 +00:00
use Composer\Repository\Vcs\VcsDriverInterface ;
use Composer\Package\Version\VersionParser ;
use Composer\Package\Loader\ArrayLoader ;
2012-11-05 11:08:02 +00:00
use Composer\Package\Loader\ValidatingArrayLoader ;
use Composer\Package\Loader\InvalidPackageException ;
2012-07-18 15:21:21 +00:00
use Composer\Package\Loader\LoaderInterface ;
2012-01-16 13:14:15 +00:00
use Composer\IO\IOInterface ;
2012-04-09 14:36:06 +00:00
use Composer\Config ;
2011-11-03 18:22:38 +00:00
/**
* @ author Jordi Boggiano < j . boggiano @ seld . be >
*/
class VcsRepository extends ArrayRepository
{
protected $url ;
protected $packageName ;
2012-04-01 02:32:00 +00:00
protected $verbose ;
2012-01-16 13:14:15 +00:00
protected $io ;
2012-04-24 14:56:03 +00:00
protected $config ;
2012-02-23 22:21:33 +00:00
protected $versionParser ;
2012-03-09 17:30:59 +00:00
protected $type ;
2012-07-18 15:21:21 +00:00
protected $loader ;
2012-08-30 14:52:37 +00:00
protected $repoConfig ;
2012-11-05 11:28:53 +00:00
protected $branchErrorOccurred = false ;
2011-11-03 18:22:38 +00:00
2012-05-06 11:28:37 +00:00
public function __construct ( array $repoConfig , IOInterface $io , Config $config , array $drivers = null )
2011-11-03 18:22:38 +00:00
{
2011-11-20 20:23:50 +00:00
$this -> drivers = $drivers ? : array (
2012-03-09 17:30:59 +00:00
'github' => 'Composer\Repository\Vcs\GitHubDriver' ,
'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver' ,
'git' => 'Composer\Repository\Vcs\GitDriver' ,
'svn' => 'Composer\Repository\Vcs\SvnDriver' ,
'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver' ,
'hg' => 'Composer\Repository\Vcs\HgDriver' ,
2011-11-20 20:23:50 +00:00
);
2012-04-09 14:36:06 +00:00
$this -> url = $repoConfig [ 'url' ];
2012-01-16 13:14:15 +00:00
$this -> io = $io ;
2012-04-09 14:36:06 +00:00
$this -> type = isset ( $repoConfig [ 'type' ]) ? $repoConfig [ 'type' ] : 'vcs' ;
2012-04-01 02:32:00 +00:00
$this -> verbose = $io -> isVerbose ();
2012-04-24 14:56:03 +00:00
$this -> config = $config ;
2012-08-30 14:52:37 +00:00
$this -> repoConfig = $repoConfig ;
2011-11-20 20:23:50 +00:00
}
2012-07-18 15:21:21 +00:00
public function setLoader ( LoaderInterface $loader )
{
$this -> loader = $loader ;
}
2011-11-27 19:01:56 +00:00
public function getDriver ()
2011-11-03 18:22:38 +00:00
{
2012-03-09 17:30:59 +00:00
if ( isset ( $this -> drivers [ $this -> type ])) {
$class = $this -> drivers [ $this -> type ];
2012-08-30 14:52:37 +00:00
$driver = new $class ( $this -> repoConfig , $this -> io , $this -> config );
2012-03-09 17:30:59 +00:00
$driver -> initialize ();
2012-05-22 10:07:08 +00:00
2012-03-09 17:30:59 +00:00
return $driver ;
}
2011-11-20 20:23:50 +00:00
foreach ( $this -> drivers as $driver ) {
2012-04-01 16:52:53 +00:00
if ( $driver :: supports ( $this -> io , $this -> url )) {
2012-08-30 14:52:37 +00:00
$driver = new $driver ( $this -> repoConfig , $this -> io , $this -> config );
2011-11-03 18:22:38 +00:00
$driver -> initialize ();
2012-05-22 10:07:08 +00:00
2011-11-27 19:01:56 +00:00
return $driver ;
}
}
foreach ( $this -> drivers as $driver ) {
2012-04-01 16:52:53 +00:00
if ( $driver :: supports ( $this -> io , $this -> url , true )) {
2012-08-30 14:52:37 +00:00
$driver = new $driver ( $this -> repoConfig , $this -> io , $this -> config );
2011-11-27 19:01:56 +00:00
$driver -> initialize ();
2012-05-22 10:07:08 +00:00
2011-11-27 19:01:56 +00:00
return $driver ;
2011-11-03 18:22:38 +00:00
}
}
2011-11-27 19:01:56 +00:00
}
2012-11-05 11:28:53 +00:00
public function hadInvalidBranches ()
{
return $this -> branchErrorOccurred ;
}
2011-11-27 19:01:56 +00:00
protected function initialize ()
{
parent :: initialize ();
2012-04-01 02:32:00 +00:00
$verbose = $this -> verbose ;
2011-11-03 18:22:38 +00:00
2011-11-27 19:01:56 +00:00
$driver = $this -> getDriver ();
2011-11-15 10:54:26 +00:00
if ( ! $driver ) {
throw new \InvalidArgumentException ( 'No driver found to handle VCS repository ' . $this -> url );
}
2012-02-23 22:21:33 +00:00
$this -> versionParser = new VersionParser ;
2012-07-18 15:21:21 +00:00
if ( ! $this -> loader ) {
$this -> loader = new ArrayLoader ( $this -> versionParser );
}
2011-11-03 18:22:38 +00:00
2012-03-09 23:10:41 +00:00
try {
if ( $driver -> hasComposerFile ( $driver -> getRootIdentifier ())) {
$data = $driver -> getComposerInformation ( $driver -> getRootIdentifier ());
$this -> packageName = ! empty ( $data [ 'name' ]) ? $data [ 'name' ] : null ;
}
} catch ( \Exception $e ) {
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<error>Skipped parsing ' . $driver -> getRootIdentifier () . ', ' . $e -> getMessage () . '</error>' );
2012-03-09 23:10:41 +00:00
}
2011-11-03 18:22:38 +00:00
}
foreach ( $driver -> getTags () as $tag => $identifier ) {
2012-05-06 11:28:37 +00:00
$msg = 'Reading composer.json of <info>' . ( $this -> packageName ? : $this -> url ) . '</info> (<comment>' . $tag . '</comment>)' ;
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-02-19 12:48:42 +00:00
$this -> io -> write ( $msg );
} else {
$this -> io -> overwrite ( $msg , false );
}
2012-05-28 12:41:26 +00:00
// strip the release- prefix from tags if present
$tag = str_replace ( 'release-' , '' , $tag );
2012-03-09 23:10:41 +00:00
if ( ! $parsedTag = $this -> validateTag ( $tag )) {
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped tag ' . $tag . ', invalid tag name</warning>' );
2012-03-09 23:10:41 +00:00
}
continue ;
}
try {
if ( ! $data = $driver -> getComposerInformation ( $identifier )) {
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped tag ' . $tag . ', no composer file</warning>' );
2011-11-03 18:22:38 +00:00
}
2012-02-18 18:26:43 +00:00
continue ;
2011-11-03 18:22:38 +00:00
}
2012-05-06 11:28:37 +00:00
// manually versioned package
if ( isset ( $data [ 'version' ])) {
$data [ 'version_normalized' ] = $this -> versionParser -> normalize ( $data [ 'version' ]);
} else {
2012-10-24 23:14:04 +00:00
// auto-versioned package, read value from tag
2012-05-06 11:28:37 +00:00
$data [ 'version' ] = $tag ;
$data [ 'version_normalized' ] = $parsedTag ;
2011-11-03 18:22:38 +00:00
}
2012-05-06 11:28:37 +00:00
// make sure tag packages have no -dev flag
$data [ 'version' ] = preg_replace ( '{[.-]?dev$}i' , '' , $data [ 'version' ]);
$data [ 'version_normalized' ] = preg_replace ( '{(^dev-|[.-]?dev$)}i' , '' , $data [ 'version_normalized' ]);
2011-11-03 18:22:38 +00:00
2012-05-06 11:28:37 +00:00
// broken package, version doesn't match tag
if ( $data [ 'version_normalized' ] !== $parsedTag ) {
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped tag ' . $tag . ', tag (' . $parsedTag . ') does not match version (' . $data [ 'version_normalized' ] . ') in composer.json</warning>' );
2012-05-06 11:28:37 +00:00
}
continue ;
}
2011-11-03 18:22:38 +00:00
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-05-06 11:28:37 +00:00
$this -> io -> write ( 'Importing tag ' . $tag . ' (' . $data [ 'version_normalized' ] . ')' );
2011-11-03 18:22:38 +00:00
}
2012-07-18 15:21:21 +00:00
$this -> addPackage ( $this -> loader -> load ( $this -> preProcess ( $driver , $data , $identifier )));
2012-05-06 11:28:37 +00:00
} catch ( \Exception $e ) {
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped tag ' . $tag . ', ' . ( $e instanceof TransportException ? 'no composer file was found' : $e -> getMessage ()) . '</warning>' );
2012-05-06 11:28:37 +00:00
}
continue ;
2011-11-03 18:22:38 +00:00
}
}
2012-11-02 17:12:40 +00:00
if ( ! $verbose ) {
$this -> io -> overwrite ( '' , false );
}
2012-01-16 19:09:32 +00:00
2011-11-03 18:22:38 +00:00
foreach ( $driver -> getBranches () as $branch => $identifier ) {
2012-05-06 11:28:37 +00:00
$msg = 'Reading composer.json of <info>' . ( $this -> packageName ? : $this -> url ) . '</info> (<comment>' . $branch . '</comment>)' ;
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-02-19 12:48:42 +00:00
$this -> io -> write ( $msg );
} else {
$this -> io -> overwrite ( $msg , false );
}
2012-03-09 23:10:41 +00:00
if ( ! $parsedBranch = $this -> validateBranch ( $branch )) {
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped branch ' . $branch . ', invalid name</warning>' );
2012-03-09 23:10:41 +00:00
}
continue ;
}
2011-11-03 18:22:38 +00:00
2012-03-09 23:10:41 +00:00
try {
if ( ! $data = $driver -> getComposerInformation ( $identifier )) {
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped branch ' . $branch . ', no composer file</warning>' );
2011-12-07 10:44:03 +00:00
}
continue ;
2011-11-03 18:22:38 +00:00
}
2012-05-06 11:28:37 +00:00
2012-10-24 23:14:04 +00:00
// branches are always auto-versioned, read value from branch name
2012-05-06 11:28:37 +00:00
$data [ 'version' ] = $branch ;
$data [ 'version_normalized' ] = $parsedBranch ;
// make sure branch packages have a dev flag
if ( 'dev-' === substr ( $parsedBranch , 0 , 4 ) || '9999999-dev' === $parsedBranch ) {
$data [ 'version' ] = 'dev-' . $data [ 'version' ];
} else {
$data [ 'version' ] = preg_replace ( '{(\.9{7})+}' , '.x' , $parsedBranch );
}
if ( $verbose ) {
$this -> io -> write ( 'Importing branch ' . $branch . ' (' . $data [ 'version' ] . ')' );
}
2012-11-05 11:08:02 +00:00
$packageData = $this -> preProcess ( $driver , $data , $identifier );
$package = $this -> loader -> load ( $packageData );
if ( $this -> loader instanceof ValidatingArrayLoader && $this -> loader -> getWarnings ()) {
throw new InvalidPackageException ( $this -> loader -> getErrors (), $this -> loader -> getWarnings (), $packageData );
}
$this -> addPackage ( $package );
2012-03-09 23:10:41 +00:00
} catch ( TransportException $e ) {
2012-04-01 02:32:00 +00:00
if ( $verbose ) {
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<warning>Skipped branch ' . $branch . ', no composer file was found</warning>' );
2011-11-03 18:22:38 +00:00
}
2012-03-09 23:10:41 +00:00
continue ;
} catch ( \Exception $e ) {
2012-11-05 11:23:08 +00:00
if ( ! $verbose ) {
$this -> io -> write ( '' );
}
2012-11-05 11:28:53 +00:00
$this -> branchErrorOccurred = true ;
2012-11-05 11:38:11 +00:00
$this -> io -> write ( '<error>Skipped branch ' . $branch . ', ' . $e -> getMessage () . '</error>' );
2012-11-05 11:23:08 +00:00
$this -> io -> write ( '' );
2012-03-09 23:10:41 +00:00
continue ;
}
2011-11-03 18:22:38 +00:00
}
2012-01-16 19:09:32 +00:00
2012-11-02 17:12:40 +00:00
if ( ! $verbose ) {
$this -> io -> overwrite ( '' , false );
}
2012-08-14 09:19:40 +00:00
if ( ! $this -> getPackages ()) {
2012-08-21 14:04:19 +00:00
throw new \RuntimeException ( 'No valid composer.json was found in any branch or tag of ' . $this -> url . ', could not load a package from it.' );
2012-08-14 09:19:40 +00:00
}
2011-11-03 18:22:38 +00:00
}
private function preProcess ( VcsDriverInterface $driver , array $data , $identifier )
{
// keep the name of the main identifier for all packages
$data [ 'name' ] = $this -> packageName ? : $data [ 'name' ];
if ( ! isset ( $data [ 'dist' ])) {
$data [ 'dist' ] = $driver -> getDist ( $identifier );
}
if ( ! isset ( $data [ 'source' ])) {
$data [ 'source' ] = $driver -> getSource ( $identifier );
}
return $data ;
}
2012-02-23 22:21:33 +00:00
private function validateBranch ( $branch )
2011-11-03 18:22:38 +00:00
{
try {
2012-02-23 22:21:33 +00:00
return $this -> versionParser -> normalizeBranch ( $branch );
2011-11-03 18:22:38 +00:00
} catch ( \Exception $e ) {
}
return false ;
}
2012-02-23 22:21:33 +00:00
private function validateTag ( $version )
2011-11-03 18:22:38 +00:00
{
try {
2012-02-23 22:21:33 +00:00
return $this -> versionParser -> normalize ( $version );
2011-11-03 18:22:38 +00:00
} catch ( \Exception $e ) {
}
return false ;
}
2011-11-04 08:59:55 +00:00
}