mirror of
				https://github.com/hauke68/Magallanes.git
				synced 2025-11-04 00:50:18 +01:00 
			
		
		
		
	Merge pull request #355 from Toflar/composer-selfupdate
Added composer selfupdate command
This commit is contained in:
		
						commit
						5054fb45d0
					
				
							
								
								
									
										146
									
								
								src/Task/BuiltIn/Composer/SelfUpdateTask.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/Task/BuiltIn/Composer/SelfUpdateTask.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
			
		||||
<?php
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of the Magallanes package.
 | 
			
		||||
 *
 | 
			
		||||
 * (c) Andrés Montañez <andres@andresmontanez.com>
 | 
			
		||||
 *
 | 
			
		||||
 * For the full copyright and license information, please view the LICENSE
 | 
			
		||||
 * file that was distributed with this source code.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Mage\Task\BuiltIn\Composer;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Process\Process;
 | 
			
		||||
use Mage\Task\AbstractTask;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Composer Task - Self update
 | 
			
		||||
 *
 | 
			
		||||
 * @author Yanick Witschi <https://github.com/Toflar>
 | 
			
		||||
 */
 | 
			
		||||
class SelfUpdateTask extends AbstractTask
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Only used for unit tests.
 | 
			
		||||
     *
 | 
			
		||||
     * @var \DateTime
 | 
			
		||||
     */
 | 
			
		||||
    private $dateToCompare;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public function getName()
 | 
			
		||||
    {
 | 
			
		||||
        return 'composer/selfupdate';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public function getDescription()
 | 
			
		||||
    {
 | 
			
		||||
        return '[Composer] Selfupdate';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    public function execute()
 | 
			
		||||
    {
 | 
			
		||||
        $options = $this->getOptions();
 | 
			
		||||
        $days = $options['days'];
 | 
			
		||||
        $versionCommand = sprintf('%s --version', $options['path']);
 | 
			
		||||
 | 
			
		||||
        /** @var Process $process */
 | 
			
		||||
        $process = $this->runtime->runCommand(trim($versionCommand));
 | 
			
		||||
 | 
			
		||||
        if (!$process->isSuccessful()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $dt = $this->extractDate($process->getOutput());
 | 
			
		||||
 | 
			
		||||
        // Date could not be extracted, always run update
 | 
			
		||||
        if (false === $dt) {
 | 
			
		||||
            return $this->selfUpdate($options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check age
 | 
			
		||||
        if (!$this->isOlderThan($dt, $days)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->selfUpdate($options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This tasks obviously always takes the current date to compare the age
 | 
			
		||||
     * of the composer.phar. This method is used for unit test purposes
 | 
			
		||||
     * only.
 | 
			
		||||
     *
 | 
			
		||||
     * @param \DateTime $dateToCompare
 | 
			
		||||
     */
 | 
			
		||||
    public function setDateToCompare(\DateTime $dateToCompare)
 | 
			
		||||
    {
 | 
			
		||||
        $this->dateToCompare = $dateToCompare;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param \DateTime $dt
 | 
			
		||||
     * @param int       $days
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    protected function isOlderThan(\DateTime $dt, $days)
 | 
			
		||||
    {
 | 
			
		||||
        $dtComp = new \DateTime($days . ' days ago');
 | 
			
		||||
 | 
			
		||||
        if (null !== $this->dateToCompare) {
 | 
			
		||||
            $dtComp = $this->dateToCompare;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $dt < $dtComp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param array $options
 | 
			
		||||
     *
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    protected function selfUpdate(array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $selfupdateCommand = sprintf('%s selfupdate %s', $options['path'], $options['release']);
 | 
			
		||||
 | 
			
		||||
        /** @var Process $process */
 | 
			
		||||
        $process = $this->runtime->runCommand(trim($selfupdateCommand));
 | 
			
		||||
 | 
			
		||||
        return $process->isSuccessful();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param string $output
 | 
			
		||||
     *
 | 
			
		||||
     * @return \DateTime|false
 | 
			
		||||
     */
 | 
			
		||||
    protected function extractDate($output)
 | 
			
		||||
    {
 | 
			
		||||
        $date = substr($output, -19);
 | 
			
		||||
 | 
			
		||||
        return \DateTime::createFromFormat('Y-m-d H:i:s', $date);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    protected function getOptions()
 | 
			
		||||
    {
 | 
			
		||||
        $options = array_merge(
 | 
			
		||||
            ['path' => 'composer', 'release' => '', 'days' => 30],
 | 
			
		||||
            $this->runtime->getMergedOption('composer'),
 | 
			
		||||
            $this->options
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return $options;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										157
									
								
								tests/Command/BuiltIn/Composer/SelfUpdateTaskTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								tests/Command/BuiltIn/Composer/SelfUpdateTaskTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Mage\Tests\Command\BuiltIn\Composer;
 | 
			
		||||
 | 
			
		||||
use Mage\Runtime\Runtime;
 | 
			
		||||
use Mage\Task\BuiltIn\Composer\SelfUpdateTask;
 | 
			
		||||
use PHPUnit_Framework_TestCase as TestCase;
 | 
			
		||||
use Symfony\Component\Process\Process;
 | 
			
		||||
 | 
			
		||||
class SelfUpdateTaskTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    public function testBasics()
 | 
			
		||||
    {
 | 
			
		||||
        $task = new SelfUpdateTask();
 | 
			
		||||
        $this->assertSame('composer/selfupdate', $task->getName());
 | 
			
		||||
        $this->assertSame('[Composer] Selfupdate', $task->getDescription());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testExecuteWithFailingVersionDoesNotCallSelfupdate()
 | 
			
		||||
    {
 | 
			
		||||
        $runtime = $this->getMockBuilder(Runtime::class)
 | 
			
		||||
            ->setMethods(['runCommand'])
 | 
			
		||||
            ->getMock();
 | 
			
		||||
 | 
			
		||||
        $runtime
 | 
			
		||||
            ->expects($this->once())
 | 
			
		||||
            ->method('runCommand')
 | 
			
		||||
            ->with('composer --version')
 | 
			
		||||
            ->willReturn($this->mockProcess(false));
 | 
			
		||||
 | 
			
		||||
        $task = $this->getTask($runtime);
 | 
			
		||||
        $this->assertFalse($task->execute());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testExecuteWithNoDateVersionDoesCallSelfupdate()
 | 
			
		||||
    {
 | 
			
		||||
        $runtime = $this->getMockBuilder(Runtime::class)
 | 
			
		||||
                        ->setMethods(['runCommand'])
 | 
			
		||||
                        ->getMock();
 | 
			
		||||
 | 
			
		||||
        $runtime
 | 
			
		||||
            ->expects($this->exactly(2))
 | 
			
		||||
            ->method('runCommand')
 | 
			
		||||
            ->withConsecutive(
 | 
			
		||||
                ['composer --version'],
 | 
			
		||||
                ['composer selfupdate']
 | 
			
		||||
            )
 | 
			
		||||
            ->willReturnOnConsecutiveCalls(
 | 
			
		||||
                $this->mockProcess(true, 'whatever-without-valid-date'),
 | 
			
		||||
                $this->mockProcess(true)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        $task = $this->getTask($runtime);
 | 
			
		||||
        $this->assertTrue($task->execute());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testExecuteShouldUpdate()
 | 
			
		||||
    {
 | 
			
		||||
        $runtime = $this->getMockBuilder(Runtime::class)
 | 
			
		||||
                        ->setMethods(['runCommand'])
 | 
			
		||||
                        ->getMock();
 | 
			
		||||
 | 
			
		||||
        $runtime
 | 
			
		||||
            ->expects($this->exactly(2))
 | 
			
		||||
            ->method('runCommand')
 | 
			
		||||
            ->withConsecutive(
 | 
			
		||||
                ['composer --version'],
 | 
			
		||||
                ['composer selfupdate']
 | 
			
		||||
            )
 | 
			
		||||
            ->willReturnOnConsecutiveCalls(
 | 
			
		||||
                $this->mockProcess(true, 'Composer version 1.3.2 2017-01-01 18:23:41'),
 | 
			
		||||
                $this->mockProcess(true)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        $task = $this->getTask($runtime);
 | 
			
		||||
        $task->setOptions(['days' => 30]);
 | 
			
		||||
        $this->assertTrue($task->execute());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testExecuteShouldNotUpdate()
 | 
			
		||||
    {
 | 
			
		||||
        $runtime = $this->getMockBuilder(Runtime::class)
 | 
			
		||||
                        ->setMethods(['runCommand'])
 | 
			
		||||
                        ->getMock();
 | 
			
		||||
 | 
			
		||||
        $runtime
 | 
			
		||||
            ->expects($this->exactly(1))
 | 
			
		||||
            ->method('runCommand')
 | 
			
		||||
            ->with('composer --version')
 | 
			
		||||
            ->willReturn($this->mockProcess(true, 'Composer version 1.3.2 2017-01-01 18:23:41'));
 | 
			
		||||
 | 
			
		||||
        $task = $this->getTask($runtime);
 | 
			
		||||
        $task->setDateToCompare(\DateTime::createFromFormat('Y-m-d H:i:s', '2016-12-10 18:23:41'));
 | 
			
		||||
        $task->setOptions(['days' => 30]);
 | 
			
		||||
        $this->assertTrue($task->execute());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testWithRelease()
 | 
			
		||||
    {
 | 
			
		||||
        $runtime = $this->getMockBuilder(Runtime::class)
 | 
			
		||||
            ->setMethods(['runCommand'])
 | 
			
		||||
            ->getMock();
 | 
			
		||||
 | 
			
		||||
        $runtime
 | 
			
		||||
            ->expects($this->exactly(2))
 | 
			
		||||
            ->method('runCommand')
 | 
			
		||||
            ->withConsecutive(
 | 
			
		||||
                ['composer --version'],
 | 
			
		||||
                ['composer selfupdate 1.3.1']
 | 
			
		||||
            )
 | 
			
		||||
            ->willReturnOnConsecutiveCalls(
 | 
			
		||||
                $this->mockProcess(true, 'Composer version 1.3.2 2017-01-01 18:23:41'),
 | 
			
		||||
                $this->mockProcess(true)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        $task = $this->getTask($runtime);
 | 
			
		||||
        $task->setOptions(['days' => 30, 'release' => '1.3.1']);
 | 
			
		||||
        $this->assertTrue($task->execute());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTask($runtime)
 | 
			
		||||
    {
 | 
			
		||||
        $config = [
 | 
			
		||||
            'magephp'   => [
 | 
			
		||||
                'composer' => [
 | 
			
		||||
                    'path' => 'composer.phar'
 | 
			
		||||
                ]
 | 
			
		||||
            ]
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        /** @var Runtime $runtime */
 | 
			
		||||
        $runtime->setConfiguration($config);
 | 
			
		||||
 | 
			
		||||
        $task = new SelfUpdateTask();
 | 
			
		||||
        $task->setRuntime($runtime);
 | 
			
		||||
 | 
			
		||||
        return $task;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function mockProcess($successful, $output = '')
 | 
			
		||||
    {
 | 
			
		||||
        $process = $this->getMockBuilder(Process::class)
 | 
			
		||||
                        ->disableOriginalConstructor()
 | 
			
		||||
                        ->getMock();
 | 
			
		||||
        $process
 | 
			
		||||
            ->expects($this->any())
 | 
			
		||||
            ->method('isSuccessful')
 | 
			
		||||
            ->willReturn($successful);
 | 
			
		||||
 | 
			
		||||
        $process
 | 
			
		||||
            ->expects($this->any())
 | 
			
		||||
            ->method('getOutput')
 | 
			
		||||
            ->willReturn($output);
 | 
			
		||||
 | 
			
		||||
        return $process;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user