vagrant-devcommands 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ module VagrantPlugins
5
5
  class Help
6
6
  UTIL = VagrantPlugins::DevCommands::Util
7
7
  MESSAGES = VagrantPlugins::DevCommands::Messages
8
+ PRINTER = VagrantPlugins::DevCommands::HelpPrinter
8
9
 
9
10
  def initialize(env, registry)
10
11
  @env = env
@@ -16,120 +17,82 @@ module VagrantPlugins
16
17
 
17
18
  command = argv[0]
18
19
 
19
- return plugin_help(command) unless @registry.valid_command?(command)
20
+ return plugin_help(command) unless @registry.available?(command)
20
21
  return internal_help(command) if @registry.reserved_command?(command)
21
22
 
22
- command_help(command)
23
+ help(command)
23
24
  end
24
25
 
25
26
  private
26
27
 
27
- def command_help(command)
28
- command_help_header(command)
29
- command_help_parameters(command)
30
- command_help_body(@registry.commands[command].help)
31
- end
32
-
33
- def command_help_body(help)
34
- @env.ui.info ''
35
-
36
- if help.nil?
37
- message(:no_help)
28
+ def help(command)
29
+ if @registry.valid_chain?(command)
30
+ PRINTER::Chain.new(@env).output(@registry.chains[command])
38
31
  else
39
- @env.ui.info help.strip
32
+ PRINTER::Command.new(@env).output(@registry.commands[command])
40
33
  end
41
34
  end
42
35
 
43
- def command_help_header(command)
44
- usage = "vagrant run [box] #{command}"
45
- usage = usage_params(usage, @registry.commands[command])
46
-
47
- unless @registry.commands[command].usage.nil?
48
- usage = @registry.commands[command].usage % { command: command }
49
- end
50
-
51
- @env.ui.info "Usage: #{usage}"
52
- end
53
-
54
- def command_help_parameters(command)
55
- return if @registry.commands[command].parameters.nil?
56
-
57
- @env.ui.info ''
58
- @env.ui.info 'Parameters:'
59
-
60
- command_help_parameters_body(command)
61
- end
62
-
63
- def command_help_parameters_body(command)
64
- params = @registry.commands[command].parameters
65
- pad_to = UTIL.pad_to(params)
66
-
67
- params.sort.each do |name, options|
68
- @env.ui.info UTIL.padded_columns(pad_to, name, options[:desc])
69
- end
36
+ def info(msg, pre_ln = false)
37
+ @env.ui.info '' if pre_ln
38
+ @env.ui.info msg
70
39
  end
71
40
 
72
41
  def internal_commands
73
- VagrantPlugins::DevCommands::Internal::COMMANDS
42
+ VagrantPlugins::DevCommands::Runner::InternalCommand::COMMANDS
74
43
  end
75
44
 
76
45
  def internal_help(command)
77
46
  internal_help_header(command)
47
+ info(internal_commands[command].help.strip, true)
78
48
 
79
- @env.ui.info ''
80
- @env.ui.info internal_commands[command].help.strip
49
+ message(:plugin_readme, true) if 'help' == command
81
50
  end
82
51
 
83
52
  def internal_help_header(command)
84
53
  spec = internal_commands[command]
85
- usage = spec.usage % { command: command }
54
+ usage = format(spec.usage, command: command)
86
55
 
87
- @env.ui.info "Usage: #{usage}"
56
+ info(I18n.t('vagrant_devcommands.internal.help.usage', what: usage))
88
57
  end
89
58
 
90
- def message(msg)
91
- MESSAGES.public_send(msg, &@env.ui.method(:info))
59
+ def message(msg, pre_ln = false)
60
+ if pre_ln
61
+ MESSAGES.pre_ln(msg, &@env.ui.method(:info))
62
+ else
63
+ MESSAGES.public_send(msg, &@env.ui.method(:info))
64
+ end
92
65
  end
93
66
 
94
67
  def plugin_help(command)
95
68
  message(:plugin_usage) unless '--commands' == command
96
69
 
97
- pad_to = UTIL.pad_to(internal_commands.merge(@registry.commands))
70
+ pad_to = UTIL.max_pad([internal_commands,
71
+ @registry.commands,
72
+ @registry.chains])
98
73
 
99
74
  plugin_help_commands('Available', @registry.commands, pad_to)
75
+ plugin_help_chains(@registry.chains, pad_to)
100
76
  plugin_help_commands('Internal', internal_commands, pad_to)
101
-
102
- message(:plugin_usage_info) unless '--commands' == command
103
77
  end
104
78
 
