From 7fba1698b330068ab165a5f7aa2a5eaaf70fcbfa Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Sun, 22 Mar 2015 19:37:51 +0100 Subject: [PATCH] updated build command to set up dev environment issue #7812 --- .gitignore | 4 + build/controllers/AppController.php | 124 ------------- build/controllers/DevController.php | 267 ++++++++++++++++++++++++++++ docs/internals/getting-started.md | 8 +- 4 files changed, 276 insertions(+), 127 deletions(-) delete mode 100644 build/controllers/AppController.php create mode 100644 build/controllers/DevController.php diff --git a/.gitignore b/.gitignore index 4e4a6b9d03e..1be1354029b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ composer.phar phpunit.phar # local phpunit config /phpunit.xml + +# ignore sub directory for dev installed apps and extensions +/apps +/extensions diff --git a/build/controllers/AppController.php b/build/controllers/AppController.php deleted file mode 100644 index a9f907c4ec8..00000000000 --- a/build/controllers/AppController.php +++ /dev/null @@ -1,124 +0,0 @@ - - * @since 2.0 - */ -class AppController extends Controller -{ - public $defaultAction = 'link'; - - /** - * Properly removes symlinked directory under Windows, MacOS and Linux - * - * @param string $file path to symlink - */ - protected function unlink($file) - { - if (is_dir($file) && DIRECTORY_SEPARATOR === '\\') { - rmdir($file); - } else { - unlink($file); - } - } - - /** - * This command runs the following shell commands in the dev repo root: - * - * - Run `composer update` - * - `rm -rf apps/basic/vendor/yiisoft/yii2` - * - `rm -rf apps/basic/vendor/yiisoft/yii2-*` - * - * And replaces them with symbolic links to the extensions and framework path in the dev repo. - * @param string $app the application name `basic` or `advanced`. - */ - public function actionLink($app) - { - // root of the dev repo - $base = dirname(dirname(__DIR__)); - $appDir = "$base/apps/$app"; - - // cleanup - if (is_link($link = "$appDir/vendor/yiisoft/yii2")) { - $this->stdout("Removing symlink $link.\n"); - $this->unlink($link); - } - $extensions = $this->findDirs("$appDir/vendor/yiisoft"); - foreach($extensions as $ext) { - if (is_link($link = "$appDir/vendor/yiisoft/yii2-$ext")) { - $this->stdout("Removing symlink $link.\n"); - $this->unlink($link); - } - } - - // composer update - chdir($appDir); - passthru('composer update --prefer-dist'); - - // link directories - if (is_dir($link = "$appDir/vendor/yiisoft/yii2")) { - $this->stdout("Removing dir $link.\n"); - FileHelper::removeDirectory($link); - $this->stdout("Creating symlink for $link.\n"); - symlink("$base/framework", $link); - } - $extensions = $this->findDirs("$appDir/vendor/yiisoft"); - foreach($extensions as $ext) { - if (is_dir($link = "$appDir/vendor/yiisoft/yii2-$ext")) { - $this->stdout("Removing dir $link.\n"); - FileHelper::removeDirectory($link); - $this->stdout("Creating symlink for $link.\n"); - symlink("$base/extensions/$ext", $link); - } - } - - $this->stdout("done.\n"); - } - - /** - * Finds linkable applications - * - * @param string $dir directory to search in - * @return array list of applications command can link - */ - protected function findDirs($dir) - { - $list = []; - $handle = @opendir($dir); - if ($handle === false) { - return []; - } - while (($file = readdir($handle)) !== false) { - if ($file === '.' || $file === '..') { - continue; - } - $path = $dir . DIRECTORY_SEPARATOR . $file; - if (is_dir($path) && preg_match('/^yii2-(.*)$/', $file, $matches)) { - $list[] = $matches[1]; - } - } - closedir($handle); - - foreach($list as $i => $e) { - if ($e == 'composer') { // skip composer to not break composer update - unset($list[$i]); - } - } - - return $list; - } -} diff --git a/build/controllers/DevController.php b/build/controllers/DevController.php new file mode 100644 index 00000000000..e9a8e035230 --- /dev/null +++ b/build/controllers/DevController.php @@ -0,0 +1,267 @@ + + * @since 2.0 + */ +class DevController extends Controller +{ + public $defaultAction = 'all'; + + public $apps = [ + 'basic' => 'git@github.com:yiisoft/yii2-app-basic.git', + 'advanced' => 'git@github.com:yiisoft/yii2-app-advanced.git', + ]; + + public $extensions = [ + 'apidoc' => 'git@github.com:yiisoft/yii2-apidoc.git', + 'authclient' => 'git@github.com:yiisoft/yii2-authclient.git', + 'bootstrap' => 'git@github.com:yiisoft/yii2-bootstrap.git', + 'codeception' => 'git@github.com:yiisoft/yii2-codeception.git', + 'composer' => 'git@github.com:yiisoft/yii2-composer.git', + 'debug' => 'git@github.com:yiisoft/yii2-debug.git', + 'elasticsearch' => 'git@github.com:yiisoft/yii2-elasticsearch.git', + 'faker' => 'git@github.com:yiisoft/yii2-faker.git', + 'gii' => 'git@github.com:yiisoft/yii2-gii.git', + 'imagine' => 'git@github.com:yiisoft/yii2-imagine.git', + 'jui' => 'git@github.com:yiisoft/yii2-jui.git', + 'mongodb' => 'git@github.com:yiisoft/yii2-mongodb.git', + 'redis' => 'git@github.com:yiisoft/yii2-redis.git', + 'smarty' => 'git@github.com:yiisoft/yii2-smarty.git', + 'sphinx' => 'git@github.com:yiisoft/yii2-sphinx.git', + 'swiftmailer' => 'git@github.com:yiisoft/yii2-swiftmailer.git', + 'twig' => 'git@github.com:yiisoft/yii2-twig.git', + ]; + + + /** + * Install all extensions and advanced + basic app + */ + public function actionAll() + { + if (!$this->confirm('Install all applications and all extensions now?')) { + return 1; + } + + foreach($this->extensions as $ext => $repo) { + $ret = $this->actionExt($ext, $repo); + if ($ret !== 0) { + return $ret; + } + } + + foreach($this->apps as $app => $repo) { + $ret = $this->actionApp($app, $repo); + if ($ret !== 0) { + return $ret; + } + } + + return 0; + } + + /** + * This command installs an application template in the `apps` directory and links the framework and extensions + * + * It basically runs the following commands in the dev repo root: + * + * - Run `composer update` + * - `rm -rf apps/basic/vendor/yiisoft/yii2` + * - `rm -rf apps/basic/vendor/yiisoft/yii2-*` + * + * And replaces them with symbolic links to the extensions and framework path in the dev repo. + * + * Extensions required by the application are automatically installed using the `ext` action. + * + * @param string $app the application name e.g. `basic` or `advanced`. + * @param string $repo url of the git repo to clone if it does not already exist. + */ + public function actionApp($app, $repo = null) + { + // root of the dev repo + $base = dirname(dirname(__DIR__)); + $appDir = "$base/apps/$app"; + + if (!file_exists($appDir)) { + if (empty($repo)) { + if (isset($this->apps[$app])) { + $repo = $this->apps[$app]; + } else { + $this->stderr("Repo argument is required for app '$app'.\n", Console::FG_RED); + return 1; + } + } + + $this->stdout("cloning application repo '$app' from '$repo'...\n", Console::BOLD); + passthru('git clone ' . escapeshellarg($repo) . ' ' . $appDir); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + } + + // cleanup + $this->stdout("cleaning up application vendor directory...\n", Console::BOLD); + $this->cleanupVendorDir($appDir); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + + // composer update + $this->stdout("updating composer...\n", Console::BOLD); + chdir($appDir); + passthru('composer update --prefer-dist'); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + + // link directories + $this->stdout("linking framework and extensions to vendor dir...\n", Console::BOLD); + $this->linkFrameworkAndExtensions($appDir, $base); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + + } + + /** + * This command installs an extension in the `extensions` directory and links the framework and other extensions + * + * @param string $extension the application name e.g. `basic` or `advanced`. + * @param string $repo url of the git repo to clone if it does not already exist. + */ + public function actionExt($extension, $repo = null) + { + // root of the dev repo + $base = dirname(dirname(__DIR__)); + $extensionDir = "$base/extensions/$extension"; + + if (!file_exists($extensionDir)) { + if (empty($repo)) { + if (isset($this->extensions[$extension])) { + $repo = $this->extensions[$extension]; + } else { + $this->stderr("Repo argument is required for extension '$extension'.\n", Console::FG_RED); + return 1; + } + } + + $this->stdout("cloning extension repo '$extension' from '$repo'...\n", Console::BOLD); + passthru('git clone ' . escapeshellarg($repo) . ' ' . $extensionDir); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + } + + // cleanup + $this->stdout("cleaning up extension vendor directory...\n", Console::BOLD); + $this->cleanupVendorDir($extensionDir); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + + // composer update + $this->stdout("updating composer...\n", Console::BOLD); + chdir($extensionDir); + passthru('composer update --prefer-dist'); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + + // link directories + $this->stdout("linking framework and extensions to vendor dir...\n", Console::BOLD); + $this->linkFrameworkAndExtensions($extensionDir, $base); + $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN); + + } + + + protected function cleanupVendorDir($dir) + { + if (is_link($link = "$dir/vendor/yiisoft/yii2")) { + $this->stdout("Removing symlink $link.\n"); + $this->unlink($link); + } + $extensions = $this->findDirs("$dir/vendor/yiisoft"); + foreach($extensions as $ext) { + if (is_link($link = "$dir/vendor/yiisoft/yii2-$ext")) { + $this->stdout("Removing symlink $link.\n"); + $this->unlink($link); + } + } + } + + protected function linkFrameworkAndExtensions($dir, $base) + { + if (is_dir($link = "$dir/vendor/yiisoft/yii2")) { + $this->stdout("Removing dir $link.\n"); + FileHelper::removeDirectory($link); + $this->stdout("Creating symlink for $link.\n"); + symlink("$base/framework", $link); + } + $extensions = $this->findDirs("$dir/vendor/yiisoft"); + foreach($extensions as $ext) { + if (is_dir($link = "$dir/vendor/yiisoft/yii2-$ext")) { + $this->stdout("Removing dir $link.\n"); + FileHelper::removeDirectory($link); + $this->stdout("Creating symlink for $link.\n"); + if (!file_exists("$base/extensions/$ext")) { + $ret = $this->actionExt($ext); + if ($ret !== 0) { + return $ret; + } + } + symlink("$base/extensions/$ext", $link); + } + } + } + + /** + * Properly removes symlinked directory under Windows, MacOS and Linux + * + * @param string $file path to symlink + */ + protected function unlink($file) + { + if (is_dir($file) && DIRECTORY_SEPARATOR === '\\') { + rmdir($file); + } else { + unlink($file); + } + } + + /** + * Finds linkable applications + * + * @param string $dir directory to search in + * @return array list of applications command can link + */ + protected function findDirs($dir) + { + $list = []; + $handle = @opendir($dir); + if ($handle === false) { + return []; + } + while (($file = readdir($handle)) !== false) { + if ($file === '.' || $file === '..') { + continue; + } + $path = $dir . DIRECTORY_SEPARATOR . $file; + if (is_dir($path) && preg_match('/^yii2-(.*)$/', $file, $matches)) { + $list[] = $matches[1]; + } + } + closedir($handle); + + foreach($list as $i => $e) { + if ($e == 'composer') { // skip composer to not break composer update + unset($list[$i]); + } + } + + return $list; + } +} diff --git a/docs/internals/getting-started.md b/docs/internals/getting-started.md index eab246da6e6..e024d42d190 100644 --- a/docs/internals/getting-started.md +++ b/docs/internals/getting-started.md @@ -3,11 +3,11 @@ Getting started with Yii2 development 1. Clone your fork of yii2 `git clone git@github.com:/yii2.git`. 2. Change into the repo folder `cd yii2`. -3. run `./build/build app/link basic` to install composer dependecies for the basic app. +3. run `./build/build dev/app basic` to clone the basic app and install composer dependencies for the basic app. This command will install foreign composer packages as normal but will link the yii2 repo to the currently checked out repo, so you have one instance of all the code installed. -4. Do the same for the advanced app if needed: `./build/build app/link advanced` - This command will also be used to update dependecies, it runs `composer update` internally. +4. Do the same for the advanced app if needed: `./build/build dev/app advanced` + This command will also be used to update dependencies, it runs `composer update` internally. 5. Now you have a working playground for hacking on Yii 2. You may also add the yii2 upstream repo to pull the latest changes: @@ -32,6 +32,8 @@ You may limit the tests to a group of tests you are working on e.g. to run only Extensions ---------- +> Note: this section is outdated as we are currently changing the repository structure. instructions will be updated soon. + To work on extensions you have to install them in the application you want to try them in. Just add them to the `composer.json` as you would normally do e.g. add `"yiisoft/yii2-redis": "*"` to the `require` section of the basic app.