Add a host of patches from upstream's tracker for Ruby 1.9.3.
authorHans de Graaff <graaff@gentoo.org>
Fri, 6 Jan 2012 07:35:54 +0000 (07:35 +0000)
committerHans de Graaff <graaff@gentoo.org>
Fri, 6 Jan 2012 07:35:54 +0000 (07:35 +0000)
Package-Manager: portage-2.1.10.41/cvs/Linux x86_64

dev-ruby/fakefs/ChangeLog
dev-ruby/fakefs/Manifest
dev-ruby/fakefs/fakefs-0.4.0-r1.ebuild [new file with mode: 0644]
dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-advise.patch [new file with mode: 0644]
dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-pathname.patch [new file with mode: 0644]
dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-ruby-pathname.patch [new file with mode: 0644]
dev-ruby/fakefs/files/fakefs-0.4.0-ruby193.patch [new file with mode: 0644]

index 4c6f561bfcd59758866dbb55031bc4786866afaf..0fb508ce4510846b05b1cc7c7fe5ab28f44e4fb8 100644 (file)
@@ -1,6 +1,15 @@
 # ChangeLog for dev-ruby/fakefs
-# Copyright 1999-2011 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/dev-ruby/fakefs/ChangeLog,v 1.21 2011/12/05 13:04:28 naota Exp $
+# Copyright 1999-2012 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-x86/dev-ruby/fakefs/ChangeLog,v 1.22 2012/01/06 07:35:54 graaff Exp $
+
+*fakefs-0.4.0-r1 (06 Jan 2012)
+
+  06 Jan 2012; Hans de Graaff <graaff@gentoo.org> +fakefs-0.4.0-r1.ebuild,
+  +files/fakefs-0.4.0-ruby193-advise.patch,
+  +files/fakefs-0.4.0-ruby193-pathname.patch,
+  +files/fakefs-0.4.0-ruby193-ruby-pathname.patch,
+  +files/fakefs-0.4.0-ruby193.patch:
+  Add a host of patches from upstream's tracker for Ruby 1.9.3.
 
   05 Dec 2011; Naohiro Aota <naota@gentoo.org> fakefs-0.2.1-r1.ebuild:
   Add ~x86-fbsd.
index d45baaa559b2b7749babe551419e0a5f6ee34eba..4afd56d5d356eaf122cce22e8d5842fe00b37e9b 100644 (file)
@@ -2,25 +2,21 @@
 Hash: SHA256
 
 AUX fakefs-0.2.1-ruby19.patch 707 RMD160 f0bf05202c07e6b1170904a9effd5fe8143db198 SHA1 eceae253cf102fb5ee011c3048156c8dc6a4c2a6 SHA256 1c63a39d47c862a3a925efd848330898d33572b128355ded235b9e6c16691211
+AUX fakefs-0.4.0-ruby193-advise.patch 1023 RMD160 d90b1234b91d0ee9434c2e58fed2ca82a5fc49fc SHA1 514f580f2654056146593037cb45d3ee3cc1306f SHA256 c84b2a675e269f2f4bc562357d7ef8ab4d6be0350b1fb6ba35af8dbcc3ace5d5
+AUX fakefs-0.4.0-ruby193-pathname.patch 1751 RMD160 6a4220275af41dfe4ded24610d00f081ba1b6d31 SHA1 961e7a526438fd42fceefaeb3d3f00e3f9c70782 SHA256 5d3dc1233d3d296c8e89ff8aa933749284f5b641cd550a86a5e02b36c3ab7f98
+AUX fakefs-0.4.0-ruby193-ruby-pathname.patch 28924 RMD160 7e40775d98a49ab912722aef08c89394a012ea80 SHA1 720ee16279561d4325ef26b01121218e66dce415 SHA256 f97576b29908be04ef27c7f5e29a5575205fabc19d77bfd91070908c18c3e49e
+AUX fakefs-0.4.0-ruby193.patch 6364 RMD160 03b26e6336bba9412af2ff3cc62ca9b605cce147 SHA1 320f4296320002d23e39730763199b7e6a8135ca SHA256 bc365513d05b7b4be5232adabffad5cbd4ff10e7fd2c342594969d63f2740e89
 DIST fakefs-0.2.1.gem 17408 RMD160 0d15c94d7d5864ad72abbcc5509f3eb720de2974 SHA1 7181b2dfaa1b81149ec59cf065577a31d16f7b8e SHA256 1acb4fb80abee462b4c58679bf8d528a9094f79a81ece4c91e7647d6e853517f
+DIST fakefs-0.4.0.gem 24064 RMD160 a58f0fb1f963c47fd318611c64afe996e7c4a7a1 SHA1 2a1a34ec200650b1cdfa04778f251c967248138c SHA256 d5e26fc81facfdcdb5b31732358c6b3d86c8b53c91e2359b9d5b1cc68665b00a
 EBUILD fakefs-0.2.1-r1.ebuild 824 RMD160 8d4a746294f5069096ffd6549771f9ef7755e10e SHA1 942cec74a60859c3c69c0ac2c4849f38ee85ed3b SHA256 d6381365fbc975e63b2d8bbee700168d2db6cd9a18fc44b05baf62ec5123011a
 EBUILD fakefs-0.2.1.ebuild 713 RMD160 d39f556881de25441b0d1d6fb3dd53888e91a297 SHA1 75dc0e3c4c5ea4dc557c8f14da35e6f1ba3a9dd7 SHA256 f282dde87205847b92def2b4e274ee7554a54740e09ae684af694d74259bddaf
