Merge pull request #174 from Seldaek/lockdetect
Detect lock file changes and warn users on install, fixes #75pull/188/merge
commit
35c62f67be
|
@ -85,7 +85,7 @@ EOT
|
||||||
// creating requirements request
|
// creating requirements request
|
||||||
$request = new Request($pool);
|
$request = new Request($pool);
|
||||||
if ($update) {
|
if ($update) {
|
||||||
$output->writeln('<info>Updating dependencies.</info>');
|
$output->writeln('<info>Updating dependencies</info>');
|
||||||
$installedPackages = $installedRepo->getPackages();
|
$installedPackages = $installedRepo->getPackages();
|
||||||
$links = $this->collectLinks($input, $composer->getPackage());
|
$links = $this->collectLinks($input, $composer->getPackage());
|
||||||
|
|
||||||
|
@ -100,7 +100,11 @@ EOT
|
||||||
$request->install($link->getTarget(), $link->getConstraint());
|
$request->install($link->getTarget(), $link->getConstraint());
|
||||||
}
|
}
|
||||||
} elseif ($composer->getLocker()->isLocked()) {
|
} elseif ($composer->getLocker()->isLocked()) {
|
||||||
$output->writeln('<info>Installing from lockfile.</info> (Run "composer update" to add or update packages)');
|
$output->writeln('<info>Installing from lock file</info>');
|
||||||
|
|
||||||
|
if (!$composer->getLocker()->isFresh()) {
|
||||||
|
$output->writeln('<warning>Your lock file is out of sync with your composer.json, run "composer.phar update" to update dependencies</warning>');
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($composer->getLocker()->getLockedPackages() as $package) {
|
foreach ($composer->getLocker()->getLockedPackages() as $package) {
|
||||||
$constraint = new VersionConstraint('=', $package->getVersion());
|
$constraint = new VersionConstraint('=', $package->getVersion());
|
||||||
|
@ -150,6 +154,9 @@ EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute operations
|
// execute operations
|
||||||
|
if (!$operations) {
|
||||||
|
$output->writeln('<info>Nothing to install/update</info>');
|
||||||
|
}
|
||||||
foreach ($operations as $operation) {
|
foreach ($operations as $operation) {
|
||||||
if ($verbose) {
|
if ($verbose) {
|
||||||
$output->writeln((string) $operation);
|
$output->writeln((string) $operation);
|
||||||
|
@ -162,7 +169,7 @@ EOT
|
||||||
if (!$dryRun) {
|
if (!$dryRun) {
|
||||||
if ($update || !$composer->getLocker()->isLocked()) {
|
if ($update || !$composer->getLocker()->isLocked()) {
|
||||||
$composer->getLocker()->lockPackages($localRepo->getPackages());
|
$composer->getLocker()->lockPackages($localRepo->getPackages());
|
||||||
$output->writeln('<info>Locked</info>');
|
$output->writeln('<info>Writing lock file</info>');
|
||||||
}
|
}
|
||||||
|
|
||||||
$localRepo->write();
|
$localRepo->write();
|
||||||
|
@ -171,8 +178,6 @@ EOT
|
||||||
$generator = new AutoloadGenerator;
|
$generator = new AutoloadGenerator;
|
||||||
$generator->dump($localRepo, $composer->getPackage(), $installationManager, $installationManager->getVendorPath().'/.composer');
|
$generator->dump($localRepo, $composer->getPackage(), $installationManager, $installationManager->getVendorPath().'/.composer');
|
||||||
}
|
}
|
||||||
|
|
||||||
$output->writeln('<info>Done</info>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function collectLinks(InputInterface $input, PackageInterface $package)
|
private function collectLinks(InputInterface $input, PackageInterface $package)
|
||||||
|
|
|
@ -49,6 +49,7 @@ class Application extends BaseApplication
|
||||||
{
|
{
|
||||||
if (null === $output) {
|
if (null === $output) {
|
||||||
$styles['highlight'] = new OutputFormatterStyle('red');
|
$styles['highlight'] = new OutputFormatterStyle('red');
|
||||||
|
$styles['warning'] = new OutputFormatterStyle('black', 'yellow');
|
||||||
$formatter = new OutputFormatter(null, $styles);
|
$formatter = new OutputFormatter(null, $styles);
|
||||||
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
|
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +153,7 @@ class Application extends BaseApplication
|
||||||
|
|
||||||
// init locker
|
// init locker
|
||||||
$lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock';
|
$lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock';
|
||||||
$locker = new Package\Locker(new JsonFile($lockFile), $rm);
|
$locker = new Package\Locker(new JsonFile($lockFile), $rm, md5_file($composerFile));
|
||||||
|
|
||||||
// initialize composer
|
// initialize composer
|
||||||
$composer = new Composer();
|
$composer = new Composer();
|
||||||
|
|
|
@ -24,33 +24,48 @@ class Locker
|
||||||
{
|
{
|
||||||
private $lockFile;
|
private $lockFile;
|
||||||
private $repositoryManager;
|
private $repositoryManager;
|
||||||
|
private $hash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes packages locker.
|
* Initializes packages locker.
|
||||||
*
|
*
|
||||||
* @param JsonFile $lockFile lockfile loader
|
* @param JsonFile $lockFile lockfile loader
|
||||||
* @param RepositoryManager $repositoryManager repository manager instance
|
* @param RepositoryManager $repositoryManager repository manager instance
|
||||||
|
* @param string $hash unique hash of the current composer configuration
|
||||||
*/
|
*/
|
||||||
public function __construct(JsonFile $lockFile, RepositoryManager $repositoryManager)
|
public function __construct(JsonFile $lockFile, RepositoryManager $repositoryManager, $hash)
|
||||||
{
|
{
|
||||||
$this->lockFile = $lockFile;
|
$this->lockFile = $lockFile;
|
||||||
$this->repositoryManager = $repositoryManager;
|
$this->repositoryManager = $repositoryManager;
|
||||||
|
$this->hash = $hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether locker were been locked (lockfile found).
|
* Checks whether locker were been locked (lockfile found).
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
public function isLocked()
|
public function isLocked()
|
||||||
{
|
{
|
||||||
return $this->lockFile->exists();
|
return $this->lockFile->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the lock file is still up to date with the current hash
|
||||||
|
*
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public function isFresh()
|
||||||
|
{
|
||||||
|
$lock = $this->lockFile->read();
|
||||||
|
|
||||||
|
return $this->hash === $lock['hash'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches and returns an array of locked packages, retrieved from registered repositories.
|
* Searches and returns an array of locked packages, retrieved from registered repositories.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getLockedPackages()
|
public function getLockedPackages()
|
||||||
{
|
{
|
||||||
|
@ -60,7 +75,7 @@ class Locker
|
||||||
|
|
||||||
$lockList = $this->lockFile->read();
|
$lockList = $this->lockFile->read();
|
||||||
$packages = array();
|
$packages = array();
|
||||||
foreach ($lockList as $info) {
|
foreach ($lockList['packages'] as $info) {
|
||||||
$package = $this->repositoryManager->getLocalRepository()->findPackage($info['package'], $info['version']);
|
$package = $this->repositoryManager->getLocalRepository()->findPackage($info['package'], $info['version']);
|
||||||
|
|
||||||
if (!$package) {
|
if (!$package) {
|
||||||
|
@ -83,11 +98,14 @@ class Locker
|
||||||
/**
|
/**
|
||||||
* Locks provided packages into lockfile.
|
* Locks provided packages into lockfile.
|
||||||
*
|
*
|
||||||
* @param array $packages array of packages
|
* @param array $packages array of packages
|
||||||
*/
|
*/
|
||||||
public function lockPackages(array $packages)
|
public function lockPackages(array $packages)
|
||||||
{
|
{
|
||||||
$hash = array();
|
$lock = array(
|
||||||
|
'hash' => $this->hash,
|
||||||
|
'packages' => array(),
|
||||||
|
);
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
$name = $package->getPrettyName();
|
$name = $package->getPrettyName();
|
||||||
$version = $package->getPrettyVersion();
|
$version = $package->getPrettyVersion();
|
||||||
|
@ -98,9 +116,9 @@ class Locker
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash[] = array('package' => $name, 'version' => $version);
|
$lock['packages'][] = array('package' => $name, 'version' => $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->lockFile->write($hash);
|
$this->lockFile->write($lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
public function testIsLocked()
|
public function testIsLocked()
|
||||||
{
|
{
|
||||||
$json = $this->createJsonFileMock();
|
$json = $this->createJsonFileMock();
|
||||||
$locker = new Locker($json, $this->createRepositoryManagerMock());
|
$locker = new Locker($json, $this->createRepositoryManagerMock(), 'md5');
|
||||||
|
|
||||||
$json
|
$json
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
@ -34,7 +34,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
$json = $this->createJsonFileMock();
|
$json = $this->createJsonFileMock();
|
||||||
$repo = $this->createRepositoryManagerMock();
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
$locker = new Locker($json, $repo);
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
$json
|
$json
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
@ -51,7 +51,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
$json = $this->createJsonFileMock();
|
$json = $this->createJsonFileMock();
|
||||||
$repo = $this->createRepositoryManagerMock();
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
$locker = new Locker($json, $repo);
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
$json
|
$json
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
@ -61,8 +61,10 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('read')
|
->method('read')
|
||||||
->will($this->returnValue(array(
|
->will($this->returnValue(array(
|
||||||
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
'packages' => array(
|
||||||
array('package' => 'pkg2', 'version' => '0.1.10')
|
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
||||||
|
array('package' => 'pkg2', 'version' => '0.1.10')
|
||||||
|
)
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$package1 = $this->createPackageMock();
|
$package1 = $this->createPackageMock();
|
||||||
|
@ -82,7 +84,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
$json = $this->createJsonFileMock();
|
$json = $this->createJsonFileMock();
|
||||||
$repo = $this->createRepositoryManagerMock();
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
$locker = new Locker($json, $repo);
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
$json
|
$json
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
@ -92,8 +94,10 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('read')
|
->method('read')
|
||||||
->will($this->returnValue(array(
|
->will($this->returnValue(array(
|
||||||
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
'packages' => array(
|
||||||
array('package' => 'pkg2', 'version' => '0.1.10')
|
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
||||||
|
array('package' => 'pkg2', 'version' => '0.1.10')
|
||||||
|
)
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$package1 = $this->createPackageMock();
|
$package1 = $this->createPackageMock();
|
||||||
|
@ -115,7 +119,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
$json = $this->createJsonFileMock();
|
$json = $this->createJsonFileMock();
|
||||||
$repo = $this->createRepositoryManagerMock();
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
$locker = new Locker($json, $repo);
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
$package1 = $this->createPackageMock();
|
$package1 = $this->createPackageMock();
|
||||||
$package2 = $this->createPackageMock();
|
$package2 = $this->createPackageMock();
|
||||||
|
@ -142,8 +146,11 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('write')
|
->method('write')
|
||||||
->with(array(
|
->with(array(
|
||||||
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
'hash' => 'md5',
|
||||||
array('package' => 'pkg2', 'version' => '0.1.10')
|
'packages' => array(
|
||||||
|
array('package' => 'pkg1', 'version' => '1.0.0-beta'),
|
||||||
|
array('package' => 'pkg2', 'version' => '0.1.10')
|
||||||
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
$locker->lockPackages(array($package1, $package2));
|
$locker->lockPackages(array($package1, $package2));
|
||||||
|
@ -154,7 +161,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
$json = $this->createJsonFileMock();
|
$json = $this->createJsonFileMock();
|
||||||
$repo = $this->createRepositoryManagerMock();
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
$locker = new Locker($json, $repo);
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
$package1 = $this->createPackageMock();
|
$package1 = $this->createPackageMock();
|
||||||
$package1
|
$package1
|
||||||
|
@ -167,6 +174,36 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
$locker->lockPackages(array($package1));
|
$locker->lockPackages(array($package1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testIsFresh()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue(array('hash' => 'md5')));
|
||||||
|
|
||||||
|
$this->assertTrue($locker->isFresh());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsFreshFalse()
|
||||||
|
{
|
||||||
|
$json = $this->createJsonFileMock();
|
||||||
|
$repo = $this->createRepositoryManagerMock();
|
||||||
|
|
||||||
|
$locker = new Locker($json, $repo, 'md5');
|
||||||
|
|
||||||
|
$json
|
||||||
|
->expects($this->once())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue(array('hash' => 'oldmd5')));
|
||||||
|
|
||||||
|
$this->assertFalse($locker->isFresh());
|
||||||
|
}
|
||||||
|
|
||||||
private function createJsonFileMock()
|
private function createJsonFileMock()
|
||||||
{
|
{
|
||||||
return $this->getMockBuilder('Composer\Json\JsonFile')
|
return $this->getMockBuilder('Composer\Json\JsonFile')
|
||||||
|
|
Loading…
Reference in New Issue