diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index eb9548a17..518b63ee3 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -49,6 +49,11 @@ class Cache } } + public function isEnabled() + { + return $this->enabled; + } + public function getRoot() { return $this->root; diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 9684edab0..7220092e7 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -26,6 +26,10 @@ class Config 'bin-dir' => '{$vendor-dir}/bin', 'notify-on-install' => true, 'github-protocols' => array('git', 'https', 'http'), + 'cache-dir' => '{$home}/cache', + 'cache-files-dir' => '{$cache-dir}/files', + 'cache-repo-dir' => '{$cache-dir}/repo', + 'cache-vcs-dir' => '{$cache-dir}/vcs', ); public static $defaultRepositories = array( @@ -115,6 +119,10 @@ class Config case 'vendor-dir': case 'bin-dir': case 'process-timeout': + case 'cache-dir': + case 'cache-files-dir': + case 'cache-repo-dir': + case 'cache-vcs-dir': // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_')); diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 48bae966d..da468f2bd 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -35,27 +35,44 @@ class Factory */ public static function createConfig() { - // load main Composer configuration - if (!$home = getenv('COMPOSER_HOME')) { + // determine home and cache dirs + $home = getenv('COMPOSER_HOME'); + $cacheDir = getenv('COMPOSER_CACHE_DIR'); + if (!$home) { if (defined('PHP_WINDOWS_VERSION_MAJOR')) { $home = getenv('APPDATA') . '/Composer'; } else { $home = rtrim(getenv('HOME'), '/') . '/.composer'; } } - - // Protect directory against web access - if (!file_exists($home . '/.htaccess')) { - if (!is_dir($home)) { - @mkdir($home, 0777, true); + if (!$cacheDir) { + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { + if ($cacheDir = getenv('LOCALAPPDATA')) { + $cacheDir .= '/Composer'; + } else { + $cacheDir = getenv('APPDATA') . '/Composer/cache'; + } + } else { + $cacheDir = $home.'/cache'; + } + } + + // Protect directory against web access. Since HOME could be + // the www-data's user home and be web-accessible it is a + // potential security risk + foreach (array($home, $cacheDir) as $dir) { + if (!file_exists($dir . '/.htaccess')) { + if (!is_dir($dir)) { + @mkdir($dir, 0777, true); + } + @file_put_contents($dir . '/.htaccess', 'Deny from all'); } - @file_put_contents($home . '/.htaccess', 'Deny from all'); } $config = new Config(); - // add home dir to the config - $config->merge(array('config' => array('home' => $home))); + // add dirs to the config + $config->merge(array('config' => array('home' => $home, 'cache-dir' => $cacheDir))); $file = new JsonFile($home.'/config.json'); if ($file->exists()) { @@ -63,6 +80,34 @@ class Factory } $config->setConfigSource(new JsonConfigSource($file)); + // move old cache dirs to the new locations + $legacyPaths = array( + 'cache-repo-dir' => array('/cache' => '/http*', '/cache.svn' => '/*', '/cache.github' => '/*'), + 'cache-vcs-dir' => array('/cache.git' => '/*', '/cache.hg' => '/*'), + 'cache-files-dir' => array('/cache.files' => '/*'), + ); + foreach ($legacyPaths as $key => $oldPaths) { + foreach ($oldPaths as $oldPath => $match) { + $dir = $config->get($key); + if ('/cache.github' === $oldPath) { + $dir .= '/github.com'; + } + $oldPath = $config->get('home').$oldPath; + $oldPathMatch = $oldPath . $match; + if (is_dir($oldPath) && $dir !== $oldPath) { + if (!is_dir($dir)) { + if (!@mkdir($dir, 0777, true)) { + continue; + } + } + foreach (glob($oldPathMatch) as $child) { + @rename($child, $dir.'/'.basename($child)); + } + @unlink($oldPath); + } + } + } + return $config; } @@ -242,7 +287,7 @@ class Factory { $cache = null; if ($config->get('cache-files-ttl') > 0) { - $cache = new Cache($io, $config->get('home').'/cache.files/', 'a-z0-9_./'); + $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./'); } $dm = new Downloader\DownloadManager(); diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 85f438db8..557c45393 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -72,7 +72,7 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository $this->url = $repoConfig['url']; $this->baseUrl = rtrim(preg_replace('{^(.*)(?:/packages.json)?(?:[?#].*)?$}', '$1', $this->url), '/'); $this->io = $io; - $this->cache = new Cache($io, $config->get('home').'/cache/'.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)); $this->loader = new ArrayLoader(); } diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index b5abbd9c4..8a6d8e42a 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -36,7 +36,7 @@ class GitDriver extends VcsDriver if (static::isLocalUrl($this->url)) { $this->repoDir = str_replace('file://', '', $this->url); } else { - $this->repoDir = $this->config->get('home') . '/cache.git/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; + $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; $fs = new Filesystem(); $fs->ensureDirectoryExists(dirname($this->repoDir)); diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 1546b7852..5fc1df471 100755 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -50,7 +50,7 @@ class GitHubDriver extends VcsDriver $this->owner = $match[1]; $this->repository = $match[2]; $this->originUrl = 'github.com'; - $this->cache = new Cache($this->io, $this->config->get('home').'/cache.github/'.$this->owner.'/'.$this->repository); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository); $this->fetchRootIdentifier(); } diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index 4c09eca35..ec590b927 100755 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -36,7 +36,7 @@ class HgDriver extends VcsDriver if (static::isLocalUrl($this->url)) { $this->repoDir = str_replace('file://', '', $this->url); } else { - $cacheDir = $this->config->get('home') . '/cache.hg'; + $cacheDir = $this->config->get('cache-vcs-dir'); $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/'; $fs = new Filesystem(); diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index a3b2b37e2..7b3cae73f 100755 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -63,7 +63,7 @@ class SvnDriver extends VcsDriver $this->baseUrl = substr($this->url, 0, $pos); } - $this->cache = new Cache($this->io, $this->config->get('home').'/cache.svn/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl)); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl)); $this->getBranches(); $this->getTags();