mirror of
https://github.com/getgrav/grav.git
synced 2026-01-30 03:10:06 +01:00
Merge branch 'develop' of https://github.com/getgrav/grav into feature/blueprints-update
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.0.10');
|
||||
define('GRAV_VERSION', '1.1.0-beta');
|
||||
define('DS', '/');
|
||||
define('GRAV_PHP_MIN', '5.5.9');
|
||||
|
||||
|
||||
@@ -3,6 +3,17 @@ namespace Grav\Common\GPM\Common;
|
||||
|
||||
use Grav\Common\Data\Data;
|
||||
|
||||
/**
|
||||
* @property string name
|
||||
* @property string version
|
||||
* @property string available
|
||||
* @property string package_type
|
||||
* @property string description_plain
|
||||
* @property string slug
|
||||
* @property array author
|
||||
* @property mixed changelog
|
||||
*/
|
||||
|
||||
class Package {
|
||||
|
||||
protected $data;
|
||||
|
||||
@@ -194,6 +194,28 @@ class GPM extends Iterator
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest release of a package from the GPM
|
||||
*
|
||||
* @param $package_name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLatestVersionOfPackage($package_name)
|
||||
{
|
||||
$repository = $this->repository['plugins'];
|
||||
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->version;
|
||||
}
|
||||
|
||||
//Not a plugin, it's a theme?
|
||||
$repository = $this->repository['themes'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->version;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Plugin or Theme is updatable
|
||||
* @param string $slug The slug of the package
|
||||
@@ -349,11 +371,6 @@ class GPM extends Iterator
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of Plugins and Themes available in the repository
|
||||
* @return array Array of available Plugins and Themes
|
||||
* Format: ['plugins' => array, 'themes' => array]
|
||||
*/
|
||||
/**
|
||||
* Searches for a list of Packages in the repository
|
||||
* @param array $searches An array of either slugs or names
|
||||
|
||||
@@ -12,7 +12,7 @@ class Plugins extends AbstractPackageCollection
|
||||
*/
|
||||
protected $type = 'plugins';
|
||||
|
||||
protected $repository = 'https://getgrav.org/downloads/plugins.json';
|
||||
protected $repository = 'https://getgrav.org/downloads/plugins.json?v=' . GRAV_VERSION;
|
||||
|
||||
/**
|
||||
* Local Plugins Constructor
|
||||
|
||||
@@ -12,7 +12,7 @@ class Themes extends AbstractPackageCollection
|
||||
*/
|
||||
protected $type = 'themes';
|
||||
|
||||
protected $repository = 'https://getgrav.org/downloads/themes.json';
|
||||
protected $repository = 'https://getgrav.org/downloads/themes.json?v=' . GRAV_VERSION;
|
||||
|
||||
/**
|
||||
* Local Themes Constructor
|
||||
|
||||
@@ -14,7 +14,10 @@ use Symfony\Component\Console\Input\InputArgument;
|
||||
*/
|
||||
class BackupCommand extends ConsoleCommand
|
||||
{
|
||||
/** @var string $source */
|
||||
protected $source;
|
||||
|
||||
/** @var ProgressBar $progress */
|
||||
protected $progress;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Grav\Console\Cli;
|
||||
use Grav\Common\Filesystem\Folder;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
|
||||
@@ -184,6 +183,9 @@ class CleanCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int|null|void
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
@@ -214,7 +216,7 @@ class CleanCommand extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set colors style definition for the formatter.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
@@ -222,16 +224,16 @@ class CleanCommand extends Command
|
||||
*/
|
||||
public function setupConsole(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->input = $input;
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
|
||||
$this->output->getFormatter()->setStyle('normal', new OutputFormatterStyle('white'));
|
||||
$this->output->getFormatter()->setStyle('yellow', new OutputFormatterStyle('yellow', null, array('bold')));
|
||||
$this->output->getFormatter()->setStyle('red', new OutputFormatterStyle('red', null, array('bold')));
|
||||
$this->output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan', null, array('bold')));
|
||||
$this->output->getFormatter()->setStyle('green', new OutputFormatterStyle('green', null, array('bold')));
|
||||
$this->output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta', null, array('bold')));
|
||||
$this->output->getFormatter()->setStyle('white', new OutputFormatterStyle('white', null, array('bold')));
|
||||
$this->output->getFormatter()->setStyle('yellow', new OutputFormatterStyle('yellow', null, ['bold']));
|
||||
$this->output->getFormatter()->setStyle('red', new OutputFormatterStyle('red', null, ['bold']));
|
||||
$this->output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan', null, ['bold']));
|
||||
$this->output->getFormatter()->setStyle('green', new OutputFormatterStyle('green', null, ['bold']));
|
||||
$this->output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta', null, ['bold']));
|
||||
$this->output->getFormatter()->setStyle('white', new OutputFormatterStyle('white', null, ['bold']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
namespace Grav\Console\Cli;
|
||||
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,17 +43,17 @@ class NewProjectCommand extends ConsoleCommand
|
||||
$sandboxCommand = $this->getApplication()->find('sandbox');
|
||||
$installCommand = $this->getApplication()->find('install');
|
||||
|
||||
$sandboxArguments = new ArrayInput(array(
|
||||
$sandboxArguments = new ArrayInput([
|
||||
'command' => 'sandbox',
|
||||
'destination' => $this->input->getArgument('destination'),
|
||||
'-s' => $this->input->getOption('symlink')
|
||||
));
|
||||
]);
|
||||
|
||||
$installArguments = new ArrayInput(array(
|
||||
$installArguments = new ArrayInput([
|
||||
'command' => 'install',
|
||||
'destination' => $this->input->getArgument('destination'),
|
||||
'-s' => $this->input->getOption('symlink')
|
||||
));
|
||||
]);
|
||||
|
||||
$sandboxCommand->run($sandboxArguments, $this->output);
|
||||
$installCommand->run($installArguments, $this->output);
|
||||
|
||||
@@ -15,7 +15,7 @@ class SandboxCommand extends ConsoleCommand
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $directories = array(
|
||||
protected $directories = [
|
||||
'/backup',
|
||||
'/cache',
|
||||
'/logs',
|
||||
@@ -27,22 +27,22 @@ class SandboxCommand extends ConsoleCommand
|
||||
'/user/data',
|
||||
'/user/plugins',
|
||||
'/user/themes',
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $files = array(
|
||||
protected $files = [
|
||||
'/.dependencies',
|
||||
'/.htaccess',
|
||||
'/user/config/site.yaml',
|
||||
'/user/config/system.yaml',
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $mappings = array(
|
||||
protected $mappings = [
|
||||
'/.editorconfig' => '/.editorconfig',
|
||||
'/.gitignore' => '/.gitignore',
|
||||
'/CHANGELOG.md' => '/CHANGELOG.md',
|
||||
@@ -56,7 +56,7 @@ class SandboxCommand extends ConsoleCommand
|
||||
'/vendor' => '/vendor',
|
||||
'/webserver-configs' => '/webserver-configs',
|
||||
'/codeception.yml' => '/codeception.yml',
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@@ -200,7 +200,7 @@ class SandboxCommand extends ConsoleCommand
|
||||
*/
|
||||
private function initFiles()
|
||||
{
|
||||
$this->check($this->output);
|
||||
$this->check();
|
||||
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln('<comment>File Initializing</comment>');
|
||||
@@ -225,8 +225,6 @@ class SandboxCommand extends ConsoleCommand
|
||||
if (!$files_init) {
|
||||
$this->output->writeln(' <red>Files already exist</red>');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +237,7 @@ class SandboxCommand extends ConsoleCommand
|
||||
|
||||
// get pages files and initialize if no pages exist
|
||||
$pages_dir = $this->destination . '/user/pages';
|
||||
$pages_files = array_diff(scandir($pages_dir), array('..', '.'));
|
||||
$pages_files = array_diff(scandir($pages_dir), ['..', '.']);
|
||||
|
||||
if (count($pages_files) == 0) {
|
||||
$destination = $this->source . '/user/pages';
|
||||
@@ -269,7 +267,6 @@ class SandboxCommand extends ConsoleCommand
|
||||
$this->output->writeln("");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -295,6 +292,7 @@ class SandboxCommand extends ConsoleCommand
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln('<comment>install should be run with --symlink|--s to symlink first</comment>');
|
||||
|
||||
@@ -3,7 +3,6 @@ namespace Grav\Console;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,7 +83,7 @@ class InfoCommand extends ConsoleCommand
|
||||
$this->output->writeln("<green>" . str_pad("Author",
|
||||
12) . ":</green> " . $foundPackage->author['name'] . ' <' . $foundPackage->author['email'] . '> ' . $packageURL);
|
||||
|
||||
foreach (array(
|
||||
foreach ([
|
||||
'version',
|
||||
'keywords',
|
||||
'date',
|
||||
@@ -95,7 +95,7 @@ class InfoCommand extends ConsoleCommand
|
||||
'bugs',
|
||||
'zipball_url',
|
||||
'license'
|
||||
) as $info) {
|
||||
] as $info) {
|
||||
if (isset($foundPackage->$info)) {
|
||||
$name = ucfirst($info);
|
||||
$data = $foundPackage->$info;
|
||||
|
||||
@@ -5,12 +5,12 @@ use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\GPM\GPM;
|
||||
use Grav\Common\GPM\Installer;
|
||||
use Grav\Common\GPM\Response;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
define('GIT_REGEX', '/http[s]?:\/\/(?:.*@)?(github|bitbucket)(?:.org|.com)\/.*\/(.*)/');
|
||||
@@ -21,29 +21,29 @@ define('GIT_REGEX', '/http[s]?:\/\/(?:.*@)?(github|bitbucket)(?:.org|.com)\/.*\/
|
||||
*/
|
||||
class InstallCommand extends ConsoleCommand
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
/** @var */
|
||||
protected $data;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
|
||||
/** @var GPM */
|
||||
protected $gpm;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
|
||||
/** @var */
|
||||
protected $destination;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
|
||||
/** @var */
|
||||
protected $file;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
|
||||
/** @var */
|
||||
protected $tmp;
|
||||
|
||||
/** @var */
|
||||
protected $local_config;
|
||||
|
||||
/** @var bool */
|
||||
protected $use_symlinks;
|
||||
|
||||
/** @var array */
|
||||
protected $demo_processing = [];
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -81,7 +81,17 @@ class InstallCommand extends ConsoleCommand
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null|void
|
||||
* Allows to set the GPM object, used for testing the class
|
||||
*
|
||||
* @param $gpm
|
||||
*/
|
||||
public function setGpm($gpm)
|
||||
{
|
||||
$this->gpm = $gpm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null|void|bool
|
||||
*/
|
||||
protected function serve()
|
||||
{
|
||||
@@ -91,7 +101,7 @@ class InstallCommand extends ConsoleCommand
|
||||
$packages = array_map('strtolower', $this->input->getArgument('package'));
|
||||
$this->data = $this->gpm->findPackages($packages);
|
||||
|
||||
if (false === $this->isWindows() && @is_file(getenv("HOME").'/.grav/config')) {
|
||||
if (false === $this->isWindows() && @is_file(getenv("HOME") . '/.grav/config')) {
|
||||
$local_config_file = exec('eval echo ~/.grav/config');
|
||||
if (file_exists($local_config_file)) {
|
||||
$this->local_config = Yaml::parse($local_config_file);
|
||||
@@ -122,36 +132,344 @@ class InstallCommand extends ConsoleCommand
|
||||
unset($this->data['not_found']);
|
||||
unset($this->data['total']);
|
||||
|
||||
foreach ($this->data as $data) {
|
||||
foreach ($data as $package) {
|
||||
//Check for dependencies
|
||||
if (isset($package->dependencies)) {
|
||||
$this->output->writeln("Package <cyan>" . $package->name . "</cyan> has ". count($package->dependencies) . " required dependencies that must be installed first...");
|
||||
$this->output->writeln('');
|
||||
if (isset($this->local_config)) {
|
||||
// Symlinks available, ask if Grav should use them
|
||||
|
||||
$dependency_data = $this->gpm->findPackages($package->dependencies);
|
||||
$this->use_symlinks = false;
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion('Should Grav use the symlinks if available? [y|N] ', false);
|
||||
|
||||
if (!$dependency_data['total']) {
|
||||
$this->output->writeln("No dependencies found...");
|
||||
$this->output->writeln('');
|
||||
} else {
|
||||
unset($dependency_data['total']);
|
||||
if ($helper->ask($this->input, $this->output, $question)) {
|
||||
$this->use_symlinks = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($dependency_data as $type => $dep_data) {
|
||||
foreach($dep_data as $name => $dep_package) {
|
||||
$this->output->writeln('');
|
||||
|
||||
$this->processPackage($dep_package);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
$dependencies = $this->processDependencies($packages);
|
||||
} catch (\Exception $e) {
|
||||
//Error out if there are incompatible packages requirements and tell which ones, and what to do
|
||||
//Error out if there is any error in parsing the dependencies and their versions, and tell which one is broken
|
||||
$this->output->writeln("<red>" . $e->getMessage() . "</red>");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($dependencies) {
|
||||
//First, check for Grav dependency. If a dependency requires Grav > the current version, abort and tell.
|
||||
if (isset($dependencies['grav'])) {
|
||||
if (version_compare($this->calculateVersionNumberFromDependencyVersion($dependencies['grav']), GRAV_VERSION) === 1) {
|
||||
//Needs a Grav update first
|
||||
$this->output->writeln("<red>One of the package dependencies requires Grav " . $dependencies['grav'] . ". Please update Grav first with `bin/gpm selfupgrade`</red>");
|
||||
return false;
|
||||
}
|
||||
unset($dependencies['grav']);
|
||||
}
|
||||
|
||||
$this->processPackage($package);
|
||||
try {
|
||||
$this->installDependencies($dependencies, 'install', "The following dependencies need to be installed...");
|
||||
$this->installDependencies($dependencies, 'update', "The following dependencies need to be updated...");
|
||||
$this->installDependencies($dependencies, 'ignore', "The following dependencies can be updated as there is a newer version, but it's not mandatory...");
|
||||
} catch (\Exception $e) {
|
||||
$this->output->writeln("<red>Installation aborted</red>");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//We're done installing dependencies. Install the actual packages
|
||||
foreach ($this->data as $data) {
|
||||
foreach ($data as $packageName => $package) {
|
||||
if (in_array($packageName, array_keys($dependencies))) {
|
||||
$this->output->writeln("<green>Package " . $packageName . " already installed as dependency</green>");
|
||||
} else {
|
||||
$this->processPackage($package);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($this->demo_processing) > 0) {
|
||||
foreach ($this->demo_processing as $package) {
|
||||
$this->installDemoContent($package);
|
||||
}
|
||||
}
|
||||
|
||||
// clear cache after successful upgrade
|
||||
$this->clearCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a $dependencies list, filters their type according to $type and
|
||||
* shows $message prior to listing them to the user. Then asks the user a confirmation prior
|
||||
* to installing them.
|
||||
*
|
||||
* @param array $dependencies The dependencies array
|
||||
* @param string $type The type of dependency to show: install, update, ignore
|
||||
* @param string $message A message to be shown prior to listing the dependencies
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function installDependencies($dependencies, $type, $message) {
|
||||
$packages = array_filter($dependencies, function ($action) use ($type) { return $action === $type; });
|
||||
if (count($packages) > 0) {
|
||||
$this->output->writeln($message);
|
||||
|
||||
foreach ($packages as $dependencyName => $dependencyVersion) {
|
||||
$this->output->writeln(" |- Package <cyan>" . $dependencyName . "</cyan> requires a newer version");
|
||||
}
|
||||
|
||||
$this->output->writeln("");
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion('Update these packages? [y|N] ', false);
|
||||
|
||||
if ($helper->ask($this->input, $this->output, $question)) {
|
||||
foreach ($packages as $dependencyName => $dependencyVersion) {
|
||||
$this->processPackage($dependencyName);
|
||||
}
|
||||
$this->output->writeln('');
|
||||
} else {
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the dependencies, check the installed packages and return an array with
|
||||
* the list of packages with associated an information on what to do: install, update or ignore.
|
||||
*
|
||||
* `ignore` means the package is already installed and can be safely left as-is.
|
||||
* `install` means the package is not installed and must be installed.
|
||||
* `update` means the package is already installed and must be updated as a dependency needs a higher version.
|
||||
*
|
||||
* @param array $packages
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function processDependencies($packages) {
|
||||
$dependencies = $this->calculateMergedDependenciesOfPackages($packages);
|
||||
|
||||
foreach ($dependencies as $dependencySlug => $dependencyVersion) {
|
||||
if ($this->gpm->isPluginInstalled($dependencySlug)) {
|
||||
$dependencyVersion = $this->calculateVersionNumberFromDependencyVersion($dependencyVersion);
|
||||
|
||||
// check the version, if an update is not strictly required mark as 'ignore'
|
||||
$locator = Grav::instance()['locator'];
|
||||
$blueprints_path = $locator->findResource('plugins://' . $dependencySlug . DS . 'blueprints.yaml');
|
||||
$package_yaml = Yaml::parse(file_get_contents($blueprints_path));
|
||||
$currentlyInstalledVersion = $package_yaml['version'];
|
||||
|
||||
//if I already have the latest release, remove the dependency
|
||||
$latestRelease = $this->gpm->getLatestVersionOfPackage($dependencySlug);
|
||||
|
||||
if (version_compare($latestRelease, $dependencyVersion) == -1) {
|
||||
//throw an exception if a required version cannot be found in the GPM yet
|
||||
throw new \Exception('Dependency ' . $package_yaml['name'] . ' is required in a version higher than the latest release. Try running `bin/gpm -f index` to force a refresh of the GPM cache', 1);
|
||||
}
|
||||
|
||||
if (version_compare($currentlyInstalledVersion, $dependencyVersion) == -1) {
|
||||
$dependencies[$dependencySlug] = 'update';
|
||||
} else {
|
||||
if ($currentlyInstalledVersion == $latestRelease) {
|
||||
unset($dependencies[$dependencySlug]);
|
||||
} else {
|
||||
$dependencies[$dependencySlug] = 'ignore';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dependencies[$dependencySlug] = 'install';
|
||||
}
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and merges the dependencies of a package
|
||||
*
|
||||
* @param string $packageName The package information
|
||||
*
|
||||
* @param array $dependencies The dependencies array
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function calculateMergedDependenciesOfPackage($packageName, $dependencies)
|
||||
{
|
||||
$packageData = $this->gpm->findPackage($packageName);
|
||||
|
||||
//Check for dependencies
|
||||
if (isset($packageData->dependencies)) {
|
||||
foreach ($packageData->dependencies as $dependency) {
|
||||
$current_package_name = $dependency['name'];
|
||||
if (isset($dependency['version'])) {
|
||||
$current_package_version_information = $dependency['version'];
|
||||
}
|
||||
|
||||
if (!isset($dependencies[$current_package_name])) {
|
||||
// Dependency added for the first time
|
||||
|
||||
if (!isset($current_package_version_information)) {
|
||||
$dependencies[$current_package_name] = '*';
|
||||
} else {
|
||||
$dependencies[$current_package_name] = $current_package_version_information;
|
||||
}
|
||||
|
||||
//Factor in the package dependencies too
|
||||
$dependencies = $this->calculateMergedDependenciesOfPackage($current_package_name, $dependencies);
|
||||
}
|
||||
else {
|
||||
// Dependency already added by another package
|
||||
//if this package requires a version higher than the currently stored one, store this requirement instead
|
||||
if (isset($current_package_version_information) && $current_package_version_information !== '*') {
|
||||
|
||||
$currently_stored_version_information = $dependencies[$current_package_name];
|
||||
$currently_stored_version_number = $this->calculateVersionNumberFromDependencyVersion($currently_stored_version_information);
|
||||
|
||||
$currently_stored_version_is_in_next_significant_release_format = false;
|
||||
if ($this->versionFormatIsNextSignificantRelease($currently_stored_version_information)) {
|
||||
$currently_stored_version_is_in_next_significant_release_format = true;
|
||||
}
|
||||
|
||||
if (!$currently_stored_version_number) {
|
||||
$currently_stored_version_number = '*';
|
||||
}
|
||||
|
||||
$current_package_version_number = $this->calculateVersionNumberFromDependencyVersion($current_package_version_information);
|
||||
if (!$current_package_version_number) {
|
||||
throw new \Exception('Bad format for version of dependency ' . $current_package_name . ' for package ' . $packageName, 1);
|
||||
}
|
||||
|
||||
$current_package_version_is_in_next_significant_release_format = false;
|
||||
if ($this->versionFormatIsNextSignificantRelease($current_package_version_information)) {
|
||||
$current_package_version_is_in_next_significant_release_format = true;
|
||||
}
|
||||
|
||||
//If I had stored '*', change right away with the more specific version required
|
||||
if ($currently_stored_version_number === '*') {
|
||||
$dependencies[$current_package_name] = $current_package_version_information;
|
||||
} else {
|
||||
if (!$currently_stored_version_is_in_next_significant_release_format && !$current_package_version_is_in_next_significant_release_format) {
|
||||
//Comparing versions equals or higher, a simple version_compare is enough
|
||||
if (version_compare($currently_stored_version_number, $current_package_version_number) == -1) { //Current package version is higher
|
||||
$dependencies[$current_package_name] = $current_package_version_information;
|
||||
}
|
||||
} else {
|
||||
$compatible = $this->checkNextSignificantReleasesAreCompatible($currently_stored_version_number, $current_package_version_number);
|
||||
if (!$compatible) {
|
||||
throw new \Exception('Dependency ' . $current_package_name . ' is required in two incompatible versions', 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and merges the dependencies of the passed packages
|
||||
*
|
||||
* @param array $packages
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function calculateMergedDependenciesOfPackages($packages)
|
||||
{
|
||||
$dependencies = [];
|
||||
|
||||
foreach ($packages as $package) {
|
||||
$dependencies = $this->calculateMergedDependenciesOfPackage($package, $dependencies);
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual version from a dependency version string.
|
||||
* Examples:
|
||||
* $versionInformation == '~2.0' => returns '2.0'
|
||||
* $versionInformation == '>=2.0.2' => returns '2.0.2'
|
||||
* $versionInformation == '*' => returns null
|
||||
* $versionInformation == '' => returns null
|
||||
*
|
||||
* @param $versionInformation
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function calculateVersionNumberFromDependencyVersion($versionInformation)
|
||||
{
|
||||
if ($this->versionFormatIsNextSignificantRelease($versionInformation)) {
|
||||
return substr($versionInformation, 1);
|
||||
} elseif ($this->versionFormatIsEqualOrHigher($versionInformation)) {
|
||||
return substr($versionInformation, 2);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed version information contains next significant release (tilde) operator
|
||||
*
|
||||
* Example: returns true for $version: '~2.0'
|
||||
*
|
||||
* @param $version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function versionFormatIsNextSignificantRelease($version) {
|
||||
return substr($version, 0, 1) == '~';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed version information contains equal or higher operator
|
||||
*
|
||||
* Example: returns true for $version: '>=2.0'
|
||||
*
|
||||
* @param $version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function versionFormatIsEqualOrHigher($version) {
|
||||
return substr($version, 0, 2) == '>=';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two releases are compatible by next significant release
|
||||
*
|
||||
* ~1.2 is equivalent to >=1.2 <2.0.0
|
||||
* ~1.2.3 is equivalent to >=1.2.3 <1.3.0
|
||||
*
|
||||
* In short, allows the last digit specified to go up
|
||||
*
|
||||
* @param string $version1 the version string (e.g. '2.0.0' or '1.0')
|
||||
* @param string $version2 the version string (e.g. '2.0.0' or '1.0')
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkNextSignificantReleasesAreCompatible($version1, $version2)
|
||||
{
|
||||
$version1array = explode('.', $version1);
|
||||
$version2array = explode('.', $version2);
|
||||
|
||||
if (count($version1array) > count($version2array)) {
|
||||
list($version1array, $version2array) = [$version2array, $version1array];
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
while ($i < count($version1array) - 1) {
|
||||
if ($version1array[$i] != $version2array[$i]) {
|
||||
return false;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,78 +477,65 @@ class InstallCommand extends ConsoleCommand
|
||||
*/
|
||||
private function processPackage($package)
|
||||
{
|
||||
$install_options = ['GPM'];
|
||||
|
||||
// if no name, not found in GPM
|
||||
if (!isset($package->version)) {
|
||||
unset($install_options[0]);
|
||||
}
|
||||
// if local config found symlink is a valid option
|
||||
if (isset($this->local_config) && $this->getSymlinkSource($package)) {
|
||||
$install_options[] = 'Symlink';
|
||||
}
|
||||
// if override set, can install via git
|
||||
if (isset($package->override_repository)) {
|
||||
$install_options[] = 'Git';
|
||||
$symlink = false;
|
||||
if ($this->use_symlinks) {
|
||||
if ($this->getSymlinkSource($package) || !isset($package->version)) {
|
||||
$symlink = true;
|
||||
}
|
||||
}
|
||||
|
||||
// reindex list
|
||||
$install_options = array_values($install_options);
|
||||
$symlink ? $this->processSymlink($package) : $this->processGpm($package);
|
||||
|
||||
if (count($install_options) == 0) {
|
||||
// no valid install options - error and return
|
||||
$this->output->writeln("<red>not valid installation methods found!</red>");
|
||||
return;
|
||||
} elseif (count($install_options) == 1) {
|
||||
// only one option, use it...
|
||||
$method = $install_options[0];
|
||||
} else {
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ChoiceQuestion(
|
||||
'Please select installation method for <cyan>' . $package->name . '</cyan> (<magenta>'.$install_options[0].' is default</magenta>)', array_values($install_options), 0
|
||||
);
|
||||
$question->setErrorMessage('Method %s is invalid');
|
||||
$method = $helper->ask($this->input, $this->output, $question);
|
||||
}
|
||||
|
||||
$this->output->writeln('');
|
||||
|
||||
$method_name = 'process'.$method;
|
||||
$this->$method_name($package);
|
||||
|
||||
$this->installDemoContent($package);
|
||||
$this->processDemo($package);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add package to the queue to process the demo content, if demo content exists
|
||||
*
|
||||
* @param $package
|
||||
*/
|
||||
private function processDemo($package)
|
||||
{
|
||||
$demo_dir = $this->destination . DS . $package->install_path . DS . '_demo';
|
||||
if (file_exists($demo_dir)) {
|
||||
$this->demo_processing[] = $package;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt to install the demo content of a package
|
||||
*
|
||||
* @param $package
|
||||
*/
|
||||
private function installDemoContent($package)
|
||||
{
|
||||
$demo_dir = $this->destination . DS . $package->install_path . DS . '_demo';
|
||||
$dest_dir = $this->destination . DS . 'user';
|
||||
$pages_dir = $dest_dir . DS . 'pages';
|
||||
|
||||
if (file_exists($demo_dir)) {
|
||||
$dest_dir = $this->destination . DS . 'user';
|
||||
$pages_dir = $dest_dir . DS . 'pages';
|
||||
|
||||
// Demo content exists, prompt to install it.
|
||||
$this->output->writeln("<white>Attention: </white><cyan>".$package->name . "</cyan> contains demo content");
|
||||
$this->output->writeln("<white>Attention: </white><cyan>" . $package->name . "</cyan> contains demo content");
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion('Do you wish to install this demo content? [y|N] ', false);
|
||||
|
||||
if (!$helper->ask($this->input, $this->output, $question)) {
|
||||
$this->output->writeln(" '- <red>Skipped!</red> ");
|
||||
$this->output->writeln('');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if pages folder exists in demo
|
||||
if (file_exists($demo_dir . DS . 'pages')) {
|
||||
$pages_backup = 'pages.' . date('m-d-Y-H-i-s');
|
||||
$question = new ConfirmationQuestion('This will backup your current `user/pages` folder to `user/'. $pages_backup. '`, continue? [y|N]', false);
|
||||
$question = new ConfirmationQuestion('This will backup your current `user/pages` folder to `user/' . $pages_backup . '`, continue? [y|N]', false);
|
||||
|
||||
if (!$helper->ask($this->input, $this->output, $question)) {
|
||||
$this->output->writeln(" '- <red>Skipped!</red> ");
|
||||
$this->output->writeln('');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -259,9 +564,7 @@ class InstallCommand extends ConsoleCommand
|
||||
*/
|
||||
private function getGitRegexMatches($package)
|
||||
{
|
||||
if (isset($package->override_repository)) {
|
||||
$repository = $package->override_repository;
|
||||
} elseif (isset($package->repository)) {
|
||||
if (isset($package->repository)) {
|
||||
$repository = $package->repository;
|
||||
} else {
|
||||
return false;
|
||||
@@ -294,6 +597,7 @@ class InstallCommand extends ConsoleCommand
|
||||
return $from;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -336,6 +640,7 @@ class InstallCommand extends ConsoleCommand
|
||||
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -346,34 +651,7 @@ class InstallCommand extends ConsoleCommand
|
||||
/**
|
||||
* @param $package
|
||||
*/
|
||||
private function processGit($package)
|
||||
{
|
||||
$matches = $this->getGitRegexMatches($package);
|
||||
|
||||
$this->output->writeln("Preparing to Git clone <cyan>" . $package->name . "</cyan> from " . $matches[0]);
|
||||
|
||||
$this->output->write(" |- Checking destination... ");
|
||||
$checks = $this->checkDestination($package);
|
||||
|
||||
if (!$checks) {
|
||||
$this->output->writeln(" '- <red>Installation failed or aborted.</red>");
|
||||
$this->output->writeln('');
|
||||
} else {
|
||||
$cmd = 'cd ' . $this->destination . ' && git clone ' . $matches[0] . ' ' . $package->install_path;
|
||||
exec($cmd);
|
||||
|
||||
// extra white spaces to clear out the buffer properly
|
||||
$this->output->writeln(" |- Cloning package... <green>ok</green> ");
|
||||
|
||||
$this->output->writeln(" '- <green>Success!</green> ");
|
||||
$this->output->writeln('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $package
|
||||
*/
|
||||
private function processGPM($package)
|
||||
private function processGpm($package)
|
||||
{
|
||||
$version = isset($package->available) ? $package->available : $package->version;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class SelfupgradeCommand extends ConsoleCommand
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $types = array('plugins', 'themes');
|
||||
protected $types = ['plugins', 'themes'];
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,38 @@ class UninstallCommand extends ConsoleCommand
|
||||
->setHelp('The <info>uninstall</info> command allows to uninstall plugins and themes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of packages that have the passed one as dependency
|
||||
*
|
||||
* @param $package_slug The slug name of the package
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function getPackagesThatDependOnPackage($package_slug)
|
||||
{
|
||||
$plugins = $this->gpm->getInstalledPlugins();
|
||||
$themes = $this->gpm->getInstalledThemes();
|
||||
$packages = array_merge($plugins->toArray(), $themes->toArray());
|
||||
|
||||
$dependent_packages = [];
|
||||
|
||||
foreach($packages as $package_name => $package) {
|
||||
if (isset($package['dependencies'])) {
|
||||
foreach($package['dependencies'] as $dependency) {
|
||||
if (is_array($dependency)) {
|
||||
$dependency = array_keys($dependency)[0];
|
||||
}
|
||||
|
||||
if ($dependency == $package_slug) {
|
||||
$dependent_packages[] = $package_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dependent_packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null|void
|
||||
*/
|
||||
@@ -98,7 +130,6 @@ class UninstallCommand extends ConsoleCommand
|
||||
foreach ($this->data as $slug => $package) {
|
||||
$this->output->writeln("Preparing to uninstall <cyan>" . $package->name . "</cyan> [v" . $package->version . "]");
|
||||
|
||||
|
||||
$this->output->write(" |- Checking destination... ");
|
||||
$checks = $this->checkDestination($slug, $package);
|
||||
|
||||
@@ -117,6 +148,7 @@ class UninstallCommand extends ConsoleCommand
|
||||
$this->output->writeln('');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// clear cache after successful upgrade
|
||||
@@ -132,6 +164,23 @@ class UninstallCommand extends ConsoleCommand
|
||||
*/
|
||||
private function uninstallPackage($slug, $package)
|
||||
{
|
||||
//check if there are packages that have this as a dependency. Abort and show list
|
||||
$dependency_packages = $this->getPackagesThatDependOnPackage($slug);
|
||||
if ($dependency_packages) {
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln("<red>Uninstallation failed.</red>");
|
||||
$this->output->writeln('');
|
||||
if (count($dependency_packages) > 1) {
|
||||
$this->output->writeln("The installed packages <cyan>" . implode('</cyan>, <cyan>', $dependency_packages) . "</cyan> depend on this package. Please remove those first.");
|
||||
} else {
|
||||
$this->output->writeln("The installed package <cyan>" . implode('</cyan>, <cyan>', $dependency_packages) . "</cyan> depend on this package. Please remove it first.");
|
||||
}
|
||||
|
||||
$this->output->writeln('');
|
||||
exit;
|
||||
}
|
||||
|
||||
$path = Grav::instance()['locator']->findResource($package->package_type . '://' .$slug);
|
||||
Installer::uninstall($path);
|
||||
$errorCode = Installer::lastErrorCode();
|
||||
@@ -149,6 +198,35 @@ class UninstallCommand extends ConsoleCommand
|
||||
// extra white spaces to clear out the buffer properly
|
||||
$this->output->writeln(" |- Uninstalling package... <green>ok</green> ");
|
||||
|
||||
|
||||
if (isset($package->dependencies)) {
|
||||
$questionHelper = $this->getHelper('question');
|
||||
|
||||
foreach($package->dependencies as $dependency) {
|
||||
if (is_array($dependency)) {
|
||||
$dependency = array_keys($dependency)[0];
|
||||
}
|
||||
|
||||
$dependencyPackage = $this->gpm->findPackage($dependency);
|
||||
$question = new ConfirmationQuestion(" | '- Delete dependency <cyan>" . $dependency . "</cyan> too? [y|N] ", false);
|
||||
$answer = $questionHelper->ask($this->input, $this->output, $question);
|
||||
|
||||
if ($answer) {
|
||||
$this->output->writeln(" | '- <red>You decided to delete " . $dependency . ".</red>");
|
||||
|
||||
$uninstall = $this->uninstallPackage($dependency, $dependencyPackage);
|
||||
|
||||
if (!$uninstall) {
|
||||
$this->output->writeln(" '- <red>Uninstallation failed or aborted.</red>");
|
||||
$this->output->writeln('');
|
||||
} else {
|
||||
$this->output->writeln(" '- <green>Success!</green> ");
|
||||
$this->output->writeln('');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class UpdateCommand extends ConsoleCommand
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $types = array('plugins', 'themes');
|
||||
protected $types = ['plugins', 'themes'];
|
||||
/**
|
||||
* @var GPM $gpm
|
||||
*/
|
||||
@@ -149,13 +149,13 @@ class UpdateCommand extends ConsoleCommand
|
||||
// finally update
|
||||
$install_command = $this->getApplication()->find('install');
|
||||
|
||||
$args = new ArrayInput(array(
|
||||
$args = new ArrayInput([
|
||||
'command' => 'install',
|
||||
'package' => $slugs,
|
||||
'-f' => $this->input->getOption('force'),
|
||||
'-d' => $this->destination,
|
||||
'-y' => true
|
||||
));
|
||||
]);
|
||||
$command_exec = $install_command->run($args, $this->output);
|
||||
|
||||
if ($command_exec != 0) {
|
||||
|
||||
@@ -70,7 +70,8 @@ class VersionCommand extends ConsoleCommand
|
||||
}
|
||||
|
||||
} else {
|
||||
if ($installed = $this->gpm->findPackage($package)) {
|
||||
$installed = $this->gpm->findPackage($package);
|
||||
if ($installed) {
|
||||
$name = $installed->name;
|
||||
$version = $installed->version;
|
||||
|
||||
|
||||
@@ -138,9 +138,9 @@ class InflectorTest extends \Codeception\TestCase\Test
|
||||
public function testMonthize()
|
||||
{
|
||||
$this->assertSame(0, $this->inflector->monthize(10));
|
||||
$this->assertSame(1, $this->inflector->monthize(30));
|
||||
$this->assertSame(1, $this->inflector->monthize(33));
|
||||
$this->assertSame(1, $this->inflector->monthize(41));
|
||||
$this->assertSame(11, $this->inflector->monthize(365));
|
||||
$this->assertSame(11, $this->inflector->monthize(364));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
326
tests/unit/Grav/Console/Gpm/InstallCommandTest.php
Normal file
326
tests/unit/Grav/Console/Gpm/InstallCommandTest.php
Normal file
@@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
use Codeception\Util\Fixtures;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Console\Gpm\InstallCommand;
|
||||
|
||||
define('EXCEPTION_BAD_FORMAT', 1);
|
||||
define('EXCEPTION_INCOMPATIBLE_VERSIONS', 2);
|
||||
|
||||
class GpmStub extends stdClass
|
||||
{
|
||||
public function findPackage($packageName)
|
||||
{
|
||||
if (isset($this->data[$packageName])) {
|
||||
return $this->data[$packageName];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function findPackages()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class InstallCommandTest
|
||||
*/
|
||||
class InstallCommandTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
/** @var Grav $grav */
|
||||
protected $grav;
|
||||
|
||||
/** @var InstallCommand */
|
||||
protected $installCommand;
|
||||
|
||||
/** @var GpmStub */
|
||||
protected $gpm;
|
||||
|
||||
protected function _before()
|
||||
{
|
||||
$this->grav = Fixtures::get('grav');
|
||||
$this->installCommand = new InstallCommand();
|
||||
|
||||
$this->gpm = new GpmStub();
|
||||
}
|
||||
|
||||
protected function _after()
|
||||
{
|
||||
}
|
||||
|
||||
public function testCalculateMergedDependenciesOfPackages()
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// First working example
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$this->gpm->data = [
|
||||
'admin' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "grav", "version" => ">=1.0.10"],
|
||||
["name" => "form", "version" => "~2.0"],
|
||||
["name" => "login", "version" => ">=2.0"],
|
||||
["name" => "errors", "version" => "*"],
|
||||
["name" => "problems"],
|
||||
]
|
||||
],
|
||||
'test' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">=1.0"]
|
||||
]
|
||||
],
|
||||
'grav',
|
||||
'form' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">=3.2"]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
];
|
||||
$this->installCommand->setGpm($this->gpm);
|
||||
|
||||
$packages = ['admin', 'test'];
|
||||
|
||||
$dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
|
||||
$this->assertTrue(is_array($dependencies));
|
||||
$this->assertSame(5, count($dependencies));
|
||||
|
||||
$this->assertTrue($dependencies['grav'] == '>=1.0.10');
|
||||
$this->assertTrue(isset($dependencies['errors']));
|
||||
$this->assertTrue(isset($dependencies['problems']));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Second working example
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$packages = ['admin', 'form'];
|
||||
|
||||
$dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
$this->assertTrue(is_array($dependencies));
|
||||
$this->assertSame(5, count($dependencies));
|
||||
$this->assertTrue($dependencies['errors'] == '>=3.2');
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Third working example
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$this->gpm->data = [
|
||||
|
||||
'admin' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">=4.0"],
|
||||
]
|
||||
],
|
||||
'test' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">=1.0"]
|
||||
]
|
||||
],
|
||||
'another' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">=3.2"]
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
$this->installCommand->setGpm($this->gpm);
|
||||
|
||||
$packages = ['admin', 'test', 'another'];
|
||||
|
||||
|
||||
$dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
$this->assertTrue(is_array($dependencies));
|
||||
$this->assertSame(1, count($dependencies));
|
||||
$this->assertTrue($dependencies['errors'] == '>=4.0');
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Test alpha / beta / rc
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$this->gpm->data = [
|
||||
'admin' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "package1", "version" => ">=4.0.0-rc1"],
|
||||
["name" => "package4", "version" => ">=3.2.0"],
|
||||
]
|
||||
],
|
||||
'test' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "package1", "version" => ">=4.0.0-rc2"],
|
||||
["name" => "package2", "version" => ">=3.2.0-alpha"],
|
||||
["name" => "package3", "version" => ">=3.2.0-alpha.2"],
|
||||
["name" => "package4", "version" => ">=3.2.0-alpha"],
|
||||
]
|
||||
],
|
||||
'another' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "package2", "version" => ">=3.2.0-beta.11"],
|
||||
["name" => "package3", "version" => ">=3.2.0-alpha.1"],
|
||||
["name" => "package4", "version" => ">=3.2.0-beta"],
|
||||
]
|
||||
]
|
||||
];
|
||||
$this->installCommand->setGpm($this->gpm);
|
||||
|
||||
$packages = ['admin', 'test', 'another'];
|
||||
|
||||
|
||||
$dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
$this->assertTrue($dependencies['package1'] == '>=4.0.0-rc2');
|
||||
$this->assertTrue($dependencies['package2'] == '>=3.2.0-beta.11');
|
||||
$this->assertTrue($dependencies['package3'] == '>=3.2.0-alpha.2');
|
||||
$this->assertTrue($dependencies['package4'] == '>=3.2.0');
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Raise exception if no version is specified
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$this->gpm->data = [
|
||||
|
||||
'admin' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">=4.0"],
|
||||
]
|
||||
],
|
||||
'test' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => ">="]
|
||||
]
|
||||
],
|
||||
|
||||
];
|
||||
$this->installCommand->setGpm($this->gpm);
|
||||
$packages = ['admin', 'test'];
|
||||
|
||||
try {
|
||||
$this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
$this->fail("Expected Exception not thrown");
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals(EXCEPTION_BAD_FORMAT, $e->getCode());
|
||||
$this->assertStringStartsWith("Bad format for version of dependency", $e->getMessage());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Raise exception if incompatible versions are specified
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$this->gpm->data = [
|
||||
'admin' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => "~4.0"],
|
||||
]
|
||||
],
|
||||
'test' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "errors", "version" => "~3.0"]
|
||||
]
|
||||
],
|
||||
];
|
||||
$this->installCommand->setGpm($this->gpm);
|
||||
$packages = ['admin', 'test'];
|
||||
|
||||
try {
|
||||
$this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
$this->fail("Expected Exception not thrown");
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals(EXCEPTION_INCOMPATIBLE_VERSIONS, $e->getCode());
|
||||
$this->assertStringEndsWith("required in two incompatible versions", $e->getMessage());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Test dependencies of dependencies
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
$this->gpm->data = [
|
||||
'admin' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "grav", "version" => ">=1.0.10"],
|
||||
["name" => "form", "version" => "~2.0"],
|
||||
["name" => "login", "version" => ">=2.0"],
|
||||
["name" => "errors", "version" => "*"],
|
||||
["name" => "problems"],
|
||||
]
|
||||
],
|
||||
'login' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "antimatter", "version" => ">=1.0"]
|
||||
]
|
||||
],
|
||||
'grav',
|
||||
'antimatter' => (object)[
|
||||
'dependencies' => [
|
||||
["name" => "something", "version" => ">=3.2"]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
];
|
||||
$this->installCommand->setGpm($this->gpm);
|
||||
|
||||
$packages = ['admin'];
|
||||
|
||||
$dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($packages);
|
||||
|
||||
$this->assertTrue(is_array($dependencies));
|
||||
$this->assertSame(7, count($dependencies));
|
||||
|
||||
$this->assertSame('>=1.0.10', $dependencies['grav']);
|
||||
$this->assertTrue(isset($dependencies['errors']));
|
||||
$this->assertTrue(isset($dependencies['problems']));
|
||||
$this->assertTrue(isset($dependencies['antimatter']));
|
||||
$this->assertTrue(isset($dependencies['something']));
|
||||
$this->assertSame('>=3.2', $dependencies['something']);
|
||||
}
|
||||
|
||||
public function testVersionFormatIsNextSignificantRelease()
|
||||
{
|
||||
$this->assertFalse($this->installCommand->versionFormatIsNextSignificantRelease('>=1.0'));
|
||||
$this->assertFalse($this->installCommand->versionFormatIsNextSignificantRelease('>=2.3.4'));
|
||||
$this->assertFalse($this->installCommand->versionFormatIsNextSignificantRelease('>=2.3.x'));
|
||||
$this->assertFalse($this->installCommand->versionFormatIsNextSignificantRelease('1.0'));
|
||||
$this->assertTrue($this->installCommand->versionFormatIsNextSignificantRelease('~2.3.x'));
|
||||
$this->assertTrue($this->installCommand->versionFormatIsNextSignificantRelease('~2.0'));
|
||||
}
|
||||
|
||||
public function testVersionFormatIsEqualOrHigher()
|
||||
{
|
||||
$this->assertTrue($this->installCommand->versionFormatIsEqualOrHigher('>=1.0'));
|
||||
$this->assertTrue($this->installCommand->versionFormatIsEqualOrHigher('>=2.3.4'));
|
||||
$this->assertTrue($this->installCommand->versionFormatIsEqualOrHigher('>=2.3.x'));
|
||||
$this->assertFalse($this->installCommand->versionFormatIsEqualOrHigher('~2.3.x'));
|
||||
$this->assertFalse($this->installCommand->versionFormatIsEqualOrHigher('1.0'));
|
||||
}
|
||||
|
||||
public function testCheckNextSignificantReleasesAreCompatible()
|
||||
{
|
||||
/*
|
||||
* ~1.0 is equivalent to >=1.0 < 2.0.0
|
||||
* ~1.2 is equivalent to >=1.2 <2.0.0
|
||||
* ~1.2.3 is equivalent to >=1.2.3 <1.3.0
|
||||
*/
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.0', '1.2'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.2', '1.0'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.0', '1.0.10'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.1', '1.1.10'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('30.0', '30.10'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.0', '1.1.10'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.0', '1.8'));
|
||||
$this->assertTrue($this->installCommand->checkNextSignificantReleasesAreCompatible('1.0.1', '1.1'));
|
||||
|
||||
$this->assertFalse($this->installCommand->checkNextSignificantReleasesAreCompatible('1.0', '2.2'));
|
||||
$this->assertFalse($this->installCommand->checkNextSignificantReleasesAreCompatible('0.9.99', '1.0.0'));
|
||||
$this->assertFalse($this->installCommand->checkNextSignificantReleasesAreCompatible('0.9.99', '1.0.10'));
|
||||
$this->assertFalse($this->installCommand->checkNextSignificantReleasesAreCompatible('0.9.99', '1.0.10.2'));
|
||||
}
|
||||
|
||||
|
||||
public function testCalculateVersionNumberFromDependencyVersion()
|
||||
{
|
||||
$this->assertSame('2.0', $this->installCommand->calculateVersionNumberFromDependencyVersion('>=2.0'));
|
||||
$this->assertSame('2.0.2', $this->installCommand->calculateVersionNumberFromDependencyVersion('>=2.0.2'));
|
||||
$this->assertSame('2.0.2', $this->installCommand->calculateVersionNumberFromDependencyVersion('~2.0.2'));
|
||||
$this->assertSame('1', $this->installCommand->calculateVersionNumberFromDependencyVersion('~1'));
|
||||
$this->assertSame(null, $this->installCommand->calculateVersionNumberFromDependencyVersion(''));
|
||||
$this->assertSame(null, $this->installCommand->calculateVersionNumberFromDependencyVersion('*'));
|
||||
$this->assertSame(null, $this->installCommand->calculateVersionNumberFromDependencyVersion('2.0.2'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user