rhc 1.6.8 → 1.7.8

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.
Files changed (85) hide show
  1. data/autocomplete/rhc_bash +1167 -0
  2. data/features/README.md +1 -1
  3. data/features/domain.feature +1 -1
  4. data/features/lib/rhc_helper/persistable.rb +4 -1
  5. data/features/multiple_cartridge.feature +4 -3
  6. data/features/sshkey.feature +3 -3
  7. data/features/support/assumptions.rb +3 -3
  8. data/features/support/env.rb +10 -0
  9. data/features/support/platform_support.rb +2 -2
  10. data/lib/rhc.rb +6 -0
  11. data/lib/rhc/auth/token.rb +4 -0
  12. data/lib/rhc/autocomplete.rb +50 -52
  13. data/lib/rhc/autocomplete_templates/{rhc.erb → bash.erb} +8 -2
  14. data/lib/rhc/cartridge_helpers.rb +1 -1
  15. data/lib/rhc/cli.rb +1 -7
  16. data/lib/rhc/command_runner.rb +45 -16
  17. data/lib/rhc/commands.rb +75 -55
  18. data/lib/rhc/commands/account.rb +7 -51
  19. data/lib/rhc/commands/alias.rb +26 -17
  20. data/lib/rhc/commands/app.rb +75 -39
  21. data/lib/rhc/commands/authorization.rb +4 -2
  22. data/lib/rhc/commands/base.rb +31 -29
  23. data/lib/rhc/commands/cartridge.rb +66 -44
  24. data/lib/rhc/commands/domain.rb +20 -8
  25. data/lib/rhc/commands/git_clone.rb +3 -3
  26. data/lib/rhc/commands/logout.rb +51 -0
  27. data/lib/rhc/commands/port_forward.rb +15 -11
  28. data/lib/rhc/commands/setup.rb +25 -0
  29. data/lib/rhc/commands/snapshot.rb +20 -10
  30. data/lib/rhc/commands/sshkey.rb +21 -7
  31. data/lib/rhc/commands/tail.rb +2 -2
  32. data/lib/rhc/commands/threaddump.rb +2 -2
  33. data/lib/rhc/context_helper.rb +0 -4
  34. data/lib/rhc/core_ext.rb +96 -76
  35. data/lib/rhc/exceptions.rb +6 -0
  36. data/lib/rhc/help_formatter.rb +19 -2
  37. data/lib/rhc/helpers.rb +32 -194
  38. data/lib/rhc/highline_extensions.rb +412 -0
  39. data/lib/rhc/output_helpers.rb +31 -67
  40. data/lib/rhc/rest.rb +4 -2
  41. data/lib/rhc/rest/alias.rb +0 -2
  42. data/lib/rhc/rest/application.rb +9 -4
  43. data/lib/rhc/rest/authorization.rb +0 -2
  44. data/lib/rhc/rest/base.rb +1 -1
  45. data/lib/rhc/rest/client.rb +11 -9
  46. data/lib/rhc/rest/domain.rb +5 -1
  47. data/lib/rhc/rest/gear_group.rb +0 -2
  48. data/lib/rhc/rest/key.rb +0 -2
  49. data/lib/rhc/rest/mock.rb +32 -10
  50. data/lib/rhc/ssh_helpers.rb +2 -2
  51. data/lib/rhc/usage_templates/command_help.erb +20 -13
  52. data/lib/rhc/usage_templates/command_syntax_help.erb +1 -3
  53. data/lib/rhc/usage_templates/help.erb +15 -16
  54. data/lib/rhc/usage_templates/options_help.erb +7 -9
  55. data/lib/rhc/wizard.rb +193 -159
  56. data/spec/rest_spec_helper.rb +2 -2
  57. data/spec/rhc/cli_spec.rb +36 -5
  58. data/spec/rhc/command_spec.rb +94 -42
  59. data/spec/rhc/commands/account_spec.rb +1 -75
  60. data/spec/rhc/commands/alias_spec.rb +28 -28
  61. data/spec/rhc/commands/app_spec.rb +141 -33
  62. data/spec/rhc/commands/apps_spec.rb +4 -4
  63. data/spec/rhc/commands/authorization_spec.rb +8 -8
  64. data/spec/rhc/commands/cartridge_spec.rb +18 -9
  65. data/spec/rhc/commands/domain_spec.rb +16 -16
  66. data/spec/rhc/commands/git_clone_spec.rb +3 -3
  67. data/spec/rhc/commands/logout_spec.rb +86 -0
  68. data/spec/rhc/commands/port_forward_spec.rb +9 -9
  69. data/spec/rhc/commands/server_spec.rb +5 -5
  70. data/spec/rhc/commands/setup_spec.rb +19 -5
  71. data/spec/rhc/commands/snapshot_spec.rb +12 -12
  72. data/spec/rhc/commands/sshkey_spec.rb +11 -11
  73. data/spec/rhc/commands/tail_spec.rb +5 -5
  74. data/spec/rhc/commands/threaddump_spec.rb +3 -3
  75. data/spec/rhc/config_spec.rb +6 -6
  76. data/spec/rhc/helpers_spec.rb +72 -219
  77. data/spec/rhc/highline_extensions_spec.rb +269 -0
  78. data/spec/rhc/rest_application_spec.rb +28 -1
  79. data/spec/rhc/rest_client_spec.rb +20 -21
  80. data/spec/rhc/rest_spec.rb +10 -0
  81. data/spec/rhc/wizard_spec.rb +72 -32
  82. data/spec/spec_helper.rb +86 -56
  83. data/spec/wizard_spec_helper.rb +7 -4
  84. metadata +165 -160
  85. data/spec/spec.opts +0 -1
@@ -179,7 +179,7 @@ doesn't exist.
179
179
  Given "a demo directory exists or is created" do
180
180
  begin
181
181
  Given "the demo directory exists"
182
- rescue Spec::Expectations::ExpectationNotMetError
182
+ rescue RSpec::Expectations::ExpectationNotMetError
183
183
  Then "create the demo directory"
184
184
  end
185
185
  end
@@ -17,7 +17,7 @@ Feature: Existing Domain Operations
17
17
 
18
18
  Scenario: Domain Create Fails
19
19
  When rhc domain create is called
20
- Then the domain command should fail with an exitcode of 128
20
+ Then the domain command should fail with an exitcode of 1
21
21
 
22
22
  Scenario: Domain Delete
23
23
  When domain is deleted
@@ -31,7 +31,10 @@ module RHCHelper
31
31
  app.mysql_password = json['mysql_password']
32
32
  app.mysql_hostname = json['mysql_hostname']
33
33
  app.uid = json['uid']
34
- return app
34
+ # Strip off any version info for the type
35
+ app.type = app.type.split('-').first
36
+
37
+ app
35
38
  end
36
39
  end
37
40
 
@@ -8,11 +8,12 @@ Feature: Multiple Cartridge Tests
8
8
  Then the phpmyadmin cartridge should be running
9
9
 
10
10
  @not-origin
11
- Scenario: Conflicting Cartridge Fails
12
- Then adding the postgresql cartridge should fail
11
+ Scenario: Multiple DBs Allowed
12
+ When the postgresql cartridge is added
13
+ Then the postgresql cartridge should be running
13
14
 
14
15
  Scenario: Cartridge Removed
15
16
  When the phpmyadmin cartridge is removed
16
17
  When the mysql cartridge is removed
17
18
  Then the phpmyadmin cartridge should be removed
18
- Then the mysql cartridge should be removed
19
+ Then the mysql cartridge should be removed
@@ -28,7 +28,7 @@ As an OpenShift user, I want to manage SSH keys with 'rhc sshkey' commands.
28
28
  @sshkey_add
29
29
  Scenario: invalid key name is given
30
30
  When a new SSH key "key1.pub" is added as "blah\\ss"
31
- Then the command exits with status code 128
31
+ Then the command exits with status code 1
32
32
 
33
33
  @sshkey_add
34
34
  Scenario: invalid SSH key is added
@@ -43,13 +43,13 @@ As an OpenShift user, I want to manage SSH keys with 'rhc sshkey' commands.
43
43
  @sshkey_add @key1
44
44
  Scenario: SSH key with the same name already exists
45
45
  When a new SSH key "key2.pub" is added as "key1"
46
- Then the command exits with status code 128
46
+ Then the command exits with status code 1
47
47
 
48
48
  @sshkey_add
49
49
  Scenario: SSH key with the identical content already exists
50
50
  Given a new SSH key "key1.pub" is added as "key1"
51
51
  And a new SSH key "key1.pub" is added as "key2"
52
- Then the command exits with status code 128
52
+ Then the command exits with status code 1
53
53
 
54
54
  @sshkey_remove @key1
55
55
  Scenario: SSH key is deleted successfully
@@ -9,7 +9,7 @@ Given 'we have an existing domain' do
9
9
  begin
10
10
  step 'the key "key1" is shown'
11
11
  step 'the output includes the key information for "key1"'
12
- rescue Spec::Expectations::ExpectationNotMetError
12
+ rescue RSpec::Expectations::ExpectationNotMetError
13
13
  step 'a new SSH key "key1.pub" is added as "key1"'
14
14
  end
15
15
  end
@@ -27,7 +27,7 @@ Given /^we have a (.*) (.*) cartridge$/ do |status,type|
27
27
  retried = false
28
28
  begin
29
29
  step "the #{type} cartridge should be #{status}"
30
- rescue Spec::Expectations::ExpectationNotMetError
30
+ rescue RSpec::Expectations::ExpectationNotMetError
31
31
  step "the #{type} cartridge is #{cmd}"
32
32
  (retried = true && retry) unless retried
33
33
  end
@@ -43,7 +43,7 @@ Given /^we have a (stopped|running) application$/ do |state|
43
43
 
44
44
  begin
45
45
  step "the application should #{before}"
46
- rescue Spec::Expectations::ExpectationNotMetError
46
+ rescue RSpec::Expectations::ExpectationNotMetError
47
47
  step "the application is #{after}"
48
48
  end
49
49
  end
@@ -1,5 +1,15 @@
1
1
  $: << File.expand_path(File.join(File.dirname(__FILE__), "../lib"))
2
2
 
3
+ begin
4
+ require 'rspec/expectations'
5
+ World(RSpec::Matchers)
6
+ rescue
7
+ puts "Require RSpec >= 2"
8
+ exit 1
9
+ end
10
+
11
+ $target_os = ENV['RHC_TARGET'] || (File.exist?("/etc/fedora-release") ? "Fedora" : "RHEL")
12
+
3
13
  require 'rhc/coverage_helper'
4
14
  SimpleCov.at_exit{ SimpleCov.result.format! } if defined? SimpleCov
5
15
 
@@ -1,4 +1,4 @@
1
- if File.exist?("/etc/fedora-release")
1
+ if $target_os == 'Fedora'
2
2
  CARTRIDGE_MAP = {
3
3
  "php" => { type: "php-5.4", name: "PHP 5.4" },
4
4
  "mysql" => { type: "mysql-5.1", name: "MySQL Database 5.1" },
@@ -26,4 +26,4 @@ end
26
26
 
27
27
  def map_cartridge_name(type)
28
28
  CARTRIDGE_MAP[type][:name]
29
- end
29
+ end
data/lib/rhc.rb CHANGED
@@ -11,6 +11,7 @@ require 'pry' if ENV['PRY']
11
11
  require 'rhc/core_ext'
12
12
 
13
13
  module RHC
14
+ autoload :AutoComplete, 'rhc/autocomplete'
14
15
  autoload :Auth, 'rhc/auth'
15
16
  autoload :CartridgeHelpers, 'rhc/cartridge_helpers'
16
17
  autoload :CommandRunner, 'rhc/command_runner'
@@ -27,3 +28,8 @@ end
27
28
 
28
29
  require 'rhc/exceptions'
29
30
 
31
+ require 'commander'
32
+ require 'commander/delegates'
33
+ require 'highline/system_extensions'
34
+
35
+ require 'rhc/highline_extensions'
@@ -16,8 +16,10 @@ module RHC::Auth
16
16
 
17
17
  def to_request(request)
18
18
  if token
19
+ debug "Using token authentication"
19
20
  (request[:headers] ||= {})['authorization'] = "Bearer #{token}"
20
21
  elsif auth and (!@allows_tokens or @can_get_token == false)
22
+ debug "Bypassing token auth"
21
23
  auth.to_request(request)
22
24
  end
23
25
  request
@@ -56,6 +58,7 @@ module RHC::Auth
56
58
  if has_token
57
59
  raise RHC::Rest::TokenExpiredOrInvalid, "Your authorization token is expired or invalid."
58
60
  end
61
+ debug "Cannot authenticate via token or password, exiting"
59
62
  return false
60
63
  end
61
64
 
@@ -78,6 +81,7 @@ module RHC::Auth
78
81
 
79
82
  return auth.retry_auth?(response, client) unless @can_get_token
80
83
 
84
+ debug "Creating a new authorization token"
81
85
  if auth_token = client.new_session(:auth => auth)
82
86
  @fetch_once = true
83
87
  save(auth_token.token)
@@ -1,68 +1,66 @@
1
- require 'rhc'
2
- require 'commander'
3
- require 'commander/runner'
4
- require 'commander/delegates'
5
- require 'rhc/commands'
6
-
7
1
  module RHC
8
- class AutoCompleteBindings
9
- attr_reader :top_level_opts, :commands
10
- def initialize(top_level_opts, commands)
11
- @top_level_opts = top_level_opts
12
- @commands = commands
13
- end
14
- end
15
-
16
2
  class AutoComplete
17
- def initialize(script="rhc")
18
- @script_erb = ERB.new(File.read(File.join(File.dirname(__FILE__), 'autocomplete_templates', "#{script}.erb")), nil, '-')
19
- cli_init
20
- # :name => {:actions => [], :switches => []}
21
- @command_data = {}
22
- @top_level_commands = []
23
- @global_switches = []
24
- Commander::Runner.instance.options.each { |o| @global_switches << o[:switches][-1] }
3
+ attr_reader :runner
4
+
5
+ def initialize(runner=::Commander::Runner.instance, shell='bash')
6
+ @runner, @shell = runner, shell
25
7
  end
26
8
 
27
- def gen()
28
- process_data
29
- gen_script
9
+ def to_s
10
+ @s ||= template.result AutoCompleteBindings.new(self).get_binding
30
11
  end
31
12
 
32
13
  private
33
- def cli_init
34
- runner = RHC::CommandRunner.new([])
35
- Commander::Runner.instance_variable_set :@singleton, runner
36
- RHC::Commands.load.to_commander
14
+
15
+ def template
16
+ @template ||= ERB.new(File.read(File.join(File.dirname(__FILE__), 'autocomplete_templates', "#{@shell}.erb")), nil, '-')
37
17
  end
18
+ end
19
+
20
+ class AutoCompleteBindings
21
+ attr_reader :commands, :top_level_commands, :global_options
22
+
23
+ def initialize(data)
24
+ @commands = {}
25
+ @top_level_commands = []
38
26
 
39
- def process_data
40
- Commander::Runner.instance.commands.each_pair do |name, cmd|
41
- next if cmd.summary.nil?
27
+ data.runner.commands.each_pair do |name, cmd|
28
+ next if cmd.summary.nil?
29
+ next if cmd.deprecated(name)
42
30
 
43
- if name.rindex(' ').nil?
31
+ if cmd.root?
32
+ if cmd.name == name
44
33
  @top_level_commands << name
45
- else
46
- commands = name.split ' '
47
- action = commands.pop
48
- id = commands.join(' ')
49
- data = @command_data[:"#{id}"] || {:actions => [],
50
- :switches => []}
51
- data[:actions] << action
52
- @command_data[:"#{id}"] = data
53
34
  end
54
-
55
- switches = []
56
- cmd.options { |o| switches << o[:switches][-1] if o[:switches] }
57
- data = @command_data[:"#{name}"] || {:actions => [],
58
- :switches => []}
59
- data[:switches] = switches.concat(@global_switches)
60
- @command_data[:"#{name}"] = data
35
+ else
36
+ @top_level_commands << name if name == cmd.name
37
+ commands = name.split ' '
38
+ action = commands.pop
39
+ id = commands.join(' ')
40
+ v = @commands[id] || {:actions => [], :switches => []}
41
+ v[:actions] << action unless id == '' && name != cmd.name
42
+ @commands[id] = v
61
43
  end
62
- end
63
44
 
64
- def gen_script
65
- @script_erb.result AutoCompleteBindings.new(@top_level_commands.join(' '), @command_data).get_binding
45
+ v = @commands[name.to_s] || {:actions => [], :switches => []}
46
+ v[:switches].concat(cmd.options.map do |o|
47
+ if o[:switches]
48
+ s = o[:switches][-1].split(' ')[0]
49
+ if m = /--\[no-\](.+)/.match(s)
50
+ s = ["--#{m[1]}", "--no-#{m[1]}"]
51
+ else
52
+ s
53
+ end
54
+ end
55
+ end.flatten.compact.sort)
56
+ @commands[name.to_s] = v
66
57
  end
67
- end
58
+ @commands.delete('')
59
+ @commands = @commands.to_a.sort{ |a,b| a[0] <=> b[0] }
60
+
61
+ @top_level_commands.sort!
62
+
63
+ @global_options = data.runner.options.map{ |o| o[:switches][-1].split(' ')[0] }.sort
64
+ end
65
+ end
68
66
  end
@@ -7,13 +7,19 @@ _rhc()
7
7
  COMPREPLY=()
8
8
  cur="${COMP_WORDS[COMP_CWORD]}"
9
9
  if [ $COMP_CWORD -eq 1 ]; then
10
- opts=<%= "\"%s\"" % @top_level_opts %>
10
+ if [[ "$cur" == -* ]]; then
11
+ opts=<%= "\"%s\"" % global_options.join(' ') %>
12
+ elif [ -z $cur ]; then
13
+ opts=<%= "\"%s\"" % top_level_commands.join(' ') %>
14
+ else
15
+ opts=<%= "\"%s\"" % commands.map{ |c| c.first }.delete_if{ |s| s.include? ' ' }.sort.join(' ') %>
16
+ fi
11
17
  else
12
18
  prev="${COMP_WORDS[@]:0:COMP_CWORD}"
13
19
  SAVE_IFS=$IFS
14
20
  IFS=" "
15
21
  case "${prev[*]}" in
16
- <%- for name, data in @commands %>
22
+ <%- for name, data in commands %>
17
23
  <%= "\"rhc %s\")" % name %>
18
24
  if [[ "$cur" == -* ]]; then
19
25
  opts=<%= "\"%s\"" % data[:switches].join(" ") %>
@@ -92,7 +92,7 @@ module RHC
92
92
  carts = cartridges.map{ |c| [c.name, c.display_name || ''] }.sort{ |a,b| a[1].downcase <=> b[1].downcase }
93
93
  carts.unshift ['==========', '=========']
94
94
  carts.unshift ['Short Name', 'Full name']
95
- say table(carts).join("\n")
95
+ say table(carts)
96
96
  end
97
97
  end
98
98
  end
@@ -1,12 +1,6 @@
1
1
  require 'rhc'
2
- require 'commander'
3
- require 'commander/runner'
4
- require 'commander/delegates'
5
2
  require 'rhc/commands'
6
3
 
7
- include Commander::UI
8
- include Commander::UI::AskForClass
9
-
10
4
  module RHC
11
5
  #
12
6
  # Run and execute a command line session with the RHC tools.
@@ -21,7 +15,7 @@ module RHC
21
15
 
22
16
  def self.set_terminal
23
17
  $terminal.wrap_at = HighLine::SystemExtensions.terminal_size.first rescue 80 if $stdin.tty?
24
- $terminal.page_at = :auto if $stdin.tty? and $stdout.tty?
18
+ #$terminal.page_at = :auto if $stdin.tty? and $stdout.tty?
25
19
  # FIXME: ANSI terminals are not default on windows but we may just be
26
20
  # hitting a bug in highline if windows does support another method.
27
21
  # This is a safe fix for now but needs more research.
@@ -35,7 +35,7 @@ module RHC
35
35
  if (@args & HELP_OPTIONS).present?
36
36
  args = (@args -= HELP_OPTIONS)
37
37
  args.shift if args.first == 'help' && !command_exists?(args.join(' '))
38
- exit run_help(args, nil)
38
+ exit run_help(args)
39
39
  end
40
40
  end
41
41
 
@@ -69,14 +69,8 @@ module RHC
69
69
  begin
70
70
  run_active_command
71
71
  rescue InvalidCommandError => e
72
- if provided_arguments.empty?
73
- return RHC::Wizard.new.run unless RHC::Wizard.has_configuration?
74
- say RHC::HelpFormatter.new(self).render
75
- else
76
- RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
77
- say "See '#{program :name} help' for a list of valid commands."
78
- end
79
- 1
72
+ return RHC::Wizard.new.run unless RHC::Wizard.has_configuration? || provided_arguments.present?
73
+ run_help(provided_arguments)
80
74
  rescue \
81
75
  OptionParser::InvalidOption => e
82
76
  RHC::Helpers.error e.message
@@ -107,7 +101,7 @@ module RHC
107
101
  end
108
102
 
109
103
  def provided_arguments
110
- @args[0, @args.find_index { |arg| arg.start_with?('-') } || @args.length]
104
+ @args[0, @args.find_index { |arg| arg != '--' and arg.start_with?('-') } || @args.length]
111
105
  end
112
106
 
113
107
  def global_option(*args, &block)
@@ -122,6 +116,7 @@ module RHC
122
116
  c.description = "Display all global options and information about configuration"
123
117
  c.when_called do |args, options|
124
118
  say help_formatter.render_options self
119
+ 0
125
120
  end
126
121
  end
127
122
  command :help do |c|
@@ -131,17 +126,51 @@ module RHC
131
126
  end
132
127
  end
133
128
 
134
- def run_help(args, options)
135
- cmd = (1..args.length).reverse_each.map{ |n| args[0,n].join(' ') }.find{ |cmd| command_exists?(cmd) }
129
+ def run_help(args=[], options=nil)
130
+ args.delete_if{ |a| a.start_with? '-' }
131
+ unless args[0] == 'commands'
132
+ variations = (1..args.length).reverse_each.map{ |n| args[0,n].join('-') }
133
+ cmd = variations.first(1).find{ |cmd| command_exists?(cmd) }
134
+ end
136
135
 
137
136
  if args.empty?
138
137
  say help_formatter.render
139
138
  0
140
- elsif cmd.nil?
141
- RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
142
- say "See '#{program :name} help' for a list of valid commands."
143
- 1
144
139
  else
140
+ if cmd.nil?
141
+ matches = (variations || ['']).inject(nil) do |candidates, term|
142
+ prefix = commands.keys.select{ |n| n.downcase.start_with? term.downcase }
143
+ inline = commands.keys.select{ |n| n.downcase.include? term.downcase }
144
+ break [term, prefix, inline - prefix] unless prefix.empty? && inline.empty?
145
+ end
146
+
147
+ unless matches
148
+ RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
149
+ say "See '#{program :name} help' for a list of valid commands."
150
+ return 1
151
+ end
152
+
153
+ candidates = (matches[1] + matches[2]).map{ |n| commands[n] }.uniq.sort_by{ |c| c.name }.reverse
154
+ if candidates.length == 1
155
+ cmd = candidates.first.name
156
+ else
157
+ RHC::Helpers.pager
158
+ RHC::Helpers.say matches[0] != '' ? "Showing commands matching '#{matches[0]}'" : "Showing all commands"
159
+ candidates.reverse.each do |command|
160
+ RHC::Helpers.paragraph do
161
+ aliases = (commands.map{ |(k,v)| k if command == v }.compact - [command.name]).map{ |s| "'#{s}'"}
162
+ aliases[0] = "(also #{aliases[0]}" if aliases[0]
163
+ aliases[-1] << ')' if aliases[0]
164
+
165
+ RHC::Helpers.header [RHC::Helpers.color(command.name, :cyan), *aliases.join(', ')]
166
+ say command.description || command.summary
167
+ end
168
+ end
169
+ return 1
170
+ end
171
+ end
172
+
173
+ RHC::Helpers.pager
145
174
  command = command(cmd)
146
175
  help_bindings = CommandHelpBindings.new command, commands, self
147
176
  say help_formatter.render_command help_bindings
@@ -5,10 +5,19 @@ require 'commander/command'
5
5
  # to avoid conflicts and side effects of similar short switches
6
6
  module Commander
7
7
  class Command
8
- attr_accessor :default_action
8
+ attr_accessor :default_action, :root, :info
9
9
  def default_action?
10
10
  default_action.present?
11
11
  end
12
+ def root?
13
+ root.present?
14
+ end
15
+
16
+ def deprecated(as_alias=nil)
17
+ return false unless info
18
+ return info[:deprecated] if info[:deprecated]
19
+ info[:aliases].select{ |a| ['-',' '].map{ |s| Array(a[:action]).join(s) }.include?(as_alias) }.map{ |a| a[:deprecated] }.first if as_alias
20
+ end
12
21
 
13
22
  def parse_options_and_call_procs *args
14
23
  runner = Commander::Runner.instance
@@ -25,7 +34,11 @@ module Commander
25
34
  opts
26
35
  end
27
36
 
28
- remaining = opts.parse! args
37
+ # Separate option lists with '--'
38
+ remaining = args.split('--').map{ |a| opts.parse!(a) }.inject([]) do |arr, sub|
39
+ arr << '--' unless arr.empty?
40
+ arr.concat(sub)
41
+ end
29
42
 
30
43
  _, config_path = proxy_options.find{ |arg| arg[0] == :config }
31
44
  clean, _ = proxy_options.find{ |arg| arg[0] == :clean }
@@ -134,12 +147,12 @@ module RHC
134
147
  global_options << [args.freeze, block]
135
148
  end
136
149
 
137
- def self.deprecated?
138
- command_name = Commander::Runner.instance.command_name_from_args
139
- command = Commander::Runner.instance.active_command
150
+ def self.deprecated!
151
+ instance = Commander::Runner.instance
152
+ command_name = instance.command_name_from_args
153
+ command = instance.active_command
140
154
 
141
- new_cmd = deprecated[command_name.to_sym]
142
- if new_cmd
155
+ if new_cmd = command.deprecated(command_name)
143
156
  new_cmd = "rhc #{command.name}" if new_cmd == true
144
157
  RHC::Helpers.deprecated_command new_cmd
145
158
  end
@@ -152,9 +165,7 @@ module RHC
152
165
  config.has_local_config? or
153
166
  config.has_opts_config?)
