Skip to content

Fallback to copy symlinks on Windows#9296

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

Fallback to copy symlinks on Windows#9296
larskanis wants to merge 3 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.


push:
branches:
- master
Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's for running my branch in CI. I can restore it, when review is OK.

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.

2 participants

Comments