Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

183 lines (160 sloc) 6.024 kb
module Rake
class Pipeline
# This class wraps a file for consumption inside of filters. It is
# initialized with a root and path, and filters usually use the
# {#read} and {#write} methods to work with these files.
#
# The {#root} and +path+ parameters are provided by the {Filter}
# class' internal implementation. Individual filters do not need
# to worry about them.
#
# The root of a {FileWrapper} is always an absolute path.
class FileWrapper
# @return [String] an absolute path representing this {FileWrapper}'s
# root directory.
attr_accessor :root
# @return [String] the path to the file represented by the {FileWrapper},
# relative to its {#root}.
attr_accessor :path
# @return [String] the encoding that the file represented by this
# {FileWrapper} is encoded in. Filters set the {#encoding} to
# +BINARY+ if they are declared as processing binary data.
attr_accessor :encoding
# Create a new {FileWrapper}, passing in optional root, path, and
# encoding. Any of the parameters can be ommitted and supplied later.
#
# @return [void]
def initialize(root=nil, path=nil, encoding="UTF-8")
@root, @path, @encoding = root, path, encoding
@created_file = nil
end
# Create a new {FileWrapper FileWrapper} with the same root and
# path as this {FileWrapper FileWrapper}, but with a specified
# encoding.
#
# @param [String] encoding the encoding for the new object
# @return [FileWrapper]
def with_encoding(encoding)
self.class.new(@root, @path, encoding)
end
# A {FileWrapper} is equal to another {FileWrapper} for hashing purposes
# if they have the same {#root} and {#path}
#
# @param [FileWrapper] other another {FileWrapper} to compare.
# @return [true,false]
def eql?(other)
return false unless other.is_a?(self.class)
root == other.root && path == other.path
end
alias == eql?
# Similar to {#eql?}, generate a {FileWrapper}'s {#hash} from its {#root}
# and {#path}
#
# @see #eql?
# @return [Fixnum] a hash code
def hash
[root, path].hash
end
# The full path of a FileWrapper is its root joined with its path
#
# @return [String] the {FileWrapper}'s full path
def fullpath
raise "#{root}, #{path}" unless root =~ /^(\/|[a-zA-Z]:[\\\/])/
File.join(root, path)
end
# Check to see if this file is inside the given directory
#
# @return [Boolean]
def in_directory?(directory)
!!(fullpath =~ %r{^#{Regexp.escape(directory)}/})
end
# Make FileWrappers sortable
#
# @param [FileWrapper] other {FileWrapper FileWrapper}
# @return [Fixnum] -1, 0, or 1
def <=>(other)
[root, path, encoding] <=> [other.root, other.path, other.encoding]
end
# Does the file represented by the {FileWrapper} exist in the file system?
#
# @return [true,false]
def exists?
File.exists?(fullpath)
end
# Read the contents of the file represented by the {FileWrapper}.
#
# Read the file using the {FileWrapper}'s encoding, which will result in
# this method returning a +String+ tagged with the {FileWrapper}'s encoding.
#
# @return [String] the contents of the file
# @raise [EncodingError] when the contents of the file are not valid in the
# expected encoding specified in {#encoding}.
def read
contents = if "".respond_to?(:encode)
File.read(fullpath, :encoding => encoding)
else
File.read(fullpath)
end
# In our unit tests Rubinius returns false when the encoding is BINARY
# The encoding type check bypasses the problem and is probably acceptable, but isn't ideal
if encoding != "BINARY" && "".respond_to?(:encode) && !contents.valid_encoding?
raise EncodingError, "The file at the path #{fullpath} is not valid #{encoding}. Please save it again as #{encoding}."
end
contents
end
# Create a new file at the {FileWrapper}'s {#fullpath}. If the file already
# exists, it will be overwritten.
#
# @api private
# @yieldparam [File] file the newly created file
# @return [File] if a block was not given
def create
FileUtils.mkdir_p(File.dirname(fullpath))
@created_file = if "".respond_to?(:encode)
File.open(fullpath, "w:#{encoding}")
else
File.open(fullpath, "w")
end
if block_given?
yield @created_file
end
@created_file
ensure
if block_given?
@created_file.close
@created_file = nil
end
end
# Close the file represented by the {FileWrapper} if it was previously opened.
#
# @api private
# @return [void]
def close
raise IOError, "closed stream" unless @created_file
@created_file.close
@created_file = nil
end
# Check to see whether the file represented by the {FileWrapper} is open.
#
# @api private
# @return [true,false]
def closed?
@created_file.nil?
end
# Write a String to a previously opened file. This method is called repeatedly
# by a {Filter}'s +#generate_output+ method and does not create a brand new
# file for each invocation.
#
# @raise [UnopenedFile] if the file is not already opened.
def write(string)
raise UnopenedFile unless @created_file
@created_file.write(string)
end
# @return [String] A pretty representation of the {FileWrapper}.
def inspect
"#<FileWrapper root=#{root.inspect} path=#{path.inspect} encoding=#{encoding.inspect}>"
end
alias to_s inspect
end
end
end
Jump to Line
Something went wrong with that request. Please try again.