Ocramius / PackageVersions

:package: Composer addon to efficiently get installed packages' version numbers
MIT License
3.22k stars 67 forks source link

Strange error when building PHPStan PHAR #48

Closed ondrejmirtes closed 6 years ago

ondrejmirtes commented 7 years ago

Hi Marco, since fixing the Composer issue in 1.1.3, I'm not able to build a PHAR package when depending on this library. It fails with a strange issue:

PHP Fatal error:  Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in /Users/ondrej/Development/phpstan-compiler/tmp/build/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 5

When trying to run composer dump-autoload --optimize --classmap-authoritative.

I'm really not able to debug this, I just know that if I remove dependency on PackageVersions, it starts working.

The PHAR is built using phpstan-compiler and these are the steps to reproduce:

git clone https://github.com/fprochazka/phpstan-compiler
cd phpstan-compiler
composer install
php -dphar.readonly=0 bin/compile --no-extensions [version]

And as [version] you can try:

fa989c1ce3de562c22fc1478b8025f2e426c1821 - current master, fails 5ded1c16fae9eca894cc246aae8f38d59bddceec - removed jean85/pretty-package-versions, works a035f4ea618c3d4b3d169e0ef6f7c8162420cbd4 - added ocramius/package-versions directly, fails

The README of phpstan-compiler does a good job of explaining what it does so I'm not going to rehash it here in depth. Basically it prefixes all dependencies with a namespace so that it does not clash with runtime versions of loaded libraries in case they are different. (This hack will be possible to remove once PHPStan runs on static reflection.)

cc @Jean85 @fprochazka this might also be interesting for you

ondrejmirtes commented 7 years ago

I also tried to compile commit hash e7e6db84cbb92b02a36d5b261fff918905057011 (uses older ocramius/package-versions 1.1.2) and it works. So the issue is really casued by 1.1.3

Ocramius commented 7 years ago

The class file is declared twice in this package: once as a fallback, and after installation as a compiled class. I suggest checking the state of the package before the phar processing begins. If the phar-ification moves stuff around, be aware that this package modifies the file in-place.

On 23 Oct 2017 23:50, "Ondřej Mirtes" notifications@github.com wrote:

Hi Marco, since fixing the Composer issue in 1.1.3, I'm not able to build a PHAR package when depending on this library. It fails with a strange issue:

PHP Fatal error: Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in /Users/ondrej/Development/phpstan-compiler/tmp/build/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 5

When trying to run composer dump-autoload --optimize --classmap-authoritative.

I'm really not able to debug this, I just know that if I remove dependency on PackageVersions, it starts working.

The PHAR is built using phpstan-compiler https://github.com/fprochazka/phpstan-compiler and these are the steps to reproduce:

git clone https://github.com/fprochazka/phpstan-compiler cd phpstan-compiler composer install php -dphar.readonly=0 bin/compile --no-extensions [version]

And as [version] you can try:

fa989c1ce3de562c22fc1478b8025f2e426c1821 - current master, fails 5ded1c16fae9eca894cc246aae8f38d59bddceec - removed jean85/pretty-package-versions, works a035f4ea618c3d4b3d169e0ef6f7c8162420cbd4 - added ocramius/package-versions directly, fails

The README of phpstan-compiler does a good job of explaining what it does so I'm not going to rehash it here in depth. Basically it prefixes all dependencies with a namespace so that it does not clash with runtime versions of loaded libraries in case they are different. (This hack will be possible to remove once PHPStan runs on static reflection.)

cc @Jean85 https://github.com/jean85 @fprochazka https://github.com/fprochazka this might also be interesting for you

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Ocramius/PackageVersions/issues/48, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakNZuk73zsvQGpkwxlkcqOJggrWn-ks5svQolgaJpZM4QDi-d .

ondrejmirtes commented 7 years ago

I don't understand fully what should I do, but I at least have steps to reproduce this problem on a clean repo:

1) composer require ocramius/package-versions 2) composer update --no-dev --no-suggest --optimize-autoloader --classmap-authoritative 3) Rename manually the namespace of the three classes this package consists of. 4) composer dump-autoload --optimize --classmap-authoritative => PHP Fatal error: Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in

What step should I add and when to mitigate this?

Ocramius commented 7 years ago

I can't reproduce this locally. Here's what I did:

