crazy-yard 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +19 -0
  3. data/README.md +438 -0
  4. data/bin/ey +9 -0
  5. data/lib/engineyard.rb +9 -0
  6. data/lib/engineyard/cli.rb +816 -0
  7. data/lib/engineyard/cli/api.rb +98 -0
  8. data/lib/engineyard/cli/recipes.rb +129 -0
  9. data/lib/engineyard/cli/ui.rb +275 -0
  10. data/lib/engineyard/cli/web.rb +85 -0
  11. data/lib/engineyard/config.rb +158 -0
  12. data/lib/engineyard/deploy_config.rb +65 -0
  13. data/lib/engineyard/deploy_config/ref.rb +56 -0
  14. data/lib/engineyard/error.rb +82 -0
  15. data/lib/engineyard/eyrc.rb +59 -0
  16. data/lib/engineyard/repo.rb +105 -0
  17. data/lib/engineyard/serverside_runner.rb +159 -0
  18. data/lib/engineyard/templates.rb +6 -0
  19. data/lib/engineyard/templates/ey.yml.erb +196 -0
  20. data/lib/engineyard/templates/ey_yml.rb +119 -0
  21. data/lib/engineyard/thor.rb +215 -0
  22. data/lib/engineyard/version.rb +4 -0
  23. data/lib/vendor/thor/Gemfile +15 -0
  24. data/lib/vendor/thor/LICENSE.md +20 -0
  25. data/lib/vendor/thor/README.md +35 -0
  26. data/lib/vendor/thor/lib/thor.rb +473 -0
  27. data/lib/vendor/thor/lib/thor/actions.rb +318 -0
  28. data/lib/vendor/thor/lib/thor/actions/create_file.rb +105 -0
  29. data/lib/vendor/thor/lib/thor/actions/create_link.rb +60 -0
  30. data/lib/vendor/thor/lib/thor/actions/directory.rb +119 -0
  31. data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +137 -0
  32. data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +314 -0
  33. data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +109 -0
  34. data/lib/vendor/thor/lib/thor/base.rb +652 -0
  35. data/lib/vendor/thor/lib/thor/command.rb +136 -0
  36. data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
  37. data/lib/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
  38. data/lib/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
  39. data/lib/vendor/thor/lib/thor/error.rb +28 -0
  40. data/lib/vendor/thor/lib/thor/group.rb +282 -0
  41. data/lib/vendor/thor/lib/thor/invocation.rb +172 -0
  42. data/lib/vendor/thor/lib/thor/parser.rb +4 -0
  43. data/lib/vendor/thor/lib/thor/parser/argument.rb +74 -0
  44. data/lib/vendor/thor/lib/thor/parser/arguments.rb +171 -0
  45. data/lib/vendor/thor/lib/thor/parser/option.rb +121 -0
  46. data/lib/vendor/thor/lib/thor/parser/options.rb +218 -0
  47. data/lib/vendor/thor/lib/thor/rake_compat.rb +72 -0
  48. data/lib/vendor/thor/lib/thor/runner.rb +322 -0
  49. data/lib/vendor/thor/lib/thor/shell.rb +88 -0
  50. data/lib/vendor/thor/lib/thor/shell/basic.rb +393 -0
  51. data/lib/vendor/thor/lib/thor/shell/color.rb +148 -0
  52. data/lib/vendor/thor/lib/thor/shell/html.rb +127 -0
  53. data/lib/vendor/thor/lib/thor/util.rb +270 -0
  54. data/lib/vendor/thor/lib/thor/version.rb +3 -0
  55. data/lib/vendor/thor/thor.gemspec +24 -0
  56. data/spec/engineyard/cli/api_spec.rb +50 -0
  57. data/spec/engineyard/cli_spec.rb +28 -0
  58. data/spec/engineyard/config_spec.rb +61 -0
  59. data/spec/engineyard/deploy_config_spec.rb +194 -0
  60. data/spec/engineyard/eyrc_spec.rb +76 -0
  61. data/spec/engineyard/repo_spec.rb +83 -0
  62. data/spec/engineyard_spec.rb +7 -0
  63. data/spec/ey/console_spec.rb +57 -0
  64. data/spec/ey/deploy_spec.rb +435 -0
  65. data/spec/ey/ey_spec.rb +23 -0
  66. data/spec/ey/init_spec.rb +123 -0
  67. data/spec/ey/list_environments_spec.rb +120 -0
  68. data/spec/ey/login_spec.rb +33 -0
  69. data/spec/ey/logout_spec.rb +24 -0
  70. data/spec/ey/logs_spec.rb +36 -0
  71. data/spec/ey/rebuild_spec.rb +18 -0
  72. data/spec/ey/recipes/apply_spec.rb +29 -0
  73. data/spec/ey/recipes/download_spec.rb +43 -0
  74. data/spec/ey/recipes/upload_spec.rb +99 -0
  75. data/spec/ey/rollback_spec.rb +73 -0
  76. data/spec/ey/scp_spec.rb +176 -0
  77. data/spec/ey/servers_spec.rb +209 -0
  78. data/spec/ey/ssh_spec.rb +273 -0
  79. data/spec/ey/status_spec.rb +45 -0
  80. data/spec/ey/timeout_deploy_spec.rb +18 -0
  81. data/spec/ey/web/disable_spec.rb +21 -0
  82. data/spec/ey/web/enable_spec.rb +26 -0
  83. data/spec/ey/web/restart_spec.rb +21 -0
  84. data/spec/ey/whoami_spec.rb +30 -0
  85. data/spec/spec_helper.rb +84 -0
  86. data/spec/support/bundled_ey +7 -0
  87. data/spec/support/fixture_recipes.tgz +0 -0
  88. data/spec/support/git_repos.rb +115 -0
  89. data/spec/support/helpers.rb +330 -0
  90. data/spec/support/matchers.rb +16 -0
  91. data/spec/support/ruby_ext.rb +13 -0
  92. data/spec/support/shared_behavior.rb +278 -0
  93. metadata +411 -0
@@ -0,0 +1,119 @@
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
+ # If :mode => :preserve, preserve the file mode from the source.
42
+ # If :exclude_pattern => /regexp/, prevents copying files that match that regexp.
43
+ #
44
+ # ==== Examples
45
+ #
46
+ # directory "doc"
47
+ # directory "doc", "docs", :recursive => false
48
+ #
49
+ def directory(source, *args, &block)
50
+ config = args.last.is_a?(Hash) ? args.pop : {}
51
+ destination = args.first || source
52
+ action Directory.new(self, source, destination || source, config, &block)
53
+ end
54
+
55
+ class Directory < EmptyDirectory #:nodoc:
56
+ attr_reader :source
57
+
58
+ def initialize(base, source, destination=nil, config={}, &block)
59
+ @source = File.expand_path(base.find_in_source_paths(source.to_s))
60
+ @block = block
61
+ super(base, destination, { :recursive => true }.merge(config))
62
+ end
63
+
64
+ def invoke!
65
+ base.empty_directory given_destination, config
66
+ execute!
67
+ end
68
+
69
+ def revoke!
70
+ execute!
71
+ end
72
+
73
+ protected
74
+
75
+ def execute!
76
+ lookup = Util.escape_globs(source)
77
+ lookup = config[:recursive] ? File.join(lookup, '**') : lookup
78
+ lookup = file_level_lookup(lookup)
79
+
80
+ files(lookup).sort.each do |file_source|
81
+ next if File.directory?(file_source)
82
+ next if config[:exclude_pattern] && file_source.match(config[:exclude_pattern])
83
+ file_destination = File.join(given_destination, file_source.gsub(source, '.'))
84
+ file_destination.gsub!('/./', '/')
85
+
86
+ case file_source
87
+ when /\.empty_directory$/
88
+ dirname = File.dirname(file_destination).gsub(/\/\.$/, '')
89
+ next if dirname == given_destination
90
+ base.empty_directory(dirname, config)
91
+ when /\.tt$/
92
+ destination = base.template(file_source, file_destination[0..-4], config, &@block)
93
+ else
94
+ destination = base.copy_file(file_source, file_destination, config, &@block)
95
+ end
96
+ end
97
+ end
98
+
99
+ if RUBY_VERSION < '2.0'
100
+ def file_level_lookup(previous_lookup)
101
+ File.join(previous_lookup, '{*,.[a-z]*}')
102
+ end
103
+
104
+ def files(lookup)
105
+ Dir[lookup]
106
+ end
107
+ else
108
+ def file_level_lookup(previous_lookup)
109
+ File.join(previous_lookup, '*')
110
+ end
111
+
112
+ def files(lookup)
113
+ Dir.glob(lookup, File::FNM_DOTMATCH)
114
+ end
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,137 @@
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 can be either public or private.
101
+ #
102
+ def convert_encoded_instructions(filename)
103
+ filename.gsub(/%(.*?)%/) do |initial_string|
104
+ method = $1.strip
105
+ base.respond_to?(method, true) ? base.send(method) : initial_string
106
+ end
107
+ end
108
+
109
+ # Receives a hash of options and just execute the block if some
110
+ # conditions are met.
111
+ #
112
+ def invoke_with_conflict_check(&block)
113
+ if exists?
114
+ on_conflict_behavior(&block)
115
+ else
116
+ say_status :create, :green
117
+ block.call unless pretend?
118
+ end
119
+
120
+ destination
121
+ end
122
+
123
+ # What to do when the destination file already exists.
124
+ #
125
+ def on_conflict_behavior(&block)
126
+ say_status :exist, :blue
127
+ end
128
+
129
+ # Shortcut to say_status shell method.
130
+ #
131
+ def say_status(status, color)
132
+ base.shell.say_status status, relative_destination, color if config[:verbose]
133
+ end
134
+
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,314 @@
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, and
14
+ # :mode => :preserve, to preserve the file mode from the source.
15
+
16
+ #
17
+ # ==== Examples
18
+ #
19
+ # copy_file "README", "doc/README"
20
+ #
21
+ # copy_file "doc/README"
22
+ #
23
+ def copy_file(source, *args, &block)
24
+ config = args.last.is_a?(Hash) ? args.pop : {}
25
+ destination = args.first || source
26
+ source = File.expand_path(find_in_source_paths(source.to_s))
27
+
28
+ create_file destination, nil, config do
29
+ content = File.binread(source)
30
+ content = block.call(content) if block
31
+ content
32
+ end
33
+ if config[:mode] == :preserve
34
+ mode = File.stat(source).mode
35
+ chmod(destination, mode, config)
36
+ end
37
+ end
38
+
39
+ # Links the file from the relative source to the relative destination. If
40
+ # the destination is not given it's assumed to be equal to the source.
41
+ #
42
+ # ==== Parameters
43
+ # source<String>:: the relative path to the source root.
44
+ # destination<String>:: the relative path to the destination root.
45
+ # config<Hash>:: give :verbose => false to not log the status.
46
+ #
47
+ # ==== Examples
48
+ #
49
+ # link_file "README", "doc/README"
50
+ #
51
+ # link_file "doc/README"
52
+ #
53
+ def link_file(source, *args, &block)
54
+ config = args.last.is_a?(Hash) ? args.pop : {}
55
+ destination = args.first || source
56
+ source = File.expand_path(find_in_source_paths(source.to_s))
57
+
58
+ create_link destination, source, config
59
+ end
60
+
61
+ # Gets the content at the given address and places it at the given relative
62
+ # destination. If a block is given instead of destination, the content of
63
+ # the url is yielded and used as location.
64
+ #
65
+ # ==== Parameters
66
+ # source<String>:: the address of the given content.
67
+ # destination<String>:: the relative path to the destination root.
68
+ # config<Hash>:: give :verbose => false to not log the status.
69
+ #
70
+ # ==== Examples
71
+ #
72
+ # get "http://gist.github.com/103208", "doc/README"
73
+ #
74
+ # get "http://gist.github.com/103208" do |content|
75
+ # content.split("\n").first
76
+ # end
77
+ #
78
+ def get(source, *args, &block)
79
+ config = args.last.is_a?(Hash) ? args.pop : {}
80
+ destination = args.first
81
+
82
+ source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^https?\:\/\//
83
+ render = open(source) {|input| input.binmode.read }
84
+
85
+ destination ||= if block_given?
86
+ block.arity == 1 ? block.call(render) : block.call
87
+ else
88
+ File.basename(source)
89
+ end
90
+
91
+ create_file destination, render, config
92
+ end
93
+
94
+ # Gets an ERB template at the relative source, executes it and makes a copy
95
+ # at the relative destination. If the destination is not given it's assumed
96
+ # to be equal to the source removing .tt from the filename.
97
+ #
98
+ # ==== Parameters
99
+ # source<String>:: the relative path to the source root.
100
+ # destination<String>:: the relative path to the destination root.
101
+ # config<Hash>:: give :verbose => false to not log the status.
102
+ #
103
+ # ==== Examples
104
+ #
105
+ # template "README", "doc/README"
106
+ #
107
+ # template "doc/README"
108
+ #
109
+ def template(source, *args, &block)
110
+ config = args.last.is_a?(Hash) ? args.pop : {}
111
+ destination = args.first || source.sub(/\.tt$/, '')
112
+
113
+ source = File.expand_path(find_in_source_paths(source.to_s))
114
+ context = instance_eval('binding')
115
+
116
+ create_file destination, nil, config do
117
+ content = ERB.new(::File.binread(source), nil, '-', '@output_buffer').result(context)
118
+ content = block.call(content) if block
119
+ content
120
+ end
121
+ end
122
+
123
+ # Changes the mode of the given file or directory.
124
+ #
125
+ # ==== Parameters
126
+ # mode<Integer>:: the file mode
127
+ # path<String>:: the name of the file to change mode
128
+ # config<Hash>:: give :verbose => false to not log the status.
129
+ #
130
+ # ==== Example
131
+ #
132
+ # chmod "script/server", 0755
133
+ #
134
+ def chmod(path, mode, config={})
135
+ return unless behavior == :invoke
136
+ path = File.expand_path(path, destination_root)
137
+ say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true)
138
+ FileUtils.chmod_R(mode, path) unless options[:pretend]
139
+ end
140
+
141
+ # Prepend text to a file. Since it depends on insert_into_file, it's reversible.
142
+ #
143
+ # ==== Parameters
144
+ # path<String>:: path of the file to be changed
145
+ # data<String>:: the data to prepend to the file, can be also given as a block.
146
+ # config<Hash>:: give :verbose => false to not log the status.
147
+ #
148
+ # ==== Example
149
+ #
150
+ # prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"'
151
+ #
152
+ # prepend_to_file 'config/environments/test.rb' do
153
+ # 'config.gem "rspec"'
154
+ # end
155
+ #
156
+ def prepend_to_file(path, *args, &block)
157
+ config = args.last.is_a?(Hash) ? args.pop : {}
158
+ config.merge!(:after => /\A/)
159
+ insert_into_file(path, *(args << config), &block)
160
+ end
161
+ alias_method :prepend_file, :prepend_to_file
162
+
163
+ # Append text to a file. Since it depends on insert_into_file, it's reversible.
164
+ #
165
+ # ==== Parameters
166
+ # path<String>:: path of the file to be changed
167
+ # data<String>:: the data to append to the file, can be also given as a block.
168
+ # config<Hash>:: give :verbose => false to not log the status.
169
+ #
170
+ # ==== Example
171
+ #
172
+ # append_to_file 'config/environments/test.rb', 'config.gem "rspec"'
173
+ #
174
+ # append_to_file 'config/environments/test.rb' do
175
+ # 'config.gem "rspec"'
176
+ # end
177
+ #
178
+ def append_to_file(path, *args, &block)
179
+ config = args.last.is_a?(Hash) ? args.pop : {}
180
+ config.merge!(:before => /\z/)
181
+ insert_into_file(path, *(args << config), &block)
182
+ end
183
+ alias_method :append_file, :append_to_file
184
+
185
+ # Injects text right after the class definition. Since it depends on
186
+ # insert_into_file, it's reversible.
187
+ #
188
+ # ==== Parameters
189
+ # path<String>:: path of the file to be changed
190
+ # klass<String|Class>:: the class to be manipulated
191
+ # data<String>:: the data to append to the class, can be also given as a block.
192
+ # config<Hash>:: give :verbose => false to not log the status.
193
+ #
194
+ # ==== Examples
195
+ #
196
+ # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
197
+ #
198
+ # inject_into_class "app/controllers/application_controller.rb", ApplicationController do
199
+ # " filter_parameter :password\n"
200
+ # end
201
+ #
202
+ def inject_into_class(path, klass, *args, &block)
203
+ config = args.last.is_a?(Hash) ? args.pop : {}
204
+ config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/)
205
+ insert_into_file(path, *(args << config), &block)
206
+ end
207
+
208
+ # Run a regular expression replacement on a file.
209
+ #
210
+ # ==== Parameters
211
+ # path<String>:: path of the file to be changed
212
+ # flag<Regexp|String>:: the regexp or string to be replaced
213
+ # replacement<String>:: the replacement, can be also given as a block
214
+ # config<Hash>:: give :verbose => false to not log the status.
215
+ #
216
+ # ==== Example
217
+ #
218
+ # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
219
+ #
220
+ # gsub_file 'README', /rake/, :green do |match|
221
+ # match << " no more. Use thor!"
222
+ # end
223
+ #
224
+ def gsub_file(path, flag, *args, &block)
225
+ return unless behavior == :invoke
226
+ config = args.last.is_a?(Hash) ? args.pop : {}
227
+
228
+ path = File.expand_path(path, destination_root)
229
+ say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
230
+
231
+ unless options[:pretend]
232
+ content = File.binread(path)
233
+ content.gsub!(flag, *args, &block)
234
+ File.open(path, 'wb') { |file| file.write(content) }
235
+ end
236
+ end
237
+
238
+ # Uncomment all lines matching a given regex. It will leave the space
239
+ # which existed before the comment hash in tact but will remove any spacing
240
+ # between the comment hash and the beginning of the line.
241
+ #
242
+ # ==== Parameters
243
+ # path<String>:: path of the file to be changed
244
+ # flag<Regexp|String>:: the regexp or string used to decide which lines to uncomment
245
+ # config<Hash>:: give :verbose => false to not log the status.
246
+ #
247
+ # ==== Example
248
+ #
249
+ # uncomment_lines 'config/initializers/session_store.rb', /active_record/
250
+ #
251
+ def uncomment_lines(path, flag, *args)
252
+ flag = flag.respond_to?(:source) ? flag.source : flag
253
+
254
+ gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args)
255
+ end
256
+
257
+ # Comment all lines matching a given regex. It will leave the space
258
+ # which existed before the beginning of the line in tact and will insert
259
+ # a single space after the comment hash.
260
+ #
261
+ # ==== Parameters
262
+ # path<String>:: path of the file to be changed
263
+ # flag<Regexp|String>:: the regexp or string used to decide which lines to comment
264
+ # config<Hash>:: give :verbose => false to not log the status.
265
+ #
266
+ # ==== Example
267
+ #
268
+ # comment_lines 'config/initializers/session_store.rb', /cookie_store/
269
+ #
270
+ def comment_lines(path, flag, *args)
271
+ flag = flag.respond_to?(:source) ? flag.source : flag
272
+
273
+ gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args)
274
+ end
275
+
276
+ # Removes a file at the given location.
277
+ #
278
+ # ==== Parameters
279
+ # path<String>:: path of the file to be changed
280
+ # config<Hash>:: give :verbose => false to not log the status.
281
+ #
282
+ # ==== Example
283
+ #
284
+ # remove_file 'README'
285
+ # remove_file 'app/controllers/application_controller.rb'
286
+ #
287
+ def remove_file(path, config={})
288
+ return unless behavior == :invoke
289
+ path = File.expand_path(path, destination_root)
290
+
291
+ say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
292
+ ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path)
293
+ end
294
+ alias :remove_dir :remove_file
295
+
296
+ private
297
+ attr_accessor :output_buffer
298
+ def concat(string)
299
+ @output_buffer.concat(string)
300
+ end
301
+
302
+ def capture(*args, &block)
303
+ with_output_buffer { block.call(*args) }
304
+ end
305
+
306
+ def with_output_buffer(buf = '') #:nodoc:
307
+ self.output_buffer, old_buffer = buf, output_buffer
308
+ yield
309
+ output_buffer
310
+ ensure
311
+ self.output_buffer = old_buffer
312
+ end
313
+ end
314
+ end