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.
- data/.gitignore +5 -0
- data/GENERATORS.md +2 -0
- data/LICENSE +18 -0
- data/OPTIONS.md +2 -0
- data/README.md +251 -0
- data/TASKS.md +21 -0
- data/bin/ing +5 -0
- data/examples/rspec_convert.rb +102 -0
- data/ing.gemspec +29 -0
- data/ing.rb +102 -0
- data/lib/ing.rb +78 -0
- data/lib/ing/actions/create_file.rb +105 -0
- data/lib/ing/actions/create_link.rb +57 -0
- data/lib/ing/actions/directory.rb +98 -0
- data/lib/ing/actions/empty_directory.rb +155 -0
- data/lib/ing/actions/file_manipulation.rb +308 -0
- data/lib/ing/actions/inject_into_file.rb +109 -0
- data/lib/ing/commands/boot.rb +76 -0
- data/lib/ing/commands/generate.rb +64 -0
- data/lib/ing/commands/help.rb +87 -0
- data/lib/ing/commands/implicit.rb +59 -0
- data/lib/ing/commands/list.rb +108 -0
- data/lib/ing/dispatcher.rb +132 -0
- data/lib/ing/files.rb +190 -0
- data/lib/ing/lib_trollop.rb +782 -0
- data/lib/ing/shell.rb +390 -0
- data/lib/ing/trollop/parser.rb +17 -0
- data/lib/ing/util.rb +61 -0
- data/lib/ing/version.rb +3 -0
- data/lib/thor/actions/file_manipulation.rb +30 -0
- data/lib/thor/shell/basic.rb +44 -0
- data/test/acceptance/ing_run_tests.rb +164 -0
- data/test/actions/create_file_spec.rb +209 -0
- data/test/actions/create_link_spec.rb +90 -0
- data/test/actions/directory_spec.rb +167 -0
- data/test/actions/empty_directory_spec.rb +146 -0
- data/test/actions/file_manipulation_spec.rb +433 -0
- data/test/actions/inject_into_file_spec.rb +147 -0
- data/test/fixtures/application.rb +2 -0
- data/test/fixtures/app{1}/README +3 -0
- data/test/fixtures/bundle/execute.rb +6 -0
- data/test/fixtures/bundle/main.thor +1 -0
- data/test/fixtures/doc/%file_name%.rb.tt +1 -0
- data/test/fixtures/doc/COMMENTER +10 -0
- data/test/fixtures/doc/README +3 -0
- data/test/fixtures/doc/block_helper.rb +3 -0
- data/test/fixtures/doc/components/.empty_directory +0 -0
- data/test/fixtures/doc/config.rb +1 -0
- data/test/fixtures/doc/config.yaml.tt +1 -0
- data/test/fixtures/group.ing.rb +76 -0
- data/test/fixtures/invok.ing.rb +50 -0
- data/test/fixtures/namespace.ing.rb +52 -0
- data/test/fixtures/require.ing.rb +7 -0
- data/test/fixtures/task.ing.rb +36 -0
- data/test/fixtures/task.thor +10 -0
- data/test/spec_helper.rb +2 -0
- data/test/test_helper.rb +41 -0
- data/todo.yml +7 -0
- metadata +147 -0
data/lib/ing/version.rb
ADDED
@@ -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
|