summaryrefslogtreecommitdiff
path: root/lib/pathname.rb
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-12-21 07:28:59 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-12-21 07:28:59 +0000
commit3e67076db01cbc53486e51f4b455220c9e4a3890 (patch)
tree5d245add08453c7d04d0eba6b3d0a42b39c47b6f /lib/pathname.rb
parentda99e407fbf36051bf9ebce01418589bff557298 (diff)
lib/pathname.rb (Pathname#+): re-implemented to resolve ".." in
beginning of the argument. (Pathname#join): concatenate from the last argument. (Pathname#parent): just use Pathname#+. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/pathname.rb')
-rw-r--r--lib/pathname.rb88
1 files changed, 61 insertions, 27 deletions
diff --git a/lib/pathname.rb b/lib/pathname.rb
index 0cd0c9a377..bf4dcf4d94 100644
--- a/lib/pathname.rb
+++ b/lib/pathname.rb
@@ -173,14 +173,9 @@ class Pathname
# parent method returns parent directory.
#
- # If self is `.', `..' is returned.
- # Otherwise, `..' is joined to self.
+ # This is same as self + '..'.
def parent
- if @path == '.'
- Pathname.new('..')
- else
- self.join('..')
- end
+ self + '..'
end
# mountpoint? method returns true if self points a mountpoint.
@@ -222,22 +217,37 @@ class Pathname
@path.scan(%r{[^/]+}) { yield $& }
end
- # Pathname#+ return new pathname which is concatenated with self and
- # an argument.
- # If self is the current working directory `.' or
- # the argument is absolute pathname,
- # the argument is just returned.
- # If the argument is `.', self is returned.
+ # Pathname#+ concatenates self and an argument.
+ # I.e. a result is basically same as the argument but the base directory
+ # is changed to self if the argument is relative.
+ #
+ # Pathname#+ doesn't access actual filesystem.
def +(other)
other = Pathname.new(other) unless Pathname === other
- if @path == '.' || other.absolute?
- other
- elsif other.to_s == '.'
- self
- elsif %r{/\z} =~ @path
- Pathname.new(@path + other.to_s)
+
+ 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?
+ end
+ if %r{\A/+\z} =~ path1
+ while m2 = %r{\A\.\.(?:/+|\z)}.match(path2)
+ path2 = '.' if (path2 = m2.post_match).empty?
+ end
+ end
+
+ return Pathname.new(path2) if path1 == '.'
+ return Pathname.new(path1) if path2 == '.'
+
+ if %r{/\z} =~ path1
+ Pathname.new(path1 + path2)
else
- Pathname.new(@path + '/' + other.to_s)
+ Pathname.new(path1 + '/' + path2)
end
end
@@ -245,8 +255,16 @@ class Pathname
#
# path0.join(path1, ... pathN) is same as path0 + path1 + ... + pathN.
def join(*args)
- args.map! {|arg| Pathname === arg ? arg : Pathname.new(arg) }
- args.inject(self) {|pathname, arg| pathname + arg }
+ args.unshift self
+ result = args.pop
+ result = Pathname.new(result) unless Pathname === result
+ return result if result.absolute?
+ args.reverse_each {|arg|
+ arg = Pathname.new(arg) unless Pathname === arg
+ result = arg + result
+ return result if result.absolute?
+ }
+ result
end
# Pathname#children returns the children of the directory as an array of
@@ -739,12 +757,28 @@ if $0 == __FILE__
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_equal(Pathname.new('a/b'), Pathname.new('a') + Pathname.new('b'))
- assert_equal(Pathname.new('a'), Pathname.new('a') + Pathname.new('.'))
- assert_equal(Pathname.new('b'), Pathname.new('.') + Pathname.new('b'))
- assert_equal(Pathname.new('.'), Pathname.new('.') + Pathname.new('.'))
- assert_equal(Pathname.new('/b'), Pathname.new('a') + Pathname.new('/b'))
+ 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('/c', '/', '../c')
+ assert_pathname_plus('c', 'a', '../c')
+ assert_pathname_plus('a/c', 'a/b', '../c')
end
end
end