epath 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +19 -0
 - data/README.md +106 -0
 - data/epath.gemspec +5 -3
 - data/lib/epath.rb +196 -0
 - data/lib/epath/implementation.rb +873 -0
 - metadata +10 -6
 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (C) 2011 Benoit Daloze
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 4 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 5 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 6 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 7 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 8 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in
         
     | 
| 
      
 11 
     | 
    
         
            +
            all copies or substantial portions of the Software.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 14 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 15 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 16 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 17 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 18 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         
     | 
| 
      
 19 
     | 
    
         
            +
            THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,106 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Path - Enhanced Pathname
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Path is a library to manage paths.  
         
     | 
| 
      
 4 
     | 
    
         
            +
            It is similar to Pathname, but has some extra goodness.  
         
     | 
| 
      
 5 
     | 
    
         
            +
            The method names are intended to be short and explicit, and avoid too much duplication like having 'name' or 'path' in the method name.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            I believe the object-oriented approach to manipulate paths is very elegant and useful.  
         
     | 
| 
      
 8 
     | 
    
         
            +
            Paths are naturally the subject of their methods and even if they are simple Strings behind, they carry way much more information and deserve a first-class status.
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Also, using a path library like this avoid to remember in which class the functionality is implemented, everything is in one place (if not, please open an issue!).
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## API
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            All the useful methods of `File` (and so `IO`) and `Dir` should be included.  
         
     | 
| 
      
 15 
     | 
    
         
            +
            Most methods of `FileUtils` should be there too.
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            ### creation
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ``` ruby
         
     | 
| 
      
 20 
     | 
    
         
            +
            Path.new('/usr/bin')
         
     | 
| 
      
 21 
     | 
    
         
            +
            Path['/usr/bin']
         
     | 
| 
      
 22 
     | 
    
         
            +
            Path('/usr/bin') # unless NO_EPATH_GLOBAL_FUNCTION is defined
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            Path.new('/usr', 'bin')
         
     | 
| 
      
 25 
     | 
    
         
            +
            %w[foo bar].map(&Path) # => [Path('foo'), Path('bar')]
         
     | 
| 
      
 26 
     | 
    
         
            +
            ```
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            ``` ruby
         
     | 
| 
      
 29 
     | 
    
         
            +
            Path.here # == Path(__FILE__).expand
         
     | 
| 
      
 30 
     | 
    
         
            +
            Path.dir # == Path(File.dirname(__FILE__)).expand
         
     | 
| 
      
 31 
     | 
    
         
            +
            Path.relative(path) # == Path(File.expand_path("../#{path}", __FILE__))
         
     | 
| 
      
 32 
     | 
    
         
            +
            Path.home # == Path(File.expand_path('~'))
         
     | 
| 
      
 33 
     | 
    
         
            +
            ```
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ### temporary
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            ``` ruby
         
     | 
| 
      
 38 
     | 
    
         
            +
            Path.tmpfile
         
     | 
| 
      
 39 
     | 
    
         
            +
            Path.tmpdir
         
     | 
| 
      
 40 
     | 
    
         
            +
            ```
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ### aliases
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            * expand => expand_path
         
     | 
| 
      
 45 
     | 
    
         
            +
            * relative_to => relative_path_from
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            ### parts
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            * base: basename(extname)
         
     | 
| 
      
 50 
     | 
    
         
            +
            * dir: alias of dirname
         
     | 
| 
      
 51 
     | 
    
         
            +
            * ext: extname without the leading dot
         
     | 
| 
      
 52 
     | 
    
         
            +
            * /: join paths
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 55 
     | 
    
         
            +
            Path('/usr')/'bin'
         
     | 
| 
      
 56 
     | 
    
         
            +
            ```
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            These method names are too long, any idea to make them shorter and clear?
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            * without_extension
         
     | 
| 
      
 61 
     | 
    
         
            +
            * replace_extension(new_ext)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            ### glob
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            * entries: files under self, without . and ..
         
     | 
| 
      
 66 
     | 
    
         
            +
            * glob: relative glob to self, yield absolute paths
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            ### structure
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            * ancestors: self and all the parent directories
         
     | 
| 
      
 71 
     | 
    
         
            +
            * backfind: ascends the parents until it finds the given path
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            ``` ruby
         
     | 
| 
      
 74 
     | 
    
         
            +
            # Path.backfind is Path.here.backfind
         
     | 
| 
      
 75 
     | 
    
         
            +
            Path.backfind('lib') # => Path's lib folder
         
     | 
| 
      
 76 
     | 
    
         
            +
            # it accepts XPath-like context
         
     | 
| 
      
 77 
     | 
    
         
            +
            Path.backfind('.[.git]') # => the root of this repository
         
     | 
| 
      
 78 
     | 
    
         
            +
            ```
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            ### IO
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            * read
         
     | 
| 
      
 83 
     | 
    
         
            +
            * write(contents)
         
     | 
| 
      
 84 
     | 
    
         
            +
            * append(contents)
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            ### management
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            * mkdir
         
     | 
| 
      
 89 
     | 
    
         
            +
            * mkdir_p
         
     | 
| 
      
 90 
     | 
    
         
            +
            * rm_rf
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            ### Incompatibilities with Pathname
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            * #entries never returns . and ..
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            ## Status
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            This is still in the early development stage, you should expect many additions and some changes.
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
            ## Author
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            Benoit Daloze - eregon
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            ### Contributors
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            Bernard Lambeau - blambeau
         
     | 
    
        data/epath.gemspec
    CHANGED
    
    | 
         @@ -1,7 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Gem::Specification.new do |s|
         
     | 
| 
       2 
2 
     | 
    
         
             
              s.name = 'epath'
         
     | 
| 
       3 
     | 
    
         
            -
              s.summary = ' 
     | 
| 
      
 3 
     | 
    
         
            +
              s.summary = 'a Path manipulation library'
         
     | 
| 
       4 
4 
     | 
    
         
             
              s.author = 'eregon'
         
     | 
| 
       5 
     | 
    
         
            -
              s. 
     | 
| 
       6 
     | 
    
         
            -
              s. 
     | 
| 
      
 5 
     | 
    
         
            +
              s.email = 'eregontp@gmail.com'
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.homepage = 'https://github.com/eregon/epath'
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.files = Dir['lib/**/*.rb'] + %w[README.md LICENSE epath.gemspec]
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.version = '0.0.1'
         
     | 
| 
       7 
9 
     | 
    
         
             
            end
         
     | 
    
        data/lib/epath.rb
    ADDED
    
    | 
         @@ -0,0 +1,196 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Enchanced Pathname
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Use the composite pattern with a Pathname
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require File.expand_path('../epath/implementation', __FILE__)
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'tempfile'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            class Path
         
     | 
| 
      
 8 
     | 
    
         
            +
              DOTS = %w[. ..]
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                def new(*args)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  if args.size == 1 and Path === args[0]
         
     | 
| 
      
 13 
     | 
    
         
            +
                    args[0]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  else
         
     | 
| 
      
 15 
     | 
    
         
            +
                    super(*args)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
                alias_method :[], :new
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def to_proc
         
     | 
| 
      
 21 
     | 
    
         
            +
                  lambda { |path| new(path) }
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def here(from = nil)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  from ||= caller
         
     | 
| 
      
 26 
     | 
    
         
            +
                  new(from.first.split(/:\d+(?:$|:in)/).first).expand
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
                alias_method :file, :here
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def dir(from = nil)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  from ||= caller
         
     | 
| 
      
 32 
     | 
    
         
            +
                  file(from).dir
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def home
         
     | 
| 
      
 36 
     | 
    
         
            +
                  new(Dir.respond_to?(:home) ? Dir.home : new("~").expand)
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def relative(path)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  new(path).expand dir(caller)
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def backfind(path)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  here(caller).backfind(path)
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def tmpfile(basename = '', tmpdir = nil, options = nil)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  tempfile = Tempfile.new(basename, *[tmpdir, options].compact)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  file = new tempfile
         
     | 
| 
      
 50 
     | 
    
         
            +
                  if block_given?
         
     | 
| 
      
 51 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                      yield file
         
     | 
| 
      
 53 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 54 
     | 
    
         
            +
                      tempfile.close
         
     | 
| 
      
 55 
     | 
    
         
            +
                      tempfile.unlink if file.exist?
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  file
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
                alias_method :tempfile, :tmpfile
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def tmpdir(prefix_suffix = nil, *rest)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  require 'tmpdir'
         
     | 
| 
      
 64 
     | 
    
         
            +
                  dir = new Dir.mktmpdir(prefix_suffix, *rest)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  if block_given?
         
     | 
| 
      
 66 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 67 
     | 
    
         
            +
                      yield dir
         
     | 
| 
      
 68 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 69 
     | 
    
         
            +
                      FileUtils.remove_entry_secure(dir) rescue nil
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  dir
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              def initialize(*parts)
         
     | 
| 
      
 77 
     | 
    
         
            +
                path = parts.size > 1 ? parts.join(File::SEPARATOR) : parts.first
         
     | 
| 
      
 78 
     | 
    
         
            +
                if Tempfile === path
         
     | 
| 
      
 79 
     | 
    
         
            +
                  @_tmpfile = path # We would not want it to be GC'd
         
     | 
| 
      
 80 
     | 
    
         
            +
                  @path = path.path
         
     | 
| 
      
 81 
     | 
    
         
            +
                elsif String === path
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @path = path.dup
         
     | 
| 
      
 83 
     | 
    
         
            +
                else
         
     | 
| 
      
 84 
     | 
    
         
            +
                  @path = path.to_s
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
                taint if @path.tainted?
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
              def / part
         
     | 
| 
      
 90 
     | 
    
         
            +
                join part.to_s
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              def base # basename(extname)
         
     | 
| 
      
 94 
     | 
    
         
            +
                basename(extname)
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              def ext # extname without leading .
         
     | 
| 
      
 98 
     | 
    
         
            +
                ext = extname
         
     | 
| 
      
 99 
     | 
    
         
            +
                ext.empty? ? ext : ext[1..-1]
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              def without_extension # rm_ext
         
     | 
| 
      
 103 
     | 
    
         
            +
                dir / base
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
              # NOTE: Pathname has a similar feature named sub_ext
         
     | 
| 
      
 107 
     | 
    
         
            +
              # It might be a better method name
         
     | 
| 
      
 108 
     | 
    
         
            +
              def replace_extension(ext)
         
     | 
| 
      
 109 
     | 
    
         
            +
                ext = ".#{ext}" unless ext.start_with? '.'
         
     | 
| 
      
 110 
     | 
    
         
            +
                Path.new(without_extension.to_s + ext)
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              def entries
         
     | 
| 
      
 114 
     | 
    
         
            +
                (Dir.entries(@path) - DOTS).map { |entry| Path.new(@path, entry).cleanpath }
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
              def glob(pattern, flags = 0)
         
     | 
| 
      
 118 
     | 
    
         
            +
                Dir.glob(join(pattern), flags).map(&Path)
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
              def rm
         
     | 
| 
      
 122 
     | 
    
         
            +
                FileUtils.rm(@path)
         
     | 
| 
      
 123 
     | 
    
         
            +
                self
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              def rm_f
         
     | 
| 
      
 127 
     | 
    
         
            +
                FileUtils.rm_f(@path)
         
     | 
| 
      
 128 
     | 
    
         
            +
                self
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              def rm_rf
         
     | 
| 
      
 132 
     | 
    
         
            +
                FileUtils.rm_rf(@path)
         
     | 
| 
      
 133 
     | 
    
         
            +
                self
         
     | 
| 
      
 134 
     | 
    
         
            +
              end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
              def mkdir_p
         
     | 
| 
      
 137 
     | 
    
         
            +
                FileUtils.mkdir_p(@path)
         
     | 
| 
      
 138 
     | 
    
         
            +
                self
         
     | 
| 
      
 139 
     | 
    
         
            +
              end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
              def write(contents, open_args = nil)
         
     | 
| 
      
 142 
     | 
    
         
            +
                if IO.respond_to? :write
         
     | 
| 
      
 143 
     | 
    
         
            +
                  IO.write(@path, contents, *[open_args].compact)
         
     | 
| 
      
 144 
     | 
    
         
            +
                else
         
     | 
| 
      
 145 
     | 
    
         
            +
                  open('w', *[open_args].compact) { |f| f.write(contents) }
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              def append(contents, open_args = nil)
         
     | 
| 
      
 150 
     | 
    
         
            +
                if IO.respond_to? :write
         
     | 
| 
      
 151 
     | 
    
         
            +
                  open_args = (Array(open_args) << {:mode => 'a'})
         
     | 
| 
      
 152 
     | 
    
         
            +
                  IO.write(@path, contents, *open_args.compact)
         
     | 
| 
      
 153 
     | 
    
         
            +
                else
         
     | 
| 
      
 154 
     | 
    
         
            +
                  open('a', *[open_args].compact) { |f| f.write(contents) }
         
     | 
| 
      
 155 
     | 
    
         
            +
                end
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              def to_sym
         
     | 
| 
      
 159 
     | 
    
         
            +
                to_s.to_sym
         
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
              def relative_to other
         
     | 
| 
      
 163 
     | 
    
         
            +
                relative_path_from Path.new other
         
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
              alias_method :%, :relative_to
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
              def ancestors
         
     | 
| 
      
 168 
     | 
    
         
            +
                ancestors = lambda do |y|
         
     | 
| 
      
 169 
     | 
    
         
            +
                  y << path = expand
         
     | 
| 
      
 170 
     | 
    
         
            +
                  until (path = path.parent).root?
         
     | 
| 
      
 171 
     | 
    
         
            +
                    y << path
         
     | 
| 
      
 172 
     | 
    
         
            +
                  end
         
     | 
| 
      
 173 
     | 
    
         
            +
                  y << path
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
                RUBY_VERSION > '1.9' ? Enumerator.new(&ancestors) : ancestors.call([])
         
     | 
| 
      
 176 
     | 
    
         
            +
              end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
              def backfind(path)
         
     | 
| 
      
 179 
     | 
    
         
            +
                condition = path[/\[(.*)\]$/, 1] || ''
         
     | 
| 
      
 180 
     | 
    
         
            +
                path = $` unless condition.empty?
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                result = ancestors.find { |ancestor| (ancestor/path/condition).exist? }
         
     | 
| 
      
 183 
     | 
    
         
            +
                result/path if result
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
              alias_method :expand, :expand_path
         
     | 
| 
      
 187 
     | 
    
         
            +
              alias_method :dir, :dirname
         
     | 
| 
      
 188 
     | 
    
         
            +
            end
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
            EPath = Path # to meet everyone's expectations
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
            unless defined? NO_EPATH_GLOBAL_FUNCTION
         
     | 
| 
      
 193 
     | 
    
         
            +
              def Path(*args)
         
     | 
| 
      
 194 
     | 
    
         
            +
                Path.new(*args)
         
     | 
| 
      
 195 
     | 
    
         
            +
              end
         
     | 
| 
      
 196 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,873 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Path's low-level implementation based on Pathname
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Path
         
     | 
| 
      
 6 
     | 
    
         
            +
              # :stopdoc:
         
     | 
| 
      
 7 
     | 
    
         
            +
              SAME_PATHS = if File::FNM_SYSCASE.nonzero?
         
     | 
| 
      
 8 
     | 
    
         
            +
                proc {|a, b| a.casecmp(b).zero?}
         
     | 
| 
      
 9 
     | 
    
         
            +
              else
         
     | 
| 
      
 10 
     | 
    
         
            +
                proc {|a, b| a == b}
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              # :startdoc:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def freeze() super; @path.freeze; self end
         
     | 
| 
      
 16 
     | 
    
         
            +
              def taint() super; @path.taint; self end
         
     | 
| 
      
 17 
     | 
    
         
            +
              def untaint() super; @path.untaint; self end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              #
         
     | 
| 
      
 20 
     | 
    
         
            +
              # Compare this pathname with +other+.  The comparison is string-based.
         
     | 
| 
      
 21 
     | 
    
         
            +
              # Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
         
     | 
| 
      
 22 
     | 
    
         
            +
              # can refer to the same file.
         
     | 
| 
      
 23 
     | 
    
         
            +
              #
         
     | 
| 
      
 24 
     | 
    
         
            +
              def == other
         
     | 
| 
      
 25 
     | 
    
         
            +
                Path === other and @path == other.to_s
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
              alias eql? ==
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              # Provides for comparing pathnames, case-sensitively.
         
     | 
| 
      
 30 
     | 
    
         
            +
              def <=>(other)
         
     | 
| 
      
 31 
     | 
    
         
            +
                return nil unless Path === other
         
     | 
| 
      
 32 
     | 
    
         
            +
                @path.tr('/', "\0") <=> other.to_s.tr('/', "\0")
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def hash # :nodoc:
         
     | 
| 
      
 36 
     | 
    
         
            +
                @path.hash
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              # Return the path as a String.
         
     | 
| 
      
 40 
     | 
    
         
            +
              def to_s
         
     | 
| 
      
 41 
     | 
    
         
            +
                @path.dup
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              # to_path is implemented so Path objects are usable with File.open, etc.
         
     | 
| 
      
 45 
     | 
    
         
            +
              alias to_path to_s
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              alias to_str to_s if RUBY_VERSION < '1.9'
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              def inspect
         
     | 
| 
      
 50 
     | 
    
         
            +
                "#<Path #{@path}>"
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              if File::ALT_SEPARATOR
         
     | 
| 
      
 54 
     | 
    
         
            +
                SEPARATOR_LIST = "#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}"
         
     | 
| 
      
 55 
     | 
    
         
            +
                SEPARATOR_PAT = /[#{SEPARATOR_LIST}]/
         
     | 
| 
      
 56 
     | 
    
         
            +
              else
         
     | 
| 
      
 57 
     | 
    
         
            +
                SEPARATOR_LIST = "#{Regexp.quote File::SEPARATOR}"
         
     | 
| 
      
 58 
     | 
    
         
            +
                SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              # Return a pathname which the extension of the basename is substituted by
         
     | 
| 
      
 62 
     | 
    
         
            +
              # <i>repl</i>.
         
     | 
| 
      
 63 
     | 
    
         
            +
              #
         
     | 
| 
      
 64 
     | 
    
         
            +
              # If self has no extension part, <i>repl</i> is appended.
         
     | 
| 
      
 65 
     | 
    
         
            +
              def sub_ext(repl)
         
     | 
| 
      
 66 
     | 
    
         
            +
                ext = File.extname(@path)
         
     | 
| 
      
 67 
     | 
    
         
            +
                Path.new(@path.chomp(ext) + repl)
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              # chop_basename(path) -> [pre-basename, basename] or nil
         
     | 
| 
      
 71 
     | 
    
         
            +
              def chop_basename(path)
         
     | 
| 
      
 72 
     | 
    
         
            +
                base = File.basename(path)
         
     | 
| 
      
 73 
     | 
    
         
            +
                if /\A#{SEPARATOR_PAT}?\z/o =~ base
         
     | 
| 
      
 74 
     | 
    
         
            +
                  return nil
         
     | 
| 
      
 75 
     | 
    
         
            +
                else
         
     | 
| 
      
 76 
     | 
    
         
            +
                  return path[0, path.rindex(base)], base
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
              private :chop_basename
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              # split_names(path) -> prefix, [name, ...]
         
     | 
| 
      
 82 
     | 
    
         
            +
              def split_names(path)
         
     | 
| 
      
 83 
     | 
    
         
            +
                names = []
         
     | 
| 
      
 84 
     | 
    
         
            +
                while r = chop_basename(path)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  path, basename = r
         
     | 
| 
      
 86 
     | 
    
         
            +
                  names.unshift basename
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
                return path, names
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
              private :split_names
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              def prepend_prefix(prefix, relpath)
         
     | 
| 
      
 93 
     | 
    
         
            +
                if relpath.empty?
         
     | 
| 
      
 94 
     | 
    
         
            +
                  File.dirname(prefix)
         
     | 
| 
      
 95 
     | 
    
         
            +
                elsif /#{SEPARATOR_PAT}/o =~ prefix
         
     | 
| 
      
 96 
     | 
    
         
            +
                  prefix = File.dirname(prefix)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
         
     | 
| 
      
 98 
     | 
    
         
            +
                  prefix + relpath
         
     | 
| 
      
 99 
     | 
    
         
            +
                else
         
     | 
| 
      
 100 
     | 
    
         
            +
                  prefix + relpath
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
              end
         
     | 
| 
      
 103 
     | 
    
         
            +
              private :prepend_prefix
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              # Returns clean pathname of +self+ with consecutive slashes and useless dots
         
     | 
| 
      
 106 
     | 
    
         
            +
              # removed.  The filesystem is not accessed.
         
     | 
| 
      
 107 
     | 
    
         
            +
              #
         
     | 
| 
      
 108 
     | 
    
         
            +
              # If +consider_symlink+ is +true+, then a more conservative algorithm is used
         
     | 
| 
      
 109 
     | 
    
         
            +
              # to avoid breaking symbolic linkages.  This may retain more <tt>..</tt>
         
     | 
| 
      
 110 
     | 
    
         
            +
              # entries than absolutely necessary, but without accessing the filesystem,
         
     | 
| 
      
 111 
     | 
    
         
            +
              # this can't be avoided.  See #realpath.
         
     | 
| 
      
 112 
     | 
    
         
            +
              #
         
     | 
| 
      
 113 
     | 
    
         
            +
              def cleanpath(consider_symlink=false)
         
     | 
| 
      
 114 
     | 
    
         
            +
                if consider_symlink
         
     | 
| 
      
 115 
     | 
    
         
            +
                  cleanpath_conservative
         
     | 
| 
      
 116 
     | 
    
         
            +
                else
         
     | 
| 
      
 117 
     | 
    
         
            +
                  cleanpath_aggressive
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
              #
         
     | 
| 
      
 122 
     | 
    
         
            +
              # Clean the path simply by resolving and removing excess "." and ".." entries.
         
     | 
| 
      
 123 
     | 
    
         
            +
              # Nothing more, nothing less.
         
     | 
| 
      
 124 
     | 
    
         
            +
              #
         
     | 
| 
      
 125 
     | 
    
         
            +
              def cleanpath_aggressive
         
     | 
| 
      
 126 
     | 
    
         
            +
                path = @path
         
     | 
| 
      
 127 
     | 
    
         
            +
                names = []
         
     | 
| 
      
 128 
     | 
    
         
            +
                pre = path
         
     | 
| 
      
 129 
     | 
    
         
            +
                while r = chop_basename(pre)
         
     | 
| 
      
 130 
     | 
    
         
            +
                  pre, base = r
         
     | 
| 
      
 131 
     | 
    
         
            +
                  case base
         
     | 
| 
      
 132 
     | 
    
         
            +
                  when '.'
         
     | 
| 
      
 133 
     | 
    
         
            +
                  when '..'
         
     | 
| 
      
 134 
     | 
    
         
            +
                    names.unshift base
         
     | 
| 
      
 135 
     | 
    
         
            +
                  else
         
     | 
| 
      
 136 
     | 
    
         
            +
                    if names[0] == '..'
         
     | 
| 
      
 137 
     | 
    
         
            +
                      names.shift
         
     | 
| 
      
 138 
     | 
    
         
            +
                    else
         
     | 
| 
      
 139 
     | 
    
         
            +
                      names.unshift base
         
     | 
| 
      
 140 
     | 
    
         
            +
                    end
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
                if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
         
     | 
| 
      
 144 
     | 
    
         
            +
                  names.shift while names[0] == '..'
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
                Path.new(prepend_prefix(pre, File.join(*names)))
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
              private :cleanpath_aggressive
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              # has_trailing_separator?(path) -> bool
         
     | 
| 
      
 151 
     | 
    
         
            +
              def has_trailing_separator?(path)
         
     | 
| 
      
 152 
     | 
    
         
            +
                if r = chop_basename(path)
         
     | 
| 
      
 153 
     | 
    
         
            +
                  pre, basename = r
         
     | 
| 
      
 154 
     | 
    
         
            +
                  pre.length + basename.length < path.length
         
     | 
| 
      
 155 
     | 
    
         
            +
                else
         
     | 
| 
      
 156 
     | 
    
         
            +
                  false
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
              end
         
     | 
| 
      
 159 
     | 
    
         
            +
              private :has_trailing_separator?
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
              # add_trailing_separator(path) -> path
         
     | 
| 
      
 162 
     | 
    
         
            +
              def add_trailing_separator(path)
         
     | 
| 
      
 163 
     | 
    
         
            +
                if File.basename(path + 'a') == 'a'
         
     | 
| 
      
 164 
     | 
    
         
            +
                  path
         
     | 
| 
      
 165 
     | 
    
         
            +
                else
         
     | 
| 
      
 166 
     | 
    
         
            +
                  File.join(path, "") # xxx: Is File.join is appropriate to add separator?
         
     | 
| 
      
 167 
     | 
    
         
            +
                end
         
     | 
| 
      
 168 
     | 
    
         
            +
              end
         
     | 
| 
      
 169 
     | 
    
         
            +
              private :add_trailing_separator
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
              def del_trailing_separator(path)
         
     | 
| 
      
 172 
     | 
    
         
            +
                if r = chop_basename(path)
         
     | 
| 
      
 173 
     | 
    
         
            +
                  pre, basename = r
         
     | 
| 
      
 174 
     | 
    
         
            +
                  pre + basename
         
     | 
| 
      
 175 
     | 
    
         
            +
                elsif /#{SEPARATOR_PAT}+\z/o =~ path
         
     | 
| 
      
 176 
     | 
    
         
            +
                  $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o]
         
     | 
| 
      
 177 
     | 
    
         
            +
                else
         
     | 
| 
      
 178 
     | 
    
         
            +
                  path
         
     | 
| 
      
 179 
     | 
    
         
            +
                end
         
     | 
| 
      
 180 
     | 
    
         
            +
              end
         
     | 
| 
      
 181 
     | 
    
         
            +
              private :del_trailing_separator
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
              def cleanpath_conservative
         
     | 
| 
      
 184 
     | 
    
         
            +
                path = @path
         
     | 
| 
      
 185 
     | 
    
         
            +
                names = []
         
     | 
| 
      
 186 
     | 
    
         
            +
                pre = path
         
     | 
| 
      
 187 
     | 
    
         
            +
                while r = chop_basename(pre)
         
     | 
| 
      
 188 
     | 
    
         
            +
                  pre, base = r
         
     | 
| 
      
 189 
     | 
    
         
            +
                  names.unshift base if base != '.'
         
     | 
| 
      
 190 
     | 
    
         
            +
                end
         
     | 
| 
      
 191 
     | 
    
         
            +
                if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
         
     | 
| 
      
 192 
     | 
    
         
            +
                  names.shift while names[0] == '..'
         
     | 
| 
      
 193 
     | 
    
         
            +
                end
         
     | 
| 
      
 194 
     | 
    
         
            +
                if names.empty?
         
     | 
| 
      
 195 
     | 
    
         
            +
                  Path.new(File.dirname(pre))
         
     | 
| 
      
 196 
     | 
    
         
            +
                else
         
     | 
| 
      
 197 
     | 
    
         
            +
                  if names.last != '..' && File.basename(path) == '.'
         
     | 
| 
      
 198 
     | 
    
         
            +
                    names << '.'
         
     | 
| 
      
 199 
     | 
    
         
            +
                  end
         
     | 
| 
      
 200 
     | 
    
         
            +
                  result = prepend_prefix(pre, File.join(*names))
         
     | 
| 
      
 201 
     | 
    
         
            +
                  if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path)
         
     | 
| 
      
 202 
     | 
    
         
            +
                    Path.new(add_trailing_separator(result))
         
     | 
| 
      
 203 
     | 
    
         
            +
                  else
         
     | 
| 
      
 204 
     | 
    
         
            +
                    Path.new(result)
         
     | 
| 
      
 205 
     | 
    
         
            +
                  end
         
     | 
| 
      
 206 
     | 
    
         
            +
                end
         
     | 
| 
      
 207 
     | 
    
         
            +
              end
         
     | 
| 
      
 208 
     | 
    
         
            +
              private :cleanpath_conservative
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
              if File.respond_to?(:realpath) and File.respond_to?(:realdirpath)
         
     | 
| 
      
 211 
     | 
    
         
            +
                def real_path_internal(strict = false, basedir = nil)
         
     | 
| 
      
 212 
     | 
    
         
            +
                  strict ? File.realpath(@path, basedir) : File.realdirpath(@path, basedir)
         
     | 
| 
      
 213 
     | 
    
         
            +
                end
         
     | 
| 
      
 214 
     | 
    
         
            +
                private :real_path_internal
         
     | 
| 
      
 215 
     | 
    
         
            +
              else
         
     | 
| 
      
 216 
     | 
    
         
            +
                def realpath_rec(prefix, unresolved, h, strict, last = true)
         
     | 
| 
      
 217 
     | 
    
         
            +
                  resolved = []
         
     | 
| 
      
 218 
     | 
    
         
            +
                  until unresolved.empty?
         
     | 
| 
      
 219 
     | 
    
         
            +
                    n = unresolved.shift
         
     | 
| 
      
 220 
     | 
    
         
            +
                    if n == '.'
         
     | 
| 
      
 221 
     | 
    
         
            +
                      next
         
     | 
| 
      
 222 
     | 
    
         
            +
                    elsif n == '..'
         
     | 
| 
      
 223 
     | 
    
         
            +
                      resolved.pop
         
     | 
| 
      
 224 
     | 
    
         
            +
                    else
         
     | 
| 
      
 225 
     | 
    
         
            +
                      path = prepend_prefix(prefix, File.join(*(resolved + [n])))
         
     | 
| 
      
 226 
     | 
    
         
            +
                      if h.include? path
         
     | 
| 
      
 227 
     | 
    
         
            +
                        if h[path] == :resolving
         
     | 
| 
      
 228 
     | 
    
         
            +
                          raise Errno::ELOOP.new(path)
         
     | 
| 
      
 229 
     | 
    
         
            +
                        else
         
     | 
| 
      
 230 
     | 
    
         
            +
                          prefix, *resolved = h[path]
         
     | 
| 
      
 231 
     | 
    
         
            +
                        end
         
     | 
| 
      
 232 
     | 
    
         
            +
                      else
         
     | 
| 
      
 233 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 234 
     | 
    
         
            +
                          s = File.lstat(path)
         
     | 
| 
      
 235 
     | 
    
         
            +
                        rescue Errno::ENOENT => e
         
     | 
| 
      
 236 
     | 
    
         
            +
                          raise e if strict || !last || !unresolved.empty?
         
     | 
| 
      
 237 
     | 
    
         
            +
                          resolved << n
         
     | 
| 
      
 238 
     | 
    
         
            +
                          break
         
     | 
| 
      
 239 
     | 
    
         
            +
                        end
         
     | 
| 
      
 240 
     | 
    
         
            +
                        if s.symlink?
         
     | 
| 
      
 241 
     | 
    
         
            +
                          h[path] = :resolving
         
     | 
| 
      
 242 
     | 
    
         
            +
                          link_prefix, link_names = split_names(File.readlink(path))
         
     | 
| 
      
 243 
     | 
    
         
            +
                          if link_prefix == ''
         
     | 
| 
      
 244 
     | 
    
         
            +
                            prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h, strict, unresolved.empty?)
         
     | 
| 
      
 245 
     | 
    
         
            +
                          else
         
     | 
| 
      
 246 
     | 
    
         
            +
                            prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h, strict, unresolved.empty?)
         
     | 
| 
      
 247 
     | 
    
         
            +
                          end
         
     | 
| 
      
 248 
     | 
    
         
            +
                        else
         
     | 
| 
      
 249 
     | 
    
         
            +
                          resolved << n
         
     | 
| 
      
 250 
     | 
    
         
            +
                          h[path] = [prefix, *resolved]
         
     | 
| 
      
 251 
     | 
    
         
            +
                        end
         
     | 
| 
      
 252 
     | 
    
         
            +
                      end
         
     | 
| 
      
 253 
     | 
    
         
            +
                    end
         
     | 
| 
      
 254 
     | 
    
         
            +
                  end
         
     | 
| 
      
 255 
     | 
    
         
            +
                  return prefix, *resolved
         
     | 
| 
      
 256 
     | 
    
         
            +
                end
         
     | 
| 
      
 257 
     | 
    
         
            +
                private :realpath_rec
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
                def real_path_internal(strict = false, basedir = nil)
         
     | 
| 
      
 260 
     | 
    
         
            +
                  path = @path
         
     | 
| 
      
 261 
     | 
    
         
            +
                  path = File.join(basedir, path) if basedir and relative?
         
     | 
| 
      
 262 
     | 
    
         
            +
                  prefix, names = split_names(path)
         
     | 
| 
      
 263 
     | 
    
         
            +
                  if prefix == ''
         
     | 
| 
      
 264 
     | 
    
         
            +
                    prefix, names2 = split_names(Dir.pwd)
         
     | 
| 
      
 265 
     | 
    
         
            +
                    names = names2 + names
         
     | 
| 
      
 266 
     | 
    
         
            +
                  end
         
     | 
| 
      
 267 
     | 
    
         
            +
                  prefix, *names = realpath_rec(prefix, names, {}, strict)
         
     | 
| 
      
 268 
     | 
    
         
            +
                  prepend_prefix(prefix, File.join(*names))
         
     | 
| 
      
 269 
     | 
    
         
            +
                end
         
     | 
| 
      
 270 
     | 
    
         
            +
                private :real_path_internal
         
     | 
| 
      
 271 
     | 
    
         
            +
              end
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
              #
         
     | 
| 
      
 274 
     | 
    
         
            +
              # Returns the real (absolute) pathname of +self+ in the actual
         
     | 
| 
      
 275 
     | 
    
         
            +
              # filesystem not containing symlinks or useless dots.
         
     | 
| 
      
 276 
     | 
    
         
            +
              #
         
     | 
| 
      
 277 
     | 
    
         
            +
              # All components of the pathname must exist when this method is
         
     | 
| 
      
 278 
     | 
    
         
            +
              # called.
         
     | 
| 
      
 279 
     | 
    
         
            +
              #
         
     | 
| 
      
 280 
     | 
    
         
            +
              def realpath(basedir=nil)
         
     | 
| 
      
 281 
     | 
    
         
            +
                Path.new(real_path_internal(true, basedir))
         
     | 
| 
      
 282 
     | 
    
         
            +
              end
         
     | 
| 
      
 283 
     | 
    
         
            +
             
     | 
| 
      
 284 
     | 
    
         
            +
              #
         
     | 
| 
      
 285 
     | 
    
         
            +
              # Returns the real (absolute) pathname of +self+ in the actual filesystem.
         
     | 
| 
      
 286 
     | 
    
         
            +
              # The real pathname doesn't contain symlinks or useless dots.
         
     | 
| 
      
 287 
     | 
    
         
            +
              #
         
     | 
| 
      
 288 
     | 
    
         
            +
              # The last component of the real pathname can be nonexistent.
         
     | 
| 
      
 289 
     | 
    
         
            +
              #
         
     | 
| 
      
 290 
     | 
    
         
            +
              def realdirpath(basedir=nil)
         
     | 
| 
      
 291 
     | 
    
         
            +
                Path.new(real_path_internal(false, basedir))
         
     | 
| 
      
 292 
     | 
    
         
            +
              end
         
     | 
| 
      
 293 
     | 
    
         
            +
             
     | 
| 
      
 294 
     | 
    
         
            +
              # #parent returns the parent directory.
         
     | 
| 
      
 295 
     | 
    
         
            +
              #
         
     | 
| 
      
 296 
     | 
    
         
            +
              # This is same as <tt>self + '..'</tt>.
         
     | 
| 
      
 297 
     | 
    
         
            +
              def parent
         
     | 
| 
      
 298 
     | 
    
         
            +
                self + '..'
         
     | 
| 
      
 299 
     | 
    
         
            +
              end
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
              # #mountpoint? returns +true+ if <tt>self</tt> points to a mountpoint.
         
     | 
| 
      
 302 
     | 
    
         
            +
              def mountpoint?
         
     | 
| 
      
 303 
     | 
    
         
            +
                begin
         
     | 
| 
      
 304 
     | 
    
         
            +
                  stat1 = lstat
         
     | 
| 
      
 305 
     | 
    
         
            +
                  stat2 = parent.lstat
         
     | 
| 
      
 306 
     | 
    
         
            +
                  stat1.dev != stat2.dev or stat1.ino == stat2.ino
         
     | 
| 
      
 307 
     | 
    
         
            +
                rescue Errno::ENOENT
         
     | 
| 
      
 308 
     | 
    
         
            +
                  false
         
     | 
| 
      
 309 
     | 
    
         
            +
                end
         
     | 
| 
      
 310 
     | 
    
         
            +
              end
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
              #
         
     | 
| 
      
 313 
     | 
    
         
            +
              # #root? is a predicate for root directories.  I.e. it returns +true+ if the
         
     | 
| 
      
 314 
     | 
    
         
            +
              # pathname consists of consecutive slashes.
         
     | 
| 
      
 315 
     | 
    
         
            +
              #
         
     | 
| 
      
 316 
     | 
    
         
            +
              # It doesn't access actual filesystem.  So it may return +false+ for some
         
     | 
| 
      
 317 
     | 
    
         
            +
              # pathnames which points to roots such as <tt>/usr/..</tt>.
         
     | 
| 
      
 318 
     | 
    
         
            +
              #
         
     | 
| 
      
 319 
     | 
    
         
            +
              def root?
         
     | 
| 
      
 320 
     | 
    
         
            +
                !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path)
         
     | 
| 
      
 321 
     | 
    
         
            +
              end
         
     | 
| 
      
 322 
     | 
    
         
            +
             
     | 
| 
      
 323 
     | 
    
         
            +
              # Predicate method for testing whether a path is absolute.
         
     | 
| 
      
 324 
     | 
    
         
            +
              # It returns +true+ if the pathname begins with a slash.
         
     | 
| 
      
 325 
     | 
    
         
            +
              def absolute?
         
     | 
| 
      
 326 
     | 
    
         
            +
                !relative?
         
     | 
| 
      
 327 
     | 
    
         
            +
              end
         
     | 
| 
      
 328 
     | 
    
         
            +
             
     | 
| 
      
 329 
     | 
    
         
            +
              # The opposite of #absolute?
         
     | 
| 
      
 330 
     | 
    
         
            +
              def relative?
         
     | 
| 
      
 331 
     | 
    
         
            +
                path = @path
         
     | 
| 
      
 332 
     | 
    
         
            +
                while r = chop_basename(path)
         
     | 
| 
      
 333 
     | 
    
         
            +
                  path, = r
         
     | 
| 
      
 334 
     | 
    
         
            +
                end
         
     | 
| 
      
 335 
     | 
    
         
            +
                path == ''
         
     | 
| 
      
 336 
     | 
    
         
            +
              end
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
              #
         
     | 
| 
      
 339 
     | 
    
         
            +
              # Iterates over each component of the path.
         
     | 
| 
      
 340 
     | 
    
         
            +
              #
         
     | 
| 
      
 341 
     | 
    
         
            +
              #   Path.new("/usr/bin/ruby").each_filename {|filename| ... }
         
     | 
| 
      
 342 
     | 
    
         
            +
              #     # yields "usr", "bin", and "ruby".
         
     | 
| 
      
 343 
     | 
    
         
            +
              #
         
     | 
| 
      
 344 
     | 
    
         
            +
              def each_filename # :yield: filename
         
     | 
| 
      
 345 
     | 
    
         
            +
                return to_enum(__method__) unless block_given?
         
     | 
| 
      
 346 
     | 
    
         
            +
                _, names = split_names(@path)
         
     | 
| 
      
 347 
     | 
    
         
            +
                names.each {|filename| yield filename }
         
     | 
| 
      
 348 
     | 
    
         
            +
                nil
         
     | 
| 
      
 349 
     | 
    
         
            +
              end
         
     | 
| 
      
 350 
     | 
    
         
            +
             
     | 
| 
      
 351 
     | 
    
         
            +
              # Iterates over and yields a new Path object
         
     | 
| 
      
 352 
     | 
    
         
            +
              # for each element in the given path in descending order.
         
     | 
| 
      
 353 
     | 
    
         
            +
              #
         
     | 
| 
      
 354 
     | 
    
         
            +
              #  Path.new('/path/to/some/file.rb').descend {|v| p v}
         
     | 
| 
      
 355 
     | 
    
         
            +
              #     #<Path:/>
         
     | 
| 
      
 356 
     | 
    
         
            +
              #     #<Path:/path>
         
     | 
| 
      
 357 
     | 
    
         
            +
              #     #<Path:/path/to>
         
     | 
| 
      
 358 
     | 
    
         
            +
              #     #<Path:/path/to/some>
         
     | 
| 
      
 359 
     | 
    
         
            +
              #     #<Path:/path/to/some/file.rb>
         
     | 
| 
      
 360 
     | 
    
         
            +
              #
         
     | 
| 
      
 361 
     | 
    
         
            +
              #  Path.new('path/to/some/file.rb').descend {|v| p v}
         
     | 
| 
      
 362 
     | 
    
         
            +
              #     #<Path:path>
         
     | 
| 
      
 363 
     | 
    
         
            +
              #     #<Path:path/to>
         
     | 
| 
      
 364 
     | 
    
         
            +
              #     #<Path:path/to/some>
         
     | 
| 
      
 365 
     | 
    
         
            +
              #     #<Path:path/to/some/file.rb>
         
     | 
| 
      
 366 
     | 
    
         
            +
              #
         
     | 
| 
      
 367 
     | 
    
         
            +
              # It doesn't access actual filesystem.
         
     | 
| 
      
 368 
     | 
    
         
            +
              def descend
         
     | 
| 
      
 369 
     | 
    
         
            +
                vs = []
         
     | 
| 
      
 370 
     | 
    
         
            +
                ascend {|v| vs << v }
         
     | 
| 
      
 371 
     | 
    
         
            +
                vs.reverse_each {|v| yield v }
         
     | 
| 
      
 372 
     | 
    
         
            +
                nil
         
     | 
| 
      
 373 
     | 
    
         
            +
              end
         
     | 
| 
      
 374 
     | 
    
         
            +
             
     | 
| 
      
 375 
     | 
    
         
            +
              # Iterates over and yields a new Path object
         
     | 
| 
      
 376 
     | 
    
         
            +
              # for each element in the given path in ascending order.
         
     | 
| 
      
 377 
     | 
    
         
            +
              #
         
     | 
| 
      
 378 
     | 
    
         
            +
              #  Path.new('/path/to/some/file.rb').ascend {|v| p v}
         
     | 
| 
      
 379 
     | 
    
         
            +
              #     #<Path:/path/to/some/file.rb>
         
     | 
| 
      
 380 
     | 
    
         
            +
              #     #<Path:/path/to/some>
         
     | 
| 
      
 381 
     | 
    
         
            +
              #     #<Path:/path/to>
         
     | 
| 
      
 382 
     | 
    
         
            +
              #     #<Path:/path>
         
     | 
| 
      
 383 
     | 
    
         
            +
              #     #<Path:/>
         
     | 
| 
      
 384 
     | 
    
         
            +
              #
         
     | 
| 
      
 385 
     | 
    
         
            +
              #  Path.new('path/to/some/file.rb').ascend {|v| p v}
         
     | 
| 
      
 386 
     | 
    
         
            +
              #     #<Path:path/to/some/file.rb>
         
     | 
| 
      
 387 
     | 
    
         
            +
              #     #<Path:path/to/some>
         
     | 
| 
      
 388 
     | 
    
         
            +
              #     #<Path:path/to>
         
     | 
| 
      
 389 
     | 
    
         
            +
              #     #<Path:path>
         
     | 
| 
      
 390 
     | 
    
         
            +
              #
         
     | 
| 
      
 391 
     | 
    
         
            +
              # It doesn't access actual filesystem.
         
     | 
| 
      
 392 
     | 
    
         
            +
              def ascend
         
     | 
| 
      
 393 
     | 
    
         
            +
                path = @path
         
     | 
| 
      
 394 
     | 
    
         
            +
                yield self
         
     | 
| 
      
 395 
     | 
    
         
            +
                while r = chop_basename(path)
         
     | 
| 
      
 396 
     | 
    
         
            +
                  path, = r
         
     | 
| 
      
 397 
     | 
    
         
            +
                  break if path.empty?
         
     | 
| 
      
 398 
     | 
    
         
            +
                  yield Path.new(del_trailing_separator(path))
         
     | 
| 
      
 399 
     | 
    
         
            +
                end
         
     | 
| 
      
 400 
     | 
    
         
            +
              end
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
              #
         
     | 
| 
      
 403 
     | 
    
         
            +
              # Path#+ appends a pathname fragment to this one to produce a new Path
         
     | 
| 
      
 404 
     | 
    
         
            +
              # object.
         
     | 
| 
      
 405 
     | 
    
         
            +
              #
         
     | 
| 
      
 406 
     | 
    
         
            +
              #   p1 = Path.new("/usr")      # Path:/usr
         
     | 
| 
      
 407 
     | 
    
         
            +
              #   p2 = p1 + "bin/ruby"           # Path:/usr/bin/ruby
         
     | 
| 
      
 408 
     | 
    
         
            +
              #   p3 = p1 + "/etc/passwd"        # Path:/etc/passwd
         
     | 
| 
      
 409 
     | 
    
         
            +
              #
         
     | 
| 
      
 410 
     | 
    
         
            +
              # This method doesn't access the file system; it is pure string manipulation.
         
     | 
| 
      
 411 
     | 
    
         
            +
              #
         
     | 
