require 'optparse' module Dandelion class CLI def initialize(args) @args = args @options = {} @options[:help] = true if @args.length == 0 @parser = Command::Base.parser(@options) end def config @config ||= Config.new(path: config_path).tap do |config| config[:adapter] ||= config[:scheme] # backward compat end end def adapter @adapter ||= Adapter::Base.create_adapter(config[:adapter], config) rescue Adapter::InvalidAdapterError => e log.fatal("Unsupported adapter: #{config[:adapter]}") exit 1 rescue Adapter::MissingDependencyError => e log.fatal("The #{config[:adapter]} adapter requires additional gems:") log.fatal(e.gems.map { |name| " #{name}"}.join("\n")) log.fatal("Please install the gems first: gem install #{e.gems.join(' ')}") exit 1 end def repo @repo ||= Rugged::Repository.new(repo_path) end def workspace @workspace ||= Workspace.new(repo, adapter, config) end def command_class @command_class ||= Command::Base.lookup(@args.shift.to_sym) rescue Command::InvalidCommandError => e log.fatal("Invalid command: #{e}") display_help exit 1 end def execute! parse!(@parser) if @options[:help] display_help exit end if @options[:version] log.info("Dandelion #{Dandelion::VERSION}") exit end validate! parse!(command_class.parser(@options)) command = command_class.new(workspace, config, @options) command.setup(@args) begin command.execute! rescue RevisionError => e log.fatal("Invalid revision: #{e}") exit 1 end end private def config_path @options[:config] || File.join(repo_path, 'dandelion.yml') end def repo_path if @options[:repo] File.expand_path(@options[:repo]) else closest_repo(File.expand_path('.')) end end def validate! unless File.exists?(File.join(repo_path, '.git')) log.fatal("Not a git repository: #{repo_path}") exit 1 end unless File.exists?(config_path) log.fatal("Missing config file: #{config_path}") exit 1 end end def parse!(parser) begin parser.order!(@args) rescue OptionParser::InvalidOption => e log.fatal(e.to_s.capitalize) display_help exit 1 end end def closest_repo(dir) if File.exists?(File.join(dir, '.git')) dir else File.dirname(dir) != dir && closest_repo(File.dirname(dir)) || File.expand_path('.') end end def display_help log.info(@parser.help) log.info("Available commands:") log.info(Command::Base.commands.map { |c| " #{c}"}.join("\n")) end def log Dandelion.logger end end end