#
# h2. lib/imw/files/file.rb -- base class for files
#
# == About
#
# Defines a base class for classes for specific filetypes to subclass.
#
# Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
# Copyright:: Copyright (c) 2008 infochimps.org
# License:: GPL 3.0
# Website:: http://infinitemonkeywrench.org/
#
# puts "#{File.basename(__FILE__)}: At the very bottom of the office building, wedged between a small boulder and a rotting log you see a weathered manilla file folder. The writing on the tab is too faded to make out." # at bottom
module IMW
module Files
module BasicFile
attr_reader :uri, :host, :path, :dirname, :basename, :extname, :name
protected
def uri= uri
@uri = uri.is_a?(URI::Generic) ? uri : URI.parse(uri)
@host = self.uri.host
@path = local? ? ::File.expand_path(self.uri.path) : self.uri.path
@dirname = ::File.dirname path
@basename = ::File.basename path
@extname = find_extname
@name = @basename[0,@basename.length - @extname.length]
end
# Some files (like .tar.gz) have an "extra" extension.
# Classes in the IMW::Files module should define a
# class method extname which returns the their full
# extension.
def find_extname
self.class.respond_to?(:extname) ? self.class.extname(path) : ::File.extname(path)
end
public
# Is this file on the local machine (the scheme of the file's URI is nil or
def local?
host == 'file' || host.nil?
end
# Is this file on a remote machine?
def remote?
(! local?)
end
# Steal a bunch of class methods from File which only take a
# path as a first argument.
[:executable?, :executable_real?, :file?, :directory?, :ftype, :owned?, :pipe?, :readable?, :readable_real?, :setgid?, :setuid?, :size, :size?, :socket?, :split, :stat, :sticky?, :writable?, :writable_real?, :zero?].each do |class_method|
define_method class_method do
File.send(class_method, path)
end
end
# Is there a real file at the path of this File? Will attempt
# to open files online too to check.
def exist?
if local?
::File.exist?(path)
else
begin
true if open(uri)
rescue SocketError
false
end
end
end
alias_method :exists?, :exist?
# Delete this file.
def rm
raise IMW::PathError.new("cannot delete remote file #{uri}") unless local?
raise IMW::PathError.new("cannot delete #{uri}, doesn't exist!") unless exist?
FileUtils.rm path
end
alias_method :rm!, :rm
# Copy this file to +new_path+.
def cp new_path
raise IMW::PathError.new("cannot copy from #{path}, doesn't exist!") unless exist?
if local?
FileUtils.cp path, new_path
else
# FIXME better way to do this?
File.open(new_path,'w') { |f| f.write(open(uri).read) }
end
self.class.new(new_path)
end
# Copy this file to +dir+.
def cp_to_dir dir
cp File.join(File.expand_path(dir),basename)
end
# Move this file to +new_path+.
def mv new_path
raise IMW::PathError.new("cannot move from #{path}, doesn't exist!") unless exist?
if local?
FileUtils.mv path, new_path
else
# FIXME better way to do this?
File.open(new_path,'w') { |f| f.write(open(uri).read) }
end
self.class.new(new_path)
end
alias_method :mv!, :mv
# Move this file to +dir+.
def mv_to_dir dir
mv File.join(File.expand_path(dir),basename)
end
alias_method :mv_to_dir!, :mv_to_dir
end
end
end