Skip to content

Commit 1a1e2f3

Browse files
larskanisEdouard-chin
authored andcommitted
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 8bb5a2f commit 1a1e2f3

6 files changed

Lines changed: 50 additions & 42 deletions

File tree

.github/workflows/rubygems.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ on:
44
pull_request:
55

66
push:
7+
branches:
8+
- master
79

810
concurrency:
911
group: ci-${{ github.ref }}-${{ github.workflow }}
@@ -61,11 +63,6 @@ jobs:
6163
bundler: none
6264
- name: Install Dependencies
6365
run: bin/rake setup
64-
- name: Run Test with non-Admin user
65-
run: |
66-
gem inst win32-process --no-doc --conservative
67-
ruby bin/windows_run_as_user ruby -S rake test
68-
if: matrix.symlink == 'off'
6966
- name: Run Test
7067
run: bin/rake test
7168
if: matrix.ruby.name != 'truffleruby' && matrix.ruby.name != 'jruby' && matrix.symlink != 'off'
@@ -78,6 +75,11 @@ jobs:
7875
- name: Run Test (Truffleruby)
7976
run: TRUFFLERUBYOPT="--experimental-options --testing-rubygems" bin/rake test
8077
if: matrix.ruby.name == 'truffleruby'
78+
- name: Run Test with non-Admin user
79+
run: |
80+
gem inst win32-process --no-doc --conservative
81+
ruby bin/windows_run_as_user ruby -S rake test
82+
if: matrix.symlink == 'off'
8183

8284
timeout-minutes: 60
8385

bin/windows_run_as_user

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
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+
pinfo = nil
15+
IO.pipe do |stdout_read, stdout_write|
16+
cmd = ARGV.join(" ")
17+
env = {
1318
"TMP" => "#{Dir.pwd}/tmp",
1419
"TEMP" => "#{Dir.pwd}/tmp"
15-
}
16-
pinfo = Process.create command_line: cmd,
17-
with_logon: TESTUSER,
18-
password: "Password123+",
20+
}
21+
pinfo = Process.create command_line: cmd,
22+
with_logon: testuser,
23+
password: testpassword,
1924
cwd: Dir.pwd,
2025
environment: ENV.to_h.merge(env).map{|k,v| "#{k}=#{v}" },
2126
startup_info: { stdout: stdout_write, stderr: stdout_write }
2227

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

2733
# Wait for process to terminate
28-
sleep 0.1 while !(ecode=Process.get_exitcode(pinfo.process_id))
34+
sleep 1 while !(ecode=Process.get_exitcode(pinfo.process_id))
2935

3036
exit ecode

lib/rubygems/package.rb

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
470470

471471
symlinks.each do |name, target, destination, real_destination|
472472
if File.exist?(real_destination)
473-
create_symlink_safe(target, destination)
473+
create_symlink(target, destination)
474474
else
475475
alert_warning "#{@spec.full_name} ships with a dangling symlink named #{name} pointing to missing #{target} file. Ignoring"
476476
end
@@ -726,14 +726,19 @@ def limit_read(io, name, limit)
726726
bytes
727727
end
728728

729-
# Create a symlink and fallback to copy the file or directory on Windows,
730-
# where symlink creation needs special privileges in form of the Developer Mode.
731-
def create_symlink_safe(old_name, new_name) # :nodoc:
732-
File.symlink(old_name, new_name)
733-
rescue Errno::EACCES
734-
raise unless Gem.win_platform?
735-
from = File.expand_path(old_name, File.dirname(new_name))
736-
FileUtils.cp_r(from, new_name)
729+
if Gem.win_platform?
730+
# Create a symlink and fallback to copy the file or directory on Windows,
731+
# where symlink creation needs special privileges in form of the Developer Mode.
732+
def create_symlink(old_name, new_name)
733+
File.symlink(old_name, new_name)
734+
rescue Errno::EACCES
735+
from = File.expand_path(old_name, File.dirname(new_name))
736+
FileUtils.cp_r(from, new_name)
737+
end
738+
else
739+
def create_symlink(old_name, new_name)
740+
File.symlink(old_name, new_name)
741+
end
737742
end
738743
end
739744

test/rubygems/helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,10 +1268,10 @@ def symlink_supported?
12681268
if @@symlink_supported.nil?
12691269
begin
12701270
File.symlink(File.join(@tempdir, "a"), File.join(@tempdir, "b"))
1271-
File.unlink(File.join(@tempdir, "b"))
12721271
rescue NotImplementedError, SystemCallError
12731272
@@symlink_supported = false
12741273
else
1274+
File.unlink(File.join(@tempdir, "b"))
12751275
@@symlink_supported = true
12761276
end
12771277
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)