setName('install') ->addOption( 'symlink', 's', InputOption::VALUE_NONE, 'Symlink the required bits' ) ->addArgument( 'destination', InputArgument::OPTIONAL, 'Where to install the required bits (default to current project)' ) ->setDescription('Installs the dependencies needed by Grav. Optionally can create symbolic links') ->setHelp('The install command installs the dependencies needed by Grav. Optionally can create symbolic links'); } protected function serve() { $dependencies_file = '.dependencies'; $this->destination = $this->input->getArgument('destination') ?: ROOT_DIR; // fix trailing slash $this->destination = rtrim($this->destination, DS) . DS; $this->user_path = $this->destination . USER_PATH; if ($local_config_file = $this->loadLocalConfig()) { $this->output->writeln('Read local config from ' . $local_config_file . ''); } // Look for dependencies file in ROOT and USER dir if (file_exists($this->user_path . $dependencies_file)) { $file = YamlFile::instance($this->user_path . $dependencies_file); } elseif (file_exists($this->destination . $dependencies_file)) { $file = YamlFile::instance($this->destination . $dependencies_file); } else { $this->output->writeln('ERROR Missing .dependencies file in user/ folder'); if ($this->input->getArgument('destination')) { $this->output->writeln('HINT Are you trying to install a plugin or a theme? Make sure you use bin/gpm install , not bin/grav install. This command is only used to install Grav skeletons.'); } else { $this->output->writeln('HINT Are you trying to install Grav? Grav is already installed. You need to run this command only if you download a skeleton from GitHub directly.'); } return; } $this->config = $file->content(); $file->free(); // If yaml config, process if ($this->config) { if (!$this->input->getOption('symlink')) { // Updates composer first $this->output->writeln("\nInstalling vendor dependencies"); $this->output->writeln($this->composerUpdate(GRAV_ROOT, 'install')); $this->gitclone(); } else { $this->symlink(); } } else { $this->output->writeln('ERROR invalid YAML in ' . $dependencies_file); } } /** * Clones from Git */ private function gitclone() { $this->output->writeln(''); $this->output->writeln('Cloning Bits'); $this->output->writeln('============'); $this->output->writeln(''); foreach ($this->config['git'] as $repo => $data) { $this->destination = rtrim($this->destination, DS); $path = $this->destination . DS . $data['path']; if (!file_exists($path)) { exec('cd "' . $this->destination . '" && git clone -b ' . $data['branch'] . ' --depth 1 ' . $data['url'] . ' ' . $data['path'], $output, $return); if (!$return) { $this->output->writeln('SUCCESS cloned ' . $data['url'] . ' -> ' . $path . ''); } else { $this->output->writeln('ERROR cloning ' . $data['url']); } $this->output->writeln(''); } else { $this->output->writeln('' . $path . ' already exists, skipping...'); $this->output->writeln(''); } } } /** * Symlinks */ private function symlink() { $this->output->writeln(''); $this->output->writeln('Symlinking Bits'); $this->output->writeln('==============='); $this->output->writeln(''); if (!$this->local_config) { $this->output->writeln('No local configuration available, aborting...'); $this->output->writeln(''); return; } exec('cd ' . $this->destination); foreach ($this->config['links'] as $repo => $data) { $repos = (array) $this->local_config[$data['scm'] . '_repos']; $from = false; $to = $this->destination . $data['path']; foreach ($repos as $repo) { $path = $repo . $data['src']; if (file_exists($path)) { $from = $path; continue; } } if (!$from) { $this->output->writeln('source for ' . $data['src'] . ' does not exists, skipping...'); $this->output->writeln(''); } else { if (!file_exists($to)) { symlink($from, $to); $this->output->writeln('SUCCESS symlinked ' . $data['src'] . ' -> ' . $data['path'] . ''); $this->output->writeln(''); } else { $this->output->writeln('destination: ' . $to . ' already exists, skipping...'); $this->output->writeln(''); } } } } }