Browse Source

Merge branch 'InstallAppCommand' of https://github.com/beberlei/composer

Jordi Boggiano 13 years ago
parent
commit
cb57c7bf42

+ 22 - 0
doc/create-projects.md

@@ -0,0 +1,22 @@
+# Create Projects
+
+You can use Composer to create new projects from an existing package.
+There are several applications for this:
+
+1. You can deploy application packages.
+2. You can check out any package and start developing on patches for example.
+3. Projects with multiple developers can use this feature to bootstrap the initial application for development.
+
+To create a new project using composer you can use the "create-project",
+pass it a package name + version and a directory to create the project in.
+The directory is not allowed to exist, it will be created during installation.
+
+    php composer.phar create-project doctrine/orm 2.2.0 /path/to/new-project
+
+By default the command checks for the packages on packagist.org. To change this behavior
+you can use the --repository-url parameter and either point it to an HTTP url
+for your own packagist repository or to a packages.json file.
+
+If you want to get a development version of the code directly checked out
+from version control you have to add the --prefer-source parameter.
+

+ 130 - 0
src/Composer/Command/CreateProjectCommand.php

@@ -0,0 +1,130 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Command;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\OutputInterface;
+use Composer\IO\IOInterface;
+use Composer\Factory;
+use Composer\Repository\ComposerRepository;
+use Composer\Repository\FilesystemRepository;
+use Composer\Installer\ProjectInstaller;
+
+/**
+ * Install a package as new project into new directory.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class CreateProjectCommand extends Command
+{
+    protected function configure()
+    {
+        $this
+            ->setName('create-project')
+            ->setDescription('Create new project from a package into given directory.')
+            ->setDefinition(array(
+                new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
+                new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'Pick a different repository url to look for the package.'),
+                new InputArgument('package', InputArgument::REQUIRED),
+                new InputArgument('version', InputArgument::OPTIONAL),
+                new InputArgument('directory', InputArgument::OPTIONAL),
+            ))
+            ->setHelp(<<<EOT
+The <info>create-project</info> command creates a new project from a given
+package into a new directory. You can use this command to bootstrap new
+projects or setup a clean version-controlled installation
+for developers of your project.
+
+<info>php composer.phar create-project vendor/project intodirectory</info>
+
+To setup a developer workable version you should create the project using the source
+controlled code by appending the <info>'--prefer-source'</info> flag.
+
+To install a package from another repository repository than the default one you
+can pass the <info>'--repository-url=http://myrepository.org'</info> flag.
+
+EOT
+            )
+        ;
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $io = $this->getApplication()->getIO();
+
+        return $this->installProject(
+            $io,
+            $this->getInstallCommand($input, $output),
+            $input->getArgument('package'),
+            $input->getArgument('directory'),
+            $input->getArgument('version'),
+            (Boolean)$input->getOption('prefer-source'),
+            $input->getOption('repository-url')
+        );
+    }
+
+    protected function getInstallCommand($input, $output)
+    {
+        $app = $this->getApplication();
+        return function() use ($app, $input, $output) {
+            $newInput = new ArrayInput(array('command' => 'install'));
+            $app->doRUn($newInput, $output);
+        };
+    }
+
+    public function installProject(IOInterface $io, $installCommand, $packageName, $directory = null, $version = null, $preferSource = false, $repositoryUrl = null)
+    {
+        $dm = $this->createDownloadManager($io);
+        if ($preferSource) {
+            $dm->setPreferSource(true);
+        }
+
+        if (null === $repositoryUrl) {
+            $sourceRepo = new ComposerRepository(array('url' => 'http://packagist.org'));
+        } elseif (".json" === substr($repositoryUrl, -5)) {
+            $sourceRepo = new FilesystemRepository($repositoryUrl);
+        } elseif (0 === strpos($repositoryUrl, 'http')) {
+            $sourceRepo = new ComposerRepository(array('url' => $repositoryUrl));
+        } else {
+            throw new \InvalidArgumentException("Invalid repository url given. Has to be a .json file or an http url.");
+        }
+
+        $package = $sourceRepo->findPackage($packageName, $version);
+        if (!$package) {
+            throw new \InvalidArgumentException("Could not find package $packageName with version $version.");
+        }
+
+        if (null === $directory) {
+            $parts = explode("/", $packageName);
+            $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
+        }
+
+        $io->write('<info>Installing ' . $package->getName() . ' as new project.</info>', true);
+        $projectInstaller = new ProjectInstaller($directory, $dm);
+        $projectInstaller->install($package);
+
+        $io->write('<info>Created project into directory ' . $directory . '</info>', true);
+        chdir($directory);
+        $installCommand();
+    }
+
+    protected function createDownloadManager(IOInterface $io)
+    {
+        $factory = new Factory();
+        return $factory->createDownloadManager($io);
+    }
+}
+

+ 2 - 1
src/Composer/Console/Application.php

@@ -107,6 +107,7 @@ class Application extends BaseApplication
         $this->add(new Command\DependsCommand());
         $this->add(new Command\InitCommand());
         $this->add(new Command\InstallCommand());
+        $this->add(new Command\CreateProjectCommand());
         $this->add(new Command\UpdateCommand());
         $this->add(new Command\SearchCommand());
         $this->add(new Command\ValidateCommand());
@@ -128,4 +129,4 @@ class Application extends BaseApplication
 
         return $helperSet;
     }
-}
+}

+ 1 - 1
src/Composer/Factory.php

@@ -139,7 +139,7 @@ class Factory
         $rm->addRepository(new Repository\ComposerRepository(array('url' => 'http://packagist.org')));
     }
 
-    protected function createDownloadManager(IOInterface $io)
+    public function createDownloadManager(IOInterface $io)
     {
         $dm = new Downloader\DownloadManager();
         $dm->setDownloader('git', new Downloader\GitDownloader($io));

+ 111 - 0
src/Composer/Installer/ProjectInstaller.php

@@ -0,0 +1,111 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Installer;
+
+use Composer\DependencyResolver\Operation\OperationInterface;
+use Composer\Package\PackageInterface;
+use Composer\Downloader\DownloadManager;
+
+/**
+ * Project Installer is used to install a single package into a directory as
+ * root project.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class ProjectInstaller implements InstallerInterface
+{
+    private $installPath;
+    private $downloadManager;
+
+    public function __construct($installPath, DownloadManager $dm)
+    {
+        $this->installPath = $installPath;
+        $this->downloadManager = $dm;
+    }
+
+    /**
+     * Decides if the installer supports the given type
+     *
+     * @param   string  $packageType
+     * @return  Boolean
+     */
+    public function supports($packageType)
+    {
+        return true;
+    }
+
+    /**
+     * Checks that provided package is installed.
+     *
+     * @param   PackageInterface    $package    package instance
+     *
+     * @return  Boolean
+     */
+    public function isInstalled(PackageInterface $package)
+    {
+        return false;
+    }
+
+    /**
+     * Installs specific package.
+     *
+     * @param   PackageInterface    $package    package instance
+     */
+    public function install(PackageInterface $package)
+    {
+        $installPath = $this->installPath;
+        if (file_exists($installPath)) {
+            throw new \InvalidArgumentException("Project directory $installPath already exists.");
+        }
+        if (!file_exists(dirname($installPath))) {
+            throw new \InvalidArgumentException("Project root " . dirname($installPath) . " does not exist.");
+        }
+        mkdir($installPath, 0777);
+        $this->downloadManager->download($package, $installPath);
+    }
+
+    /**
+     * Updates specific package.
+     *
+     * @param   PackageInterface    $initial    already installed package version
+     * @param   PackageInterface    $target     updated version
+     *
+     * @throws  InvalidArgumentException        if $from package is not installed
+     */
+    public function update(PackageInterface $initial, PackageInterface $target)
+    {
+        throw new \InvalidArgumentException("not supported");
+    }
+
+    /**
+     * Uninstalls specific package.
+     *
+     * @param   PackageInterface    $package    package instance
+     */
+    public function uninstall(PackageInterface $package)
+    {
+        throw new \InvalidArgumentException("not supported");
+    }
+
+    /**
+     * Returns the installation path of a package
+     *
+     * @param   PackageInterface    $package
+     * @return  string path
+     */
+    public function getInstallPath(PackageInterface $package)
+    {
+        return $this->installPath;
+    }
+}
+