MDL-38493 Make mdeploy.php able to install new plugin

The patch implements the second mode of the mdeploy.php script. If
--install option is passed, the given package is downloaded, verified
and deployed to the requested location.
This commit is contained in:
David Mudrák 2013-03-14 20:44:35 +01:00
parent d8201d49d8
commit 203b432159
2 changed files with 90 additions and 6 deletions

View File

@ -775,7 +775,53 @@ class worker extends singleton_pattern {
$this->done(); $this->done();
} else if ($this->input->get_option('install')) { } else if ($this->input->get_option('install')) {
// Installing a new plugin not implemented yet. $this->log('Plugin installation requested');
$plugintyperoot = $this->input->get_option('typeroot');
$pluginname = $this->input->get_option('name');
$source = $this->input->get_option('package');
$md5remote = $this->input->get_option('md5');
// Check if the plugin location if available for us.
$pluginlocation = $plugintyperoot.'/'.$pluginname;
$this->log('New plugin code location: '.$pluginlocation);
if (file_exists($pluginlocation)) {
throw new filesystem_exception('Unable to prepare the plugin location (directory already exists)');
}
if (!$this->create_directory_precheck($pluginlocation)) {
throw new filesystem_exception('Unable to prepare the plugin location (cannot create new directory)');
}
// Fetch the ZIP file into a temporary location.
$target = $this->target_location($source);
$this->log('Downloading package '.$source);
if ($this->download_file($source, $target)) {
$this->log('Package downloaded into '.$target);
} else {
$this->log('cURL error ' . $this->curlerrno . ' ' . $this->curlerror);
$this->log('Unable to download the file');
throw new download_file_exception('Unable to download the package');
}
// Compare MD5 checksum of the ZIP file
$md5local = md5_file($target);
if ($md5local !== $md5remote) {
$this->log('MD5 checksum failed. Expected: '.$md5remote.' Got: '.$md5local);
throw new checksum_exception('MD5 checksum failed');
}
$this->log('MD5 checksum ok');
// Unzip the plugin package file into the plugin location.
$this->unzip_plugin($target, $plugintyperoot, $pluginlocation, false);
$this->log('Package successfully extracted');
// Redirect to the given URL (in HTTP) or exit (in CLI).
$this->done();
} }
// Print help in CLI by default. // Print help in CLI by default.
@ -1126,18 +1172,36 @@ class worker extends singleton_pattern {
} }
/** /**
* Checks to see if a source foldr could be safely moved into the given new location * Checks to see if a source folder could be safely moved into the given new location
* *
* @param string $destination full path to the new expected location of a folder * @param string $destination full path to the new expected location of a folder
* @return bool * @return bool
*/ */
protected function move_directory_target_precheck($target) { protected function move_directory_target_precheck($target) {
if (file_exists($target)) { // Check if the target folder does not exist yet, can be created
// and removed again.
$result = $this->create_directory_precheck($target);
// At the moment, it seems to be enough to check. We may want to add
// more steps in the future.
return $result;
}
/**
* Make sure the given directory can be created (and removed)
*
* @param string $path full path to the folder
* @return bool
*/
protected function create_directory_precheck($path) {
if (file_exists($path)) {
return false; return false;
} }
$result = mkdir($target, 02777) && rmdir($target); $result = mkdir($path, 02777) && rmdir($path);
return $result; return $result;
} }
@ -1273,7 +1337,9 @@ class worker extends singleton_pattern {
$result = $zip->open($ziplocation); $result = $zip->open($ziplocation);
if ($result !== true) { if ($result !== true) {
$this->move_directory($backuplocation, $expectedlocation); if ($backuplocation !== false) {
$this->move_directory($backuplocation, $expectedlocation);
}
throw new zip_exception('Unable to open the zip package'); throw new zip_exception('Unable to open the zip package');
} }
@ -1292,7 +1358,9 @@ class worker extends singleton_pattern {
if (!$zip->extractTo($plugintyperoot)) { if (!$zip->extractTo($plugintyperoot)) {
$zip->close(); $zip->close();
$this->remove_directory($expectedlocation, true); // just in case something was created $this->remove_directory($expectedlocation, true); // just in case something was created
$this->move_directory_into($backuplocation, $expectedlocation); if ($backuplocation !== false) {
$this->move_directory_into($backuplocation, $expectedlocation);
}
throw new zip_exception('Unable to extract the zip package'); throw new zip_exception('Unable to extract the zip package');
} }

View File

@ -106,6 +106,13 @@ class testable_worker extends worker {
public function remove_directory($path, $keeppathroot = false) { public function remove_directory($path, $keeppathroot = false) {
return parent::remove_directory($path, $keeppathroot); return parent::remove_directory($path, $keeppathroot);
} }
/**
* Provides access to the protected method.
*/
public function create_directory_precheck($path) {
return parent::create_directory_precheck($path);
}
} }
@ -284,4 +291,13 @@ class mdeploytest extends PHPUnit_Framework_TestCase {
$this->assertTrue($worker->remove_directory($root.'/c')); $this->assertTrue($worker->remove_directory($root.'/c'));
$this->assertFalse(is_dir($root.'/c')); $this->assertFalse(is_dir($root.'/c'));
} }
public function test_create_directory_precheck() {
$worker = testable_worker::instance();
$root = sys_get_temp_dir().'/'.uniqid('mdeploytest', true);
$this->assertFalse(file_exists($root));
$this->assertTrue($worker->create_directory_precheck($root));
$this->assertFalse(file_exists($root)); // The precheck is supposed to remove it again.
}
} }