#!/usr/bin/env ruby -w require 'fileutils' require 'erb' require 'optparse' include FileUtils def main(basedir,force) if Dir.exists? basedir if force rm_rf basedir, :verbose => true, :secure => true else STDERR.puts "error: #{basedir} exists, use --force to override" return 1 end end mkdir_p basedir gemname = File.basename(basedir) chdir File.dirname(basedir) %x[bundle gem #{gemname}] chdir gemname template_dirs_in(:full).each { |dir| mkdir_p dir } copy_file "Rakefile" copy_file "test/tc_something.rb" copy_file "features/executable.feature", :as => "#{gemname}.feature", :binding => binding copy_file "features/support/env.rb" copy_file "features/step_definitions/executable_steps.rb", :as => "#{gemname}_steps.rb" copy_file "bin/executable", :as => gemname, :executable => true add_to_file "#{gemname}.gemspec", [ " s.add_development_dependency('rdoc')", " s.add_development_dependency('aruba')", ], :before => /^end\s*$/ return 0 end # Add content to a file # # +file+:: path to the file # +lines+:: Array of String representing the lines to add # +options+:: Hash of options: # :before:: A regexp that will appear right after the new content. i.e. # this is where to insert said content. def add_to_file(file,lines,options = {}) new_lines = [] found_line = false File.open(file).readlines.each do |line| line.chomp! if options[:before] && options[:before] === line found_line = true new_lines += lines end new_lines << line end raise "No line matched #{options[:before]}" if options[:before] && !found_line new_lines += lines unless options[:before] File.open(file,'w') do |fp| new_lines.each { |line| fp.puts line } end end # Copies a file, running it through ERB # # +relative_path+:: path to the file, relative to the project root, minus the .erb extension # You should use forward slashes to separate paths; this method # will handle making the ultimate path OS independent. # +options+:: Options to affect how the copy is done: # :from:: The name of the profile from which to find the file, "full" by default # :as:: The name the file should get if not the one in relative_path # :executable:: true if this file should be set executable # :binding:: the binding to use for the template def copy_file(relative_path,options = {}) options[:from] ||= :full relative_path = File.join(relative_path.split(/\//)) template_path = File.join(template_dir(options[:from]),relative_path + ".erb") template = ERB.new(File.open(template_path).readlines.join('')) relative_path_parts = File.split(relative_path) relative_path_parts[-1] = options[:as] if options[:as] erb_binding = options[:binding] or binding File.open(File.join(relative_path_parts),'w') do |file| file.puts template.result(erb_binding) file.chmod(0755) if options[:executable] end end # Get the location of the templates for profile "from" def template_dir(from) File.join(File.dirname(EXE),'..','templates',from.to_s) end def template_dirs_in(profile) template_dir = template_dir(:full) Dir["#{template_dir}/**/*"].select { |x| File.directory? x }.map { |dir| dir.gsub(/^#{template_dir}\//,'') } end options = {} option_parser = OptionParser.new do |opts| executable = File.basename(__FILE__) opts.banner = "Usage: #{executable} [options] app_name" opts.on("--force","Overwrite files if they exist") do options[:force] = true end end option_parser.parse! EXE = File.expand_path(__FILE__) if ARGV.empty? STDERR.puts("error: app_dir required") exit 2 else exit main(ARGV[0],options[:force]) end