engineyard 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/lib/engineyard/cli.rb +11 -2
  2. data/lib/engineyard/model/environment.rb +36 -3
  3. data/lib/engineyard/model/instance.rb +1 -1
  4. data/lib/engineyard/thor.rb +50 -68
  5. data/lib/engineyard/version.rb +1 -1
  6. data/spec/ey/deploy_spec.rb +66 -0
  7. metadata +23 -36
  8. data/lib/engineyard/vendor/thor.rb +0 -270
  9. data/lib/engineyard/vendor/thor/actions.rb +0 -297
  10. data/lib/engineyard/vendor/thor/actions/create_file.rb +0 -105
  11. data/lib/engineyard/vendor/thor/actions/directory.rb +0 -93
  12. data/lib/engineyard/vendor/thor/actions/empty_directory.rb +0 -134
  13. data/lib/engineyard/vendor/thor/actions/file_manipulation.rb +0 -229
  14. data/lib/engineyard/vendor/thor/actions/inject_into_file.rb +0 -104
  15. data/lib/engineyard/vendor/thor/base.rb +0 -540
  16. data/lib/engineyard/vendor/thor/core_ext/file_binary_read.rb +0 -9
  17. data/lib/engineyard/vendor/thor/core_ext/hash_with_indifferent_access.rb +0 -75
  18. data/lib/engineyard/vendor/thor/core_ext/ordered_hash.rb +0 -100
  19. data/lib/engineyard/vendor/thor/error.rb +0 -30
  20. data/lib/engineyard/vendor/thor/group.rb +0 -271
  21. data/lib/engineyard/vendor/thor/invocation.rb +0 -180
  22. data/lib/engineyard/vendor/thor/parser.rb +0 -4
  23. data/lib/engineyard/vendor/thor/parser/argument.rb +0 -67
  24. data/lib/engineyard/vendor/thor/parser/arguments.rb +0 -161
  25. data/lib/engineyard/vendor/thor/parser/option.rb +0 -128
  26. data/lib/engineyard/vendor/thor/parser/options.rb +0 -164
  27. data/lib/engineyard/vendor/thor/rake_compat.rb +0 -66
  28. data/lib/engineyard/vendor/thor/runner.rb +0 -314
  29. data/lib/engineyard/vendor/thor/shell.rb +0 -83
  30. data/lib/engineyard/vendor/thor/shell/basic.rb +0 -268
  31. data/lib/engineyard/vendor/thor/shell/color.rb +0 -108
  32. data/lib/engineyard/vendor/thor/task.rb +0 -102
  33. data/lib/engineyard/vendor/thor/util.rb +0 -229
  34. data/lib/engineyard/vendor/thor/version.rb +0 -3
