refactored PackageLock to Locker and stabilized it
parent
1fcb833902
commit
21191ffa00
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Package;
|
||||||
|
|
||||||
|
use Composer\Json\JsonFile;
|
||||||
|
use Composer\Repository\RepositoryManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads/writes project lockfile (composer.lock).
|
||||||
|
*
|
||||||
|
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||||
|
*/
|
||||||
|
class Locker
|
||||||
|
{
|
||||||
|
private $lockFile;
|
||||||
|
private $repositoryManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes packages locker.
|
||||||
|
*
|
||||||
|
* @param JsonFile $lockFile lockfile loader
|
||||||
|
* @param RepositoryManager $repositoryManager repository manager instance
|
||||||
|
*/
|
||||||
|
public function __construct(JsonFile $lockFile, RepositoryManager $repositoryManager)
|
||||||
|
{
|
||||||
|
$this->lockFile = $lockFile;
|
||||||
|
$this->repositoryManager = $repositoryManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether locker were been locked (lockfile found).
|
||||||
|
*
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public function isLocked()
|
||||||
|
{
|
||||||
|
return $this->lockFile->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches and returns an array of locked packages, retrieved from registered repositories.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getLockedPackages()
|
||||||
|
{
|
||||||
|
if (!$this->isLocked()) {
|
||||||
|
throw new \LogicException('No lockfile found. Unable to read locked packages');
|
||||||
|
}
|
||||||
|
|
||||||
|
$lockList = $this->lockFile->read();
|
||||||
|
$packages = array();
|
||||||
|
foreach ($lockList as $info) {
|
||||||
|
$package = $this->repositoryManager->findPackage($info['package'], $info['version']);
|
||||||
|
|
||||||
|
if (!$package) {
|
||||||
|
throw new \LogicException(sprintf(
|
||||||
|
'Can not find "%s-%s" package in registered repositories',
|
||||||
|
$info['package'], $info['version']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$packages[] = $package;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks provided packages into lockfile.
|
||||||
|
*
|
||||||
|
* @param array $packages array of packages
|
||||||
|
*/
|
||||||
|
public function lockPackages(array $packages)
|
||||||
|
{
|
||||||
|
$hash = array();
|
||||||
|
foreach ($packages as $package) {
|
||||||
|
$name = $package->getName();
|
||||||
|
$version = $package->getVersion();
|
||||||
|
|
||||||
|
if (!$name || !$version) {
|
||||||
|
throw new \LogicException(sprintf(
|
||||||
|
'Package "%s" has no version or name and can not be locked', $package
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash[] = array('package' => $name, 'version' => $version);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->lockFile->write($hash);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,91 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Composer.
|
|
||||||
*
|
|
||||||
* (c) Nils Adermann <naderman@naderman.de>
|
|
||||||
* Jordi Boggiano <j.boggiano@seld.be>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Composer\Package;
|
|
||||||
|
|
||||||
use Composer\Package\MemoryPackage;
|
|
||||||
use Composer\Package\Version\VersionParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
|
||||||
*/
|
|
||||||
class PackageLock
|
|
||||||
{
|
|
||||||
private $file;
|
|
||||||
private $isLocked = false;
|
|
||||||
|
|
||||||
public function __construct($file = 'composer.lock')
|
|
||||||
{
|
|
||||||
if (file_exists($file)) {
|
|
||||||
$this->file = $file;
|
|
||||||
$this->isLocked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isLocked()
|
|
||||||
{
|
|
||||||
return $this->isLocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLockedPackages()
|
|
||||||
{
|
|
||||||
$lockList = $this->loadJsonConfig($this->file);
|
|
||||||
|
|
||||||
$versionParser = new VersionParser();
|
|
||||||
$packages = array();
|
|
||||||
foreach ($lockList as $info) {
|
|
||||||
$version = $versionParser->normalize($info['version']);
|
|
||||||
$packages[] = new MemoryPackage($info['package'], $version);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lock(array $packages)
|
|
||||||
{
|
|
||||||
// TODO: write installed packages info into $this->file
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadJsonConfig($json)
|
|
||||||
{
|
|
||||||
if (is_file($json)) {
|
|
||||||
$json = file_get_contents($json);
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = json_decode($json, true);
|
|
||||||
if (!$config) {
|
|
||||||
switch (json_last_error()) {
|
|
||||||
case JSON_ERROR_NONE:
|
|
||||||
$msg = 'No error has occurred, is your composer.json file empty?';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_DEPTH:
|
|
||||||
$msg = 'The maximum stack depth has been exceeded';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_STATE_MISMATCH:
|
|
||||||
$msg = 'Invalid or malformed JSON';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_CTRL_CHAR:
|
|
||||||
$msg = 'Control character error, possibly incorrectly encoded';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_SYNTAX:
|
|
||||||
$msg = 'Syntax error';
|
|
||||||
break;
|
|
||||||
case JSON_ERROR_UTF8:
|
|
||||||
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
throw new \UnexpectedValueException('Incorrect composer.json file: '.$msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $config;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Test\Package;
|
||||||
|
|
||||||
|
use Composer\Package\Locker;
|
||||||
|
|
||||||
|
class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testIsLocked()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$locker = new Locker($json, $this->createRepositoryManagerMock());
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('exists')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
|
||||||
|
$this->assertTrue($locker->isLocked());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetNotLockedPackages()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo);
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('exists')
|
||||||
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
|
$this->setExpectedException('LogicException');
|
||||||
|
|
||||||
|
$locker->getLockedPackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLockedPackages()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo);
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('exists')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue(array(
|
||||||
|
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
||||||
|
array('package' => 'pkg2', 'version' => '0.1.10')
|
||||||
|
)));
|
||||||
|
|
||||||
|
$package1 = $this->createPackageMock();
|
||||||
|
$package2 = $this->createPackageMock();
|
||||||
|
|
||||||
|
$repo
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('findPackage')
|
||||||
|
->with($this->logicalOr('pkg1', 'pkg2'), $this->logicalOr('1.0.0-beta', '0.1.10'))
|
||||||
|
->will($this->onConsecutiveCalls($package1, $package2));
|
||||||
|
|
||||||
|
$this->assertEquals(array($package1, $package2), $locker->getLockedPackages());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetPackagesWithoutRepo()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo);
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('exists')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue(array(
|
||||||
|
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
||||||
|
array('package' => 'pkg2', 'version' => '0.1.10')
|
||||||
|
)));
|
||||||
|
|
||||||
|
$package1 = $this->createPackageMock();
|
||||||
|
$package2 = $this->createPackageMock();
|
||||||
|
|
||||||
|
$repo
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('findPackage')
|
||||||
|
->with($this->logicalOr('pkg1', 'pkg2'), $this->logicalOr('1.0.0-beta', '0.1.10'))
|
||||||
|
->will($this->onConsecutiveCalls($package1, null));
|
||||||
|
|
||||||
|
$this->setExpectedException('LogicException');
|
||||||
|
|
||||||
|
$locker->getLockedPackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLockPackages()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo);
|
||||||
|
|
||||||
|
$package1 = $this->createPackageMock();
|
||||||
|
$package2 = $this->createPackageMock();
|
||||||
|
|
||||||
|
$package1
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getName')
|
||||||
|
->will($this->returnValue('pkg1'));
|
||||||
|
$package1
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getVersion')
|
||||||
|
->will($this->returnValue('1.0.0-beta'));
|
||||||
|
|
||||||
|
$package2
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getName')
|
||||||
|
->will($this->returnValue('pkg2'));
|
||||||
|
$package2
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getVersion')
|
||||||
|
->will($this->returnValue('0.1.10'));
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('write')
|
||||||
|
->with(array(
|
||||||
|
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
||||||
|
array('package' => 'pkg2', 'version' => '0.1.10')
|
||||||
|
));
|
||||||
|
|
||||||
|
$locker->lockPackages(array($package1, $package2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLockBadPackages()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo);
|
||||||
|
|
||||||
|
$package1 = $this->createPackageMock();
|
||||||
|
$package1
|
||||||
|
->expects($this->once())
|
||||||
|
->method('getName')
|
||||||
|
->will($this->returnValue('pkg1'));
|
||||||
|
|
||||||
|
$this->setExpectedException('LogicException');
|
||||||
|
|
||||||
|
$locker->lockPackages(array($package1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createJsonFileMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('Composer\Json\JsonFile')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createRepositoryManagerMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('Composer\Repository\RepositoryManager')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createPackageMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('Composer\Package\PackageInterface')
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue