require 'enumerator' require 'fileutils' #class Enumerator # alias_method :list, :to_a #end module Folio # = File Object # # Base class for all folio objects. class FileObject Separator = ::File::Separator # Factory method. def self.[](*path) path = ::File.join(*path) raise FileNotFound.new(path) unless ::File.exist?(path) case ::File.ftype(path) when 'file' Document.new(path) when 'directory' Directory.new(path) when 'link' Link.new(path) when 'characterSpecial' CharacterDevice.new(path) when 'blockSpecial' BlockDevice.new(path) when 'socket' raise TypeError # Socket.new(path) ? when 'fifo' raise TypeError # Pipe? else # 'unknown' raise FileNotFound.new(path) end end private def initialize(path) @path = ::File.expand_path(path) assert_exists if ::File.exist?(@path) end def assert_exists end public attr :path def ==(other) #p @path, other.path return false unless FileObject===other @path == other.path end # This will alwasy be true, EXCEPT when # #rm, #delete or #unlink have been used. def exist? ::FileTest.exist?(path) end alias_method :exists?, :exist? # Returns the parent directory object. def parent self.class[File.dirname(path)] end #-- # File Manipulation #++ def link(new) ::File.ln(path, new) end alias_method :ln, :link def link_force(new) ::File.remove(new) link(new) end alias_method :ln_f, :link_force def symlink(new) ::File.symlink(path, new) end alias_method :ln_s, :symlink def symlink_force(new) ::File.remove(new) symlink(new) end alias_method :ln_sf, :symlink_force def rename(dest) ::File.rename(path, dest) @path = ::File.expand_path(dest) end alias_method :mv, :rename # how to handle --b/c it disappears? def unlink ::File.delete(path) end alias_method :delete, :unlink alias_method :rm, :unlink def unlink_force ::File.remove(new) unlink(path) end alias_method :delete_force, :unlink_force alias_method :rm_f, :unlink_force def chmod(mode) ::File.chmod(mode, path) end def chown(user, group) ::File.chown(user, group, path) end def utime(atime, mtime) ::File.utime(atime, mtime, path) end # Wherever possible we have tried to avoid using # FileUtils. Hoever there are a few methods that # require it's use becuase of the complications # in their implementation. Evenutlly we might port # these methods. # Copy file to destination path. def cp(dest) util.cp(path, dest) end # Install file to destination path. def install(dest, mode=nil) util.install(path, dest, mode) end # def touch util.touch(path) end # Status methods. These methods all access a cached # ::File::Stat object. You can use #stat! to refresh # the status cache. # Get stat and cache it. def stat @stat ||= File.stat(path) end # Refresh status cache. def restat @stat = File.stat(path) end alias_method :stat!, :restat #def file? ; stat.file? ; end def document? ; stat.file? ; end def directory? ; stat.directory? ; end def blockdev? ; stat.blockdev? ; end def chardev? ; stat.chardev? ; end def socket? ; stat.socket? ; end def pipe? ; stat.pipe? ; end def atime ; stat.atime ; end def ctime ; stat.ctime ; end def grpowned? ; stat.grpowned? ; end def identical? ; stat.identical? ; end def mtime ; stat.mtime ; end def owned? ; stat.owned? ; end def readable? ; stat.readable? ; end def readable_real? ; stat.readable_real ; end def setgid? ; stat.setgid? ; end def setuid? ; stat.setuid? ; end def size ; stat.size ; end def size? ; stat.size? ; end def sticky? ; stat.sticky? ; end def writable? ; stat.writable? ; end def writable_real? ; stat.writable_real? ; end def zero? ; stat.zero? ; end #-- # Pathname Methods #++ def basename ; ::File.basename(path) ; end def dirname ; ::File.dirname(path) ; end def extname ; ::File.extname(path) ; end # TODO: I don't like the name of this. def split ; ::File.split(path) ; end # Gives path relative to current working directory. # If current is below path one step then it uses '..', # further below and it returns the full path. def relative pwd = Dir.pwd pth = path if pth.index(pwd) == 0 r = pth[pwd.size+1..-1] r = '.' unless r return r else pwd = File.dirname(pwd) if pth.index(pwd) == 0 r = pth[pwd.size+1..-1] return '..' unless r return File.join('..', r) else pth end end end def fnmatch(pattern, flags=0) ::File.fnmatch(path, pattern, flags) end alias_method :fnmatch?, :fnmatch #-- # Standard Object Methods #++ # Inspect returns the path string relative to # the current working directory. def inspect; "#{relative}"; end # Returns the path string. def to_s ; path ; end def <=>(other) path <=> other.to_s end def ==(other) path == other.path end private def util ::FileUtils end end end