105
- def plugin_help_commands(type, commands, pad_to)
106
- @env.ui.info ''
107
- @env.ui.info "#{type} commands:"
79
+ def plugin_help_chains(chains, pad_to)
80
+ return if chains.empty?
108
81
 
109
- commands.sort.each do |name, command|
110
- @env.ui.info UTIL.padded_columns(pad_to, name, command.desc)
82
+ info('Command chains:', true)
83
+
84
+ chains.sort.each do |name, chain|
85
+ info(UTIL.padded_columns(pad_to, name, chain.desc))
111
86
  end
112
87
  end
113
88
 
114
- def usage_params(usage, command)
115
- return usage if command.parameters.nil?
116
-
117
- [
118
- usage,
119
- usage_params_mandatory(command.parameters),
120
- usage_params_optional(command.parameters)
121
- ].flatten.compact.join(' ').strip
122
- end
89
+ def plugin_help_commands(type, commands, pad_to)
90
+ return if commands.empty?
123
91
 
124
- def usage_params_mandatory(params)
125
- params.collect do |key, opts|
126
- "--#{key}=<#{key}>" unless opts[:optional]
127
- end
128
- end
92
+ info("#{type} commands:", true)
129
93
 
130
- def usage_params_optional(params)
131
- params.collect do |key, opts|
132
- "[--#{key}=<#{key}>]" if opts[:optional]
94
+ commands.sort.each do |name, command|
95
+ info(UTIL.padded_columns(pad_to, name, command.desc))
133
96
  end
134
97
  end
135
98
  end
@@ -2,18 +2,20 @@ module VagrantPlugins
2
2
  module DevCommands
3
3
  # Contains the specs for internal commands
4
4
  class InternalSpec
5
+ I18N_KEY = 'vagrant_devcommands.internal'.freeze
6
+
5
7
  HELP = {
6
- desc: I18n.t('vagrant_devcommands.internal.help.desc'),
8
+ desc: I18n.t("#{I18N_KEY}.help.desc"),
7
9
  name: 'help',
8
10
  usage: 'vagrant run %{command} [command]',
9
- help: I18n.t('vagrant_devcommands.internal.help.help')
11
+ help: I18n.t("#{I18N_KEY}.help.help")
10
12
  }.freeze
11
13
 
12
14
  VERSION = {
13
- desc: I18n.t('vagrant_devcommands.internal.version.desc'),
15
+ desc: I18n.t("#{I18N_KEY}.version.desc"),
14
16
  name: 'version',
15
17
  usage: 'vagrant run %{command}',
16
- help: I18n.t('vagrant_devcommands.internal.version.help')
18
+ help: I18n.t("#{I18N_KEY}.version.help")
17
19
  }.freeze
18
20
  end
19
21
  end
@@ -4,29 +4,39 @@ module VagrantPlugins
4
4
  module DevCommands
5
5
  # Provides access to messages used by the plugin
6
6
  class Messages
7
- def self.no_help(&out)
8
- out.call 'No detailed help for this command available.'
7
+ I18N_KEY = 'vagrant_devcommands.message'.freeze
8
+
9
+ def self.chain_no_help(&out)
10
+ out.call I18n.t("#{I18N_KEY}.chain_no_help")
9
11
  end
10
12
 
11
- def self.no_commands(&out)
12
- out.call 'No commands defined!'
13
+ def self.command_no_help(&out)
14
+ out.call I18n.t("#{I18N_KEY}.command_no_help")
13
15
  end
14
16
 
15
- def self.plugin_usage(&out)
16
- out.call 'Usage: vagrant run [box] <command>'
17
- out.call 'Help: vagrant run help <command>'
17
+ def self.missing_commandfile(&out)
18
+ out.call I18n.t("#{I18N_KEY}.missing_commandfile")
19
+ end
20
+
21
+ def self.no_commands(&out)
22
+ out.call I18n.t("#{I18N_KEY}.no_commands")
18
23
  end
19
24
 
20
- def self.plugin_usage_info(&out)
25
+ def self.plugin_readme(&out)
21
26
  curdir = File.expand_path(File.dirname(__FILE__))
22
27
  readme = File.expand_path(File.join(curdir, '../../../README.md'))
23
28
 
29
+ out.call I18n.t("#{I18N_KEY}.plugin_readme", readme: readme)
30
+ end
31
+
32
+ def self.plugin_usage(&out)
33
+ out.call I18n.t("#{I18N_KEY}.plugin_usage")
34
+ end
35
+
36
+ def self.pre_ln(msg, &out)
24
37
  out.call ''