| 
      
 412 
     | 
    
         
            +
              def +(other)
         
     | 
| 
      
 413 
     | 
    
         
            +
                other = Path.new(other) unless Path === other
         
     | 
| 
      
 414 
     | 
    
         
            +
                Path.new(plus(@path, other.to_s))
         
     | 
| 
      
 415 
     | 
    
         
            +
              end
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
              def plus(path1, path2) # -> path
         
     | 
| 
      
 418 
     | 
    
         
            +
                prefix2 = path2
         
     | 
| 
      
 419 
     | 
    
         
            +
                index_list2 = []
         
     | 
| 
      
 420 
     | 
    
         
            +
                basename_list2 = []
         
     | 
| 
      
 421 
     | 
    
         
            +
                while r2 = chop_basename(prefix2)
         
     | 
| 
      
 422 
     | 
    
         
            +
                  prefix2, basename2 = r2
         
     | 
| 
      
 423 
     | 
    
         
            +
                  index_list2.unshift prefix2.length
         
     | 
| 
      
 424 
     | 
    
         
            +
                  basename_list2.unshift basename2
         
     | 
| 
      
 425 
     | 
    
         
            +
                end
         
     | 
| 
      
 426 
     | 
    
         
            +
                return path2 if prefix2 != ''
         
     | 
| 
      
 427 
     | 
    
         
            +
                prefix1 = path1
         
     | 
| 
      
 428 
     | 
    
         
            +
                while true
         
     | 
| 
      
 429 
     | 
    
         
            +
                  while !basename_list2.empty? && basename_list2.first == '.'
         
     | 
| 
      
 430 
     | 
    
         
            +
                    index_list2.shift
         
     | 
| 
      
 431 
     | 
    
         
            +
                    basename_list2.shift
         
     | 
| 
      
 432 
     | 
    
         
            +
                  end
         
     | 
| 
      
 433 
     | 
    
         
            +
                  break unless r1 = chop_basename(prefix1)
         
     | 
| 
      
 434 
     | 
    
         
            +
                  prefix1, basename1 = r1
         
     | 
| 
      
 435 
     | 
    
         
            +
                  next if basename1 == '.'
         
     | 
| 
      
 436 
     | 
    
         
            +
                  if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..'
         
     | 
| 
      
 437 
     | 
    
         
            +
                    prefix1 = prefix1 + basename1
         
     | 
| 
      
 438 
     | 
    
         
            +
                    break
         
     | 
| 
      
 439 
     | 
    
         
            +
                  end
         
     | 
| 
      
 440 
     | 
    
         
            +
                  index_list2.shift
         
     | 
| 
      
 441 
     | 
    
         
            +
                  basename_list2.shift
         
     | 
| 
      
 442 
     | 
    
         
            +
                end
         
     | 
| 
      
 443 
     | 
    
         
            +
                r1 = chop_basename(prefix1)
         
     | 
| 
      
 444 
     | 
    
         
            +
                if !r1 && /#{SEPARATOR_PAT}/o =~ File.basename(prefix1)
         
     | 
| 
      
 445 
     | 
    
         
            +
                  while !basename_list2.empty? && basename_list2.first == '..'
         
     | 
| 
      
 446 
     | 
    
         
            +
                    index_list2.shift
         
     | 
| 
      
 447 
     | 
    
         
            +
                    basename_list2.shift
         
     | 
| 
      
 448 
     | 
    
         
            +
                  end
         
     | 
| 
      
 449 
     | 
    
         
            +
                end
         
     | 
| 
      
 450 
     | 
    
         
            +
                if !basename_list2.empty?
         
     | 
| 
      
 451 
     | 
    
         
            +
                  suffix2 = path2[index_list2.first..-1]
         
     | 
| 
      
 452 
     | 
    
         
            +
                  r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2
         
     | 
| 
      
 453 
     | 
    
         
            +
                else
         
     | 
| 
      
 454 
     | 
    
         
            +
                  r1 ? prefix1 : File.dirname(prefix1)
         
     | 
| 
      
 455 
     | 
    
         
            +
                end
         
     | 
| 
      
 456 
     | 
    
         
            +
              end
         
     | 
| 
      
 457 
     | 
    
         
            +
              private :plus
         
     | 
| 
      
 458 
     | 
    
         
            +
             
     | 
| 
      
 459 
     | 
    
         
            +
              #
         
     | 
| 
      
 460 
     | 
    
         
            +
              # Path#join joins pathnames.
         
     | 
| 
      
 461 
     | 
    
         
            +
              #
         
     | 
| 
      
 462 
     | 
    
         
            +
              # <tt>path0.join(path1, ..., pathN)</tt> is the same as
         
     | 
| 
      
 463 
     | 
    
         
            +
              # <tt>path0 + path1 + ... + pathN</tt>.
         
     | 
| 
      
 464 
     | 
    
         
            +
              #
         
     | 
| 
      
 465 
     | 
    
         
            +
              def join(*args)
         
     | 
| 
      
 466 
     | 
    
         
            +
                args.unshift self
         
     | 
| 
      
 467 
     | 
    
         
            +
                result = args.pop
         
     | 
| 
      
 468 
     | 
    
         
            +
                result = Path.new(result) unless Path === result
         
     | 
| 
      
 469 
     | 
    
         
            +
                return result if result.absolute?
         
     | 
| 
      
 470 
     | 
    
         
            +
                args.reverse_each {|arg|
         
     | 
| 
      
 471 
     | 
    
         
            +
                  arg = Path.new(arg) unless Path === arg
         
     | 
| 
      
 472 
     | 
    
         
            +
                  result = arg + result
         
     | 
| 
      
 473 
     | 
    
         
            +
                  return result if result.absolute?
         
     | 
| 
      
 474 
     | 
    
         
            +
                }
         
     | 
| 
      
 475 
     | 
    
         
            +
                result
         
     | 
| 
      
 476 
     | 
    
         
            +
              end
         
     | 
| 
      
 477 
     | 
    
         
            +
             
     | 
| 
      
 478 
     | 
    
         
            +
              #
         
     | 
| 
      
 479 
     | 
    
         
            +
              # Returns the children of the directory (files and subdirectories, not
         
     | 
| 
      
 480 
     | 
    
         
            +
              # recursive) as an array of Path objects.  By default, the returned
         
     | 
| 
      
 481 
     | 
    
         
            +
              # pathnames will have enough information to access the files.  If you set
         
     | 
| 
      
 482 
     | 
    
         
            +
              # +with_directory+ to +false+, then the returned pathnames will contain the
         
     | 
| 
      
 483 
     | 
    
         
            +
              # filename only.
         
     | 
| 
      
 484 
     | 
    
         
            +
              #
         
     | 
| 
      
 485 
     | 
    
         
            +
              # For example:
         
     | 
| 
      
 486 
     | 
    
         
            +
              #   pn = Path("/usr/lib/ruby/1.8")
         
     | 
| 
      
 487 
     | 
    
         
            +
              #   pn.children
         
     | 
| 
      
 488 
     | 
    
         
            +
              #       # -> [ Path:/usr/lib/ruby/1.8/English.rb,
         
     | 
| 
      
 489 
     | 
    
         
            +
              #              Path:/usr/lib/ruby/1.8/Env.rb,
         
     | 
| 
      
 490 
     | 
    
         
            +
              #              Path:/usr/lib/ruby/1.8/abbrev.rb, ... ]
         
     | 
| 
      
 491 
     | 
    
         
            +
              #   pn.children(false)
         
     | 
| 
      
 492 
     | 
    
         
            +
              #       # -> [ Path:English.rb, Path:Env.rb, Path:abbrev.rb, ... ]
         
     | 
| 
      
 493 
     | 
    
         
            +
              #
         
     | 
| 
      
 494 
     | 
    
         
            +
              # Note that the results never contain the entries <tt>.</tt> and <tt>..</tt> in
         
     | 
| 
      
 495 
     | 
    
         
            +
              # the directory because they are not children.
         
     | 
| 
      
 496 
     | 
    
         
            +
              #
         
     | 
| 
      
 497 
     | 
    
         
            +
              def children(with_directory=true)
         
     | 
| 
      
 498 
     | 
    
         
            +
                with_directory = false if @path == '.'
         
     | 
| 
      
 499 
     | 
    
         
            +
                result = []
         
     | 
| 
      
 500 
     | 
    
         
            +
                Dir.foreach(@path) {|e|
         
     | 
| 
      
 501 
     | 
    
         
            +
                  next if e == '.' || e == '..'
         
     | 
| 
      
 502 
     | 
    
         
            +
                  if with_directory
         
     | 
| 
      
 503 
     | 
    
         
            +
                    result << Path.new(File.join(@path, e))
         
     | 
| 
      
 504 
     | 
    
         
            +
                  else
         
     | 
| 
      
 505 
     | 
    
         
            +
                    result << Path.new(e)
         
     | 
| 
      
 506 
     | 
    
         
            +
                  end
         
     | 
| 
      
 507 
     | 
    
         
            +
                }
         
     | 
| 
      
 508 
     | 
    
         
            +
                result
         
     | 
| 
      
 509 
     | 
    
         
            +
              end
         
     | 
| 
      
 510 
     | 
    
         
            +
             
     | 
| 
      
 511 
     | 
    
         
            +
              # Iterates over the children of the directory
         
     | 
| 
      
 512 
     | 
    
         
            +
              # (files and subdirectories, not recursive).
         
     | 
| 
      
 513 
     | 
    
         
            +
              # It yields Path object for each child.
         
     | 
| 
      
 514 
     | 
    
         
            +
              # By default, the yielded pathnames will have enough information to access the files.
         
     | 
| 
      
 515 
     | 
    
         
            +
              # If you set +with_directory+ to +false+, then the returned pathnames will contain the filename only.
         
     | 
| 
      
 516 
     | 
    
         
            +
              #
         
     | 
| 
      
 517 
     | 
    
         
            +
              #   Path("/usr/local").each_child {|f| p f }
         
     | 
| 
      
 518 
     | 
    
         
            +
              #   #=> #<Path:/usr/local/share>
         
     | 
| 
      
 519 
     | 
    
         
            +
              #   #   #<Path:/usr/local/bin>
         
     | 
| 
      
 520 
     | 
    
         
            +
              #   #   #<Path:/usr/local/games>
         
     | 
| 
      
 521 
     | 
    
         
            +
              #   #   #<Path:/usr/local/lib>
         
     | 
| 
      
 522 
     | 
    
         
            +
              #   #   #<Path:/usr/local/include>
         
     | 
| 
      
 523 
     | 
    
         
            +
              #   #   #<Path:/usr/local/sbin>
         
     | 
| 
      
 524 
     | 
    
         
            +
              #   #   #<Path:/usr/local/src>
         
     | 
| 
      
 525 
     | 
    
         
            +
              #   #   #<Path:/usr/local/man>
         
     | 
| 
      
 526 
     | 
    
         
            +
              #
         
     | 
| 
      
 527 
     | 
    
         
            +
              #   Path("/usr/local").each_child(false) {|f| p f }
         
     | 
| 
      
 528 
     | 
    
         
            +
              #   #=> #<Path:share>
         
     | 
| 
      
 529 
     | 
    
         
            +
              #   #   #<Path:bin>
         
     | 
| 
      
 530 
     | 
    
         
            +
              #   #   #<Path:games>
         
     | 
| 
      
 531 
     | 
    
         
            +
              #   #   #<Path:lib>
         
     | 
| 
      
 532 
     | 
    
         
            +
              #   #   #<Path:include>
         
     | 
