Class: Moonshot::CommandLine

Inherits:
Object
  • Object
show all
Defined in:
lib/moonshot/command_line.rb

Overview

This class implements the command-line ‘moonshot` tool.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.register(klass) ⇒ Object



6
7
8
9
# File 'lib/moonshot/command_line.rb', line 6

def self.register(klass)
  @classes ||= []
  @classes << klass
end

.registered_commandsObject



11
12
13
# File 'lib/moonshot/command_line.rb', line 11

def self.registered_commands
  @classes || []
end

Instance Method Details

#commandify(klass) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/moonshot/command_line.rb', line 120

def commandify(klass)
  word = klass.to_s.split('::').last
  word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
  word.tr!('_', '-')
  word.downcase!
  word
end

#handle_early_commandsObject



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/moonshot/command_line.rb', line 129

def handle_early_commands
  # If this is a legacy (Thor) help command, re-write it as
  # OptionParser format.
  case ARGV[0]
  when 'help'
    ARGV.delete_at(0)
    ARGV.push('-h')
  when 'new'
    app_name = ARGV[1]
    ::Moonshot::Commands::New.run!(app_name)
    return true
  end

  # Proceed to processing commands normally.
  false
end

#load_cli_extensions(moonfile_dir) ⇒ Object



80
81
82
83
84
85
# File 'lib/moonshot/command_line.rb', line 80

def load_cli_extensions(moonfile_dir)
  cli_extensions_path = File.join(moonfile_dir, 'moonshot', 'cli_extensions', '**', '*.rb')
  Dir.glob(cli_extensions_path).each do |file|
    load(file)
  end
end

#load_commandsObject



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/moonshot/command_line.rb', line 104

def load_commands
  @commands = {}

  # Include all Moonshot::Command and Moonshot::SSHCommand
  # derived classes as subcommands, with the description of their
  # default task.
  self.class.registered_commands.each do |klass|
    next unless klass.instance_methods.include?(:execute)

    command_name = commandify(klass)
    @commands[command_name] = klass
  end

  @commands = @commands.sort_by { |k, _v| k.to_s }.to_h
end

#load_plugins(moonfile_dir) ⇒ Object



73
74
75
76
77
78
# File 'lib/moonshot/command_line.rb', line 73

def load_plugins(moonfile_dir)
  plugins_path = File.join(moonfile_dir, 'moonshot', 'plugins', '**', '*.rb')
  Dir.glob(plugins_path).each do |file|
    load(file)
  end
end

#run!Object

rubocop:disable Metrics/MethodLength



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/moonshot/command_line.rb', line 15

def run! # rubocop:disable Metrics/MethodLength
  # Commands defined as Moonshot::Commands require a properly
  # configured Moonshot.rb and supporting files. Without them, we only
  # support `--help` and `new`.
  return if handle_early_commands

  # Find the Moonfile in this project.
  orig_dir = Dir.pwd

  loop do
    break if File.exist?('Moonfile.rb')

    if Dir.pwd == '/'
      warn 'No Moonfile.rb found, are you in a project? Maybe you need to '\
            'create one with `moonshot new <app_name>`?'
      raise 'No Moonfile found'
    end

    Dir.chdir('..')
  end

  moonfile_dir = Dir.pwd
  Dir.chdir(orig_dir)

  # Load any plugins and CLI extensions relative to the Moonfile
  if File.directory?(File.join(moonfile_dir, 'moonshot'))
    load_plugins(moonfile_dir)
    load_cli_extensions(moonfile_dir)
  end

  Object.include(Moonshot::ArtifactRepository)
  Object.include(Moonshot::BuildMechanism)
  Object.include(Moonshot::DeploymentMechanism)
  load(File.join(moonfile_dir, 'Moonfile.rb'))

  Moonshot.config.project_root = moonfile_dir

  load_commands

  # Determine what command is being run, which should be the first argument.
  command = ARGV.shift
  if %w[--help -h help].include?(command) || command.nil?
    usage
    return
  end

  # Dispatch to that command, by executing it's parser, then
  # comparing ARGV to the execute methods arity.
  unless @commands.key?(command)
    usage
    raise "Command not found '#{command}'"
  end

  command_class = @commands[command]

  CommandLineDispatcher.new(command, command_class, ARGV).dispatch!
end

#usageObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/moonshot/command_line.rb', line 87

def usage
  warn 'Usage: moonshot [command]'
  warn
  warn 'Valid commands include:'
  fields = []
  @commands.each do |c, k|
    fields << [c, k.description]
  end

  max_len = fields.map(&:first).map(&:size).max

  fields.each do |f|
    line = format("  %-#{max_len}s # %s", *f) # rubocop:disable Lint/FormatParameterMismatch
    warn line
  end
end