Thanks to visit codestin.com
Credit goes to github.com

Skip to content

On Windows platforms where projects are deployed on junctions/symlinks, symfony/runtime's ComposerPlugin writes bad $projectDir #49041

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

Closed
nerdgod opened this issue Jan 19, 2023 · 5 comments

Comments

@nerdgod
Copy link
Contributor

nerdgod commented Jan 19, 2023

Symfony version(s) affected

6.0+

Description

On Windows platforms, if the project is placed in a junction or symlink on another drive than the directory the commands are run from, then, symfony/runtime/Internal/ComposerPlugin.php' $this->composer->getConfig()->get('vendor-dir') returns the junction path, but realpath(Factory::getComposerFile()) returns the junction target path.

So if your project is at C:\www\fooProject ->{junction-to}-> D:\some-storage-directory\www\fooProj, the call to $fs->makePathRelative() tries to make relative paths across filesystems and you end up with a project directory of C:\www\fooProject\\D:\some-storage-directory\www\fooProj in your vendor/autoload_runtime.php.

How to reproduce

Create a project on a windows system having two separate drives.

In another directory use mklink /D <projname> <orig_proj_path>

e.g.: project is in Z:\Projects\foo (the 'source') but it is linked to C:\Users\fabien\Desktop\foo (the 'link')

change directory to the link.

remove the vendor dir and re-run composer update

run any composer scripts (auto-scripts or cache:clear)

the script fails with an error because the C:\Users\fabien\Desktop\foo\vendor/autoload_runtime.php has something like

$runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + [
  'project_dir' => __DIR__.'/Z:/Projects/foo/',
]);

Possible Solution

Call realpath() when retrieving both the vendor-dir property and the the composer.json file.

Additional Context

No response

@nerdgod
Copy link
Contributor Author

nerdgod commented Jan 19, 2023

@xabbuh xabbuh added the Runtime label Jan 20, 2023
@xabbuh
Copy link
Member

xabbuh commented Jan 20, 2023

Are you up for sending a PR with your solution?

@nerdgod
Copy link
Contributor Author

nerdgod commented Jan 20, 2023

symfony/runtime#3

@stof
Copy link
Member

stof commented Jan 20, 2023

@nerdgod PRs should be sent in the monorepo where development happens, not in the subtree split.

nicolas-grekas added a commit that referenced this issue Jan 20, 2023
…mlinks (nerdgod)

This PR was submitted for the 6.0 branch but it was merged into the 5.4 branch instead.

Discussion
----------

Fix for Windows when projects are deployed on junctions/symlinks

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #49041
| License       | MIT
| Doc PR        | none

On windows systems where a project directory may be located at a directory that is a junction to a path on another drive, realpath() must be called on both sides of a call to `Filesystem::makePathRelative($path1,$path2)`. Otherwise the result will be an irresolvable comparison across filesystems and the return value will be the value of $path1, not a relative path.

Commits
-------

6bbc46c Update ComposerPlugin.php
@eartahhj
Copy link

eartahhj commented Apr 6, 2023

For those that are struggling with this exact problem while running a Symfony < 5.4.19 (which fixed the issue), I had to try and research for 2 hours but this is the temporary solution I came up with:

(Symfony 5.4.4)

  1. Create an autoload_runtime.template file somewhere in your app folder, could be even in the root where the composer.json file is

  2. You can find the original autoload_runtime.template file in vendor/symfony/runtime/internal. Copy the contents and paste them in the new autoload_runtime.template file you created

  3. Now in the new file, change the line for:
    $runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + %runtime_options%);
    with:
    $runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + [ 'project_dir' => 'C:/path/to/project', ]);'

This is because even if I set project_dir or dotenv_path inside the composer.json file they apparently get ignored.
Of course adjust the project_dir path according to your needs.

  1. Modify your composer.json file and configure the path to point at the new autoload template in the extra options:
    "extra": { "runtime": { "autoload_template": "C:/path/to/the/new/file/autoload_runtime.template" }, }

I hope this helps someone, expecially myself from the future in case I encounter this problem again. And thanks for finding this issue and solving it, so at least I got confirmation that it was a bug and not just a problem in my system configuration. Took me a while to figure it all out, but anyway.

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

No branches or pull requests

6 participants