154
167
 
155
- RHC::Helpers.warn(
156
- "You have not yet configured the OpenShift client tools. Please run 'rhc setup'.",
157
- :stderr => true)
168
+ $stderr.puts RHC::Helpers.color("You have not yet configured the OpenShift client tools. Please run 'rhc setup'.", :yellow)
158
169
  end
159
170
  end
160
171
 
@@ -166,47 +177,48 @@ module RHC
166
177
  option.merge!(opts)
167
178
  end
168
179
  commands.each_pair do |name, opts|
180
+ name = Array(name)
181
+ names = [name.reverse.join('-'), name.join(' ')] if name.length > 1
182
+ name = name.join('-')
183
+
169
184
  instance.command name do |c|
170
185
  c.description = opts[:description]
171
186
  c.summary = opts[:summary]
172
187
  c.syntax = opts[:syntax]
173
188
  c.default_action = opts[:default]
174
189
 
175
- (options_metadata = opts[:options] || []).each do |o|
190
+ c.info = opts
191
+
192
+ (options_metadata = Array(opts[:options])).each do |o|
176
193
  option_data = [o[:switches], o[:description]].flatten(1)
177
194
  c.option *option_data
178
195
  o[:arg] = Commander::Runner.switch_to_sym(Array(o[:switches]).last)
