Merge pull request #8736 from owncloud/appinfo-newrequirefields

App info new fields "requiremin" and "requiremax"
This commit is contained in:
Vincent Petry 2014-05-27 14:28:47 +02:00
commit a9661962fe
11 changed files with 284 additions and 103 deletions

View file

@ -4,8 +4,8 @@
<name>Files</name>
<description>File Management</description>
<licence>AGPL</licence>
<author>Robin Appelman</author>
<require>4.93</require>
<author>Robin Appelman, Vincent Petry</author>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<standalone/>
<default_enable/>

View file

@ -5,7 +5,7 @@
<description>The ownCloud files encryption system provides server side-encryption. After the app is enabled you need to re-login to initialize your encryption keys. Please note that server side encryption requires that the ownCloud server admin can be trusted. The main purpose of this app is the encryption of files that are stored on externally mounted storages.</description>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<require>4</require>
<requiremin>4</requiremin>
<shipped>true</shipped>
<documentation>
<user>http://doc.owncloud.org/server/6.0/user_manual/files/encryption.html</user>

View file

@ -4,8 +4,8 @@
<name>External storage support</name>
<description>Mount external storage sources</description>
<licence>AGPL</licence>
<author>Robin Appelman, Michael Gapczynski</author>
<require>4.93</require>
<author>Robin Appelman, Michael Gapczynski, Vincent Petry</author>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<types>
<filesystem/>

View file

@ -4,8 +4,8 @@
<name>Share Files</name>
<description>File sharing between users</description>
<licence>AGPL</licence>
<author>Michael Gapczynski</author>
<require>4.93</require>
<author>Michael Gapczynski, Bjoern Schiessle</author>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<default_enable/>
<types>

View file

@ -19,7 +19,7 @@
<licence>AGPL</licence>
<author>Bjoern Schiessle</author>
<shipped>true</shipped>
<require>4.9</require>
<requiremin>4.9</requiremin>
<default_enable/>
<types>
<filesystem/>

View file

@ -3,8 +3,8 @@
<id>files_versions</id>
<name>Versions</name>
<licence>AGPL</licence>
<author>Frank Karlitschek</author>
<require>4.93</require>
<author>Frank Karlitschek, Bjoern Schiessle</author>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<description>
ownCloud supports simple version control for files. The versioning app

View file

@ -9,7 +9,7 @@
</description>
<licence>AGPL</licence>
<author>Dominik Schmidt and Arthur Schiwon</author>
<require>4.93</require>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<types>
<authentication/>

View file

@ -7,7 +7,7 @@
This app is not compatible with the LDAP user and group backend.</description>
<licence>AGPL</licence>
<author>Frank Karlitschek</author>
<require>4.93</require>
<requiremin>4.93</requiremin>
<shipped>true</shipped>
<types>
<authentication/>

View file

