ing 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,3 @@
1
+ module Ing
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,30 @@
1
+ # patch to access captures in gsub_file
2
+ # https://github.com/kentaroi/thor/commit/46b6d0b18a58eb8f7586e57eb633e96664fb1722
3
+ #
4
+ class Thor
5
+ module Actions
6
+
7
+ def gsub_file(path, flag, *args, &block)
8
+ return unless behavior == :invoke
9
+ config = args.last.is_a?(Hash) ? args.pop : {}
10
+
11
+ path = File.expand_path(path, destination_root)
12
+ say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
13
+
14
+ unless options[:pretend]
15
+ content = File.binread(path)
16
+ if block
17
+ if block.arity == 1
18
+ content.gsub!(flag, *args) { block.call($&) }
19
+ else
20
+ content.gsub!(flag, *args) { block.call(*$~) }
21
+ end
22
+ else
23
+ content.gsub!(flag, *args)
24
+ end
25
+ File.open(path, 'wb') { |file| file.write(content) }
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,44 @@
1
+ # monkey patch for better ask behavior
2
+
3
+ class Thor
4
+ module Shell
5
+ class Basic
6
+
7
+ def ask(statement, *args)
8
+ options = args.last.is_a?(Hash) ? args.pop : {}
9
+ color = args.pop
10
+ default = options[:default]
11
+ if options[:limited_to]
12
+ ask_filtered(statement, options[:limited_to], color, default)
13
+ else
14
+ ask_simply(statement, color, default)
15
+ end
16
+ end
17
+
18
+ def yes?(statement, *args)
19
+ !!(ask(statement, *args) =~ is?(:yes))
20
+ end
21
+
22
+ protected
23
+
24
+
25
+ def ask_simply(statement, color=nil, default=nil)
26
+ say("#{statement} #{default ? '(default ' + default + ')' : nil} ", color)
27
+ input = stdin.gets.strip
28
+ input.empty? ? default : input
29
+ end
30
+
31
+ def ask_filtered(statement, answer_set, color=nil, default=nil)
32
+ correct_answer = nil
33
+ until correct_answer
34
+ answer = ask_simply("#{statement} #{answer_set.inspect}", color, default)
35
+ correct_answer = answer_set.include?(answer) ? answer : nil
36
+ answers = answer_set.map(&:inspect).join(", ")
37
+ say("Your response must be one of: [#{answers}]. Please try again.") unless correct_answer
38
+ end
39
+ correct_answer
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,164 @@
1
+ require File.expand_path('../test_helper', File.dirname(__FILE__))
2
+
3
+ describe Ing do
4
+ include TestHelpers
5
+
6
+ def capture_run(args)
7
+ capture(:stdout) { Ing.run args }
8
+ end
9
+
10
+ def reset
11
+ Ing::Dispatcher.dispatched.clear
12
+ end
13
+
14
+ describe "#run" do
15
+
16
+ describe "no method or args given" do
17
+ before { reset }
18
+ subject { ["count_args"] }
19
+
20
+ it 'should run with expected output' do
21
+ assert_equal "CountArgs called with 0 args",
22
+ capture_run(subject).chomp
23
+ end
24
+
25
+ end
26
+
27
+ describe "method given with args" do
28
+ before { reset }
29
+ subject { ["amazing", "describe", "Malcolm"] }
30
+
31
+ it 'should run with expected output' do
32
+ assert_equal "Malcolm is amazing", capture_run(subject).chomp
33
+ end
34
+
35
+ end
36
+
37
+ describe "option args given" do
38
+ before { reset }
39
+ subject { ["amazing", "describe", "--forcefully", "Malcolm"] }
40
+
41
+ it 'should run with expected output' do
42
+ assert_equal "MALCOLM IS AMAZING", capture_run(subject).chomp
43
+ end
44
+
45
+ describe "and option args given at end" do
46
+ before { reset }
47
+ subject { ["amazing", "describe", "Malcolm", "--forcefully"] }
48
+
49
+ it 'should run with expected output' do
50
+ assert_equal "MALCOLM IS AMAZING", capture_run(subject).chomp
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ describe "unknown method given" do
57
+ before { reset }
58
+ subject { ["amazing", "write", "Malcolm"] }
59
+
60
+ it 'should raise error' do
61
+ assert_raises(::NoMethodError) { capture_run subject }
62
+ end
63
+
64
+ end
65
+
66
+ describe "undefined option given" do
67
+ before { reset }
68
+ subject { ["amazing", "describe", "Malcolm", "--times=3"] }
69
+
70
+ it 'should exit' do
71
+ assert_raises(::SystemExit) { capture_run(subject) }
72
+ end
73
+ end
74
+
75
+ describe "wrong number of args given" do
76
+ before { reset }
77
+ subject { ["amazing", "describe"] }
78
+
79
+ it 'should raise error' do
80
+ assert_raises(::ArgumentError) { capture_run subject }
81
+ end
82
+ end
83
+
84
+ describe "require boot option given" do
85
+ before { reset }
86
+ subject { ["-r", "./test/fixtures/require.ing",
87
+ "--require", "cgi",
88
+ "dynamic_require"
89
+ ]
90
+ }
91
+
92
+ it 'should load specified files and libraries' do
93
+ capture_run subject
94
+ DynamicRequire; CGI
95
+ assert true
96
+ end
97
+
98
+ end
99
+
100
+ describe "namespace boot option given" do
101
+ before { reset }
102
+ subject { ["--require=./test/fixtures/namespace.ing",
103
+ "-n", "some_base_namespace",
104
+ "one:two:three:echo", "call", "hello world"
105
+ ]
106
+ }
107
+
108
+ it 'should run with expected output' do
109
+ assert_equal "hello world", capture_run(subject).chomp
110
+ end
111
+
112
+ describe "and class not within namespace" do
113
+ before { reset }
114
+ subject { ["--require=./test/fixtures/namespace.ing",
115
+ "-n", "some_base_namespace",
116
+ "echo", "call", "hello world"
117
+ ]
118
+ }
119
+
120
+ it 'should raise error' do
121
+ assert_raises(::NameError) { capture_run(subject).chomp }
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ describe "dispatch to proc" do
129
+ before { reset }
130
+ subject { %w[p 1 2 3] }
131
+
132
+ P = lambda {|*args|
133
+ opts = (Hash === args.last ? args.pop : {})
134
+ args.reverse.each_with_index {|a,i| puts "#{i}:#{a}"}
135
+ }
136
+
137
+ it 'should run with expected output' do
138
+ log = capture_run(subject).chomp
139
+ assert_equal "0:3\n1:2\n2:1", log
140
+ end
141
+
142
+ end
143
+
144
+ end
145
+
146
+ describe "invoking within tasks" do
147
+ before { reset }
148
+ subject { ["invoking:counter", "one"] }
149
+
150
+ it 'should run with expected output' do
151
+ assert_equal "1\n2\n3\n", capture_run(subject)
152
+ end
153
+ end
154
+
155
+ describe "executing within tasks" do
156
+ before { reset }
157
+ subject { ["executing:counter", "one"] }
158
+
159
+ it 'should run with expected output' do
160
+ assert_equal "1\n2\n3\n3\n", capture_run(subject)
161
+ end
162
+ end
163
+
164
+ end
@@ -0,0 +1,209 @@
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::CreateFile do
5
+ include SpecHelpers
6
+
7
+ def reset
8
+ ARGV.replace []
9
+ ::FileUtils.rm_rf(destination_root)
10
+ end
11
+
12
+ def create_file(destination=nil, config={}, options={})
13
+ @base = MyCounter.new(options)
14
+ @base.destination_root = destination_root
15
+ @base.call 1,2
16
+ MyCounter.send(:define_method, :file_name, Proc.new {'rdoc'} )
17
+
18
+ @action = Ing::Files::CreateFile.new(@base, destination, "CONFIGURATION",
19
+ { :verbose => !@silence }.merge(config))
20
+ end
21
+
22
+ def invoke!
23
+ capture(:stdout){ @action.invoke! }
24
+ end
25
+
26
+ def revoke!
27
+ capture(:stdout){ @action.revoke! }
28
+ end
29
+
30
+ def silence!
31
+ @silence = true
32
+ end
33
+
34
+ # stubs multiple input responses from $stdin.gets
35
+ # not currently used
36
+ class StubInput
37
+
38
+ def initialize(expected)
39
+ @s = Array(expected)
40
+ end
41
+
42
+ def gets
43
+ @s.shift
44
+ end
45
+
46
+ def reply_for(stream=$stdin, &b)
47
+ stream.stub(:gets, self.method(:gets), &b)
48
+ end
49
+
50
+ end
51
+
52
+ describe "#invoke!" do
53
+ before { reset }
54
+
55
+ it "creates a file" do
56
+ create_file("doc/config.rb")
57
+ invoke!
58
+ assert File.exists?(File.join(destination_root, "doc/config.rb"))
59
+ end
60
+
61
+ it "does not create a file if pretending" do
62
+ create_file("doc/config.rb", {}, :pretend => true)
63
+ invoke!
64
+ refute File.exists?(File.join(destination_root, "doc/config.rb"))
65
+ end
66
+
67
+ it "shows created status to the user" do
68
+ create_file("doc/config.rb")
69
+ assert_equal " create doc/config.rb\n", invoke!
70
+ end
71
+
72
+ it "does not show any information if log status is false" do
73
+ silence!
74
+ create_file("doc/config.rb")
75
+ assert_empty invoke!
76
+ end
77
+
78
+ it "returns the given destination" do
79
+ capture(:stdout) do
80
+ assert_equal "doc/config.rb", create_file("doc/config.rb").invoke!
81
+ end
82
+ end
83
+
84
+ it "converts encoded instructions" do
85
+ create_file("doc/%file_name%.rb.tt")
86
+ invoke!
87
+ assert File.exists?(File.join(destination_root, "doc/rdoc.rb.tt"))
88
+ end
89
+
90
+ describe "when file exists" do
91
+
92
+ describe "and is identical" do
93
+ before do
94
+ reset
95
+ create_file("doc/config.rb")
96
+ invoke!
97
+ end
98
+
99
+ it "shows identical status" do
100
+ create_file("doc/config.rb")
101
+ invoke!
102
+ assert_equal " identical doc/config.rb\n", invoke!
103
+ end
104
+ end
105
+
106
+ describe "and is not identical" do
107
+ before do
108
+ reset
109
+ create_file("doc/config.rb")
110
+ invoke!
111
+ File.open(File.join(destination_root, 'doc/config.rb'), 'w'){ |f| f.write("FOO = 3") }
112
+ end
113
+
114
+ it "shows forced status to the user if force is given" do
115
+ refute create_file("doc/config.rb", {}, :force => true).identical?
116
+ assert_equal " force doc/config.rb\n", invoke!
117
+ end
118
+
119
+ it "shows skipped status to the user if skip is given" do
120
+ refute create_file("doc/config.rb", {}, :skip => true).identical?
121
+ assert_equal " skip doc/config.rb\n", invoke!
122
+ end
123
+
124
+ it "shows forced status to the user if force is configured" do
125
+ refute create_file("doc/config.rb", :force => true).identical?
126
+ assert_equal " force doc/config.rb\n", invoke!
127
+ end
128
+
129
+ it "shows skipped status to the user if skip is configured" do
130
+ refute create_file("doc/config.rb", :skip => true).identical?
131
+ assert_equal " skip doc/config.rb\n", invoke!
132
+ end
133
+
134
+ it "shows conflict status to ther user" do
135
+ refute create_file("doc/config.rb").identical?
136
+ file = File.join(destination_root, 'doc/config.rb')
137
+ content = nil
138
+ $stdin.stub(:gets,'s') do
139
+ content = invoke!
140
+ end
141
+ assert_match(/conflict doc\/config\.rb/, content)
142
+ assert_match(/Overwrite #{file}\? \(enter "h" for help\) \[Ynaqdh\]/, content)
143
+ assert_match(/skip doc\/config\.rb/, content)
144
+ end
145
+
146
+ it "creates the file if the file collision menu returns true" do
147
+ create_file("doc/config.rb")
148
+ $stdin.stub(:gets,'y') do
149
+ assert_match(/force doc\/config\.rb/, invoke!)
150
+ end
151
+ end
152
+
153
+ it "skips the file if the file collision menu returns false" do
154
+ create_file("doc/config.rb")
155
+ $stdin.stub(:gets,'n') do
156
+ assert_match(/skip doc\/config\.rb/, invoke!)
157
+ end
158
+ end
159
+
160
+ # Not sure how to do the mock method here without more flexible mocks....
161
+ # it "executes the block given to show file content" do
162
+ # create_file("doc/config.rb")
163
+ # $stdin.should_receive(:gets).and_return('d')
164
+ # $stdin.should_receive(:gets).and_return('n')
165
+ # @base.shell.should_receive(:system).with(/diff -u/)
166
+ # invoke!
167
+ # end
168
+
169
+ end
170
+ end
171
+ end
172
+
173
+ describe "#revoke!" do
174
+ before { reset }
175
+
176
+ it "removes the destination file" do
177
+ create_file("doc/config.rb")
178
+ invoke!
179
+ revoke!
180
+ refute File.exists?(@action.destination)
181
+ end
182
+
183
+ it "does not raise an error if the file does not exist" do
184
+ create_file("doc/config.rb")
185
+ revoke!
186
+ refute File.exists?(@action.destination)
187
+ end
188
+ end
189
+
190
+ describe "#exists?" do
191
+ before { reset }
192
+ it "returns true if the destination file exists" do
193
+ create_file("doc/config.rb")
194
+ refute @action.exists?
195
+ invoke!
196
+ assert @action.exists?
197
+ end
198
+ end
199
+
200
+ describe "#identical?" do
201
+ before { reset }
202
+ it "returns true if the destination file and is identical" do
203
+ create_file("doc/config.rb")
204
+ refute @action.identical?
205
+ invoke!
206
+ assert @action.identical?
207
+ end
208
+ end
209
+ end