Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions spec/bundled_gems_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,12 @@ def my
end

context "with bundle environment" do
# Windows has no executable bit or shebang dispatch, so running the
# script directly is rejected by bundler as "not executable". Invoke it
# through ruby there. What matters here is force_activate's behavior under
# the bundle environment, not shebang execution (covered by another spec).
let(:exec_command) { Gem.win_platform? ? "exec ruby ./script.rb" : "exec ./script.rb" }

before do
code = <<-RUBY
#!/usr/bin/env ruby
Expand All @@ -400,13 +406,13 @@ def my

it "lockfile is available" do
bundle "install"
bundle "exec ./script.rb"
bundle exec_command

expect(err).to include("gem install csv")
end

it "lockfile is not available" do
bundle "exec ./script.rb"
bundle exec_command

expect(err).to include("gem install csv")
end
Expand Down
2 changes: 1 addition & 1 deletion spec/ruby/core/file/atime_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926
## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed.
it "returns the last access time for the named file with microseconds" do
supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
supports_subseconds = Integer(`stat -c%x #{__FILE__}`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
expected_time = Time.at(Time.now.to_i + 0.123456)
File.utime expected_time, 0, @file
Expand Down
2 changes: 1 addition & 1 deletion spec/ruby/core/file/ctime_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

platform_is :linux, :windows do
it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself) with microseconds." do
supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
supports_subseconds = Integer(`stat -c%z #{__FILE__}`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
File.ctime(__FILE__).usec.should > 0
else
Expand Down
2 changes: 1 addition & 1 deletion spec/ruby/core/file/mtime_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
platform_is :linux, :windows do
unless ENV.key?('TRAVIS') # https://bugs.ruby-lang.org/issues/17926
it "returns the modification Time of the file with microseconds" do
supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d{1,6})/, 1], 10)
supports_subseconds = Integer(`stat -c%y #{__FILE__}`[/\.(\d{1,6})/, 1], 10)
if supports_subseconds != 0
expected_time = Time.at(Time.now.to_i + 0.123456)
File.utime 0, expected_time, @filename
Expand Down
27 changes: 25 additions & 2 deletions test/ruby/test_file_exhaustive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,28 @@ def test_symlink
assert_raise(Errno::EEXIST) { File.symlink(utf8_file, utf8_file) }
end

def test_symlink_to_relative_directory
# A relative target is interpreted relative to the link's directory, not the
# current directory. A relative target pointing at a directory must produce
# a directory symlink even when the current directory differs from the link's
# directory; otherwise Dir operations on the link fail (Windows).
Dir.mktmpdir(__method__.to_s) do |tmpdir|
Dir.chdir(tmpdir) do
Dir.mkdir("subdir")
Dir.mkdir(File.join("subdir", "target"))
link = File.join("subdir", "link")
begin
File.symlink("target", link)
rescue NotImplementedError, Errno::EACCES, Errno::EPERM => e
omit e.message
end
assert_file.symlink?(link)
assert_file.directory?(link)
assert(Dir.exist?(link), "relative directory symlink should be a directory")
end
end
end

def test_utime
t = Time.local(2000)
File.utime(t + 1, t + 2, zerofile)
Expand Down Expand Up @@ -805,10 +827,11 @@ def test_readlink_junction
def test_realpath_mount_point
vol = IO.popen(["mountvol", DRIVE, "/l"], &:read).strip
Dir.mkdir(mnt = File.join(@dir, mntpnt = "mntpnt"))
system("mountvol", mntpnt, vol, chdir: @dir)
err = IO.popen(%W"mountvol #{mntpnt} #{vol}", chdir: @dir, err: %i[child out], &:read)
omit err unless $?.success?
assert_equal(mnt, File.realpath(mnt))
ensure
system("mountvol", mntpnt, "/d", chdir: @dir)
system("mountvol", mntpnt, "/d", chdir: @dir, out: IO::NULL, err: IO::NULL)
end
end

Expand Down
13 changes: 11 additions & 2 deletions test/ruby/test_io_m17n.rb
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,17 @@ def test_dup_undef
end

def test_stdin
assert_equal(Encoding.default_external, STDIN.external_encoding)
assert_equal(nil, STDIN.internal_encoding)
encoding = Encoding.default_external
internal = nil
if /mswin|mingw/ =~ RUBY_PLATFORM and STDIN.tty?
# Interactive console input on Windows is read in the locale (console
# code page) encoding and transcoded to the default external encoding.
encoding = Encoding.find("locale")
internal = Encoding.default_internal || Encoding.default_external
internal = nil if internal == encoding
end
assert_equal(encoding, STDIN.external_encoding)
assert_equal(internal, STDIN.internal_encoding)
end