25
- out.call 'For detailed usage please read the'
26
- out.call 'README.md at the original source location:'
27
- out.call '>>> https://github.com/mneudert/vagrant-devcommands'
28
- out.call 'A copy of this file should be locally available at'
29
- out.call ">>> #{readme}"
38
+
39
+ public_send(msg, &out)
30
40
  end
31
41
  end
32
42
  end
@@ -0,0 +1,28 @@
1
+ module VagrantPlugins
2
+ module DevCommands
3
+ module Model
4
+ # Definition of an executable command chain
5
+ class Chain
6
+ attr_reader :name
7
+ attr_reader :commands
8
+
9
+ attr_reader :desc
10
+ attr_reader :help
11
+
12
+ def initialize(spec)
13
+ @name = spec[:name]
14
+ @commands = spec[:commands]
15
+
16
+ @desc = spec[:desc]
17
+ @help = spec[:help]
18
+
19
+ @break_on_error = false != spec[:break_on_error]
20
+ end
21
+
22
+ def break_on_error?
23
+ @break_on_error
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,107 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module DevCommands
5
+ module Model
6
+ # Definition of an executable command
7
+ class Command
8
+ attr_reader :name
9
+
10
+ attr_reader :flags
11
+ attr_reader :parameters
12
+ attr_reader :script
13
+
14
+ attr_reader :box
15
+ attr_reader :desc
16
+ attr_reader :help
17
+ attr_reader :usage
18
+
19
+ def initialize(spec)
20
+ @name = spec[:name]
21
+
22
+ @flags = spec[:flags]
23
+ @parameters = spec[:parameters]
24
+ @script = spec[:script]
25
+
26
+ @box = spec[:box]
27
+ @desc = spec[:desc]
28
+ @help = spec[:help]
29
+ @usage = spec[:usage]
30
+ end
31
+
32
+ def run_script(argv)
33
+ script = @script
34
+ script = script.call if script.is_a?(Proc)
35
+
36
+ opts = {}
37
+ opts = parse_argv(argv) if @flags || @parameters
38
+
39
+ (script % opts).strip
40
+ end
41
+
42
+ private
43
+
44
+ def escape_option_values(options)
45
+ (@parameters || {}).each do |key, conf|
46
+ next if conf[:escape].nil?
47
+
48
+ conf[:escape].each do |char, with|
49
+ char = char.to_s unless char.is_a?(String)
50
+ options[key] = options[key].sub(char, "#{with}#{char}")
51
+ end
52
+ end
53
+
54
+ options
55
+ end
56
+
57
+ def options_with_defaults
58
+ options = {}
59
+
60
+ (@parameters || {}).each do |key, conf|
61
+ options[key] = '' if conf[:optional]
62
+ options[key] = conf[:default] unless conf[:default].nil?
63
+ end
64
+
65
+ options
66
+ end
67
+
68
+ # rubocop:disable Metrics/MethodLength
69
+ def parse_argv(argv)
70
+ options = options_with_defaults
71
+
72
+ OptionParser.new do |opts|
73
+ (@flags || {}).each do |key, conf|
74
+ options[key] = ''
75
+
76
+ opts.on("--#{key}", "Flag: #{key}") do
77
+ options[key] = conf[:value] || "--#{key}"
78
+ end
79
+ end
80
+
81
+ (@parameters || {}).each do |key, _conf|
82
+ opts.on("--#{key} OPTION", "Parameter: #{key}") do |o|
83
+ options[key] = o
84
+ end
85
+ end
86
+ end.parse!(argv)
87
+
88
+ wrap_option_values(escape_option_values(options))
89
+ end
90
+
91
+ def wrap_option_values(options)
92
+ (@parameters || {}).each do |key, conf|
93
+ next if conf[:wrap].nil?
94
+
95
+ if conf[:default].nil?
96
+ next if options[key].nil? || options[key].empty?
97
+ end
98
+
99
+ options[key] = conf[:wrap] % options[key]
100
+ end
101
+
102
+ options
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -3,7 +3,7 @@ module VagrantPlugins
3
3
  # Vagrant plugin definition
4
4
  class Plugin < Vagrant.plugin(2)
5
5
  name 'vagrant-devcommands'
6
- description 'Runs vagrant commands from a Commandfile'
6
+ description VagrantPlugins::DevCommands::SYNOPSIS
7
7
 
8
8
  command :run do
9
9
  Command
@@ -2,15 +2,24 @@ module VagrantPlugins
2
2
  module DevCommands
3
3
  # Vagrant command registry
4
4
  class Registry
5
- RESERVED_COMMANDS = %w(help version).freeze
5
+ I18N_KEY = 'vagrant_devcommands.registry'.freeze
6
+ NAMESPACE_MODEL = VagrantPlugins::DevCommands::Model
6
7
 
