require "thor" # Override thor's long_desc identation behavior # https://github.com/erikhuda/thor/issues/398 class Thor module Shell class Basic def print_wrapped(message, options = {}) message = "\n#{message}" unless message[0] == "\n" stdout.puts message end end end end # Gets rid of the c_l_i extra commands in the help menu. Seems like thor_classes_in is only used # for this purpose. More details: https://gist.github.com/tongueroo/ee92ec28a4d3eed301d88e8ccdd2fe10 module ThorPrepend module Util def thor_classes_in(klass) klass.name.include?("CLI") ? [] : super end end end Thor::Util.singleton_class.prepend(ThorPrepend::Util) module Terraspace class Command < Thor class << self include Terraspace::Util::Logging def dispatch(m, args, options, config) # Terraspace.argv provides consistency when terraspace is being called by rspec-terrspace test harness Terraspace.argv = args.clone # important to clone since Thor removes the first argv check_standalone_install! check_project!(args.first) # Allow calling for help via: # terraspace command help # terraspace command -h # terraspace command --help # terraspace command -D # # as well thor's normal way: # # terraspace help command if args.length > 1 && !(args & help_flags).empty? args -= help_flags args.insert(-2, "help") end # terraspace version # terraspace --version # terraspace -v version_flags = ["--version", "-v"] if args.length == 1 && !(args & version_flags).empty? args = ["version"] end super end def help_flags Thor::HELP_MAPPINGS + ["help"] end private :help_flags def check_standalone_install! return unless opt? version_manager = "rvm" if rvm? version_manager = "rbenv" if rbenv? if rbenv? || rvm? puts <<~EOL.color(:yellow) WARN: It looks like a standalone Terraspace install and #{version_manager} is also in use. Different gems from the standalone Terraspace install and #{version_manager} can cause all kinds of trouble. Please install Terraspace as a gem instead and remove the standalone Terraspace /opt/terraspace installation. See: https://terraspace.cloud/docs/install/gem/ EOL end end def opt? paths = ENV['PATH'].split(':') opt = paths.detect { |p| p.include?('/opt/terraspace') } opt && File.exist?('/opt/terraspace') end def rvm? paths = ENV['PATH'].split(':') rvm = paths.detect { |p| p.include?('/rvm/') || p.include?('/.rvm/') } rvm && system("type rvm > /dev/null 2>&1") end def rbenv? paths = ENV['PATH'].split(':') rbenv = paths.detect { |p| p.include?('/rbenv/') || p.include?('/.rbenv/') } rbenv && system("type rbenv > /dev/null 2>&1") end def check_project!(command_name) return if subcommand? return if command_name.nil? return if help_flags.include?(Terraspace.argv.last) # IE: -h help return if %w[-h -v check_setup completion completion_script help new test version].include?(command_name) return if File.exist?("#{Terraspace.root}/config/app.rb") logger.error "ERROR: It doesnt look like this is a terraspace project. Are you sure you are in a terraspace project?".color(:red) ENV['TS_TEST'] ? raise : exit(1) end def subcommand? !!caller.detect { |l| l.include?('in subcommand') } end # Override command_help to include the description at the top of the # long_description. def command_help(shell, command_name) meth = normalize_command_name(command_name) command = all_commands[meth] alter_command_description(command) super end def alter_command_description(command) return unless command # Add description to beginning of long_description long_desc = if command.long_description "#{command.description}\n\n#{command.long_description}" else command.description end # add reference url to end of the long_description unless website.empty? full_command = [command.ancestor_name, command.name].compact.join('-') url = "#{website}/reference/terraspace-#{full_command}" long_desc += "\n\nHelp also available at: #{url}" end command.long_description = long_desc end private :alter_command_description # meant to be overriden def website "https://terraspace.cloud" end # https://github.com/erikhuda/thor/issues/244 # Deprecation warning: Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `Lono::CLI` # You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION. def exit_on_failure? true end end end end