Skip to content

Commit 0365027

Browse files
committed
Fallback to copy symlinks on Windows
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.
1 parent 8f32bfe commit 0365027

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

lib/rubygems/package.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
466466

467467
symlinks.each do |name, target, destination, real_destination|
468468
if File.exist?(real_destination)
469-
File.symlink(target, destination)
469+
create_symlink_safe(target, destination)
470470
else
471471
alert_warning "#{@spec.full_name} ships with a dangling symlink named #{name} pointing to missing #{target} file. Ignoring"
472472
end
@@ -721,6 +721,16 @@ def limit_read(io, name, limit)
721721
raise Gem::Package::FormatError, "#{name} is too big (over #{limit} bytes)" if bytes.size > limit
722722
bytes
723723
end
724+
725+
# Create a symlink and fallback to copy the file or directory on Windows,
726+
# where symlink creation needs special privileges in form of the Developer Mode.
727+
def create_symlink_safe(old_name, new_name) # :nodoc:
728+
File.symlink(old_name, new_name)
729+
rescue Errno::EACCES
730+
raise unless Gem.win_platform?
731+
from = File.expand_path(old_name, File.dirname(new_name))
732+
FileUtils.cp_r(from, new_name)
733+
end
724734
end
725735

726736
require_relative "package/digest_io"

0 commit comments

Comments
 (0)