Пример #1
0
 public function onPreFileDownload(CPlugin\PreFileDownloadEvent $ev)
 {
     $scheme = parse_url($ev->getProcessedUrl(), PHP_URL_SCHEME);
     if ($scheme === 'http' || $scheme === 'https') {
         $rfs = $ev->getRemoteFilesystem();
         $curlrfs = new CurlRemoteFilesystem($this->io, $this->config, $rfs->getOptions());
         $curlrfs->setPluginConfig($this->getConfig());
         $ev->setRemoteFilesystem($curlrfs);
     }
 }
 /**
  * @param Package\PackageInterface[] $packages
  * @param array $pluginConfig
  * @return void
  */
 public function download(array $packages, array $pluginConfig)
 {
     $mh = curl_multi_init();
     $unused = array();
     $maxConns = $pluginConfig['maxConnections'];
     for ($i = 0; $i < $maxConns; ++$i) {
         $unused[] = curl_init();
     }
     /// @codeCoverageIgnoreStart
     if (function_exists('curl_share_init')) {
         $sh = curl_share_init();
         curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
         foreach ($unused as $ch) {
             curl_setopt($ch, CURLOPT_SHARE, $sh);
         }
     }
     if (function_exists('curl_multi_setopt')) {
         if ($pluginConfig['pipeline']) {
             curl_multi_setopt($mh, CURLMOPT_PIPELINING, true);
         }
     }
     /// @codeCoverageIgnoreEnd
     $cachedir = rtrim($this->config->get('cache-files-dir'), '\\/');
     $chFpMap = array();
     $running = 0;
     //ref type
     $remains = 0;
     //ref type
     $this->totalCnt = count($packages);
     $this->successCnt = 0;
     $this->failureCnt = 0;
     $this->io->write("    Prefetch start: <comment>success: {$this->successCnt}, failure: {$this->failureCnt}, total: {$this->totalCnt}</comment>");
     do {
         // prepare curl resources
         while ($unused && $packages) {
             $package = array_pop($packages);
             $filepath = $cachedir . DIRECTORY_SEPARATOR . static::getCacheKey($package);
             if (file_exists($filepath)) {
                 ++$this->successCnt;
                 continue;
             }
             $ch = array_pop($unused);
             // make file resource
             $fp = CurlRemoteFilesystem::createFile($filepath);
             $chFpMap[(int) $ch] = compact('fp', 'filepath');
             // make url
             $url = $package->getDistUrl();
             $request = new Aspects\HttpGetRequest(parse_url($url, PHP_URL_HOST), $url, $this->io);
             $request->verbose = $pluginConfig['verbose'];
             if (in_array($package->getName(), $pluginConfig['privatePackages'])) {
                 $request->maybePublic = false;
             } else {
                 $request->maybePublic = preg_match('%^(?:https|git)://github\\.com%', $package->getSourceUrl());
             }
             $onPreDownload = Factory::getPreEvent($request);
             $onPreDownload->notify();
             $opts = $request->getCurlOpts();
             unset($opts[CURLOPT_ENCODING]);
             unset($opts[CURLOPT_USERPWD]);
             curl_setopt_array($ch, $opts);
             curl_setopt($ch, CURLOPT_FILE, $fp);
             curl_multi_add_handle($mh, $ch);
         }
         // start multi download
         do {
             $stat = curl_multi_exec($mh, $running);
         } while ($stat === CURLM_CALL_MULTI_PERFORM);
         // wait for any event
         do {
             switch (curl_multi_select($mh, 5)) {
                 case -1:
                     usleep(10);
                     do {
                         $stat = curl_multi_exec($mh, $running);
                     } while ($stat === CURLM_CALL_MULTI_PERFORM);
                     continue 2;
                 case 0:
                     continue 2;
                 default:
                     do {
                         $stat = curl_multi_exec($mh, $running);
                     } while ($stat === CURLM_CALL_MULTI_PERFORM);
                     do {
                         if ($raised = curl_multi_info_read($mh, $remains)) {
                             $ch = $raised['handle'];
                             $errno = curl_errno($ch);
                             $info = curl_getinfo($ch);
                             curl_setopt($ch, CURLOPT_FILE, STDOUT);
                             $index = (int) $ch;
                             $fileinfo = $chFpMap[$index];
                             unset($chFpMap[$index]);
                             $fp = $fileinfo['fp'];
                             $filepath = $fileinfo['filepath'];
                             fclose($fp);
                             if (CURLE_OK === $errno && 200 === $info['http_code']) {
                                 ++$this->successCnt;
                             } else {
                                 ++$this->failureCnt;
                                 unlink($filepath);
                             }
                             $this->io->write($this->makeDownloadingText($info['url']));
                             curl_multi_remove_handle($mh, $ch);
                             $unused[] = $ch;
                         }
                     } while ($remains);
                     if ($packages) {
                         break 2;
                     }
             }
         } while ($running);
     } while ($packages);
     $this->io->write("    Finished: <comment>success: {$this->successCnt}, failure: {$this->failureCnt}, total: {$this->totalCnt}</comment>");
     foreach ($unused as $ch) {
         curl_close($ch);
     }
     curl_multi_close($mh);
 }