rudy 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +53 -3
- data/README.rdoc +9 -5
- data/bin/rudy +115 -292
- data/bin/rudy-ec2 +107 -0
- data/lib/console.rb +322 -278
- data/lib/rudy.rb +78 -55
- data/lib/rudy/aws/ec2.rb +63 -5
- data/lib/rudy/command/addresses.rb +18 -13
- data/lib/rudy/command/backups.rb +175 -0
- data/lib/rudy/command/base.rb +664 -146
- data/lib/rudy/command/config.rb +77 -0
- data/lib/rudy/command/deploy.rb +12 -0
- data/lib/rudy/command/disks.rb +165 -195
- data/lib/rudy/command/environment.rb +42 -64
- data/lib/rudy/command/groups.rb +21 -19
- data/lib/rudy/command/images.rb +34 -19
- data/lib/rudy/command/instances.rb +46 -92
- data/lib/rudy/command/machines.rb +161 -0
- data/lib/rudy/command/metadata.rb +14 -30
- data/lib/rudy/command/release.rb +174 -0
- data/lib/rudy/command/volumes.rb +26 -10
- data/lib/rudy/config.rb +93 -0
- data/lib/rudy/metadata/backup.rb +1 -1
- data/lib/rudy/metadata/disk.rb +15 -50
- data/lib/rudy/scm/svn.rb +32 -21
- data/lib/rudy/utils.rb +2 -3
- data/lib/storable.rb +4 -0
- data/lib/tryouts.rb +40 -0
- data/rudy.gemspec +25 -9
- data/support/mailtest +40 -0
- data/support/rudy-ec2-startup +41 -15
- data/tryouts/console_tryout.rb +91 -0
- metadata +86 -11
- data/lib/drydock.rb +0 -524
- data/lib/rudy/command/stage.rb +0 -45
- data/lib/rudy/metadata/config.rb +0 -8
- data/lib/rudy/metadata/environment.rb +0 -0
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rudy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,11 +9,80 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-03-12 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: drydock
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: caesars
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: net-ssh
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: net-scp
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: net-ssh-gateway
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: net-ssh-multi
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: highline
|
77
|
+
type: :runtime
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
description: Your friend in staging and deploying with EC2.
|
17
86
|
email: delano@solutious.com
|
18
87
|
executables:
|
19
88
|
- rudy
|
@@ -28,36 +97,42 @@ files:
|
|
28
97
|
- README.rdoc
|
29
98
|
- Rakefile
|
30
99
|
- bin/rudy
|
100
|
+
- bin/rudy-ec2
|
31
101
|
- lib/aws_sdb.rb
|
32
102
|
- lib/aws_sdb/error.rb
|
33
103
|
- lib/aws_sdb/service.rb
|
34
104
|
- lib/console.rb
|
35
|
-
- lib/drydock.rb
|
36
105
|
- lib/rudy.rb
|
37
106
|
- lib/rudy/aws.rb
|
38
107
|
- lib/rudy/aws/ec2.rb
|
39
108
|
- lib/rudy/aws/s3.rb
|
40
109
|
- lib/rudy/aws/simpledb.rb
|
41
110
|
- lib/rudy/command/addresses.rb
|
111
|
+
- lib/rudy/command/backups.rb
|
42
112
|
- lib/rudy/command/base.rb
|
113
|
+
- lib/rudy/command/config.rb
|
114
|
+
- lib/rudy/command/deploy.rb
|
43
115
|
- lib/rudy/command/disks.rb
|
44
116
|
- lib/rudy/command/environment.rb
|
45
117
|
- lib/rudy/command/groups.rb
|
46
118
|
- lib/rudy/command/images.rb
|
47
119
|
- lib/rudy/command/instances.rb
|
120
|
+
- lib/rudy/command/machines.rb
|
48
121
|
- lib/rudy/command/metadata.rb
|
49
|
-
- lib/rudy/command/
|
122
|
+
- lib/rudy/command/release.rb
|
50
123
|
- lib/rudy/command/volumes.rb
|
124
|
+
- lib/rudy/config.rb
|
51
125
|
- lib/rudy/metadata.rb
|
52
126
|
- lib/rudy/metadata/backup.rb
|
53
|
-
- lib/rudy/metadata/config.rb
|
54
127
|
- lib/rudy/metadata/disk.rb
|
55
|
-
- lib/rudy/metadata/environment.rb
|
56
128
|
- lib/rudy/scm/svn.rb
|
57
129
|
- lib/rudy/utils.rb
|
58
130
|
- lib/storable.rb
|
131
|
+
- lib/tryouts.rb
|
59
132
|
- rudy.gemspec
|
133
|
+
- support/mailtest
|
60
134
|
- support/rudy-ec2-startup
|
135
|
+
- tryouts/console_tryout.rb
|
61
136
|
has_rdoc: true
|
62
137
|
homepage: http://github.com/solutious/rudy
|
63
138
|
post_install_message:
|
@@ -65,7 +140,7 @@ rdoc_options:
|
|
65
140
|
- --line-numbers
|
66
141
|
- --inline-source
|
67
142
|
- --title
|
68
|
-
- "Rudy: Your friend in staging and deploying with EC2"
|
143
|
+
- "Rudy: Your friend in staging and deploying with EC2."
|
69
144
|
- --main
|
70
145
|
- README.rdoc
|
71
146
|
require_paths:
|
@@ -88,6 +163,6 @@ rubyforge_project: rudy
|
|
88
163
|
rubygems_version: 1.2.0
|
89
164
|
signing_key:
|
90
165
|
specification_version: 2
|
91
|
-
summary:
|
166
|
+
summary: Your friend in staging and deploying with EC2.
|
92
167
|
test_files: []
|
93
168
|
|
data/lib/drydock.rb
DELETED
@@ -1,524 +0,0 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
require 'ostruct'
|
3
|
-
|
4
|
-
|
5
|
-
module Drydock
|
6
|
-
# The base class for all command objects. There is an instance of this class
|
7
|
-
# for every command defined. Global and command-specific options are added
|
8
|
-
# as attributes to this class dynamically.
|
9
|
-
#
|
10
|
-
# i.e. "example -v date -f yaml"
|
11
|
-
#
|
12
|
-
# global_option :v, :verbose, "I want mooooore!"
|
13
|
-
# option :f, :format, String, "Long date format"
|
14
|
-
# command :date do |obj|
|
15
|
-
# puts obj.verbose #=> true
|
16
|
-
# puts obj.format #=> "yaml"
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# You can inherit from this class to create your own: EatFood < Drydock::Command.
|
20
|
-
# And then specific your class in the command definition:
|
21
|
-
#
|
22
|
-
# command :eat => EatFood do |obj|; ...; end
|
23
|
-
#
|
24
|
-
class Command
|
25
|
-
attr_reader :cmd, :alias
|
26
|
-
attr_accessor :verbose
|
27
|
-
|
28
|
-
# The default constructor sets the short name of the command
|
29
|
-
# and stores a reference to the block (if supplied).
|
30
|
-
# You don't need to override this method to add functionality
|
31
|
-
# to your custom Command classes. Define an +init+ method instead.
|
32
|
-
# It will be called just before the block is executed.
|
33
|
-
# +cmd+ is the short name of this command.
|
34
|
-
# +b+ is the block associated to this command.
|
35
|
-
def initialize(cmd, &b)
|
36
|
-
@cmd = (cmd.kind_of?(Symbol)) ? cmd : cmd.to_sym
|
37
|
-
@b = b
|
38
|
-
@verbose = 0
|
39
|
-
end
|
40
|
-
|
41
|
-
# Execute the block.
|
42
|
-
#
|
43
|
-
# Calls self.init before calling the block. Implement this method when
|
44
|
-
#
|
45
|
-
# +cmd_str+ is the short name used to evoke this command. It will equal @cmd
|
46
|
-
# unless an alias was used used to evoke this command.
|
47
|
-
# +argv+ an array of unnamed arguments. If ignore :options was declared this
|
48
|
-
# will contain the arguments exactly as they were defined on the command-line.
|
49
|
-
# +stdin+ contains the output of stdin do; ...; end otherwise it's a STDIN IO handle.
|
50
|
-
# +global_options+ a hash of the global options specified on the command-line
|
51
|
-
# +options+ a hash of the command-specific options specific on the command-line.
|
52
|
-
def call(cmd_str=nil, argv=[], stdin=[], global_options={}, options={})
|
53
|
-
@alias = cmd_str.nil? ? @cmd : cmd_str
|
54
|
-
global_options.merge(options).each_pair do |n,v|
|
55
|
-
self.send("#{n}=", v)
|
56
|
-
end
|
57
|
-
|
58
|
-
self.init if respond_to? :init
|
59
|
-
|
60
|
-
block_args = [self, argv, stdin] # TODO: review order
|
61
|
-
@b.call(*block_args[0..(@b.arity-1)]) # send only as many args as defined
|
62
|
-
end
|
63
|
-
|
64
|
-
# The name of the command
|
65
|
-
def to_s
|
66
|
-
@cmd.to_s
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
module Drydock
|
72
|
-
class UnknownCommand < RuntimeError
|
73
|
-
attr_reader :name
|
74
|
-
def initialize(name)
|
75
|
-
@name = name || :unknown
|
76
|
-
end
|
77
|
-
def message
|
78
|
-
"Unknown command: #{@name}"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
class NoCommandsDefined < RuntimeError
|
82
|
-
def message
|
83
|
-
"No commands defined"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
class InvalidArgument < RuntimeError
|
87
|
-
attr_accessor :args
|
88
|
-
def initialize(args)
|
89
|
-
@args = args || []
|
90
|
-
end
|
91
|
-
def message
|
92
|
-
"Unknown option: #{@args.join(", ")}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
class MissingArgument < InvalidArgument
|
96
|
-
def message
|
97
|
-
"Option requires a value: #{@args.join(", ")}"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Drydock is a DSL for command-line apps.
|
103
|
-
# See bin/example for usage examples.
|
104
|
-
module Drydock
|
105
|
-
extend self
|
106
|
-
|
107
|
-
VERSION = 0.3
|
108
|
-
|
109
|
-
private
|
110
|
-
# Stolen from Sinatra!
|
111
|
-
#def delegate(*args)
|
112
|
-
# args.each do |m|
|
113
|
-
# eval(<<-end_eval, binding, "(__Drydock__)", __LINE__)
|
114
|
-
# def #{m}(*args, &b)
|
115
|
-
# Drydock.#{m}(*args, &b)
|
116
|
-
# end
|
117
|
-
# end_eval
|
118
|
-
# end
|
119
|
-
#end
|
120
|
-
#
|
121
|
-
#delegate :before, :after, :alias_command, :desc
|
122
|
-
#delegate :global_option, :global_usage, :usage, :commands, :command
|
123
|
-
#delegate :debug, :option, :stdin, :default, :ignore, :command_alias
|
124
|
-
|
125
|
-
@@debug = false
|
126
|
-
@@has_run = false
|
127
|
-
@@run = true
|
128
|
-
@@default_command = nil
|
129
|
-
|
130
|
-
public
|
131
|
-
# Enable or disable debug output.
|
132
|
-
#
|
133
|
-
# debug :on
|
134
|
-
# debug :off
|
135
|
-
#
|
136
|
-
# Calling without :on or :off will toggle the value.
|
137
|
-
#
|
138
|
-
def debug(toggle=false)
|
139
|
-
if toggle.is_a? Symbol
|
140
|
-
@@debug = true if toggle == :on
|
141
|
-
@@debug = false if toggle == :off
|
142
|
-
else
|
143
|
-
@@debug = (!@@debug)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
# Returns true if debug output is enabled.
|
147
|
-
def debug?
|
148
|
-
@@debug
|
149
|
-
end
|
150
|
-
|
151
|
-
# Define a default command.
|
152
|
-
#
|
153
|
-
# default :task
|
154
|
-
#
|
155
|
-
def default(cmd)
|
156
|
-
@@default_command = canonize(cmd)
|
157
|
-
end
|
158
|
-
|
159
|
-
# Provide a description for a method
|
160
|
-
def desc(txt)
|
161
|
-
@@command_descriptions ||= []
|
162
|
-
@@command_descriptions << txt
|
163
|
-
end
|
164
|
-
|
165
|
-
# Define a block for processing STDIN before the command is called.
|
166
|
-
# The command block receives the return value of this block in a named argument:
|
167
|
-
#
|
168
|
-
# command :task do |obj, argv, stdin|; ...; end
|
169
|
-
#
|
170
|
-
# If a stdin block isn't defined, +stdin+ above will be the STDIN IO handle.
|
171
|
-
def stdin(&b)
|
172
|
-
@@stdin_block = b
|
173
|
-
end
|
174
|
-
|
175
|
-
# Define a block to be called before the command.
|
176
|
-
# This is useful for opening database connections, etc...
|
177
|
-
def before(&b)
|
178
|
-
@@before_block = b
|
179
|
-
end
|
180
|
-
|
181
|
-
# Define a block to be called after the command.
|
182
|
-
# This is useful for stopping, closing, etc... the stuff in the before block.
|
183
|
-
def after(&b)
|
184
|
-
@@after_block = b
|
185
|
-
end
|
186
|
-
|
187
|
-
# Define the default global usage banner. This is displayed
|
188
|
-
# with "script -h".
|
189
|
-
def global_usage(msg)
|
190
|
-
@@global_options ||= OpenStruct.new
|
191
|
-
global_opts_parser.banner = "USAGE: #{msg}"
|
192
|
-
end
|
193
|
-
|
194
|
-
# Define a command-specific usage banner. This is displayed
|
195
|
-
# with "script command -h"
|
196
|
-
def usage(msg)
|
197
|
-
get_current_option_parser.banner = "USAGE: #{msg}"
|
198
|
-
end
|
199
|
-
|
200
|
-
# Grab the options parser for the current command or create it if it doesn't exist.
|
201
|
-
def get_current_option_parser
|
202
|
-
@@command_opts_parser ||= []
|
203
|
-
@@command_index ||= 0
|
204
|
-
(@@command_opts_parser[@@command_index] ||= OptionParser.new)
|
205
|
-
end
|
206
|
-
|
207
|
-
# Tell the Drydock parser to ignore something.
|
208
|
-
# Drydock will currently only listen to you if you tell it to "ignore :options",
|
209
|
-
# otherwise it will ignore you!
|
210
|
-
#
|
211
|
-
# +what+ the thing to ignore. When it equals :options Drydock will not parse
|
212
|
-
# the command-specific arguments. It will pass the arguments directly to the
|
213
|
-
# Command object. This is useful when you want to parse the arguments in some a way
|
214
|
-
# that's too crazy, dangerous for Drydock to handle automatically.
|
215
|
-
def ignore(what=:nothing)
|
216
|
-
@@command_opts_parser[@@command_index] = :ignore if what == :options || what == :all
|
217
|
-
end
|
218
|
-
|
219
|
-
# Define a global option. See +option+ for more info.
|
220
|
-
def global_option(*args, &b)
|
221
|
-
args.unshift(global_opts_parser)
|
222
|
-
global_option_names << option_parser(args, &b)
|
223
|
-
end
|
224
|
-
|
225
|
-
# Define a command-specific option.
|
226
|
-
#
|
227
|
-
# +args+ is passed directly to OptionParser.on so it can contain anything
|
228
|
-
# that's valid to that method. Some examples:
|
229
|
-
# [:h, :help, "Displays this message"]
|
230
|
-
# [:m, :max, Integer, "Maximum threshold"]
|
231
|
-
# ['-l x,y,z', '--lang=x,y,z', Array, "Requested languages"]
|
232
|
-
# If a class is included, it will tell OptionParser to expect a value
|
233
|
-
# otherwise it assumes a boolean value.
|
234
|
-
#
|
235
|
-
# All calls to +option+ must come before the command they're associated
|
236
|
-
# to. Example:
|
237
|
-
#
|
238
|
-
# option :l, :longname, String, "Description" do; ...; end
|
239
|
-
# command :task do |obj|; ...; end
|
240
|
-
#
|
241
|
-
# When calling your script with a specific command-line option, the value
|
242
|
-
# is available via obj.longname inside the command block.
|
243
|
-
#
|
244
|
-
def option(*args, &b)
|
245
|
-
args.unshift(get_current_option_parser)
|
246
|
-
current_command_option_names << option_parser(args, &b)
|
247
|
-
end
|
248
|
-
|
249
|
-
# Define a command.
|
250
|
-
#
|
251
|
-
# command :task do
|
252
|
-
# ...
|
253
|
-
# end
|
254
|
-
#
|
255
|
-
# A custom command class can be specified using Hash syntax. The class
|
256
|
-
# must inherit from Drydock::Command (class CustomeClass < Drydock::Command)
|
257
|
-
#
|
258
|
-
# command :task => CustomCommand do
|
259
|
-
# ...
|
260
|
-
# end
|
261
|
-
#
|
262
|
-
def command(*cmds, &b)
|
263
|
-
@@command_index ||= 0
|
264
|
-
@@command_opts_parser ||= []
|
265
|
-
@@command_option_names ||= []
|
266
|
-
cmds.each do |cmd|
|
267
|
-
if cmd.is_a? Hash
|
268
|
-
c = cmd.values.first.new(cmd.keys.first, &b)
|
269
|
-
else
|
270
|
-
c = Drydock::Command.new(cmd, &b)
|
271
|
-
end
|
272
|
-
commands[c.cmd] = c
|
273
|
-
command_index_map[c.cmd] = @@command_index
|
274
|
-
@@command_index += 1
|
275
|
-
end
|
276
|
-
|
277
|
-
end
|
278
|
-
|
279
|
-
# Used to create an alias to a defined command.
|
280
|
-
# Here's an example:
|
281
|
-
#
|
282
|
-
# command :task do; ...; end
|
283
|
-
# alias_command :pointer, :task
|
284
|
-
#
|
285
|
-
# Either name can be used on the command-line:
|
286
|
-
#
|
287
|
-
# $ script task [options]
|
288
|
-
# $ script pointer [options]
|
289
|
-
#
|
290
|
-
# Inside of the command definition, you have access to the
|
291
|
-
# command name that was used via obj.alias.
|
292
|
-
def alias_command(aliaz, cmd)
|
293
|
-
return unless commands.has_key? cmd
|
294
|
-
commands[canonize(aliaz)] = commands[cmd]
|
295
|
-
end
|
296
|
-
|
297
|
-
# Identical to +alias_command+ with reversed arguments.
|
298
|
-
# For whatever reason I forget the order so Drydock supports both.
|
299
|
-
# Tip: the argument order matches the method name.
|
300
|
-
def command_alias(cmd, aliaz)
|
301
|
-
return unless commands.has_key? cmd
|
302
|
-
puts "#{canonize(aliaz)} to #{commands[cmd]}"
|
303
|
-
commands[canonize(aliaz)] = commands[cmd]
|
304
|
-
end
|
305
|
-
|
306
|
-
# An array of the currently defined Drydock::Command objects
|
307
|
-
def commands
|
308
|
-
@@commands ||= {}
|
309
|
-
@@commands
|
310
|
-
end
|
311
|
-
|
312
|
-
# An array of the currently defined commands names
|
313
|
-
def command_names
|
314
|
-
@@commands ||= {}
|
315
|
-
@@commands.keys.collect { |cmd| decanonize(cmd); }
|
316
|
-
end
|
317
|
-
|
318
|
-
# Returns true if automatic execution is enabled.
|
319
|
-
def run?
|
320
|
-
@@run
|
321
|
-
end
|
322
|
-
|
323
|
-
# Disable automatic execution (enabled by default)
|
324
|
-
#
|
325
|
-
# Drydock.run = false
|
326
|
-
def run=(v)
|
327
|
-
@@run = (v == true) ? true : false
|
328
|
-
end
|
329
|
-
|
330
|
-
# Return true if a command has been executed.
|
331
|
-
def has_run?
|
332
|
-
@@has_run
|
333
|
-
end
|
334
|
-
|
335
|
-
# Execute the given command.
|
336
|
-
# By default, Drydock automatically executes itself and provides handlers for known errors.
|
337
|
-
# You can override this functionality by calling +Drydock.run!+ yourself. Drydock
|
338
|
-
# will only call +run!+ once.
|
339
|
-
def run!(argv=[], stdin=STDIN)
|
340
|
-
return if has_run?
|
341
|
-
@@has_run = true
|
342
|
-
raise NoCommandsDefined.new if commands.empty?
|
343
|
-
@@global_options, cmd_name, @@command_options, argv = process_arguments(argv)
|
344
|
-
|
345
|
-
cmd_name ||= default_command
|
346
|
-
|
347
|
-
raise UnknownCommand.new(cmd_name) unless command?(cmd_name)
|
348
|
-
|
349
|
-
stdin = (defined? @@stdin_block) ? @@stdin_block.call(stdin, []) : stdin
|
350
|
-
@@before_block.call if defined? @@before_block
|
351
|
-
|
352
|
-
call_command(cmd_name, argv, stdin)
|
353
|
-
|
354
|
-
@@after_block.call if defined? @@after_block
|
355
|
-
|
356
|
-
rescue OptionParser::InvalidOption => ex
|
357
|
-
raise Drydock::InvalidArgument.new(ex.args)
|
358
|
-
rescue OptionParser::MissingArgument => ex
|
359
|
-
raise Drydock::MissingArgument.new(ex.args)
|
360
|
-
end
|
361
|
-
|
362
|
-
private
|
363
|
-
|
364
|
-
# Executes the block associated to +cmd+
|
365
|
-
def call_command(cmd, argv=[], stdin=nil)
|
366
|
-
return unless command?(cmd)
|
367
|
-
get_command(cmd).call(cmd, argv, stdin, @@global_options || {}, @@command_options || {})
|
368
|
-
end
|
369
|
-
|
370
|
-
# Returns the Drydock::Command object with the name +cmd+
|
371
|
-
def get_command(cmd)
|
372
|
-
return unless command?(cmd)
|
373
|
-
@@commands[canonize(cmd)]
|
374
|
-
end
|
375
|
-
|
376
|
-
# Returns true if a command with the name +cmd+ has been defined.
|
377
|
-
def command?(cmd)
|
378
|
-
name = canonize(cmd)
|
379
|
-
(@@commands || {}).has_key? name
|
380
|
-
end
|
381
|
-
|
382
|
-
# Canonizes a string (+cmd+) to the symbol for command names
|
383
|
-
# '-' is replaced with '_'
|
384
|
-
def canonize(cmd)
|
385
|
-
return unless cmd
|
386
|
-
return cmd if cmd.kind_of?(Symbol)
|
387
|
-
cmd.to_s.tr('-', '_').to_sym
|
388
|
-
end
|
389
|
-
|
390
|
-
# Returns a string version of +cmd+, decanonized.
|
391
|
-
# Lowercase, '_' is replaced with '-'
|
392
|
-
def decanonize(cmd)
|
393
|
-
return unless cmd
|
394
|
-
cmd.to_s.tr('_', '-')
|
395
|
-
end
|
396
|
-
|
397
|
-
# Processes calls to option and global_option. Symbols are converted into
|
398
|
-
# OptionParser style strings (:h and :help become '-h' and '--help').
|
399
|
-
def option_parser(args=[], &b)
|
400
|
-
return if args.empty?
|
401
|
-
opts_parser = args.shift
|
402
|
-
|
403
|
-
arg_name = ''
|
404
|
-
symbol_switches = []
|
405
|
-
args.each_with_index do |arg, index|
|
406
|
-
if arg.is_a? Symbol
|
407
|
-
arg_name = arg.to_s if arg.to_s.size > arg_name.size
|
408
|
-
args[index] = (arg.to_s.length == 1) ? "-#{arg.to_s}" : "--#{arg.to_s}"
|
409
|
-
symbol_switches << args[index]
|
410
|
-
elsif arg.kind_of?(Class)
|
411
|
-
symbol_switches.each do |arg|
|
412
|
-
arg << "=S"
|
413
|
-
end
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
if args.size == 1
|
418
|
-
opts_parser.on(args.shift)
|
419
|
-
else
|
420
|
-
opts_parser.on(*args) do |v|
|
421
|
-
block_args = [v, opts_parser]
|
422
|
-
result = (b.nil?) ? v : b.call(*block_args[0..(b.arity-1)])
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
arg_name
|
427
|
-
end
|
428
|
-
|
429
|
-
|
430
|
-
# Split the +argv+ array into global args and command args and
|
431
|
-
# find the command name.
|
432
|
-
# i.e. ./script -H push -f (-H is a global arg, push is the command, -f is a command arg)
|
433
|
-
# returns [global_options, cmd, command_options, argv]
|
434
|
-
def process_arguments(argv=[])
|
435
|
-
global_options = command_options = {}
|
436
|
-
cmd = nil
|
437
|
-
|
438
|
-
global_options = global_opts_parser.getopts(argv)
|
439
|
-
|
440
|
-
cmd_name = (argv.empty?) ? @@default_command : argv.shift
|
441
|
-
raise UnknownCommand.new(cmd_name) unless command?(cmd_name)
|
442
|
-
|
443
|
-
cmd = get_command(cmd_name)
|
444
|
-
|
445
|
-
command_parser = @@command_opts_parser[get_command_index(cmd.cmd)]
|
446
|
-
command_options = {}
|
447
|
-
|
448
|
-
# We only need to parse the options out of the arguments when
|
449
|
-
# there are args available, there is a valid parser, and
|
450
|
-
# we weren't requested to ignore the options.
|
451
|
-
if !argv.empty? && command_parser && command_parser != :ignore
|
452
|
-
command_options = command_parser.getopts(argv)
|
453
|
-
end
|
454
|
-
|
455
|
-
# Add accessors to the Drydock::Command object
|
456
|
-
# for the global and command specific options
|
457
|
-
[global_option_names, (command_option_names[get_command_index(cmd_name)] || [])].flatten.each do |n|
|
458
|
-
unless cmd.respond_to?(n)
|
459
|
-
cmd.class.send(:define_method, n) do
|
460
|
-
instance_variable_get("@#{n}")
|
461
|
-
end
|
462
|
-
end
|
463
|
-
unless cmd.respond_to?("#{n}=")
|
464
|
-
cmd.class.send(:define_method, "#{n}=") do |val|
|
465
|
-
instance_variable_set("@#{n}", val)
|
466
|
-
end
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
[global_options, cmd_name, command_options, argv]
|
471
|
-
end
|
472
|
-
|
473
|
-
def global_option_names
|
474
|
-
@@global_option_names ||= []
|
475
|
-
end
|
476
|
-
|
477
|
-
# Grab the current list of command-specific option names. This is a list of the
|
478
|
-
# long names.
|
479
|
-
def current_command_option_names
|
480
|
-
@@command_option_names ||= []
|
481
|
-
@@command_index ||= 0
|
482
|
-
(@@command_option_names[@@command_index] ||= [])
|
483
|
-
end
|
484
|
-
|
485
|
-
def command_index_map
|
486
|
-
@@command_index_map ||= {}
|
487
|
-
end
|
488
|
-
|
489
|
-
def get_command_index(cmd)
|
490
|
-
command_index_map[canonize(cmd)] || -1
|
491
|
-
end
|
492
|
-
|
493
|
-
def command_option_names
|
494
|
-
@@command_option_names ||= []
|
495
|
-
end
|
496
|
-
|
497
|
-
def global_opts_parser
|
498
|
-
@@global_opts_parser ||= OptionParser.new
|
499
|
-
end
|
500
|
-
|
501
|
-
def default_command
|
502
|
-
@@default_command ||= nil
|
503
|
-
end
|
504
|
-
|
505
|
-
end
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
trap ("SIGINT") do
|
510
|
-
puts "#{$/}Exiting..."
|
511
|
-
exit 1
|
512
|
-
end
|
513
|
-
|
514
|
-
|
515
|
-
at_exit {
|
516
|
-
begin
|
517
|
-
Drydock.run!(ARGV, STDIN) if Drydock.run? && !Drydock.has_run?
|
518
|
-
rescue => ex
|
519
|
-
STDERR.puts "ERROR: #{ex.message}"
|
520
|
-
STDERR.puts ex.backtrace if Drydock.debug?
|
521
|
-
end
|
522
|
-
}
|
523
|
-
|
524
|
-
|