3 namespace DrupalComposer\DrupalScaffold;
5 use Composer\Util\RemoteFilesystem;
7 use Composer\IO\IOInterface;
8 use Hirak\Prestissimo\CopyRequest;
9 use Hirak\Prestissimo\CurlMulti;
12 * Extends the default FileFetcher and uses hirak/prestissimo for parallel
15 class PrestissimoFileFetcher extends FileFetcher {
18 * @var \Composer\Config
23 * Constructs this PrestissimoFileFetcher object.
25 public function __construct(RemoteFilesystem $remoteFilesystem, $source, IOInterface $io, $progress = TRUE, Config $config) {
26 parent::__construct($remoteFilesystem, $source, $io, $progress);
27 $this->config = $config;
33 public function fetch($version, $destination, $override) {
34 if (class_exists(CurlMulti::class)) {
35 $this->fetchWithPrestissimo($version, $destination, $override);
38 parent::fetch($version, $destination, $override);
42 * Fetch files in parallel.
44 protected function fetchWithPrestissimo($version, $destination, $override) {
47 foreach ($this->filenames as $sourceFilename => $filename) {
48 $target = "$destination/$filename";
49 if ($override || !file_exists($target)) {
50 $url = $this->getUri($sourceFilename, $version);
51 $this->fs->ensureDirectoryExists($destination . '/' . dirname($filename));
52 $requests[] = new CopyRequest($url, $target, FALSE, $this->io, $this->config);
56 $successCnt = $failureCnt = 0;
58 $totalCnt = count($requests);
63 $multi = new CurlMulti();
64 $multi->setRequests($requests);
66 $multi->setupEventLoop();
68 $result = $multi->getFinishedResults();
69 $successCnt += $result['successCnt'];
70 $failureCnt += $result['failureCnt'];
71 if (isset($result['errors'])) {
72 $errors += $result['errors'];
74 if ($this->progress) {
75 foreach ($result['urls'] as $url) {
76 $this->io->writeError(" - Downloading <comment>$successCnt</comment>/<comment>$totalCnt</comment>: <info>$url</info>", TRUE);
79 } while ($multi->remain());
81 $urls = array_keys($errors);
83 throw new \Exception('Failed to download ' . implode(", ", $urls));