8
+ RESERVED_COMMANDS = %w[help version].freeze
9
+
10
+ attr_accessor :chains
7
11
  attr_accessor :commands
8
12
 
9
13
  def initialize(env)
14
+ @chains = {}
10
15
  @commands = {}
11
16
  @env = env
12
17
  end
13
18
 
19
+ def available?(name)
20
+ valid_command?(name) || valid_chain?(name)
21
+ end
22
+
14
23
  def read_commandfile(commandfile)
15
24
  global = commandfile.path_global
16
25
  local = commandfile.path
@@ -20,18 +29,35 @@ module VagrantPlugins
20
29
  contents += "\n" + local.read unless nil == local
21
30
 
22
31
  instance_eval(contents)
32
+ resolve_naming_conflicts
33
+ validate_chains
23
34
  end
24
35
 
25
36
  def reserved_command?(command)
26
37
  RESERVED_COMMANDS.include?(command)
27
38
  end
28
39
 
40
+ def valid_chain?(chain)
41
+ @chains.include?(chain)
42
+ end
43
+
29
44
  def valid_command?(command)
30
45
  @commands.include?(command) || reserved_command?(command)
31
46
  end
32
47
 
33
48
  private
34
49
 
50
+ def chain(name, options = nil)
51
+ options = {} unless options.is_a?(Hash)
52
+ options[:commands] = {} unless options.key?(:commands)
53
+
54
+ return empty_chain_warning(name) if options[:commands].empty?
55
+
56
+ options[:name] = name
57
+
58
+ @chains[name] = NAMESPACE_MODEL::Chain.new(options)
59
+ end
60
+
35
61
  def command(name, options = nil)
36
62
  return reserved_warning(name) if reserved_command?(name)
37
63
 
@@ -41,21 +67,43 @@ module VagrantPlugins
41
67
 
42
68
  options[:name] = name
43
69
 
44
- @commands[name] = CommandDef.new(options)
70
+ @commands[name] = NAMESPACE_MODEL::Command.new(options)
45
71
  end
46
72
 
47
- def script_warning(name)
48
- @env.ui.warn "The command '#{name}' has no script defined to execute."
49
- @env.ui.warn 'Your definition of it will be ignored.'
73
+ def empty_chain_warning(name)
74
+ @env.ui.warn I18n.t("#{I18N_KEY}.empty_chain", name: name)
75
+ @env.ui.warn I18n.t("#{I18N_KEY}.def_ignored")
76
+ @env.ui.warn ''
77
+ end
78
+
79
+ def missing_chain_command_warning(chain, command)
80
+ i18n_args = { chain: chain, command: command }
81
+
82
+ @env.ui.warn I18n.t("#{I18N_KEY}.missing_command", i18n_args)
83
+ @env.ui.warn I18n.t("#{I18N_KEY}.def_ignored")
50
84
  @env.ui.warn ''
51
85
  end
52
86
 
53
87
  def reserved_warning(name)
54
- @env.ui.warn(
55
- "The command name '#{name}' is reserved for internal usage."
56
- )
88
+ @env.ui.warn I18n.t("#{I18N_KEY}.reserved", name: name)
89
+ @env.ui.warn I18n.t("#{I18N_KEY}.def_ignored")
90
+ @env.ui.warn ''
91
+ end
92
+
93
+ def resolve_naming_conflicts
94
+ @chains.keys.each do |chain|
95
+ next unless @commands.key?(chain)
96
+
97
+ @env.ui.warn I18n.t("#{I18N_KEY}.conflict", name: chain)
98
+ @env.ui.warn I18n.t("#{I18N_KEY}.chain_ignored")
99
+
100
+ @chains.delete(chain)
101
+ end
102
+ end
57
103
 
58
- @env.ui.warn 'Your definition of it will be ignored.'
104
+ def script_warning(name)
105
+ @env.ui.warn I18n.t("#{I18N_KEY}.no_script", name: name)
106
+ @env.ui.warn I18n.t("#{I18N_KEY}.def_ignored")
59
107
  @env.ui.warn ''
60
108
  end
61
109
 
@@ -67,6 +115,21 @@ module VagrantPlugins
67
115
 
68
116
  true
69
117
  end
118
+
119
+ def validate_chains
120
+ @chains.all? do |chain, chain_def|
121
+ chain_def.commands.each do |element|
122
+ next unless element.is_a?(Hash)
123
+ next if valid_command?(element[:command])
124
+
125
+ missing_chain_command_warning(chain, element)
126
+
127
+ @chains.delete(chain)
128
+
129
+ break
130
+ end
131
+ end
132
+ end
70
133
  end
71
134
  end
72
135
  end