Skip to content

Replace PrestissimoFileFetcher with Guzzle #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"require": {
"php": ">=5.4.5",
"composer-plugin-api": "^1.0.0",
"composer/semver": "^1.4"
"composer/semver": "^1.4",
"guzzlehttp/guzzle": "^6.2.1"
},
"autoload": {
"psr-4": {
Expand Down
3 changes: 3 additions & 0 deletions src/DrupalScaffoldCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ protected function configure() {
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$vendorDir = $this->getComposer()->getConfig()->get('vendor-dir');
require $vendorDir . '/autoload.php';

$handler = new Handler($this->getComposer(), $this->getIO());
$handler->downloadScaffold();
// Generate the autoload.php file after generating the scaffold files.
Expand Down
68 changes: 68 additions & 0 deletions src/GuzzleFileFetcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace DrupalComposer\DrupalScaffold;

use Composer\Util\RemoteFilesystem;
use Composer\Config;
use Composer\IO\IOInterface;
use GuzzleHttp\Promise;
use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;

/**
* Extends the default FileFetcher and uses Guzzle for
* parallel downloads.
*/
class GuzzleFileFetcher extends FileFetcher {

/**
* @var \Composer\Config
*/
protected $config;

/**
* Constructs this RollingCurlFileFetcher object.
*/
public function __construct(RemoteFilesystem $remoteFilesystem, $source, IOInterface $io, $progress = TRUE, Config $config) {
parent::__construct($remoteFilesystem, $source, $io, $progress);
$this->config = $config;
}

/**
* {@inheritdoc}
*/
public function fetch($version, $destination, $override) {
$client = new Client();
$requests = [];
$metadata = [];

foreach ($this->filenames as $sourceFilename => $filename) {
$target = "$destination/$filename";
if ($override || !file_exists($target)) {
$url = $this->getUri($sourceFilename, $version);
$this->fs->ensureDirectoryExists($destination . '/' . dirname($filename));
$requests[] = new Request('GET', $url);
$metadata[] = [
'url' => $url,
'target' => $target,
'filename' => $filename,
];
}
}

$pool = new Pool($client, $requests, [
'concurrency' => 5,
'fulfilled' => function ($response, $index) use ($metadata) {
$this->io->writeError(" - <info>{$metadata[$index]['filename']}</info> (<comment>{$metadata[$index]['url']}</comment>): ", TRUE);
file_put_contents($metadata[$index]['target'], (string) $response->getBody());
},
'rejected' => function ($reason, $index) {
throw $reason;
},
]);

$promise = $pool->promise();
$promise->wait();
}
}
12 changes: 11 additions & 1 deletion src/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Composer\Semver\Semver;
use Composer\Util\Filesystem;
use Composer\Util\RemoteFilesystem;
use GuzzleHttp\ClientInterface;
use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;

/**
Expand Down Expand Up @@ -69,6 +70,7 @@ protected function manualLoad() {
'CommandProvider',
'DrupalScaffoldCommand',
'FileFetcher',
'GuzzleFileFetcher',
'PrestissimoFileFetcher',
];

Expand Down Expand Up @@ -157,8 +159,9 @@ public function downloadScaffold() {
$version = $this->getDrupalCoreVersion($drupalCorePackage);

$remoteFs = new RemoteFilesystem($this->io);
$fetcherClass = $this->getFetcherClass();

$fetcher = new PrestissimoFileFetcher($remoteFs, $options['source'], $this->io, $this->progress, $this->composer->getConfig());
$fetcher = new $fetcherClass($remoteFs, $options['source'], $this->io, $this->progress, $this->composer->getConfig());
$fetcher->setFilenames(array_combine($files, $files));
$fetcher->fetch($version, $webroot, TRUE);

Expand Down Expand Up @@ -408,4 +411,11 @@ protected function getInitialDefault() {
return [];
}

protected function getFetcherClass() {
if (interface_exists("\\GuzzleHttp\\ClientInterface") && Semver::satisfies(ClientInterface::VERSION, '^6')) {
return GuzzleFileFetcher::class;
}
return FileFetcher::class;
}

}
2 changes: 1 addition & 1 deletion src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static function getSubscribedEvents() {
return array(
PackageEvents::POST_PACKAGE_INSTALL => 'postPackage',
PackageEvents::POST_PACKAGE_UPDATE => 'postPackage',
ScriptEvents::POST_UPDATE_CMD => 'postCmd',
ScriptEvents::POST_AUTOLOAD_DUMP => 'postCmd',
PluginEvents::COMMAND => 'cmdBegins',
);
}
Expand Down
63 changes: 2 additions & 61 deletions src/PrestissimoFileFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,68 +11,9 @@
/**
* Extends the default FileFetcher and uses hirak/prestissimo for parallel
* downloads.
*
* @deprecated Use the GuzzleFileFetcher instead.
*/
class PrestissimoFileFetcher extends FileFetcher {

/**
* @var \Composer\Config
*/
protected $config;

/**
* Constructs this PrestissimoFileFetcher object.
*/
public function __construct(RemoteFilesystem $remoteFilesystem, $source, IOInterface $io, $progress = TRUE, Config $config) {
parent::__construct($remoteFilesystem, $source, $io, $progress);
$this->config = $config;
}

/**
* {@inheritdoc}
*/
public function fetch($version, $destination, $override) {
if (class_exists(CurlMulti::class)) {
$this->fetchWithPrestissimo($version, $destination, $override);
return;
}
parent::fetch($version, $destination, $override);
}

/**
* Fetch files in parallel.
*/
protected function fetchWithPrestissimo($version, $destination, $override) {
$requests = [];

foreach ($this->filenames as $sourceFilename => $filename) {
$target = "$destination/$filename";
if ($override || !file_exists($target)) {
$url = $this->getUri($sourceFilename, $version);
$this->fs->ensureDirectoryExists($destination . '/' . dirname($filename));
$requests[] = new CopyRequest($url, $target, FALSE, $this->io, $this->config);
}
}

$successCnt = $failureCnt = 0;
$totalCnt = count($requests);
if ($totalCnt == 0) {
return;
}

$multi = new CurlMulti();
$multi->setRequests($requests);
do {
$multi->setupEventLoop();
$multi->wait();
$result = $multi->getFinishedResults();
$successCnt += $result['successCnt'];
$failureCnt += $result['failureCnt'];
if ($this->progress) {
foreach ($result['urls'] as $url) {
$this->io->writeError(" - Downloading <comment>$successCnt</comment>/<comment>$totalCnt</comment>: <info>$url</info>", TRUE);
}
}
} while ($multi->remain());
}

}