1
0
Fork 0

Added support for backup PHARs

pull/1407/head
Nicolas Toniazzi 2014-10-16 14:39:48 +02:00
parent b79f38fd99
commit 83a1441285
3 changed files with 109 additions and 49 deletions

View File

@ -61,7 +61,7 @@ EOT
$config = Factory::createConfig(); $config = Factory::createConfig();
$remoteFilesystem = new RemoteFilesystem($this->getIO(), $config); $remoteFilesystem = new RemoteFilesystem($this->getIO(), $config);
$cacheDir = $config->get('cache-dir'); $cacheDir = $config->get('cache-dir');
$rollbackDir = $config->get('home'); $rollbackDir = $config->get('data-dir');
$localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
// check if current dir is writable and if not try the cache dir from settings // check if current dir is writable and if not try the cache dir from settings

View File

@ -28,6 +28,7 @@ class Config
'vendor-dir' => 'vendor', 'vendor-dir' => 'vendor',
'bin-dir' => '{$vendor-dir}/bin', 'bin-dir' => '{$vendor-dir}/bin',
'cache-dir' => '{$home}/cache', 'cache-dir' => '{$home}/cache',
'data-dir' => '{$home}',
'cache-files-dir' => '{$cache-dir}/files', 'cache-files-dir' => '{$cache-dir}/files',
'cache-repo-dir' => '{$cache-dir}/repo', 'cache-repo-dir' => '{$cache-dir}/repo',
'cache-vcs-dir' => '{$cache-dir}/vcs', 'cache-vcs-dir' => '{$cache-dir}/vcs',
@ -157,6 +158,7 @@ class Config
case 'vendor-dir': case 'vendor-dir':
case 'bin-dir': case 'bin-dir':
case 'process-timeout': case 'process-timeout':
case 'data-dir':
case 'cache-dir': case 'cache-dir':
case 'cache-files-dir': case 'cache-files-dir':
case 'cache-repo-dir': case 'cache-repo-dir':

View File