| 
      
 533 
     | 
    
         
            +
              #   #   #<Path:sbin>
         
     | 
| 
      
 534 
     | 
    
         
            +
              #   #   #<Path:src>
         
     | 
| 
      
 535 
     | 
    
         
            +
              #   #   #<Path:man>
         
     | 
| 
      
 536 
     | 
    
         
            +
              #
         
     | 
| 
      
 537 
     | 
    
         
            +
              def each_child(with_directory=true, &b)
         
     | 
| 
      
 538 
     | 
    
         
            +
                children(with_directory).each(&b)
         
     | 
| 
      
 539 
     | 
    
         
            +
              end
         
     | 
| 
      
 540 
     | 
    
         
            +
             
     | 
| 
      
 541 
     | 
    
         
            +
              #
         
     | 
| 
      
 542 
     | 
    
         
            +
              # #relative_path_from returns a relative path from the argument to the
         
     | 
| 
      
 543 
     | 
    
         
            +
              # receiver.  If +self+ is absolute, the argument must be absolute too.  If
         
     | 
| 
      
 544 
     | 
    
         
            +
              # +self+ is relative, the argument must be relative too.
         
     | 
| 
      
 545 
     | 
    
         
            +
              #
         
     | 
| 
      
 546 
     | 
    
         
            +
              # #relative_path_from doesn't access the filesystem.  It assumes no symlinks.
         
     | 
| 
      
 547 
     | 
    
         
            +
              #
         
     | 
| 
      
 548 
     | 
    
         
            +
              # ArgumentError is raised when it cannot find a relative path.
         
     | 
| 
      
 549 
     | 
    
         
            +
              #
         
     | 
| 
      
 550 
     | 
    
         
            +
              def relative_path_from(base_directory)
         
     | 
| 
      
 551 
     | 
    
         
            +
                dest_directory = cleanpath.to_s
         
     | 
| 
      
 552 
     | 
    
         
            +
                base_directory = base_directory.cleanpath.to_s
         
     | 
| 
      
 553 
     | 
    
         
            +
                dest_prefix = dest_directory
         
     | 
| 
      
 554 
     | 
    
         
            +
                dest_names = []
         
     | 
| 
      
 555 
     | 
    
         
            +
                while r = chop_basename(dest_prefix)
         
     | 
| 
      
 556 
     | 
    
         
            +
                  dest_prefix, basename = r
         
     | 
| 
      
 557 
     | 
    
         
            +
                  dest_names.unshift basename if basename != '.'
         
     | 
| 
      
 558 
     | 
    
         
            +
                end
         
     | 
| 
      
 559 
     | 
    
         
            +
                base_prefix = base_directory
         
     | 
| 
      
 560 
     | 
    
         
            +
                base_names = []
         
     | 
| 
      
 561 
     | 
    
         
            +
                while r = chop_basename(base_prefix)
         
     | 
| 
      
 562 
     | 
    
         
            +
                  base_prefix, basename = r
         
     | 
| 
      
 563 
     | 
    
         
            +
                  base_names.unshift basename if basename != '.'
         
     | 
| 
      
 564 
     | 
    
         
            +
                end
         
     | 
| 
      
 565 
     | 
    
         
            +
                unless SAME_PATHS[dest_prefix, base_prefix]
         
     | 
| 
      
 566 
     | 
    
         
            +
                  raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
         
     | 
| 
      
 567 
     | 
    
         
            +
                end
         
     | 
| 
      
 568 
     | 
    
         
            +
                while !dest_names.empty? &&
         
     | 
| 
      
 569 
     | 
    
         
            +
                      !base_names.empty? &&
         
     | 
| 
      
 570 
     | 
    
         
            +
                      SAME_PATHS[dest_names.first, base_names.first]
         
     | 
| 
      
 571 
     | 
    
         
            +
                  dest_names.shift
         
     | 
| 
      
 572 
     | 
    
         
            +
                  base_names.shift
         
     | 
| 
      
 573 
     | 
    
         
            +
                end
         
     | 
| 
      
 574 
     | 
    
         
            +
                if base_names.include? '..'
         
     | 
| 
      
 575 
     | 
    
         
            +
                  raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
         
     | 
| 
      
 576 
     | 
    
         
            +
                end
         
     | 
| 
      
 577 
     | 
    
         
            +
                base_names.fill('..')
         
     | 
| 
      
 578 
     | 
    
         
            +
                relpath_names = base_names + dest_names
         
     | 
| 
      
 579 
     | 
    
         
            +
                if relpath_names.empty?
         
     | 
| 
      
 580 
     | 
    
         
            +
                  Path.new('.')
         
     | 
| 
      
 581 
     | 
    
         
            +
                else
         
     | 
| 
      
 582 
     | 
    
         
            +
                  Path.new(File.join(*relpath_names))
         
     | 
| 
      
 583 
     | 
    
         
            +
                end
         
     | 
| 
      
 584 
     | 
    
         
            +
              end
         
     | 
| 
      
 585 
     | 
    
         
            +
            end
         
     | 
| 
      
 586 
     | 
    
         
            +
             
     | 
| 
      
 587 
     | 
    
         
            +
            class Path    # * IO *
         
     | 
| 
      
 588 
     | 
    
         
            +
              #
         
     | 
| 
      
 589 
     | 
    
         
            +
              # #each_line iterates over the line in the file.  It yields a String object
         
     | 
| 
      
 590 
     | 
    
         
            +
              # for each line.
         
     | 
| 
      
 591 
     | 
    
         
            +
              #
         
     | 
| 
      
 592 
     | 
    
         
            +
              def each_line(*args, &block) # :yield: line
         
     | 
| 
      
 593 
     | 
    
         
            +
                IO.foreach(@path, *args, &block)
         
     | 
| 
      
 594 
     | 
    
         
            +
              end
         
     | 
| 
      
 595 
     | 
    
         
            +
             
     | 
| 
      
 596 
     | 
    
         
            +
              # See <tt>IO.read</tt>.  Returns all data from the file, or the first +N+ bytes
         
     | 
| 
      
 597 
     | 
    
         
            +
              # if specified.
         
     | 
| 
      
 598 
     | 
    
         
            +
              def read(*args) IO.read(@path, *args) end
         
     | 
| 
      
 599 
     | 
    
         
            +
             
     | 
| 
      
 600 
     | 
    
         
            +
              # See <tt>IO.binread</tt>.  Returns all the bytes from the file, or the first +N+
         
     | 
| 
      
 601 
     | 
    
         
            +
              # if specified.
         
     | 
| 
      
 602 
     | 
    
         
            +
              def binread(*args) IO.binread(@path, *args) end
         
     | 
| 
      
 603 
     | 
    
         
            +
             
     | 
| 
      
 604 
     | 
    
         
            +
              # See <tt>IO.readlines</tt>.  Returns all the lines from the file.
         
     | 
| 
      
 605 
     | 
    
         
            +
              def readlines(*args) IO.readlines(@path, *args) end
         
     | 
| 
      
 606 
     | 
    
         
            +
             
     | 
| 
      
 607 
     | 
    
         
            +
              # See <tt>IO.sysopen</tt>.
         
     | 
| 
      
 608 
     | 
    
         
            +
              def sysopen(*args) IO.sysopen(@path, *args) end
         
     | 
| 
      
 609 
     | 
    
         
            +
            end
         
     | 
| 
      
 610 
     | 
    
         
            +
             
     | 
| 
      
 611 
     | 
    
         
            +
             
     | 
| 
      
 612 
     | 
    
         
            +
            class Path    # * File *
         
     | 
| 
      
 613 
     | 
    
         
            +
             
     | 
| 
      
 614 
     | 
    
         
            +
              # See <tt>File.atime</tt>.  Returns last access time.
         
     | 
| 
      
 615 
     | 
    
         
            +
              def atime() File.atime(@path) end
         
     | 
| 
      
 616 
     | 
    
         
            +
             
     | 
| 
      
 617 
     | 
    
         
            +
              # See <tt>File.ctime</tt>.  Returns last (directory entry, not file) change time.
         
     | 
| 
      
 618 
     | 
    
         
            +
              def ctime() File.ctime(@path) end
         
     | 
| 
      
 619 
     | 
    
         
            +
             
     | 
| 
      
 620 
     | 
    
         
            +
              # See <tt>File.mtime</tt>.  Returns last modification time.
         
     | 
| 
      
 621 
     | 
    
         
            +
              def mtime() File.mtime(@path) end
         
     | 
| 
      
 622 
     | 
    
         
            +
             
     | 
| 
      
 623 
     | 
    
         
            +
              # See <tt>File.chmod</tt>.  Changes permissions.
         
     | 
| 
      
 624 
     | 
    
         
            +
              def chmod(mode) File.chmod(mode, @path) end
         
     | 
| 
      
 625 
     | 
    
         
            +
             
     | 
| 
      
 626 
     | 
    
         
            +
              # See <tt>File.lchmod</tt>.
         
     | 
| 
      
 627 
     | 
    
         
            +
              def lchmod(mode) File.lchmod(mode, @path) end
         
     | 
| 
      
 628 
     | 
    
         
            +
             
     | 
| 
      
 629 
     | 
    
         
            +
              # See <tt>File.chown</tt>.  Change owner and group of file.
         
     | 
| 
      
 630 
     | 
    
         
            +
              def chown(owner, group) File.chown(owner, group, @path) end
         
     | 
| 
      
 631 
     | 
    
         
            +
             
     | 
| 
      
 632 
     | 
    
         
            +
              # See <tt>File.lchown</tt>.
         
     | 
| 
      
 633 
     | 
    
         
            +
              def lchown(owner, group) File.lchown(owner, group, @path) end
         
     | 
| 
      
 634 
     | 
    
         
            +
             
     | 
| 
      
 635 
     | 
    
         
            +
              # See <tt>File.fnmatch</tt>.  Return +true+ if the receiver matches the given
         
     | 
| 
      
 636 
     | 
    
         
            +
              # pattern.
         
     | 
| 
      
 637 
     | 
    
         
            +
              def fnmatch(pattern, *args) File.fnmatch(pattern, @path, *args) end
         
     | 
| 
      
 638 
     | 
    
         
            +
             
     | 
| 
      
 639 
     | 
    
         
            +
              # See <tt>File.fnmatch?</tt> (same as #fnmatch).
         
     | 
| 
      
 640 
     | 
    
         
            +
              def fnmatch?(pattern, *args) File.fnmatch?(pattern, @path, *args) end
         
     | 
| 
      
 641 
     | 
    
         
            +
             
     | 
| 
      
 642 
     | 
    
         
            +
              # See <tt>File.ftype</tt>.  Returns "type" of file ("file", "directory",
         
     | 
| 
      
 643 
     | 
    
         
            +
              # etc).
         
     | 
| 
      
 644 
     | 
    
         
            +
              def ftype() File.ftype(@path) end
         
     | 
| 
      
 645 
     | 
    
         
            +
             
     | 
| 
      
 646 
     | 
    
         
            +
              # See <tt>File.link</tt>.  Creates a hard link.
         
     | 
| 
      
 647 
     | 
    
         
            +
              def make_link(old) File.link(old, @path) end
         
     | 
| 
      
 648 
     | 
    
         
            +
             
     | 
| 
      
 649 
     | 
    
         
            +
              # See <tt>File.open</tt>.  Opens the file for reading or writing.
         
     | 
| 
      
 650 
     | 
    
         
            +
              def open(*args, &block) # :yield: file
         
     | 
| 
      
 651 
     | 
    
         
            +
                File.open(@path, *args, &block)
         
     | 