@@ -1,164 +0,0 @@
1
- class Thor
2
- # This is a modified version of Daniel Berger's Getopt::Long class, licensed
3
- # under Ruby's license.
4
- #
5
- class Options < Arguments #:nodoc:
6
- LONG_RE = /^(--\w+(?:-\w+)*)$/
7
- SHORT_RE = /^(-[a-z])$/i
8
- EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i
9
- SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args
10
- SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i
11
-
12
- # Receives a hash and makes it switches.
13
- def self.to_switches(options)
14
- options.map do |key, value|
15
- case value
16
- when true
17
- "--#{key}"
18
- when Array
19
- "--#{key} #{value.map{ |v| v.inspect }.join(' ')}"
20
- when Hash
21
- "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}"
22
- when nil, false
23
- ""
24
- else
25
- "--#{key} #{value.inspect}"
26
- end
27
- end.join(" ")
28
- end
29
-
30
- # Takes a hash of Thor::Option and a hash with defaults.
31
- def initialize(hash_options={}, defaults={})
32
- options = hash_options.values
33
- super(options)
34
-
35
- # Add defaults
36
- defaults.each do |key, value|
37
- @assigns[key.to_s] = value
38
- @non_assigned_required.delete(hash_options[key])
39
- end
40
-
41
- @shorts, @switches, @unknown = {}, {}, []
42
-
43
- options.each do |option|
44
- @switches[option.switch_name] = option
45
-
46
- option.aliases.each do |short|
47
- @shorts[short.to_s] ||= option.switch_name
48
- end
49
- end
50
- end
51
-
52
- def parse(args)
53
- @pile = args.dup
54
-
55
- while peek
56
- if current_is_switch?
57
- case shift
58
- when SHORT_SQ_RE
59
- unshift($1.split('').map { |f| "-#{f}" })
60
- next
61
- when EQ_RE, SHORT_NUM
62
- unshift($2)
63
- switch = $1
64
- when LONG_RE, SHORT_RE
65
- switch = $1
66
- end
67
-
68
- switch = normalize_switch(switch)
69
- option = switch_option(switch)
70
- @assigns[option.human_name] = parse_peek(switch, option)
71
- elsif current_is_switch_formatted?
72
- @unknown << shift
73
- else
74
- shift
75
- end
76
- end
77
-
78
- check_requirement!
79
-
80
- assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
81
- assigns.freeze
82
- assigns
83
- end
84
-
85
- def check_unknown!
86
- raise UnknownArgumentError, "Unknown switches '#{@unknown.join(', ')}'" unless @unknown.empty?
87
- end
88
-
89
- protected
90
-
91
- # Returns true if the current value in peek is a registered switch.
92
- #
93
- def current_is_switch?
94
- case peek
95
- when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
96
- switch?($1)
97
- when SHORT_SQ_RE
98
- $1.split('').any? { |f| switch?("-#{f}") }
99
- end
100
- end
101
-
102
- def switch_formatted?(arg)
103
- case arg
104
- when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
105
- true
106
- else
107
- false
108
- end
109
- end
110
-
111
- def current_is_switch_formatted?
112
- switch_formatted? peek
113
- end
114
-
115
- def switch?(arg)
116
- switch_option(arg) || @shorts.key?(arg)
117
- end
118
-
119
- def switch_option(arg)
120
- if match = no_or_skip?(arg)
121
- @switches[arg] || @switches["--#{match}"]
122
- else
123
- @switches[arg]
124
- end
125
- end
126
-
127
- # Check if the given argument is actually a shortcut.
128
- #
129
- def normalize_switch(arg)
130
- @shorts.key?(arg) ? @shorts[arg] : arg
131
- end
132
-
133
- # Parse boolean values which can be given as --foo=true, --foo or --no-foo.
134
- #
135
- def parse_boolean(switch)
136
- if current_is_value?
137
- ["true", "TRUE", "t", "T", true].include?(shift)
138
- else
139
- @switches.key?(switch) || !no_or_skip?(switch)
140
- end
141
- end
142
-
143
- # Parse the value at the peek analyzing if it requires an input or not.
144
- #
145
- def parse_peek(switch, option)
146
- if current_is_switch_formatted? || last?
147
- if option.boolean?
148
- # No problem for boolean types
149
- elsif no_or_skip?(switch)
150
- return nil # User set value to nil
151
- elsif option.string? && !option.required?
152
- # Return the default if there is one, else the human name
153
- return option.default || option.human_name
154
- else
155
- raise MalformattedArgumentError, "No value provided for option '#{switch}'"
156
- end
157
- end
158
-
159
- @non_assigned_required.delete(option)
160
- send(:"parse_#{option.type}", switch)
161
- end
162
-
163
- end
164
- end
@@ -1,66 +0,0 @@
1
- require 'rake'
2
-
3
- class Thor
4
- # Adds a compatibility layer to your Thor classes which allows you to use
5
- # rake package tasks. For example, to use rspec rake tasks, one can do:
6
- #
7
- # require 'thor/rake_compat'
8
- #
9
- # class Default < Thor
10
- # include Thor::RakeCompat
11
- #
12
- # Spec::Rake::SpecTask.new(:spec) do |t|
13
- # t.spec_opts = ['--options', "spec/spec.opts"]
14
- # t.spec_files = FileList['spec/**/*_spec.rb']
15
- # end
16
- # end
17
- #
18
- module RakeCompat
19
- def self.rake_classes
20
- @rake_classes ||= []
21
- end
22
-
23
- def self.included(base)
24
- # Hack. Make rakefile point to invoker, so rdoc task is generated properly.
25
- rakefile = File.basename(caller[0].match(/(.*):\d+/)[1])
26
- Rake.application.instance_variable_set(:@rakefile, rakefile)
27
- self.rake_classes << base
28
- end
29
- end
30
- end
31
-
32
- class Object #:nodoc:
33
- alias :rake_task :task
34
- alias :rake_namespace :namespace
35
-
36
- def task(*args, &block)
37
- task = rake_task(*args, &block)
38
-
39
- if klass = Thor::RakeCompat.rake_classes.last
40
- non_namespaced_name = task.name.split(':').last
41
-
42
- description = non_namespaced_name
43
- description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ')
44
- description.strip!
45
-
46
- klass.desc description, task.comment || non_namespaced_name
47
- klass.send :define_method, non_namespaced_name do |*args|
48
- Rake::Task[task.name.to_sym].invoke(*args)
49
- end
50
- end
51
-
52
- task
53
- end
54
-
55
- def namespace(name, &block)
56
- if klass = Thor::RakeCompat.rake_classes.last
57
- const_name = Thor::Util.camel_case(name.to_s).to_sym
58
- klass.const_set(const_name, Class.new(Thor))
59
- new_klass = klass.const_get(const_name)
60
- Thor::RakeCompat.rake_classes << new_klass
61
- end
62
-
63
- rake_namespace(name, &block)
64
- Thor::RakeCompat.rake_classes.pop
65
- end
66
- end
@@ -1,314 +0,0 @@
1
- require 'thor'
2
- require 'thor/group'
3
- require 'thor/core_ext/file_binary_read'
4
-
5
- require 'fileutils'
6
- require 'open-uri'
7
- require 'yaml'
8
- require 'digest/md5'
9
- require 'pathname'
10
-
11
- class Thor::Runner < Thor #:nodoc:
12
- map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
13
-
14
- # Override Thor#help so it can give information about any class and any method.
15
- #
16
- def help(meth=nil)
17
- if meth && !self.respond_to?(meth)
18
- initialize_thorfiles(meth)
19
- klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
20
- klass.start(["-h", task].compact, :shell => self.shell)
21
- else
22
- super
23
- end
24
- end
25
-
26
- # If a task is not found on Thor::Runner, method missing is invoked and
27
- # Thor::Runner is then responsable for finding the task in all classes.
28
- #
29
- def method_missing(meth, *args)
30
- meth = meth.to_s
31
- initialize_thorfiles(meth)
32
- klass, task = Thor::Util.find_class_and_task_by_namespace(meth)
33
- args.unshift(task) if task
34
- klass.start(args, :shell => self.shell)
35
- end
36
-
37
- desc "install NAME", "Install an optionally named Thor file into your system tasks"
38
- method_options :as => :string, :relative => :boolean, :force => :boolean
39
- def install(name)
40
- initialize_thorfiles
41
-
42
- # If a directory name is provided as the argument, look for a 'main.thor'
43
- # task in said directory.
44
- begin
45
- if File.directory?(File.expand_path(name))
46
- base, package = File.join(name, "main.thor"), :directory
47
- contents = open(base) {|input| input.read }
48
- else
49
- base, package = name, :file
50
- contents = open(name) {|input| input.read }
51
- end
52
- rescue OpenURI::HTTPError
53
- raise Error, "Error opening URI '#{name}'"
54
- rescue Errno::ENOENT
55
- raise Error, "Error opening file '#{name}'"
56
- end
57
-
58
- say "Your Thorfile contains:"
59
- say contents
60
-
61
- unless options["force"]
62
- return false if no?("Do you wish to continue [y/N]?")
63
- end
64
-
65
- as = options["as"] || begin
66
- first_line = contents.split("\n")[0]
67
- (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil
68
- end
69
-
70
- unless as
71
- basename = File.basename(name)
72
- as = ask("Please specify a name for #{name} in the system repository [#{basename}]:")
73
- as = basename if as.empty?
74
- end
75
-
76
- location = if options[:relative] || name =~ /^http:\/\//
77
- name
78
- else
79
- File.expand_path(name)
80
- end
81
-
82
- thor_yaml[as] = {
83
- :filename => Digest::MD5.hexdigest(name + as),
84
- :location => location,
85
- :namespaces => Thor::Util.namespaces_in_content(contents, base)
86
- }
87
-
88
- save_yaml(thor_yaml)
89
- say "Storing thor file in your system repository"
90
- destination = File.join(thor_root, thor_yaml[as][:filename])
91
-
92
- if package == :file
93
- File.open(destination, "w") { |f| f.puts contents }
94
- else
95
- FileUtils.cp_r(name, destination)
96
- end
97
-
98
- thor_yaml[as][:filename] # Indicate success
99
- end
100
-
101
- desc "version", "Show Thor version"
102
- def version
103
- require 'thor/version'
104
- say "Thor #{Thor::VERSION}"
105
- end
106
-
107
- desc "uninstall NAME", "Uninstall a named Thor module"
108
- def uninstall(name)
109
- raise Error, "Can't find module '#{name}'" unless thor_yaml[name]
110
- say "Uninstalling #{name}."
111
- FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}"))
112
-
113
- thor_yaml.delete(name)
114
- save_yaml(thor_yaml)
115
-
116
- puts "Done."
117
- end
118
-
119
- desc "update NAME", "Update a Thor file from its original location"
120
- def update(name)
121
- raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]
122
-
123
- say "Updating '#{name}' from #{thor_yaml[name][:location]}"
124
-
125
- old_filename = thor_yaml[name][:filename]
126
- self.options = self.options.merge("as" => name)
127
- filename = install(thor_yaml[name][:location])
128
-
129
- unless filename == old_filename
130
- File.delete(File.join(thor_root, old_filename))
131
- end
132
- end
133
-
134
- desc "installed", "List the installed Thor modules and tasks"
135
- method_options :internal => :boolean
136
- def installed
137
- initialize_thorfiles(nil, true)
138
- display_klasses(true, options["internal"])
139
- end
140
-
141
- desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)"
142
- method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
143
- def list(search="")
144
- initialize_thorfiles
145
-
146
- search = ".*#{search}" if options["substring"]
147
- search = /^#{search}.*/i
148
- group = options[:group] || "standard"
149
-
150
- klasses = Thor::Base.subclasses.select do |k|
151
- (options[:all] || k.group == group) && k.namespace =~ search
152
- end
153
-
154
- display_klasses(false, false, klasses)
155
- end
156
-
157
- private
158
-
159
- def self.banner(task)
160
- "thor " + task.formatted_usage(self, false)
161
- end
162
-
163
- def thor_root
164
- Thor::Util.thor_root
165
- end
166
-
167
- def thor_yaml
168
- @thor_yaml ||= begin
169
- yaml_file = File.join(thor_root, "thor.yml")
170
- yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file)
171
- yaml || {}
172
- end
173
- end
174
-
175
- # Save the yaml file. If none exists in thor root, creates one.
176
- #
177
- def save_yaml(yaml)
178
- yaml_file = File.join(thor_root, "thor.yml")
179
-
180
- unless File.exists?(yaml_file)
181
- FileUtils.mkdir_p(thor_root)
182
- yaml_file = File.join(thor_root, "thor.yml")
183
- FileUtils.touch(yaml_file)
184
- end
185
-
186
- File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
187
- end
188
-
189
- def self.exit_on_failure?
190
- true
191
- end
192
-
193
- # Load the thorfiles. If relevant_to is supplied, looks for specific files
194
- # in the thor_root instead of loading them all.
195
- #
196
- # By default, it also traverses the current path until find Thor files, as
197
- # described in thorfiles. This look up can be skipped by suppliying
198
- # skip_lookup true.
199
- #
200
- def initialize_thorfiles(relevant_to=nil, skip_lookup=false)
201
- thorfiles(relevant_to, skip_lookup).each do |f|
202
- Thor::Util.load_thorfile(f, nil, options[:debug]) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
203
- end
204
- end
205
-
206
- # Finds Thorfiles by traversing from your current directory down to the root
207
- # directory of your system. If at any time we find a Thor file, we stop.
208
- #
209
- # We also ensure that system-wide Thorfiles are loaded first, so local
210
- # Thorfiles can override them.
211
- #
212
- # ==== Example
213
- #
214
- # If we start at /Users/wycats/dev/thor ...
215
- #
216
- # 1. /Users/wycats/dev/thor
217
- # 2. /Users/wycats/dev
218
- # 3. /Users/wycats <-- we find a Thorfile here, so we stop
219
- #
220
- # Suppose we start at c:\Documents and Settings\james\dev\thor ...
221
- #
222
- # 1. c:\Documents and Settings\james\dev\thor
223
- # 2. c:\Documents and Settings\james\dev
224
- # 3. c:\Documents and Settings\james
225
- # 4. c:\Documents and Settings
226
- # 5. c:\ <-- no Thorfiles found!
227
- #
228
- def thorfiles(relevant_to=nil, skip_lookup=false)
229
- thorfiles = []
230
-
231
- unless skip_lookup
232
- Pathname.pwd.ascend do |path|
233
- thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten
234
- break unless thorfiles.empty?
235
- end
236
- end
237
-
238
- files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob)
239
- files += thorfiles
240
- files -= ["#{thor_root}/thor.yml"]
241
-
242
- files.map! do |file|
243
- File.directory?(file) ? File.join(file, "main.thor") : file
244
- end
245
- end
246
-
247
- # Load thorfiles relevant to the given method. If you provide "foo:bar" it
248
- # will load all thor files in the thor.yaml that has "foo" e "foo:bar"
249
- # namespaces registered.
250
- #
251
- def thorfiles_relevant_to(meth)
252
- lookup = [ meth, meth.split(":")[0...-1].join(":") ]
253
-
254
- files = thor_yaml.select do |k, v|
255
- v[:namespaces] && !(v[:namespaces] & lookup).empty?
256
- end
257
-
258
- files.map { |k, v| File.join(thor_root, "#{v[:filename]}") }
259
- end
260
-
261
- # Display information about the given klasses. If with_module is given,
262
- # it shows a table with information extracted from the yaml file.
263
- #
264
- def display_klasses(with_modules=false, show_internal=false, klasses=Thor::Base.subclasses)
265
- klasses -= [Thor, Thor::Runner, Thor::Group] unless show_internal
266
-
267
- raise Error, "No Thor tasks available" if klasses.empty?
268
- show_modules if with_modules && !thor_yaml.empty?
269
-
270
- # Remove subclasses
271
- klasses.dup.each do |klass|
272
- klasses -= Thor::Util.thor_classes_in(klass)
273
- end
274
-
275
- list = Hash.new { |h,k| h[k] = [] }
276
- groups = klasses.select { |k| k.ancestors.include?(Thor::Group) }
277
-
278
- # Get classes which inherit from Thor
279
- (klasses - groups).each { |k| list[k.namespace] += k.printable_tasks(false) }
280
-
281
- # Get classes which inherit from Thor::Base
282
- groups.map! { |k| k.printable_tasks(false).first }
283
- list["root"] = groups
284
-
285
- # Order namespaces with default coming first
286
- list = list.sort{ |a,b| a[0].sub(/^default/, '') <=> b[0].sub(/^default/, '') }
287
- list.each { |n, tasks| display_tasks(n, tasks) unless tasks.empty? }
288
- end
289
-
290
- def display_tasks(namespace, list) #:nodoc:
291
- list.sort!{ |a,b| a[0] <=> b[0] }
292
-
293
- say shell.set_color(namespace, :blue, true)
294
- say "-" * namespace.size
295
-
296
- print_table(list, :truncate => true)
297
- say
298
- end
299
-
300
- def show_modules #:nodoc:
301
- info = []
302
- labels = ["Modules", "Namespaces"]
303
-
304
- info << labels
305
- info << [ "-" * labels[0].size, "-" * labels[1].size ]
306
-
307
- thor_yaml.each do |name, hash|
308
- info << [ name, hash[:namespaces].join(", ") ]
309
- end
310
-
311
- print_table info
312
- say ""
313
- end
314
- end