179
196
  end
180
197
 
181
- deprecated[name.to_sym] = opts[:deprecated] unless opts[:deprecated].nil?
182
-
183
- args_metadata = opts[:args] || []
184
- args_metadata.each do |arg_meta|
185
- arg_switches = arg_meta[:switches]
186
- unless arg_switches.nil? or arg_switches.empty?
187
- arg_switches << arg_meta[:description]
188
- c.option *arg_switches
198
+ (args_metadata = Array(opts[:args])).each do |meta|
199
+ switches = meta[:switches]
200
+ unless switches.nil? or switches.empty?
201
+ switches << meta[:description]
202
+ c.option *switches
189
203
  end
190
204
  end
191
205
 
192
- unless opts[:aliases].nil?
193
- opts[:aliases].each do |a|
194
- alias_cmd = a[:action]
195
-
196
- unless a[:root_command]
197
- # prepend the current resource
198
- alias_components = name.split(" ")
199
- alias_components[-1] = a[:action]
200
- alias_cmd = alias_components.join(' ').to_sym
201
- end
202
-
203
- deprecated[alias_cmd] = true if a[:deprecated]
204
- instance.alias_command "#{alias_cmd}", :"#{name}"
206
+ Array(opts[:aliases]).each do |a|
207
+ action = Array(a[:action])
208
+ [' ', '-'].each do |s|
209
+ cmd = action.join(s)
210
+ instance.alias_command cmd, name
205
211
  end