| 
      
 652 
     | 
    
         
            +
              end
         
     | 
| 
      
 653 
     | 
    
         
            +
             
     | 
| 
      
 654 
     | 
    
         
            +
              # See <tt>File.readlink</tt>.  Read symbolic link.
         
     | 
| 
      
 655 
     | 
    
         
            +
              def readlink() Path.new(File.readlink(@path)) end
         
     | 
| 
      
 656 
     | 
    
         
            +
             
     | 
| 
      
 657 
     | 
    
         
            +
              # See <tt>File.rename</tt>.  Rename the file.
         
     | 
| 
      
 658 
     | 
    
         
            +
              def rename(to) File.rename(@path, to) end
         
     | 
| 
      
 659 
     | 
    
         
            +
             
     | 
| 
      
 660 
     | 
    
         
            +
              # See <tt>File.stat</tt>.  Returns a <tt>File::Stat</tt> object.
         
     | 
| 
      
 661 
     | 
    
         
            +
              def stat() File.stat(@path) end
         
     | 
| 
      
 662 
     | 
    
         
            +
             
     | 
| 
      
 663 
     | 
    
         
            +
              # See <tt>File.lstat</tt>.
         
     | 
| 
      
 664 
     | 
    
         
            +
              def lstat() File.lstat(@path) end
         
     | 
| 
      
 665 
     | 
    
         
            +
             
     | 
| 
      
 666 
     | 
    
         
            +
              # See <tt>File.symlink</tt>.  Creates a symbolic link.
         
     | 
| 
      
 667 
     | 
    
         
            +
              def make_symlink(old) File.symlink(old, @path) end
         
     | 
| 
      
 668 
     | 
    
         
            +
             
     | 
| 
      
 669 
     | 
    
         
            +
              # See <tt>File.truncate</tt>.  Truncate the file to +length+ bytes.
         
     | 
| 
      
 670 
     | 
    
         
            +
              def truncate(length) File.truncate(@path, length) end
         
     | 
| 
      
 671 
     | 
    
         
            +
             
     | 
| 
      
 672 
     | 
    
         
            +
              # See <tt>File.utime</tt>.  Update the access and modification times.
         
     | 
| 
      
 673 
     | 
    
         
            +
              def utime(atime, mtime) File.utime(atime, mtime, @path) end
         
     | 
| 
      
 674 
     | 
    
         
            +
             
     | 
| 
      
 675 
     | 
    
         
            +
              # See <tt>File.basename</tt>.  Returns the last component of the path.
         
     | 
| 
      
 676 
     | 
    
         
            +
              def basename(*args) Path.new(File.basename(@path, *args)) end
         
     | 
| 
      
 677 
     | 
    
         
            +
             
     | 
| 
      
 678 
     | 
    
         
            +
              # See <tt>File.dirname</tt>.  Returns all but the last component of the path.
         
     | 
| 
      
 679 
     | 
    
         
            +
              def dirname() Path.new(File.dirname(@path)) end
         
     | 
| 
      
 680 
     | 
    
         
            +
             
     | 
| 
      
 681 
     | 
    
         
            +
              # See <tt>File.extname</tt>.  Returns the file's extension.
         
     | 
| 
      
 682 
     | 
    
         
            +
              def extname() File.extname(@path) end
         
     | 
| 
      
 683 
     | 
    
         
            +
             
     | 
| 
      
 684 
     | 
    
         
            +
              # See <tt>File.expand_path</tt>.
         
     | 
| 
      
 685 
     | 
    
         
            +
              def expand_path(*args) Path.new(File.expand_path(@path, *args)) end
         
     | 
| 
      
 686 
     | 
    
         
            +
             
     | 
| 
      
 687 
     | 
    
         
            +
              # See <tt>File.split</tt>.  Returns the #dirname and the #basename in an
         
     | 
| 
      
 688 
     | 
    
         
            +
              # Array.
         
     | 
| 
      
 689 
     | 
    
         
            +
              def split() File.split(@path).map {|f| Path.new(f) } end
         
     | 
| 
      
 690 
     | 
    
         
            +
            end
         
     | 
| 
      
 691 
     | 
    
         
            +
             
     | 
| 
      
 692 
     | 
    
         
            +
             
     | 
| 
      
 693 
     | 
    
         
            +
            class Path    # * FileTest *
         
     | 
| 
      
 694 
     | 
    
         
            +
             
     | 
| 
      
 695 
     | 
    
         
            +
              # See <tt>FileTest.blockdev?</tt>.
         
     | 
| 
      
 696 
     | 
    
         
            +
              def blockdev?() FileTest.blockdev?(@path) end
         
     | 
| 
      
 697 
     | 
    
         
            +
             
     | 
| 
      
 698 
     | 
    
         
            +
              # See <tt>FileTest.chardev?</tt>.
         
     | 
| 
      
 699 
     | 
    
         
            +
              def chardev?() FileTest.chardev?(@path) end
         
     | 
| 
      
 700 
     | 
    
         
            +
             
     | 
| 
      
 701 
     | 
    
         
            +
              # See <tt>FileTest.executable?</tt>.
         
     | 
| 
      
 702 
     | 
    
         
            +
              def executable?() FileTest.executable?(@path) end
         
     | 
| 
      
 703 
     | 
    
         
            +
             
     | 
| 
      
 704 
     | 
    
         
            +
              # See <tt>FileTest.executable_real?</tt>.
         
     | 
| 
      
 705 
     | 
    
         
            +
              def executable_real?() FileTest.executable_real?(@path) end
         
     | 
| 
      
 706 
     | 
    
         
            +
             
     | 
| 
      
 707 
     | 
    
         
            +
              # See <tt>FileTest.exist?</tt>.
         
     | 
| 
      
 708 
     | 
    
         
            +
              def exist?() FileTest.exist?(@path) end
         
     | 
| 
      
 709 
     | 
    
         
            +
             
     | 
| 
      
 710 
     | 
    
         
            +
              # See <tt>FileTest.grpowned?</tt>.
         
     | 
| 
      
 711 
     | 
    
         
            +
              def grpowned?() FileTest.grpowned?(@path) end
         
     | 
| 
      
 712 
     | 
    
         
            +
             
     | 
| 
      
 713 
     | 
    
         
            +
              # See <tt>FileTest.directory?</tt>.
         
     | 
| 
      
 714 
     | 
    
         
            +
              def directory?() FileTest.directory?(@path) end
         
     | 
| 
      
 715 
     | 
    
         
            +
             
     | 
| 
      
 716 
     | 
    
         
            +
              # See <tt>FileTest.file?</tt>.
         
     | 
| 
      
 717 
     | 
    
         
            +
              def file?() FileTest.file?(@path) end
         
     | 
| 
      
 718 
     | 
    
         
            +
             
     | 
| 
      
 719 
     | 
    
         
            +
              # See <tt>FileTest.pipe?</tt>.
         
     | 
| 
      
 720 
     | 
    
         
            +
              def pipe?() FileTest.pipe?(@path) end
         
     | 
| 
      
 721 
     | 
    
         
            +
             
     | 
| 
      
 722 
     | 
    
         
            +
              # See <tt>FileTest.socket?</tt>.
         
     | 
| 
      
 723 
     | 
    
         
            +
              def socket?() FileTest.socket?(@path) end
         
     | 
| 
      
 724 
     | 
    
         
            +
             
     | 
| 
      
 725 
     | 
    
         
            +
              # See <tt>FileTest.owned?</tt>.
         
     | 
| 
      
 726 
     | 
    
         
            +
              def owned?() FileTest.owned?(@path) end
         
     | 
| 
      
 727 
     | 
    
         
            +
             
     | 
| 
      
 728 
     | 
    
         
            +
              # See <tt>FileTest.readable?</tt>.
         
     | 
| 
      
 729 
     | 
    
         
            +
              def readable?() FileTest.readable?(@path) end
         
     | 
| 
      
 730 
     | 
    
         
            +
             
     | 
| 
      
 731 
     | 
    
         
            +
              if FileTest.respond_to? :world_readable?
         
     | 
| 
      
 732 
     | 
    
         
            +
                # See <tt>FileTest.world_readable?</tt>.
         
     | 
| 
      
 733 
     | 
    
         
            +
                def world_readable?() FileTest.world_readable?(@path) end
         
     | 
| 
      
 734 
     | 
    
         
            +
              else
         
     | 
| 
      
 735 
     | 
    
         
            +
                def world_readable?
         
     | 
| 
      
 736 
     | 
    
         
            +
                  mode = File.stat(@path).mode & 0777
         
     | 
| 
      
 737 
     | 
    
         
            +
                  mode if (mode & 04).nonzero?
         
     | 
| 
      
 738 
     | 
    
         
            +
                end
         
     | 
| 
      
 739 
     | 
    
         
            +
              end
         
     | 
| 
      
 740 
     | 
    
         
            +
             
     | 
| 
      
 741 
     | 
    
         
            +
              # See <tt>FileTest.readable_real?</tt>.
         
     | 
| 
      
 742 
     | 
    
         
            +
              def readable_real?() FileTest.readable_real?(@path) end
         
     | 
| 
      
 743 
     | 
    
         
            +
             
     | 
| 
      
 744 
     | 
    
         
            +
              # See <tt>FileTest.setuid?</tt>.
         
     | 
| 
      
 745 
     | 
    
         
            +
              def setuid?() FileTest.setuid?(@path) end
         
     | 
| 
      
 746 
     | 
    
         
            +
             
     | 
| 
      
 747 
     | 
    
         
            +
              # See <tt>FileTest.setgid?</tt>.
         
     | 
| 
      
 748 
     | 
    
         
            +
              def setgid?() FileTest.setgid?(@path) end
         
     | 
| 
      
 749 
     | 
    
         
            +
             
     | 
| 
      
 750 
     | 
    
         
            +
              # See <tt>FileTest.size</tt>.
         
     | 
| 
      
 751 
     | 
    
         
            +
              def size() FileTest.size(@path) end
         
     | 
| 
      
 752 
     | 
    
         
            +
             
     | 
| 
      
 753 
     | 
    
         
            +
              # See <tt>FileTest.size?</tt>.
         
     | 
| 
      
 754 
     | 
    
         
            +
              def size?() FileTest.size?(@path) end
         
     | 
| 
      
 755 
     | 
    
         
            +
             
     | 
| 
      
 756 
     | 
    
         
            +
              # See <tt>FileTest.sticky?</tt>.
         
     | 
| 
      
 757 
     | 
    
         
            +
              def sticky?() FileTest.sticky?(@path) end
         
     | 
| 
      
 758 
     | 
    
         
            +
             
     | 
| 
      
 759 
     | 
    
         
            +
              # See <tt>FileTest.symlink?</tt>.
         
     | 
| 
      
 760 
     | 
    
         
            +
              def symlink?() FileTest.symlink?(@path) end
         
     | 
| 
      
 761 
     | 
    
         
            +
             
     | 
| 
      
 762 
     | 
    
         
            +
              # See <tt>FileTest.writable?</tt>.
         
     | 
| 
      
 763 
     | 
    
         
            +
              def writable?() FileTest.writable?(@path) end
         
     | 
| 
      
 764 
     | 
    
         
            +
             
     | 
| 
      
 765 
     | 
    
         
            +
              if FileTest.respond_to? :world_writable?
         
     | 
| 
      
 766 
     | 
    
         
            +
                # See <tt>FileTest.world_writable?</tt>.
         
     | 
| 
      
 767 
     | 
    
         
            +
                def world_writable?() FileTest.world_writable?(@path) end
         
     | 
| 
      
 768 
     | 
    
         
            +
              else
         
     | 
