66use Composer \Package \AliasPackage ;
77use Composer \Package \PackageInterface ;
88use Composer \Repository \RepositoryInterface ;
9+ use Composer \Package \Dumper \ArrayDumper ;
10+ use Composer \Package \Loader \ArrayLoader ;
11+ use Composer \Json \JsonFile ;
12+ use Composer \Semver \Semver ;
913use Psr \Log \LoggerInterface ;
1014
1115class PackageApplicationRepository
@@ -30,6 +34,16 @@ class PackageApplicationRepository
3034 */
3135 private $ logger ;
3236
37+ /**
38+ * @var ArrayDumper
39+ */
40+ private $ packageDumper ;
41+
42+ /**
43+ * @var ArrayLoader
44+ */
45+ private $ packageLoader ;
46+
3347 /**
3448 * @param RepositoryInterface $installedRepository
3549 * @param InstallationManager $installationManager
@@ -46,6 +60,9 @@ public function __construct(
4660 $ this ->installationManager = $ installationManager ;
4761 $ this ->pathResolver = $ pathResolver ;
4862 $ this ->logger = $ logger ;
63+
64+ $ this ->packageDumper = new ArrayDumper ();
65+ $ this ->packageLoader = new ArrayLoader ();
4966 }
5067
5168 /**
@@ -81,7 +98,7 @@ public function getPackageApplication(PackageInterface $targetPackage)
8198 }
8299
83100 if (!is_readable ($ dataFile )) {
84- throw new \RuntimeException ('Cannot read applied patches data file "%s" ' , $ dataFile );
101+ throw new \RuntimeException ('Cannot Loaded applied patches data file "%s" ' , $ dataFile );
85102 }
86103
87104 $ data = json_decode (file_get_contents ($ dataFile ), true );
@@ -126,46 +143,104 @@ private function encodeData(array $data)
126143 * @param array $data
127144 * @return PackagePatchApplication
128145 */
129- private function createPackagePatchApplication (PackageInterface $ targetPackage , array $ data )
146+ private function createPackagePatchApplication ($ targetPackage , array $ data )
130147 {
131- return new PackagePatchApplication ($ targetPackage ,
132- array_map ([$ this , 'createPatchApplication ' ], $ data ['patches ' ])
133- );
148+ return new PackagePatchApplication ($ targetPackage , array_map (
149+ function ($ patchData ) use ($ targetPackage ) {
150+ return $ this ->createPatchApplication ($ targetPackage , $ patchData );
151+ },
152+ $ data ['patches ' ]
153+ ));
154+ }
155+
156+ /**
157+ * @param PackageInterface|null $loadedPackage
158+ * @param string $versionConstraint
159+ * @return PackageInterface|null
160+ */
161+ private function matchLoadedPackageToInstalled ($ loadedPackage , $ versionConstraint = null )
162+ {
163+ if ($ package = $ this ->installedRepository ->findPackage ($ loadedPackage ->getName (), $ loadedPackage ->getVersion ())) {
164+ return $ package ;
165+ }
166+
167+ if ($ loadedPackage ->getPrettyVersion ()
168+ && $ package = $ this ->installedRepository ->findPackage ($ loadedPackage ->getName (), $ loadedPackage ->getPrettyVersion ())) {
169+ return $ package ;
170+ }
171+
172+ if ($ loadedPackage ->getFullPrettyVersion ()
173+ && $ package = $ this ->installedRepository ->findPackage ($ loadedPackage ->getName (), $ loadedPackage ->getFullPrettyVersion ())) {
174+ return $ package ;
175+ }
176+
177+ if ($ versionConstraint && $ package = $ this ->installedRepository ->findPackage ($ loadedPackage ->getName (), $ versionConstraint )) {
178+ return $ package ;
179+ }
180+
181+ return null ;
182+ }
183+
184+ /**
185+ * @param PackageInterface $targetPackageInstalled
186+ * @param PackageInterface $targetPackageLoaded
187+ * @param Patch $patchLoaded
188+ * @return PackageInterface|null
189+ */
190+ private function matchTargetLoadedPackageToInstalled ($ targetPackageInstalled , $ targetPackageLoaded , $ patchLoaded )
191+ {
192+ if ($ targetPackageInstalled ->getName () === $ targetPackageLoaded ->getName ()) {
193+ if ($ targetPackageInstalled ->getVersion () === $ targetPackageLoaded ->getVersion ()) {
194+ return $ targetPackageInstalled ;
195+ }
196+
197+ if ($ targetPackageInstalled ->getPrettyVersion () === $ targetPackageLoaded ->getPrettyVersion ()) {
198+ return $ targetPackageInstalled ;
199+ }
200+
201+ if ($ patchLoaded ->getVersionConstraint () && Semver::satisfies ($ targetPackageInstalled ->getVersion (), $ patchLoaded ->getVersionConstraint ())) {
202+ return $ targetPackageInstalled ;
203+ }
204+
205+ $ this ->logger ->warning (sprintf (
206+ 'Could not find find installed package (%s) matching version (%s) loaded loaded from applied patch. ' .
207+ 'Name and location checks out, but it might indicate a potential problem. Continuing... ' ,
208+ $ targetPackageInstalled ->getPrettyName (),
209+ $ targetPackageLoaded ->getPrettyName ()
210+ ));
211+ }
212+
213+ return $ this ->matchLoadedPackageToInstalled ($ targetPackageLoaded , $ patchLoaded ->getVersionConstraint ());
134214 }
135215
136216 /**
217+ * @param PackageInterface $targetPackage
137218 * @param array $data
138219 * @return PatchApplication
139220 */
140- private function createPatchApplication (array $ data )
221+ private function createPatchApplication ($ targetPackage , array $ data )
141222 {
142223 $ patch = Patch::createFromArray ($ data ['patch ' ]);
143224
144- $ sourcePackage = $ this ->installedRepository ->findPackage (
145- $ data ['source_package ' ]['name ' ],
146- $ data ['source_package ' ]['version ' ]
147- );
225+ $ sourcePackageLoaded = $ this ->loadPackageFromArray ($ data ['source_package ' ]);
226+ $ targetPackageLoaded = $ this ->loadPackageFromArray ($ data ['target_package ' ]);
148227
149- if (!$ sourcePackage ) {
150- $ this ->logger ->debug (sprintf (' Could not find source package %s (%s) for installed patch, it was removed probably ' ,
151- $ data [ ' source_package ' ][ ' name ' ] ,
152- $ data [ ' source_package ' ][ ' version ' ]
228+ if (!$ sourcePackageInstalled = $ this -> matchLoadedPackageToInstalled ( $ sourcePackageLoaded ) ) {
229+ $ this ->logger ->debug (sprintf (
230+ ' Could not find source package %s for installed patch, it was removed probably ' ,
231+ $ sourcePackageLoaded -> getPrettyName ()
153232 ));
154233 }
155234
156- $ targetPackage = $ this ->installedRepository ->findPackage (
157- $ data ['target_package ' ]['name ' ],
158- $ data ['target_package ' ]['version ' ]
159- );
160235
161- if (!$ targetPackage ) {
162- throw new \RuntimeException (sprintf (' Could not find target package %s (%s) for installed patch ' ,
163- $ data [ ' target_package ' ][ ' name ' ] ,
164- $ data [ ' target_package ' ][ ' version ' ]
236+ if (!$ targetPackageInstalled = $ this -> matchTargetLoadedPackageToInstalled ( $ targetPackage, $ targetPackageLoaded , $ patch ) ) {
237+ throw new \LogicException (sprintf (
238+ ' Could not find target package %s for installed patch. This should not happen. ' ,
239+ $ targetPackageLoaded -> getPrettyName ()
165240 ));
166241 }
167242
168- return new PatchApplication ($ patch , $ sourcePackage , $ targetPackage , $ data ['hash ' ]);
243+ return new PatchApplication ($ patch , $ sourcePackageInstalled , $ targetPackageInstalled , $ data ['hash ' ]);
169244 }
170245
171246 /**
@@ -183,6 +258,24 @@ public function transformPackagePatchApplicationToArray(PackagePatchApplication
183258 ];
184259 }
185260
261+ /**
262+ * @param PackageInterface $package
263+ * @return array
264+ */
265+ public function dumpPackageToArray ($ package )
266+ {
267+ return $ this ->packageDumper ->dump ($ package );
268+ }
269+
270+ /**
271+ * @param array $packageData
272+ * @return PackageInterface
273+ */
274+ public function loadPackageFromArray ($ packageData )
275+ {
276+ return $ this ->packageLoader ->load ($ packageData );
277+ }
278+
186279 /**
187280 * @param PatchApplication $application
188281 * @return array
@@ -191,16 +284,8 @@ public function transformPatchApplicationToArray(PatchApplication $application)
191284 {
192285 return [
193286 'hash ' => $ application ->getHash (),
194- 'target_package ' => [
195- 'name ' => $ application ->getTargetPackage ()->getName (),
196- 'version ' => $ application ->getTargetPackage ()->getVersion (),
197- 'ref ' => $ application ->getTargetPackage ()->getSourceReference (),
198- ],
199- 'source_package ' => [
200- 'name ' => $ application ->getSourcePackage ()->getName (),
201- 'version ' => $ application ->getSourcePackage ()->getVersion (),
202- 'ref ' => $ application ->getSourcePackage ()->getSourceReference (),
203- ],
287+ 'target_package ' => $ this ->dumpPackageToArray ($ application ->getTargetPackage ()),
288+ 'source_package ' => $ this ->dumpPackageToArray ($ application ->getSourcePackage ()),
204289 'patch ' => $ application ->getPatch ()->toArray ()
205290 ];
206291 }
0 commit comments