-
Notifications
You must be signed in to change notification settings - Fork 53
Resolve relative symlink paths correctly #1009
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
Conversation
| ); | ||
| // For some reason, we must access the target directory after mounting it, otherwise the | ||
| // mount will not work. | ||
| this.php.listFiles( vfsTarget ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It continues to work for me when I comment out this line. Maybe it depends on the underlying filesystem and we use different ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To quickly double-check: did you restart the entire app after commenting out this line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to mount and start a site with wp-data-layer-app-pages plugin without listing the files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the wp-data-layer-app-pages test case works without this line for me, too. It's only the Yoast test case that was troublesome
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may find that this line is unnecessary after further testing, but I have a hard time seeing how it would break anything, so I'll land the PR with this included and we can keep the discussion going after merging.
|
|
||
| // Get the realpath of the symlink within the PHP runtime. | ||
| const vfsTarget = this.php.readlink( vfsPath ); | ||
| const vfsTarget = path.posix.resolve( path.dirname( vfsPath ), this.php.readlink( vfsPath ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
php.realpath does not accomplish the same thing (confirmed in my testing). I believe it just returns false because the target path does not yet exist at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To expand on this: realpath works as a more compact way of expressing this logic if the target path is already within the document root. If this is not the case, realpath returns false because the target does not yet exist (see PHP docs).
The SymlinkManager::isTargetInsideDocumentRoot added in this PR stems from the realization that if the target path is already within the document root, there's no need for SymlinkManager to intervene. This is a performance optimization that should help speed up server starts for sites with many symlinks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following up about SymlinkManager::isTargetInsideDocumentRoot: I realized that SymlinkManager::mountTarget already has this performance optimization in that it checks if the file or directory already exists in the Playground FS before attempting to mount it. Hence, I removed this method.
|
It fixes both cases for me. |
sejas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solves the issue and I can start the site without any ../acorn/bin/acorn symlink error. 👍
| ); | ||
| // For some reason, we must access the target directory after mounting it, otherwise the | ||
| // mount will not work. | ||
| this.php.listFiles( vfsTarget ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to mount and start a site with wp-data-layer-app-pages plugin without listing the files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes test well. I haven't been able to reproduce the issue anymore. 👍🏼
Symlinked plugin works well as well.
I did not observe any regressions.
|
Does that solve for Studio problems with symlinks? |
|
@adamziel, not entirely. See https://github.com/Automattic/dotcom-forge/issues/10566 and #548. I'm anticipating that we'll need some assistance with Windows support – the issue description should give you a decent idea of what the problem is currently. |
Related issues
Proposed Changes
First, a quick recap of how
SymlinkManagerworks. Symlinks are technically preserved when mounting the site directory in Playground's virtual file system. However, symlinks are in reality just a special type of file with a target path, and if the target path is outside the document root, it's not accessible in Playground's FS. This is whereSymlinkManagercomes in – it creates a directory inside Playground's FS at the target path and mounts the target path from the host filesystem there.This PR specifically fixes an issue that was introduced when we recently upgraded our Playground dependencies (#959). After the upgrade, the
php.readlinkfunction started returning the correct value, which is the symlink's exact, unresolved target path (i.e. it suddenly returned relative paths sometimes).This PR changes the
SymlinkManager::addSymlinkmethod to resolve the path returned fromphp.readlinkrelative to the directory where the symlink lives (i.e. how symlinks are normally handled).I've also added aAfter working on fixing the failing tests, I realized thatSymlinkManager::isTargetInsideDocumentRootmethod that allows us to skip mounting symlink target paths that are already accessible inside the document root. Should makeSymlinkManagermore efficient.SymlinkManager::mountTargetalready has this performance optimization in that it checks if the file or directory already exists in the Playground FS before attempting to mount it.Testing Instructions
First, let's test the specific case that was reported to us:
wp-content/pluginsnpm installinside the plugin directorySecondly, let's test a typical symlink targeting a directory outside the document root:
~/wordpress-seowp-content/pluginsdirectory, runln -s ~/wordpress-seo/wp-admin/plugins.phpPre-merge Checklist