206
212
  end
207
213
 
214
+ if names
215
+ names.each{ |alt| instance.alias_command alt, name }
216
+ else
217
+ c.root = true
218
+ end
219
+
208
220
  c.when_called do |args, options|
209
- deprecated?
221
+ deprecated!
210
222
 
211
223
  config = c.instance_variable_get(:@config)
212
224
 
@@ -232,7 +244,7 @@ module RHC
232
244
  Commander::Runner.instance.options.each do |opt|
233
245
  if opt[:context]
234
246
  arg = Commander::Runner.switch_to_sym(opt[:switches].last)
235
- options[arg] ||= lambda{ cmd.send(opt[:context]) }
247
+ options.__hash__[arg] ||= lambda{ cmd.send(opt[:context]) }
236
248
  end
237
249
  end
238
250
 
@@ -258,32 +270,43 @@ module RHC
258
270
  end
259
271
  raise ArgumentError.new("Missing required option '#{arg}'.") if option_meta[:required] && options[arg].nil?
260
272
  end
261
- # process args
262
- arg_slots = [].fill(nil, 0, args_metadata.length)
263
- fill_args = args.reverse
264
- args_metadata.each_with_index do |arg_meta, i|
265
- # check options
266
- option = arg_meta[:option_symbol]
267
- context_helper = arg_meta[:context_helper]
273
+
274
+ available = args.dup
275
+ slots = Array.new(args_metadata.length)
276
+ args_metadata.each_with_index do |arg, i|
277
+ option = arg[:option_symbol]
278
+ context_helper = arg[:context_helper]
268
279
 