git init
composer require ocramius/package-versions
Using version ^1.1 for ocramius/package-versions
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing ocramius/package-versions (1.1.3): Loading from cache
Writing lock file
Generating autoload files
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class
git add .
git commit -m "First commit"

Then:

composer update --no-dev --no-suggest --optimize-autoloader --classmap-authoritative

Produced:

commit 40305ee97e0dca916503303eb424d1c0338a9e2d
Author: Marco Pivetta <ocramius@gmail.com>
Date:   Tue Oct 24 00:46:32 2017 +0200

    Ran `composer update --no-dev --no-suggest --optimize-autoloader --classmap-authoritative`

diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 7a91153..64b74f2 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -6,4 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);

 return array(
+    'PackageVersions\\FallbackVersions' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/FallbackVersions.php',
+    'PackageVersions\\Installer' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/Installer.php',
+    'PackageVersions\\Versions' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/Versions.php',
 );
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index 1a1ea74..a0cefa0 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -29,22 +29,13 @@ class ComposerAutoloaderInit7ca84cfb1c6213da8875e75077cff7b2

             call_user_func(\Composer\Autoload\ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::getInitializer($loader));
         } else {
-            $map = require __DIR__ . '/autoload_namespaces.php';
-            foreach ($map as $namespace => $path) {
-                $loader->set($namespace, $path);
-            }
-
-            $map = require __DIR__ . '/autoload_psr4.php';
-            foreach ($map as $namespace => $path) {
-                $loader->setPsr4($namespace, $path);
-            }
-
             $classMap = require __DIR__ . '/autoload_classmap.php';
             if ($classMap) {
                 $loader->addClassMap($classMap);
             }
         }

+        $loader->setClassMapAuthoritative(true);
         $loader->register(true);

         return $loader;
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 9258949..3f44f1f 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -20,11 +20,18 @@ class ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2
         ),
     );

+    public static $classMap = array (
+        'PackageVersions\\FallbackVersions' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/FallbackVersions.php',
+        'PackageVersions\\Installer' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/Installer.php',
+        'PackageVersions\\Versions' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/Versions.php',
+    );
+
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
             $loader->prefixLengthsPsr4 = ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::$prefixLengthsPsr4;
             $loader->prefixDirsPsr4 = ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::$classMap;

         }, null, ClassLoader::class);
     }
