mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Fix for windows(mingw)
* File.expand_path: support drive letter and ALT_SEPARATOR * File.dirname: support ALT_SEPARATOR * File.basename: ditto. * IO.popen: raise NotImplementedError * IO.pipe: ditto. * `cmd`: ditto. * File#flock: ditto. * FileTest.pipe?: ditto. * FileTest.symlink?: ditto. * FileTest.socket?: ditto.
This commit is contained in:
+19
-5
@@ -89,14 +89,21 @@ class File < IO
|
||||
end
|
||||
|
||||
expanded_path = concat_path(path, default_dir)
|
||||
drive_prefix = ""
|
||||
if File::ALT_SEPARATOR && expanded_path.size > 2 &&
|
||||
("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
|
||||
drive_prefix = expanded_path[0, 2]
|
||||
expanded_path = expanded_path[2, expanded_path.size]
|
||||
end
|
||||
expand_path_array = []
|
||||
if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR)
|
||||
expanded_path.gsub!(File::ALT_SEPARATOR, '/')
|
||||
end
|
||||
while expanded_path.include?('//')
|
||||
expanded_path = expanded_path.gsub('//', '/')
|
||||
end
|
||||
|
||||
if expanded_path == "/"
|
||||
expanded_path
|
||||
else
|
||||
if expanded_path != "/"
|
||||
expanded_path.split('/').each do |path_token|
|
||||
if path_token == '..'
|
||||
if expand_path_array.size > 1
|
||||
@@ -109,8 +116,15 @@ class File < IO
|
||||
end
|
||||
end
|
||||
|
||||
expand_path = expand_path_array.join("/")
|
||||
expand_path.empty? ? '/' : expand_path
|
||||
expanded_path = expand_path_array.join("/")
|
||||
if expanded_path.empty?
|
||||
expanded_path = '/'
|
||||
end
|
||||
end
|
||||
if drive_prefix.empty?
|
||||
expanded_path
|
||||
else
|
||||
drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ class IO
|
||||
end
|
||||
|
||||
def self.popen(command, mode = 'r', &block)
|
||||
if !self.respond_to?(:_popen)
|
||||
raise NotImplementedError, "popen is not supported on this platform"
|
||||
end
|
||||
io = self._popen(command, mode)
|
||||
return io unless block
|
||||
|
||||
@@ -42,6 +45,9 @@ class IO
|
||||
end
|
||||
|
||||
def self.pipe(&block)
|
||||
if !self.respond_to?(:_pipe)
|
||||
raise NotImplementedError, "pipe is not supported on this platform"
|
||||
end
|
||||
if block
|
||||
begin
|
||||
r, w = IO._pipe
|
||||
|
||||
+31
-12
@@ -130,17 +130,28 @@ mrb_file_s_rename(mrb_state *mrb, mrb_value obj)
|
||||
static mrb_value
|
||||
mrb_file_dirname(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
char dname[_MAX_DIR], vname[_MAX_DRIVE];
|
||||
char buffer[_MAX_DRIVE + _MAX_DIR];
|
||||
char *path;
|
||||
size_t ridx;
|
||||
mrb_value s;
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
path = mrb_str_to_cstr(mrb, s);
|
||||
_splitpath((const char*)path, vname, dname, NULL, NULL);
|
||||
snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname);
|
||||
ridx = strlen(buffer);
|
||||
if (ridx == 0) {
|
||||
strncpy(buffer, ".", 2); /* null terminated */
|
||||
} else if (ridx > 1) {
|
||||
ridx--;
|
||||
while (ridx > 0 && (buffer[ridx] == '/' || buffer[ridx] == '\\')) {
|
||||
buffer[ridx] = '\0'; /* remove last char */
|
||||
ridx--;
|
||||
}
|
||||
}
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
#else
|
||||
#else
|
||||
char *dname, *path;
|
||||
mrb_value s;
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
@@ -149,25 +160,37 @@ mrb_file_dirname(mrb_state *mrb, mrb_value klass)
|
||||
if ((dname = dirname(path)) == NULL) {
|
||||
mrb_sys_fail(mrb, "dirname");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return mrb_str_new_cstr(mrb, dname);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_file_basename(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
char bname[_MAX_DIR];
|
||||
char extname[_MAX_EXT];
|
||||
char *path;
|
||||
size_t ridx;
|
||||
char buffer[_MAX_DIR + _MAX_EXT];
|
||||
mrb_value s;
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
path = mrb_str_to_cstr(mrb, s);
|
||||
ridx = strlen(path);
|
||||
if (ridx > 0) {
|
||||
ridx--;
|
||||
while (ridx > 0 && (path[ridx] == '/' || path[ridx] == '\\')) {
|
||||
path[ridx] = '\0';
|
||||
ridx--;
|
||||
}
|
||||
if (strncmp(path, "/", 2) == 0) {
|
||||
return mrb_str_new_cstr(mrb, path);
|
||||
}
|
||||
}
|
||||
_splitpath((const char*)path, NULL, NULL, bname, extname);
|
||||
snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname);
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
#else
|
||||
#else
|
||||
char *bname, *path;
|
||||
mrb_value s;
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
@@ -176,7 +199,7 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass)
|
||||
mrb_sys_fail(mrb, "basename");
|
||||
}
|
||||
return mrb_str_new_cstr(mrb, bname);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
@@ -255,12 +278,11 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
mrb_value
|
||||
mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(sun)
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "flock is not supported on Illumos/Solaris");
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(sun)
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "flock is not supported on Illumos/Solaris/Windows");
|
||||
#else
|
||||
mrb_int operation;
|
||||
int fd;
|
||||
@@ -289,7 +311,6 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_value
|
||||
mrb_file_s_symlink(mrb_state *mrb, mrb_value klass)
|
||||
@@ -333,9 +354,7 @@ mrb_init_file(mrb_state *mrb)
|
||||
mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE());
|
||||
mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1));
|
||||
|
||||
#ifndef _WIN32
|
||||
mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1));
|
||||
#endif
|
||||
|
||||
cnst = mrb_define_module_under(mrb, file, "Constants");
|
||||
mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH));
|
||||
|
||||
@@ -128,6 +128,9 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
mrb_value
|
||||
mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "pipe is not supported on this platform");
|
||||
#else
|
||||
#ifdef S_IFIFO
|
||||
# ifndef S_ISFIFO
|
||||
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
@@ -145,6 +148,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
#endif
|
||||
return mrb_false_value();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -157,6 +161,9 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
mrb_value
|
||||
mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "symlink is not supported on this platform");
|
||||
#else
|
||||
#ifndef S_ISLNK
|
||||
# ifdef _S_ISLNK
|
||||
# define S_ISLNK(m) _S_ISLNK(m)
|
||||
@@ -184,6 +191,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
|
||||
return mrb_false_value();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -196,6 +204,9 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
mrb_value
|
||||
mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "socket is not supported on this platform");
|
||||
#else
|
||||
#ifndef S_ISSOCK
|
||||
# ifdef _S_ISSOCK
|
||||
# define S_ISSOCK(m) _S_ISSOCK(m)
|
||||
@@ -223,6 +234,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
|
||||
return mrb_false_value();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+23
-9
@@ -56,12 +56,16 @@ end
|
||||
|
||||
assert('IO#flock') do
|
||||
f = File.open $mrbtest_io_rfname
|
||||
assert_equal(f.flock(File::LOCK_SH), 0)
|
||||
assert_equal(f.flock(File::LOCK_UN), 0)
|
||||
assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0)
|
||||
assert_equal(f.flock(File::LOCK_UN), 0)
|
||||
f.close
|
||||
true
|
||||
begin
|
||||
assert_equal(f.flock(File::LOCK_SH), 0)
|
||||
assert_equal(f.flock(File::LOCK_UN), 0)
|
||||
assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0)
|
||||
assert_equal(f.flock(File::LOCK_UN), 0)
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
ensure
|
||||
f.close
|
||||
end
|
||||
end
|
||||
|
||||
assert('File.join') do
|
||||
@@ -76,8 +80,13 @@ assert('File.join') do
|
||||
end
|
||||
|
||||
assert('File.realpath') do
|
||||
usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp }
|
||||
assert_equal usrbin, File.realpath("bin")
|
||||
if File.const_defined?(:ALT_SEPARATOR) && File::ALT_SEPARATOR
|
||||
readme_path = File._getwd + File::ALT_SEPARATOR + "README.md"
|
||||
assert_equal readme_path, File.realpath("README.md")
|
||||
else
|
||||
usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp }
|
||||
assert_equal usrbin, File.realpath("bin")
|
||||
end
|
||||
end
|
||||
|
||||
assert('File TEST CLEANUP') do
|
||||
@@ -95,7 +104,12 @@ assert('File.expand_path') do
|
||||
assert_equal "/hoge", File.expand_path("////tmp/..///////hoge")
|
||||
|
||||
assert_equal "/", File.expand_path("../../../..", "/")
|
||||
assert_equal "/", File.expand_path(([".."] * 100).join("/"))
|
||||
if File._getwd[1] == ":"
|
||||
drive_letter = File._getwd[0]
|
||||
assert_equal drive_letter + ":\\", File.expand_path(([".."] * 100).join("/"))
|
||||
else
|
||||
assert_equal "/", File.expand_path(([".."] * 100).join("/"))
|
||||
end
|
||||
end
|
||||
|
||||
assert('File.expand_path (with ENV)') do
|
||||
|
||||
+21
-9
@@ -6,8 +6,8 @@ assert('FileTest TEST SETUP') do
|
||||
end
|
||||
|
||||
assert("FileTest.directory?") do
|
||||
assert_equal true, FileTest.directory?("/tmp")
|
||||
assert_equal false, FileTest.directory?("/bin/sh")
|
||||
assert_equal true, FileTest.directory?(File.join(File._getwd, "mrblib"))
|
||||
assert_equal false, FileTest.directory?(File.join(File._getwd, "README.md"))
|
||||
end
|
||||
|
||||
assert("FileTest.exist?") do
|
||||
@@ -23,14 +23,18 @@ assert("FileTest.exist?") do
|
||||
end
|
||||
|
||||
assert("FileTest.file?") do
|
||||
assert_equal false, FileTest.file?("/tmp")
|
||||
assert_equal true, FileTest.file?("/bin/sh")
|
||||
assert_equal false, FileTest.file?(File.join(File._getwd, "mrblib"))
|
||||
assert_equal true, FileTest.file?(File.join(File._getwd, "README.md"))
|
||||
end
|
||||
|
||||
assert("FileTest.pipe?") do
|
||||
io = IO.popen("ls")
|
||||
assert_equal true, FileTest.pipe?(io)
|
||||
assert_equal false, FileTest.pipe?("/tmp")
|
||||
begin
|
||||
assert_equal false, FileTest.pipe?("/tmp")
|
||||
io = IO.popen("ls")
|
||||
assert_equal true, FileTest.pipe?(io)
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
assert('FileTest.size') do
|
||||
@@ -61,11 +65,19 @@ assert("FileTest.size?") do
|
||||
end
|
||||
|
||||
assert("FileTest.socket?") do
|
||||
assert_true FileTest.socket?($mrbtest_io_socketname)
|
||||
begin
|
||||
assert_true FileTest.socket?($mrbtest_io_socketname)
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
assert("FileTest.symlink?") do
|
||||
assert_true FileTest.symlink?($mrbtest_io_symlinkname)
|
||||
begin
|
||||
assert_true FileTest.symlink?($mrbtest_io_symlinkname)
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
assert("FileTest.zero?") do
|
||||
|
||||
+53
-41
@@ -359,15 +359,19 @@ assert('IO#gets - paragraph mode') do
|
||||
end
|
||||
|
||||
assert('IO.popen') do
|
||||
io = IO.popen("ls")
|
||||
assert_true io.close_on_exec?
|
||||
assert_equal Fixnum, io.pid.class
|
||||
ls = io.read
|
||||
assert_equal ls.class, String
|
||||
assert_include ls, 'AUTHORS'
|
||||
assert_include ls, 'mrblib'
|
||||
io.close
|
||||
io.closed?
|
||||
begin
|
||||
io = IO.popen("ls")
|
||||
assert_true io.close_on_exec?
|
||||
assert_equal Fixnum, io.pid.class
|
||||
ls = io.read
|
||||
assert_equal ls.class, String
|
||||
assert_include ls, 'AUTHORS'
|
||||
assert_include ls, 'mrblib'
|
||||
io.close
|
||||
io.closed?
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
assert('IO.read') do
|
||||
@@ -450,43 +454,51 @@ assert('IO#sysseek') do
|
||||
end
|
||||
|
||||
assert('IO.pipe') do
|
||||
called = false
|
||||
IO.pipe do |r, w|
|
||||
assert_true r.kind_of?(IO)
|
||||
assert_true w.kind_of?(IO)
|
||||
assert_false r.closed?
|
||||
assert_false w.closed?
|
||||
assert_true FileTest.pipe?(r)
|
||||
assert_true FileTest.pipe?(w)
|
||||
assert_nil r.pid
|
||||
assert_nil w.pid
|
||||
assert_true 2 < r.fileno
|
||||
assert_true 2 < w.fileno
|
||||
assert_true r.fileno != w.fileno
|
||||
assert_false r.sync
|
||||
assert_true w.sync
|
||||
assert_equal 8, w.write('test for')
|
||||
assert_equal 'test', r.read(4)
|
||||
assert_equal ' for', r.read(4)
|
||||
assert_equal 5, w.write(' pipe')
|
||||
assert_equal nil, w.close
|
||||
assert_equal ' pipe', r.read
|
||||
called = true
|
||||
assert_raise(IOError) { r.write 'test' }
|
||||
# TODO:
|
||||
# This assert expect raise IOError but got RuntimeError
|
||||
# Because mruby-io not have flag for I/O readable
|
||||
# assert_raise(IOError) { w.read }
|
||||
end
|
||||
assert_true called
|
||||
begin
|
||||
called = false
|
||||
IO.pipe do |r, w|
|
||||
assert_true r.kind_of?(IO)
|
||||
assert_true w.kind_of?(IO)
|
||||
assert_false r.closed?
|
||||
assert_false w.closed?
|
||||
assert_true FileTest.pipe?(r)
|
||||
assert_true FileTest.pipe?(w)
|
||||
assert_nil r.pid
|
||||
assert_nil w.pid
|
||||
assert_true 2 < r.fileno
|
||||
assert_true 2 < w.fileno
|
||||
assert_true r.fileno != w.fileno
|
||||
assert_false r.sync
|
||||
assert_true w.sync
|
||||
assert_equal 8, w.write('test for')
|
||||
assert_equal 'test', r.read(4)
|
||||
assert_equal ' for', r.read(4)
|
||||
assert_equal 5, w.write(' pipe')
|
||||
assert_equal nil, w.close
|
||||
assert_equal ' pipe', r.read
|
||||
called = true
|
||||
assert_raise(IOError) { r.write 'test' }
|
||||
# TODO:
|
||||
# This assert expect raise IOError but got RuntimeError
|
||||
# Because mruby-io not have flag for I/O readable
|
||||
# assert_raise(IOError) { w.read }
|
||||
end
|
||||
assert_true called
|
||||
|
||||
assert_nothing_raised do
|
||||
IO.pipe { |r, w| r.close; w.close }
|
||||
assert_nothing_raised do
|
||||
IO.pipe { |r, w| r.close; w.close }
|
||||
end
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
assert('`cmd`') do
|
||||
assert_equal `echo foo`, "foo\n"
|
||||
begin
|
||||
assert_equal `echo foo`, "foo\n"
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
assert('IO TEST CLEANUP') do
|
||||
|
||||
Reference in New Issue
Block a user