linecook 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History +60 -0
- data/License.txt +22 -0
- data/README +98 -0
- data/bin/linecook +58 -0
- data/cookbook +0 -0
- data/lib/linecook/attributes.rb +22 -0
- data/lib/linecook/commands/command.rb +48 -0
- data/lib/linecook/commands/command_error.rb +6 -0
- data/lib/linecook/commands/env.rb +23 -0
- data/lib/linecook/commands/helper.rb +51 -0
- data/lib/linecook/commands/helpers.rb +28 -0
- data/lib/linecook/commands/init.rb +82 -0
- data/lib/linecook/commands/package.rb +39 -0
- data/lib/linecook/commands/vbox.rb +85 -0
- data/lib/linecook/commands.rb +6 -0
- data/lib/linecook/cookbook.rb +104 -0
- data/lib/linecook/helper.rb +117 -0
- data/lib/linecook/package.rb +197 -0
- data/lib/linecook/recipe.rb +103 -0
- data/lib/linecook/shell/posix.rb +145 -0
- data/lib/linecook/shell/test.rb +254 -0
- data/lib/linecook/shell/unix.rb +117 -0
- data/lib/linecook/shell/utils.rb +138 -0
- data/lib/linecook/shell.rb +11 -0
- data/lib/linecook/template.rb +111 -0
- data/lib/linecook/test/file_test.rb +77 -0
- data/lib/linecook/test/regexp_escape.rb +86 -0
- data/lib/linecook/test.rb +172 -0
- data/lib/linecook/utils.rb +53 -0
- data/lib/linecook/version.rb +8 -0
- data/lib/linecook.rb +6 -0
- data/templates/Gemfile +2 -0
- data/templates/README +90 -0
- data/templates/Rakefile +149 -0
- data/templates/_gitignore +5 -0
- data/templates/attributes/project_name.rb +4 -0
- data/templates/cookbook +9 -0
- data/templates/files/file.txt +1 -0
- data/templates/helpers/project_name/echo.erb +5 -0
- data/templates/project_name.gemspec +30 -0
- data/templates/recipes/project_name.rb +20 -0
- data/templates/scripts/project_name.yml +7 -0
- data/templates/templates/template.txt.erb +3 -0
- data/templates/vbox/setup/virtual_box +86 -0
- data/templates/vbox/ssh/id_rsa +27 -0
- data/templates/vbox/ssh/id_rsa.pub +1 -0
- metadata +166 -0
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'linecook/test'
|
2
|
+
|
3
|
+
module Linecook
|
4
|
+
module Shell
|
5
|
+
# A module for testing shell scripts.
|
6
|
+
#
|
7
|
+
# class ShellTestSample < Test::Unit::TestCase
|
8
|
+
# include Linecook::Test::Shell
|
9
|
+
#
|
10
|
+
# # these are the default sh_test options used
|
11
|
+
# # in tests like test_sh_command_alias
|
12
|
+
# self.sh_test_options = {
|
13
|
+
# :cmd_pattern => '% inspect_argv',
|
14
|
+
# :cmd => 'ruby -e "puts ARGV.inspect"'
|
15
|
+
# }
|
16
|
+
#
|
17
|
+
# def test_echo
|
18
|
+
# assert_equal "goodnight moon", sh("echo goodnight moon").strip
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def test_echo_using_sh_test
|
22
|
+
# sh_test %q{
|
23
|
+
# echo goodnight moon
|
24
|
+
# goodnight moon
|
25
|
+
# }
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# def test_sh_command_alias
|
29
|
+
# sh_test("% inspect_env") do |output|
|
30
|
+
# assert output !~ /NEW_ENV_VAR/
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# sh_test("NEW_ENV_VAR=blue % inspect_env") do |output|
|
34
|
+
# assert output =~ /NEW_ENV_VAR=blue/
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
module Test
|
40
|
+
include Linecook::Test
|
41
|
+
|
42
|
+
def setup
|
43
|
+
super
|
44
|
+
@notify_method_name = true
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sets the specified ENV variables and returns the *current* env.
|
48
|
+
# If replace is true, current ENV variables are replaced; otherwise
|
49
|
+
# the new env variables are simply added to the existing set.
|
50
|
+
def set_env(env={}, replace=false)
|
51
|
+
current_env = {}
|
52
|
+
ENV.each_pair do |key, value|
|
53
|
+
current_env[key] = value
|
54
|
+
end
|
55
|
+
|
56
|
+
ENV.clear if replace
|
57
|
+
|
58
|
+
env.each_pair do |key, value|
|
59
|
+
if value.nil?
|
60
|
+
ENV.delete(key)
|
61
|
+
else
|
62
|
+
ENV[key] = value
|
63
|
+
end
|
64
|
+
end if env
|
65
|
+
|
66
|
+
current_env
|
67
|
+
end
|
68
|
+
|
69
|
+
# Sets the specified ENV variables for the duration of the block.
|
70
|
+
# If replace is true, current ENV variables are replaced; otherwise
|
71
|
+
# the new env variables are simply added to the existing set.
|
72
|
+
#
|
73
|
+
# Returns the block return.
|
74
|
+
def with_env(env={}, replace=false)
|
75
|
+
current_env = nil
|
76
|
+
begin
|
77
|
+
current_env = set_env(env, replace)
|
78
|
+
yield
|
79
|
+
ensure
|
80
|
+
if current_env
|
81
|
+
set_env(current_env, true)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns true if the ENV variable 'VERBOSE' is true.
|
87
|
+
def verbose?
|
88
|
+
verbose = ENV['VERBOSE']
|
89
|
+
verbose && verbose =~ /^true$/i ? true : false
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns true if the ENV variable 'QUIET' is true or nil. If 'VERBOSE'
|
93
|
+
# and 'QUIET' are both set, verbose wins.
|
94
|
+
def quiet?
|
95
|
+
return false if verbose?
|
96
|
+
|
97
|
+
quiet = ENV['QUIET']
|
98
|
+
quiet.nil? || quiet =~ /^true$/i ? true : false
|
99
|
+
end
|
100
|
+
|
101
|
+
# Executes the command using IO.popen and returns the stdout content.
|
102
|
+
#
|
103
|
+
# ==== Note
|
104
|
+
# On Windows this method requires the {win32-popen3}[http://rubyforge.org/projects/win32utils]
|
105
|
+
# utility. If it is not available, it will have to be installed:
|
106
|
+
#
|
107
|
+
# % gem install win32-open3
|
108
|
+
#
|
109
|
+
def sh(cmd, options={})
|
110
|
+
if @notify_method_name && !quiet?
|
111
|
+
@notify_method_name = false
|
112
|
+
puts
|
113
|
+
puts method_name
|
114
|
+
end
|
115
|
+
|
116
|
+
original_cmd = cmd
|
117
|
+
if cmd_pattern = options[:cmd_pattern]
|
118
|
+
cmd = cmd.sub(cmd_pattern, options[:cmd].to_s)
|
119
|
+
end
|
120
|
+
|
121
|
+
start = Time.now
|
122
|
+
result = with_env(options[:env], options[:replace_env]) do
|
123
|
+
IO.popen(cmd) do |io|
|
124
|
+
yield(io) if block_given?
|
125
|
+
io.read
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
finish = Time.now
|
130
|
+
elapsed = "%.3f" % [finish-start]
|
131
|
+
puts " (#{elapsed}s) #{verbose? ? cmd : original_cmd}" unless quiet?
|
132
|
+
result
|
133
|
+
end
|
134
|
+
|
135
|
+
# Peforms a shell test. Shell tests execute the command and yield the
|
136
|
+
# $stdout result to the block for validation. The command is executed
|
137
|
+
# through sh, ie using IO.popen.
|
138
|
+
#
|
139
|
+
# Options provided to sh_test are merged with the sh_test_options set
|
140
|
+
# for the class.
|
141
|
+
#
|
142
|
+
# ==== Command Aliases
|
143
|
+
#
|
144
|
+
# The options allow specification of a command pattern that gets
|
145
|
+
# replaced with a command alias. Only the first instance of the command
|
146
|
+
# pattern is replaced. In addition, shell tests allow the expected result
|
147
|
+
# to be specified inline with the command. Used together, these allow
|
148
|
+
# multiple tests of a complex command to be specified easily:
|
149
|
+
#
|
150
|
+
# opts = {
|
151
|
+
# :cmd_pattern => '% argv_inspect',
|
152
|
+
# :cmd => 'ruby -e "puts ARGV.inspect"'
|
153
|
+
# }
|
154
|
+
#
|
155
|
+
# sh_test %Q{
|
156
|
+
# % argv_inspect goodnight moon
|
157
|
+
# ["goodnight", "moon"]
|
158
|
+
# }, opts
|
159
|
+
#
|
160
|
+
# sh_test %Q{
|
161
|
+
# % argv_inspect hello world
|
162
|
+
# ["hello", "world"]
|
163
|
+
# }, opts
|
164
|
+
#
|
165
|
+
# ==== Indents
|
166
|
+
#
|
167
|
+
# To improve the readability of tests, sh_test will lstrip each line in the
|
168
|
+
# expected output to the same degree as the command line. So for instance
|
169
|
+
# these all pass:
|
170
|
+
#
|
171
|
+
# sh_test %Q{
|
172
|
+
# % argv_inspect hello world
|
173
|
+
# ["hello", "world"]
|
174
|
+
# }, opts
|
175
|
+
#
|
176
|
+
# sh_test %Q{
|
177
|
+
# % argv_inspect hello world
|
178
|
+
# ["hello", "world"]
|
179
|
+
# }, opts
|
180
|
+
#
|
181
|
+
# sh_test %Q{
|
182
|
+
# % argv_inspect hello world
|
183
|
+
# ["hello", "world"]
|
184
|
+
# }, opts
|
185
|
+
#
|
186
|
+
# Turn off indent stripping by specifying :indent => false.
|
187
|
+
#
|
188
|
+
# ==== ENV variables
|
189
|
+
#
|
190
|
+
# Options may specify a hash of env variables that will be set in the
|
191
|
+
# subprocess.
|
192
|
+
#
|
193
|
+
# sh_test %Q{
|
194
|
+
# ruby -e "puts ENV['SAMPLE']"
|
195
|
+
# value
|
196
|
+
# }, :env => {'SAMPLE' => 'value'}
|
197
|
+
#
|
198
|
+
# Note it is better to specify env variables in this way rather than
|
199
|
+
# through the command trick 'VAR=value cmd ...', as that syntax does
|
200
|
+
# not work on Windows. As a point of interest, see
|
201
|
+
# http://gist.github.com/107363 for a demonstration of ENV
|
202
|
+
# variables being inherited by subprocesses.
|
203
|
+
#
|
204
|
+
def sh_test(cmd, options={})
|
205
|
+
options = sh_test_options.merge(options)
|
206
|
+
|
207
|
+
# strip indentiation if possible
|
208
|
+
if cmd =~ /\A(?:\s*?\n)?( *)(.*?\n)(.*)\z/m
|
209
|
+
indent, cmd, expected = $1, $2, $3
|
210
|
+
cmd.strip!
|
211
|
+
|
212
|
+
if indent.length > 0 && options[:indents]
|
213
|
+
expected.gsub!(/^ {0,#{indent.length}}/, '')
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
result = sh(cmd, options)
|
218
|
+
|
219
|
+
assert_equal(expected, result, cmd) if expected
|
220
|
+
yield(result) if block_given?
|
221
|
+
result
|
222
|
+
end
|
223
|
+
|
224
|
+
# Similar to sh_test, but matches the output against each of the
|
225
|
+
# regexps. A hash of sh options can be provided as the last argument;
|
226
|
+
# it will be merged with the default sh_test_options.
|
227
|
+
#
|
228
|
+
# The output is yielded to the block, if given, for further validation.
|
229
|
+
# Returns the sh output.
|
230
|
+
def sh_match(cmd, *regexps)
|
231
|
+
options = regexps.last.kind_of?(Hash) ? regexps.pop : {}
|
232
|
+
options = sh_test_options.merge(options)
|
233
|
+
result = sh(cmd, options)
|
234
|
+
|
235
|
+
regexps.each do |regexp|
|
236
|
+
assert_match regexp, result, cmd
|
237
|
+
end
|
238
|
+
yield(result) if block_given?
|
239
|
+
result
|
240
|
+
end
|
241
|
+
|
242
|
+
# Returns a hash of default sh_test options.
|
243
|
+
def sh_test_options
|
244
|
+
{
|
245
|
+
:cmd_pattern => '% ',
|
246
|
+
:cmd => '2>&1 ',
|
247
|
+
:indents => true,
|
248
|
+
:env => {},
|
249
|
+
:replace_env => false
|
250
|
+
}
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
# Generated by Linecook, do not edit.
|
4
|
+
module Linecook
|
5
|
+
module Shell
|
6
|
+
module Unix
|
7
|
+
require 'linecook/shell/posix'
|
8
|
+
include Posix
|
9
|
+
# :stopdoc:
|
10
|
+
CAT_LINE = __LINE__ + 2
|
11
|
+
CAT = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
12
|
+
cat<% sources.each do |source| %> "<%= source %>"<% end %>
|
13
|
+
END_OF_TEMPLATE
|
14
|
+
# :startdoc:
|
15
|
+
|
16
|
+
def cat(*sources)
|
17
|
+
eval(CAT, binding, __FILE__, CAT_LINE)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def _cat(*args, &block) # :nodoc:
|
22
|
+
capture { cat(*args, &block) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# :stopdoc:
|
26
|
+
CHMOD_LINE = __LINE__ + 2
|
27
|
+
CHMOD = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
28
|
+
<% if mode %>
|
29
|
+
chmod <%= mode %> "<%= target %>"
|
30
|
+
<% check_status %>
|
31
|
+
<% end %>
|
32
|
+
END_OF_TEMPLATE
|
33
|
+
# :startdoc:
|
34
|
+
|
35
|
+
def chmod(target, mode=nil)
|
36
|
+
eval(CHMOD, binding, __FILE__, CHMOD_LINE)
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def _chmod(*args, &block) # :nodoc:
|
41
|
+
capture { chmod(*args, &block) }
|
42
|
+
end
|
43
|
+
|
44
|
+
# :stopdoc:
|
45
|
+
CHOWN_LINE = __LINE__ + 2
|
46
|
+
CHOWN = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
47
|
+
<% if user || group %>
|
48
|
+
chown <%= user %>:<%= group %> "<%= target %>"
|
49
|
+
<% check_status %>
|
50
|
+
<% end %>
|
51
|
+
END_OF_TEMPLATE
|
52
|
+
# :startdoc:
|
53
|
+
|
54
|
+
def chown(target, user=nil, group=nil)
|
55
|
+
eval(CHOWN, binding, __FILE__, CHOWN_LINE)
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def _chown(*args, &block) # :nodoc:
|
60
|
+
capture { chown(*args, &block) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# :stopdoc:
|
64
|
+
ECHO_LINE = __LINE__ + 2
|
65
|
+
ECHO = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
66
|
+
echo '<%= args.join(" ") %>'
|
67
|
+
END_OF_TEMPLATE
|
68
|
+
# :startdoc:
|
69
|
+
|
70
|
+
# Echos input
|
71
|
+
def echo(*args)
|
72
|
+
eval(ECHO, binding, __FILE__, ECHO_LINE)
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def _echo(*args, &block) # :nodoc:
|
77
|
+
capture { echo(*args, &block) }
|
78
|
+
end
|
79
|
+
|
80
|
+
# :stopdoc:
|
81
|
+
LN_S_LINE = __LINE__ + 2
|
82
|
+
LN_S = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
83
|
+
ln -sf "<%= source %>" "<%= target %>"
|
84
|
+
<% check_status %>
|
85
|
+
|
86
|
+
END_OF_TEMPLATE
|
87
|
+
# :startdoc:
|
88
|
+
|
89
|
+
def ln_s(source, target)
|
90
|
+
eval(LN_S, binding, __FILE__, LN_S_LINE)
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def _ln_s(*args, &block) # :nodoc:
|
95
|
+
capture { ln_s(*args, &block) }
|
96
|
+
end
|
97
|
+
|
98
|
+
# :stopdoc:
|
99
|
+
RM_LINE = __LINE__ + 2
|
100
|
+
RM = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
101
|
+
<% only_if %Q{ls -l "#{path}"} do %>
|
102
|
+
rm <% if opts %><%= opts %> <% end %>"<%= path %>"
|
103
|
+
<% end %>
|
104
|
+
END_OF_TEMPLATE
|
105
|
+
# :startdoc:
|
106
|
+
|
107
|
+
def rm(path, opts=nil)
|
108
|
+
eval(RM, binding, __FILE__, RM_LINE)
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
|
112
|
+
def _rm(*args, &block) # :nodoc:
|
113
|
+
capture { rm(*args, &block) }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
# Generated by Linecook, do not edit.
|
4
|
+
module Linecook
|
5
|
+
module Shell
|
6
|
+
module Utils
|
7
|
+
require 'linecook/shell/posix'
|
8
|
+
include Posix
|
9
|
+
|
10
|
+
DEFAULT_SHELL_PATH = '/bin/sh'
|
11
|
+
DEFAULT_ENV_PATH = '/usr/bin/env'
|
12
|
+
|
13
|
+
TARGET_PATH = '$LINECOOK_DIR/%s'
|
14
|
+
|
15
|
+
attr_writer :shell_path
|
16
|
+
attr_writer :env_path
|
17
|
+
|
18
|
+
def shell_path
|
19
|
+
@shell_path ||= DEFAULT_SHELL_PATH
|
20
|
+
end
|
21
|
+
|
22
|
+
def env_path
|
23
|
+
@env_path ||= DEFAULT_ENV_PATH
|
24
|
+
end
|
25
|
+
|
26
|
+
def target_path(source_path)
|
27
|
+
TARGET_PATH % super(source_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def close
|
31
|
+
unless closed?
|
32
|
+
break_line " (#{target_name}) "
|
33
|
+
end
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
# :stopdoc:
|
38
|
+
BREAK_LINE_LINE = __LINE__ + 2
|
39
|
+
BREAK_LINE = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
40
|
+
<% n = (76 - comment.length)/2 %>
|
41
|
+
<%= "#" * n %><%= comment %><%= "#" * n %>
|
42
|
+
|
43
|
+
END_OF_TEMPLATE
|
44
|
+
# :startdoc:
|
45
|
+
|
46
|
+
def break_line(comment="")
|
47
|
+
eval(BREAK_LINE, binding, __FILE__, BREAK_LINE_LINE)
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def _break_line(*args, &block) # :nodoc:
|
52
|
+
capture { break_line(*args, &block) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# :stopdoc:
|
56
|
+
CHECK_STATUS_LINE = __LINE__ + 2
|
57
|
+
CHECK_STATUS = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
58
|
+
check_status <%= status %> $? $LINENO
|
59
|
+
END_OF_TEMPLATE
|
60
|
+
# :startdoc:
|
61
|
+
|
62
|
+
# Adds a check after a command that ensures the status is as indicated
|
63
|
+
def check_status(status=0)
|
64
|
+
eval(CHECK_STATUS, binding, __FILE__, CHECK_STATUS_LINE)
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def _check_status(*args, &block) # :nodoc:
|
69
|
+
capture { check_status(*args, &block) }
|
70
|
+
end
|
71
|
+
|
72
|
+
# :stopdoc:
|
73
|
+
CHECK_STATUS_FUNCTION_LINE = __LINE__ + 2
|
74
|
+
CHECK_STATUS_FUNCTION = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
75
|
+
function check_status { if [ $1 -ne $2 ]; then echo "[$2] $0:$3"; exit $2; fi }
|
76
|
+
END_OF_TEMPLATE
|
77
|
+
# :startdoc:
|
78
|
+
|
79
|
+
# Adds the check status function.
|
80
|
+
def check_status_function
|
81
|
+
eval(CHECK_STATUS_FUNCTION, binding, __FILE__, CHECK_STATUS_FUNCTION_LINE)
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def _check_status_function(*args, &block) # :nodoc:
|
86
|
+
capture { check_status_function(*args, &block) }
|
87
|
+
end
|
88
|
+
|
89
|
+
# :stopdoc:
|
90
|
+
SHEBANG_LINE = __LINE__ + 2
|
91
|
+
SHEBANG = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
92
|
+
#! <%= shell_path %>
|
93
|
+
|
94
|
+
<%= break_line %>
|
95
|
+
<%= check_status_function %>
|
96
|
+
|
97
|
+
export -f check_status
|
98
|
+
export LINECOOK_DIR=$(dirname $0)
|
99
|
+
export LINECOOK_OPTIONS=
|
100
|
+
|
101
|
+
while getopts bhvx opt
|
102
|
+
do
|
103
|
+
case $opt in
|
104
|
+
v) LINECOOK_OPTIONS="$LINECOOK_OPTIONS -v";;
|
105
|
+
x) LINECOOK_OPTIONS="$LINECOOK_OPTIONS -x";;
|
106
|
+
h) printf "Usage: %s: [-hvx]\n" $0
|
107
|
+
printf " -h prints this help\n"
|
108
|
+
printf " -v verbose (set -v)\n"
|
109
|
+
printf " -x xtrace (set -x)\n"
|
110
|
+
exit 0;;
|
111
|
+
?) printf "Usage: %s: [-hvx]\n" $0
|
112
|
+
exit 2;;
|
113
|
+
esac
|
114
|
+
done
|
115
|
+
|
116
|
+
set $LINECOOK_OPTIONS > /dev/null
|
117
|
+
<%= break_line " #{target_name} " %>
|
118
|
+
|
119
|
+
END_OF_TEMPLATE
|
120
|
+
# :startdoc:
|
121
|
+
|
122
|
+
# == Notes
|
123
|
+
|
124
|
+
# Use dev/null on set such that no options will not dump ENV into stdout.
|
125
|
+
|
126
|
+
def shebang(shell_path=DEFAULT_SHELL_PATH, env_path=DEFAULT_ENV_PATH)
|
127
|
+
@shell_path = shell_path
|
128
|
+
@env_path = env_path
|
129
|
+
eval(SHEBANG, binding, __FILE__, SHEBANG_LINE)
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
|
133
|
+
def _shebang(*args, &block) # :nodoc:
|
134
|
+
capture { shebang(*args, &block) }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'stringio'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Linecook
|
6
|
+
class Template
|
7
|
+
class << self
|
8
|
+
def build(template, locals, template_path=nil)
|
9
|
+
ERB.new(template).result(OpenStruct.new(locals).send(:binding))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :erbout
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@erbout = StringIO.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns self (not the underlying erbout storage that actually receives
|
20
|
+
# the output lines). In the ERB context, this method directs erb outputs
|
21
|
+
# to Template#concat and into the redirect mechanism.
|
22
|
+
def _erbout
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
# Sets the underlying erbout storage to input.
|
27
|
+
def _erbout=(input)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Concatenates the specified input to the underlying erbout storage.
|
31
|
+
def concat(input)
|
32
|
+
erbout << input
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def capture(strip=true)
|
37
|
+
current, redirect = erbout, StringIO.new
|
38
|
+
|
39
|
+
begin
|
40
|
+
@erbout = redirect
|
41
|
+
yield
|
42
|
+
ensure
|
43
|
+
@erbout = current
|
44
|
+
end
|
45
|
+
|
46
|
+
str = redirect.string
|
47
|
+
str.strip! if strip
|
48
|
+
str
|
49
|
+
end
|
50
|
+
|
51
|
+
def indent(indent=' ', &block)
|
52
|
+
capture(&block).split("\n").each do |line|
|
53
|
+
concat "#{indent}#{line}\n"
|
54
|
+
end
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def nest(*nestings)
|
59
|
+
options = nestings.last.kind_of?(Hash) ? nestings.pop : {}
|
60
|
+
indent = options[:indent] || " "
|
61
|
+
line_sep = options[:line_sep] || "\n"
|
62
|
+
|
63
|
+
content = capture { yield }
|
64
|
+
return content if nestings.empty?
|
65
|
+
|
66
|
+
depth = nestings.length
|
67
|
+
lines = [indent * depth + content.gsub(/#{line_sep}/, line_sep + indent * depth)]
|
68
|
+
|
69
|
+
nestings.reverse_each do |(start_line, end_line)|
|
70
|
+
depth -= 1
|
71
|
+
lines.unshift(indent * depth + start_line)
|
72
|
+
lines << (indent * depth + end_line)
|
73
|
+
end
|
74
|
+
|
75
|
+
concat lines.join(line_sep)
|
76
|
+
end
|
77
|
+
|
78
|
+
def rstrip(n=10)
|
79
|
+
yield if block_given?
|
80
|
+
|
81
|
+
pos = erbout.pos
|
82
|
+
n = pos if pos < n
|
83
|
+
start = pos - n
|
84
|
+
|
85
|
+
erbout.pos = start
|
86
|
+
tail = erbout.read(n).rstrip
|
87
|
+
|
88
|
+
erbout.pos = start
|
89
|
+
erbout.truncate start
|
90
|
+
|
91
|
+
tail.length == 0 && start > 0 ? rstrip(n * 2) : concat(tail)
|
92
|
+
end
|
93
|
+
|
94
|
+
def close
|
95
|
+
erbout.close unless closed?
|
96
|
+
self
|
97
|
+
end
|
98
|
+
|
99
|
+
def closed?
|
100
|
+
erbout.closed?
|
101
|
+
end
|
102
|
+
|
103
|
+
def result(&block)
|
104
|
+
instance_eval(&block) if block
|
105
|
+
|
106
|
+
erbout.flush
|
107
|
+
erbout.rewind
|
108
|
+
erbout.read
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Linecook
|
2
|
+
module Test
|
3
|
+
module FileTest
|
4
|
+
module ClassMethods
|
5
|
+
attr_accessor :class_dir
|
6
|
+
|
7
|
+
def self.extended(base)
|
8
|
+
# Infers the test directory from the calling file.
|
9
|
+
# 'some_class_test.rb' => 'some_class_test'
|
10
|
+
calling_file = caller[2].gsub(/:\d+(:in .*)?$/, "")
|
11
|
+
base.class_dir = calling_file.chomp(File.extname(calling_file))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module ModuleMethods
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def included(base)
|
19
|
+
base.extend base.kind_of?(Class) ? ClassMethods : ModuleMethods
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
extend ModuleMethods
|
25
|
+
|
26
|
+
attr_reader :user_dir
|
27
|
+
attr_reader :method_dir
|
28
|
+
|
29
|
+
def setup
|
30
|
+
super
|
31
|
+
@user_dir = Dir.pwd
|
32
|
+
@method_dir = File.expand_path(method_name, self.class.class_dir)
|
33
|
+
|
34
|
+
cleanup method_dir
|
35
|
+
FileUtils.mkdir_p method_dir
|
36
|
+
Dir.chdir method_dir
|
37
|
+
end
|
38
|
+
|
39
|
+
def teardown
|
40
|
+
Dir.chdir user_dir
|
41
|
+
|
42
|
+
unless ENV["KEEP_OUTPUTS"] == "true"
|
43
|
+
cleanup class_dir
|
44
|
+
end
|
45
|
+
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def cleanup(dir)
|
50
|
+
FileUtils.rm_r(dir) if File.exists?(dir)
|
51
|
+
end
|
52
|
+
|
53
|
+
def path(relative_path)
|
54
|
+
File.expand_path(relative_path, method_dir)
|
55
|
+
end
|
56
|
+
|
57
|
+
def prepare(relative_path)
|
58
|
+
target = path(relative_path)
|
59
|
+
|
60
|
+
target_dir = File.dirname(target)
|
61
|
+
FileUtils.mkdir_p(target_dir) unless File.exists?(target_dir)
|
62
|
+
|
63
|
+
target
|
64
|
+
end
|
65
|
+
|
66
|
+
def file(relative_path, &block)
|
67
|
+
target = prepare(relative_path)
|
68
|
+
block ? File.open(target, 'w', &block) : FileUtils.touch(target)
|
69
|
+
target
|
70
|
+
end
|
71
|
+
|
72
|
+
def class_dir
|
73
|
+
self.class.class_dir
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|