linecook 0.6.2
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/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,86 @@
|
|
1
|
+
module Linecook
|
2
|
+
module Test
|
3
|
+
# RegexpEscape is a subclass of regexp that escapes all but the text in a
|
4
|
+
# special escape sequence. This allows the creation of complex regexps
|
5
|
+
# to match, for instance, console output.
|
6
|
+
#
|
7
|
+
# The RegexpEscape.escape (or equivalently the quote) method does the
|
8
|
+
# work; all regexp-active characters are escaped except for characters
|
9
|
+
# enclosed by ':.' and '.:' delimiters.
|
10
|
+
#
|
11
|
+
# RegexpEscape.escape('reg[exp]+ chars. are(quoted)') # => 'reg\[exp\]\+\ chars\.\ are\(quoted\)'
|
12
|
+
# RegexpEscape.escape('these are not: :.a(b*)c.:') # => 'these\ are\ not:\ a(b*)c'
|
13
|
+
#
|
14
|
+
# In addition, all-period regexps are automatically upgraded to '.*?';
|
15
|
+
# use the '.{n}' notation to specify n arbitrary characters.
|
16
|
+
#
|
17
|
+
# RegexpEscape.escape('_:..:_:...:_:....:') # => '_.*?_.*?_.*?'
|
18
|
+
# RegexpEscape.escape(':..{1}.:') # => '.{1}'
|
19
|
+
#
|
20
|
+
# RegexpEscape instances are initialized using the escaped input string
|
21
|
+
# and return the original string upon to_s.
|
22
|
+
#
|
23
|
+
# str = %q{
|
24
|
+
# a multiline
|
25
|
+
# :...:
|
26
|
+
# example}
|
27
|
+
# r = RegexpEscape.new(str)
|
28
|
+
#
|
29
|
+
# r =~ %q{
|
30
|
+
# a multiline
|
31
|
+
# matching
|
32
|
+
# example} # => true
|
33
|
+
#
|
34
|
+
# r !~ %q{
|
35
|
+
# a failing multiline
|
36
|
+
# example} # => true
|
37
|
+
#
|
38
|
+
# r.to_s # => str
|
39
|
+
#
|
40
|
+
class RegexpEscape < Regexp
|
41
|
+
|
42
|
+
# matches the escape sequence
|
43
|
+
ESCAPE_SEQUENCE = /:\..*?\.:/
|
44
|
+
|
45
|
+
class << self
|
46
|
+
|
47
|
+
# Escapes regexp-active characters in str, except for character
|
48
|
+
# delimited by ':.' and '.:'. See the class description for
|
49
|
+
# details.
|
50
|
+
def escape(str)
|
51
|
+
substituents = []
|
52
|
+
str.scan(ESCAPE_SEQUENCE) do
|
53
|
+
regexp_str = $&[2...-2]
|
54
|
+
regexp_str = ".*?" if regexp_str =~ /^\.*$/
|
55
|
+
substituents << regexp_str
|
56
|
+
end
|
57
|
+
substituents << ""
|
58
|
+
|
59
|
+
splits = str.split(ESCAPE_SEQUENCE).collect do |split|
|
60
|
+
super(split)
|
61
|
+
end
|
62
|
+
splits << "" if splits.empty?
|
63
|
+
|
64
|
+
splits.zip(substituents).to_a.flatten.join
|
65
|
+
end
|
66
|
+
|
67
|
+
# Same as escape.
|
68
|
+
def quote(str)
|
69
|
+
escape(str)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Generates a new RegexpEscape by escaping the str, using the same
|
74
|
+
# options as Regexp.
|
75
|
+
def initialize(str, *options)
|
76
|
+
super(RegexpEscape.escape(str), *options)
|
77
|
+
@original_str = str
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns the original string for self
|
81
|
+
def to_s
|
82
|
+
@original_str
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'linecook/cookbook'
|
2
|
+
require 'linecook/recipe'
|
3
|
+
require 'linecook/test/file_test'
|
4
|
+
require 'linecook/test/regexp_escape'
|
5
|
+
require 'linecook/utils'
|
6
|
+
|
7
|
+
module Linecook
|
8
|
+
module Test
|
9
|
+
include FileTest
|
10
|
+
|
11
|
+
attr_writer :cookbook
|
12
|
+
attr_writer :script
|
13
|
+
attr_writer :recipe
|
14
|
+
|
15
|
+
def cookbook
|
16
|
+
@cookbook ||= Cookbook.init(user_dir)
|
17
|
+
end
|
18
|
+
|
19
|
+
def manifest
|
20
|
+
cookbook.manifest
|
21
|
+
end
|
22
|
+
|
23
|
+
def default_env
|
24
|
+
{Package::CONFIG_KEY => {Package::MANIFEST_KEY => manifest}}
|
25
|
+
end
|
26
|
+
|
27
|
+
def recipe
|
28
|
+
@recipe ||= Recipe.new('recipe', default_env)
|
29
|
+
end
|
30
|
+
|
31
|
+
def build(env={})
|
32
|
+
env = Utils.deep_merge(default_env, env)
|
33
|
+
Recipe.build(env).export File.join(method_dir, 'scripts')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Asserts whether or not the a and b strings are equal, with a more
|
37
|
+
# readable output than assert_equal for large strings (especially large
|
38
|
+
# strings with significant whitespace).
|
39
|
+
#
|
40
|
+
# One gotcha is that assert_output_equal lstrips indentation off of 'a',
|
41
|
+
# so that these all pass:
|
42
|
+
#
|
43
|
+
# assert_output_equal %q{
|
44
|
+
# line one
|
45
|
+
# line two
|
46
|
+
# }, "line one\nline two\n"
|
47
|
+
#
|
48
|
+
# assert_output_equal %q{
|
49
|
+
# line one
|
50
|
+
# line two
|
51
|
+
# }, "line one\nline two\n
|
52
|
+
#
|
53
|
+
# assert_output_equal %q{
|
54
|
+
# line one
|
55
|
+
# line two
|
56
|
+
# }, "line one\nline two\n"
|
57
|
+
#
|
58
|
+
# Use the assert_output_equal! method to prevent indentation stripping.
|
59
|
+
def assert_output_equal(a, b, msg=nil)
|
60
|
+
a = strip_indent(a)
|
61
|
+
assert_output_equal!(a, b, msg)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Same as assert_output_equal but without indentation stripping.
|
65
|
+
def assert_output_equal!(a, b, msg=nil)
|
66
|
+
if a == b
|
67
|
+
assert true
|
68
|
+
else
|
69
|
+
flunk %Q{
|
70
|
+
#{msg}
|
71
|
+
==================== expected output ====================
|
72
|
+
#{whitespace_escape(a)}
|
73
|
+
======================== but was ========================
|
74
|
+
#{whitespace_escape(b)}
|
75
|
+
=========================================================
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Asserts whether or not b is like a (which should be a Regexp), and
|
81
|
+
# provides a more readable output in the case of a failure as compared
|
82
|
+
# with assert_match.
|
83
|
+
#
|
84
|
+
# If a is a string, then indentation is stripped off and it is turned
|
85
|
+
# into a RegexpEscape. Using that syntax, all these pass:
|
86
|
+
#
|
87
|
+
# assert_alike %q{
|
88
|
+
# the time is: :...:
|
89
|
+
# now!
|
90
|
+
# }, "the time is: #{Time.now}\nnow!\n"
|
91
|
+
#
|
92
|
+
# assert_alike %q{
|
93
|
+
# the time is: :...:
|
94
|
+
# now!
|
95
|
+
# }, "the time is: #{Time.now}\nnow!\n"
|
96
|
+
#
|
97
|
+
# assert_alike %q{
|
98
|
+
# the time is: :...:
|
99
|
+
# now!
|
100
|
+
# }, "the time is: #{Time.now}\nnow!\n"
|
101
|
+
#
|
102
|
+
# Use assert_alike! to prevent indentation stripping (conversion to a
|
103
|
+
# RegexpEscape is still in effect).
|
104
|
+
def assert_alike(a, b, msg=nil)
|
105
|
+
a = strip_indent(a) if a.kind_of?(String)
|
106
|
+
assert_alike!(a, b, msg)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Same as assert_alike but without indentation stripping.
|
110
|
+
def assert_alike!(a, b, msg=nil)
|
111
|
+
a = RegexpEscape.new(a) if a.kind_of?(String)
|
112
|
+
|
113
|
+
if b =~ a
|
114
|
+
assert true
|
115
|
+
else
|
116
|
+
flunk %Q{
|
117
|
+
#{msg}
|
118
|
+
================= expected output like ==================
|
119
|
+
#{whitespace_escape(a)}
|
120
|
+
======================== but was ========================
|
121
|
+
#{whitespace_escape(b)}
|
122
|
+
=========================================================
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def assert_recipe(expected, &block)
|
128
|
+
recipe.instance_eval(&block)
|
129
|
+
assert_output_equal expected, recipe.result
|
130
|
+
end
|
131
|
+
|
132
|
+
def assert_recipe_match(expected, &block)
|
133
|
+
recipe.instance_eval(&block)
|
134
|
+
assert_alike expected, recipe.result
|
135
|
+
end
|
136
|
+
|
137
|
+
def assert_content(expected, build_path)
|
138
|
+
registry = recipe.close
|
139
|
+
|
140
|
+
assert_equal true, registry.has_key?(build_path), "not in registry: #{build_path}"
|
141
|
+
assert_output_equal expected, File.read(registry[build_path]), build_path
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
# helper for stripping indentation off a string
|
147
|
+
def strip_indent(str) # :nodoc:
|
148
|
+
if str =~ /\A\s*?\n( *)(.*)\z/m
|
149
|
+
indent, str = $1, $2, $3
|
150
|
+
|
151
|
+
if indent.length > 0
|
152
|
+
str.gsub!(/^ {0,#{indent.length}}/, '')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
str
|
157
|
+
end
|
158
|
+
|
159
|
+
# helper for formatting escaping whitespace into readable text
|
160
|
+
def whitespace_escape(str) # :nodoc:
|
161
|
+
str.to_s.gsub(/\s/) do |match|
|
162
|
+
case match
|
163
|
+
when "\n" then "\\n\n"
|
164
|
+
when "\t" then "\\t"
|
165
|
+
when "\r" then "\\r"
|
166
|
+
when "\f" then "\\f"
|
167
|
+
else match
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Linecook
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def nest_hash
|
6
|
+
Hash.new {|hash, key| hash[key] = nest_hash }
|
7
|
+
end
|
8
|
+
|
9
|
+
def serial_merge(*hashes)
|
10
|
+
attrs = {}
|
11
|
+
while overrides = hashes.shift
|
12
|
+
attrs = deep_merge(attrs, overrides)
|
13
|
+
end
|
14
|
+
attrs
|
15
|
+
end
|
16
|
+
|
17
|
+
def deep_merge(a, b)
|
18
|
+
b.each_pair do |key, current|
|
19
|
+
previous = a[key]
|
20
|
+
a[key] = deep_merge?(previous, current) ? deep_merge(previous, current) : current
|
21
|
+
end
|
22
|
+
|
23
|
+
a
|
24
|
+
end
|
25
|
+
|
26
|
+
def deep_merge?(previous, current)
|
27
|
+
current.kind_of?(Hash) && previous.kind_of?(Hash)
|
28
|
+
end
|
29
|
+
|
30
|
+
def camelize(str)
|
31
|
+
str.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
32
|
+
end
|
33
|
+
|
34
|
+
def underscore(str)
|
35
|
+
str.gsub(/::/, '/').
|
36
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
37
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
38
|
+
tr("-", "_").
|
39
|
+
downcase
|
40
|
+
end
|
41
|
+
|
42
|
+
def constantize(const_name)
|
43
|
+
constants = camelize(const_name).split(/::/)
|
44
|
+
|
45
|
+
const = Object
|
46
|
+
while name = constants.shift
|
47
|
+
const = const.const_get(name)
|
48
|
+
end
|
49
|
+
|
50
|
+
const
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/linecook.rb
ADDED
data/templates/Gemfile
ADDED
data/templates/README
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
= README
|
2
|
+
|
3
|
+
Linecook provides support to develop scripts using VirtualBox, an open-source
|
4
|
+
product to setup and manage virtual machines. Nothing says you have to use
|
5
|
+
VirtualBox during development and obviously you can take the shell scripts
|
6
|
+
produced by Linecook and run them wherever.
|
7
|
+
|
8
|
+
These are instructions for setting up a generic Ubuntu VM for development.
|
9
|
+
|
10
|
+
1. Download and Install VirtualBox (http://www.virtualbox.org)
|
11
|
+
2. Download a Ubuntu ISO (http://www.ubuntu.com/server/get-ubuntu/download)
|
12
|
+
3. Build the Box
|
13
|
+
|
14
|
+
Use the VirtualBox wizard to get started.
|
15
|
+
|
16
|
+
- name: vbox
|
17
|
+
- Linux/Ubuntu
|
18
|
+
- 512 MB memory
|
19
|
+
- 8 GB dynamically resizing drive
|
20
|
+
|
21
|
+
Under Settings:
|
22
|
+
|
23
|
+
- add the ubuntu iso to the cd/dvd device (under storage)
|
24
|
+
- disable audio
|
25
|
+
- network set to NAT
|
26
|
+
- disable usb (only the inner box would stay unchecked)
|
27
|
+
- shared folder: map the 'vbox' directory in project root
|
28
|
+
|
29
|
+
Start the server and install (default unless specified):
|
30
|
+
|
31
|
+
- hostname: vbox-ubuntu
|
32
|
+
- user/password: vbox
|
33
|
+
- no packages
|
34
|
+
- power off, remove ubuntu iso from the cd/dvd device
|
35
|
+
|
36
|
+
Setup Permissions (allows vbox to run sudo without password):
|
37
|
+
|
38
|
+
vm: sudo visudo
|
39
|
+
|
40
|
+
# insert line:
|
41
|
+
#
|
42
|
+
# %vbox ALL=NOPASSWD: ALL
|
43
|
+
#
|
44
|
+
# then exit (write out changes as prompted)
|
45
|
+
|
46
|
+
Setup guest additions (note they are in the application package on
|
47
|
+
osx http://forums.virtualbox.org/viewtopic.php?f=8&t=10286) See also:
|
48
|
+
http://forums.virtualbox.org/viewtopic.php?t=15868.
|
49
|
+
|
50
|
+
(cd/dvd device): add the VBoxGuestAdditions.iso
|
51
|
+
vm: sudo apt-get install linux-headers-$(uname -r) build-essential ssh openssh-server
|
52
|
+
vm: sudo mkdir /media/dvd
|
53
|
+
vm: sudo mount /dev/dvd /media/dvd/
|
54
|
+
vm: sudo sh /media/dvd/VBoxLinuxAdditions-x86.run
|
55
|
+
# there may be a warning about 'Window System drivers fail', ignore
|
56
|
+
|
57
|
+
Add an init script to mount the share on boot:
|
58
|
+
|
59
|
+
vm: sudo mkdir /vbox
|
60
|
+
vm: sudo mount -t vboxsf -o uid=1000,gid=100 vbox /vbox
|
61
|
+
vm: sudo cp /vbox/setup/virtual_box /etc/init.d
|
62
|
+
vm: sudo chmod 0755 /etc/init.d/virtual_box
|
63
|
+
vm: sudo update-rc.d virtual_box defaults 80
|
64
|
+
|
65
|
+
Setup SSH:
|
66
|
+
|
67
|
+
vm: mkdir ~/.ssh
|
68
|
+
vm: chmod 0700 ~/.ssh
|
69
|
+
vm: cat /vbox/ssh/id_rsa.pub >> ~/.ssh/authorized_keys
|
70
|
+
vm: chmod 0600 ~/.ssh/authorized_keys
|
71
|
+
|
72
|
+
Now take a snapshot and setup port forwarding:
|
73
|
+
|
74
|
+
vm: exit
|
75
|
+
ht: VBoxManage snapshot vbox take BASE
|
76
|
+
ht: VBoxManage controlvm vbox poweroff
|
77
|
+
ht: VBoxManage modifyvm vbox --natpf1 'guestssh,tcp,,2222,,22'
|
78
|
+
ht: VBoxManage modifyvm vbox --natpf1 'http,tcp,,8888,,80'
|
79
|
+
ht: VBoxManage -q snapshot vbox restore BASE
|
80
|
+
ht: VBoxManage startvm vbox --type headless
|
81
|
+
|
82
|
+
You can now ssh to the box (from the project dir):
|
83
|
+
|
84
|
+
ht: chmod 0600 vbox/ssh/id_rsa
|
85
|
+
ht: ssh -p 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i vbox/ssh/id_rsa vbox@localhost
|
86
|
+
|
87
|
+
To cleanup the port forwarding (run later):
|
88
|
+
|
89
|
+
ht: VBoxManage modifyvm vbox --natpf1 delete 'guestssh'
|
90
|
+
ht: VBoxManage modifyvm vbox --natpf1 delete 'http'
|
data/templates/Rakefile
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Gem tasks
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/gempackagetask'
|
9
|
+
|
10
|
+
def gemspec
|
11
|
+
@gemspec ||= eval(File.read('<%= project_name %>.gemspec'), TOPLEVEL_BINDING)
|
12
|
+
end
|
13
|
+
|
14
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
15
|
+
pkg.need_tar = true
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Prints the gemspec manifest.'
|
19
|
+
task :print_manifest do
|
20
|
+
files = gemspec.files.inject({}) do |files, file|
|
21
|
+
files[File.expand_path(file)] = [File.exists?(file), file]
|
22
|
+
files
|
23
|
+
end
|
24
|
+
|
25
|
+
cookbook_files = Dir.glob('{attributes,files,lib,recipes,templates}/**/*')
|
26
|
+
cookbook_file = Dir.glob('*')
|
27
|
+
|
28
|
+
(cookbook_files + cookbook_file).each do |file|
|
29
|
+
next unless File.file?(file)
|
30
|
+
path = File.expand_path(file)
|
31
|
+
files[path] = ['', file] unless files.has_key?(path)
|
32
|
+
end
|
33
|
+
|
34
|
+
# sort and output the results
|
35
|
+
files.values.sort_by {|exists, file| file }.each do |entry|
|
36
|
+
puts '%-5s %s' % entry
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Documentation tasks
|
42
|
+
#
|
43
|
+
|
44
|
+
desc 'Generate documentation.'
|
45
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
46
|
+
spec = gemspec
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.options.concat(spec.rdoc_options)
|
50
|
+
rdoc.rdoc_files.include(spec.extra_rdoc_files)
|
51
|
+
|
52
|
+
files = spec.files.select {|file| file =~ /^lib.*\.rb$/}
|
53
|
+
rdoc.rdoc_files.include( files )
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Dependency tasks
|
58
|
+
#
|
59
|
+
|
60
|
+
desc 'Bundle dependencies'
|
61
|
+
task :bundle do
|
62
|
+
output = `bundle check 2>&1`
|
63
|
+
|
64
|
+
unless $?.to_i == 0
|
65
|
+
puts output
|
66
|
+
sh "bundle install 2>&1"
|
67
|
+
puts
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# Linecook Helpers
|
73
|
+
#
|
74
|
+
|
75
|
+
lib_dir = File.expand_path("../lib", __FILE__)
|
76
|
+
helpers_dir = File.expand_path("../helpers", __FILE__)
|
77
|
+
|
78
|
+
sources = {}
|
79
|
+
helpers = []
|
80
|
+
|
81
|
+
Dir.glob("#{helpers_dir}/**/*").each do |source|
|
82
|
+
next if File.directory?(source)
|
83
|
+
(sources[File.dirname(source)] ||= []) << source
|
84
|
+
end
|
85
|
+
|
86
|
+
sources.each_pair do |dir, sources|
|
87
|
+
name = dir[(helpers_dir.length + 1)..-1]
|
88
|
+
target = File.join(lib_dir, 'linebook', "#{name}.rb")
|
89
|
+
|
90
|
+
file target => sources + [dir] do
|
91
|
+
system "bundle exec linecook helper '#{name}' --force"
|
92
|
+
end
|
93
|
+
|
94
|
+
helpers << target
|
95
|
+
end
|
96
|
+
|
97
|
+
desc "generate helpers"
|
98
|
+
task :helpers => helpers + [:bundle]
|
99
|
+
|
100
|
+
#
|
101
|
+
# Linecook Scripts
|
102
|
+
#
|
103
|
+
|
104
|
+
scripts = Dir.glob("scripts/*.yml")
|
105
|
+
dependencies = Dir.glob('{attributes,files,recipes,templates}/**/*')
|
106
|
+
|
107
|
+
scripts.each do |source|
|
108
|
+
target = source.chomp('.yml')
|
109
|
+
name = File.basename(target)
|
110
|
+
|
111
|
+
namespace :scripts do
|
112
|
+
file target => dependencies + [source] + helpers do
|
113
|
+
sh "bundle exec linecook package '#{source}' '#{target}' --force"
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "generate the script: #{name}"
|
117
|
+
task name => target
|
118
|
+
end
|
119
|
+
|
120
|
+
task :scripts => target
|
121
|
+
end
|
122
|
+
|
123
|
+
desc "generate scripts"
|
124
|
+
task :scripts
|
125
|
+
|
126
|
+
#
|
127
|
+
# Test tasks
|
128
|
+
#
|
129
|
+
|
130
|
+
desc 'Default: Run tests.'
|
131
|
+
task :default => :test
|
132
|
+
|
133
|
+
desc 'Run the tests'
|
134
|
+
task :test => :helpers do
|
135
|
+
tests = Dir.glob('test/**/*_test.rb')
|
136
|
+
|
137
|
+
if ENV['RCOV'] == 'true'
|
138
|
+
FileUtils.rm_rf File.expand_path('../coverage', __FILE__)
|
139
|
+
sh('rcov', '-w', '--text-report', '--exclude', '^/', *tests)
|
140
|
+
else
|
141
|
+
sh('ruby', '-w', '-e', 'ARGV.dup.each {|test| load test}', *tests)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
desc 'Run rcov'
|
146
|
+
task :rcov do
|
147
|
+
ENV['RCOV'] = 'true'
|
148
|
+
Rake::Task["test"].invoke
|
149
|
+
end
|
data/templates/cookbook
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Configure the cookbook here.
|
2
|
+
# Adding this file to a gem marks it as a cookbook gem
|
3
|
+
# (note that in a gem the contents of this file are ignored)
|
4
|
+
|
5
|
+
# Define directories searched for attributes/recipes/etc.
|
6
|
+
# paths: ['.']
|
7
|
+
|
8
|
+
# Name the gems added to path - defaults to all marked gems.
|
9
|
+
# gems: []
|
@@ -0,0 +1 @@
|
|
1
|
+
Contents of an example file.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "<%= project_name %>"
|
5
|
+
s.version = "0.0.1"
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.authors = "TODO: Write your name"
|
8
|
+
s.email = "TODO: Write your email address"
|
9
|
+
s.homepage = ""
|
10
|
+
s.summary = %q{TODO: Write a gem summary}
|
11
|
+
s.description = %q{TODO: Write a gem description}
|
12
|
+
s.rubyforge_project = ''
|
13
|
+
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.rdoc_options.concat %W{--main README -S -N --title <%= project_name.capitalize %>}
|
16
|
+
|
17
|
+
# add dependencies
|
18
|
+
s.add_dependency('linecook', '~> <%= Linecook::VERSION %>')
|
19
|
+
|
20
|
+
# list extra rdoc files here.
|
21
|
+
s.extra_rdoc_files = %W{
|
22
|
+
cookbook
|
23
|
+
}
|
24
|
+
|
25
|
+
# list the files you want to include here.
|
26
|
+
s.files = %W{
|
27
|
+
}
|
28
|
+
|
29
|
+
s.require_path = 'lib'
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#############################################################################
|
2
|
+
helpers 'linecook/shell'
|
3
|
+
helpers 'linebook/<%= project_name %>'
|
4
|
+
attributes '<%= project_name %>'
|
5
|
+
#############################################################################
|
6
|
+
|
7
|
+
shebang '/bin/bash'
|
8
|
+
|
9
|
+
# Write to the script target using 'script'
|
10
|
+
target.puts '# An example script.'
|
11
|
+
|
12
|
+
# Helpers are now available, as are attributes.
|
13
|
+
echo *attrs['<%= project_name %>']['letters']
|
14
|
+
echo *attrs['<%= project_name %>']['numbers']
|
15
|
+
|
16
|
+
# Use files like this:
|
17
|
+
cat file_path('file.txt')
|
18
|
+
|
19
|
+
# Use templates like this:
|
20
|
+
cat template_path('template.txt', :n => 10)
|