@ -231,7 +231,7 @@ class OC_App{
// check if the app is compatible with this version of ownCloud
$info=OC_App::getAppInfo($app);
$version=OC_Util::getVersion();
if(!isset($info['require']) or !self::isAppVersionCompatible($version, $info['require'])) {
if(!self::isAppCompatible($version, $info)) {
throw new \Exception(
$l->t("App \"%s\" can't be installed because it is not compatible with this version of ownCloud.",
array($info['name'])
@ -898,7 +898,7 @@ class OC_App{
foreach($apps as $app) {
// check if the app is compatible with this version of ownCloud
$info = OC_App::getAppInfo($app);
if(!isset($info['require']) or !self::isAppVersionCompatible($version, $info['require'])) {
if(!self::isAppCompatible($version, $info)) {
OC_Log::write('core',
'App "'.$info['name'].'" ('.$app.') can\'t be used because it is'
.' not compatible with this version of ownCloud',
@ -909,38 +909,78 @@ class OC_App{
}
}
/**
* Ajust the number of version parts of $version1 to match
* the number of version parts of $version2.
*
* @param string $version1 version to adjust
* @param string $version2 version to take the number of parts from
* @return string shortened $version1
*/
private static function adjustVersionParts($version1, $version2) {
$version1 = explode('.', $version1);
$version2 = explode('.', $version2);
// reduce $version1 to match the number of parts in $version2
while (count($version1) > count($version2)) {
array_pop($version1);
}
// if $version1 does not have enough parts, add some
while (count($version1) < count($version2)) {
$version1[] = '0';
}
return implode('.', $version1);
}
/**
* Compares the app version with the owncloud version to see if the app
* requires a newer version than the currently active one
* @param array $owncloudVersions array with 3 entries: major minor bugfix
* @param string $appRequired the required version from the xml
* major.minor.bugfix
* Check whether the current ownCloud version matches the given
* application's version requirements.
*
* The comparison is made based on the number of parts that the
* app info version has. For example for ownCloud 6.0.3 if the
* app info version is expecting version 6.0, the comparison is
* made on the first two parts of the ownCloud version.
* This means that it's possible to specify "requiremin" => 6
* and "requiremax" => 6 and it will still match ownCloud 6.0.3.
*
* @param string $ocVersion ownCloud version to check against
* @param array $appInfo app info (from xml)
*
* @return boolean true if compatible, otherwise false
*/
public static function isAppVersionCompatible($owncloudVersions, $appRequired){
$appVersions = explode('.', $appRequired);
public static function isAppCompatible($ocVersion, $appInfo){
$requireMin = '';
$requireMax = '';
if (isset($appInfo['requiremin'])) {
$requireMin = $appInfo['requiremin'];
} else if (isset($appInfo['require'])) {
$requireMin = $appInfo['require'];
}
for($i=0; $i<count($appVersions); $i++){
$appVersion = (int) $appVersions[$i];
if (isset($appInfo['requiremax'])) {
$requireMax = $appInfo['requiremax'];
}
if(isset($owncloudVersions[$i])){
$owncloudVersion = $owncloudVersions[$i];
} else {
$owncloudVersion = 0;
}
if (is_array($ocVersion)) {
$ocVersion = implode('.', $ocVersion);
}
if($owncloudVersion < $appVersion){
return false;
} elseif ($owncloudVersion > $appVersion) {
return true;
}
if (!empty($requireMin)
&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
) {
return false;
}
if (!empty($requireMax)
&& version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
) {
return false;
}
return true;
}
/**
* get the installed version of all apps
*/

View file

@ -133,10 +133,7 @@ class OC_Installer{
}
// check if the app is compatible with this version of ownCloud
if(
!isset($info['require'])
or !OC_App::isAppVersionCompatible(OC_Util::getVersion(), $info['require'])
) {
if(!OC_App::isAppCompatible(OC_Util::getVersion(), $info)) {
OC_Helper::rmdirr($extractDir);
throw new \Exception($l->t("App can't be installed because it is not compatible with this version of ownCloud"));
}

View file

@ -1,6 +1,7 @@
<?php
/**
* Copyright (c) 2012 Bernhard Posselt <dev@bernhard-posselt.com>
* Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
@ -8,75 +9,218 @@
class Test_App extends PHPUnit_Framework_TestCase {
public function testIsAppVersionCompatibleSingleOCNumber(){
$oc = array(4);
$app = '4.0';
$this->assertTrue(OC_App::isAppVersionCompatible($oc, $app));
function appVersionsProvider() {
return array(
// exact match
array(
'6.0.0.0',
array(
'requiremin' => '6.0',
'requiremax' => '6.0',
),
true
),
// in-between match
array(
'6.0.0.0',
array(
'requiremin' => '5.0',
'requiremax' => '7.0',
),
true
),
// app too old
array(
'6.0.0.0',
array(
'requiremin' => '5.0',
'requiremax' => '5.0',
),
false
),
// app too new
array(
'5.0.0.0',
array(
'requiremin' => '6.0',
'requiremax' => '6.0',
),
false
),
// only min specified
array(
'6.0.0.0',
array(
'requiremin' => '6.0',
),
true
),
// only min specified fail
array(
'5.0.0.0',
array(
'requiremin' => '6.0',
),
false
),
// only min specified legacy
array(
'6.0.0.0',
array(
'require' => '6.0',
),
true
),
// only min specified legacy fail
array(
'4.0.0.0',
array(
'require' => '6.0',
),
false
),
// only max specified
array(
'5.0.0.0',
array(
'requiremax' => '6.0',
),
true
),
// only max specified fail
array(
'7.0.0.0',
array(
'requiremax' => '6.0',
),
false
),
// variations of versions
// single OC number
array(
'4',
array(
'require' => '4.0',
),
true
),
// multiple OC number
array(
'4.3.1',
array(
'require' => '4.3',
),
true
),
// single app number
array(
'4',
array(
'require' => '4',
),
true
),
// single app number fail
array(
'4.3',
array(
'require' => '5',
),
false
),
// complex
array(
'5.0.0',
array(
'require' => '4.5.1',
),
true
),
// complex fail
array(
'4.3.1',
array(
'require' => '4.3.2',
),
false
),
// two numbers
array(
'4.3.1',
array(
'require' => '4.4',
),
false
),
// one number fail
array(
'4.3.1',
array(
'require' => '5',
),
false
),
// pre-alpha app
array(
'5.0.3',
array(
'require' => '4.93',
),
true
),
// pre-alpha OC
array(
'6.90.0.2',
array(
'require' => '6.90',
),
true
),
// pre-alpha OC max
array(
'6.90.0.2',
array(
'requiremax' => '7',
),
true
),
// expect same major number match
array(
'5.0.3',
array(
'require' => '5',
),
true
),
// expect same major number match
array(
'5.0.3',
array(
'requiremax' => '5',
),
true
),
);
}
public function testIsAppVersionCompatibleMultipleOCNumber(){
$oc = array(4, 3, 1);
$app = '4.3';
$this->assertTrue(OC_App::isAppVersionCompatible($oc, $app));
/**
* @dataProvider appVersionsProvider
*/
public function testIsAppCompatible($ocVersion, $appInfo, $expectedResult) {
$this->assertEquals($expectedResult, OC_App::isAppCompatible($ocVersion, $appInfo));
}
public function testIsAppVersionCompatibleSingleNumber(){
$oc = array(4);
$app = '4';
$this->assertTrue(OC_App::isAppVersionCompatible($oc, $app));
}
public function testIsAppVersionCompatibleSingleAppNumber(){
$oc = array(4, 3);
$app = '4';
$this->assertTrue(OC_App::isAppVersionCompatible($oc, $app));
}
public function testIsAppVersionCompatibleComplex(){
$oc = array(5, 0, 0);
$app = '4.5.1';
$this->assertTrue(OC_App::isAppVersionCompatible($oc, $app));
}
public function testIsAppVersionCompatibleShouldFail(){
$oc = array(4, 3, 1);
$app = '4.3.2';
$this->assertFalse(OC_App::isAppVersionCompatible($oc, $app));
}
public function testIsAppVersionCompatibleShouldFailTwoVersionNumbers(){
$oc = array(4, 3, 1);
$app = '4.4';
$this->assertFalse(OC_App::isAppVersionCompatible($oc, $app));
}
public function testIsAppVersionCompatibleShouldWorkForPreAlpha(){
$oc = array(5, 0, 3);
$app = '4.93';
$this->assertTrue(OC_App::isAppVersionCompatible($oc, $app));
}
public function testIsAppVersionCompatibleShouldFailOneVersionNumbers(){
$oc = array(4, 3, 1);
$app = '5';
$this->assertFalse(OC_App::isAppVersionCompatible($oc, $app));
/**
* Test that the isAppCompatible method also supports passing an array
* as $ocVersion
*/
public function testIsAppCompatibleWithArray() {
$ocVersion = array(6);
$appInfo = array(
'requiremin' => '6',
'requiremax' => '6',
);
$this->assertTrue(OC_App::isAppCompatible($ocVersion, $appInfo));
}
/**