| 
      
 769 
     | 
    
         
            +
                def world_writable?
         
     | 
| 
      
 770 
     | 
    
         
            +
                  mode = File.stat(@path).mode & 0777
         
     | 
| 
      
 771 
     | 
    
         
            +
                  mode if (mode & 02).nonzero?
         
     | 
| 
      
 772 
     | 
    
         
            +
                end
         
     | 
| 
      
 773 
     | 
    
         
            +
              end
         
     | 
| 
      
 774 
     | 
    
         
            +
             
     | 
| 
      
 775 
     | 
    
         
            +
              # See <tt>FileTest.writable_real?</tt>.
         
     | 
| 
      
 776 
     | 
    
         
            +
              def writable_real?() FileTest.writable_real?(@path) end
         
     | 
| 
      
 777 
     | 
    
         
            +
             
     | 
| 
      
 778 
     | 
    
         
            +
              # See <tt>FileTest.zero?</tt>.
         
     | 
| 
      
 779 
     | 
    
         
            +
              def zero?() FileTest.zero?(@path) end
         
     | 
| 
      
 780 
     | 
    
         
            +
            end
         
     | 
| 
      
 781 
     | 
    
         
            +
             
     | 
| 
      
 782 
     | 
    
         
            +
             
     | 
| 
      
 783 
     | 
    
         
            +
            class Path    # * Dir *
         
     | 
| 
      
 784 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 785 
     | 
    
         
            +
                # See <tt>Dir.glob</tt>.  Returns or yields Path objects.
         
     | 
| 
      
 786 
     | 
    
         
            +
                def glob(*args) # :yield: pathname
         
     | 
| 
      
 787 
     | 
    
         
            +
                  if block_given?
         
     | 
| 
      
 788 
     | 
    
         
            +
                    Dir.glob(*args) {|f| yield new(f) }
         
     | 
| 
      
 789 
     | 
    
         
            +
                  else
         
     | 
| 
      
 790 
     | 
    
         
            +
                    Dir.glob(*args).map {|f| new(f) }
         
     | 
| 
      
 791 
     | 
    
         
            +
                  end
         
     | 
| 
      
 792 
     | 
    
         
            +
                end
         
     | 
| 
      
 793 
     | 
    
         
            +
             
     | 
| 
      
 794 
     | 
    
         
            +
                # See <tt>Dir.getwd</tt>.  Returns the current working directory as a Path.
         
     | 
| 
      
 795 
     | 
    
         
            +
                def Path.getwd
         
     | 
| 
      
 796 
     | 
    
         
            +
                  new Dir.getwd
         
     | 
| 
      
 797 
     | 
    
         
            +
                end
         
     | 
| 
      
 798 
     | 
    
         
            +
             
     | 
| 
      
 799 
     | 
    
         
            +
                alias pwd getwd
         
     | 
| 
      
 800 
     | 
    
         
            +
              end
         
     | 
| 
      
 801 
     | 
    
         
            +
             
     | 
| 
      
 802 
     | 
    
         
            +
              # Iterates over the entries (files and subdirectories) in the directory.  It
         
     | 
| 
      
 803 
     | 
    
         
            +
              # yields a Path object for each entry.
         
     | 
| 
      
 804 
     | 
    
         
            +
              def each_entry(&block) # :yield: pathname
         
     | 
| 
      
 805 
     | 
    
         
            +
                Dir.foreach(@path) {|f| yield Path.new(f) }
         
     | 
| 
      
 806 
     | 
    
         
            +
              end
         
     | 
| 
      
 807 
     | 
    
         
            +
             
     | 
| 
      
 808 
     | 
    
         
            +
              # See <tt>Dir.mkdir</tt>.  Create the referenced directory.
         
     | 
| 
      
 809 
     | 
    
         
            +
              def mkdir(*args) Dir.mkdir(@path, *args) end
         
     | 
| 
      
 810 
     | 
    
         
            +
             
     | 
| 
      
 811 
     | 
    
         
            +
              # See <tt>Dir.rmdir</tt>.  Remove the referenced directory.
         
     | 
| 
      
 812 
     | 
    
         
            +
              def rmdir() Dir.rmdir(@path) end
         
     | 
| 
      
 813 
     | 
    
         
            +
             
     | 
| 
      
 814 
     | 
    
         
            +
              # See <tt>Dir.open</tt>.
         
     | 
| 
      
 815 
     | 
    
         
            +
              def opendir(&block) # :yield: dir
         
     | 
| 
      
 816 
     | 
    
         
            +
                Dir.open(@path, &block)
         
     | 
| 
      
 817 
     | 
    
         
            +
              end
         
     | 
| 
      
 818 
     | 
    
         
            +
            end
         
     | 
| 
      
 819 
     | 
    
         
            +
             
     | 
| 
      
 820 
     | 
    
         
            +
             
     | 
| 
      
 821 
     | 
    
         
            +
            class Path    # * Find *
         
     | 
| 
      
 822 
     | 
    
         
            +
              #
         
     | 
| 
      
 823 
     | 
    
         
            +
              # Path#find is an iterator to traverse a directory tree in a depth first
         
     | 
| 
      
 824 
     | 
    
         
            +
              # manner.  It yields a Path for each file under "this" directory.
         
     | 
| 
      
 825 
     | 
    
         
            +
              #
         
     | 
| 
      
 826 
     | 
    
         
            +
              # Since it is implemented by <tt>find.rb</tt>, <tt>Find.prune</tt> can be used
         
     | 
| 
      
 827 
     | 
    
         
            +
              # to control the traversal.
         
     | 
| 
      
 828 
     | 
    
         
            +
              #
         
     | 
| 
      
 829 
     | 
    
         
            +
              # If +self+ is <tt>.</tt>, yielded pathnames begin with a filename in the
         
     | 
| 
      
 830 
     | 
    
         
            +
              # current directory, not <tt>./</tt>.
         
     | 
| 
      
 831 
     | 
    
         
            +
              #
         
     | 
| 
      
 832 
     | 
    
         
            +
              def find # :yield: pathname
         
     | 
| 
      
 833 
     | 
    
         
            +
                return to_enum(__method__) unless block_given?
         
     | 
| 
      
 834 
     | 
    
         
            +
                require 'find'
         
     | 
| 
      
 835 
     | 
    
         
            +
                if @path == '.'
         
     | 
| 
      
 836 
     | 
    
         
            +
                  Find.find(@path) {|f| yield Path.new(f.sub(%r{\A\./}, '')) }
         
     | 
| 
      
 837 
     | 
    
         
            +
                else
         
     | 
| 
      
 838 
     | 
    
         
            +
                  Find.find(@path) {|f| yield Path.new(f) }
         
     | 
| 
      
 839 
     | 
    
         
            +
                end
         
     | 
| 
      
 840 
     | 
    
         
            +
              end
         
     | 
| 
      
 841 
     | 
    
         
            +
            end
         
     | 
| 
      
 842 
     | 
    
         
            +
             
     | 
| 
      
 843 
     | 
    
         
            +
             
     | 
| 
      
 844 
     | 
    
         
            +
            class Path    # * FileUtils *
         
     | 
| 
      
 845 
     | 
    
         
            +
              # See <tt>FileUtils.mkpath</tt>.  Creates a full path, including any
         
     | 
| 
      
 846 
     | 
    
         
            +
              # intermediate directories that don't yet exist.
         
     | 
| 
      
 847 
     | 
    
         
            +
              def mkpath
         
     | 
| 
      
 848 
     | 
    
         
            +
                FileUtils.mkpath(@path)
         
     | 
| 
      
 849 
     | 
    
         
            +
                nil
         
     | 
| 
      
 850 
     | 
    
         
            +
              end
         
     | 
| 
      
 851 
     | 
    
         
            +
             
     | 
| 
      
 852 
     | 
    
         
            +
              # See <tt>FileUtils.rm_r</tt>.  Deletes a directory and all beneath it.
         
     | 
| 
      
 853 
     | 
    
         
            +
              def rmtree
         
     | 
| 
      
 854 
     | 
    
         
            +
                # The name "rmtree" is borrowed from File::Path of Perl.
         
     | 
| 
      
 855 
     | 
    
         
            +
                # File::Path provides "mkpath" and "rmtree".
         
     | 
| 
      
 856 
     | 
    
         
            +
                FileUtils.rm_r(@path)
         
     | 
| 
      
 857 
     | 
    
         
            +
                nil
         
     | 
| 
      
 858 
     | 
    
         
            +
              end
         
     | 
| 
      
 859 
     | 
    
         
            +
            end
         
     | 
| 
      
 860 
     | 
    
         
            +
             
     | 
| 
      
 861 
     | 
    
         
            +
             
     | 
| 
      
 862 
     | 
    
         
            +
            class Path    # * mixed *
         
     | 
| 
      
 863 
     | 
    
         
            +
              # Removes a file or directory, using <tt>File.unlink</tt> or
         
     | 
| 
      
 864 
     | 
    
         
            +
              # <tt>Dir.unlink</tt> as necessary.
         
     | 
| 
      
 865 
     | 
    
         
            +
              def unlink()
         
     | 
| 
      
 866 
     | 
    
         
            +
                begin
         
     | 
| 
      
 867 
     | 
    
         
            +
                  Dir.unlink @path
         
     | 
| 
      
 868 
     | 
    
         
            +
                rescue Errno::ENOTDIR
         
     | 
| 
      
 869 
     | 
    
         
            +
                  File.unlink @path
         
     | 
| 
      
 870 
     | 
    
         
            +
                end
         
     | 
| 
      
 871 
     | 
    
         
            +
              end
         
     | 
| 
      
 872 
     | 
    
         
            +
              alias delete unlink
         
     | 
| 
      
 873 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: epath
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -9,16 +9,20 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2011- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2011-12-16 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       14 
14 
     | 
    
         
             
            description: 
         
     | 
| 
       15 
     | 
    
         
            -
            email: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            email: eregontp@gmail.com
         
     | 
| 
       16 
16 
     | 
    
         
             
            executables: []
         
     | 
| 
       17 
17 
     | 
    
         
             
            extensions: []
         
     | 
| 
       18 
18 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       19 
19 
     | 
    
         
             
            files:
         
     | 
| 
      
 20 
     | 
    
         
            +
            - lib/epath/implementation.rb
         
     | 
| 
      
 21 
     | 
    
         
            +
            - lib/epath.rb
         
     | 
| 
      
 22 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 23 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
       20 
24 
     | 
    
         
             
            - epath.gemspec
         
     | 
| 
       21 
     | 
    
         
            -
            homepage: 
         
     | 
| 
      
 25 
     | 
    
         
            +
            homepage: https://github.com/eregon/epath
         
     | 
| 
       22 
26 
     | 
    
         
             
            licenses: []
         
     | 
| 
       23 
27 
     | 
    
         
             
            post_install_message: 
         
     | 
| 
       24 
28 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
         @@ -38,8 +42,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       38 
42 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       39 
43 
     | 
    
         
             
            requirements: []
         
     | 
| 
       40 
44 
     | 
    
         
             
            rubyforge_project: 
         
     | 
| 
       41 
     | 
    
         
            -
            rubygems_version: 1.8. 
     | 
| 
      
 45 
     | 
    
         
            +
            rubygems_version: 1.8.11
         
     | 
| 
       42 
46 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       43 
47 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       44 
     | 
    
         
            -
            summary:  
     | 
| 
      
 48 
     | 
    
         
            +
            summary: a Path manipulation library
         
     | 
| 
       45 
49 
     | 
    
         
             
            test_files: []
         
     |