-
-
Save manveru/90392 to your computer and use it in GitHub Desktop.
Raku is a tiny rake-task manager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'optparse' | |
require 'ostruct' | |
require 'pathname' | |
require 'fileutils' | |
require 'digest/sha1' | |
ACTIONS = [] | |
TARGETS = [] | |
OPTIONS = OpenStruct.new( | |
:force => false, | |
:verbose => false, | |
:quiet => false, | |
:noop => false, | |
:color => false, | |
:proto => Pathname('~/.config/raku/tasks'), | |
:target => Pathname('./tasks') | |
) | |
target = OPTIONS.target | |
proto = OPTIONS.proto | |
op = OptionParser.new{|o| | |
o.separator(" ") | |
o.separator("Target modes:") | |
o.on('-P', '--proto', "run commands against #{proto} as target"){ TARGETS << :proto } | |
o.on('-T', '--tasks', "run commands against #{target} as target"){ TARGETS << :tasks } | |
o.separator(" ") | |
o.separator("Target commands:") | |
o.on('-u', '--update', | |
"Update all files in target"){ ACTIONS << :update } | |
o.on('-d', '--diff', | |
"Diff files between targets"){ ACTIONS << :diff } | |
o.on('-l', '--list', | |
"List files in target"){ ACTIONS << :list } | |
o.on('-i', '--init', | |
"Copy the Rakefile to target"){ ACTIONS << :init } | |
o.on('-p', '--put FILE1,FILE2,...', Array, | |
"Put given file(s) into target"){|p| ACTIONS << [:put, *p] } | |
o.on('-r', '--remove FILE!,FILE2,...', Array, | |
"Remove given files from target"){|r| ACTIONS << [:remove, *r] } | |
o.separator(" ") | |
o.separator("Configuration:") | |
o.on('-t', '--target-dir DIR', | |
"Location for project tasks, default is #{target}"){|t| OPTIONS.target = t } | |
o.on( '--proto-dir DIR', | |
"Location of PROTO, default is #{proto}"){|p| OPTIONS.proto = Pathname(p) } | |
o.on('-f', '--force', | |
"Don't ask silly questions when overwriting files"){|f| OPTIONS.force = f } | |
o.on('-v', '--verbose', | |
"Tell me everything"){|v| OPTIONS.verbose = v } | |
o.on('-q', '--quiet', | |
"Tell me nothing, takes precendence over --verbose"){|q| OPTIONS.quiet = q } | |
o.on('-n', '--noop', | |
"Don't do anything for real, useful with --verbose"){|n| OPTIONS.noop = n } | |
o.on('-c', '--color', | |
"Use colors for diff, needs colordiff installed"){|c| OPTIONS.color = c } | |
o.separator(" ") | |
o.separator("About:") | |
o.on('-V', '--version', 'Version of Raku'){ puts Raku::VERSION; exit } | |
o.on('-h', '--help', 'Display this help'){ puts o; exit } | |
} | |
class Pathname | |
def glob(g) | |
self.class.glob(self.join(g)) | |
end | |
def digest | |
Digest::SHA1.hexdigest(read) if exist? | |
end | |
end | |
class Raku | |
VERSION = '2009.03.27' | |
class ProtoPOV < Raku | |
def proto; @options.target.expand_path end | |
def target; @options.proto.expand_path end | |
end | |
class TargetPOV < Raku | |
end | |
def initialize(options) | |
@options = options | |
mkdir_p(proto) | |
end | |
def init | |
require 'erb' | |
target_rakefile = target.join('Rakefile') | |
proto_rakefile = proto.join('Rakefile') | |
cp(proto.join('Rakefile'), target.parent) | |
File.read(proto_rakefile) | |
end | |
def remove(*files) | |
end | |
def put(*files) | |
mkdir_p(target) | |
done_something = false | |
files.each do |file| | |
if file.exist? | |
done_something = true | |
put_file(file) | |
else | |
proto.glob("*#{file}*.rake").each do |from| | |
done_something = true | |
put_file(from) | |
end | |
end | |
end | |
log("No files match your request: %p", files) unless done_something | |
end | |
def put_file(from) | |
to = target.join(from.basename) | |
log("Put %s into %s", from, to) | |
cp(from, to) | |
end | |
def diff | |
diffbin = color? ? 'colordiff' : 'diff' | |
sh(diffbin, '-u', proto, target) | |
end | |
def list | |
proto_files = proto.glob('*.rake') | |
target_files = target.glob('*.rake') | |
hash = Hash.new{|h,k| h[k] = [] } | |
proto_files.each{|file| hash[file.digest] << file } | |
target_files.each{|file| hash[file.digest] << file } | |
puts "PROTO = %s | TARGET = %s" % [proto, target] | |
puts | |
proto_len = proto_files.map{|f| f.basename.to_s.size }.max | |
target_len = target_files.map{|f| f.basename.to_s.size }.max | |
hash.each do |digest, files| | |
args = files.map{|f| f.basename } | |
args << '' if args.size == 1 | |
puts "%40s : %-#{proto_len}s | %-#{target_len}s" % [digest, *args] | |
end | |
end | |
def update | |
mkdir_p(target) | |
proto.glob('*.rake').each do |from| | |
to = target.join(from.basename) | |
if from.digest == to.digest | |
debug("Won't copy %s, file contents are identical", from.basename) | |
else | |
cp(from, to) | |
end | |
end | |
end | |
private | |
def mkdir_p(dir) | |
return if File.directory?(dir) | |
debug("Create directory %p", dir) | |
FileUtils.mkdir_p(dir) | |
end | |
def cp(from, to) | |
if to.exist? | |
unless force? | |
log("Will not overwrite %s with %s", to.basename, from) | |
return | |
end | |
end | |
FileUtils.cp(from, to, | |
:noop => noop?, | |
:verbose => verbose?, | |
:preserve => true) | |
rescue ArgumentError => ex | |
debug(ex.message) unless ex.message =~ /^same file:/ | |
end | |
def sh(*cmd) | |
debug(cmd.join(' ')) | |
system(*cmd) | |
end | |
def debug(*args) | |
log(*args) if verbose? | |
end | |
def log(format, *args) | |
puts(format % args.flatten) unless quiet? | |
end | |
def target; @options.target.expand_path end | |
def proto; @options.proto.expand_path end | |
def color?; @options.color end | |
def force?; @options.force end | |
def noop?; @options.noop end | |
def quiet?; @options.quiet end | |
def verbose?; @options.verbose end | |
end | |
begin | |
op.parse!(ARGV) | |
rescue OptionParser::MissingArgument => ex | |
puts ex | |
exit | |
end | |
if ACTIONS.empty? | |
puts op | |
exit 1 | |
end | |
if TARGETS.first == :proto | |
raku = Raku::ProtoPOV.new(OPTIONS) | |
else | |
raku = Raku::TargetPOV.new(OPTIONS) | |
end | |
action, *args = ACTIONS.shift | |
args = (args + ARGV).map{|a| Pathname(a) } | |
args.delete true | |
raku.send(action, *args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment