-
-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow add the multiple ssh keys from UI for different git repositories
- refactor create composer config logic - remove validation logic from entity class - small fixes
- Loading branch information
Showing
40 changed files
with
1,228 additions
and
415 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Packagist\WebBundle\Composer; | ||
|
||
use Composer\Config; | ||
use Composer\Factory; | ||
use Composer\IO\IOInterface; | ||
use Composer\IO\NullIO; | ||
use Packagist\WebBundle\Composer\Util\ProcessExecutor; | ||
use Packagist\WebBundle\Entity\SshCredentials; | ||
|
||
class PackagistFactory | ||
{ | ||
protected $tmpDir; | ||
|
||
protected $repositoryFactory; | ||
|
||
public function __construct(VcsRepositoryFactory $repositoryFactory, string $tmpDir = null) | ||
{ | ||
$this->repositoryFactory = $repositoryFactory; | ||
$this->tmpDir = $tmpDir ?: sys_get_temp_dir(); | ||
} | ||
|
||
/** | ||
* @param SshCredentials|null $credentials | ||
* @return \Composer\Config | ||
*/ | ||
public function createConfig(SshCredentials $credentials = null) | ||
{ | ||
$config = Factory::createConfig(); | ||
|
||
if (null !== $credentials) { | ||
$credentialsFile = rtrim($this->tmpDir, '/') . '/packagist_priv_key_' . $credentials->getId(); | ||
if (!file_exists($credentialsFile)) { | ||
file_put_contents($credentialsFile, $credentials->getKey()); | ||
chmod($credentialsFile, 0600); | ||
} | ||
putenv("GIT_SSH_COMMAND=ssh -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $credentialsFile"); | ||
ProcessExecutor::inheritEnv(['GIT_SSH_COMMAND']); | ||
|
||
$config->merge(['config' => ['ssh-key-file' => $credentialsFile]]); | ||
} else { | ||
ProcessExecutor::inheritEnv([]); | ||
putenv('GIT_SSH_COMMAND'); | ||
} | ||
|
||
return $config; | ||
} | ||
|
||
/** | ||
* @param string $url | ||
* @param IOInterface|null $io | ||
* @param Config|null $config | ||
* @param SshCredentials|null $credentials | ||
* @param array $repoConfig | ||
* | ||
* @return Repository\VcsRepository | ||
*/ | ||
public function createRepository(string $url, IOInterface $io = null, Config $config = null, SshCredentials $credentials = null, array $repoConfig = []) | ||
{ | ||
$io = $io ?: new NullIO(); | ||
if (null === $config) { | ||
$config = $this->createConfig($credentials); | ||
$io->loadConfiguration($config); | ||
} | ||
|
||
$repoConfig['url'] = $url; | ||
|
||
return $this->repositoryFactory->create($repoConfig, $io, $config); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
src/Packagist/WebBundle/Composer/Repository/VcsRepository.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Packagist\WebBundle\Composer\Repository; | ||
|
||
use Composer\Config; | ||
use Composer\EventDispatcher\EventDispatcher; | ||
use Composer\IO\IOInterface; | ||
use Composer\Repository\Vcs\VcsDriver; | ||
use Composer\Repository\Vcs\VcsDriverInterface; | ||
use Composer\Repository\VcsRepository as ComposerVcsRepository; | ||
use Composer\Repository\VersionCacheInterface; | ||
use Packagist\WebBundle\Composer\VcsDriverFactory; | ||
|
||
class VcsRepository extends ComposerVcsRepository | ||
{ | ||
protected $drivers; | ||
|
||
/** @var VcsDriverInterface|VcsDriver */ | ||
protected $driver = false; | ||
|
||
/** @var VcsDriverFactory */ | ||
protected $driverFactory; | ||
|
||
public function __construct(array $repoConfig, IOInterface $io, Config $config, VcsDriverFactory $driverFactory, EventDispatcher $dispatcher = null, VersionCacheInterface $versionCache = null) | ||
{ | ||
parent::__construct($repoConfig, $io, $config, $dispatcher, [], $versionCache); | ||
$this->driverFactory = $driverFactory; | ||
} | ||
|
||
/** | ||
* @return VcsDriver|null | ||
*/ | ||
public function getDriver() | ||
{ | ||
if (false !== $this->driver) { | ||
return $this->driver; | ||
} | ||
|
||
return $this->driver = $this->driverFactory->createDriver( | ||
$this->repoConfig, | ||
$this->io, | ||
$this->config, | ||
$this->type, | ||
['url' => $this->url] | ||
); | ||
} | ||
|
||
/** | ||
* @return Config | ||
*/ | ||
public function getConfig() | ||
{ | ||
return $this->config; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?php | ||
|
||
namespace Packagist\WebBundle\Composer\Util; | ||
|
||
use Composer\Util\Platform; | ||
use Composer\Util\ProcessExecutor as ComposerProcessExecutor; | ||
use Symfony\Component\Process\Process; | ||
|
||
class ProcessExecutor extends ComposerProcessExecutor | ||
{ | ||
/** | ||
* @var array | ||
*/ | ||
protected static $inheritEnv = []; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function execute($command, &$output = null, $cwd = null) | ||
{ | ||
if ($this->io && $this->io->isDebug()) { | ||
$safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) { | ||
if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) { | ||
return '://***:***@'; | ||
} | ||
|
||
return '://'.$m['user'].':***@'; | ||
}, $command); | ||
$safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); | ||
$this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand); | ||
} | ||
|
||
// make sure that null translate to the proper directory in case the dir is a symlink | ||
// and we call a git command, because msysgit does not handle symlinks properly | ||
if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) { | ||
$cwd = realpath(getcwd()); | ||
} | ||
|
||
$this->captureOutput = func_num_args() > 1; | ||
$this->errorOutput = null; | ||
$env = $this->getInheritedEnv(); | ||
|
||
// in v3, commands should be passed in as arrays of cmd + args | ||
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) { | ||
$process = Process::fromShellCommandline($command, $cwd, $env, null, static::getTimeout()); | ||
} else { | ||
$process = new Process($command, $cwd, $env, null, static::getTimeout()); | ||
} | ||
|
||
$callback = is_callable($output) ? $output : array($this, 'outputHandler'); | ||
$process->run($callback); | ||
|
||
if ($this->captureOutput && !is_callable($output)) { | ||
$output = $process->getOutput(); | ||
} | ||
|
||
$this->errorOutput = $process->getErrorOutput(); | ||
|
||
return $process->getExitCode(); | ||
} | ||
|
||
/** | ||
* Sets the environment variables for child process. | ||
* | ||
* @param array $variables | ||
*/ | ||
public static function inheritEnv(?array $variables): void | ||
{ | ||
static::$inheritEnv = $variables; | ||
} | ||
|
||
/** | ||
* Sets the environment variables. | ||
*/ | ||
protected function getInheritedEnv(): ?array | ||
{ | ||
$env = []; | ||
foreach (static::$inheritEnv as $name) { | ||
if (getenv($name)) { | ||
$env[$name] = getenv($name); | ||
} | ||
} | ||
|
||
return $env ?: null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Packagist\WebBundle\Composer; | ||
|
||
use Composer\Config; | ||
use Composer\IO\IOInterface; | ||
use Composer\Repository\Vcs\VcsDriver; | ||
use Composer\Repository\Vcs\VcsDriverInterface; | ||
use Packagist\WebBundle\Composer\Util\ProcessExecutor; | ||
|
||
class VcsDriverFactory | ||
{ | ||
/** | ||
* @var array | ||
*/ | ||
protected $drivers; | ||
|
||
/** | ||
* @param array $drivers | ||
*/ | ||
public function __construct(array $drivers = []) | ||
{ | ||
$this->drivers = $drivers ?: [ | ||
'github' => 'Composer\Repository\Vcs\GitHubDriver', | ||
'gitlab' => 'Composer\Repository\Vcs\GitLabDriver', | ||
'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver', | ||
'git' => 'Composer\Repository\Vcs\GitDriver', | ||
'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver', | ||
'hg' => 'Composer\Repository\Vcs\HgDriver', | ||
'perforce' => 'Composer\Repository\Vcs\PerforceDriver', | ||
'fossil' => 'Composer\Repository\Vcs\FossilDriver', | ||
// svn must be last because identifying a subversion server for sure is practically impossible | ||
'svn' => 'Composer\Repository\Vcs\SvnDriver', | ||
]; | ||
} | ||
|
||
/** | ||
* @param string $type | ||
* @param string $class | ||
*/ | ||
public function setDriverClass(string $type, string $class): void | ||
{ | ||
$this->drivers[$type] = $class; | ||
} | ||
|
||
/** | ||
* @param string $classOrType | ||
* @param array $repoConfig | ||
* @param IOInterface $io | ||
* @param Config $config | ||
* @param array $options | ||
* | ||
* @return VcsDriver|VcsDriverInterface | ||
*/ | ||
public function createDriver(array $repoConfig, IOInterface $io, Config $config, string $classOrType = null, array $options = []) | ||
{ | ||
$process = $this->createProcessExecutor($io); | ||
|
||
$driver = null; | ||
if ($classOrType && class_exists($classOrType)) { | ||
$driver = new $classOrType($repoConfig, $io, $config, $process); | ||
return $driver; | ||
} | ||
|
||
if (null === $driver && null !== $classOrType && isset($this->drivers[$classOrType])) { | ||
$class = $this->drivers[$classOrType]; | ||
$driver = new $class($repoConfig, $io, $config); | ||
return $driver; | ||
} | ||
|
||
if (null === $driver && isset($options['url'])) { | ||
foreach ($this->drivers as $driverClass) { | ||
if ($driverClass::supports($io, $config, $options['url'])) { | ||
$driver = new $driverClass($repoConfig, $io, $config, $process); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (null === $driver && isset($options['url'])) { | ||
foreach ($this->drivers as $driverClass) { | ||
if ($driverClass::supports($io, $config, $options['url'], true)) { | ||
$driver = new $driverClass($repoConfig, $io, $config, $process); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if ($driver instanceof VcsDriverInterface) { | ||
$driver->initialize(); | ||
} | ||
|
||
return $driver; | ||
} | ||
|
||
protected function createProcessExecutor(IOInterface $io) | ||
{ | ||
return new ProcessExecutor($io); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Packagist\WebBundle\Composer; | ||
|
||
use Composer\Config; | ||
use Composer\IO\IOInterface; | ||
use Packagist\WebBundle\Composer\Repository\VcsRepository; | ||
|
||
class VcsRepositoryFactory | ||
{ | ||
/** | ||
* @var VcsDriverFactory | ||
*/ | ||
protected $driverFactory; | ||
|
||
/** | ||
* @param VcsDriverFactory $driverFactory | ||
*/ | ||
public function __construct(VcsDriverFactory $driverFactory) | ||
{ | ||
$this->driverFactory = $driverFactory; | ||
} | ||
|
||
/** | ||
* @param array $repoConfig | ||
* @param IOInterface $io | ||
* @param Config $config | ||
* | ||
* @return VcsRepository | ||
*/ | ||
public function create(array $repoConfig, IOInterface $io, Config $config) | ||
{ | ||
return new VcsRepository( | ||
$repoConfig, | ||
$io, | ||
$config, | ||
$this->driverFactory | ||
); | ||
} | ||
} |
Oops, something went wrong.