diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index ebb546a96..54cdd4240 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -13,13 +13,20 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; /** * @author Jordi Boggiano */ class GitDownloader implements DownloaderInterface { + protected $process; + + public function __construct(ProcessExecutor $process = null) + { + $this->process = $process ?: new ProcessExecutor; + } + /** * {@inheritDoc} */ @@ -39,7 +46,7 @@ class GitDownloader implements DownloaderInterface $url = escapeshellarg($package->getSourceUrl()); $ref = escapeshellarg($package->getSourceReference()); - Process::execute(sprintf('git clone %s %s && cd %2$s && git checkout %3$s && git reset --hard %3$s', $url, $path, $ref)); + $this->process->execute(sprintf('git clone %s %s && cd %2$s && git checkout %3$s && git reset --hard %3$s', $url, $path, $ref)); } /** @@ -52,7 +59,7 @@ class GitDownloader implements DownloaderInterface } $this->enforceCleanDirectory($path); - Process::execute(sprintf('cd %s && git fetch && git checkout %2$s && git reset --hard %2$s', $path, $target->getSourceReference())); + $this->process->execute(sprintf('cd %s && git fetch && git checkout %2$s && git reset --hard %2$s', $path, $target->getSourceReference())); } /** @@ -67,7 +74,7 @@ class GitDownloader implements DownloaderInterface private function enforceCleanDirectory($path) { - Process::execute(sprintf('cd %s && git status --porcelain', $path),$output); + $this->process->execute(sprintf('cd %s && git status --porcelain', $path),$output); if (implode('', $output)) { throw new \RuntimeException('Source directory has uncommitted changes'); } diff --git a/src/Composer/Downloader/HgDownloader.php b/src/Composer/Downloader/HgDownloader.php index b7d7fbbe0..d45711228 100644 --- a/src/Composer/Downloader/HgDownloader.php +++ b/src/Composer/Downloader/HgDownloader.php @@ -13,13 +13,20 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; /** * @author Per Bernhardt */ class HgDownloader implements DownloaderInterface { + protected $process; + + public function __construct(ProcessExecutor $process = null) + { + $this->process = $process ?: new ProcessExecutor; + } + /** * {@inheritDoc} */ @@ -39,7 +46,7 @@ class HgDownloader implements DownloaderInterface $url = escapeshellarg($package->getSourceUrl()); $ref = escapeshellarg($package->getSourceReference()); - Process::execute(sprintf('(hg clone %s %s 2> /dev/null) && cd %2$s && hg up %s', $url, $path, $ref)); + $this->process->execute(sprintf('(hg clone %s %s 2> /dev/null) && cd %2$s && hg up %s', $url, $path, $ref)); } /** @@ -52,7 +59,7 @@ class HgDownloader implements DownloaderInterface } $this->enforceCleanDirectory($path); - Process::execute(sprintf('cd %s && hg pull && hg up %s', $path, escapeshellarg($target->getSourceReference()))); + $this->process->execute(sprintf('cd %s && hg pull && hg up %s', $path, escapeshellarg($target->getSourceReference()))); } /** @@ -67,7 +74,7 @@ class HgDownloader implements DownloaderInterface private function enforceCleanDirectory($path) { - Process::execute(sprintf('cd %s && hg st', $path), $output); + $this->process->execute(sprintf('cd %s && hg st', $path), $output); if (implode('', $output)) { throw new \RuntimeException('Source directory has uncommitted changes'); } diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php index d6577a0b1..7661760bb 100644 --- a/src/Composer/Downloader/SvnDownloader.php +++ b/src/Composer/Downloader/SvnDownloader.php @@ -1,15 +1,32 @@ + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Composer\Downloader; use Composer\Package\PackageInterface; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; /** * @author Ben Bieker */ class SvnDownloader implements DownloaderInterface { + protected $process; + + public function __construct(ProcessExecutor $process = null) + { + $this->process = $process ?: new ProcessExecutor; + } + /** * {@inheritDoc} */ @@ -29,7 +46,7 @@ class SvnDownloader implements DownloaderInterface $url = escapeshellarg($package->getSourceUrl()); $ref = escapeshellarg($package->getSourceReference()); - Process::execute(sprintf('svn co %s/%s %s', $url, $ref, $path)); + $this->process->execute(sprintf('svn co %s/%s %s', $url, $ref, $path)); } /** @@ -43,7 +60,7 @@ class SvnDownloader implements DownloaderInterface $url = escapeshellarg($target->getSourceUrl()); $ref = escapeshellarg($target->getSourceReference()); - Process::execute(sprintf('cd %s && svn switch %s/%s', $path, $url, $ref)); + $this->process->execute(sprintf('cd %s && svn switch %s/%s', $path, $url, $ref)); } /** diff --git a/src/Composer/Downloader/Util/Filesystem.php b/src/Composer/Downloader/Util/Filesystem.php index 6e73faa63..6d044e40e 100644 --- a/src/Composer/Downloader/Util/Filesystem.php +++ b/src/Composer/Downloader/Util/Filesystem.php @@ -12,7 +12,7 @@ namespace Composer\Downloader\Util; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; /** * @author Jordi Boggiano @@ -22,10 +22,12 @@ class Filesystem public function removeDirectory($directory) { if (defined('PHP_WINDOWS_VERSION_BUILD')) { - Process::execute(sprintf('rmdir /S /Q %s', escapeshellarg(realpath($directory)))); + $cmd = sprintf('rmdir /S /Q %s', escapeshellarg(realpath($directory))); } else { - Process::execute(sprintf('rm -rf %s', escapeshellarg($directory))); + $cmd = sprintf('rm -rf %s', escapeshellarg($directory)); } + + return $this->getProcess()->execute($cmd) === 0; } public function ensureDirectoryExists($directory) @@ -127,4 +129,9 @@ class Filesystem { return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':'; } + + protected function getProcess() + { + return new ProcessExecutor; + } } \ No newline at end of file diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index 9d74d1a73..2ca0bf90d 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -3,7 +3,7 @@ namespace Composer\Repository\Vcs; use Composer\Json\JsonFile; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; /** @@ -16,11 +16,11 @@ class GitDriver extends VcsDriver implements VcsDriverInterface protected $rootIdentifier; protected $infoCache = array(); - public function __construct($url, IOInterface $io) + public function __construct($url, IOInterface $io, ProcessExecutor $process = null) { $this->tmpDir = sys_get_temp_dir() . '/composer-' . preg_replace('{[^a-z0-9]}i', '-', $url) . '/'; - parent::__construct($url, $io); + parent::__construct($url, $io, $process); } /** @@ -31,9 +31,9 @@ class GitDriver extends VcsDriver implements VcsDriverInterface $url = escapeshellarg($this->url); $tmpDir = escapeshellarg($this->tmpDir); if (is_dir($this->tmpDir)) { - Process::execute(sprintf('cd %s && git fetch origin', $tmpDir), $output); + $this->process->execute(sprintf('cd %s && git fetch origin', $tmpDir), $output); } else { - Process::execute(sprintf('git clone %s %s', $url, $tmpDir), $output); + $this->process->execute(sprintf('git clone %s %s', $url, $tmpDir), $output); } $this->getTags(); @@ -47,7 +47,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface { if (null === $this->rootIdentifier) { $this->rootIdentifier = 'master'; - Process::execute(sprintf('cd %s && git branch --no-color -r', escapeshellarg($this->tmpDir)), $output); + $this->process->execute(sprintf('cd %s && git branch --no-color -r', escapeshellarg($this->tmpDir)), $output); foreach ($output as $branch) { if ($branch && preg_match('{/HEAD +-> +[^/]+/(\S+)}', $branch, $match)) { $this->rootIdentifier = $match[1]; @@ -91,7 +91,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface public function getComposerInformation($identifier) { if (!isset($this->infoCache[$identifier])) { - Process::execute(sprintf('cd %s && git show %s:composer.json', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); + $this->process->execute(sprintf('cd %s && git show %s:composer.json', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); $composer = implode("\n", $output); unset($output); @@ -102,7 +102,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface $composer = JsonFile::parseJson($composer); if (!isset($composer['time'])) { - Process::execute(sprintf('cd %s && git log -1 --format=%%at %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); + $this->process->execute(sprintf('cd %s && git log -1 --format=%%at %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); $date = new \DateTime('@'.$output[0]); $composer['time'] = $date->format('Y-m-d H:i:s'); } @@ -118,7 +118,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface public function getTags() { if (null === $this->tags) { - Process::execute(sprintf('cd %s && git tag', escapeshellarg($this->tmpDir)), $output); + $this->process->execute(sprintf('cd %s && git tag', escapeshellarg($this->tmpDir)), $output); $this->tags = $output ? array_combine($output, $output) : array(); } @@ -133,7 +133,7 @@ class GitDriver extends VcsDriver implements VcsDriverInterface if (null === $this->branches) { $branches = array(); - Process::execute(sprintf('cd %s && git branch --no-color -rv', escapeshellarg($this->tmpDir)), $output); + $this->process->execute(sprintf('cd %s && git branch --no-color -rv', escapeshellarg($this->tmpDir)), $output); foreach ($output as $branch) { if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { preg_match('{^ *[^/]+/(\S+) *([a-f0-9]+) .*$}', $branch, $match); diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index e66fc0a6f..e458eb499 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -13,7 +13,7 @@ namespace Composer\Repository\Vcs; use Composer\Json\JsonFile; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; /** @@ -26,11 +26,11 @@ class HgDriver extends VcsDriver implements VcsDriverInterface protected $rootIdentifier; protected $infoCache = array(); - public function __construct($url, IOInterface $io) + public function __construct($url, IOInterface $io, ProcessExecutor $process = null) { $this->tmpDir = sys_get_temp_dir() . '/composer-' . preg_replace('{[^a-z0-9]}i', '-', $url) . '/'; - parent::__construct($url, $io); + parent::__construct($url, $io, $process); } /** @@ -41,9 +41,9 @@ class HgDriver extends VcsDriver implements VcsDriverInterface $url = escapeshellarg($this->url); $tmpDir = escapeshellarg($this->tmpDir); if (is_dir($this->tmpDir)) { - Process::execute(sprintf('cd %s && hg pull -u', $tmpDir), $output); + $this->process->execute(sprintf('cd %s && hg pull -u', $tmpDir), $output); } else { - Process::execute(sprintf('cd %s && hg clone %s %s', escapeshellarg(sys_get_temp_dir()), $url, $tmpDir), $output); + $this->process->execute(sprintf('cd %s && hg clone %s %s', escapeshellarg(sys_get_temp_dir()), $url, $tmpDir), $output); } $this->getTags(); @@ -57,7 +57,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface { $tmpDir = escapeshellarg($this->tmpDir); if (null === $this->rootIdentifier) { - Process::execute(sprintf('cd %s && hg tip --template "{node}"', $tmpDir), $output); + $this->process->execute(sprintf('cd %s && hg tip --template "{node}"', $tmpDir), $output); $this->rootIdentifier = $output[0]; } @@ -96,7 +96,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface public function getComposerInformation($identifier) { if (!isset($this->infoCache[$identifier])) { - Process::execute(sprintf('cd %s && hg cat -r %s composer.json', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); + $this->process->execute(sprintf('cd %s && hg cat -r %s composer.json', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); $composer = implode("\n", $output); unset($output); @@ -107,7 +107,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface $composer = JsonFile::parseJson($composer); if (!isset($composer['time'])) { - Process::execute(sprintf('cd %s && hg log --template "{date|rfc822date}" -r %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); + $this->process->execute(sprintf('cd %s && hg log --template "{date|rfc822date}" -r %s', escapeshellarg($this->tmpDir), escapeshellarg($identifier)), $output); $date = new \DateTime($output[0]); $composer['time'] = $date->format('Y-m-d H:i:s'); } @@ -125,7 +125,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface if (null === $this->tags) { $tags = array(); - Process::execute(sprintf('cd %s && hg tags', escapeshellarg($this->tmpDir)), $output); + $this->process->execute(sprintf('cd %s && hg tags', escapeshellarg($this->tmpDir)), $output); foreach ($output as $tag) { if (preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) $tags[$match[1]] = $match[2]; @@ -145,7 +145,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface if (null === $this->branches) { $branches = array(); - Process::execute(sprintf('cd %s && hg branches', escapeshellarg($this->tmpDir)), $output); + $this->process->execute(sprintf('cd %s && hg branches', escapeshellarg($this->tmpDir)), $output); foreach ($output as $branch) { if (preg_match('(^([^\s]+)\s+\d+:(.*)$)', $branch, $match)) $branches[$match[1]] = $match[2]; @@ -184,7 +184,7 @@ class HgDriver extends VcsDriver implements VcsDriverInterface return false; } - $exit = Process::execute(sprintf('cd %s && hg identify %s', escapeshellarg(sys_get_temp_dir()), escapeshellarg($url)), $ignored); + $exit = $this->process->execute(sprintf('cd %s && hg identify %s', escapeshellarg(sys_get_temp_dir()), escapeshellarg($url)), $ignored); return $exit === 0; } } diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index 9ff3ba613..ad28080a0 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -3,7 +3,7 @@ namespace Composer\Repository\Vcs; use Composer\Json\JsonFile; -use Composer\Util\Process; +use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; /** @@ -16,9 +16,9 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface protected $branches; protected $infoCache = array(); - public function __construct($url, IOInterface $io) + public function __construct($url, IOInterface $io, ProcessExecutor $process = null) { - parent::__construct($this->baseUrl = rtrim($url, '/'), $io); + parent::__construct($this->baseUrl = rtrim($url, '/'), $io, $process); if (false !== ($pos = strrpos($url, '/trunk'))) { $this->baseUrl = substr($url, 0, $pos); @@ -80,7 +80,7 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface $rev = ''; } - Process::execute(sprintf('svn cat --non-interactive %s', escapeshellarg($this->baseUrl.$identifier.'composer.json'.$rev)),$output); + $this->process->execute(sprintf('svn cat --non-interactive %s', escapeshellarg($this->baseUrl.$identifier.'composer.json'.$rev)),$output); $composer = implode("\n", $output); unset($output); @@ -91,7 +91,7 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface $composer = JsonFile::parseJson($composer); if (!isset($composer['time'])) { - Process::execute(sprintf('svn info %s', escapeshellarg($this->baseUrl.$identifier.$rev)), $output); + $this->process->execute(sprintf('svn info %s', escapeshellarg($this->baseUrl.$identifier.$rev)), $output); foreach ($output as $line) { if (preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) { $date = new \DateTime($match[1]); @@ -112,7 +112,7 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface public function getTags() { if (null === $this->tags) { - Process::execute(sprintf('svn ls --non-interactive %s', escapeshellarg($this->baseUrl.'/tags')), $output); + $this->process->execute(sprintf('svn ls --non-interactive %s', escapeshellarg($this->baseUrl.'/tags')), $output); $this->tags = array(); foreach ($output as $tag) { $this->tags[rtrim($tag, '/')] = '/tags/'.$tag; @@ -128,7 +128,7 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface public function getBranches() { if (null === $this->branches) { - Process::execute(sprintf('svn ls --verbose --non-interactive %s', escapeshellarg($this->baseUrl.'/')), $output); + $this->process->execute(sprintf('svn ls --verbose --non-interactive %s', escapeshellarg($this->baseUrl.'/')), $output); $this->branches = array(); foreach ($output as $line) { @@ -140,7 +140,7 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface } unset($output); - Process::execute(sprintf('svn ls --verbose --non-interactive %s', escapeshellarg($this->baseUrl.'/branches')), $output); + $this->process->execute(sprintf('svn ls --verbose --non-interactive %s', escapeshellarg($this->baseUrl.'/branches')), $output); foreach ($output as $line) { preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match); if ($match[2] === './') { @@ -180,7 +180,7 @@ class SvnDriver extends VcsDriver implements VcsDriverInterface return false; } - $exit = Process::execute(sprintf('svn info --non-interactive %s 2>/dev/null', escapeshellarg($url)), $ignored); + $exit = $this->process->execute(sprintf('svn info --non-interactive %s 2>/dev/null', escapeshellarg($url)), $ignored); return $exit === 0; } } diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 62d69b324..cf7af1fa9 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -13,6 +13,7 @@ namespace Composer\Repository\Vcs; use Composer\IO\IOInterface; +use Composer\Util\ProcessExecutor; /** * A driver implementation for driver with authorization interaction. @@ -23,6 +24,7 @@ abstract class VcsDriver { protected $url; protected $io; + protected $process; private $firstCall; private $contentUrl; private $content; @@ -32,11 +34,13 @@ abstract class VcsDriver * * @param string $url The URL * @param IOInterface $io The IO instance + * @param ProcessExecutor $process Process instance, injectable for mocking */ - public function __construct($url, IOInterface $io) + public function __construct($url, IOInterface $io, ProcessExecutor $process = null) { $this->url = $url; $this->io = $io; + $this->process = $process ?: new ProcessExecutor; $this->firstCall = true; } diff --git a/src/Composer/Util/Process.php b/src/Composer/Util/ProcessExecutor.php similarity index 81% rename from src/Composer/Util/Process.php rename to src/Composer/Util/ProcessExecutor.php index 1a34b0ea7..08bcc1e0e 100644 --- a/src/Composer/Util/Process.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -12,24 +12,23 @@ namespace Composer\Util; -use Symfony\Component\Process\Process as BaseProcess; +use Symfony\Component\Process\Process; /** * @author Robert Schönthal */ -class Process extends BaseProcess +class ProcessExecutor { /** * runs a process on the commandline * - * @static * @param $command the command to execute * @param null $output the output will be written into this var if passed * @return int statuscode */ - public static function execute($command, &$output = null) + public function execute($command, &$output = null) { - $process = new static($command); + $process = new Process($command); $process->run(function($type, $buffer) use ($output) { if (null === $output) { return;