Browse Source

Add name and version to the relevant fields, move content hash checking to the Locker

Zsolt Szeberenyi 9 years ago
parent
commit
bfb83f1fb7

+ 1 - 35
src/Composer/Factory.php

@@ -306,7 +306,7 @@ class Factory
             $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
                 ? substr($composerFile, 0, -4).'lock'
                 : $composerFile . '.lock';
-            $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, md5_file($composerFile), $this->getContentHash($composerFile));
+            $locker = new Package\Locker($io, new JsonFile($lockFile, new RemoteFilesystem($io, $config)), $rm, $im, file_get_contents($composerFile));
             $composer->setLocker($locker);
         }
 
@@ -485,38 +485,4 @@ class Factory
 
         return $factory->createComposer($io, $config, $disablePlugins);
     }
-
-    /**
-     * Returns the md5 hash of the sorted content of the composer file.
-     *
-     * @param string $composerFilePath Path to the composer file.
-     *
-     * @return string
-     */
-    private function getContentHash($composerFilePath)
-    {
-        $content = json_decode(file_get_contents($composerFilePath), true);
-
-        $relevantKeys = array(
-            'require',
-            'require-dev',
-            'conflict',
-            'replace',
-            'provide',
-            'suggest',
-            'minimum-stability',
-            'prefer-stable',
-            'repositories',
-            'extra',
-        );
-
-        $relevantContent = array();
-
-        foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
-            $relevantContent[$key] = $content[$key];
-        }
-
-        ksort($relevantContent);
-        return md5(json_encode($relevantContent));
-    }
 }

+ 42 - 8
src/Composer/Package/Locker.php

@@ -45,19 +45,18 @@ class Locker
      * Initializes packages locker.
      *
      * @param IOInterface         $io
-     * @param JsonFile            $lockFile            lockfile loader
-     * @param RepositoryManager   $repositoryManager   repository manager instance
-     * @param InstallationManager $installationManager installation manager instance
-     * @param string              $hash                unique hash of the current composer configuration
-     * @param string              $contentHash         unique hash of the content of the current composer configuration
+     * @param JsonFile            $lockFile             lockfile loader
+     * @param RepositoryManager   $repositoryManager    repository manager instance
+     * @param InstallationManager $installationManager  installation manager instance
+     * @param string              $composerFileContents The contents of the composer file
      */
-    public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $hash, $contentHash)
+    public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
     {
         $this->lockFile = $lockFile;
         $this->repositoryManager = $repositoryManager;
         $this->installationManager = $installationManager;
-        $this->hash = $hash;
-        $this->contentHash = $contentHash;
+        $this->hash = md5($composerFileContents);
+        $this->contentHash = $this->getContentHash($composerFileContents);
         $this->loader = new ArrayLoader(null, true);
         $this->dumper = new ArrayDumper();
         $this->process = new ProcessExecutor($io);
@@ -387,4 +386,39 @@ class Locker
 
         return $datetime ? $datetime->format('Y-m-d H:i:s') : null;
     }
+
+    /**
+     * Returns the md5 hash of the sorted content of the composer file.
+     *
+     * @param string $composerFileContents The contents of the composer file.
+     *
+     * @return string
+     */
+    private function getContentHash($composerFileContents)
+    {
+        $content = json_decode($composerFileContents, true);
+
+        $relevantKeys = array(
+            'require',
+            'require-dev',
+            'conflict',
+            'replace',
+            'provide',
+            'minimum-stability',
+            'prefer-stable',
+            'repositories',
+            'extra',
+            'version',
+            'name',
+        );
+
+        $relevantContent = array();
+
+        foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
+            $relevantContent[$key] = $content[$key];
+        }
+
+        ksort($relevantContent);
+        return md5(json_encode($relevantContent));
+    }
 }

+ 2 - 2
tests/Composer/Test/InstallerTest.php

@@ -191,8 +191,8 @@ class InstallerTest extends TestCase
                 }));
         }
 
-        $hash   = md5(json_encode($composerConfig));
-        $locker = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), $hash, $hash);
+        $contents = json_encode($composerConfig);
+        $locker   = new Locker($io, $lockJsonMock, $repositoryManager, $composer->getInstallationManager(), $contents);
         $composer->setLocker($locker);
 
         $eventDispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->disableOriginalConstructor()->getMock();

