Skip to content

Commit 2ae765c

Browse files
committed
Update Windows symlink patch based on PR reviews
- 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
1 parent 1c8bc39 commit 2ae765c

6 files changed

Lines changed: 47 additions & 42 deletions

File tree

.github/workflows/rubygems.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ jobs:
5555
bundler: none
5656
- name: Install Dependencies
5757
run: bin/rake setup
58-
- name: Run Test with non-Admin user
59-
run: |
60-
gem inst win32-process --no-doc --conservative
61-
ruby bin/windows_run_as_user ruby -S rake test
62-
if: matrix.symlink == 'off'
6358
- name: Run Test
6459
run: bin/rake test
6560
if: matrix.ruby.name != 'truffleruby' && matrix.ruby.name != 'jruby' && matrix.symlink != 'off'
@@ -72,6 +67,11 @@ jobs:
7267
- name: Run Test (Truffleruby)
7368
run: TRUFFLERUBYOPT="--experimental-options --testing-rubygems" bin/rake test
7469
if: matrix.ruby.name == 'truffleruby'
70+
- name: Run Test with non-Admin user
71+
run: |
72+
gem inst win32-process --no-doc --conservative
73+
ruby bin/windows_run_as_user ruby -S rake test
74+
if: matrix.symlink == 'off'
7575

7676
timeout-minutes: 60
7777

bin/windows_run_as_user

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,35 @@
11
require "win32/process"
22
require "rbconfig"
33

4-
TESTUSER = "testuser"
4+
testuser = "testuser"
5+
testpassword = "Password123+"
56

6-
system("net user #{TESTUSER} /del 2>NUL")
7-
system("net user #{TESTUSER} \"Password123+\" /add") || raise
8-
system("icacls . /grant #{TESTUSER}:(OI)(CI)(IO)(F)")
7+
# Remove a previous test user if present
8+
system("net user #{testuser} /del 2>NUL")
9+
# Create a new non-admin user
10+
system("net user #{testuser} \"#{testpassword}\" /add")
11+
# Give the new user full access permission on the working directory
12+
system("icacls . /grant #{testuser}:(OI)(CI)(IO)F")
913

10-
stdout_read, stdout_write = IO.pipe
11-
cmd = ARGV.join(" ")
12-
env = {
14+
IO.pipe do |stdout_read, stdout_write|
15+
cmd = ARGV.join(" ")
16+
env = {
1317
"TMP" => "#{Dir.pwd}/tmp",
1418
"TEMP" => "#{Dir.pwd}/tmp"
15-
}
16-
pinfo = Process.create command_line: cmd,
17-
with_logon: TESTUSER,
18-
password: "Password123+",
19+
}
20+
pinfo = Process.create command_line: cmd,
21+
with_logon: testuser,
22+
password: testpassword,
1923
cwd: Dir.pwd,
2024
environment: ENV.to_h.merge(env).map{|k,v| "#{k}=#{v}" },
2125
startup_info: { stdout: stdout_write, stderr: stdout_write }
2226

23-
stdout_write.close
24-
out = stdout_read.read
25-
puts out
27+
stdout_write.close
28+
out = stdout_read.read
29+
puts out
30+
end
2631

2732
# Wait for process to terminate
28-
sleep 0.1 while !(ecode=Process.get_exitcode(pinfo.process_id))
33+
sleep 1 while !(ecode=Process.get_exitcode(pinfo.process_id))
2934

3035
exit ecode

lib/rubygems/package.rb

Lines changed: 14 additions & 9 deletions
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-
create_symlink_safe(target, destination)
469+
create_symlink(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
@@ -722,14 +722,19 @@ def limit_read(io, name, limit)
722722
bytes
723723
end
724724

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)
725+
if Gem.win_platform?
726+
# Create a symlink and fallback to copy the file or directory on Windows,
727+
# where symlink creation needs special privileges in form of the Developer Mode.
728+
def create_symlink(old_name, new_name)
729+
File.symlink(old_name, new_name)
730+
rescue Errno::EACCES
731+
from = File.expand_path(old_name, File.dirname(new_name))
732+
FileUtils.cp_r(from, new_name)
733+
end
734+
else
735+
def create_symlink(old_name, new_name)
736+
File.symlink(old_name, new_name)
737+
end
733738
end
734739
end
735740

test/rubygems/helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1246,10 +1246,10 @@ def symlink_supported?
12461246
if @@symlink_supported.nil?
12471247
begin
12481248
File.symlink(File.join(@tempdir, "a"), File.join(@tempdir, "b"))
1249-
File.unlink(File.join(@tempdir, "b"))
12501249
rescue NotImplementedError, SystemCallError
12511250
@@symlink_supported = false
12521251
else
1252+
File.unlink(File.join(@tempdir, "b"))
12531253
@@symlink_supported = true
12541254
end
12551255
end

test/rubygems/test_gem_installer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ def test_generate_bin_with_dangling_symlink
763763
assert_empty errors
764764
else
765765
assert_match(/Unable to use symlinks, installing wrapper/i,
766-
errors.to_s)
766+
errors.to_s)
767767
end
768768
assert_empty @ui.output
769769
end

test/rubygems/test_gem_package.rb

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ def test_add_files
175175
end
176176

177177
def test_add_files_symlink
178+
unless symlink_supported?
179+
omit("symlink - developer mode must be enabled on Windows")
180+
end
178181
spec = Gem::Specification.new
179182
spec.files = %w[lib/code.rb lib/code_sym.rb lib/code_sym2.rb]
180183

@@ -185,16 +188,8 @@ def test_add_files_symlink
185188
end
186189

187190
# NOTE: 'code.rb' is correct, because it's relative to lib/code_sym.rb
188-
begin
189-
File.symlink("code.rb", "lib/code_sym.rb")
190-
File.symlink("../lib/code.rb", "lib/code_sym2.rb")
191-
rescue Errno::EACCES => e
192-
if Gem.win_platform?
193-
pend "symlink - developer mode must be enabled on Windows"
194-
else
195-
raise e
196-
end
197-
end
191+
File.symlink("code.rb", "lib/code_sym.rb")
192+
File.symlink("../lib/code.rb", "lib/code_sym2.rb")
198193

199194
package = Gem::Package.new "bogus.gem"
200195
package.spec = spec
@@ -621,7 +616,7 @@ def test_extract_tar_gz_symlink_directory
621616
end
622617

623618
def test_extract_symlink_into_symlink_dir
624-
pend "Symlinks not supported or not enabled" unless symlink_supported?
619+
omit "Symlinks not supported or not enabled" unless symlink_supported?
625620
package = Gem::Package.new @gem
626621
tgz_io = util_tar_gz do |tar|
627622
tar.mkdir "lib", 0o755

0 commit comments

Comments
 (0)