소스 검색

Make use of new hashed provider filenames, fixes #1431, refs composer/packagist#283

Jordi Boggiano 12 년 전
부모
커밋
9521d1e7ad
1개의 변경된 파일56개의 추가작업 그리고 18개의 파일을 삭제
  1. 56 18
      src/Composer/Repository/ComposerRepository.php

+ 56 - 18
src/Composer/Repository/ComposerRepository.php

@@ -33,9 +33,11 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
     protected $url;
     protected $baseUrl;
     protected $io;
+    protected $rfs;
     protected $cache;
     protected $notifyUrl;
     protected $hasProviders = false;
+    protected $providersUrl;
     protected $providerListing;
     protected $providers = array();
     protected $providersByUid = array();
@@ -72,8 +74,9 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
         $this->url = $repoConfig['url'];
         $this->baseUrl = rtrim(preg_replace('{^(.*)(?:/packages.json)?(?:[?#].*)?$}', '$1', $this->url), '/');
         $this->io = $io;
-        $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url));
+        $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
         $this->loader = new ArrayLoader();
+        $this->rfs = new RemoteFilesystem($this->io, $this->options);
     }
 
     public function setRootAliases(array $rootAliases)
@@ -201,17 +204,31 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
             $this->loadProviderListings($this->loadRootServerFile());
         }
 
-        $url = 'p/'.$name.'.json';
+        if ($this->providersUrl) {
+            // package does not exist in this repo
+            if (!isset($this->providerListing[$name])) {
+                return array();
+            }
 
-        // package does not exist in this repo
-        if (!isset($this->providerListing[$url])) {
-            return array();
+            $hash = $this->providerListing[$name]['sha256'];
+            $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
+            $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
+        } else {
+            // BC handling for old providers-includes
+            $url = 'p/'.$name.'.json';
+
+            // package does not exist in this repo
+            if (!isset($this->providerListing[$url])) {
+                return array();
+            }
+            $hash = $this->providerListing[$url]['sha256'];
+            $cacheKey = null;
         }
 
-        if ($this->cache->sha256($url) === $this->providerListing[$url]['sha256']) {
-            $packages = json_decode($this->cache->read($url), true);
+        if ($this->cache->sha256($cacheKey) === $hash) {
+            $packages = json_decode($this->cache->read($cacheKey), true);
         } else {
-            $packages = $this->fetchFile($url, null, $this->providerListing[$url]['sha256']);
+            $packages = $this->fetchFile($url, $cacheKey, $hash);
         }
 
         $this->providers[$name] = array();
@@ -311,11 +328,18 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
 
         $data = $this->fetchFile($jsonUrl, 'packages.json');
 
+        // TODO remove this BC notify_batch support
         if (!empty($data['notify_batch'])) {
-            if ('/' === $data['notify_batch'][0]) {
-                $this->notifyUrl = preg_replace('{(https?://[^/]+).*}i', '$1' . $data['notify_batch'], $this->url);
+            $notifyBatchUrl = $data['notify_batch'];
+        }
+        if (!empty($data['notify-batch'])) {
+            $notifyBatchUrl = $data['notify-batch'];
+        }
+        if (!empty($notifyBatchUrl)) {
+            if ('/' === $notifyBatchUrl[0]) {
+                $this->notifyUrl = preg_replace('{(https?://[^/]+).*}i', '$1' . $notifyBatchUrl, $this->url);
             } else {
-                $this->notifyUrl = $data['notify_batch'];
+                $this->notifyUrl = $notifyBatchUrl;
             }
         }
 
@@ -327,6 +351,15 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
             }
         }
 
+        if (!empty($data['providers-url'])) {
+            if ('/' === $data['providers-url'][0]) {
+                $this->providersUrl = preg_replace('{(https?://[^/]+).*}i', '$1' . $data['providers-url'], $this->url);
+            } else {
+                $this->providersUrl = $data['providers-url'];
+            }
+            $this->hasProviders = true;
+        }
+
         if (!empty($data['providers']) || !empty($data['providers-includes'])) {
             $this->hasProviders = true;
         }
@@ -350,8 +383,14 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
             $this->providerListing = array_merge($this->providerListing, $data['providers']);
         }
 
-        if (isset($data['providers-includes'])) {
-            foreach ($data['providers-includes'] as $include => $metadata) {
+        if ($this->providersUrl && isset($data['provider-includes'])) {
+            $includes = $data['provider-includes'];
+        } elseif (isset($data['providers-includes'])) {
+            // BC layer for old-style providers-includes
+            $includes = $data['providers-includes'];
+        }
+        if (!empty($includes)) {
+            foreach ($includes as $include => $metadata) {
                 if ($this->cache->sha256($include) === $metadata['sha256']) {
                     $includedData = json_decode($this->cache->read($include), true);
                 } else {
@@ -421,10 +460,8 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
         $retries = 3;
         while ($retries--) {
             try {
-                $json = new JsonFile($filename, new RemoteFilesystem($this->io, $this->options));
-                $data = $json->read();
-                $encoded = json_encode($data);
-                if ($sha256 && $sha256 !== hash('sha256', $encoded)) {
+                $json = $this->rfs->getContents($filename, $filename, false);
+                if ($sha256 && $sha256 !== hash('sha256', $json)) {
                     if ($retries) {
                         usleep(100);
 
@@ -434,7 +471,8 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
                     // TODO throw SecurityException and abort once we are sure this can not happen accidentally
                     $this->io->write('<warning>The contents of '.$filename.' do not match its signature, this is most likely due to a temporary glitch but could indicate a man-in-the-middle attack. Try running composer again and please report it if it still persists.</warning>');
                 }
-                $this->cache->write($cacheKey, $encoded);
+                $data = JsonFile::parseJson($json, $filename);
+                $this->cache->write($cacheKey, $json);
 
                 break;
             } catch (\Exception $e) {