+ 36 - 15
tests/Composer/Test/Package/LockerTest.php

@@ -20,7 +20,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase
     public function testIsLocked()
     {
         $json   = $this->createJsonFileMock();
-        $locker = new Locker(new NullIO, $json, $this->createRepositoryManagerMock(), $this->createInstallationManagerMock(), 'md5', 'contentMd5');
+        $locker = new Locker(new NullIO, $json, $this->createRepositoryManagerMock(), $this->createInstallationManagerMock(),
+            $this->getJsonContent());
 
         $json
             ->expects($this->any())
@@ -40,7 +41,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent());
 
         $json
             ->expects($this->once())
@@ -58,7 +59,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent());
 
         $json
             ->expects($this->once())
@@ -85,7 +86,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $jsonContent = $this->getJsonContent() . '  ';
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $jsonContent);
 
         $package1 = $this->createPackageMock();
         $package2 = $this->createPackageMock();
@@ -116,6 +118,9 @@ class LockerTest extends \PHPUnit_Framework_TestCase
             ->method('getVersion')
             ->will($this->returnValue('0.1.10.0'));
 
+        $hash = md5($jsonContent);
+        $contentHash = md5(trim($jsonContent));
+
         $json
             ->expects($this->once())
             ->method('write')
@@ -123,8 +128,8 @@ class LockerTest extends \PHPUnit_Framework_TestCase
                 '_readme' => array('This file locks the dependencies of your project to a known state',
                                    'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
                                    'This file is @gener'.'ated automatically'),
-                'hash' => 'md5',
-                'content-hash' => 'contentMd5',
+                'hash' => $hash,
+                'content-hash' => $contentHash,
                 'packages' => array(
                     array('name' => 'pkg1', 'version' => '1.0.0-beta'),
                     array('name' => 'pkg2', 'version' => '0.1.10')
@@ -149,7 +154,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'md5');
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent());
 
         $package1 = $this->createPackageMock();
         $package1
@@ -168,12 +173,13 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $jsonContent = $this->getJsonContent();
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $jsonContent);
 
         $json
             ->expects($this->once())
             ->method('read')
-            ->will($this->returnValue(array('hash' => 'md5')));
+            ->will($this->returnValue(array('hash' => md5($jsonContent))));
 
         $this->assertTrue($locker->isFresh());
     }
@@ -184,12 +190,12 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent());
 
         $json
             ->expects($this->once())
             ->method('read')
-            ->will($this->returnValue(array('hash' => 'oldmd5')));
+            ->will($this->returnValue(array('hash' => $this->getJsonContent(array('name' => 'test2')))));
 
         $this->assertFalse($locker->isFresh());
     }
@@ -200,12 +206,13 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $jsonContent = $this->getJsonContent();
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $jsonContent);
 
         $json
             ->expects($this->once())
             ->method('read')
-            ->will($this->returnValue(array('hash' => 'oldMd5', 'content-hash' => 'contentMd5')));
+            ->will($this->returnValue(array('hash' => md5($jsonContent . '  '), 'content-hash' => md5($jsonContent))));
 
         $this->assertTrue($locker->isFresh());
     }
@@ -216,12 +223,14 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         $repo = $this->createRepositoryManagerMock();
         $inst = $this->createInstallationManagerMock();
 
-        $locker = new Locker(new NullIO, $json, $repo, $inst, 'md5', 'contentMd5');
+        $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent());
+
+        $differentHash = md5($this->getJsonContent(['name' => 'test2']));
 
         $json
             ->expects($this->once())
             ->method('read')
-            ->will($this->returnValue(array('hash' => 'md5', 'content-hash' => 'oldMd5')));
+            ->will($this->returnValue(array('hash' => $differentHash, 'content-hash' => $differentHash)));
 
         $this->assertFalse($locker->isFresh());
     }
@@ -260,4 +269,16 @@ class LockerTest extends \PHPUnit_Framework_TestCase
         return $this->getMockBuilder('Composer\Package\PackageInterface')
             ->getMock();
     }
+
+    private function getJsonContent(array $customData = array())
+    {
+        $data = array_merge(array(
+            'minimum-stability' => 'beta',
+            'name' => 'test',
+        ), $customData);
+
+        ksort($data);
+
+        return json_encode($data);
+    }
 }