-
Notifications
You must be signed in to change notification settings - Fork 86
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
Changes from all commits
8c66854
65eae59
a77c724
a81c93f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,10 +139,10 @@ export class SymlinkManager { | |
| * @param filename | ||
| */ | ||
| private async addSymlink( filename: string ) { | ||
| const fullPath = path.join( this.projectPath, filename ); | ||
| let target: string; | ||
| const fullPath = path.resolve( this.projectPath, filename ); | ||
| let hostTarget: string; | ||
| try { | ||
| target = await fs.realpath( fullPath ); | ||
| hostTarget = await fs.realpath( fullPath ); | ||
| } catch ( err ) { | ||
| if ( isErrnoException( err ) && err.code === 'ENOENT' ) { | ||
| console.error( `Symlink target does not exist: ${ fullPath }` ); | ||
|
|
@@ -152,18 +152,19 @@ export class SymlinkManager { | |
| return; | ||
| } | ||
|
|
||
| const vfsPath = path.posix.join( this.documentRoot, filename ); | ||
| const vfsPath = path.posix.resolve( this.documentRoot, filename ); | ||
|
|
||
| // Double check to ensure the symlink exists | ||
| if ( ! this.php.fileExists( vfsPath ) ) { | ||
| return; | ||
| } | ||
|
|
||
| // 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 ) ); | ||
|
|
||
| this.symlinks.set( filename, vfsTarget ); | ||
|
|
||
| await this.mountTarget( vfsTarget, target ); | ||
| await this.mountTarget( vfsTarget, hostTarget ); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -195,6 +196,9 @@ export class SymlinkManager { | |
| vfsTarget, | ||
| createNodeFsMountHandler( hostTarget ) | ||
| ); | ||
| // For some reason, we must access the target directory after mounting it, otherwise the | ||
| // mount will not work. | ||
| this.php.listFiles( vfsTarget ); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was able to mount and start a site with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
| } | ||
|
|
||
| /** | ||
|
|
||
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.realpathdoes not accomplish the same thing (confirmed in my testing). I believe it just returnsfalsebecause 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:
realpathworks 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,realpathreturns false because the target does not yet exist (see PHP docs).The
SymlinkManager::isTargetInsideDocumentRootadded in this PR stems from the realization that if the target path is already within the document root, there's no need forSymlinkManagerto 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 thatSymlinkManager::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. Hence, I removed this method.