engineyard 1.4.21 → 1.4.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.rdoc +19 -0
  2. data/lib/engineyard.rb +3 -0
  3. data/lib/engineyard/cli.rb +1 -1
  4. data/lib/engineyard/model/instance.rb +4 -2
  5. data/lib/engineyard/thor.rb +10 -0
  6. data/lib/engineyard/version.rb +1 -1
  7. data/lib/vendor/thor/LICENSE.md +20 -0
  8. data/lib/vendor/thor/README.md +26 -0
  9. data/lib/vendor/thor/lib/thor.rb +379 -0
  10. data/lib/vendor/thor/lib/thor/actions.rb +318 -0
  11. data/lib/vendor/thor/lib/thor/actions/create_file.rb +105 -0
  12. data/lib/vendor/thor/lib/thor/actions/create_link.rb +57 -0
  13. data/lib/vendor/thor/lib/thor/actions/directory.rb +97 -0
  14. data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +153 -0
  15. data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +308 -0
  16. data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +109 -0
  17. data/lib/vendor/thor/lib/thor/base.rb +611 -0
  18. data/lib/vendor/thor/lib/thor/core_ext/file_binary_read.rb +9 -0
  19. data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  20. data/lib/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
  21. data/lib/vendor/thor/lib/thor/error.rb +35 -0
  22. data/lib/vendor/thor/lib/thor/group.rb +285 -0
  23. data/lib/vendor/thor/lib/thor/invocation.rb +170 -0
  24. data/lib/vendor/thor/lib/thor/parser.rb +4 -0
  25. data/lib/vendor/thor/lib/thor/parser/argument.rb +67 -0
  26. data/lib/vendor/thor/lib/thor/parser/arguments.rb +165 -0
  27. data/lib/vendor/thor/lib/thor/parser/option.rb +121 -0
  28. data/lib/vendor/thor/lib/thor/parser/options.rb +181 -0
  29. data/lib/vendor/thor/lib/thor/rake_compat.rb +71 -0
  30. data/lib/vendor/thor/lib/thor/runner.rb +321 -0
  31. data/lib/vendor/thor/lib/thor/shell.rb +88 -0
  32. data/lib/vendor/thor/lib/thor/shell/basic.rb +331 -0
  33. data/lib/vendor/thor/lib/thor/shell/color.rb +108 -0
  34. data/lib/vendor/thor/lib/thor/shell/html.rb +121 -0
  35. data/lib/vendor/thor/lib/thor/task.rb +132 -0
  36. data/lib/vendor/thor/lib/thor/util.rb +248 -0
  37. data/lib/vendor/thor/lib/thor/version.rb +3 -0
  38. metadata +67 -52
