Skip to content

Fallback to copy symlinks on Windows#9296

Open
larskanis wants to merge 4 commits intoruby:masterfrom
larskanis:copy-symlink
Open

Fallback to copy symlinks on Windows#9296
larskanis wants to merge 4 commits intoruby:masterfrom
larskanis:copy-symlink

Conversation

@larskanis
Copy link
Contributor

Symlinks are not permitted by default for a Windows user. To use them, a switch called "Development Mode" in the system settings has to be enabled.

What was the end-user or developer problem that led to this PR?

Ordinary users as well as administrators are unable per default to install gems using symlinks.
One such problematical gem is haml-rails-3.0.0.
It uses symlinks for files and directories.
The resulting error message is not very helpful:

$ gem inst haml-rails
Fetching haml-rails-3.0.0.gem
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the directory. (Gem::FilePermissionError)
        C:/ruby/lib/ruby/4.0.0/rubygems/installer.rb:308:in 'Gem::Installer#install'
        C:/ruby/lib/ruby/4.0.0/rubygems/resolver/specification.rb:105:in 'Gem::Resolver::Specification#install'
        C:/ruby/lib/ruby/4.0.0/rubygems/request_set.rb:192:in 'block in Gem::RequestSet#install'
        C:/ruby/lib/ruby/4.0.0/rubygems/request_set.rb:183:in 'Array#each'
        C:/ruby/lib/ruby/4.0.0/rubygems/request_set.rb:183:in 'Gem::RequestSet#install'
        C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:207:in 'Gem::Commands::InstallCommand#install_gem'
        C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:223:in 'block in Gem::Commands::InstallCommand#install_gems'
        C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:216:in 'Array#each'
        C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:216:in 'Gem::Commands::InstallCommand#install_gems'
        C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:162:in 'Gem::Commands::InstallCommand#execute'
        C:/ruby/lib/ruby/4.0.0/rubygems/command.rb:326:in 'Gem::Command#invoke_with_build_args'
        C:/ruby/lib/ruby/4.0.0/rubygems/command_manager.rb:252:in 'Gem::CommandManager#invoke_command'
        C:/ruby/lib/ruby/4.0.0/rubygems/command_manager.rb:193:in 'Gem::CommandManager#process_args'
        C:/ruby/lib/ruby/4.0.0/rubygems/command_manager.rb:151:in 'Gem::CommandManager#run'
        C:/ruby/lib/ruby/4.0.0/rubygems/gem_runner.rb:56:in 'Gem::GemRunner#run'
        C:/ruby/bin/gem.cmd:20:in '<main>'

What is your fix for the problem, implemented in this PR?

Instead of working around the situation in the affected gem or to skip symlinks completely, I think the better solution would be to make copies of the files in question. This would allow Windows users to install and use the gem smoothly.

I didn't adjust the rubygems tests to support this non-developer-mode use case, because I want to ask if this approach is acceptable, first.

The switch for the "Developer Mode" is available in the Windows registry under
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock
entry
AllowDevelopmentWithoutDevLicense

Maybe we could add a Github Action run with AllowDevelopmentWithoutDevLicense=0, and adjust the tests to succeed in both cases.

Make sure the following tasks are checked

@larskanis
Copy link
Contributor Author

Is copying the files as a fallback to symlink an option for the rubygems maintainers? If so I would like to add proper tests.

@larskanis larskanis force-pushed the copy-symlink branch 2 times, most recently from da5283f to f5cb532 Compare February 15, 2026 19:25
Symlinks are not permitted for an ordinary Windows user.
To use them, a switch called "Development Mode" in the system settings has to be enabled.

This prevents users per default to install gems using symlinks.
One such example is haml-rails-3.0.0.
It uses symlinks for files and directories.
The resulting error message is not very helpful:

```
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the directory. (Gem::FilePermissionError)
```

Instead of fixing the situaltion in the affected gem or to skip symlinks completely,
I think the better solution would be to make copies of the files in question.
This would allow Windows users to install and use the gem smoothly.
@larskanis larskanis force-pushed the copy-symlink branch 10 times, most recently from 39149d0 to d2da6ed Compare February 16, 2026 10:25
This adjust symlink tests on Windows to succeed with developer mode enabled and disabled.

Move `symlink_supported?` to be available for other tests.
Return `true` only if symlink permission is granted (developer mode enabled).
…mode

