Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symlinked dir+file combo evades exclude-from-classmap #9773

Open
crossbap opened this issue Mar 11, 2021 · 6 comments
Open

Symlinked dir+file combo evades exclude-from-classmap #9773

crossbap opened this issue Mar 11, 2021 · 6 comments
Labels
Milestone

Comments

@crossbap
Copy link

My composer.json:

{
  "autoload": {
    "classmap": ["src/","src1/","src2/"],
    "exclude-from-classmap": ["src/A.php", "src1/A.php", "src2/A.php"]
  }
}

Output of composer diagnose:

Checking composer.json: WARNING
No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist: OK
Checking https connectivity to packagist: OK
Checking github.com rate limit: OK
Checking disk free space: OK
Checking pubkeys: 
Tags Public Key Fingerprint: 57815BA2 7E54DC31 7ECC7CC5 573090D0  87719BA6 8F3BB723 4E5D42D0 84A14642
Dev Public Key Fingerprint: 4AC45767 E5EC2265 2F0C1167 CBBB8A2B  0C708369 153E328C AD90147D AFE50952
OK
Checking composer version: OK
Composer version: 2.0.11
PHP version: 7.4.3
PHP binary path: /usr/bin/php7.4
OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020
cURL version: 7.68.0 libz 1.2.11 ssl OpenSSL/1.1.1i
zip: extension present, unzip present

When I run this command:

composer dump -o -vvv

I get the following output:

$ composer dump -o -vvv
Reading ./composer.json (/home/rossc/tmp/t3/composer.json)
Loading config file ./composer.json (/home/rossc/tmp/t3/composer.json)
Checked CA file /etc/ssl/certs/ca-certificates.crt: valid
Executing command (/home/rossc/tmp/t3): git branch -a --no-color --no-abbrev -v
Executing command (/home/rossc/tmp/t3): git describe --exact-match --tags
Executing command (CWD): git --version
Executing command (/home/rossc/tmp/t3): git log --pretty="%H" -n1 HEAD --no-show-signature
Executing command (/home/rossc/tmp/t3): hg branch
Executing command (/home/rossc/tmp/t3): fossil branch list
Executing command (/home/rossc/tmp/t3): fossil tag list
Executing command (/home/rossc/tmp/t3): svn info --xml
Failed to initialize global composer: Composer could not find the config file: /home/rossc/.config/composer/composer.json

Running 2.0.11 (2021-02-24 14:57:23) with PHP 7.4.3 on Linux / 5.4.0-66-generic
Generating optimized autoload files
Generated optimized autoload files containing 2 classes

And I expected this to happen:

We should see "Generated optimized autoload files containing 1 class".

But really, there should NOT be src/A.php in vendor/composer/autoload_classmap.php, as it has been specifically excluded.

Instead, I see the following in vendor/composer/autoload_classmap.php:

<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'A' => $baseDir . '/src/A.php',
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

The directory structure is as follows:

.
├── composer.json
├── src -> src1
├── src1
│   └── A.php -> ../src2/A.php
├── src2
│   └── A.php

Which can be easily re-created with the following commands:

mkdir src1 src2
ln -s src1 src
ln -s ../src2/A.php src1/A.php
echo "<?php class A {}" >src2/A.php

Basically, a symlink to a dir, which contains a symlink to a file within it.

@alcohol
Copy link
Member

alcohol commented Mar 31, 2021

When processing the classmap directories, we filter the exclude-from-classmap list to the entries that match the current given dir we are iterating over (realpath()ed).

When we process src, it is realpath()ed to src1 and we limit the exclude-from-classmap list entries to just src1/A.php. Thus src/A.php does not get ignored.

@Seldaek I think we only took into account that files might be symlinked, not directories. I could be mistaken though.

@Seldaek
Copy link
Member

Seldaek commented Mar 31, 2021

Yeah I am not sure what is the exact cause.. This symlink setup seems like quite a mess and I don't know where it's failing but it's most likely the source of the problem.

Does it work if you do "exclude-from-classmap": ["**/A.php"] (or */A.php)?

@alcohol
Copy link
Member

alcohol commented Mar 31, 2021

When processing src, we end up having a $excluded value of {(/composer\-test/src1/Dummy\.php($|/))}, a $realPath value of /composer-test/src2/Dummy.php, and a $filePath value of composer-test/src/Dummy.php.

@alcohol
Copy link
Member

alcohol commented Mar 31, 2021

Yeah I am not sure what is the exact cause.. This symlink setup seems like quite a mess and I don't know where it's failing but it's most likely the source of the problem.

Does it work if you do "exclude-from-classmap": ["**/A.php"] (or */A.php)?

👍 These both work. Whether or not they fit his use-case is another question though.

@azorus-ross
Copy link

Many thanks for looking into this!

Yeah I am not sure what is the exact cause.. This symlink setup seems like quite a mess and I don't know where it's failing but it's most likely the source of the problem.

I do realize how convoluted this example appears after I simplified it, but I assure you this was a real use case 😄. I can elaborate a little bit just for context.

This was a development-level working set up where I could swap out top-level dirs by just flipping symlinks. I have a specific top-level repo dir for each of my clients (e.g. app-CLIENT1 app-CLIENT2, the symlink being just app), each of which symlink a number of framework-required files from my "core" code repo that they are assembled into as part of my build process. Only under this set up, I had a few files that are specifically excluded from my classmap (used for dev-only) appearing in the classmap unexpectedly.

I have since worked around this by no longer using these top-level directory symlinks, and just rename the directories when I need to swap clients, and that works fine. I will note that I use many file-symlinks to avoid duplication, and everything works together nicely - only when there is also a directory symlink in play do I have any issues.

Does it work if you do "exclude-from-classmap": ["**/A.php"] (or */A.php)?

This actually will work for my use case, as for my case I do happen to have unique filenames that I always want excluded from the classmap.

However, I feel like the exclude-from-classmap should always exclude if I have put in the realpath of a file... but then again, I am probably the first person to encounter this and so I will of course, respectfully leave it to your discretion as to how to proceed.

If there is any way I can be of assistance please let me know.

@Seldaek Seldaek added the Bug label Apr 6, 2021
@Seldaek Seldaek added this to the Bugs milestone Apr 6, 2021
@Seldaek
Copy link
Member

Seldaek commented Apr 6, 2021

Happy to mark this as a bug, but realistically this is quite the edge case situation so not likely someone will look at fixing this soon, especially as you have a working solution now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants