ing 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +5 -0
  2. data/GENERATORS.md +2 -0
  3. data/LICENSE +18 -0
  4. data/OPTIONS.md +2 -0
  5. data/README.md +251 -0
  6. data/TASKS.md +21 -0
  7. data/bin/ing +5 -0
  8. data/examples/rspec_convert.rb +102 -0
  9. data/ing.gemspec +29 -0
  10. data/ing.rb +102 -0
  11. data/lib/ing.rb +78 -0
  12. data/lib/ing/actions/create_file.rb +105 -0
  13. data/lib/ing/actions/create_link.rb +57 -0
  14. data/lib/ing/actions/directory.rb +98 -0
  15. data/lib/ing/actions/empty_directory.rb +155 -0
  16. data/lib/ing/actions/file_manipulation.rb +308 -0
  17. data/lib/ing/actions/inject_into_file.rb +109 -0
  18. data/lib/ing/commands/boot.rb +76 -0
  19. data/lib/ing/commands/generate.rb +64 -0
  20. data/lib/ing/commands/help.rb +87 -0
  21. data/lib/ing/commands/implicit.rb +59 -0
  22. data/lib/ing/commands/list.rb +108 -0
  23. data/lib/ing/dispatcher.rb +132 -0
  24. data/lib/ing/files.rb +190 -0
  25. data/lib/ing/lib_trollop.rb +782 -0
  26. data/lib/ing/shell.rb +390 -0
  27. data/lib/ing/trollop/parser.rb +17 -0
  28. data/lib/ing/util.rb +61 -0
  29. data/lib/ing/version.rb +3 -0
  30. data/lib/thor/actions/file_manipulation.rb +30 -0
  31. data/lib/thor/shell/basic.rb +44 -0
  32. data/test/acceptance/ing_run_tests.rb +164 -0
  33. data/test/actions/create_file_spec.rb +209 -0
  34. data/test/actions/create_link_spec.rb +90 -0
  35. data/test/actions/directory_spec.rb +167 -0
  36. data/test/actions/empty_directory_spec.rb +146 -0
  37. data/test/actions/file_manipulation_spec.rb +433 -0
  38. data/test/actions/inject_into_file_spec.rb +147 -0
  39. data/test/fixtures/application.rb +2 -0
  40. data/test/fixtures/app{1}/README +3 -0
  41. data/test/fixtures/bundle/execute.rb +6 -0
  42. data/test/fixtures/bundle/main.thor +1 -0
  43. data/test/fixtures/doc/%file_name%.rb.tt +1 -0
  44. data/test/fixtures/doc/COMMENTER +10 -0
  45. data/test/fixtures/doc/README +3 -0
  46. data/test/fixtures/doc/block_helper.rb +3 -0
  47. data/test/fixtures/doc/components/.empty_directory +0 -0
  48. data/test/fixtures/doc/config.rb +1 -0
  49. data/test/fixtures/doc/config.yaml.tt +1 -0
  50. data/test/fixtures/group.ing.rb +76 -0
  51. data/test/fixtures/invok.ing.rb +50 -0
  52. data/test/fixtures/namespace.ing.rb +52 -0
  53. data/test/fixtures/require.ing.rb +7 -0
  54. data/test/fixtures/task.ing.rb +36 -0
  55. data/test/fixtures/task.thor +10 -0
  56. data/test/spec_helper.rb +2 -0
  57. data/test/test_helper.rb +41 -0
  58. data/todo.yml +7 -0
  59. metadata +147 -0
@@ -0,0 +1,90 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ require File.expand_path("../../lib/ing/files", File.dirname(__FILE__))
3
+
4
+ require 'tempfile'
5
+
6
+ describe Ing::Files::CreateLink do
7
+ include SpecHelpers
8
+
9
+ def reset
10
+ @hardlink_to = File.join(Dir.tmpdir, 'linkdest.rb')
11
+ ::FileUtils.rm_rf(destination_root)
12
+ ::FileUtils.rm_rf(@hardlink_to)
13
+ end
14
+
15
+ def create_link(destination=nil, config={}, options={})
16
+ @base = MyCounter.new(options)
17
+ @base.destination_root = destination_root
18
+ @base.call 1, 2
19
+ MyCounter.send(:define_method, :file_name, Proc.new {'rdoc'} )
20
+
21
+ @tempfile = Tempfile.new("config.rb")
22
+
23
+ @action = Ing::Files::CreateLink.new(@base, destination, @tempfile.path,
24
+ { :verbose => !@silence }.merge(config))
25
+ end
26
+
27
+ def invoke!
28
+ capture(:stdout){ @action.invoke! }
29
+ end
30
+
31
+ def silence!
32
+ @silence = true
33
+ end
34
+
35
+ describe "#invoke!" do
36
+ before { reset }
37
+
38
+ it "creates a symbolic link for :symbolic => true" do
39
+ create_link("doc/config.rb", :symbolic => true)
40
+ invoke!
41
+ destination_path = File.join(destination_root, "doc/config.rb")
42
+ assert File.exists?(destination_path)
43
+ assert File.symlink?(destination_path)
44
+ end
45
+
46
+ it "creates a hard link for :symbolic => false" do
47
+ create_link(@hardlink_to, :symbolic => false)
48
+ invoke!
49
+ destination_path = @hardlink_to
50
+ assert File.exists?(destination_path)
51
+ refute File.symlink?(destination_path)
52
+ end
53
+
54
+ it "creates a symbolic link by default" do
55
+ create_link("doc/config.rb")
56
+ invoke!
57
+ destination_path = File.join(destination_root, "doc/config.rb")
58
+ assert File.exists?(destination_path)
59
+ assert File.symlink?(destination_path)
60
+ end
61
+
62
+ it "does not create a link if pretending" do
63
+ create_link("doc/config.rb", {}, :pretend => true)
64
+ invoke!
65
+ refute File.exists?(File.join(destination_root, "doc/config.rb"))
66
+ end
67
+
68
+ it "shows created status to the user" do
69
+ create_link("doc/config.rb")
70
+ assert_equal " create doc/config.rb\n", invoke!
71
+ end
72
+
73
+ it "does not show any information if log status is false" do
74
+ silence!
75
+ create_link("doc/config.rb")
76
+ assert invoke!.empty?
77
+ end
78
+ end
79
+
80
+ describe "#identical?" do
81
+ before { reset }
82
+
83
+ it "returns true if the destination link exists and is identical" do
84
+ create_link("doc/config.rb")
85
+ refute @action.identical?
86
+ invoke!
87
+ assert @action.identical?
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,167 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ require File.expand_path("../../lib/ing/files", File.dirname(__FILE__))
3
+
4
+ describe Ing::Files::Directory do
5
+ include TestHelpers
6
+
7
+ def reset
8
+ ::FileUtils.rm_rf(destination_root)
9
+ invoker.class.send(:define_method, :file_name, Proc.new{ "rdoc" })
10
+ end
11
+
12
+ def invoker
13
+ @invoker ||= begin
14
+ wg=WhinyGenerator.new({})
15
+ wg.destination_root = destination_root
16
+ wg.call 1,2
17
+ wg
18
+ end
19
+ end
20
+
21
+ def revoker
22
+ @revoker ||= begin
23
+ wg=WhinyGenerator.new({:revoke => true})
24
+ wg.destination_root = destination_root
25
+ wg.call 1,2
26
+ wg
27
+ end
28
+ end
29
+
30
+ def invoke!(*args, &block)
31
+ capture(:stdout){ invoker.directory(*args, &block) }
32
+ end
33
+
34
+ def revoke!(*args, &block)
35
+ capture(:stdout){ revoker.directory(*args, &block) }
36
+ end
37
+
38
+ def exists_and_identical?(source_path, destination_path)
39
+ %w(config.rb README).each do |file|
40
+ source = File.join(source_root, source_path, file)
41
+ destination = File.join(destination_root, destination_path, file)
42
+
43
+ assert File.exists?(destination)
44
+ assert FileUtils.identical?(source, destination)
45
+ end
46
+ end
47
+
48
+ describe "#invoke!" do
49
+
50
+ before { reset }
51
+
52
+ it "raises an error if the source does not exist" do
53
+ assert_match(
54
+ /Could not find "unknown" in any of your source paths/,
55
+ assert_raises(Ing::FileNotFoundError) { invoke! "unknown" }.message
56
+ )
57
+ end
58
+
59
+ it "should not create a directory in pretend mode" do
60
+ invoke! "doc", "ghost", :pretend => true
61
+ refute File.exists?("ghost")
62
+ end
63
+
64
+ it "copies the whole directory recursively to the default destination" do
65
+ invoke! "doc"
66
+ exists_and_identical?("doc", "doc")
67
+ end
68
+
69
+ it "copies the whole directory recursively to the specified destination" do
70
+ invoke! "doc", "docs"
71
+ exists_and_identical?("doc", "docs")
72
+ end
73
+
74
+ it "copies only the first level files if not recursive" do
75
+ invoke! ".", "tasks", :recursive => false
76
+
77
+ file = File.join(destination_root, "tasks", "group.ing.rb")
78
+ assert File.exists?(file)
79
+
80
+ file = File.join(destination_root, "tasks", "doc")
81
+ refute File.exists?(file)
82
+
83
+ file = File.join(destination_root, "tasks", "doc", "README")
84
+ refute File.exists?(file)
85
+ end
86
+
87
+ it "copies files from the source relative to the current path" do
88
+ invoker.inside "doc" do
89
+ invoke! "."
90
+ end
91
+ exists_and_identical?("doc", "doc")
92
+ end
93
+
94
+ it "copies and evaluates templates" do
95
+ invoke! "doc", "docs"
96
+ file = File.join(destination_root, "docs", "rdoc.rb")
97
+ assert File.exists?(file)
98
+ assert_equal "FOO = FOO\n", File.read(file)
99
+ end
100
+
101
+ it "copies directories" do
102
+ invoke! "doc", "docs"
103
+ file = File.join(destination_root, "docs", "components")
104
+ assert File.exists?(file)
105
+ assert File.directory?(file)
106
+ end
107
+
108
+ it "does not copy .empty_directory files" do
109
+ invoke! "doc", "docs"
110
+ file = File.join(destination_root, "docs", "components", ".empty_directory")
111
+ refute File.exists?(file)
112
+ end
113
+
114
+ it "copies directories even if they are empty" do
115
+ invoke! "doc/components", "docs/components"
116
+ file = File.join(destination_root, "docs", "components")
117
+ assert File.exists?(file)
118
+ end
119
+
120
+ it "does not copy empty directories twice" do
121
+ content = invoke!("doc/components", "docs/components")
122
+ refute_match(/exist/, content)
123
+ end
124
+
125
+ it "logs status" do
126
+ content = invoke!("doc")
127
+ assert_match(/create doc\/README/, content)
128
+ assert_match(/create doc\/config\.rb/, content)
129
+ assert_match(/create doc\/rdoc\.rb/, content)
130
+ assert_match(/create doc\/components/, content)
131
+ end
132
+
133
+ it "yields a block" do
134
+ checked = false
135
+ invoke!("doc") do |content|
136
+ checked ||= !!(content =~ /FOO/)
137
+ end
138
+ assert checked
139
+ end
140
+
141
+ it "works with glob characters in the path" do
142
+ content = invoke!("app{1}")
143
+ assert_match(/create app\{1\}\/README/, content)
144
+ end
145
+ end
146
+
147
+ describe "#revoke!" do
148
+ before { reset }
149
+
150
+ it "removes the destination file" do
151
+ invoke! "doc"
152
+ revoke! "doc"
153
+
154
+ refute File.exists?(File.join(destination_root, "doc", "README"))
155
+ refute File.exists?(File.join(destination_root, "doc", "config.rb"))
156
+ refute File.exists?(File.join(destination_root, "doc", "components"))
157
+ end
158
+
159
+ it "works with glob characters in the path" do
160
+ invoke! "app{1}"
161
+ assert File.exists?(File.join(destination_root, "app{1}", "README"))
162
+
163
+ revoke! "app{1}"
164
+ refute File.exists?(File.join(destination_root, "app{1}", "README"))
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,146 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ require File.expand_path("../../lib/ing/files", File.dirname(__FILE__))
3
+
4
+ describe Ing::Files::EmptyDirectory do
5
+ include SpecHelpers
6
+
7
+ def reset
8
+ ::FileUtils.rm_rf(destination_root)
9
+ end
10
+
11
+ def empty_directory(destination, options={})
12
+ @action = Ing::Files::EmptyDirectory.new(base, destination)
13
+ end
14
+
15
+ def invoke!
16
+ capture(:stdout){ @action.invoke! }
17
+ end
18
+
19
+ def revoke!
20
+ capture(:stdout){ @action.revoke! }
21
+ end
22
+
23
+ def base
24
+ @base ||= begin
25
+ x = MyCounter.new({})
26
+ x.destination_root = destination_root
27
+ x.call 1,2
28
+ x
29
+ end
30
+
31
+ end
32
+
33
+ describe "#destination" do
34
+ before { reset }
35
+ it "returns the full destination with the destination_root" do
36
+ assert_equal File.join(destination_root, 'doc'), empty_directory('doc').destination
37
+ end
38
+
39
+ it "takes relative root into account" do
40
+ base.inside('doc') do
41
+ assert_equal File.join(destination_root, 'doc', 'contents'), empty_directory('contents').destination
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#relative_destination" do
47
+ before { reset }
48
+ it "returns the relative destination to the original destination root" do
49
+ base.inside('doc') do
50
+ assert_equal 'doc/contents', empty_directory('contents').relative_destination
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "#given_destination" do
56
+ before { reset }
57
+ it "returns the destination supplied by the user" do
58
+ base.inside('doc') do
59
+ assert_equal 'contents', empty_directory('contents').given_destination
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#invoke!" do
65
+ before { reset }
66
+ it "copies the file to the specified destination" do
67
+ empty_directory("doc")
68
+ invoke!
69
+ assert File.exists?(File.join(destination_root, "doc"))
70
+ end
71
+
72
+ it "shows created status to the user" do
73
+ empty_directory("doc")
74
+ assert_equal " create doc\n", invoke!
75
+ end
76
+
77
+ it "does not create a directory if pretending" do
78
+ base.inside("foo", :pretend => true) do
79
+ empty_directory("ghost")
80
+ end
81
+ refute File.exists?(File.join(base.destination_root, "ghost"))
82
+ end
83
+
84
+ describe "when directory exists" do
85
+ it "shows exist status" do
86
+ empty_directory("doc")
87
+ invoke!
88
+ assert_equal " exist doc\n", invoke!
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "#revoke!" do
94
+ before { reset }
95
+ it "removes the destination file" do
96
+ empty_directory("doc")
97
+ invoke!
98
+ revoke!
99
+ refute File.exists?(@action.destination)
100
+ end
101
+ end
102
+
103
+ describe "#exists?" do
104
+ before { reset }
105
+ it "returns true if the destination file exists" do
106
+ empty_directory("doc")
107
+ refute @action.exists?
108
+ invoke!
109
+ assert @action.exists?
110
+ end
111
+ end
112
+
113
+ describe "protected methods" do
114
+ describe "#convert_encoded_instructions" do
115
+ before do
116
+ reset
117
+ empty_directory("test_dir")
118
+ @action.base.class.send :define_method, :file_name, Proc.new{"expected"}
119
+ end
120
+
121
+ it "accepts and executes a 'legal' %\w+% encoded instruction" do
122
+ assert_equal "expected.txt",
123
+ @action.send(:convert_encoded_instructions, "%file_name%.txt")
124
+ end
125
+
126
+ it "ignores an 'illegal' %\w+% encoded instruction" do
127
+ assert_equal "%some_name%.txt", @action.send(:convert_encoded_instructions, "%some_name%.txt")
128
+ end
129
+
130
+ it "ignores incorrectly encoded instruction" do
131
+ assert_equal "%some.name%.txt", @action.send(:convert_encoded_instructions, "%some.name%.txt")
132
+ end
133
+
134
+ it "raises an error if the instruction refers to a private method" do
135
+ module PrivExt
136
+ private
137
+ def private_file_name
138
+ "something_hidden"
139
+ end
140
+ end
141
+ @action.base.extend(PrivExt)
142
+ assert_raises(NoMethodError) { @action.send(:convert_encoded_instructions, "%private_file_name%.txt") }
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,433 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ require File.expand_path("../../lib/ing/files", File.dirname(__FILE__))
3
+
4
+ class Application; end
5
+
6
+ describe Ing::Files do
7
+ include SpecHelpers
8
+
9
+ def reset
10
+ ::FileUtils.rm_rf(destination_root)
11
+ end
12
+
13
+ def runner(options={})
14
+ @runner ||= begin
15
+ r = MyCounter.new(options)
16
+ r.destination_root = destination_root
17
+ r.call 1
18
+ r
19
+ end
20
+ end
21
+
22
+ def action(*args, &block)
23
+ capture(:stdout){ runner.send(*args, &block) }
24
+ end
25
+
26
+ def exists_and_identical?(source, destination)
27
+ destination = File.join(destination_root, destination)
28
+ assert File.exists?(destination)
29
+
30
+ source = File.join(source_root, source)
31
+ assert FileUtils.identical?(source, destination)
32
+ end
33
+
34
+ def file
35
+ File.join(destination_root, "foo")
36
+ end
37
+
38
+ describe "#chmod" do
39
+ before { reset }
40
+
41
+ # A bit hacky. But really FileUtils method should not be mocked.
42
+ def expecting_chmod(*expected_args)
43
+ saved = FileUtils
44
+ m = MiniTest::Mock.new; m.expect(:chmod_R, nil, expected_args)
45
+ Object.const_set("FileUtils", m)
46
+ yield m
47
+ ensure
48
+ Object.const_set("FileUtils", saved)
49
+ end
50
+
51
+ it "executes the command given" do
52
+ expecting_chmod(0755, file) do
53
+ action :chmod, "foo", 0755
54
+ end
55
+ end
56
+
57
+ ### Stupid test of implementation not behavior, I'm taking it out
58
+ # it "does not execute the command if pretending given" do
59
+ # FileUtils.should_not_receive(:chmod_R)
60
+ # runner(:pretend => true)
61
+ # action :chmod, "foo", 0755
62
+ # end
63
+
64
+ it "logs status" do
65
+ expecting_chmod(0755, file) do
66
+ log = action(:chmod, "foo", 0755)
67
+ assert_equal " chmod foo\n", log
68
+ end
69
+ end
70
+
71
+ it "does not log status if required" do
72
+ expecting_chmod(0755, file) do
73
+ log = action(:chmod, "foo", 0755, :verbose => false)
74
+ assert log.empty?
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "#copy_file" do
80
+ before { reset }
81
+
82
+ it "copies file from source to default destination" do
83
+ action :copy_file, "task.thor"
84
+ exists_and_identical?("task.thor", "task.thor")
85
+ end
86
+
87
+ it "copies file from source to the specified destination" do
88
+ action :copy_file, "task.thor", "foo.thor"
89
+ exists_and_identical?("task.thor", "foo.thor")
90
+ end
91
+
92
+ it "copies file from the source relative to the current path" do
93
+ runner.inside("doc") do
94
+ action :copy_file, "README"
95
+ end
96
+ exists_and_identical?("doc/README", "doc/README")
97
+ end
98
+
99
+ it "logs status" do
100
+ assert_equal " create task.thor\n", action(:copy_file, "task.thor")
101
+ end
102
+
103
+ it "accepts a block to change output" do
104
+ action :copy_file, "task.thor" do |content|
105
+ "OMG" + content
106
+ end
107
+ assert_match(/^OMG/, File.read(File.join(destination_root, "task.thor")))
108
+ end
109
+ end
110
+
111
+ describe "#link_file" do
112
+ before { reset }
113
+
114
+ it "links file from source to default destination" do
115
+ action :link_file, "task.thor"
116
+ exists_and_identical?("task.thor", "task.thor")
117
+ end
118
+
119
+ it "links file from source to the specified destination" do
120
+ action :link_file, "task.thor", "foo.thor"
121
+ exists_and_identical?("task.thor", "foo.thor")
122
+ end
123
+
124
+ it "links file from the source relative to the current path" do
125
+ runner.inside("doc") do
126
+ action :link_file, "README"
127
+ end
128
+ exists_and_identical?("doc/README", "doc/README")
129
+ end
130
+
131
+ it "logs status" do
132
+ assert_equal " create task.thor\n", action(:link_file, "task.thor")
133
+ end
134
+ end
135
+
136
+ describe "#get" do
137
+ before { reset }
138
+
139
+ it "copies file from source to the specified destination" do
140
+ action :get, "doc/README", "docs/README"
141
+ exists_and_identical?("doc/README", "docs/README")
142
+ end
143
+
144
+ it "uses just the source basename as destination if none is specified" do
145
+ action :get, "doc/README"
146
+ exists_and_identical?("doc/README", "README")
147
+ end
148
+
149
+ it "allows the destination to be set as a block result" do
150
+ action(:get, "doc/README"){ |c| "docs/README" }
151
+ exists_and_identical?("doc/README", "docs/README")
152
+ end
153
+
154
+ it "yields file content to a block" do
155
+ action :get, "doc/README" do |content|
156
+ assert_equal "__start__\nREADME\n__end__\n", content
157
+ end
158
+ end
159
+
160
+ it "logs status" do
161
+ assert_equal " create docs/README\n", action(:get, "doc/README", "docs/README")
162
+ end
163
+
164
+ it "accepts http remote sources" do
165
+ body = "__start__\nHTTPFILE\n__end__\n"
166
+ FakeWeb.register_uri(:get, 'http://example.com/file.txt', :body => body)
167
+ action :get, 'http://example.com/file.txt' do |content|
168
+ assert_equal body, content
169
+ end
170
+ FakeWeb.clean_registry
171
+ end
172
+
173
+ it "accepts https remote sources" do
174
+ body = "__start__\nHTTPSFILE\n__end__\n"
175
+ FakeWeb.register_uri(:get, 'https://example.com/file.txt', :body => body)
176
+ action :get, 'https://example.com/file.txt' do |content|
177
+ assert_equal body, content
178
+ end
179
+ FakeWeb.clean_registry
180
+ end
181
+ end
182
+
183
+ describe "#template" do
184
+ before { reset }
185
+
186
+ it "allows using block helpers in the template" do
187
+ action :template, "doc/block_helper.rb"
188
+
189
+ file = File.join(destination_root, "doc/block_helper.rb")
190
+ assert_equal "Hello world!", File.read(file)
191
+ end
192
+
193
+ it "evaluates the template given as source" do
194
+ runner.instance_variable_set("@klass", "Config")
195
+ action :template, "doc/config.rb"
196
+
197
+ file = File.join(destination_root, "doc/config.rb")
198
+ assert_equal "class Config; end\n", File.read(file)
199
+ end
200
+
201
+ it "copies the template to the specified destination" do
202
+ action :template, "doc/config.rb", "doc/configuration.rb"
203
+ file = File.join(destination_root, "doc/configuration.rb")
204
+ assert File.exists?(file)
205
+ end
206
+
207
+ it "converts enconded instructions" do
208
+ runner.class.send(:define_method, :file_name, Proc.new {"rdoc"})
209
+ action :template, "doc/%file_name%.rb.tt"
210
+ file = File.join(destination_root, "doc/rdoc.rb")
211
+ assert File.exists?(file)
212
+ end
213
+
214
+ it "logs status" do
215
+ assert_equal " create doc/config.rb\n", capture(:stdout){ runner.template("doc/config.rb") }
216
+ end
217
+
218
+ it "accepts a block to change output" do
219
+ action :template, "doc/config.rb" do |content|
220
+ "OMG" + content
221
+ end
222
+ assert_match(/^OMG/, File.read(File.join(destination_root, "doc/config.rb")))
223
+ end
224
+
225
+ it "guesses the destination name when given only a source" do
226
+ action :template, "doc/config.yaml.tt"
227
+
228
+ file = File.join(destination_root, "doc/config.yaml")
229
+ assert File.exists?(file)
230
+ end
231
+ end
232
+
233
+ describe "when changing existent files" do
234
+
235
+ def file
236
+ File.join(destination_root, "doc", "README")
237
+ end
238
+
239
+ describe "#remove_file" do
240
+ before do
241
+ reset
242
+ ::FileUtils.cp_r(source_root, destination_root)
243
+ end
244
+
245
+ it "removes the file given" do
246
+ action :remove_file, "doc/README"
247
+ refute File.exists?(file)
248
+ end
249
+
250
+ it "removes directories too" do
251
+ action :remove_dir, "doc"
252
+ refute File.exists?(File.join(destination_root, "doc"))
253
+ end
254
+
255
+ it "does not remove if pretending" do
256
+ runner(:pretend => true)
257
+ action :remove_file, "doc/README"
258
+ assert File.exists?(file)
259
+ end
260
+
261
+ it "logs status" do
262
+ assert_equal " remove doc/README\n", action(:remove_file, "doc/README")
263
+ end
264
+
265
+ it "does not log status if required" do
266
+ assert action(:remove_file, "doc/README", :verbose => false).empty?
267
+ end
268
+ end
269
+
270
+ describe "#gsub_file" do
271
+ before do
272
+ reset
273
+ ::FileUtils.cp_r(source_root, destination_root)
274
+ end
275
+
276
+ it "replaces the content in the file" do
277
+ action :gsub_file, "doc/README", "__start__", "START"
278
+ assert_equal "START\nREADME\n__end__\n", File.binread(file)
279
+ end
280
+
281
+ it "does not replace if pretending" do
282
+ runner(:pretend => true)
283
+ action :gsub_file, "doc/README", "__start__", "START"
284
+ assert_equal "__start__\nREADME\n__end__\n", File.binread(file)
285
+ end
286
+
287
+ it "accepts a block" do
288
+ action(:gsub_file, "doc/README", "__start__"){ |match| match.gsub('__', '').upcase }
289
+ assert_equal "START\nREADME\n__end__\n", File.binread(file)
290
+ end
291
+
292
+ it "logs status" do
293
+ assert_equal " gsub doc/README\n", action(:gsub_file, "doc/README", "__start__", "START")
294
+ end
295
+
296
+ it "does not log status if required" do
297
+ assert action(:gsub_file, file, "__", :verbose => false){ |match| match * 2 }.empty?
298
+ end
299
+ end
300
+
301
+ describe "#append_to_file" do
302
+ before do
303
+ reset
304
+ ::FileUtils.cp_r(source_root, destination_root)
305
+ end
306
+
307
+ it "appends content to the file" do
308
+ action :append_to_file, "doc/README", "END\n"
309
+ assert_equal "__start__\nREADME\n__end__\nEND\n", File.binread(file)
310
+ end
311
+
312
+ it "accepts a block" do
313
+ action(:append_to_file, "doc/README"){ "END\n" }
314
+ assert_equal "__start__\nREADME\n__end__\nEND\n", File.binread(file)
315
+ end
316
+
317
+ it "logs status" do
318
+ assert_equal " append doc/README\n", action(:append_to_file, "doc/README", "END")
319
+ end
320
+ end
321
+
322
+ describe "#prepend_to_file" do
323
+ before do
324
+ reset
325
+ ::FileUtils.cp_r(source_root, destination_root)
326
+ end
327
+
328
+ it "prepends content to the file" do
329
+ action :prepend_to_file, "doc/README", "START\n"
330
+ assert_equal "START\n__start__\nREADME\n__end__\n", File.binread(file)
331
+ end
332
+
333
+ it "accepts a block" do
334
+ action(:prepend_to_file, "doc/README"){ "START\n" }
335
+ assert_equal "START\n__start__\nREADME\n__end__\n", File.binread(file)
336
+ end
337
+
338
+ it "logs status" do
339
+ assert_equal " prepend doc/README\n", action(:prepend_to_file, "doc/README", "START")
340
+ end
341
+ end
342
+
343
+ describe "#inject_into_class" do
344
+ before do
345
+ reset
346
+ ::FileUtils.cp_r(source_root, destination_root)
347
+ end
348
+
349
+ def file
350
+ File.join(destination_root, "application.rb")
351
+ end
352
+
353
+ it "appends content to a class" do
354
+ action :inject_into_class, "application.rb", Application, " filter_parameters :password\n"
355
+ assert_equal "class Application < Base\n filter_parameters :password\nend\n", File.binread(file)
356
+ end
357
+
358
+ it "accepts a block" do
359
+ action(:inject_into_class, "application.rb", Application){ " filter_parameters :password\n" }
360
+ assert_equal "class Application < Base\n filter_parameters :password\nend\n", File.binread(file)
361
+ end
362
+
363
+ it "logs status" do
364
+ assert_equal " insert application.rb\n", action(:inject_into_class, "application.rb", Application, " filter_parameters :password\n")
365
+ end
366
+
367
+ it "does not append if class name does not match" do
368
+ action :inject_into_class, "application.rb", "App", " filter_parameters :password\n"
369
+ assert_equal "class Application < Base\nend\n", File.binread(file)
370
+ end
371
+ end
372
+ end
373
+
374
+ describe "when adjusting comments" do
375
+
376
+ def file
377
+ File.join(destination_root, "doc", "COMMENTER")
378
+ end
379
+
380
+ unmodified_comments_file = /__start__\n # greenblue\n# yellowblue\n#yellowred\n #greenred\norange\n purple\n ind#igo\n # ind#igo\n__end__/
381
+
382
+ describe "#uncomment_lines" do
383
+ before do
384
+ reset
385
+ ::FileUtils.cp_r(source_root, destination_root)
386
+ end
387
+
388
+ it "uncomments all matching lines in the file" do
389
+ action :uncomment_lines, "doc/COMMENTER", "green"
390
+ assert_match(/__start__\n greenblue\n# yellowblue\n#yellowred\n greenred\norange\n purple\n ind#igo\n # ind#igo\n__end__/, File.binread(file))
391
+
392
+ action :uncomment_lines, "doc/COMMENTER", "red"
393
+ assert_match(/__start__\n greenblue\n# yellowblue\nyellowred\n greenred\norange\n purple\n ind#igo\n # ind#igo\n__end__/, File.binread(file))
394
+ end
395
+
396
+ it "correctly uncomments lines with hashes in them" do
397
+ action :uncomment_lines, "doc/COMMENTER", "ind#igo"
398
+ assert_match(/__start__\n # greenblue\n# yellowblue\n#yellowred\n #greenred\norange\n purple\n ind#igo\n ind#igo\n__end__/, File.binread(file))
399
+ end
400
+
401
+ it "does not modify already uncommented lines in the file" do
402
+ action :uncomment_lines, "doc/COMMENTER", "orange"
403
+ action :uncomment_lines, "doc/COMMENTER", "purple"
404
+ assert_match(unmodified_comments_file, File.binread(file))
405
+ end
406
+ end
407
+
408
+ describe "#comment_lines" do
409
+ before do
410
+ reset
411
+ ::FileUtils.cp_r(source_root, destination_root)
412
+ end
413
+
414
+ it "comments lines which are not commented" do
415
+ action :comment_lines, "doc/COMMENTER", "orange"
416
+ assert_match(/__start__\n # greenblue\n# yellowblue\n#yellowred\n #greenred\n# orange\n purple\n ind#igo\n # ind#igo\n__end__/, File.binread(file))
417
+
418
+ action :comment_lines, "doc/COMMENTER", "purple"
419
+ assert_match(/__start__\n # greenblue\n# yellowblue\n#yellowred\n #greenred\n# orange\n # purple\n ind#igo\n # ind#igo\n__end__/, File.binread(file))
420
+ end
421
+
422
+ it "correctly comments lines with hashes in them" do
423
+ action :comment_lines, "doc/COMMENTER", "ind#igo"
424
+ assert_match(/__start__\n # greenblue\n# yellowblue\n#yellowred\n #greenred\norange\n purple\n # ind#igo\n # ind#igo\n__end__/, File.binread(file))
425
+ end
426
+
427
+ it "does not modify already commented lines" do
428
+ action :comment_lines, "doc/COMMENTER", "green"
429
+ assert_match(unmodified_comments_file, File.binread(file))
430
+ end
431
+ end
432
+ end
433
+ end