lib/proutils/mint/copier.rb in proutils-0.3.0 vs lib/proutils/mint/copier.rb in proutils-0.3.1
- old
+ new
@@ -15,168 +15,172 @@
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
- )
+ (ENV['MINT_PATH'] || []) + [datadir]
end
# TODO Better way to support RubyGems and Rolls?
def self.datadir
- dir = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'data', 'mint')
+ dir = File.expand_path("#{File.dirname(__FILE__)}/../../../data/mint")
if File.directory?(dir)
dir
else
File.join(File.join(Config::CONFIG['datadir'], 'mint'))
end
end
- # = Mint Copier
+ # Mint Copier provides a factility for
+ # performing interactive, managed copies.
class Copier
- IGNORE = [ '.', '..', '.svn']
+ #IGNORE = [ '.', '..', '.svn']
- attr_reader :sources, :destination, :options
+ # Look for source file(s) in system locations?
- attr_reader :actions
+ attr_accessor :system
- def initialize(sources, destination, options=nil)
- @sources = [sources].flatten
- @destination = destination
- @options = options || {}
+ # Source paths to copy. This can be a glob or an array of globs.
- @special = options[:special]
+ attr_accessor :source
- @dryrun = options[:dryrun]
- @force = options[:force]
- @skip = options[:skip]
+ # Directory (or a file, if copying one file) in which to store copied source.
- if special?
- @sources = special_lookup(*sources)
- else
- @sources = general_lookup(*sources)
- end
+ attr_accessor :destination
+ # Just pretend to do the commit action.
+
+ attr_accessor :dryrun
+
+ # Force provided an extra "dangerous" option of "(W)rite all".
+
+ attr_accessor :force
+
+ # Automatically skip all overwrites.
+
+ attr_accessor :skip
+
+ # Stores actions to be performed upon commit.
+
+ attr_reader :actions
+
+ # New copier.
+
+ def initialize(source, destination, options=nil)
+ @source = [source].flatten
+ @destination = destination
+
@actions = []
+
+ options.each do |k,v|
+ send("#{k}=",v)
+ end
end
- def special? ; @special; end
- def dryrun? ; @dryrun ; end
- def force? ; @force ; end
- def skip? ; @skip ; end
+ def system? ; @system ; end
- # Lookup in special mint locations.
+ def dryrun? ; @dryrun ; end
+ def force? ; @force ; end
+ def skip? ; @skip ; end
- 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
+ # Files to copy.
+
+ def copies
+ if system?
+ system_lookup
+ else
+ common_lookup
end
- #
- sources.collect do |source|
- type = *source.split(/[\/\\]/).first
- [Mint.paths[type], source]
- end
end
- #
+ # Look up file in system locations.
- def requested_locations(*sources)
- sources.collect do |source|
- source.split(/[\/\\]/).first
+ def system_lookup
+ copies = []
+ Mint.paths.each do |path|
+ source.each do |src|
+ jpath = File.join(path, src)
+ files = Dir.glob(jpath)
+ files.each do |file|
+ file = file.sub(path+'/','')
+ copies << [path, file]
+ end
+ end
end
+ copies
end
- #
+ # Non-system lookup.
- def general_lookup(*sources)
- sources.collect do |source|
- [ '.', source ]
+ def common_lookup
+ copies = []
+ source.each do |src|
+ files = Dir.glob(File.join(path, src))
+ unless files.empty?
+ copies << [nil, files]
+ end
end
+ copies
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)
+ puts "KEY: (d)iff (r)eplace (s)kip (a)ll (q)uit"
+ copies.each do |dir, file|
+ path = dir ? File.join(dir, file) : file
if File.file?(path)
copy_file(dir, file)
- else
- dirs, files = *partition_path(path)
+ elsif File.directory?(path)
+ dirs, files = *partition(path)
# make empty directories
dirs.each do |d|
- if File.directory?(d)
+ if File.directory?(File.join(destination,d))
skip_dir(d)
else
pth = File.join(path,d)
entries = Dir.entries(pth) - IGNORE
- make_dir(d) if entries.empty?
+ make_dir(path, d) if entries.empty?
end
end
# copy files in directories
files.each do |f|
copy_file(path, f)
end
+ else
+ raise ArgumentError, "unsupported file object -- #{path}"
end
end
commit
end
private
- # List of source files.
+ # Partition a directory's content between dirs and files.
- #def source_paths
- # Dir.glob(File.join(@source, '**/*'))
- #end
-
- # Partition a path's contents between dirs and files.
-
- def partition_path(path)
+ def partition(directory)
dirs, files = [], []
- chdir(path) do
+ chdir(directory) 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)
+ def make_dir(source, dir)
dst = File.join(destination, dir)
if File.file?(dst)
puts "Directory to replace file..."
- action = query(file) || 'skip'
+ action = query(source, dir) || 'skip'
else
action = 'make'
end
@actions << [action, dst]
action_print(action, dst + '/')
@@ -185,19 +189,17 @@
# 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)
+ action = query(source, file)
elsif File.file?(dst)
unless FileTest.identical?(src, dst)
- action = query(file)
+ action = query(source, file)
end
else
action = 'copy'
end
@@ -217,38 +219,40 @@
@actions << ['skip', dst]
action_print('skip', dst + '/')
end
# Skip file.
+ #
+ # TODO: Why is this never called?
def skip_file(src, dst)
@actions << ['skip', [src, dst]]
action_print('skip', dst)
end
# Show diff of files.
- def diff(file)
+ def diff(source, 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)
+ def query(source, 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)
+ diff(source, file)
when 'r', 'R'
action = 'replace'
when 's', 'S'
action = 'skip'
when 'a', 'A'
@@ -259,38 +263,25 @@
end
end
return action
end
- # Get user input
+ # Action print.
- 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
+ # Perform actions.
def commit!
- @actions.each do |action, path|
+ actions.each do |action, path|
case action
when 'make'
- rm(path) unless File.directory?(path)
+ #rm(path) if File.directory?(path)
mkdir_p(path)
when 'copy'
src, dst = *path
rm_r(dst) if File.directory?(dst)
mkdir_p(File.dirname(dst))
@@ -299,17 +290,35 @@
src, dst = *path
rm_r(dst) if File.directory?(dst)
#mkdir_p(File.dirname(dst))
cp(src, dst)
else # skip
- #
+ # do nothing
end
end
end
- # Delegate to fileutils.
+ # Confirm commit.
+ def commit
+ ans = ask("Commit y/N?")
+ case ans.downcase
+ when 'y', 'yes'
+ commit!
+ end
+ end
+
+ # Get user input.
+
+ def ask(msg)
+ print "#{msg} "
+ until inp = $stdin.gets ; sleep 1 ; end
+ inp.chomp
+ end
+
+ # Delegation to FileUtils.
+
def fu
@dryrun ? FileUtils::DryRun : FileUtils
end
def chdir(*a,&b) ; fu.chdir(*a,&b) ; end
@@ -319,6 +328,7 @@
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