Browse Source

Add local cache to dist downloads

Jordi Boggiano 12 years ago
parent
commit
fb3a43b2f0
2 changed files with 44 additions and 6 deletions
  1. 33 5
      src/Composer/Cache.php
  2. 11 1
      src/Composer/Downloader/FileDownloader.php

+ 33 - 5
src/Composer/Cache.php

@@ -13,6 +13,7 @@
 namespace Composer;
 
 use Composer\IO\IOInterface;
+use Composer\Util\Filesystem;
 
 /**
  * Reads/writes to a filesystem cache
@@ -24,11 +25,15 @@ class Cache
     private $io;
     private $root;
     private $enabled = true;
+    private $whitelist;
+    private $filesystem;
 
-    public function __construct(IOInterface $io, $cacheDir)
+    public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
     {
         $this->io = $io;
         $this->root = rtrim($cacheDir, '/\\') . '/';
+        $this->whitelist = $whitelist;
+        $this->filesystem = $filesystem ?: new Filesystem();
 
         if (!is_dir($this->root)) {
             if (!@mkdir($this->root, 0777, true)) {
@@ -44,7 +49,7 @@ class Cache
 
     public function read($file)
     {
-        $file = preg_replace('{[^a-z0-9.]}i', '-', $file);
+        $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
         if ($this->enabled && file_exists($this->root . $file)) {
             return file_get_contents($this->root . $file);
         }
@@ -53,14 +58,37 @@ class Cache
     public function write($file, $contents)
     {
         if ($this->enabled) {
-            $file = preg_replace('{[^a-z0-9.]}i', '-', $file);
+            $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
             file_put_contents($this->root . $file, $contents);
         }
     }
 
+    public function copyFrom($file, $source)
+    {
+        if ($this->enabled) {
+            $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
+            $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
+            copy($source, $this->root . $file);
+        }
+    }
+
+    public function copyTo($file, $target)
+    {
+        $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
+        if ($this->enabled && file_exists($this->root . $file)) {
+            touch($this->root . $file);
+            return copy($this->root . $file, $target);
+        }
+    }
+
+    public function gc($expire)
+    {
+        // TODO
+    }
+
     public function sha1($file)
     {
-        $file = preg_replace('{[^a-z0-9.]}i', '-', $file);
+        $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
         if ($this->enabled && file_exists($this->root . $file)) {
             return sha1_file($this->root . $file);
         }
@@ -68,7 +96,7 @@ class Cache
 
     public function sha256($file)
     {
-        $file = preg_replace('{[^a-z0-9.]}i', '-', $file);
+        $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
         if ($this->enabled && file_exists($this->root . $file)) {
             return hash_file('sha256', $this->root . $file);
         }

+ 11 - 1
src/Composer/Downloader/FileDownloader.php

@@ -13,6 +13,7 @@
 namespace Composer\Downloader;
 
 use Composer\Config;
+use Composer\Cache;
 use Composer\IO\IOInterface;
 use Composer\Package\PackageInterface;
 use Composer\Package\Version\VersionParser;
@@ -33,6 +34,7 @@ class FileDownloader implements DownloaderInterface
     protected $config;
     protected $rfs;
     protected $filesystem;
+    protected $cache;
 
     /**
      * Constructor.
@@ -48,6 +50,11 @@ class FileDownloader implements DownloaderInterface
         $this->config = $config;
         $this->rfs = $rfs ?: new RemoteFilesystem($io);
         $this->filesystem = $filesystem ?: new Filesystem();
+        $this->cache = new Cache($this->io, $config->get('home').'/cache.files/', 'a-z0-9_./');
+
+        if (!rand(0, 50)) {
+            $this->cache->gc($config->get('cache-ttl') ?: 86400 * 30);
+        }
     }
 
     /**
@@ -78,7 +85,10 @@ class FileDownloader implements DownloaderInterface
 
         try {
             try {
-                $this->rfs->copy(parse_url($processUrl, PHP_URL_HOST), $processUrl, $fileName);
+                if (!$this->cache->copyTo($package->getName().'/'.$package->getVersion().'-'.$package->getDistReference().'.'.$package->getDistType(), $fileName)) {
+                    $this->rfs->copy(parse_url($processUrl, PHP_URL_HOST), $processUrl, $fileName);
+                    $this->cache->copyFrom($package->getName().'/'.$package->getVersion().'-'.$package->getDistReference().'.'.$package->getDistType(), $fileName);
+                }
             } catch (TransportException $e) {
                 if (404 === $e->getCode() && 'github.com' === parse_url($processUrl, PHP_URL_HOST)) {
                     $message = "\n".'Could not fetch '.$processUrl.', enter your GitHub credentials to access private repos';