build/controllers/DevController.php
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];
                    if ($this->useHttp) {
                        $repo = str_replace('git@github.com:', 'https://github.com/', $repo);
                    }
                } 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 '$app' vendor directory...\n", Console::BOLD);
        $this->cleanupVendorDir($appDir);
        $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);

        // composer update
        $this->stdout("updating composer for app '$app'...\n", Console::BOLD);
        chdir($appDir);
        $command = 'composer update --prefer-dist';
        if ($this->composerNoProgress) {
            $command .= ' --no-progress';
        }
        passthru($command);
        $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);

        // link directories
        $this->stdout("linking framework and extensions to '$app' app vendor dir...\n", Console::BOLD);
        $this->linkFrameworkAndExtensions($appDir, $base);
        $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);

        return 0;
    }
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];
                    if ($this->useHttp) {
                        $repo = str_replace('git@github.com:', 'https://github.com/', $repo);
                    }
                } 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 '$app' vendor directory...\n", Console::BOLD);
        $this->cleanupVendorDir($appDir);
        $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);

        // composer update
        $this->stdout("updating composer for app '$app'...\n", Console::BOLD);
        chdir($appDir);
        $command = 'composer update --prefer-dist';
        if ($this->composerNoProgress) {
            $command .= ' --no-progress';
        }
        passthru($command);
        $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);

        // link directories
        $this->stdout("linking framework and extensions to '$app' app vendor dir...\n", Console::BOLD);
        $this->linkFrameworkAndExtensions($appDir, $base);
        $this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);

        return 0;
    }
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 ] ; if ( $ this -> useHttp ) { $ repo = str_replace ( 'git@github.com:' , 'https://github.com/' , $ repo ) ; } } 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 '$app' vendor directory...\n" , Console :: BOLD ) ; $ this -> cleanupVendorDir ( $ appDir ) ; $ this -> stdout ( "done.\n" , Console :: BOLD , Console :: FG_GREEN ) ; // composer update $ this -> stdout ( "updating composer for app '$app'...\n" , Console :: BOLD ) ; chdir ( $ appDir ) ; $ command = 'composer update --prefer-dist' ; if ( $ this -> composerNoProgress ) { $ command .= ' --no-progress' ; } passthru ( $ command ) ; $ this -> stdout ( "done.\n" , Console :: BOLD , Console :: FG_GREEN ) ; // link directories $ this -> stdout ( "linking framework and extensions to '$app' app vendor dir...\n" , Console :: BOLD ) ; $ this -> linkFrameworkAndExtensions ( $ appDir , $ base ) ; $ this -> stdout ( "done.\n" , Console :: BOLD , Console :: FG_GREEN ) ; return 0 ; }
This command installs a project 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.
@return int return code
This command installs a project template in the apps directory and links the framework and extensions .