diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-11-26 20:43:08 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-11-26 20:43:08 +0000 |
commit | 66283e1c0fff38f9a814603e7171a1121d5f436a (patch) | |
tree | 29516012d5b44a1f8a831e01e844602c6c1ff92d /lib/pathname.rb | |
parent | 14a0dd769e8869ecd76c95461c3d60311a7bf8e3 (diff) | |
download | ruby-66283e1c0fff38f9a814603e7171a1121d5f436a.tar.gz |
* lib/pathname.rb: use File.basename to decompose pathnames.
experimental Windows support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/pathname.rb')
-rw-r--r-- | lib/pathname.rb | 762 |
1 files changed, 235 insertions, 527 deletions
diff --git a/lib/pathname.rb b/lib/pathname.rb index e4e2b01992..c81a70562b 100644 --- a/lib/pathname.rb +++ b/lib/pathname.rb @@ -15,8 +15,8 @@ # == Pathname # # Pathname represents a pathname which locates a file in a filesystem. -# It supports only Unix style pathnames. It does not represent the file -# itself. A Pathname can be relative or absolute. It's not until you try to +# It does not represent the file itself. +# A Pathname can be relative or absolute. It's not until you try to # reference the file that it even matters whether the file exists or not. # # Pathname is immutable. It has no method for destructive update. @@ -240,6 +240,47 @@ class Pathname Pathname.new(@path.sub(pattern, *rest, &block)) end + if File::ALT_SEPARATOR + SEPARATOR_PAT = /[#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}]/ + else + SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/ + end + + # chop_basename(path) -> [pre-basename, basename] or nil + def chop_basename(path) + base = File.basename(path) + if /\A#{SEPARATOR_PAT}?\z/ =~ base + return nil + else + return path[0, path.rindex(base)], base + end + end + private :chop_basename + + # split_names(path) -> prefix, [name, ...] + def split_names(path) + names = [] + while r = chop_basename(path) + path, basename = r + names.unshift basename + end + return path, names + end + private :split_names + + def prepend_prefix(prefix, relpath) + if relpath.empty? + File.dirname(prefix) + elsif /#{SEPARATOR_PAT}/ =~ prefix + prefix = File.dirname(prefix) + prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a' + prefix + relpath + else + prefix + relpath + end + end + private :prepend_prefix + # Returns clean pathname of +self+ with consecutive slashes and useless dots # removed. The filesystem is not accessed. # @@ -261,118 +302,142 @@ class Pathname # Nothing more, nothing less. # def cleanpath_aggressive - # cleanpath_aggressive assumes: - # * no symlink - # * all pathname prefix contained in the pathname is existing directory - return Pathname.new('') if @path == '' - absolute = absolute? + path = @path names = [] - @path.scan(%r{[^/]+}) {|name| - next if name == '.' - if name == '..' - if names.empty? - next if absolute + pre = path + while r = chop_basename(pre) + pre, base = r + case base + when '.' + when '..' + names.unshift base + else + if names[0] == '..' + names.shift else - if names.last != '..' - names.pop - next - end + names.unshift base end end - names << name - } - return Pathname.new(absolute ? '/' : '.') if names.empty? - path = absolute ? '/' : '' - path << names.join('/') - Pathname.new(path) + end + if /#{SEPARATOR_PAT}/o =~ File.basename(pre) + names.shift while names[0] == '..' + end + Pathname.new(prepend_prefix(pre, File.join(*names))) end private :cleanpath_aggressive - def cleanpath_conservative - return Pathname.new('') if @path == '' - names = @path.scan(%r{[^/]+}) - last_dot = names.last == '.' - names.delete('.') - names.shift while names.first == '..' if absolute? - return Pathname.new(absolute? ? '/' : '.') if names.empty? - path = absolute? ? '/' : '' - path << names.join('/') - if names.last != '..' - if last_dot - path << '/.' - elsif %r{/\z} =~ @path - path << '/' - end + # has_trailing_separator?(path) -> bool + def has_trailing_separator?(path) + if r = chop_basename(path) + pre, basename = r + pre.length + basename.length < path.length + else + false end - Pathname.new(path) end - private :cleanpath_conservative + private :has_trailing_separator? - # - # 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(*args) - unless args.empty? - warn "The argument for Pathname#realpath is obsoleted." + # add_trailing_separator(path) -> path + def add_trailing_separator(path) + if File.basename(path + 'a') == 'a' + path + else + File.join(path, "") # xxx: Is File.join is appropriate to add separator? end - force_absolute = args.fetch(0, true) - - if %r{\A/} =~ @path - top = '/' - unresolved = @path.scan(%r{[^/]+}) - elsif force_absolute - # Although POSIX getcwd returns a pathname which contains no symlink, - # 4.4BSD-Lite2 derived getcwd may return the environment variable $PWD - # which may contain a symlink. - # So the return value of Dir.pwd should be examined. - top = '/' - unresolved = Dir.pwd.scan(%r{[^/]+}) + @path.scan(%r{[^/]+}) + end + private :add_trailing_separator + + def del_trailing_separator(path) + if r = chop_basename(path) + pre, basename = r + pre + basename + elsif /#{SEPARATOR_PAT}+\z/o =~ path + $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o] else - top = '' - unresolved = @path.scan(%r{[^/]+}) + path end - resolved = [] + end + private :del_trailing_separator + + def cleanpath_conservative + path = @path + names = [] + pre = path + while r = chop_basename(pre) + pre, base = r + names.unshift base if base != '.' + end + if /#{SEPARATOR_PAT}/o =~ File.basename(pre) + names.shift while names[0] == '..' + end + if names.empty? + File.dirname(pre) + else + if names.last != '..' && File.basename(path) == '.' + names << '.' + end + result = prepend_prefix(pre, File.join(*names)) + if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path) + Pathname.new(add_trailing_separator(result)) + else + Pathname.new(result) + end + end + end + private :cleanpath_conservative + def realpath_rec(prefix, unresolved, h) + resolved = [] until unresolved.empty? - case unresolved.last - when '.' - unresolved.pop - when '..' - resolved.unshift unresolved.pop + n = unresolved.shift + if n == '.' + next + elsif n == '..' + resolved.pop else - loop_check = {} - while (stat = File.lstat(path = top + unresolved.join('/'))).symlink? - symlink_id = "#{stat.dev}:#{stat.ino}" - raise Errno::ELOOP.new(path) if loop_check[symlink_id] - loop_check[symlink_id] = true - if %r{\A/} =~ (link = File.readlink(path)) - top = '/' - unresolved = link.scan(%r{[^/]+}) + path = prepend_prefix(prefix, File.join(*(resolved + [n]))) + if h.include? path + if h[path] == :resolving + raise Errno::ELOOP.new(path) else - unresolved[-1,1] = link.scan(%r{[^/]+}) + prefix, *resolved = h[path] end - end - next if (filename = unresolved.pop) == '.' - if filename != '..' && resolved.first == '..' - resolved.shift else - resolved.unshift filename + s = File.lstat(path) + 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) + else + prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h) + end + else + resolved << n + h[path] = [prefix, *resolved] + end end end end + return prefix, *resolved + end + private :realpath_rec - if top == '/' - resolved.shift while resolved[0] == '..' - end - - if resolved.empty? - Pathname.new(top.empty? ? '.' : '/') - else - Pathname.new(top + resolved.join('/')) + # + # 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 + 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, {}) + Pathname.new(prepend_prefix(prefix, File.join(*names))) end # #parent returns the parent directory. @@ -402,18 +467,22 @@ class Pathname # pathnames which points to roots such as <tt>/usr/..</tt>. # def root? - %r{\A/+\z} =~ @path ? true : false + !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path) end # Predicate method for testing whether a path is absolute. # It returns +true+ if the pathname begins with a slash. def absolute? - %r{\A/} =~ @path ? true : false + !relative? end # The opposite of #absolute? def relative? - !absolute? + path = @path + while r = chop_basename(path) + path, basename = r + end + path == '' end # @@ -423,7 +492,7 @@ class Pathname # # yields "usr", "bin", and "ruby". # def each_filename # :yield: s - @path.scan(%r{[^/]+}) { yield $& } + split_names(@path).each {|filename| yield filename } end # Iterates over and yields a new Pathname object @@ -445,22 +514,9 @@ class Pathname # It doesn't access actual filesystem. # def descend - paths = [] - v = self - if absolute? - until v.root? - paths << v - v = v.dirname - end - paths << v - else - until v.basename == v - paths << v - v = v.dirname - end - paths << v - end - paths.reverse_each {|path| yield path } + vs = [] + ascend {|v| vs << v } + vs.reverse_each {|v| yield v } end # Iterates over and yields a new Pathname object @@ -482,22 +538,13 @@ class Pathname # It doesn't access actual filesystem. # def ascend - paths = [] - v = self - if absolute? - until v.root? - paths << v - v = v.dirname - end - paths << v - else - until v.basename == v - paths << v - v = v.dirname - end - paths << v + path = @path + yield self + while r = chop_basename(path) + path, name = r + break if path.empty? + yield Pathname.new(del_trailing_separator(path)) end - paths.each {|path| yield path } end # @@ -512,30 +559,47 @@ class Pathname # def +(other) other = Pathname.new(other) unless Pathname === other + Pathname.new(plus(@path, other.to_s)) + end - return other if other.absolute? - - path1 = @path - path2 = other.to_s - while m2 = %r{\A\.\.(?:/+|\z)}.match(path2) and - m1 = %r{(\A|/+)([^/]+)\z}.match(path1) and - %r{\A(?:\.|\.\.)\z} !~ m1[2] - path1 = m1[1].empty? ? '.' : '/' if (path1 = m1.pre_match).empty? - path2 = '.' if (path2 = m2.post_match).empty? + def plus(path1, path2) # -> path + prefix2 = path2 + index_list2 = [] + basename_list2 = [] + while r2 = chop_basename(prefix2) + prefix2, basename2 = r2 + index_list2.unshift prefix2.length + basename_list2.unshift basename2 end - if %r{\A/+\z} =~ path1 - while m2 = %r{\A\.\.(?:/+|\z)}.match(path2) - path2 = '.' if (path2 = m2.post_match).empty? + return path2 if prefix2 != '' + prefix1 = path1 + while true + while !basename_list2.empty? && basename_list2.first == '.' + index_list2.shift + basename_list2.shift end + break unless r1 = chop_basename(prefix1) + prefix1, basename1 = r1 + next if basename1 == '.' + if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..' + prefix1 = prefix1 + basename1 + break + end + index_list2.shift + basename_list2.shift end - - return Pathname.new(path2) if path1 == '.' - return Pathname.new(path1) if path2 == '.' - - if %r{/\z} =~ path1 - Pathname.new(path1 + path2) + r1 = chop_basename(prefix1) + if !r1 && /#{SEPARATOR_PAT}/o =~ File.basename(prefix1) + while !basename_list2.empty? && basename_list2.first == '..' + index_list2.shift + basename_list2.shift + end + end + if !basename_list2.empty? + suffix2 = path2[index_list2.first..-1] + r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2 else - Pathname.new(path1 + '/' + path2) + r1 ? prefix1 : File.dirname(prefix1) end end @@ -605,44 +669,42 @@ class Pathname # This method has existed since 1.8.1. # def relative_path_from(base_directory) - if self.absolute? != base_directory.absolute? - raise ArgumentError, - "relative path between absolute and relative path: #{self.inspect}, #{base_directory.inspect}" + dest_directory = self.cleanpath.to_s + base_directory = base_directory.cleanpath.to_s + dest_prefix = dest_directory + dest_names = [] + while r = chop_basename(dest_prefix) + dest_prefix, basename = r + dest_names.unshift basename if basename != '.' end - - dest = [] - self.cleanpath.each_filename {|f| - next if f == '.' - dest << f - } - - base = [] - base_directory.cleanpath.each_filename {|f| - next if f == '.' - base << f - } - - while !base.empty? && !dest.empty? && base[0] == dest[0] - base.shift - dest.shift + base_prefix = base_directory + base_names = [] + while r = chop_basename(base_prefix) + base_prefix, basename = r + base_names.unshift basename if basename != '.' end - - if base.include? '..' + if dest_prefix != base_prefix + raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}" + end + while !dest_names.empty? && + !base_names.empty? && + dest_names.first == base_names.first + dest_names.shift + base_names.shift + end + if base_names.include? '..' raise ArgumentError, "base_directory has ..: #{base_directory.inspect}" end - - base.fill '..' - relpath = base + dest - if relpath.empty? - Pathname.new(".") + base_names.fill('..') + relpath_names = base_names + dest_names + if relpath_names.empty? + Pathname.new('.') else - Pathname.new(relpath.join('/')) + Pathname.new(File.join(*relpath_names)) end end - end - class Pathname # * IO * # # #each_line iterates over the line in the file. It yields a String object @@ -966,357 +1028,3 @@ class Pathname # * mixed * end end end - -if $0 == __FILE__ - require 'test/unit' - - class PathnameTest < Test::Unit::TestCase # :nodoc: - def test_initialize - p1 = Pathname.new('a') - assert_equal('a', p1.to_s) - p2 = Pathname.new(p1) - assert_equal(p1, p2) - end - - class AnotherStringLike # :nodoc: - def initialize(s) @s = s end - def to_str() @s end - def ==(other) @s == other end - end - - def test_equality - obj = Pathname.new("a") - str = "a" - sym = :a - ano = AnotherStringLike.new("a") - assert_equal(false, obj == str) - assert_equal(false, str == obj) - assert_equal(false, obj == ano) - assert_equal(false, ano == obj) - assert_equal(false, obj == sym) - assert_equal(false, sym == obj) - - obj2 = Pathname.new("a") - assert_equal(true, obj == obj2) - assert_equal(true, obj === obj2) - assert_equal(true, obj.eql?(obj2)) - end - - def test_hashkey - h = {} - h[Pathname.new("a")] = 1 - h[Pathname.new("a")] = 2 - assert_equal(1, h.size) - end - - def assert_pathname_cmp(e, s1, s2) - p1 = Pathname.new(s1) - p2 = Pathname.new(s2) - r = p1 <=> p2 - assert(e == r, - "#{p1.inspect} <=> #{p2.inspect}: <#{e}> expected but was <#{r}>") - end - def test_comparison - assert_pathname_cmp( 0, "a", "a") - assert_pathname_cmp( 1, "b", "a") - assert_pathname_cmp(-1, "a", "b") - ss = %w( - a - a/ - a/b - a. - a0 - ) - s1 = ss.shift - ss.each {|s2| - assert_pathname_cmp(-1, s1, s2) - s1 = s2 - } - end - - def test_comparison_string - assert_equal(nil, Pathname.new("a") <=> "a") - assert_equal(nil, "a" <=> Pathname.new("a")) - end - - def test_syntactical - assert_equal(true, Pathname.new("/").root?) - assert_equal(true, Pathname.new("//").root?) - assert_equal(true, Pathname.new("///").root?) - assert_equal(false, Pathname.new("").root?) - assert_equal(false, Pathname.new("a").root?) - end - - def test_cleanpath - assert_equal('/', Pathname.new('/').cleanpath(true).to_s) - assert_equal('/', Pathname.new('//').cleanpath(true).to_s) - assert_equal('', Pathname.new('').cleanpath(true).to_s) - - assert_equal('.', Pathname.new('.').cleanpath(true).to_s) - assert_equal('..', Pathname.new('..').cleanpath(true).to_s) - assert_equal('a', Pathname.new('a').cleanpath(true).to_s) - assert_equal('/', Pathname.new('/.').cleanpath(true).to_s) - assert_equal('/', Pathname.new('/..').cleanpath(true).to_s) - assert_equal('/a', Pathname.new('/a').cleanpath(true).to_s) - assert_equal('.', Pathname.new('./').cleanpath(true).to_s) - assert_equal('..', Pathname.new('../').cleanpath(true).to_s) - assert_equal('a/', Pathname.new('a/').cleanpath(true).to_s) - - assert_equal('a/b', Pathname.new('a//b').cleanpath(true).to_s) - assert_equal('a/.', Pathname.new('a/.').cleanpath(true).to_s) - assert_equal('a/.', Pathname.new('a/./').cleanpath(true).to_s) - assert_equal('a/..', Pathname.new('a/../').cleanpath(true).to_s) - assert_equal('/a/.', Pathname.new('/a/.').cleanpath(true).to_s) - assert_equal('..', Pathname.new('./..').cleanpath(true).to_s) - assert_equal('..', Pathname.new('../.').cleanpath(true).to_s) - assert_equal('..', Pathname.new('./../').cleanpath(true).to_s) - assert_equal('..', Pathname.new('.././').cleanpath(true).to_s) - assert_equal('/', Pathname.new('/./..').cleanpath(true).to_s) - assert_equal('/', Pathname.new('/../.').cleanpath(true).to_s) - assert_equal('/', Pathname.new('/./../').cleanpath(true).to_s) - assert_equal('/', Pathname.new('/.././').cleanpath(true).to_s) - - assert_equal('a/b/c', Pathname.new('a/b/c').cleanpath(true).to_s) - assert_equal('b/c', Pathname.new('./b/c').cleanpath(true).to_s) - assert_equal('a/c', Pathname.new('a/./c').cleanpath(true).to_s) - assert_equal('a/b/.', Pathname.new('a/b/.').cleanpath(true).to_s) - assert_equal('a/..', Pathname.new('a/../.').cleanpath(true).to_s) - - assert_equal('/a', Pathname.new('/../.././../a').cleanpath(true).to_s) - assert_equal('a/b/../../../../c/../d', - Pathname.new('a/b/../../../../c/../d').cleanpath(true).to_s) - end - - def test_cleanpath_no_symlink - assert_equal('/', Pathname.new('/').cleanpath.to_s) - assert_equal('/', Pathname.new('//').cleanpath.to_s) - assert_equal('', Pathname.new('').cleanpath.to_s) - - assert_equal('.', Pathname.new('.').cleanpath.to_s) - assert_equal('..', Pathname.new('..').cleanpath.to_s) - assert_equal('a', Pathname.new('a').cleanpath.to_s) - assert_equal('/', Pathname.new('/.').cleanpath.to_s) - assert_equal('/', Pathname.new('/..').cleanpath.to_s) - assert_equal('/a', Pathname.new('/a').cleanpath.to_s) - assert_equal('.', Pathname.new('./').cleanpath.to_s) - assert_equal('..', Pathname.new('../').cleanpath.to_s) - assert_equal('a', Pathname.new('a/').cleanpath.to_s) - - assert_equal('a/b', Pathname.new('a//b').cleanpath.to_s) - assert_equal('a', Pathname.new('a/.').cleanpath.to_s) - assert_equal('a', Pathname.new('a/./').cleanpath.to_s) - assert_equal('.', Pathname.new('a/../').cleanpath.to_s) - assert_equal('/a', Pathname.new('/a/.').cleanpath.to_s) - assert_equal('..', Pathname.new('./..').cleanpath.to_s) - assert_equal('..', Pathname.new('../.').cleanpath.to_s) - assert_equal('..', Pathname.new('./../').cleanpath.to_s) - assert_equal('..', Pathname.new('.././').cleanpath.to_s) - assert_equal('/', Pathname.new('/./..').cleanpath.to_s) - assert_equal('/', Pathname.new('/../.').cleanpath.to_s) - assert_equal('/', Pathname.new('/./../').cleanpath.to_s) - assert_equal('/', Pathname.new('/.././').cleanpath.to_s) - - assert_equal('a/b/c', Pathname.new('a/b/c').cleanpath.to_s) - assert_equal('b/c', Pathname.new('./b/c').cleanpath.to_s) - assert_equal('a/c', Pathname.new('a/./c').cleanpath.to_s) - assert_equal('a/b', Pathname.new('a/b/.').cleanpath.to_s) - assert_equal('.', Pathname.new('a/../.').cleanpath.to_s) - - assert_equal('/a', Pathname.new('/../.././../a').cleanpath.to_s) - assert_equal('../../d', Pathname.new('a/b/../../../../c/../d').cleanpath.to_s) - end - - def test_destructive_update - path = Pathname.new("a") - path.to_s.replace "b" - assert_equal(Pathname.new("a"), path) - end - - def test_null_character - assert_raise(ArgumentError) { Pathname.new("\0") } - end - - def assert_relpath(result, dest, base) - assert_equal(Pathname.new(result), - Pathname.new(dest).relative_path_from(Pathname.new(base))) - end - - def assert_relpath_err(dest, base) - assert_raise(ArgumentError) { - Pathname.new(dest).relative_path_from(Pathname.new(base)) - } - end - - def test_relative_path_from - assert_relpath("../a", "a", "b") - assert_relpath("../a", "a", "b/") - assert_relpath("../a", "a/", "b") - assert_relpath("../a", "a/", "b/") - assert_relpath("../a", "/a", "/b") - assert_relpath("../a", "/a", "/b/") - assert_relpath("../a", "/a/", "/b") - assert_relpath("../a", "/a/", "/b/") - - assert_relpath("../b", "a/b", "a/c") - assert_relpath("../a", "../a", "../b") - - assert_relpath("a", "a", ".") - assert_relpath("..", ".", "a") - - assert_relpath(".", ".", ".") - assert_relpath(".", "..", "..") - assert_relpath("..", "..", ".") - - assert_relpath("c/d", "/a/b/c/d", "/a/b") - assert_relpath("../..", "/a/b", "/a/b/c/d") - assert_relpath("../../../../e", "/e", "/a/b/c/d") - assert_relpath("../b/c", "a/b/c", "a/d") - - assert_relpath("../a", "/../a", "/b") - assert_relpath("../../a", "../a", "b") - assert_relpath(".", "/a/../../b", "/b") - assert_relpath("..", "a/..", "a") - assert_relpath(".", "a/../b", "b") - - assert_relpath("a", "a", "b/..") - assert_relpath("b/c", "b/c", "b/..") - - assert_relpath_err("/", ".") - assert_relpath_err(".", "/") - assert_relpath_err("a", "..") - assert_relpath_err(".", "..") - end - - def assert_pathname_plus(a, b, c) - a = Pathname.new(a) - b = Pathname.new(b) - c = Pathname.new(c) - d = b + c - assert(a == d, - "#{b.inspect} + #{c.inspect}: #{a.inspect} expected but was #{d.inspect}") - end - - def test_plus - assert_pathname_plus('a/b', 'a', 'b') - assert_pathname_plus('a', 'a', '.') - assert_pathname_plus('b', '.', 'b') - assert_pathname_plus('.', '.', '.') - assert_pathname_plus('/b', 'a', '/b') - - assert_pathname_plus('/', '/', '..') - assert_pathname_plus('.', 'a', '..') - assert_pathname_plus('a', 'a/b', '..') - assert_pathname_plus('../..', '..', '..') - assert_pathname_plus('/c', '/', '../c') - assert_pathname_plus('c', 'a', '../c') - assert_pathname_plus('a/c', 'a/b', '../c') - assert_pathname_plus('../../c', '..', '../c') - end - - def test_taint - obj = Pathname.new("a"); assert_same(obj, obj.taint) - obj = Pathname.new("a"); assert_same(obj, obj.untaint) - - assert_equal(false, Pathname.new("a" ) .tainted?) - assert_equal(false, Pathname.new("a" ) .to_s.tainted?) - assert_equal(true, Pathname.new("a" ).taint .tainted?) - assert_equal(true, Pathname.new("a" ).taint.to_s.tainted?) - assert_equal(true, Pathname.new("a".taint) .tainted?) - assert_equal(true, Pathname.new("a".taint) .to_s.tainted?) - assert_equal(true, Pathname.new("a".taint).taint .tainted?) - assert_equal(true, Pathname.new("a".taint).taint.to_s.tainted?) - - str = "a" - path = Pathname.new(str) - str.taint - assert_equal(false, path .tainted?) - assert_equal(false, path.to_s.tainted?) - end - - def test_untaint - obj = Pathname.new("a"); assert_same(obj, obj.untaint) - - assert_equal(false, Pathname.new("a").taint.untaint .tainted?) - assert_equal(false, Pathname.new("a").taint.untaint.to_s.tainted?) - - str = "a".taint - path = Pathname.new(str) - str.untaint - assert_equal(true, path .tainted?) - assert_equal(true, path.to_s.tainted?) - end - - def test_freeze - obj = Pathname.new("a"); assert_same(obj, obj.freeze) - - assert_equal(false, Pathname.new("a" ) .frozen?) - assert_equal(false, Pathname.new("a".freeze) .frozen?) - assert_equal(true, Pathname.new("a" ).freeze .frozen?) - assert_equal(true, Pathname.new("a".freeze).freeze .frozen?) - assert_equal(false, Pathname.new("a" ) .to_s.frozen?) - assert_equal(false, Pathname.new("a".freeze) .to_s.frozen?) - assert_equal(false, Pathname.new("a" ).freeze.to_s.frozen?) - assert_equal(false, Pathname.new("a".freeze).freeze.to_s.frozen?) - end - - def test_to_s - str = "a" - obj = Pathname.new(str) - assert_equal(str, obj.to_s) - assert_not_same(str, obj.to_s) - assert_not_same(obj.to_s, obj.to_s) - end - - def test_kernel_open - count = 0 - stat1 = File.stat(__FILE__) - result = Kernel.open(Pathname.new(__FILE__)) {|f| - stat2 = f.stat - assert_equal(stat1.dev, stat2.dev) - assert_equal(stat1.ino, stat2.ino) - assert_equal(stat1.size, stat2.size) - count += 1 - 2 - } - assert_equal(1, count) - assert_equal(2, result) - end - - def test_descend_abs - rs = %w[/ /a /a/b /a/b/c].map {|s| Pathname.new(s) } - Pathname.new("/a/b/c").descend {|v| assert_equal(rs.shift, v) } - assert_equal([], rs) - end - - def test_descend_rel - rs = %w[a a/b a/b/c].map {|s| Pathname.new(s) } - Pathname.new("a/b/c").descend {|v| assert_equal(rs.shift, v) } - assert_equal([], rs) - end - - def test_descend_rel_with_current_dir - rs = %w[. ./a ./a/b ./a/b/c].map {|s| Pathname.new(s) } - Pathname.new("./a/b/c").descend {|v| assert_equal(rs.shift, v) } - assert_equal([], rs) - end - - def test_ascend_abs - rs = %w[/a/b/c /a/b /a /].map {|s| Pathname.new(s) } - Pathname.new("/a/b/c").ascend {|v| assert_equal(rs.shift, v) } - assert_equal([], rs) - end - - def test_ascend_rel - rs = %w[a/b/c a/b a].map {|s| Pathname.new(s) } - Pathname.new("a/b/c").ascend {|v| assert_equal(rs.shift, v) } - assert_equal([], rs) - end - - def test_ascend_rel_with_current_dir - rs = %w[./a/b/c ./a/b ./a .].map {|s| Pathname.new(s) } - Pathname.new("./a/b/c").ascend {|v| assert_equal(rs.shift, v) } - assert_equal([], rs) - end - - end -end |