def test_stdout
Expand Down
2 changes: 1 addition & 1 deletion tool/outdate-bundled-gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def default_gem?(spec)
(@defaults ||= {}).fetch(spec) do
File.open(prefixed(spec)) do |f|
if /^# default: (\S+) (\d+\.\d+)/ =~ f.gets("")
File.mtime(prefixed($1)) <= Time.at(Rational($2))
File.mtime($1) <= Time.at(Rational($2))
else
false
end
Expand Down
29 changes: 29 additions & 0 deletions tool/test-bundled-gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,35 @@
'irb',
'csv',
] : []

# minitest's assertion tests compare against unified diff output produced by
# the `diff` command, so they fail spuriously when it is not available.
diff_available = ENV["PATH"].to_s.split(File::PATH_SEPARATOR).any? do |dir|
next false if dir.empty?
exe = File.join(dir, "diff")
File.executable?(exe) || (/mswin|mingw/ =~ RUBY_PLATFORM && File.file?("#{exe}.exe"))
end
DEFAULT_ALLOWED_FAILURES << 'minitest' unless diff_available

# rake's TestBacktraceSuppression#test_system_dir_suppressed expects rake to
# suppress RbConfig's rubylibprefix from backtraces. In an uninstalled
# out-of-tree build it is a POSIX "/usr"-style prefix that File.expand_path
# turns into a drive-prefixed path on Windows, which no longer matches rake's
# suppression pattern, so the test fails.
if /mswin|mingw/ =~ RUBY_PLATFORM && RbConfig::CONFIG["rubylibprefix"] !~ /\A[a-zA-Z]:/
DEFAULT_ALLOWED_FAILURES << 'rake'
end

# rbs's stdlib Resolv tests need to resolve "localhost"; allow its failures on
# hosts where the Resolv library cannot resolve it.
begin
require 'resolv'
Resolv.getaddress('localhost')
rescue LoadError
rescue Resolv::ResolvError
DEFAULT_ALLOWED_FAILURES << 'rbs'
end

allowed_failures = ENV['TEST_BUNDLED_GEMS_ALLOW_FAILURES'] || ''
allowed_failures = allowed_failures.split(',').concat(DEFAULT_ALLOWED_FAILURES).uniq.reject(&:empty?)

Expand Down
27 changes: 26 additions & 1 deletion win32/win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -5284,8 +5284,33 @@ w32_symlink(UINT cp, const char *src, const char *link)
MultiByteToWideChar(cp, 0, src, -1, wsrc, len1);
MultiByteToWideChar(cp, 0, link, -1, wlink, len2);
translate_wchar(wsrc, L'/', L'\\');
translate_wchar(wlink, L'/', L'\\');

atts = GetFileAttributesW(wsrc);
/* A relative target is interpreted relative to the directory of the link,
not the current directory. Resolve it there to decide whether to create
a directory symlink; otherwise a relative target pointing at a directory
would wrongly become a file symlink when the current directory differs
from the link's directory. */
{
WCHAR *sep;
int independent =
(((wsrc[0] >= L'A' && wsrc[0] <= L'Z') ||
(wsrc[0] >= L'a' && wsrc[0] <= L'z')) && wsrc[1] == L':') ||
wsrc[0] == L'\\';
if (!independent && (sep = wcsrchr(wlink, L'\\')) != NULL) {
VALUE buf2;
size_t dirlen = sep - wlink + 1;
size_t srclen = wcslen(wsrc) + 1;
WCHAR *fullsrc = ALLOCV_N(WCHAR, buf2, dirlen + srclen);
MEMCPY(fullsrc, wlink, WCHAR, dirlen);
MEMCPY(fullsrc + dirlen, wsrc, WCHAR, srclen);
atts = GetFileAttributesW(fullsrc);
ALLOCV_END(buf2);
}
else {
atts = GetFileAttributesW(wsrc);
}
}
if (atts != -1 && atts & FILE_ATTRIBUTE_DIRECTORY)
flag = SYMBOLIC_LINK_FLAG_DIRECTORY;
ret = CreateSymbolicLinkW(wlink, wsrc, flag |= create_flag);
Expand Down