Support legacy rewrite for projects with mysite folder

This commit is contained in:
Damian Mooyman 2018-04-05 16:35:24 +12:00
parent 3e16a5b138
commit 9ab71cf1e9
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
4 changed files with 103 additions and 36 deletions

View File

@ -20,6 +20,10 @@
"dev-master": "1.x-dev" "dev-master": "1.x-dev"
} }
}, },
"scripts": {
"lint": "phpcs src/",
"lint-clean": "phpcbf src/"
},
"require": { "require": {
"composer-plugin-api": "^1.1" "composer-plugin-api": "^1.1"
}, },

2
phpcs.xml.dist Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset><rule ref="PSR2" /></ruleset>

View File

@ -242,7 +242,7 @@ trait RecipeCommandBehaviour
// Add new require / extra-installed // Add new require / extra-installed
$composerData['require'] = $require; $composerData['require'] = $require;
if ($previouslyInstalled){ if ($previouslyInstalled) {
if (!isset($composerData['extra'])) { if (!isset($composerData['extra'])) {
$composerData['extra'] = []; $composerData['extra'] = [];
} }

View File

@ -14,9 +14,11 @@ use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
use RegexIterator; use RegexIterator;
class RecipeInstaller extends LibraryInstaller { class RecipeInstaller extends LibraryInstaller
{
public function __construct(IOInterface $io, Composer $composer) { public function __construct(IOInterface $io, Composer $composer)
{
parent::__construct($io, $composer, null); parent::__construct($io, $composer, null);
} }
@ -30,8 +32,14 @@ class RecipeInstaller extends LibraryInstaller {
* @param string $registrationKey Registration key for installed files * @param string $registrationKey Registration key for installed files
* @param string $name Name of project file type being installed * @param string $name Name of project file type being installed
*/ */
protected function installProjectFiles($recipe, $sourceRoot, $destinationRoot, $filePatterns, $registrationKey, $name = 'project') protected function installProjectFiles(
{ $recipe,
$sourceRoot,
$destinationRoot,
$filePatterns,
$registrationKey,
$name = 'project'
) {
// load composer json data // load composer json data
$composerFile = new JsonFile(Factory::getComposerFile(), null, $this->io); $composerFile = new JsonFile(Factory::getComposerFile(), null, $this->io);
$composerData = $composerFile->read(); $composerData = $composerFile->read();
@ -42,38 +50,15 @@ class RecipeInstaller extends LibraryInstaller {
// Load all project files // Load all project files
$fileIterator = $this->getFileIterator($sourceRoot, $filePatterns); $fileIterator = $this->getFileIterator($sourceRoot, $filePatterns);
$any = false; $any = false;
foreach($fileIterator as $path => $info) { foreach ($fileIterator as $path => $info) {
$destination = $destinationRoot . substr($path, strlen($sourceRoot)); // Write header on first file
$relativePath = substr($path, strlen($sourceRoot) + 1); // Name path without leading '/'
// Write header
if (!$any) { if (!$any) {
$this->io->write("Installing {$name} files for recipe <info>{$recipe}</info>:"); $this->io->write("Installing {$name} files for recipe <info>{$recipe}</info>:");
$any = true; $any = true;
} }
// Check if file exists // Install this file
if (file_exists($destination)) { $relativePath = $this->installProjectFile($sourceRoot, $destinationRoot, $path, $installedFiles);
if (file_get_contents($destination) === file_get_contents($path)) {
$this->io->write(
" - Skipping <info>$relativePath</info> (<comment>existing, but unchanged</comment>)"
);
} else {
$this->io->write(
" - Skipping <info>$relativePath</info> (<comment>existing and modified in project</comment>)"
);
}
} elseif (in_array($relativePath, $installedFiles)) {
// Don't re-install previously installed files that have been deleted
$this->io->write(
" - Skipping <info>$relativePath</info> (<comment>previously installed</comment>)"
);
} else {
$any++;
$this->io->write(" - Copying <info>$relativePath</info>");
$this->filesystem->ensureDirectoryExists(dirname($destination));
copy($path, $destination);
}
// Add file to installed (even if already exists) // Add file to installed (even if already exists)
if (!in_array($relativePath, $installedFiles)) { if (!in_array($relativePath, $installedFiles)) {
@ -92,6 +77,46 @@ class RecipeInstaller extends LibraryInstaller {
} }
} }
/**
* @param string $sourceRoot Base of source files (no trailing slash)
* @param string $destinationRoot Base of destination directory (no trailing slash)
* @param string $sourcePath Full filesystem path to the file to copy
* @param array $installedFiles List of installed files
* @return bool|string
*/
protected function installProjectFile($sourceRoot, $destinationRoot, $sourcePath, $installedFiles)
{
// Relative path
$relativePath = substr($sourcePath, strlen($sourceRoot) + 1); // Name path without leading '/'
// Get destination path
$relativeDestination = $this->rewriteFilePath($destinationRoot, $relativePath);
$destination = $destinationRoot . DIRECTORY_SEPARATOR . $relativeDestination;
// Check if file exists
if (file_exists($destination)) {
if (file_get_contents($destination) === file_get_contents($sourcePath)) {
$this->io->write(
" - Skipping <info>$relativePath</info> (<comment>existing, but unchanged</comment>)"
);
} else {
$this->io->write(
" - Skipping <info>$relativePath</info> (<comment>existing and modified in project</comment>)"
);
}
} elseif (in_array($relativePath, $installedFiles) || in_array($relativeDestination, $installedFiles)) {
// Don't re-install previously installed files that have been deleted
$this->io->write(
" - Skipping <info>$relativePath</info> (<comment>previously installed</comment>)"
);
} else {
$this->io->write(" - Copying <info>$relativePath</info>");
$this->filesystem->ensureDirectoryExists(dirname($destination));
copy($sourcePath, $destination);
}
return $relativePath;
}
/** /**
* Get iterator of matching source files to copy * Get iterator of matching source files to copy
* *
@ -99,10 +124,11 @@ class RecipeInstaller extends LibraryInstaller {
* @param array $patterns List of wildcard patterns to match * @param array $patterns List of wildcard patterns to match
* @return Iterator File iterator, where key is path and value is file info object * @return Iterator File iterator, where key is path and value is file info object
*/ */
protected function getFileIterator($sourceRoot, $patterns) { protected function getFileIterator($sourceRoot, $patterns)
{
// Build regexp pattern // Build regexp pattern
$expressions = []; $expressions = [];
foreach($patterns as $pattern) { foreach ($patterns as $pattern) {
$expressions[] = $this->globToRegexp($pattern); $expressions[] = $this->globToRegexp($pattern);
} }
$regExp = '#^' . $this->globToRegexp($sourceRoot . '/').'(('.implode(')|(', $expressions).'))$#'; $regExp = '#^' . $this->globToRegexp($sourceRoot . '/').'(('.implode(')|(', $expressions).'))$#';
@ -127,9 +153,10 @@ class RecipeInstaller extends LibraryInstaller {
* @param string $glob * @param string $glob
* @return string * @return string
*/ */
protected function globToRegexp($glob) { protected function globToRegexp($glob)
{
$sourceParts = explode('*', $glob); $sourceParts = explode('*', $glob);
$regexParts = array_map(function($part) { $regexParts = array_map(function ($part) {
return preg_quote($part, '#'); return preg_quote($part, '#');
}, $sourceParts); }, $sourceParts);
return implode('(.+)', $regexParts); return implode('(.+)', $regexParts);
@ -183,4 +210,38 @@ class RecipeInstaller extends LibraryInstaller {
); );
} }
} }
/**
* Perform any file rewrites necessary to a relative path of a file being installed.
* E.g. if 'mysite' folder exists, rewrite 'mysite' to 'app' and 'mysite/code' to 'app/src'
*
* @deprecated 1.2..2.0 Will be removed in 2.0; app folder will be hard coded and no
* rewrites supported.
* @param string $destinationRoot Project root
* @param string $relativePath Relative path to the resource being installed
* @return string Relative path we should write to
*/
protected function rewriteFilePath($destinationRoot, $relativePath)
{
// If app folder exists, no rewrite
if (is_dir($destinationRoot . DIRECTORY_SEPARATOR . 'app')) {
return $relativePath;
}
// if mysite folder does NOT exist, no rewrite
if (!is_dir($destinationRoot . DIRECTORY_SEPARATOR . 'mysite')) {
return $relativePath;
}
// Return first rewrite
$rewrites = [
'app/src' => 'mysite/code',
'app' => 'mysite',
];
foreach ($rewrites as $from => $to) {
if (stripos($relativePath, $from) === 0) {
return $to . substr($relativePath, strlen($from));
}
}
return $relativePath;
}
} }