-MISC ChangeLog 2627 RMD160 b7d3dceecdcc981a2e41a50470f4c990bec8ce57 SHA1 e267fdce612a4c5a954e1582da3e9a94b7d7a635 SHA256 b40b284a2a14afdebf11b5a18a5fc5f2373b51105b2ad66eef41fa824d972ed6
+EBUILD fakefs-0.4.0-r1.ebuild 1101 RMD160 4bb76ddbdf8ced6fc170244d412726d3fc1cfcbd SHA1 316f45d9c67b9dc9619bd795ae2965bef1bb907f SHA256 b3140eb0b942a4dd627690f8fcdcf5b616494555e0799fabf0e647c2ffc903e6
+MISC ChangeLog 2978 RMD160 413775797d1c09313c52aabe7593be01bc081b56 SHA1 ebb10d439188782e09b2451fd33fcf98ac315006 SHA256 b85e8588df3d8393b48483111466c1e1afc8b59be1ea2ee35677254f51de4643
 MISC metadata.xml 157 RMD160 5d9e2c7ecba96ffebd936d38acedf859cdea84e1 SHA1 8ce15dcc608eeb5616aeec610dc695cbe6f93e02 SHA256 11fba03a217e2d996f5cd8895493a5692ece8ddac2c1a2dfc71d0e830555121c
 -----BEGIN PGP SIGNATURE-----
-Version: GnuPG v2.0.18 (GNU/Linux)
+Version: GnuPG v2.0.17 (GNU/Linux)
 
-iQIcBAEBCAAGBQJO3MFcAAoJEDYO1FT4VRUUYJcP/3JjMlvbTIiOddrJ14Z6DVMz
-T2bRmYHBIrlsCvaI1oMeltS3SpF8KWOmr+A+eQ0EGQPytEOpkxVskrt6PZZMY0uv
-p2XfE5qklmgfozSNyCGmga9JAiscm/j4eUfRCHKE1BWYf70tujjZv/XLsYdAvQnx
-MjybpemJ4xYL/UZV5UGr9yO0ZTigmgXu4X+ndgiBWdikyVYLDDfCDtB2zU4qfjoS
-RPtGW6p0L1G9EJwaxFRNTz+6EaHl66EHOANZktcpRN8ttjmslSuWQeP+E/Qdn5mN
-C5m/bG5ewJhpp2Q3RfZs9P0YHT7eBRwdWuZZB8JZ1pS7GOxBwSHxBhgAdrBkd3UN
-e6tPpqw9urg3MmmS4Zzko14g9d/g7i+56XbarLJF9tliX1VC2unZou2bg6B4ZfjT
-JtzweMZDE3bTzVLX2ZBCQ6nGH1GjoXFLjgRSkWdI4nRGfMGyBtDIVDv3JPs3muJq
-+Z5LpdWG52D/Xfsx87pVuOEPe8wyx/dWgfJ5ZaGa8N1TYUpsH/GRqyk1/GW5mHIm
-wlbB1GCtEGhdZe4Ho4BLhflXcliaGtBrIgsCXs3dU/FRUPFz9t7HglX0yfOBLfqR
-3K1wx8b9fo9PgJOkPmiZPz5TQVLEFfYfri3HNAJBgbnriG2rGGHn4/KNKUCZ1W4N
-2sPQakxY5r6Jnqi3igt/
-=nQ0E
+iF4EAREIAAYFAk8GpGUACgkQiIP6VqMIqNcnWAD8C4yw7xc8Nnlir8CX/rVoiWWR
+XXfR8RgdMc8m3evDNhIA/2chm+QgOHZdxGbQ6zWUC3V1Kfy4Z/2fsKr4/I/4MrD4
+=/f2C
 -----END PGP SIGNATURE-----
