Skip to content

Conversation

@jakebailey
Copy link
Member

This should be faster than doing a realpath.

Copilot AI review requested due to automatic review settings November 4, 2025 03:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors Windows junction and symlink detection by replacing the Realpath-based approach with a dedicated IsSymlinkOrJunction function. The change improves efficiency by using direct Windows API calls to check for reparse points instead of resolving full paths.

  • Adds platform-specific isSymlinkOrJunction implementations for Windows and Unix-like systems
  • Updates internal.Common struct to use IsSymlinkOrJunction instead of Realpath field
  • Simplifies junction detection logic in GetAccessibleEntries

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
internal/vfs/osvfs/symlink_windows.go New file implementing Windows-specific junction/symlink detection using FILE_ATTRIBUTE_REPARSE_POINT
internal/vfs/osvfs/symlink_other.go New file with nil function stub for Unix-like systems where detection is unnecessary
internal/vfs/osvfs/os.go Updates osVFS initialization to use IsSymlinkOrJunction instead of Realpath
internal/vfs/internal/internal.go Replaces Realpath field with IsSymlinkOrJunction in Common struct and simplifies detection logic in GetAccessibleEntries

@DanielRosenwasser
Copy link
Member

Any specific differences you've seen in perf?

@jakebailey
Copy link
Member Author

Haven't tested yet, just cleaning up some TODOs with my name on it. On any project I have it probably won't be very noticable...

if realpath := vfs.Realpath(fullPath); fullPath != realpath {
if stat := vfs.Stat(realpath); stat != nil {
if vfs.IsSymlinkOrJunction(fullPath) {
if stat := vfs.Stat(fullPath); stat != nil {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If something is a junction, maybe we don't even need to stat it and just say that it's a dir? (I don't believe junctions/reparse points can be files, in which case I could rename funcs too)

}

var data syscall.Win32FileAttributeData
err = syscall.GetFileAttributesEx(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to prepend \\?\ to automatically handle long filepaths? https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileattributesexa

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, crap, converting those is a whole thing that is hard and not available to us outside stdlib. I'd need to do something like I did in realpath

func realpath(path string) (string, error) {
	var h windows.Handle
	if len(path) < 248 {
		var err error
		h, err = openMetadata(path)
		if err != nil {
			return "", err
		}
		defer windows.CloseHandle(h) //nolint:errcheck
	} else {
		// For long paths, defer to os.Open to run the path through fixLongPath.
		f, err := os.Open(path)
		if err != nil {
			return "", err
		}
		defer f.Close()

		// Works on directories too since https://go.dev/cl/405275.
		h = windows.Handle(f.Fd())
	}

Guess I'll wait on things until I figure that out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't block this on it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's pretty easy to hit this on the use cases where it matters, e.g. pnpm ones, so I should definitely check it in afraid

@jakebailey jakebailey marked this pull request as draft November 4, 2025 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants