# TITLE: # # Scaffold Controller # # COPYRIGHT: # # Copyright (c) 2007 7rans # # TODOs: # # - Need to make actions lazy and only commit when # everything is acknowledged. require 'rbconfig' require 'proutils/mint/fileutils' module Mint # def self.lookup(type) # globs = [] # paths.each do |path| # parts = type.split(/[\/\\]/) # if File.basename(path) == parts.first # globs << File.join(File.dirname(path), type) # end # end # globs.collect{ |g| Dir.glob(g) }.flatten # end def self.paths @paths ||= ( builtin = Dir.glob(File.join(datadir, '*')) paths = ENV['MINT_PATH'].to_s.split(/[:;]/) + builtin paths.inject({}) do |hash, path| dir, type = *File.split(path) hash[type] = dir hash end ) end # TODO Better way to support RubyGems and Rolls? def self.datadir dir = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'data', 'mint') if File.directory?(dir) dir else File.join(File.join(Config::CONFIG['datadir'], 'mint')) end end # = Mint Copier class Copier IGNORE = [ '.', '..', '.svn'] attr_reader :sources, :destination, :options attr_reader :actions def initialize(sources, destination, options=nil) @sources = [sources].flatten @destination = destination @options = options || {} @special = options[:special] @dryrun = options[:dryrun] @force = options[:force] @skip = options[:skip] if special? @sources = special_lookup(*sources) else @sources = general_lookup(*sources) end @actions = [] end def special? ; @special; end def dryrun? ; @dryrun ; end def force? ; @force ; end def skip? ; @skip ; end # Lookup in special mint locations. def special_lookup(*sources) # First lets make sure there are not bad requests. missing = requested_locations(*sources) - Mint.paths.keys unless missing.empty? puts "Missing special sources -- #{missing.join(', ')}" exit 0 end # sources.collect do |source| type = *source.split(/[\/\\]/).first [Mint.paths[type], source] end end # def requested_locations(*sources) sources.collect do |source| source.split(/[\/\\]/).first end end # def general_lookup(*sources) sources.collect do |source| [ '.', source ] end end # Copy files. def copy puts "KEY: (d)iff (r)eplace (s)kip skip(a)ll (q)uit" sources.each do |dir, file| path = File.join(dir, file) if File.file?(path) copy_file(dir, file) else dirs, files = *partition_path(path) # make empty directories dirs.each do |d| if File.directory?(d) skip_dir(d) else pth = File.join(path,d) entries = Dir.entries(pth) - IGNORE make_dir(d) if entries.empty? end end # copy files in directories files.each do |f| copy_file(path, f) end end end commit end private # List of source files. #def source_paths # Dir.glob(File.join(@source, '**/*')) #end # Partition a path's contents between dirs and files. def partition_path(path) dirs, files = [], [] chdir(path) do paths = Dir.glob('**/*') dirs, files = *paths.partition do |f| File.directory?(f) end end return dirs, files end # Make a directory. def make_dir(dir) dst = File.join(destination, dir) if File.file?(dst) puts "Directory to replace file..." action = query(file) || 'skip' else action = 'make' end @actions << [action, dst] action_print(action, dst + '/') end # Copy a file. def copy_file(source, file) src = File.join(source, file) dst = File.join(destination, file) action = 'skip' if File.directory?(dst) puts "File to replace directory..." action = query(file) elsif File.file?(dst) unless FileTest.identical?(src, dst) action = query(file) end else action = 'copy' end @actions << [action, [src, dst]] #if action == 'copy' or action == 'replace' # rm_r(dst) if File.directory?(dst) # cp(src, dst) #end action_print(action, dst) #, file) end # Skip directory. def skip_dir(dst) @actions << ['skip', dst] action_print('skip', dst + '/') end # Skip file. def skip_file(src, dst) @actions << ['skip', [src, dst]] action_print('skip', dst) end # Show diff of files. def diff(file) src = File.join(source, file) dst = File.join(destination, file) diff = FileTest.diff(src, dst) puts diff unless diff.empty? end # Query about file. def query(file) return 's' if @safe return 'o' if @force action = nil #msg = "#{file} -- (d)iff (r)eplace (s)kip (a)ll (q)uit?" msg = " ? #{file} " until action ans = ask(msg).strip[0,1] case ans when 'd', 'D' diff(file) when 'r', 'R' action = 'replace' when 's', 'S' action = 'skip' when 'a', 'A' @safe = true action = 'skip' when 'q', 'Q' exit 0 end end return action end # Get user input def ask(msg) print "#{msg} " until inp = $stdin.gets ; sleep 1 ; end inp.chomp end # Action print def action_print(action, file) file = file.sub(/^[.]\//,'') action = (' ' * (8 - action.size)) + action puts "#{action} #{file}" end def commit ans = ask("Commit y/N?") case ans.downcase when 'y', 'yes' commit! end end def commit! @actions.each do |action, path| case action when 'make' rm(path) unless File.directory?(path) mkdir_p(path) when 'copy' src, dst = *path rm_r(dst) if File.directory?(dst) mkdir_p(File.dirname(dst)) cp(src, dst) when 'replace' src, dst = *path rm_r(dst) if File.directory?(dst) #mkdir_p(File.dirname(dst)) cp(src, dst) else # skip # end end end # Delegate to fileutils. def fu @dryrun ? FileUtils::DryRun : FileUtils end def chdir(*a,&b) ; fu.chdir(*a,&b) ; end def rm(*a,&b) ; fu.rm(*a,&b) ; end def rm_r(*a,&b) ; fu.rm_r(*a,&b) ; end def cp(*a,&b) ; fu.cp(*a,&b) ; end def cp_r(*a,&b) ; fu.cp_r(*a,&b) ; end def mkdir(*a,&b) ; fu.mkdir(*a,&b) ; end def mkdir_p(*a,&b) ; fu.mkdir_p(*a,&b) ; end end end