diff --git a/dev-ruby/fakefs/fakefs-0.4.0-r1.ebuild b/dev-ruby/fakefs/fakefs-0.4.0-r1.ebuild
new file mode 100644 (file)
index 0000000..303f362
--- /dev/null
@@ -0,0 +1,39 @@
+# Copyright 1999-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-ruby/fakefs/fakefs-0.4.0-r1.ebuild,v 1.1 2012/01/06 07:35:54 graaff Exp $
+
+EAPI=2
+
+# jruby → Marshal/DeMarshal to clone directories fail; tests fail in
+# release 0.2.1
+USE_RUBY="ruby18 ree18 ruby19"
+
+RUBY_FAKEGEM_TASK_TEST="test spec"
+
+# requires sdoc
+RUBY_FAKEGEM_TASK_DOC=""
+
+RUBY_FAKEGEM_EXTRADOC="CONTRIBUTORS README.markdown"
+
+inherit ruby-fakegem eutils
+
+DESCRIPTION="A fake filesystem. Use it in your tests."
+HOMEPAGE="http://github.com/defunkt/fakefs"
+
+LICENSE="as-is" # truly
+SLOT="0"
+KEYWORDS="~amd64 ~hppa ~ia64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~x64-solaris ~x86-solaris"
+IUSE=""
+
+ruby_add_bdepend "test? ( dev-ruby/rspec:2 )"
+
+all_ruby_prepare() {
+       # Remove bundler
+       rm Gemfile || die
+
+       epatch "${FILESDIR}/${P}-ruby193.patch"
+       epatch "${FILESDIR}/${P}-ruby193-advise.patch"
+       epatch "${FILESDIR}/${P}-ruby193-pathname.patch"
+       epatch "${FILESDIR}/${P}-ruby193-ruby-pathname.patch"
+
+}
diff --git a/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-advise.patch b/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-advise.patch
new file mode 100644 (file)
index 0000000..a691002
--- /dev/null
@@ -0,0 +1,42 @@
+commit 332735b52720466ca8eb9e089cc42f128d54b644
+Author: Lukas Oberhuber <lukaso@gmail.com>
+Date:   Tue Dec 20 09:19:05 2011 +0000
+
+    Add advise function to File which is in ruby 1.9.3. As it is only a hint to the
+    os in some cases, the function does nothing.
+
+diff --git a/lib/fakefs/file.rb b/lib/fakefs/file.rb
+index 5684ede..ebc3ff8 100644
+--- a/lib/fakefs/file.rb
++++ b/lib/fakefs/file.rb
+@@ -392,6 +392,11 @@ module FakeFS
+       end
+     end
++    if RUBY_VERSION >= "1.9.3"
++      def advise(advice, offset=0, len=0)
++      end
++    end
++    
+   private
+     def check_modes!
+diff --git a/test/fakefs_test.rb b/test/fakefs_test.rb
+index 0f34950..1d5bf7a 100644
+--- a/test/fakefs_test.rb
++++ b/test/fakefs_test.rb
+@@ -1861,4 +1861,14 @@ class FakeFSTest < Test::Unit::TestCase
+       end
+     end
+   end
++  
++  if RUBY_VERSION >= "1.9.3"
++    def test_advise
++      File.open("foo", 'w') do |f|
++        assert_nothing_raised do
++          f.advise(:normal, 0, 0)
++        end
++      end
++    end
++  end
+ end
diff --git a/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-pathname.patch b/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-pathname.patch
new file mode 100644 (file)
index 0000000..e93cdca
--- /dev/null
@@ -0,0 +1,57 @@
+commit dcc2ad6952e334b91f0f044a1f1083c99949d840
+Author: Lukas Oberhuber <lukaso@gmail.com>
+Date:   Wed Dec 21 16:55:19 2011 +0000
+
+    Substitute Pathname to get tests to pass in ruby 1.9.3
+
+diff --git a/lib/fakefs/base.rb b/lib/fakefs/base.rb
+index 7e83e76..6c1741a 100644
+--- a/lib/fakefs/base.rb
++++ b/lib/fakefs/base.rb
+@@ -2,6 +2,7 @@ RealFile            = File
+ RealFileTest        = FileTest
+ RealFileUtils       = FileUtils
+ RealDir             = Dir
++RealPathname        = Pathname
+ module FakeFS
+   def self.activate!
+@@ -10,11 +11,14 @@ module FakeFS
+       remove_const(:File)
+       remove_const(:FileTest)
+       remove_const(:FileUtils)
++      remove_const(:Pathname) if RUBY_VERSION >= "1.9.3"
++      
+       const_set(:Dir,       FakeFS::Dir)
+       const_set(:File,      FakeFS::File)
+       const_set(:FileUtils, FakeFS::FileUtils)
+       const_set(:FileTest,  FakeFS::FileTest)
++      const_set(:Pathname,  FakeFS::Pathname) if RUBY_VERSION >= "1.9.3"
+     end
+     true
+   end
+@@ -25,11 +29,13 @@ module FakeFS
+       remove_const(:File)
+       remove_const(:FileTest)
+       remove_const(:FileUtils)
++      remove_const(:Pathname) if RUBY_VERSION >= "1.9.3"
+       const_set(:Dir,       RealDir)
+       const_set(:File,      RealFile)
+       const_set(:FileTest,  RealFileTest)
+       const_set(:FileUtils, RealFileUtils)
++      const_set(:Pathname,  RealPathname) if RUBY_VERSION >= "1.9.3"
+     end
+     true
+   end
+diff --git a/lib/fakefs/safe.rb b/lib/fakefs/safe.rb
+index a1b804c..783de74 100644
+--- a/lib/fakefs/safe.rb
++++ b/lib/fakefs/safe.rb
+@@ -9,3 +9,5 @@ require 'fakefs/fileutils'
+ require 'fakefs/file'
+ require 'fakefs/file_test'
+ require 'fakefs/dir'
++require 'fakefs/pathname' if RUBY_VERSION >= "1.9.3"
++
diff --git a/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-ruby-pathname.patch b/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193-ruby-pathname.patch
new file mode 100644 (file)
index 0000000..68b067c
--- /dev/null
@@ -0,0 +1,880 @@
+commit cf580c9274ff774f540b374e07ed348916c14518
+Author: Lukas Oberhuber <lukaso@gmail.com>
+Date:   Wed Dec 21 17:27:26 2011 +0000
+
+    Bumped version.
+    Moved pathname.rb from ruby 1.9.2 into project in order to continue compatibility to 1.9.3 where
+    the functionality has been moved into c. In the c version of the file, the unset_const trick
+    doesn't work because the constant rb_cFile in the c file is never modified. I think this is
+    actually a bug in how ruby MRI operates, but the fix is a little bit complicated.
+
+diff --git a/lib/fakefs/pathname.rb b/lib/fakefs/pathname.rb
+new file mode 100644
+index 0000000..181af36
+--- /dev/null
++++ lib/fakefs/pathname.rb
+@@ -0,0 +1,864 @@
++module FakeFS
++  if RUBY_VERSION >= "1.9.3"
++  
++    #
++    # = pathname.rb - From MRI 1.9.2
++    #
++    # Object-Oriented Pathname Class
++    #
++    # Author:: Tanaka Akira <akr@m17n.org>
++    # Documentation:: Author and Gavin Sinclair
++    #
++    # For documentation, see class Pathname.
++    #
++    class Pathname
++
++      # to_path is implemented so Pathname objects are usable with File.open, etc.
++      TO_PATH = :to_path
++
++      SAME_PATHS = if File::FNM_SYSCASE.nonzero?
++        proc {|a, b| a.casecmp(b).zero?}
++      else
++        proc {|a, b| a == b}
++      end
++
++      # :startdoc:
++
++      #
++      # Create a Pathname object from the given String (or String-like object).
++      # If +path+ contains a NUL character (<tt>\0</tt>), an ArgumentError is raised.
++      #
++      def initialize(path)
++        path = path.__send__(TO_PATH) if path.respond_to? TO_PATH
++        @path = path.dup
++
++        if /\0/ =~ @path
++          raise ArgumentError, "pathname contains \\0: #{@path.inspect}"
++        end
++
++        self.taint if @path.tainted?
++      end
++
++      def freeze() super; @path.freeze; self end
++      def taint() super; @path.taint; self end
++      def untaint() super; @path.untaint; self end
++
++      #
++      # Compare this pathname with +other+.  The comparison is string-based.
++      # Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
++      # can refer to the same file.
++      #
++      def ==(other)
++        return false unless Pathname === other
++        other.to_s == @path
++      end
++      alias === ==
++      alias eql? ==
++
++      # Provides for comparing pathnames, case-sensitively.
++      def <=>(other)
++        return nil unless Pathname === other
++        @path.tr('/', "\0") <=> other.to_s.tr('/', "\0")
++      end
++
++      def hash # :nodoc:
++        @path.hash
++      end
++
++      # Return the path as a String.
++      def to_s
++        @path.dup
++      end
++
++      # to_path is implemented so Pathname objects are usable with File.open, etc.
++      alias_method TO_PATH, :to_s
++
++      def inspect # :nodoc:
++        "#<#{self.class}:#{@path}>"
++      end
++
++      # Return a pathname which is substituted by String#sub.
++      def sub(pattern, *rest, &block)
++        if block
++          path = @path.sub(pattern, *rest) {|*args|
++            begin
++              old = Thread.current[:pathname_sub_matchdata]
++              Thread.current[:pathname_sub_matchdata] = $~
++              eval("$~ = Thread.current[:pathname_sub_matchdata]", block.binding)
++            ensure
++              Thread.current[:pathname_sub_matchdata] = old
++            end
++            yield(*args)
++          }
++        else
++          path = @path.sub(pattern, *rest)
++        end
++        self.class.new(path)
++      end
++
++      if File::ALT_SEPARATOR
++        SEPARATOR_LIST = "#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}"
++        SEPARATOR_PAT = /[#{SEPARATOR_LIST}]/
++      else
++        SEPARATOR_LIST = "#{Regexp.quote File::SEPARATOR}"
++        SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/
++      end
++
++      # Return a pathname which the extension of the basename is substituted by
++      # <i>repl</i>.
++      #
++      # If self has no extension part, <i>repl</i> is appended.
++      def sub_ext(repl)
++        ext = File.extname(@path)
++        self.class.new(@path.chomp(ext) + repl)
++      end
++
++      # chop_basename(path) -> [pre-basename, basename] or nil
++      def chop_basename(path)
++        base = File.basename(path)
++        if /\A#{SEPARATOR_PAT}?\z/o =~ 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}/o =~ 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.
++      #
++      # If +consider_symlink+ is +true+, then a more conservative algorithm is used
++      # to avoid breaking symbolic linkages.  This may retain more <tt>..</tt>
++      # entries than absolutely necessary, but without accessing the filesystem,
++      # this can't be avoided.  See #realpath.
++      #
++      def cleanpath(consider_symlink=false)
++        if consider_symlink
++          cleanpath_conservative
++        else
++          cleanpath_aggressive
++        end
++      end
++
++      #
++      # Clean the path simply by resolving and removing excess "." and ".." entries.
++      # Nothing more, nothing less.
++      #
++      def cleanpath_aggressive
++        path = @path
++        names = []
++        pre = path
++        while r = chop_basename(pre)
++          pre, base = r
++          case base
++          when '.'
++          when '..'
++            names.unshift base
++          else
++            if names[0] == '..'
++              names.shift
++            else
++              names.unshift base
++            end
++          end
++        end
++        if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
++          names.shift while names[0] == '..'
++        end
++        self.class.new(prepend_prefix(pre, File.join(*names)))
++      end
++      private :cleanpath_aggressive
++
++      # 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
++      end
++      private :has_trailing_separator?
++
++      # 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
++      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
++          path
++        end
++      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?
++          self.class.new(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)
++            self.class.new(add_trailing_separator(result))
++          else
++            self.class.new(result)
++          end
++        end
++      end
++      private :cleanpath_conservative
++
++      #
++      # 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.
++      #
++      def realpath(basedir=nil)
++        self.class.new(File.realpath(@path, basedir))
++      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(basedir=nil)
++        self.class.new(File.realdirpath(@path, basedir))
++      end
++
++      # #parent returns the parent directory.
++      #
++      # This is same as <tt>self + '..'</tt>.
++      def parent
++        self + '..'
++      end
++
++      # #mountpoint? returns +true+ if <tt>self</tt> points to a mountpoint.
++      def mountpoint?
++        begin
++          stat1 = self.lstat
++          stat2 = self.parent.lstat
++          stat1.dev == stat2.dev && stat1.ino == stat2.ino ||
++            stat1.dev != stat2.dev
++        rescue Errno::ENOENT
++          false
++        end
++      end
++
++      #
++      # #root? is a predicate for root directories.  I.e. it returns +true+ if the
++      # pathname consists of consecutive slashes.
++      #
++      # It doesn't access actual filesystem.  So it may return +false+ for some
++      # pathnames which points to roots such as <tt>/usr/..</tt>.
++      #
++      def root?
++        !!(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?
++        !relative?
++      end
++
++      # The opposite of #absolute?
++      def relative?
++        path = @path
++        while r = chop_basename(path)
++          path, basename = r
++        end
++        path == ''
++      end
++
++      #
++      # Iterates over each component of the path.
++      #
++      #   Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
++      #     # yields "usr", "bin", and "ruby".
++      #
++      def each_filename # :yield: filename
++        return to_enum(__method__) unless block_given?
++        prefix, names = split_names(@path)
++        names.each {|filename| yield filename }
++        nil
++      end
++
++      # Iterates over and yields a new Pathname object
++      # for each element in the given path in descending order.
++      #
++      #  Pathname.new('/path/to/some/file.rb').descend {|v| p v}
++      #     #<Pathname:/>
++      #     #<Pathname:/path>
++      #     #<Pathname:/path/to>
++      #     #<Pathname:/path/to/some>
++      #     #<Pathname:/path/to/some/file.rb>
++      #
++      #  Pathname.new('path/to/some/file.rb').descend {|v| p v}
++      #     #<Pathname:path>
++      #     #<Pathname:path/to>
++      #     #<Pathname:path/to/some>
++      #     #<Pathname:path/to/some/file.rb>
++      #
++      # It doesn't access actual filesystem.
++      #
++      # This method is available since 1.8.5.
++      #
++      def descend
++        vs = []
++        ascend {|v| vs << v }
++        vs.reverse_each {|v| yield v }
++        nil
++      end
++
++      # Iterates over and yields a new Pathname object
++      # for each element in the given path in ascending order.
++      #
++      #  Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
++      #     #<Pathname:/path/to/some/file.rb>
++      #     #<Pathname:/path/to/some>
++      #     #<Pathname:/path/to>
++      #     #<Pathname:/path>
++      #     #<Pathname:/>
++      #
++      #  Pathname.new('path/to/some/file.rb').ascend {|v| p v}
++      #     #<Pathname:path/to/some/file.rb>
++      #     #<Pathname:path/to/some>
++      #     #<Pathname:path/to>
++      #     #<Pathname:path>
++      #
++      # It doesn't access actual filesystem.
++      #
++      # This method is available since 1.8.5.
++      #
++      def ascend
++        path = @path
++        yield self
++        while r = chop_basename(path)
++          path, name = r
++          break if path.empty?
++          yield self.class.new(del_trailing_separator(path))
++        end
++      end
++
++      #
++      # Pathname#+ appends a pathname fragment to this one to produce a new Pathname
++      # object.
++      #
++      #   p1 = Pathname.new("/usr")      # Pathname:/usr
++      #   p2 = p1 + "bin/ruby"           # Pathname:/usr/bin/ruby
++      #   p3 = p1 + "/etc/passwd"        # Pathname:/etc/passwd
++      #
++      # This method doesn't access the file system; it is pure string manipulation.
++      #
++      def +(other)
++        other = Pathname.new(other) unless Pathname === other
++        Pathname.new(plus(@path, other.to_s))
++      end
++
++      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
++        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
++        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
++          r1 ? prefix1 : File.dirname(prefix1)
++        end
++      end
++      private :plus
++
++      #
++      # Pathname#join joins pathnames.
++      #
++      # <tt>path0.join(path1, ..., pathN)</tt> is the same as
++      # <tt>path0 + path1 + ... + pathN</tt>.
++      #
++      def join(*args)
++        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
++
++      #
++      # Returns the children of the directory (files and subdirectories, not
++      # recursive) as an array of Pathname objects.  By default, the returned
++      # pathnames will have enough information to access the files.  If you set
++      # +with_directory+ to +false+, then the returned pathnames will contain the
++      # filename only.
++      #
++      # For example:
++      #   pn = Pathname("/usr/lib/ruby/1.8")
++      #   pn.children
++      #       # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
++      #              Pathname:/usr/lib/ruby/1.8/Env.rb,
++      #              Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
++      #   pn.children(false)
++      #       # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
++      #
++      # Note that the result never contain the entries <tt>.</tt> and <tt>..</tt> in
++      # the directory because they are not children.
++      #
++      # This method has existed since 1.8.1.
++      #
++      def children(with_directory=true)
++        with_directory = false if @path == '.'
++        result = []
++        Dir.foreach(@path) {|e|
++          next if e == '.' || e == '..'
++          if with_directory
++            result << self.class.new(File.join(@path, e))
++          else
++            result << self.class.new(e)
++          end
++        }
++        result
++      end
++
++      # Iterates over the children of the directory
++      # (files and subdirectories, not recursive).
++      # It yields Pathname object for each child.
++      # By default, the yielded pathnames will have enough information to access the files.
++      # If you set +with_directory+ to +false+, then the returned pathnames will contain the filename only.
++      #
++      #   Pathname("/usr/local").each_child {|f| p f }
++      #   #=> #<Pathname:/usr/local/share>
++      #   #   #<Pathname:/usr/local/bin>
++      #   #   #<Pathname:/usr/local/games>
++      #   #   #<Pathname:/usr/local/lib>
++      #   #   #<Pathname:/usr/local/include>
++      #   #   #<Pathname:/usr/local/sbin>
++      #   #   #<Pathname:/usr/local/src>
++      #   #   #<Pathname:/usr/local/man>
++      #
++      #   Pathname("/usr/local").each_child(false) {|f| p f }
++      #   #=> #<Pathname:share>
++      #   #   #<Pathname:bin>
++      #   #   #<Pathname:games>
++      #   #   #<Pathname:lib>
++      #   #   #<Pathname:include>
++      #   #   #<Pathname:sbin>
++      #   #   #<Pathname:src>
++      #   #   #<Pathname:man>
++      #
++      def each_child(with_directory=true, &b)
++        children(with_directory).each(&b)
++      end
++
++      #
++      # #relative_path_from returns a relative path from the argument to the
++      # receiver.  If +self+ is absolute, the argument must be absolute too.  If
++      # +self+ is relative, the argument must be relative too.
++      #
++      # #relative_path_from doesn't access the filesystem.  It assumes no symlinks.
++      #
++      # ArgumentError is raised when it cannot find a relative path.
++      #
++      # This method has existed since 1.8.1.
++      #
++      def relative_path_from(base_directory)
++        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
++        base_prefix = base_directory
++        base_names = []
++        while r = chop_basename(base_prefix)
++          base_prefix, basename = r
++          base_names.unshift basename if basename != '.'
++        end
++        unless SAME_PATHS[dest_prefix, base_prefix]
++          raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
++        end
++        while !dest_names.empty? &&
++              !base_names.empty? &&
++              SAME_PATHS[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_names.fill('..')
++        relpath_names = base_names + dest_names
++        if relpath_names.empty?
++          Pathname.new('.')
++        else
++          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
++      # for each line.
++      #
++      # This method has existed since 1.8.1.
++      #
++      def each_line(*args, &block) # :yield: line
++        IO.foreach(@path, *args, &block)
++      end
++
++      # See <tt>IO.read</tt>.  Returns all data from the file, or the first +N+ bytes
++      # if specified.
++      def read(*args) IO.read(@path, *args) end
++
++      # See <tt>IO.binread</tt>.  Returns all the bytes from the file, or the first +N+
++      # if specified.
++      def binread(*args) IO.binread(@path, *args) end
++
++      # See <tt>IO.readlines</tt>.  Returns all the lines from the file.
++      def readlines(*args) IO.readlines(@path, *args) end
++
++      # See <tt>IO.sysopen</tt>.
++      def sysopen(*args) IO.sysopen(@path, *args) end
++    end
++
++
++    class Pathname    # * File *
++
++      # See <tt>File.atime</tt>.  Returns last access time.
++      def atime() File.atime(@path) end
++
++      # See <tt>File.ctime</tt>.  Returns last (directory entry, not file) change time.
++      def ctime() File.ctime(@path) end
++
++      # See <tt>File.mtime</tt>.  Returns last modification time.
++      def mtime() File.mtime(@path) end
++
++      # See <tt>File.chmod</tt>.  Changes permissions.
++      def chmod(mode) File.chmod(mode, @path) end
++
++      # See <tt>File.lchmod</tt>.
++      def lchmod(mode) File.lchmod(mode, @path) end
++
++      # See <tt>File.chown</tt>.  Change owner and group of file.
++      def chown(owner, group) File.chown(owner, group, @path) end
++
++      # See <tt>File.lchown</tt>.
++      def lchown(owner, group) File.lchown(owner, group, @path) end
++
++      # See <tt>File.fnmatch</tt>.  Return +true+ if the receiver matches the given
++      # pattern.
++      def fnmatch(pattern, *args) File.fnmatch(pattern, @path, *args) end
++
++      # See <tt>File.fnmatch?</tt> (same as #fnmatch).
++      def fnmatch?(pattern, *args) File.fnmatch?(pattern, @path, *args) end
++
++      # See <tt>File.ftype</tt>.  Returns "type" of file ("file", "directory",
++      # etc).
++      def ftype() File.ftype(@path) end
++
++      # See <tt>File.link</tt>.  Creates a hard link.
++      def make_link(old) File.link(old, @path) end
++
++      # See <tt>File.open</tt>.  Opens the file for reading or writing.
++      def open(*args, &block) # :yield: file
++        File.open(@path, *args, &block)
++      end
++
++      # See <tt>File.readlink</tt>.  Read symbolic link.
++      def readlink() self.class.new(File.readlink(@path)) end
++
++      # See <tt>File.rename</tt>.  Rename the file.
++      def rename(to) File.rename(@path, to) end
++
++      # See <tt>File.stat</tt>.  Returns a <tt>File::Stat</tt> object.
++      def stat() File.stat(@path) end
++
++      # See <tt>File.lstat</tt>.
++      def lstat() File.lstat(@path) end
++
++      # See <tt>File.symlink</tt>.  Creates a symbolic link.
++      def make_symlink(old) File.symlink(old, @path) end
++
++      # See <tt>File.truncate</tt>.  Truncate the file to +length+ bytes.
++      def truncate(length) File.truncate(@path, length) end
++
++      # See <tt>File.utime</tt>.  Update the access and modification times.
++      def utime(atime, mtime) File.utime(atime, mtime, @path) end
++
++      # See <tt>File.basename</tt>.  Returns the last component of the path.
++      def basename(*args) self.class.new(File.basename(@path, *args)) end
++
++      # See <tt>File.dirname</tt>.  Returns all but the last component of the path.
++      def dirname() self.class.new(File.dirname(@path)) end
++
++      # See <tt>File.extname</tt>.  Returns the file's extension.
++      def extname() File.extname(@path) end
++
++      # See <tt>File.expand_path</tt>.
++      def expand_path(*args) self.class.new(File.expand_path(@path, *args)) end
++
++      # See <tt>File.split</tt>.  Returns the #dirname and the #basename in an
++      # Array.
++      def split() File.split(@path).map {|f| self.class.new(f) } end
++    end
++
++
++    class Pathname    # * FileTest *
++
++      # See <tt>FileTest.blockdev?</tt>.
++      def blockdev?() FileTest.blockdev?(@path) end
++
++      # See <tt>FileTest.chardev?</tt>.
++      def chardev?() FileTest.chardev?(@path) end
++
++      # See <tt>FileTest.executable?</tt>.
++      def executable?() FileTest.executable?(@path) end
++
++      # See <tt>FileTest.executable_real?</tt>.
++      def executable_real?() FileTest.executable_real?(@path) end
++
++      # See <tt>FileTest.exist?</tt>.
++      def exist?() FileTest.exist?(@path) end
++
++      # See <tt>FileTest.grpowned?</tt>.
++      def grpowned?() FileTest.grpowned?(@path) end
++
++      # See <tt>FileTest.directory?</tt>.
++      def directory?() FileTest.directory?(@path) end
++
++      # See <tt>FileTest.file?</tt>.
++      def file?() FileTest.file?(@path) end
++
++      # See <tt>FileTest.pipe?</tt>.
++      def pipe?() FileTest.pipe?(@path) end
++
++      # See <tt>FileTest.socket?</tt>.
++      def socket?() FileTest.socket?(@path) end
++
++      # See <tt>FileTest.owned?</tt>.
++      def owned?() FileTest.owned?(@path) end
++
++      # See <tt>FileTest.readable?</tt>.
++      def readable?() FileTest.readable?(@path) end
++
++      # See <tt>FileTest.world_readable?</tt>.
++      def world_readable?() FileTest.world_readable?(@path) end
++
++      # See <tt>FileTest.readable_real?</tt>.
++      def readable_real?() FileTest.readable_real?(@path) end
++
++      # See <tt>FileTest.setuid?</tt>.
++      def setuid?() FileTest.setuid?(@path) end
++
++      # See <tt>FileTest.setgid?</tt>.
++      def setgid?() FileTest.setgid?(@path) end
++
++      # See <tt>FileTest.size</tt>.
++      def size() FileTest.size(@path) end
++
++      # See <tt>FileTest.size?</tt>.
++      def size?() FileTest.size?(@path) end
++
++      # See <tt>FileTest.sticky?</tt>.
++      def sticky?() FileTest.sticky?(@path) end
++
++      # See <tt>FileTest.symlink?</tt>.
++      def symlink?() FileTest.symlink?(@path) end
++
++      # See <tt>FileTest.writable?</tt>.
++      def writable?() FileTest.writable?(@path) end
++
++      # See <tt>FileTest.world_writable?</tt>.
++      def world_writable?() FileTest.world_writable?(@path) end
++
++      # See <tt>FileTest.writable_real?</tt>.
++      def writable_real?() FileTest.writable_real?(@path) end
++
++      # See <tt>FileTest.zero?</tt>.
++      def zero?() FileTest.zero?(@path) end
++    end
++
++
++    class Pathname    # * Dir *
++      # See <tt>Dir.glob</tt>.  Returns or yields Pathname objects.
++      def Pathname.glob(*args) # :yield: pathname
++        if block_given?
++          Dir.glob(*args) {|f| yield self.new(f) }
++        else
++          Dir.glob(*args).map {|f| self.new(f) }
++        end
++      end
++
++      # See <tt>Dir.getwd</tt>.  Returns the current working directory as a Pathname.
++      def Pathname.getwd() self.new(Dir.getwd) end
++      class << self; alias pwd getwd end
++
++      # Return the entries (files and subdirectories) in the directory, each as a
++      # Pathname object.
++      def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
++
++      # Iterates over the entries (files and subdirectories) in the directory.  It
++      # yields a Pathname object for each entry.
++      #
++      # This method has existed since 1.8.1.
++      def each_entry(&block) # :yield: pathname
++        Dir.foreach(@path) {|f| yield self.class.new(f) }
++      end
++
++      # See <tt>Dir.mkdir</tt>.  Create the referenced directory.
++      def mkdir(*args) Dir.mkdir(@path, *args) end
++
++      # See <tt>Dir.rmdir</tt>.  Remove the referenced directory.
++      def rmdir() Dir.rmdir(@path) end
++
++      # See <tt>Dir.open</tt>.
++      def opendir(&block) # :yield: dir
++        Dir.open(@path, &block)
++      end
++    end
++
++
++    class Pathname    # * Find *
++      #
++      # Pathname#find is an iterator to traverse a directory tree in a depth first
++      # manner.  It yields a Pathname for each file under "this" directory.
++      #
++      # Since it is implemented by <tt>find.rb</tt>, <tt>Find.prune</tt> can be used
++      # to control the traverse.
++      #
++      # If +self+ is <tt>.</tt>, yielded pathnames begin with a filename in the
++      # current directory, not <tt>./</tt>.
++      #
++      def find(&block) # :yield: pathname
++        require 'find'
++        if @path == '.'
++          Find.find(@path) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
++        else
++          Find.find(@path) {|f| yield self.class.new(f) }
++        end
++      end
++    end
++
++
++    class Pathname    # * FileUtils *
++      # See <tt>FileUtils.mkpath</tt>.  Creates a full path, including any
++      # intermediate directories that don't yet exist.
++      def mkpath
++        require 'fileutils'
++        FileUtils.mkpath(@path)
++        nil
++      end
++
++      # See <tt>FileUtils.rm_r</tt>.  Deletes a directory and all beneath it.
++      def rmtree
++        # The name "rmtree" is borrowed from File::Path of Perl.
++        # File::Path provides "mkpath" and "rmtree".
++        require 'fileutils'
++        FileUtils.rm_r(@path)
++        nil
++      end
++    end
++
++
++    class Pathname    # * mixed *
++      # Removes a file or directory, using <tt>File.unlink</tt> or
++      # <tt>Dir.unlink</tt> as necessary.
++      def unlink()
++        begin
++          Dir.unlink @path
++        rescue Errno::ENOTDIR
++          File.unlink @path
++        end
++      end
++      alias delete unlink
++    end
++
++    class Pathname
++      undef =~
++    end
++  end # RUBY_VERSION >= 1.9.3
++end
++
diff --git a/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193.patch b/dev-ruby/fakefs/files/fakefs-0.4.0-ruby193.patch
new file mode 100644 (file)
index 0000000..b427bef
--- /dev/null
@@ -0,0 +1,195 @@
+commit af733ea5606391c594fb5e228fc1e94515c1e7e4
+Author: Mateusz Juraszek <meceo00@gmail.com>
+Date:   Tue Jan 3 11:00:56 2012 +0100
+
+    add external encoding as default to File @content string,
+    handle hash as second parameter to File::new,
+    extend FakeFS::FileSystem::clone method to accept 'target' as a optional parameter,
+    fix Dir::mkdir for nested structure
+
+diff --git a/lib/fakefs/dir.rb b/lib/fakefs/dir.rb
+index 628626f..ed571ff 100644
+--- a/lib/fakefs/dir.rb
++++ b/lib/fakefs/dir.rb
+@@ -105,7 +105,7 @@ module FakeFS
+       parent = string.split('/')
+       parent.pop
+-      joined_parent_path = parent.join
++      joined_parent_path = parent.join("/")
+       _check_for_valid_file(joined_parent_path) unless joined_parent_path == ""
+       raise Errno::EEXIST, "File exists - #{string}" if File.exists?(string)
+diff --git a/lib/fakefs/fake/file.rb b/lib/fakefs/fake/file.rb
+index 10bdf7f..22f32d9 100644
+--- a/lib/fakefs/fake/file.rb
++++ b/lib/fakefs/fake/file.rb
+@@ -5,7 +5,8 @@ module FakeFS
+     class Inode
+       def initialize(file_owner)
+-        @content = ""
++        #1.9.3 when possible set default external encoding
++        @content = "".respond_to?(:encode) ? "".encode(Encoding.default_external) : ""
+         @links   = [file_owner]
+       end
+diff --git a/lib/fakefs/file.rb b/lib/fakefs/file.rb
+index 5684ede..5f36376 100644
+--- a/lib/fakefs/file.rb
++++ b/lib/fakefs/file.rb
+@@ -275,7 +275,7 @@ module FakeFS
+     def initialize(path, mode = READ_ONLY, perm = nil)
+       @path = path
+-      @mode = mode
++      @mode = mode.is_a?(Hash) ? (mode[:mode] || READ_ONLY) : mode
+       @file = FileSystem.find(path)
+       @autoclose = true
+@@ -283,7 +283,7 @@ module FakeFS
+       file_creation_mode? ? create_missing_file : check_file_existence!
+-      super(@file.content, mode)
++      super(@file.content, @mode)
+     end
+     def exists?
+diff --git a/lib/fakefs/file_system.rb b/lib/fakefs/file_system.rb
+index a5c8087..da58ad9 100644
+--- a/lib/fakefs/file_system.rb
++++ b/lib/fakefs/file_system.rb
+@@ -46,19 +46,20 @@ module FakeFS
+     # copies directories and files from the real filesystem
+     # into our fake one
+-    def clone(path)
++    def clone(path, target = nil)
+       path    = File.expand_path(path)
+       pattern = File.join(path, '**', '*')
+       files   = RealFile.file?(path) ? [path] : [path] + RealDir.glob(pattern, RealFile::FNM_DOTMATCH)
+       files.each do |f|
++        target_path = target ? f.gsub(path, target) : f
+         if RealFile.file?(f)
+           FileUtils.mkdir_p(File.dirname(f))
+-          File.open(f, File::WRITE_ONLY) do |g|
++          File.open(target_path, File::WRITE_ONLY) do |g|
+             g.print RealFile.open(f){|h| h.read }
+           end
+         elsif RealFile.directory?(f)
+-          FileUtils.mkdir_p(f)
++          FileUtils.mkdir_p(target_path)
+         elsif RealFile.symlink?(f)
+           FileUtils.ln_s()
+         end
+diff --git a/test/fakefs_test.rb b/test/fakefs_test.rb
+index 0f34950..7e2b8dc 100644
+--- a/test/fakefs_test.rb
++++ b/test/fakefs_test.rb
+@@ -647,6 +647,21 @@ class FakeFSTest < Test::Unit::TestCase
+     assert_equal "Yatta!", File.new(path).read
+   end
++  if RUBY_VERSION >= "1.9" 
++    def test_file_object_has_default_external_encoding
++      Encoding.default_external = "UTF-8"
++      path = 'file.txt'
++      File.open(path, 'w'){|f| f.write 'Yatta!' }
++      assert_equal "UTF-8", File.new(path).read.encoding.name
++    end
++  end
++
++  def test_file_object_initialization_with_mode_in_hash_parameter
++    assert_nothing_raised do
++      File.open("file.txt", {:mode => "w"}){ |f| f.write 'Yatta!' }
++    end
++  end
++
+   def test_file_read_errors_appropriately
+     assert_raise Errno::ENOENT do
+       File.read('anything')
+@@ -1132,24 +1147,18 @@ class FakeFSTest < Test::Unit::TestCase
+   end
+   def test_clone_clones_directories
+-    FakeFS.deactivate!
+-    RealFileUtils.mkdir_p(here('subdir'))
+-    FakeFS.activate!
++    act_on_real_fs { RealFileUtils.mkdir_p(here('subdir')) }
+     FileSystem.clone(here('subdir'))
+     assert File.exists?(here('subdir')), 'subdir was cloned'
+     assert File.directory?(here('subdir')), 'subdir is a directory'
+   ensure
+-    FakeFS.deactivate!
+-    RealFileUtils.rm_rf(here('subdir'))
+-    FakeFS.activate!
++    act_on_real_fs { RealFileUtils.rm_rf(here('subdir')) }
+   end
+   def test_clone_clones_dot_files_even_hard_to_find_ones
+-    FakeFS.deactivate!
+-    RealFileUtils.mkdir_p(here('subdir/.bar/baz/.quux/foo'))
+-    FakeFS.activate!
++    act_on_real_fs { RealFileUtils.mkdir_p(here('subdir/.bar/baz/.quux/foo')) }
+     assert !File.exists?(here('subdir'))
+@@ -1157,9 +1166,20 @@ class FakeFSTest < Test::Unit::TestCase
+     assert_equal ['.bar'], FileSystem.find(here('subdir')).keys
+     assert_equal ['foo'], FileSystem.find(here('subdir/.bar/baz/.quux')).keys
+   ensure
+-    FakeFS.deactivate!
+-    RealFileUtils.rm_rf(here('subdir'))
+-    FakeFS.activate!
++    act_on_real_fs { RealFileUtils.rm_rf(here('subdir')) }
++  end
++
++  def test_clone_with_target_specified
++    act_on_real_fs { RealFileUtils.mkdir_p(here('subdir/.bar/baz/.quux/foo')) }
++
++    assert !File.exists?(here('subdir'))
++
++    FileSystem.clone(here('subdir'), here('subdir2'))
++    assert !File.exists?(here('subdir'))
++    assert_equal ['.bar'], FileSystem.find(here('subdir2')).keys
++    assert_equal ['foo'], FileSystem.find(here('subdir2/.bar/baz/.quux')).keys
++  ensure
++    act_on_real_fs { RealFileUtils.rm_rf(here('subdir')) }
+   end
+   def test_putting_a_dot_at_end_copies_the_contents
+@@ -1464,6 +1484,12 @@ class FakeFSTest < Test::Unit::TestCase
+     assert File.exists?('/path')
+   end
++  def test_directory_mkdir_nested
++    Dir.mkdir("/tmp")
++    Dir.mkdir("/tmp/stream20120103-11847-xc8pb.lock")
++    assert File.exists?("/tmp/stream20120103-11847-xc8pb.lock")
++  end
++
+   def test_directory_mkdir_relative
+     FileUtils.mkdir_p('/new/root')
+     FileSystem.chdir('/new/root')
+diff --git a/test/test_helper.rb b/test/test_helper.rb
+index c41dd67..b6596fa 100644
+--- a/test/test_helper.rb
++++ b/test/test_helper.rb
+@@ -5,4 +5,11 @@ require 'test/unit'
+ begin
+   require 'redgreen'
+ rescue LoadError
+-end
+\ No newline at end of file
++end
++
++def act_on_real_fs
++  raise ArgumentError unless block_given?
++  FakeFS.deactivate!
++  yield
++  FakeFS.activate!
++end