linecook 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History +60 -0
  2. data/License.txt +22 -0
  3. data/README +98 -0
  4. data/bin/linecook +58 -0
  5. data/cookbook +0 -0
  6. data/lib/linecook/attributes.rb +22 -0
  7. data/lib/linecook/commands/command.rb +48 -0
  8. data/lib/linecook/commands/command_error.rb +6 -0
  9. data/lib/linecook/commands/env.rb +23 -0
  10. data/lib/linecook/commands/helper.rb +51 -0
  11. data/lib/linecook/commands/helpers.rb +28 -0
  12. data/lib/linecook/commands/init.rb +82 -0
  13. data/lib/linecook/commands/package.rb +39 -0
  14. data/lib/linecook/commands/vbox.rb +85 -0
  15. data/lib/linecook/commands.rb +6 -0
  16. data/lib/linecook/cookbook.rb +104 -0
  17. data/lib/linecook/helper.rb +117 -0
  18. data/lib/linecook/package.rb +197 -0
  19. data/lib/linecook/recipe.rb +103 -0
  20. data/lib/linecook/shell/posix.rb +145 -0
  21. data/lib/linecook/shell/test.rb +254 -0
  22. data/lib/linecook/shell/unix.rb +117 -0
  23. data/lib/linecook/shell/utils.rb +138 -0
  24. data/lib/linecook/shell.rb +11 -0
  25. data/lib/linecook/template.rb +111 -0
  26. data/lib/linecook/test/file_test.rb +77 -0
  27. data/lib/linecook/test/regexp_escape.rb +86 -0
  28. data/lib/linecook/test.rb +172 -0
  29. data/lib/linecook/utils.rb +53 -0
  30. data/lib/linecook/version.rb +8 -0
  31. data/lib/linecook.rb +6 -0
  32. data/templates/Gemfile +2 -0
  33. data/templates/README +90 -0
  34. data/templates/Rakefile +149 -0
  35. data/templates/_gitignore +5 -0
  36. data/templates/attributes/project_name.rb +4 -0
  37. data/templates/cookbook +9 -0
  38. data/templates/files/file.txt +1 -0
  39. data/templates/helpers/project_name/echo.erb +5 -0
  40. data/templates/project_name.gemspec +30 -0
  41. data/templates/recipes/project_name.rb +20 -0
  42. data/templates/scripts/project_name.yml +7 -0
  43. data/templates/templates/template.txt.erb +3 -0
  44. data/templates/vbox/setup/virtual_box +86 -0
  45. data/templates/vbox/ssh/id_rsa +27 -0
  46. data/templates/vbox/ssh/id_rsa.pub +1 -0
  47. 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
@@ -0,0 +1,8 @@
1
+ module Linecook
2
+ MAJOR = 0
3
+ MINOR = 6
4
+ TINY = 2
5
+
6
+ VERSION = "#{MAJOR}.#{MINOR}.#{TINY}"
7
+ WEBSITE = "http://github.com/pinnacol/linecook"
8
+ end
data/lib/linecook.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'linecook/helper'
2
+ require 'linecook/script'
3
+ require 'linecook/cookbook'
4
+
5
+ module Linecook
6
+ end
data/templates/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
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'
@@ -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
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ .bundle
3
+ *.gem
4
+ /rdoc
5
+ vbox/log
@@ -0,0 +1,4 @@
1
+ # Define default recipe attributes here and include in a recipe using
2
+ # 'attributes "filename"'. Script attributes override these values.
3
+ attrs['<%= project_name %>']['letters'] = ['a', 'b', 'c']
4
+ attrs['<%= project_name %>']['numbers'] = [1, 2, 3]
@@ -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,5 @@
1
+ An example of a helper definition. This is the documentation, followed by the
2
+ method signature and then the ERB template.
3
+ (*args)
4
+ --
5
+ echo '<%= "<" + "%= args.join(' ') %"+ ">" %>'
@@ -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)
@@ -0,0 +1,7 @@
1
+ # Configure Linecook
2
+ linecook:
3
+ recipes: [<%= project_name %>]
4
+
5
+ # Set attributes for the script
6
+ <%= project_name %>:
7
+ numbers: [7, 8, 9]
@@ -0,0 +1,3 @@
1
+ <%= '<' %>% n.times do %<%= '>' %>
2
+ Contents of a template file.
3
+ <%= '<' %>% end %<%= '>' %>