269
280
  value = options.__hash__[option] if option
270
- value = fill_args.pop if value.nil?
281
+
282
+ if value.nil?
283
+ value =
284
+ if arg[:arg_type] == :list
285
+ all = []
286
+ while available.first && available.first != '--'
287
+ all << available.shift
288
+ end
289
+ available.shift if available.first == '--'
290
+ all
291
+ else
292
+ available.shift
293
+ end
294
+ end
295
+
271
296
  value = cmd.send(context_helper) if value.nil? and context_helper
272
297
 
273
- if arg_meta[:arg_type] == :list
274
- fill_args.push(value) unless value.nil?
275
- value = fill_args.reverse
276
- fill_args = []
277
- elsif value.nil?
278
- raise ArgumentError.new("Missing required argument '#{arg_meta[:name]}'.") if fill_args.empty?
298
+ if value.nil?
299
+ raise ArgumentError, "Missing required argument '#{arg[:name]}'." unless arg[:optional]
300
+ break if available.empty?
301
+ else
302
+ slots[i] = value
303
+ options.__hash__[option] = value if option
279
304
  end
280
- arg_slots[i] = value
281
- options.__hash__[option] = value if option
282
305
  end
283
306
 
284
- raise ArgumentError.new("Too many arguments passed in: #{fill_args.reverse.join(" ")}") unless fill_args.empty?
307
+ raise ArgumentError, "Too many arguments passed in: #{available.reverse.join(" ")}" unless available.empty?
285
308
 
286
- arg_slots
309
+ slots
287
310
  end
288
311
 
289
312
  def self.commands
@@ -292,8 +315,5 @@ module RHC
292
315
  def self.global_options
293
316
  @options ||= []
294
317
  end
295
- def self.deprecated
296
- @deprecated ||= {}
297
- end
298
318
  end
299
319
  end