@ -36,6 +36,7 @@ use Composer\Package\Version\VersionParser;
*/ */
class Factory class Factory
{ {
/** /**
* @return string * @return string
* @throws \RuntimeException * @throws \RuntimeException
@ -43,22 +44,28 @@ class Factory
protected static function getHomeDir() protected static function getHomeDir()
{ {
$home = getenv('COMPOSER_HOME'); $home = getenv('COMPOSER_HOME');
$cacheDir = getenv('COMPOSER_CACHE_DIR');
$userDir = rtrim(getenv('HOME'), '/');
$followXDG = false;
if (!$home) { if (!$home) {
if (defined('PHP_WINDOWS_VERSION_MAJOR')) { if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$home = getenv('APPDATA') . '/Composer'; if (!getenv('APPDATA')) {
} elseif (getenv('XDG_CONFIG_DIRS')) { throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
}
$home = strtr(getenv('APPDATA'), '\\', '/') . '/Composer';
} else {
if (!getenv('HOME')) {
throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
}
$userDir = rtrim(getenv('HOME'), '/');
if (getenv('XDG_CONFIG_DIRS')) {
// XDG Base Directory Specifications // XDG Base Directory Specifications
$followXDG = true;
$xdgConfig = getenv('XDG_CONFIG_HOME'); $xdgConfig = getenv('XDG_CONFIG_HOME');
if (!$xdgConfig) { if (!$xdgConfig) {
$xdgConfig = $userDir . '/.config'; $xdgConfig = $userDir . '/.config';
} }
$home = $xdgConfig . '/composer'; $home = $xdgConfig . '/composer';
} else { } else {
$home = $userDir . '/.composer'; $home = $userDir . '/composer';
}
} }
} }
@ -80,24 +87,64 @@ class Factory
} else { } else {
$cacheDir = $home . '/cache'; $cacheDir = $home . '/cache';
} }
$cacheDir = strtr($cacheDir, '\\', '/');
} elseif (getenv('XDG_CONFIG_DIRS')) { } elseif (getenv('XDG_CONFIG_DIRS')) {
$followXDG = true;
$xdgCache = getenv('XDG_CACHE_HOME'); $xdgCache = getenv('XDG_CACHE_HOME');
if (!$xdgCache) { if (!$xdgCache) {
$xdgCache = $userDir . '/.cache'; $xdgCache = $home . '/.cache';
} }
$cacheDir = $xdgCache . '/composer'; $cacheDir = $xdgCache . '/composer';
} else { } else {
$cacheDir = $home . '/.cache'; $cacheDir = $home . '/cache';
} }
} }
return $cacheDir;
}
/**
* @param string $home
*
* @return string
*/
protected static function getDataDir($home)
{
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$dataDir = strtr($home, '\\', '/');
} elseif (getenv('XDG_CONFIG_DIRS')) {
$xdgData = getenv('XDG_DATA_HOME');
if (!$xdgData) {
if (!getenv('HOME')) {
throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
}
$userDir = rtrim(getenv('HOME'), '/');
$xdgData = $userDir . '/.local/share';
}
$dataDir = $xdgData . '/composer';
} else {
$dataDir = $home;
}
return $dataDir;
}
/**
* @param IOInterface|null $io
* @return Config
*/
public static function createConfig(IOInterface $io = null)
{
// determine home and cache dirs
$home = self::getHomeDir();
$cacheDir = self::getCacheDir($home);
$dataDir = self::getDataDir($home);
// Protect directory against web access. Since HOME could be // Protect directory against web access. Since HOME could be
// the www-data's user home and be web-accessible it is a // the www-data's user home and be web-accessible it is a
// potential security risk // potential security risk
foreach (array($home, $cacheDir) as $dir) { foreach (array($home, $cacheDir, $dataDir) as $dir) {
if (!file_exists($dir . '/.htaccess')) { if (!file_exists($dir . '/.htaccess')) {
if (!is_dir($dir)) { if (!is_dir($dir)) {
@mkdir($dir, 0777, true); @mkdir($dir, 0777, true);
@ -107,22 +154,34 @@ class Factory
} }
// Move content of old composer dir to XDG // Move content of old composer dir to XDG
if ($followXDG && file_exists($userDir . '/.composer')) { if (getenv('XDG_CONFIG_DIRS') !== false && getenv('COMPOSER_HOME') === false && getenv('COMPOSER_CACHE_DIR') === false) {
$userDir = rtrim(getenv('HOME'), '/');
$oldComposerHome = $userDir . '/.composer';
if (file_exists($oldComposerHome)) {
// migrate to XDG // migrate to XDG
@rename($userDir . '/.composer/config.json', $home . '/config.json'); foreach (glob($oldComposerHome . '/*.json') as $file) {
@unlink($userDir . '/.composer/.htaccess'); rename($file, $home . '/' . basename($file));
@unlink($userDir . '/.composer/cache/.htaccess'); }
foreach (glob($userDir . '/.composer/cache/*') as $oldCacheDir) {
@rename($oldCacheDir, $cacheDir . '/' . basename($oldCacheDir)); foreach (glob($oldComposerHome . '/*.phar') as $file) {
rename($file, $dataDir . '/' . basename($file));
}
foreach (glob($oldComposerHome . '/cache/*') as $oldCacheDir) {
rename($oldCacheDir, $cacheDir . '/' . basename($oldCacheDir));
}
unlink($oldComposerHome . '/.htaccess');
unlink($oldComposerHome . '/cache/.htaccess');
rmdir($oldComposerHome . '/cache');
rmdir($oldComposerHome);
} }
@rmdir($userDir . '/.composer/cache');
@rmdir($userDir . '/.composer');
} }
$config = new Config(); $config = new Config();
// add dirs to the config // add dirs to the config
$config->merge(array('config' => array('home' => $home, 'cache-dir' => $cacheDir))); $config->merge(array('config' => array('home' => $home, 'cache-dir' => $cacheDir, 'data-dir' => $dataDir)));
// load global config // load global config
$file = new JsonFile($home.'/config.json'); $file = new JsonFile($home.'/config.json');
@ -149,7 +208,7 @@ class Factory
public static function getComposerFile() public static function getComposerFile()
{ {
return trim(getenv('COMPOSER')) ?: './composer.json'; return trim(getenv('COMPOSER')) ? : './composer.json';
} }
public static function createAdditionalStyles() public static function createAdditionalStyles()
@ -177,10 +236,10 @@ class Factory
foreach ($config->getRepositories() as $index => $repo) { foreach ($config->getRepositories() as $index => $repo) {
if (!is_array($repo)) { if (!is_array($repo)) {
throw new \UnexpectedValueException('Repository '.$index.' ('.json_encode($repo).') should be an array, '.gettype($repo).' given'); throw new \UnexpectedValueException('Repository ' . $index . ' (' . json_encode($repo) . ') should be an array, ' . gettype($repo) . ' given');
} }
if (!isset($repo['type'])) { if (!isset($repo['type'])) {
throw new \UnexpectedValueException('Repository '.$index.' ('.json_encode($repo).') must have a type defined'); throw new \UnexpectedValueException('Repository ' . $index . ' (' . json_encode($repo) . ') must have a type defined');
} }
$name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index; $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
while (isset($repos[$name])) { while (isset($repos[$name])) {
@ -216,12 +275,12 @@ class Factory
if (!$file->exists()) { if (!$file->exists()) {
if ($localConfig === './composer.json' || $localConfig === 'composer.json') { if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
$message = 'Composer could not find a composer.json file in '.getcwd(); $message = 'Composer could not find a composer.json file in ' . getcwd();
} else { } else {
$message = 'Composer could not find the config file: '.$localConfig; $message = 'Composer could not find the config file: ' . $localConfig;
} }
$instructions = 'To initialize a project, please create a composer.json file as described in the http://getcomposer.org/ "Getting Started" section'; $instructions = 'To initialize a project, please create a composer.json file as described in the http://getcomposer.org/ "Getting Started" section';
throw new \InvalidArgumentException($message.PHP_EOL.$instructions); throw new \InvalidArgumentException($message . PHP_EOL . $instructions);
} }
$file->validateSchema(JsonFile::LAX_SCHEMA); $file->validateSchema(JsonFile::LAX_SCHEMA);
@ -306,9 +365,7 @@ class Factory
// init locker if possible // init locker if possible
if (isset($composerFile)) { if (isset($composerFile)) {
$lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION) $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION) ? substr($composerFile, 0, -4) . 'lock' : $composerFile . '.lock';
? substr($composerFile, 0, -4).'lock'
: $composerFile . '.lock';
$locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile)); $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile));
$composer->setLocker($locker); $composer->setLocker($locker);
} }
@ -344,7 +401,7 @@ class Factory
*/ */
protected function addLocalRepository(RepositoryManager $rm, $vendorDir) protected function addLocalRepository(RepositoryManager $rm, $vendorDir)
{ {
$rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json'))); $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir . '/composer/installed.json')));
} }
/** /**
@ -358,7 +415,7 @@ class Factory
return null; return null;
} }
$path = $config->get('home').'/vendor/composer/installed.json'; $path = $config->get('home') . '/vendor/composer/installed.json';
if (!file_exists($path)) { if (!file_exists($path)) {
return null; return null;
} }
@ -486,4 +543,5 @@ class Factory
return $factory->createComposer($io, $config, $disablePlugins); return $factory->createComposer($io, $config, $disablePlugins);
} }
} }