# = TITLE: # # File Utitlies # # = COPYING: # # Copyright (c) 2007,2008 Tiger Ops # # This file is part of the Reap program. # # Reap is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Reap is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Reap. If not, see . # # TODO: # # - Move out_of_data? and safe? to Facets FileTest extensions. require 'fileutils' require 'facets/ziputils' require 'reap/extensions' # module Reap module Utilities module FileUtils # Delegate access to FileUtils. def fileutils dryrun? ? ::FileUtils::DryRun : ::FileUtils end # Add FileUtils Features ::FileUtils.private_instance_methods(false).each do |meth| next if meth =~ /^fu_/ module_eval %{ def #{meth}(*a,&b) fileutils.#{meth}(*a,&b) end } end # Add FileTest Features ::FileTest.private_instance_methods(false).each do |meth| next if meth =~ /^fu_/ module_eval %{ def #{meth}(*a,&b) FileTest.#{meth}(*a,&b) end } end # Specific. def rm_r(*a) if dryrun? puts "rm_r #{a.join(' ')}" else fileutils.rm_r(*a) end end # Bonus FileUtils features. def cd(*a,&b) puts "cd #{a}" if dryrun? or trace? fileutils.chdir(*a,&b) end # Read file. def file_read(path) File.read(path) end # Write file. def file_write(path, text) if dryrun? puts "write #{path}" else File.open(path, 'w'){ |f| f << text } end end # Assert that a path exists. def exists?(path) paths = Dir.glob(path) paths.not_empty? end alias_method :exist?, :exists? ; module_function :exist? alias_method :path?, :exists? ; module_function :path? # Assert that a path exists. def exists!(*paths) abort "path not found #{path}" unless paths.any?{|path| exists?(path)} end alias_method :exist!, :exists! ; module_function :exist! alias_method :path!, :exists! ; module_function :path! # Is a given path a regular file? If +path+ is a glob # then checks to see if all matches are refular files. def file?(path) paths = Dir.glob(path) paths.not_empty? && paths.all?{ |f| FileTest.file?(f) } end # Assert that a given path is a file. def file!(*paths) abort "file not found #{path}" unless paths.any?{|path| file?(path)} end # Is a given path a directory? If +path+ is a glob # checks to see if all matches are directories. def dir?(path) paths = Dir.glob(path) paths.not_empty? && paths.all?{ |f| FileTest.directory?(f) } end alias_method :directory?, :dir? ; module_function :directory? # Assert that a given path is a directory. def dir!(*paths) paths.each do |path| abort "Directory not found: '#{path}'." unless dir?(path) end end alias_method :directory!, :dir! ; module_function :directory! # # Okay, I'm being a dork, but 'fold' seems like a better word # # then 'dir', 'folder', or 'directory'. # # def fold?(path) # paths = Dir.glob(path) # paths.not_empty? && paths.all?{ |f| FileTest.directory?(f) } # end # # # Assert that a given path is a fold (ie. a folder). # # def fold!(*paths) # abort "fold not found #{path}" unless paths.any?{|path| fold?(path)} # end # Return a cached list of the PATH environment variable. # This is a support method used by #bin? def command_paths @command_paths ||= ENV['PATH'].split(/[:;]/) end # Is a file a command executable? # # TODO: Make more robust. Probably needs to be fixed for Windows. def bin?(fname) #@command_paths ||= ENV['PATH'].split(/[:;]/) is_bin = command_paths.any? do |f| FileTest.exist?(File.join(f, fname)) end #is_bin ? File.basename(fname) : false is_bin ? fname : false end # Is a path considered reasonably "safe"? # # TODO: Make more robust. def safe?(path) case path when *[ '/', '/*', '/**/*' ] return false end true end # Does a path need updating, based on given +sources+? # This compares mtimes of give paths. Returns false # if the path needs to be updated. def out_of_date?(path, *sources) return true unless File.exist?(path) sources = sources.collect{ |source| Dir.glob(source) }.flatten mtimes = sources.collect{ |file| File.mtime(file) } return true if mtimes.empty? # TODO: This the way to go here? File.mtime(path) < mtimes.max end # Glob files. def glob(*args, &blk) Dir.glob(*args, &blk) end def multiglob(*args, &blk) Dir.multiglob(*args, &blk) end def multiglob_r(*args, &blk) Dir.multiglob_r(*args, &blk) end # Stage package by hard linking included files to a stage directory. # Stage files in a directory. # # stage_directory Stage directory. # files Files to link to stage. def stage(stage_directory, files) return stage_directory if dryrun? # Don't link to stage if dryrun. if File.directory?(stage_directory) # Ensure existance of staging area. #raise(???Error, stage_directory) unless force? rm_r(stage_directory) end mkdir_p(stage_directory) #dir = File.expand_path(stage) #files = package.filelist #+ [package.manifest_file] # TODO Dryrun test here or before folder creation? files.each do |f| # Link files into staging area. file = File.join(stage_directory, f) if File.directory?(f) mkdir_p(file) else unless File.exist?(file) and File.mtime(file) >= File.mtime(f) ln(f, file) #safe_ln ? end end end # stage meanifest ? return stage_directory end # Create manifest for a directory. # # TODO: Do this programatically rather then via shell. def stage_manifest(directory) cd(directory) do sh 'manifest up' end end # Delegate access to ZipUtils. def ziputils dryrun? ? ::ZipUtils::DryRun : ::ZipUtils end # Zip folder into file. def zip(folder, file=nil, options={}) ziputils.zip(folder, file, options) end # BZip and tarball folder into file. def tar_bzip(folder, file=nil, options={}) ziputils.tar_bzip(folder, file, options) end # GZip and tarball folder into file. Shortcut for ziputils.tgz. def tgz(folder, file=nil, options={}) ziputils.tgz(folder, file, options) end # # Is a file a task? # # def task?(path) # task = File.dirname($0) + "/#{path}" # task.chomp!('!') # task if FileTest.file?(task) && FileTest.executable?(task) # end end end end