@@ -0,0 +1,97 @@
1
+ require 'thor/actions/empty_directory'
2
+
3
+ class Thor
4
+ module Actions
5
+ # Copies recursively the files from source directory to root directory.
6
+ # If any of the files finishes with .tt, it's considered to be a template
7
+ # and is placed in the destination without the extension .tt. If any
8
+ # empty directory is found, it's copied and all .empty_directory files are
9
+ # ignored. If any file name is wrapped within % signs, the text within
10
+ # the % signs will be executed as a method and replaced with the returned
11
+ # value. Let's suppose a doc directory with the following files:
12
+ #
13
+ # doc/
14
+ # components/.empty_directory
15
+ # README
16
+ # rdoc.rb.tt
17
+ # %app_name%.rb
18
+ #
19
+ # When invoked as:
20
+ #
21
+ # directory "doc"
22
+ #
23
+ # It will create a doc directory in the destination with the following
24
+ # files (assuming that the `app_name` method returns the value "blog"):
25
+ #
26
+ # doc/
27
+ # components/
28
+ # README
29
+ # rdoc.rb
30
+ # blog.rb
31
+ #
32
+ # <b>Encoded path note:</b> Since Thor internals use Object#respond_to? to check if it can
33
+ # expand %something%, this `something` should be a public method in the class calling
34
+ # #directory. If a method is private, Thor stack raises PrivateMethodEncodedError.
35
+ #
36
+ # ==== Parameters
37
+ # source<String>:: the relative path to the source root.
38
+ # destination<String>:: the relative path to the destination root.
39
+ # config<Hash>:: give :verbose => false to not log the status.
40
+ # If :recursive => false, does not look for paths recursively.
41
+ #
42
+ # ==== Examples
43
+ #
44
+ # directory "doc"
45
+ # directory "doc", "docs", :recursive => false
46
+ #
47
+ def directory(source, *args, &block)
48
+ config = args.last.is_a?(Hash) ? args.pop : {}
49
+ destination = args.first || source
50
+ action Directory.new(self, source, destination || source, config, &block)
51
+ end
52
+
53
+ class Directory < EmptyDirectory #:nodoc:
54
+ attr_reader :source
55
+
56
+ def initialize(base, source, destination=nil, config={}, &block)
57
+ @source = File.expand_path(base.find_in_source_paths(source.to_s))
58
+ @block = block
59
+ super(base, destination, { :recursive => true }.merge(config))
60
+ end
61
+
62
+ def invoke!
63
+ base.empty_directory given_destination, config
64
+ execute!
65
+ end
66
+
67
+ def revoke!
68
+ execute!
69
+ end
70
+
71
+ protected
72
+
73
+ def execute!
74
+ lookup = config[:recursive] ? File.join(source, '**') : source
75
+ lookup = File.join(lookup, '{*,.[a-z]*}')
76
+
77
+ Dir[lookup].sort.each do |file_source|
78
+ next if File.directory?(file_source)
79
+ file_destination = File.join(given_destination, file_source.gsub(source, '.'))
80
+ file_destination.gsub!('/./', '/')
81
+
82
+ case file_source
83
+ when /\.empty_directory$/
84
+ dirname = File.dirname(file_destination).gsub(/\/\.$/, '')
85
+ next if dirname == given_destination
86
+ base.empty_directory(dirname, config)
87
+ when /\.tt$/
88
+ destination = base.template(file_source, file_destination[0..-4], config, &@block)
89
+ else
90
+ destination = base.copy_file(file_source, file_destination, config, &@block)
91
+ end
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,153 @@
1
+ class Thor
2
+ module Actions
3
+
4
+ # Creates an empty directory.
5
+ #
6
+ # ==== Parameters
7
+ # destination<String>:: the relative path to the destination root.
8
+ # config<Hash>:: give :verbose => false to not log the status.
9
+ #
10
+ # ==== Examples
11
+ #
12
+ # empty_directory "doc"
13
+ #
14
+ def empty_directory(destination, config={})
15
+ action EmptyDirectory.new(self, destination, config)
16
+ end
17
+
18
+ # Class which holds create directory logic. This is the base class for
19
+ # other actions like create_file and directory.
20
+ #
21
+ # This implementation is based in Templater actions, created by Jonas Nicklas
22
+ # and Michael S. Klishin under MIT LICENSE.
23
+ #
24
+ class EmptyDirectory #:nodoc:
25
+ attr_reader :base, :destination, :given_destination, :relative_destination, :config
26
+
27
+ # Initializes given the source and destination.
28
+ #
29
+ # ==== Parameters
30
+ # base<Thor::Base>:: A Thor::Base instance
31
+ # source<String>:: Relative path to the source of this file
32
+ # destination<String>:: Relative path to the destination of this file
33
+ # config<Hash>:: give :verbose => false to not log the status.
34
+ #
35
+ def initialize(base, destination, config={})
36
+ @base, @config = base, { :verbose => true }.merge(config)
37
+ self.destination = destination
38
+ end
39
+
40
+ # Checks if the destination file already exists.
41
+ #
42
+ # ==== Returns
43
+ # Boolean:: true if the file exists, false otherwise.
44
+ #
45
+ def exists?
46
+ ::File.exists?(destination)
47
+ end
48
+
49
+ def invoke!
50
+ invoke_with_conflict_check do
51
+ ::FileUtils.mkdir_p(destination)
52
+ end
53
+ end
54
+
55
+ def revoke!
56
+ say_status :remove, :red
57
+ ::FileUtils.rm_rf(destination) if !pretend? && exists?
58
+ given_destination
59
+ end
60
+
61
+ protected
62
+
63
+ # Shortcut for pretend.
64
+ #
65
+ def pretend?
66
+ base.options[:pretend]
67
+ end
68
+
69
+ # Sets the absolute destination value from a relative destination value.
70
+ # It also stores the given and relative destination. Let's suppose our
71
+ # script is being executed on "dest", it sets the destination root to
72
+ # "dest". The destination, given_destination and relative_destination
73
+ # are related in the following way:
74
+ #
75
+ # inside "bar" do
76
+ # empty_directory "baz"
77
+ # end
78
+ #
79
+ # destination #=> dest/bar/baz
80
+ # relative_destination #=> bar/baz
81
+ # given_destination #=> baz
82
+ #
83
+ def destination=(destination)
84
+ if destination
85
+ @given_destination = convert_encoded_instructions(destination.to_s)
86
+ @destination = ::File.expand_path(@given_destination, base.destination_root)
87
+ @relative_destination = base.relative_to_original_destination_root(@destination)
88
+ end
89
+ end
90
+
91
+ # Filenames in the encoded form are converted. If you have a file:
92
+ #
93
+ # %file_name%.rb
94
+ #
95
+ # It calls #file_name from the base and replaces %-string with the
96
+ # return value (should be String) of #file_name:
97
+ #
98
+ # user.rb
99
+ #
100
+ # The method referenced by %-string SHOULD be public. Otherwise you
101
+ # get the exception with the corresponding error message.
102
+ #
103
+ def convert_encoded_instructions(filename)
104
+ filename.gsub(/%(.*?)%/) do |initial_string|
105
+ call_public_method($1.strip) or initial_string
106
+ end
107
+ end
108
+
109
+ # Calls `base`'s public method `sym`.
110
+ # Returns:: result of `base.sym` or `nil` if `sym` wasn't found in
111
+ # `base`
112
+ # Raises:: Thor::PrivateMethodEncodedError if `sym` references
113
+ # a private method.
114
+ def call_public_method(sym)
115
+ if base.respond_to?(sym)
116
+ base.send(sym)
117
+ elsif base.respond_to?(sym, true)
118
+ raise Thor::PrivateMethodEncodedError,
119
+ "Method #{base.class}##{sym} should be public, not private"
120
+ else
121
+ nil
122
+ end
123
+ end
124
+
125
+ # Receives a hash of options and just execute the block if some
126
+ # conditions are met.
127
+ #
128
+ def invoke_with_conflict_check(&block)
129
+ if exists?
130
+ on_conflict_behavior(&block)
131
+ else
132
+ say_status :create, :green
133
+ block.call unless pretend?
134
+ end
135
+
136
+ destination
137
+ end
138
+
139
+ # What to do when the destination file already exists.
140
+ #
141
+ def on_conflict_behavior(&block)
142
+ say_status :exist, :blue
143
+ end
144
+
145
+ # Shortcut to say_status shell method.
146
+ #
147
+ def say_status(status, color)
148
+ base.shell.say_status status, relative_destination, color if config[:verbose]
149
+ end
150
+
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,308 @@
1
+ require 'erb'
2
+ require 'open-uri'
3
+
4
+ class Thor
5
+ module Actions
6
+
7
+ # Copies the file from the relative source to the relative destination. If
8
+ # the destination is not given it's assumed to be equal to the source.
9
+ #
10
+ # ==== Parameters
11
+ # source<String>:: the relative path to the source root.
12
+ # destination<String>:: the relative path to the destination root.
13
+ # config<Hash>:: give :verbose => false to not log the status.
14
+ #
15
+ # ==== Examples
16
+ #
17
+ # copy_file "README", "doc/README"
18
+ #
19
+ # copy_file "doc/README"
20
+ #
21
+ def copy_file(source, *args, &block)
22
+ config = args.last.is_a?(Hash) ? args.pop : {}
23
+ destination = args.first || source
24
+ source = File.expand_path(find_in_source_paths(source.to_s))
25
+
26
+ create_file destination, nil, config do
27
+ content = File.binread(source)
28
+ content = block.call(content) if block
29
+ content
30
+ end
31
+ end
32
+
33
+ # Links the file from the relative source to the relative destination. If
34
+ # the destination is not given it's assumed to be equal to the source.
35
+ #
36
+ # ==== Parameters
37
+ # source<String>:: the relative path to the source root.
38
+ # destination<String>:: the relative path to the destination root.
39
+ # config<Hash>:: give :verbose => false to not log the status.
40
+ #
41
+ # ==== Examples
42
+ #
43
+ # link_file "README", "doc/README"
44
+ #
45
+ # link_file "doc/README"
46
+ #
47
+ def link_file(source, *args, &block)
48
+ config = args.last.is_a?(Hash) ? args.pop : {}
49
+ destination = args.first || source
50
+ source = File.expand_path(find_in_source_paths(source.to_s))
51
+
52
+ create_link destination, source, config
53
+ end
54
+
55
+ # Gets the content at the given address and places it at the given relative
56
+ # destination. If a block is given instead of destination, the content of
57
+ # the url is yielded and used as location.
58
+ #
59
+ # ==== Parameters
60
+ # source<String>:: the address of the given content.
61
+ # destination<String>:: the relative path to the destination root.
62
+ # config<Hash>:: give :verbose => false to not log the status.
63
+ #
64
+ # ==== Examples
65
+ #
66
+ # get "http://gist.github.com/103208", "doc/README"
67
+ #
68
+ # get "http://gist.github.com/103208" do |content|
69
+ # content.split("\n").first
70
+ # end
71
+ #
72
+ def get(source, *args, &block)
73
+ config = args.last.is_a?(Hash) ? args.pop : {}
74
+ destination = args.first
75
+
76
+ source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^https?\:\/\//
77
+ render = open(source) {|input| input.binmode.read }
78
+
79
+ destination ||= if block_given?
80
+ block.arity == 1 ? block.call(render) : block.call
81
+ else
82
+ File.basename(source)
83
+ end
84
+
85
+ create_file destination, render, config
86
+ end
87
+
88
+ # Gets an ERB template at the relative source, executes it and makes a copy
89
+ # at the relative destination. If the destination is not given it's assumed
90
+ # to be equal to the source removing .tt from the filename.
91
+ #
92
+ # ==== Parameters
93
+ # source<String>:: the relative path to the source root.
94
+ # destination<String>:: the relative path to the destination root.
95
+ # config<Hash>:: give :verbose => false to not log the status.
96
+ #
97
+ # ==== Examples
98
+ #
99
+ # template "README", "doc/README"
100
+ #
101
+ # template "doc/README"
102
+ #
103
+ def template(source, *args, &block)
104
+ config = args.last.is_a?(Hash) ? args.pop : {}
105
+ destination = args.first || source.sub(/\.tt$/, '')
106
+
107
+ source = File.expand_path(find_in_source_paths(source.to_s))
108
+ context = instance_eval('binding')
109
+
110
+ create_file destination, nil, config do
111
+ content = ERB.new(::File.binread(source), nil, '-', '@output_buffer').result(context)
112
+ content = block.call(content) if block
113
+ content
114
+ end
115
+ end
116
+
117
+ # Changes the mode of the given file or directory.
118
+ #
119
+ # ==== Parameters
120
+ # mode<Integer>:: the file mode
121
+ # path<String>:: the name of the file to change mode
122
+ # config<Hash>:: give :verbose => false to not log the status.
123
+ #
124
+ # ==== Example
125
+ #
126
+ # chmod "script/*", 0755
127
+ #
128
+ def chmod(path, mode, config={})
129
+ return unless behavior == :invoke
130
+ path = File.expand_path(path, destination_root)
131
+ say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true)
132
+ FileUtils.chmod_R(mode, path) unless options[:pretend]
133
+ end
134
+
135
+ # Prepend text to a file. Since it depends on insert_into_file, it's reversible.
136
+ #
137
+ # ==== Parameters
138
+ # path<String>:: path of the file to be changed
139
+ # data<String>:: the data to prepend to the file, can be also given as a block.
140
+ # config<Hash>:: give :verbose => false to not log the status.
141
+ #
142
+ # ==== Example
143
+ #
144
+ # prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"'
145
+ #
146
+ # prepend_to_file 'config/environments/test.rb' do
147
+ # 'config.gem "rspec"'
148
+ # end
149
+ #
150
+ def prepend_to_file(path, *args, &block)
151
+ config = args.last.is_a?(Hash) ? args.pop : {}
152
+ config.merge!(:after => /\A/)
153
+ insert_into_file(path, *(args << config), &block)
154
+ end
155
+ alias_method :prepend_file, :prepend_to_file
156
+
157
+ # Append text to a file. Since it depends on insert_into_file, it's reversible.
158
+ #
159
+ # ==== Parameters
160
+ # path<String>:: path of the file to be changed
161
+ # data<String>:: the data to append to the file, can be also given as a block.
162
+ # config<Hash>:: give :verbose => false to not log the status.
163
+ #
164
+ # ==== Example
165
+ #
166
+ # append_to_file 'config/environments/test.rb', 'config.gem "rspec"'
167
+ #
168
+ # append_to_file 'config/environments/test.rb' do
169
+ # 'config.gem "rspec"'
170
+ # end
171
+ #
172
+ def append_to_file(path, *args, &block)
173
+ config = args.last.is_a?(Hash) ? args.pop : {}
174
+ config.merge!(:before => /\z/)
175
+ insert_into_file(path, *(args << config), &block)
176
+ end
177
+ alias_method :append_file, :append_to_file
178
+
179
+ # Injects text right after the class definition. Since it depends on
180
+ # insert_into_file, it's reversible.
181
+ #
182
+ # ==== Parameters
183
+ # path<String>:: path of the file to be changed
184
+ # klass<String|Class>:: the class to be manipulated
185
+ # data<String>:: the data to append to the class, can be also given as a block.
186
+ # config<Hash>:: give :verbose => false to not log the status.
187
+ #
188
+ # ==== Examples
189
+ #
190
+ # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
191
+ #
192
+ # inject_into_class "app/controllers/application_controller.rb", ApplicationController do
193
+ # " filter_parameter :password\n"
194
+ # end
195
+ #
196
+ def inject_into_class(path, klass, *args, &block)
197
+ config = args.last.is_a?(Hash) ? args.pop : {}
198
+ config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/)
199
+ insert_into_file(path, *(args << config), &block)
200
+ end
201
+
202
+ # Run a regular expression replacement on a file.
203
+ #
204
+ # ==== Parameters
205
+ # path<String>:: path of the file to be changed
206
+ # flag<Regexp|String>:: the regexp or string to be replaced
207
+ # replacement<String>:: the replacement, can be also given as a block
208
+ # config<Hash>:: give :verbose => false to not log the status.
209
+ #
210
+ # ==== Example
211
+ #
212
+ # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
213
+ #
214
+ # gsub_file 'README', /rake/, :green do |match|
215
+ # match << " no more. Use thor!"
216
+ # end
217
+ #
218
+ def gsub_file(path, flag, *args, &block)
219
+ return unless behavior == :invoke
220
+ config = args.last.is_a?(Hash) ? args.pop : {}
221
+
222
+ path = File.expand_path(path, destination_root)
223
+ say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
224
+
225
+ unless options[:pretend]
226
+ content = File.binread(path)
227
+ content.gsub!(flag, *args, &block)
228
+ File.open(path, 'wb') { |file| file.write(content) }
229
+ end
230
+ end
231
+
232
+ # Uncomment all lines matching a given regex. It will leave the space
233
+ # which existed before the comment hash in tact but will remove any spacing
234
+ # between the comment hash and the beginning of the line.
235
+ #
236
+ # ==== Parameters
237
+ # path<String>:: path of the file to be changed
238
+ # flag<Regexp|String>:: the regexp or string used to decide which lines to uncomment
239
+ # config<Hash>:: give :verbose => false to not log the status.
240
+ #
241
+ # ==== Example
242
+ #
243
+ # uncomment_lines 'config/initializers/session_store.rb', /active_record/
244
+ #
245
+ def uncomment_lines(path, flag, *args)
246
+ flag = flag.respond_to?(:source) ? flag.source : flag
247
+
248
+ gsub_file(path, /^(\s*)#\s*(.*#{flag})/, '\1\2', *args)
249
+ end
250
+
251
+ # Comment all lines matching a given regex. It will leave the space
252
+ # which existed before the beginning of the line in tact and will insert
253
+ # a single space after the comment hash.
254
+ #
255
+ # ==== Parameters
256
+ # path<String>:: path of the file to be changed
257
+ # flag<Regexp|String>:: the regexp or string used to decide which lines to comment
258
+ # config<Hash>:: give :verbose => false to not log the status.
259
+ #
260
+ # ==== Example
261
+ #
262
+ # comment_lines 'config/initializers/session_store.rb', /cookie_store/
263
+ #
264
+ def comment_lines(path, flag, *args)
265
+ flag = flag.respond_to?(:source) ? flag.source : flag
266
+
267
+ gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args)
268
+ end
269
+
270
+ # Removes a file at the given location.
271
+ #
272
+ # ==== Parameters
273
+ # path<String>:: path of the file to be changed
274
+ # config<Hash>:: give :verbose => false to not log the status.
275
+ #
276
+ # ==== Example
277
+ #
278
+ # remove_file 'README'
279
+ # remove_file 'app/controllers/application_controller.rb'
280
+ #
281
+ def remove_file(path, config={})
282
+ return unless behavior == :invoke
283
+ path = File.expand_path(path, destination_root)
284
+
285
+ say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
286
+ ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path)
287
+ end
288
+ alias :remove_dir :remove_file
289
+
290
+ private
291
+ attr_accessor :output_buffer
292
+ def concat(string)
293
+ @output_buffer.concat(string)
294
+ end
295
+
296
+ def capture(*args, &block)
297
+ with_output_buffer { block.call(*args) }
298
+ end
299
+
300
+ def with_output_buffer(buf = '') #:nodoc:
301
+ self.output_buffer, old_buffer = buf, output_buffer
302
+ yield
303
+ output_buffer
304
+ ensure
305
+ self.output_buffer = old_buffer
306
+ end
307
+ end
308
+ end