diff --git a/vendor/ocramius/package-versions/src/PackageVersions/Versions.php b/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
index 4806233..fba71b1 100644
--- a/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
+++ b/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
@@ -12,7 +12,7 @@ final class Versions
 {
     const VERSIONS = array (
   'ocramius/package-versions' => '1.1.3@72b226d2957e9e6a9ed09aeaa29cabd840d1a3b7',
-  '__root__' => '9999999-dev@2153cbb10d593de4d4c744d98d798372cb8d1302',
+  '__root__' => '9999999-dev@486a8d1a48d30c7b450826fdd5b2ee4bd7979bdb',
 );

     private function __construct()

Then edited the PackageVersions namespace:

commit 4c95a8929d0c6c6d30017b9b977207a70559e9fe
Author: Marco Pivetta <ocramius@gmail.com>
Date:   Tue Oct 24 00:48:23 2017 +0200

    Manually renamed `namespace PackageVersions` to `namespace PHPStanVendor\PackageVersions`

diff --git a/vendor/ocramius/package-versions/src/PackageVersions/FallbackVersions.php b/vendor/ocramius/package-versions/src/PackageVersions/FallbackVersions.php
index 831f5b1..86efcf2 100644
--- a/vendor/ocramius/package-versions/src/PackageVersions/FallbackVersions.php
+++ b/vendor/ocramius/package-versions/src/PackageVersions/FallbackVersions.php
@@ -1,6 +1,6 @@
 <?php

-namespace PackageVersions;
+namespace PHPStanVendor\PackageVersions;

 /**
  * @internal
diff --git a/vendor/ocramius/package-versions/src/PackageVersions/Installer.php b/vendor/ocramius/package-versions/src/PackageVersions/Installer.php
index 579042d..0ffd5c8 100644
--- a/vendor/ocramius/package-versions/src/PackageVersions/Installer.php
+++ b/vendor/ocramius/package-versions/src/PackageVersions/Installer.php
@@ -1,6 +1,6 @@
 <?php

-namespace PackageVersions;
+namespace PHPStanVendor\PackageVersions;

 use Composer\Composer;
 use Composer\Config;
@@ -19,7 +19,7 @@ final class Installer implements PluginInterface, EventSubscriberInterface
     private static $generatedClassTemplate = <<<'PHP'
 <?php

-namespace PackageVersions;
+namespace PHPStanVendor\PackageVersions;

 /**
  * This class is generated by ocramius/package-versions, specifically by
diff --git a/vendor/ocramius/package-versions/src/PackageVersions/Versions.php b/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
index fba71b1..e0bd310 100644
--- a/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
+++ b/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
@@ -1,6 +1,6 @@
 <?php

-namespace PackageVersions;
+namespace PHPStanVendor\PackageVersions;

 /**
  * This class is generated by ocramius/package-versions, specifically by

Then ran:

composer dump-autoload --optimize --classmap-authoritative

Produced following output (success):

Generating optimized autoload files

And following changes:

diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 64b74f2..7a91153 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -6,7 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);

 return array(
-    'PackageVersions\\FallbackVersions' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/FallbackVersions.php',
-    'PackageVersions\\Installer' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/Installer.php',
-    'PackageVersions\\Versions' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/Versions.php',
 );
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 3f44f1f..9258949 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -20,18 +20,11 @@ class ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2
         ),
     );

-    public static $classMap = array (
-        'PackageVersions\\FallbackVersions' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/FallbackVersions.php',
-        'PackageVersions\\Installer' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/Installer.php',
-        'PackageVersions\\Versions' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/Versions.php',
-    );
-
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
             $loader->prefixLengthsPsr4 = ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::$prefixLengthsPsr4;
             $loader->prefixDirsPsr4 = ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::$prefixDirsPsr4;
-            $loader->classMap = ComposerStaticInit7ca84cfb1c6213da8875e75077cff7b2::$classMap;

         }, null, ClassLoader::class);
     }
composer --version
Composer version 1.5.2 2017-09-11 16:59:25
ondrejmirtes commented 7 years ago

I followed the same steps and created this repo: https://github.com/ondrejmirtes/debug-48-package-versions

When I clone it to a new directory and try to run:

composer dump-autoload --optimize --classmap-authoritative

It crashes:

PHP Fatal error:  Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in /Users/ondrej/Development/debug-48-package-versions/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 17

Fatal error: Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in /Users/ondrej/Development/debug-48-package-versions/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 17
php --version
PHP 7.1.8 (cli) (built: Aug  7 2017 15:02:45) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

Even the composer --version fails:

PHP Fatal error:  Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in /Users/ondrej/Development/debug-48-package-versions/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 17

Fatal error: Cannot declare class PHPStanVendor\PackageVersions\Installer, because the name is already in use in /Users/ondrej/Development/debug-48-package-versions/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 17
ondrejmirtes commented 7 years ago

I just got an idea - maybe I have the same stuff installed globally and it clashes? I need to look at it.

ondrejmirtes commented 7 years ago

Oh god, that was it. It was sufficient to remove phpstan/phpstan from ~/.composer/composer.json and run composer global update.

Sorry for that. Do you think is there any lesson or issue to be reported to the authors of Composer or should I just close this? It seems a little bit weird to me why it autoloaded globally installed stuff even when I worked with project-scope composer.json...

Ocramius commented 7 years ago

I really don't know why a global install would affect this as well 🤔

On 24 Oct 2017 06:04, "Ondřej Mirtes" notifications@github.com wrote:

Oh god, that was it. It was sufficient to remove phpstan/phpstan from `~/.composer/composer.jsonand runcomposer global update.

Sorry for that. Do you think is there any lesson or issue to be reported to the authors of Composer or should I just close this? It seems a little bit weird to me why it autoloaded globally installed stuff even when I worked with project-scope composer.json...

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Ocramius/PackageVersions/issues/48#issuecomment-338867092, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJakHHWUE4YYy2nqwW418t1VHbOU0z3ks5svWHigaJpZM4QDi-d .

Ocramius commented 6 years ago

Closing here - this is not strictly related to this particular package.

theofidry commented 6 years ago

Sorry for the noise if it's no longer relevant.

It seems a little bit weird to me why it autoloaded globally installed stuff even when I worked with project-scope composer.json

@ondrejmirtes if you happen to use box it sometimes incorrectly look for the autoloader by starting by the most global one instead of going from the local to global