1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* lib/pathname.rb (Pathname#realdirpath): new method.

[ruby-dev:36290]



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21904 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2009-01-30 12:50:55 +00:00
parent 7a4a31064a
commit e94e674d0e
4 changed files with 89 additions and 21 deletions

View file

@ -1,3 +1,8 @@
Fri Jan 30 21:49:32 2009 Tanaka Akira <akr@fsij.org>
* lib/pathname.rb (Pathname#realdirpath): new method.
[ruby-dev:36290]
Fri Jan 30 18:04:23 2009 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (rb_w32_write): limit write size to 32KB if the file

3
NEWS
View file

@ -85,6 +85,9 @@ with all sufficient information, see the ChangeLog file.
socket option name and shutdown's how argument can be specified as a
string/symbol.
* pathname
* realdirpath
=== Compatibility issues (excluding feature bug fixes)
* Enumerator#rewind

View file

@ -76,9 +76,9 @@
#
# === Core methods
#
# These methods are effectively manipulating a String, because that's all a path
# is. Except for #mountpoint?, #children, and #realpath, they don't access the
# filesystem.
# These methods are effectively manipulating a String, because that's
# all a path is. Except for #mountpoint?, #children, #realdirpath
# and #realpath, they don't access the filesystem.
#
# - +
# - #join
@ -90,6 +90,7 @@
# - #each_filename
# - #cleanpath
# - #realpath
# - #realdirpath
# - #children
# - #mountpoint?
#
@ -411,7 +412,7 @@ class Pathname
end
private :cleanpath_conservative
def realpath_rec(prefix, unresolved, h)
def realpath_rec(prefix, unresolved, h, strict, last = true)
resolved = []
until unresolved.empty?
n = unresolved.shift
@ -428,14 +429,20 @@ class Pathname
prefix, *resolved = h[path]
end
else
s = File.lstat(path)
begin
s = File.lstat(path)
rescue Errno::ENOENT => e
raise e if strict || !last || !unresolved.empty?
resolved << n
break
end
if s.symlink?
h[path] = :resolving
link_prefix, link_names = split_names(File.readlink(path))
if link_prefix == ''
prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h)
prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h, strict, unresolved.empty?)
else
prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h)
prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h, strict, unresolved.empty?)
end
else
resolved << n
@ -448,22 +455,40 @@ class Pathname
end
private :realpath_rec
#
# Returns a real (absolute) pathname of +self+ in the actual filesystem.
# The real pathname doesn't contain symlinks or useless dots.
#
# No arguments should be given; the old behaviour is *obsoleted*.
#
def realpath
def real_path_internal(strict = false)
path = @path
prefix, names = split_names(path)
if prefix == ''
prefix, names2 = split_names(Dir.pwd)
names = names2 + names
end
prefix, *names = realpath_rec(prefix, names, {})
prefix, *names = realpath_rec(prefix, names, {}, strict)
self.class.new(prepend_prefix(prefix, File.join(*names)))
end
private :real_path_internal
#
# Returns the real (absolute) pathname of +self+ in the actual
# filesystem not containing symlinks or useless dots.
#
# All components of the pathname must exist when this method is
# called.
#
# No arguments should be given; the old behaviour is *obsoleted*.
#
def realpath
real_path_internal(true)
end
#
# Returns the real (absolute) pathname of +self+ in the actual filesystem.
# The real pathname doesn't contain symlinks or useless dots.
#
# The last component of the real pathname can be nonexistent.
#
def realdirpath
real_path_internal(false)
end
# #parent returns the parent directory.
#

View file

@ -278,24 +278,37 @@ class TestPathname < Test::Unit::TestCase
}
end
def has_symlink?
begin
File.symlink(nil, nil)
rescue NotImplementedError
return false
rescue TypeError
end
return true
end
def realpath(path)
Pathname.new(path).realpath.to_s
end
def test_realpath
begin
File.symlink(nil, nil)
rescue NotImplementedError
return
rescue TypeError
end
return if !has_symlink?
with_tmpchdir('rubytest-pathname') {|dir|
assert_raise(Errno::ENOENT) { realpath("#{dir}/not-exist") }
File.symlink("not-exist-target", "#{dir}/not-exist")
assert_raise(Errno::ENOENT) { realpath("#{dir}/not-exist") }
File.symlink("loop", "#{dir}/loop")
assert_raise(Errno::ELOOP) { realpath("#{dir}/loop") }
File.symlink("../#{File.basename(dir)}/./not-exist-target", "#{dir}/not-exist2")
assert_raise(Errno::ENOENT) { realpath("#{dir}/not-exist2") }
File.open("#{dir}/exist-target", "w") {}
File.symlink("../#{File.basename(dir)}/./exist-target", "#{dir}/exist2")
assert_nothing_raised { realpath("#{dir}/exist2") }
File.symlink("loop-relative", "loop-relative")
assert_raise(Errno::ELOOP) { realpath("#{dir}/loop-relative") }
@ -332,6 +345,28 @@ class TestPathname < Test::Unit::TestCase
}
end
def realdirpath(path)
Pathname.new(path).realdirpath.to_s
end
def test_realdirpath
return if !has_symlink?
Dir.mktmpdir('rubytest-pathname') {|dir|
rdir = realpath(dir)
assert_equal("#{rdir}/not-exist", realdirpath("#{dir}/not-exist"))
assert_raise(Errno::ENOENT) { realdirpath("#{dir}/not-exist/not-exist-child") }
File.symlink("not-exist-target", "#{dir}/not-exist")
assert_equal("#{rdir}/not-exist-target", realdirpath("#{dir}/not-exist"))
File.symlink("../#{File.basename(dir)}/./not-exist-target", "#{dir}/not-exist2")
assert_equal("#{rdir}/not-exist-target", realdirpath("#{dir}/not-exist2"))
File.open("#{dir}/exist-target", "w") {}
File.symlink("../#{File.basename(dir)}/./exist-target", "#{dir}/exist")
assert_equal("#{rdir}/exist-target", realdirpath("#{dir}/exist"))
File.symlink("loop", "#{dir}/loop")
assert_raise(Errno::ELOOP) { realdirpath("#{dir}/loop") }
}
end
def descend(path)
Pathname.new(path).enum_for(:descend).map {|v| v.to_s }
end