lib/bones/main.rb in bones-1.1.2 vs lib/bones/main.rb in bones-1.2.0

- old
+ new

@@ -1,6 +1,6 @@ -# $Id: main.rb 428 2007-12-31 17:55:51Z tim_pease $ +# $Id: main.rb 433 2008-01-01 04:32:48Z tim_pease $ require 'fileutils' require 'optparse' require 'erb' @@ -23,11 +23,12 @@ # Parse the command line arguments and store the values for later use by # the +create+ and +update+ methods. # def parse( args ) - self.data = File.join(::Bones::PATH, 'data') + self.data = File.join(mrbones_dir, 'data') + self.data = File.join(::Bones::PATH, 'data') unless test(?d, data) self.update = false self.verbose = false opts = OptionParser.new opts.banner << ' project_name' @@ -37,21 +38,32 @@ 'update the rake tasks for the project') {self.update = true} opts.on('-v', '--verbose', 'enable verbose output') {self.verbose = true} opts.separator '' + opts.on('--freeze', 'freeze the project skeleton') {freeze; exit} + opts.on('--unfreeze', 'use the standard project skeleton') {unfreeze; exit} + opts.on('-i', '--info', + 'report on the project skeleton being used') do + STDOUT.puts "the project skeleton will be copied from" + STDOUT.write " " + STDOUT.puts data + exit + end + + opts.separator '' opts.separator 'common options:' opts.on_tail( '-h', '--help', 'show this message' ) {puts opts; exit} opts.on_tail( '--version', 'show version' ) do puts "Bones #{::Bones::VERSION}" exit end # parse the command line arguments opts.parse! args - self.name = args.shift + self.name = args.join('_') if name.nil? puts opts ::Kernel.abort end @@ -63,47 +75,39 @@ # def update? @update end - # Returns the project name but converted to be useable as a Ruby class + # Returns the project name but converted to be usable as a Ruby class # name. # def classname name.split('_').map {|x| x.capitalize}.join end # Create a new project from the bones/data project template. # def create - # * copy files from either - # 1) the user's '.bones/data' directory or - # 2) the Bones 'data' directory - # - # TODO - figure out if this really is the best way of doing this - # should I just use either the .bones data or the gem data, not - # both - # see if the directory already exists abort "'#{name}' already exists" if test ?e, name begin files_to_copy.each {|fn| cp fn} pwd = File.expand_path(FileUtils.pwd) begin FileUtils.cd name system "rake manifest:create 2>&1 > #{::Bones::DEV_NULL}" + STDOUT.puts "created '#{name}'\nnow you need to fix these files" + system "rake notes" ensure FileUtils.cd pwd end rescue Exception => err FileUtils.rm_rf name abort "could not create '#{name}'" end - - STDOUT.puts "created '#{name}'" end # Archive any existing tasks in the project's tasks folder, and then # copy in new tasks from the bones/data directory. # @@ -121,23 +125,91 @@ next if fn == archive_dir FileUtils.cp fn, archive_dir end files_to_copy.each do |fn| - next unless 'tasks' == File.basename(File.dirname(fn)) + next unless %r/^tasks\// =~ fn cp fn end STDOUT.puts "updated tasks for '#{name}'" end + # Freeze the project skeleton to the current Mr Bones gem. If the project + # skeleton has already been frozen, then it will be archived before being + # overwritten by the current Mr Bones skeleton. + # + # If the project skeleton is already frozen, only the tasks from the Mr + # Bones skeleton will be copied to the user's data directory. + # + def freeze + bones_data_dir = File.join(::Bones::PATH, 'data') + data_dir = File.join(mrbones_dir, 'data') + archive_dir = File.join(mrbones_dir, 'archive') + tasks_only = false + if test(?d, data_dir) + STDOUT.puts "archiving #{data_dir}" if verbose + FileUtils.rm_rf(archive_dir) + FileUtils.mkdir(archive_dir) + FileUtils.cp_r(File.join(data_dir, '.'), archive_dir) + tasks_only = true + else + FileUtils.mkdir_p(data_dir) + end + + files_to_copy.each do |file| + next if tasks_only && !(%r/^tasks\// =~ file) + + src = File.join(bones_data_dir, file) + dst = File.join(data_dir, file) + + STDOUT.puts "freezing #{dst}" if verbose + FileUtils.mkdir_p(File.dirname(dst)) + FileUtils.cp(src, dst) + end + + File.open(frozen_version_file, 'w') {|fd| fd.puts ::Bones::VERSION} + + if tasks_only + STDOUT.puts "project skeleton tasks have been updated " << + "from Mr Bones #{::Bones::VERSION}" + else + STDOUT.puts "project skeleton has been frozen " << + "to Mr Bones #{::Bones::VERSION}" + end + end + + # Unfreeze the project skeleton. The default Mr Bones skeleton will be + # used insetad. This method will archive the current frozen skeleton if + # one exists. + # + def unfreeze + data_dir = File.join(mrbones_dir, 'data') + archive_dir = File.join(mrbones_dir, 'archive') + + if test(?d, data_dir) + STDOUT.puts "archiving #{data_dir}" if verbose + FileUtils.rm_rf(archive_dir) + FileUtils.mkdir(archive_dir) + FileUtils.cp_r(File.join(data_dir, '.'), archive_dir) + FileUtils.rm_rf(data_dir) + + STDOUT.puts "project skeleton has been unfrozen" + STDOUT.puts "(default Mr Bones #{::Bones::VERSION} sekeleton will be used)" + else + STDOUT.puts "project skeleton is not frozen (no action taken)" + end + FileUtils.rm_f frozen_version_file + end + + private # Copy a file from the Bones prototype project location to the user # specified project location. A message will be displayed to the screen - # indicating tha the file is being created. + # indicating that the file is being created. # def cp( file ) dir = File.dirname(file) dir = (dir == '.' ? name : File.join(name, dir)) dst = File.join(dir, File.basename(file, '.erb').sub('NAME', name)) @@ -177,9 +249,25 @@ end ary.compact! ary.sort! ary + end + + # Returns the .bones resource directory in the user's home directory. + # + def mrbones_dir + return @mrbones_dir if defined? @mrbones_dir + + path = (::Bones::WIN32 ? ENV['HOMEPATH'].tr("\\", "/") : ENV['HOME']) + path = File.join(path, '.mrbones') + @mrbones_dir = File.expand_path(path) + end + + # File containing the Mr Bones version from which the skeleton was frozen. + # + def frozen_version_file + File.join(mrbones_dir, 'version.txt') end end # class Main end # module Bones