#!/usr/bin/ruby -w # -*- ruby -*- require './filetest' require './log' # Additions to the File built-in class. class File include Log # Returns a File::Stat object, or null if there were errors (such as the file # not existing, access denied, etc.). def File.status(fd) begin return File.stat(fd) rescue # ignore files that could not be read, etc. return nil end end # Returns whether the given object is a file. Ignores errors. def File.is_file?(fd) fs = File.status(fd) return fs && fs.file? end # Returns whether the given object is a directory. Ignores errors. def File.is_directory?(fd) fs = File.status(fd) return fs && fs.directory? end # Returns an array containing each of the names for which the associated block # returned true. def File.find_where(dir) names = Array.new Find.find(dir) do |f| names.push(f) if yield(f) end names end # Returns an array of all files under the given directory. def File.find_files(dir) File.find_where(dir) { |f| is_file?(f) } end # Returns an array of all directory under the given directory. def File.find_directories(dir) File.find_where(dir) { |f| is_directory?(f) } end # Returns an array of all files within the given directory. def File.local_files(dir) Dir.new(dir).find_all { |f| is_file?(f) } end # Strips the PWD and the leading ./ def File.clean_name(fname) Log.log "fname: #{fname}" file = fname.dup file.gsub!(Dir.pwd, "") file.gsub!(/^\//, "") file.sub!(/^\.\//, "") file end def File.is_text?(fname) FileTester.text?(fname) end end # A hash that ensures that we use file name of the form: "foo/Bar", not # "./foo/Bar". class FileHash < Hash def []=(f, value) fname = File.clean_name(f) super(fname, value) end def [](f) fname = File.clean_name(f) super(fname) end end # An array that ensures that we use file name of the form: "foo/Bar", not # "./foo/Bar". class FileArray < Array def []=(index, name) file = File.clean_name(f) super(index, name) end def push(name) fname = File.clean_name(name) super(fname) end end # Directories listed so that the parents are first in the list. class OrderedDirectoryList < Array def initialize(files) files.each { |f| add(File.dirname(f)) } end # add a directory def add(dir) if dir && !File.exists?(dir + "/CVS/Entries") # TODO: remove the CVS-icity of this: # attempt to add the parent, unless this is "." # note: this won't work if dir == "." if dir == "." puts "ERROR: Cannot process files from within a directory" puts "not in CVS. Please move up to the parent directory" puts "and retry." exit end add(File.dirname(dir)) pos = index(dir) if pos # nothing to do; dir is already in the list else pdpos = index(File.dirname(dir)) if pdpos # parent already in the list, so insert this dir immediately afterward self[pdpos + 1, 0] = dir else # prepending unshift(dir) end end end end end if __FILE__ == $0 fa = FileArray.new fa.push("/this/is/a/test") puts fa fa.push("./another/test") puts fa end