This way we can ensure that rubygems runs on a normal user account with symlinks disabled.
That is the default on an interactive Windows.
@larskanis
Copy link
Contributor Author

This PR is ready for review now. It adds a test run with non-admin user and no symlink permission to simulate a more realistic Windows environment. Tests run green in both conditions.

@larskanis
Copy link
Contributor Author

This silence is new to me in rubygems+bundler. This used to be a very vital repository! I really miss @deivid-rodriguez, @simi, @segiddins and @indirect . Windows topics like this or #9276 are not so famous, but still important for a part of the community.

Can I help with taking a more official role for Windows specific issues? Since I maintain the RubyInstaller for Windows, I know most of the time about the issues on that platform. But it is annoying to invest time for creating or reviewing patches and then wait for months to get some answer. Having no idea why a PR isn't merged is frustrating.

@hsbt
Copy link
Member

hsbt commented Mar 5, 2026

@larskanis You may not know this, but of all the maintainers I've ever had, I was one of the few who owned and maintained Windows, and still do today.

Right now I'm extremely busy and have higher priorities, but I'm not ignoring you. I'm very disappointment by your comments. Among the Ruby core maintainers, only I and nobu maintain Windows. If you care about Windows, you should respect to such maintainers.

@ruby ruby deleted a comment from indirect Mar 5, 2026
- Move non-admin test down to correct section
- Add comments about non-admin user creation
- Use block version of IO.pipe
- Use variables for user name and password
- Move cleanup per File.unlink out of tested+rescued block
- Omit test completely instead of error prone handling in rescue branch
- Use a dedicated method on Windows to create symlinks
@simi
Copy link
Contributor

simi commented Mar 6, 2026

@larskanis You may not know this, but of all the maintainers I've ever had, I was one of the few who owned and maintained Windows, and still do today.

ℹ️ I have Windows machine and I was working on Windows issues all the time.

@larskanis
Copy link
Contributor Author

Thank you @kou for all the comments! I updated the PR accordingly.

The difference between admin user with symlink and non-admin user without symlink is visible in the test output:

2692 tests, 14215 assertions, 0 failures, 0 errors, 37 pendings, 0 omissions, 0 notifications
versus non-admin:
2692 tests, 14192 assertions, 0 failures, 0 errors, 45 pendings, 2 omissions, 0 notifications

@simi
Copy link
Contributor

simi commented Mar 6, 2026

Is symlink something valid gems should support? What about putting a warnings into gem policy for now to at least raise the awareness of the troubles it can cause?

@larskanis
Copy link
Contributor Author

The example I mentioned above is a very valid use case of symlinks: https://github.com/haml/haml-rails/tree/9f4703ddff0644ba52529c5cf41c1624829b16a7/lib/generators/haml/scaffold/templates
It avoids duplicated code in a simple, comprehensible way.

@simi
Copy link
Contributor

simi commented Mar 6, 2026

I understand, but since symlink is not platform agnostic concept, maybe it will be better to just warn on the usage and send PRs to popular gems to not use it. I think a little code to update the lookup can do the same as symlink in this haml-rails case.

@simi
Copy link
Contributor

simi commented Mar 6, 2026

@larskanis You may not know this, but of all the maintainers I've ever had, I was one of the few who owned and maintained Windows, and still do today.

Right now I'm extremely busy and have higher priorities, but I'm not ignoring you. I'm very disappointment by your comments. Among the Ruby core maintainers, only I and nobu maintain Windows. If you care about Windows, you should respect to such maintainers.

@hsbt to make it clear - you had no maintainers, project had maintainers. From the recent project maintainers, both me and David, had access to Windows machines and we were working actively on Windows issues.. Your claim over being one of the few who owned (or as in original edit the only one) is wrong.


I have checked the email to find out there was also one deleted comment here. Let me repost for the others with simple questions.

hi Lars! thank you for the kind words. We are working actively on Windows support for both Ruby and gems in https://rv.dev/. (Including using Ruby builds from RubyInstaller! Thank you for maintaining those. ❤️)
If you are interested, we would love to work with you to make sure this issue (and any others you find) are handled correctly for anyone installing gems with rv.

What was wrong with the comment that it got deleted and author was banned from discussion?

Where is the Ruby friendliness? This used to be friendly welcoming repo for long time. Now it seems to be driven by hate and personal issues over cooperation on open software.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants