Skip to content

Commit

Permalink
Resolve #14, introduce the extractor abstraction layer
Browse files Browse the repository at this point in the history
In this commit, we provide two method to extract a tar.gz file, there are call 'tar' command and Phar extension.
Also we directly extract files in tarball to the target directory while upgrading.

Signed-off-by: RazeSoldier <razesoldier@outlook.com>
  • Loading branch information
RazeSoldier committed Mar 5, 2021
1 parent ad7814d commit d2fd566
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 43 deletions.
1 change: 1 addition & 0 deletions composer.json
Expand Up @@ -20,6 +20,7 @@
"ext-phar": "*",
"symfony/console": "^4.3",
"symfony/http-client": "^4.3",
"symfony/process": "^4.3",
"ext-json": "*"
},
"autoload": {
Expand Down
25 changes: 25 additions & 0 deletions includes/Extractor/ExtractException.php
@@ -0,0 +1,25 @@
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/

namespace RazeSoldier\MWExtUpgrader\Extractor;

class ExtractException extends \Exception
{
}
30 changes: 30 additions & 0 deletions includes/Extractor/Extractor.php
@@ -0,0 +1,30 @@
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/

namespace RazeSoldier\MWExtUpgrader\Extractor;

/**
* Used to extract a tar.gz file, please use {@link ExtractorFactory} to get a new instance
* @package RazeSoldier\MWExtUpgrader\Extractor
*/
interface Extractor
{
public function extract(string $tarballFilePath, string $dstPath);
}
42 changes: 42 additions & 0 deletions includes/Extractor/ExtractorFactory.php
@@ -0,0 +1,42 @@
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/

namespace RazeSoldier\MWExtUpgrader\Extractor;

use Symfony\Component\Process\ExecutableFinder;

class ExtractorFactory
{
/**
* If 'tar' command unavailable will use native (Phar)
* @return Extractor
*/
public static function make(): Extractor {
if (($path = self::checkTarCommandExist()) !== null) {
return new TarExtractor($path);
}
return new NativeExtractor();
}

private static function checkTarCommandExist():? string {
$finder = new ExecutableFinder();
return $finder->find('tar');
}
}
34 changes: 34 additions & 0 deletions includes/Extractor/NativeExtractor.php
@@ -0,0 +1,34 @@
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/

namespace RazeSoldier\MWExtUpgrader\Extractor;

/**
* Use {@link \PharData} to extract .tar.gz file
* @package RazeSoldier\MWExtUpgrader\Extractor
*/
class NativeExtractor implements Extractor
{
public function extract(string $tarballFilePath, string $dstPath)
{
$pharData = new \PharData($tarballFilePath);
$pharData->extractTo($dstPath);
}
}
65 changes: 65 additions & 0 deletions includes/Extractor/TarExtractor.php
@@ -0,0 +1,65 @@
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/

namespace RazeSoldier\MWExtUpgrader\Extractor;

use Symfony\Component\Process\Exception\ProcessSignaledException;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Exception\RuntimeException;
use Symfony\Component\Process\Process;

/**
* Use 'tar' command to extract .tar.gz file
* @package RazeSoldier\MWExtUpgrader\Extractor
*/
class TarExtractor implements Extractor
{
/**
* @var string
*/
private $executablePath;

public function __construct(string $executablePath)
{
$this->executablePath = $executablePath;
}

/**
* @param string $tarballFilePath
* @param string $dstPath
* @throws ExtractException
*/
public function extract(string $tarballFilePath, string $dstPath)
{
if (!is_dir($dstPath)) {
mkdir($dstPath);
}

$process = new Process([$this->executablePath, '-xzf', $tarballFilePath, '-C', $dstPath]);
try {
$exitCode = $process->run();
} catch (ProcessSignaledException | RuntimeException | ProcessTimedOutException $e) {
throw new ExtractException($e->getMessage(), 0, $e);
}
if ($exitCode !== 0) {
throw new ExtractException("Failed to extract $tarballFilePath to $dstPath (error message: {$process->getErrorOutput()})");
}
}
}
10 changes: 10 additions & 0 deletions includes/Services.php
Expand Up @@ -20,6 +20,9 @@

namespace RazeSoldier\MWExtUpgrader;

use RazeSoldier\MWExtUpgrader\Extractor\Extractor;
use RazeSoldier\MWExtUpgrader\Extractor\ExtractorFactory;

/**
* Services
* @package RazeSoldier\MWExtUpgrader
Expand Down Expand Up @@ -52,4 +55,11 @@ public function getExtensionRepo() : ExtensionRepo {
}
return $this->services['extension_repo'];
}

public function getExtractor(): Extractor {
if (!isset($this->services['extractor'])) {
$this->services['extractor'] = ExtractorFactory::make();
}
return $this->services['extractor'];
}
}
51 changes: 8 additions & 43 deletions includes/UpgradeTask.php
Expand Up @@ -53,21 +53,15 @@ public function __construct(string $name, string $src, string $dst, int $type) {
public function run(OutputInterface $output) {
$filename = $this->makeTmp();
$this->pullFromSrc($filename, $output);
$this->extractTarball($filename, "{$filename}ex" );
$this->deleteDst($this->dst);
$res = $this->copyDir("{$filename}ex", dirname($this->dst));
if ($res) {
$this->deleteDst("{$filename}ex");
$version = $this->getVersion();
$text = "{$this->name} successfully upgraded";
// Try to output the extension version
if ($version !== null) {
$text .= " to $version";
}
$output->writeln("<info>$text</info>");
} else {
$output->writeln('<error>Failed to copy to dst from src</error>');
$this->extractTarball($filename, dirname($this->dst) );
$version = $this->getVersion();
$text = "{$this->name} successfully upgraded";
// Try to output the extension version
if ($version !== null) {
$text .= " to $version";
}
$output->writeln("<info>$text</info>");
}

/**
Expand Down Expand Up @@ -122,36 +116,7 @@ private function deleteDst(string $dir) : bool {
}

private function extractTarball(string $tarballPath, string $targetPath) {
$pharData = new \PharData($tarballPath);
$pharData->extractTo($targetPath);
}

private function copyDir(string $src, string $dst) {
$dir = opendir( $src );
if ( !is_resource( $dir ) ) {
return false;
}
if (!file_exists($dst)) {
mkdir( $dst );
}
while( false !== ( $file = readdir( $dir ) ) ) {
if ( ( $file != '.' ) && ( $file != '..' ) ) {
if ( is_dir( $src . '/' . $file ) ) {
$this->copyDir( $src . '/' . $file, $dst . '/' . $file );
continue;
} else {
$srcPath = $src . '/' . $file;
$dstPath = $dst . '/' . $file;
if ( is_readable( $srcPath ) && createFileAble( $dst ) ) {
copy( $srcPath, $dstPath );
} else {
return false;
}
}
}
}
closedir($dir);
return true;
Services::getInstance()->getExtractor()->extract($tarballPath, $targetPath);
}

/**
Expand Down

0 comments on commit d2fd566

Please sign in to comment.