require 'thor' require 'thor/runner' module Spontaneous module Cli class Thor < ::Thor class_option :site, :type => :string, :aliases => ["-s", "--root"], :desc => "Site root dir" class_option :environment, :type => :string, :aliases => "-e", :required => true, :default => :development, :desc => "Spontaneous Environment" class_option :mode, :type => :string, :aliases => "-m", :default => :back, :desc => "Spontaneous mode ('front' or 'back')" class_option :help, :type => :boolean, :desc => "Show help usage" protected def boot! begin require File.expand_path('config/boot.rb') rescue Spontaneous::SchemaModificationError => error fix_schema(error) end end def fix_schema(error) modification = error.modification actions = modification.actions say(actions.description, :red) say("Please choose one of the solutions below", :yellow) actions.each_with_index do |a, i| say(" #{i+1}: #{a.description}") end choice = ( ask "Choose action : ").to_i rescue nil if choice and choice <= actions.length and choice > 0 action = actions[choice - 1] begin Spontaneous::Schema.apply(action) rescue Spontaneous::SchemaModificationError => error fix_schema(error) end else say("Invalid choice '#{choice.inspect}'\n", :red) fix_schema(error) end end def prepare(task, mode = nil) if options.help? help(task.to_s) raise SystemExit end ENV["SPOT_ENV"] ||= options.environment.to_s ENV["RACK_ENV"] = ENV["SPOT_ENV"] # Also set this for middleware ENV["SPOT_MODE"] = mode.to_s unless mode.nil? chdir(options.site) unless File.exist?('config/boot.rb') puts "=> Could not find boot file in: #{options.chdir}/config/boot.rb\n=> Are you sure this is a Spontaneous site?" raise SystemExit end end def chdir(dir) return unless dir begin Dir.chdir(dir.to_s) rescue Errno::ENOENT puts "=> Specified site '#{dir}' does not appear to exist" rescue Errno::EACCES puts "=> Specified site '#{dir}' cannot be accessed by the current user" end end end class Runner < ::Thor namespace "default" remove_task :help map %w(-T) => :list, %w(--version -v) => :version desc "version", "Show Spontaneous version" def version require 'spontaneous/version' say "Spontaneous #{Spontaneous::VERSION}" end desc "list [SEARCH]", "List the available tasks (--substring means .*SEARCH)" method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean def list(search="") initialize_thorfiles search = ".*#{search}" if options["substring"] search = /^#{search}.*/i group = options[:group] || "standard" klasses = Thor::Base.subclasses.select do |k| (options[:all] || k.group == group) && k.namespace =~ search end display_klasses(false, false, klasses) end # Override Thor#help so it can give information about any class and any method. # desc "help [TASK]", "Describe available tasks or one specific task" def help(task = nil, subcommand = false) task ? self.class.task_help(shell, task) : self.class.help(shell, subcommand) end # Override Thor#help so it can give information about any class and any method. # def help(meth = nil) if meth && !self.respond_to?(meth) initialize_thorfiles(meth) klass, task = Thor::Util.find_class_and_task_by_namespace(meth) klass.start(["-h", task].compact, :shell => self.shell) else list end end # If a task is not found on Thor::Runner, method missing is invoked and # Thor::Runner is then responsable for finding the task in all classes. # def method_missing(meth, *args) meth = meth.to_s initialize_thorfiles(meth) klass, task = Thor::Util.find_class_and_task_by_namespace(meth) args.unshift(task) if task klass.start(args, :shell => self.shell) end private # Display information about the given klasses. If with_module is given, # it shows a table with information extracted from the yaml file. # def display_klasses(with_modules=false, show_internal=false, klasses=Thor::Base.subclasses) klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal raise Error, "No tasks available" if klasses.empty? show_modules if with_modules && !thor_yaml.empty? list = Hash.new { |h,k| h[k] = [] } groups = klasses.select { |k| k.ancestors.include?(Thor::Group) } # Get classes which inherit from Thor (klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_tasks(false) } list.delete("thor") # Order namespaces with default coming first list = list.sort{ |a,b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') } list.each { |n, tasks| display_tasks(n, tasks) unless tasks.empty? } end def display_tasks(namespace, list) #:nodoc: list.sort!{ |a,b| a[0] <=> b[0] } say shell.set_color(namespace, :blue, true) say "-" * namespace.size print_table(list, :truncate => true) say end def initialize_thorfiles(relevant_to=nil, skip_lookup=false) thorfiles(relevant_to, skip_lookup).each do |f| Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f)) end end def thorfiles(*args) task_dir = File.expand_path('../cli', __FILE__) Dir["#{task_dir}/*.rb"] end end autoload :Adapter, "spontaneous/cli/adapter" autoload :Base, "spontaneous/cli/base" autoload :Site, "spontaneous/cli/site" autoload :User, "spontaneous/cli/user" end end