Make assets:install smarter with symlinks

This commit is contained in:
Roy Van Ginneken 2014-07-05 13:15:16 +02:00 committed by Fabien Potencier
parent 8b54211471
commit 6537333647
2 changed files with 38 additions and 14 deletions

View File

@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
/** /**
@ -47,7 +48,7 @@ A "bundles" directory will be created inside the target directory, and the
"Resources/public" directory of each bundle will be copied into it. "Resources/public" directory of each bundle will be copied into it.
To create a symlink to each bundle instead of copying its assets, use the To create a symlink to each bundle instead of copying its assets, use the
<info>--symlink</info> option: <info>--symlink</info> option (will fall back to hard copies when symbolic links aren't possible:
<info>php %command.full_name% web --symlink</info> <info>php %command.full_name% web --symlink</info>
@ -73,17 +74,17 @@ EOT
throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
} }
if (!function_exists('symlink') && $input->getOption('symlink')) {
throw new \InvalidArgumentException('The symlink() function is not available on your system. You need to install the assets without the --symlink option.');
}
$filesystem = $this->getContainer()->get('filesystem'); $filesystem = $this->getContainer()->get('filesystem');
// Create the bundles directory otherwise symlink will fail. // Create the bundles directory otherwise symlink will fail.
$bundlesDir = $targetArg.'/bundles/'; $bundlesDir = $targetArg.'/bundles/';
$filesystem->mkdir($bundlesDir, 0777); $filesystem->mkdir($bundlesDir, 0777);
$output->writeln(sprintf('Installing assets as <comment>%s</comment>', $input->getOption('symlink') ? 'symlinks' : 'hard copies')); if ($input->getOption('symlink')) {
$output->writeln('Trying to install assets as symbolic links.');
} else {
$output->writeln('Installing assets as <comment>hard copies</comment>');
}
foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) { foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) {
if (is_dir($originDir = $bundle->getPath().'/Resources/public')) { if (is_dir($originDir = $bundle->getPath().'/Resources/public')) {
@ -99,13 +100,32 @@ EOT
} else { } else {
$relativeOriginDir = $originDir; $relativeOriginDir = $originDir;
} }
$filesystem->symlink($relativeOriginDir, $targetDir);
try {
$filesystem->symlink($relativeOriginDir, $targetDir);
$output->writeln('The assets were installed using symbolic links.');
} catch (IOException $e) {
$this->hardCopy($originDir, $targetDir);
$output->writeln('It looks like your system doesn\'t support symbolic links, so the assets were installed by copying them.');
}
} else { } else {
$filesystem->mkdir($targetDir, 0777); $this->hardCopy($originDir, $targetDir);
// We use a custom iterator to ignore VCS files
$filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
} }
} }
} }
} }
/**
* @param string $originDir
* @param string $targetDir
*/
private function hardCopy($originDir, $targetDir)
{
$filesystem = $this->getContainer()->get('filesystem');
$filesystem->mkdir($targetDir, 0777);
// We use a custom iterator to ignore VCS files
$filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
}
} }

View File

@ -268,9 +268,10 @@ class Filesystem
*/ */
public function symlink($originDir, $targetDir, $copyOnWindows = false) public function symlink($originDir, $targetDir, $copyOnWindows = false)
{ {
if (!function_exists('symlink') && $copyOnWindows) { $onWindows = strtoupper(substr(php_uname('s'), 0, 3)) === 'WIN';
$this->mirror($originDir, $targetDir);
if ($onWindows && $copyOnWindows) {
$this->mirror($originDir, $targetDir);
return; return;
} }
@ -293,9 +294,12 @@ class Filesystem
throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?'); throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?');
} }
} }
throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir); throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
} }
if (!file_exists($targetDir)) {
throw new IOException(sprintf('Symbolic link "%s" is created but appears to be broken.', $targetDir), 0, null, $targetDir);
}
} }
} }
@ -374,7 +378,7 @@ class Filesystem
} }
$copyOnWindows = false; $copyOnWindows = false;
if (isset($options['copy_on_windows']) && !function_exists('symlink')) { if (isset($options['copy_on_windows'])) {
$copyOnWindows = $options['copy_on_windows']; $copyOnWindows = $options['copy_on_windows'];
} }