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,104 @@
|
|
1
|
+
require 'linecook/package'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Linecook
|
5
|
+
class Cookbook
|
6
|
+
class << self
|
7
|
+
def config_file(dir)
|
8
|
+
Dir.glob(File.join(dir, '{C,c}ookbook')).first
|
9
|
+
end
|
10
|
+
|
11
|
+
def init(dir)
|
12
|
+
path = config_file(dir)
|
13
|
+
config = path ? YAML.load_file(path) : nil
|
14
|
+
|
15
|
+
new(dir, config || {})
|
16
|
+
end
|
17
|
+
|
18
|
+
def gems
|
19
|
+
return [] unless Object.const_defined?(:Gem)
|
20
|
+
|
21
|
+
Gem.source_index.latest_specs.select do |spec|
|
22
|
+
config_file(spec.full_gem_path) != nil
|
23
|
+
end.collect do |spec|
|
24
|
+
spec.name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
PATTERNS = [
|
30
|
+
File.join('attributes', '**', '*.rb'),
|
31
|
+
File.join('files', '**', '*'),
|
32
|
+
File.join('recipes', '**', '*.rb'),
|
33
|
+
File.join('templates', '**', '*.erb')
|
34
|
+
]
|
35
|
+
|
36
|
+
attr_reader :dir
|
37
|
+
attr_reader :config
|
38
|
+
|
39
|
+
def initialize(dir='.', config={})
|
40
|
+
@dir = File.expand_path(dir)
|
41
|
+
@config = {
|
42
|
+
'manifest' => {},
|
43
|
+
'paths' => ['.'],
|
44
|
+
'gems' => self.class.gems
|
45
|
+
}.merge(config)
|
46
|
+
end
|
47
|
+
|
48
|
+
def manifest
|
49
|
+
@manifest ||= begin
|
50
|
+
manifest = {}
|
51
|
+
|
52
|
+
paths = split config['paths']
|
53
|
+
gems = split config['gems']
|
54
|
+
gems = resolve gems
|
55
|
+
|
56
|
+
(gems + paths).each do |path|
|
57
|
+
path = File.expand_path(path, dir)
|
58
|
+
start = path.length + 1
|
59
|
+
|
60
|
+
PATTERNS.each do |pattern|
|
61
|
+
Dir.glob(File.join(path, pattern)).each do |full_path|
|
62
|
+
next unless File.file?(full_path)
|
63
|
+
|
64
|
+
rel_path = full_path[start, full_path.length - start]
|
65
|
+
manifest[rel_path] = full_path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
overrides = config['manifest']
|
71
|
+
manifest.merge!(overrides)
|
72
|
+
manifest
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def env(path=nil)
|
77
|
+
Package.env(manifest, path)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def split(str) # :nodoc:
|
83
|
+
str.kind_of?(String) ? str.split(':') : str
|
84
|
+
end
|
85
|
+
|
86
|
+
def resolve(gems) # :nodoc:
|
87
|
+
return gems if gems.empty?
|
88
|
+
specs = latest_specs
|
89
|
+
|
90
|
+
gems.collect do |name|
|
91
|
+
spec = specs[name] or raise "no such gem: #{name.inspect}"
|
92
|
+
spec.full_gem_path
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def latest_specs # :nodoc:
|
97
|
+
latest = {}
|
98
|
+
Gem.source_index.latest_specs.each do |spec|
|
99
|
+
latest[spec.name] = spec
|
100
|
+
end
|
101
|
+
latest
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'linecook/template'
|
2
|
+
|
3
|
+
module Linecook
|
4
|
+
class Helper < Template
|
5
|
+
attr_reader :const_name
|
6
|
+
attr_reader :sources
|
7
|
+
|
8
|
+
def initialize(const_name, sources)
|
9
|
+
@const_name = const_name
|
10
|
+
@sources = sources.select {|source| File.file?(source) }
|
11
|
+
@section_paths, @definition_paths = @sources.partition {|path| File.basename(path)[0] == ?_ }
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def build
|
16
|
+
eval MODULE_TEMPLATE, binding, __FILE__, MODULE_TEMPLATE_LINE
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def sections
|
21
|
+
@sections ||= begin
|
22
|
+
sections = {}
|
23
|
+
|
24
|
+
@section_paths.each do |path|
|
25
|
+
key = File.basename(path)[1..-1]
|
26
|
+
key.chomp! File.extname(path)
|
27
|
+
sections[key.to_sym] = File.read(path)
|
28
|
+
end
|
29
|
+
|
30
|
+
sections
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def definitions
|
35
|
+
@definitions ||= @definition_paths.collect do |path|
|
36
|
+
name = File.basename(path).chomp File.extname(path)
|
37
|
+
desc, signature, body = parse File.read(path)
|
38
|
+
|
39
|
+
eval ERB_TEMPLATE, binding, __FILE__, ERB_TEMPLATE_LINE
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def parse(str)
|
46
|
+
head, body = str.split(/^--.*\n/, 2)
|
47
|
+
head, body = '', head if body.nil?
|
48
|
+
signature, desc = parse_head(head)
|
49
|
+
|
50
|
+
[desc.join("\n"), signature.join("\n"), body]
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_head(head)
|
54
|
+
found_signature = false
|
55
|
+
head.split("\n").partition do |line|
|
56
|
+
found_signature = true if line =~ /^\s*\(.*?\)/
|
57
|
+
found_signature
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_name(name)
|
62
|
+
case name
|
63
|
+
when /_check$/ then name.sub(/_check$/, '?')
|
64
|
+
when /_bang$/ then name.sub(/_bang$/, '!')
|
65
|
+
else name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def module_nest(const_name, indent=" ", line_sep="\n")
|
70
|
+
nestings = const_name.split(/::/).collect {|name| ["module #{name}", "end"]}
|
71
|
+
nestings << {:indent => indent, :line_sep => line_sep}
|
72
|
+
|
73
|
+
nest(*nestings) { yield }
|
74
|
+
end
|
75
|
+
|
76
|
+
MODULE_TEMPLATE_LINE = __LINE__ + 2
|
77
|
+
MODULE_TEMPLATE = "self." + ERB.new(<<-DOC, nil, '<>').src
|
78
|
+
require 'erb'
|
79
|
+
<%= sections[:header] %>
|
80
|
+
|
81
|
+
# Generated by Linecook, do not edit.
|
82
|
+
<% module_nest(const_name, '') do %>
|
83
|
+
<%= sections[:head] %>
|
84
|
+
<% definitions.each do |definition| %>
|
85
|
+
|
86
|
+
<%= definition %>
|
87
|
+
<% end %>
|
88
|
+
<%= sections[:tail] %>
|
89
|
+
<% end %>
|
90
|
+
|
91
|
+
<%= sections[:footer] %>
|
92
|
+
DOC
|
93
|
+
|
94
|
+
ERB_TEMPLATE_LINE = __LINE__ + 2
|
95
|
+
ERB_TEMPLATE = ERB.new(<<-DOC, nil, '<>').src
|
96
|
+
# :stopdoc:
|
97
|
+
<%= name.upcase %>_LINE = __LINE__ + 2
|
98
|
+
<%= name.upcase %> = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
99
|
+
<%= body %>
|
100
|
+
|
101
|
+
END_OF_TEMPLATE
|
102
|
+
# :startdoc:
|
103
|
+
|
104
|
+
<% desc.each do |line| %>
|
105
|
+
# <%= line %>
|
106
|
+
<% end %>
|
107
|
+
def <%= method_name(name) %><%= signature %>
|
108
|
+
eval(<%= name.upcase %>, binding, __FILE__, <%= name.upcase %>_LINE)
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
|
112
|
+
def _<%= method_name(name) %>(*args, &block) # :nodoc:
|
113
|
+
capture { <%= method_name(name) %>(*args, &block) }
|
114
|
+
end
|
115
|
+
DOC
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'linecook/utils'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Linecook
|
5
|
+
class Package
|
6
|
+
class << self
|
7
|
+
def load_env(path)
|
8
|
+
(path ? YAML.load_file(path) : nil) || {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def env(manifest, path)
|
12
|
+
default = {CONFIG_KEY => {MANIFEST_KEY => manifest}}
|
13
|
+
overrides = load_env(path)
|
14
|
+
Utils.serial_merge(default, overrides)
|
15
|
+
end
|
16
|
+
|
17
|
+
def init(env={})
|
18
|
+
env.kind_of?(Package) ? env : new(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
CONFIG_KEY = 'linecook'
|
23
|
+
MANIFEST_KEY = 'manifest'
|
24
|
+
REGISTRY_KEY = 'registry'
|
25
|
+
CACHE_KEY = 'cache'
|
26
|
+
FILES_KEY = 'files'
|
27
|
+
TEMPLATES_KEY = 'templates'
|
28
|
+
RECIPES_KEY = 'recipes'
|
29
|
+
PATHS_KEY = 'paths'
|
30
|
+
GEMS_KEY = 'gems'
|
31
|
+
|
32
|
+
attr_reader :env
|
33
|
+
|
34
|
+
def initialize(env={})
|
35
|
+
@env = env
|
36
|
+
end
|
37
|
+
|
38
|
+
def config
|
39
|
+
env[CONFIG_KEY] ||= {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def cache
|
43
|
+
config[CACHE_KEY] ||= {}
|
44
|
+
end
|
45
|
+
|
46
|
+
def manifest
|
47
|
+
config[MANIFEST_KEY] ||= {}
|
48
|
+
end
|
49
|
+
|
50
|
+
def registry
|
51
|
+
config[REGISTRY_KEY] ||= {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def reverse_registry
|
55
|
+
cache[:reverse_registry] ||= {}
|
56
|
+
end
|
57
|
+
|
58
|
+
def tempfiles
|
59
|
+
cache[:tempfiles] ||= []
|
60
|
+
end
|
61
|
+
|
62
|
+
def register(source_path, build_path=nil)
|
63
|
+
source_path = File.expand_path(source_path)
|
64
|
+
build_path ||= File.basename(source_path)
|
65
|
+
|
66
|
+
count = 0
|
67
|
+
registry.each_key do |path|
|
68
|
+
if path.kind_of?(String) && path.index(build_path) == 0
|
69
|
+
count += 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
if count > 0
|
74
|
+
build_path = "#{build_path}.#{count}"
|
75
|
+
end
|
76
|
+
|
77
|
+
registry[build_path] = source_path
|
78
|
+
reverse_registry[source_path.to_sym] = build_path
|
79
|
+
|
80
|
+
build_path
|
81
|
+
end
|
82
|
+
|
83
|
+
def registered?(source_path)
|
84
|
+
source_path = File.expand_path(source_path)
|
85
|
+
reverse_registry.has_key?(source_path.to_sym)
|
86
|
+
end
|
87
|
+
|
88
|
+
def built?(build_path)
|
89
|
+
registry.has_key?(build_path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def tempfile?(source_path)
|
93
|
+
tempfiles.find {|tempfile| tempfile.path == source_path }
|
94
|
+
end
|
95
|
+
|
96
|
+
def build(build_path, source_path=nil)
|
97
|
+
case
|
98
|
+
when built?(build_path)
|
99
|
+
raise "already built: #{build_path}"
|
100
|
+
|
101
|
+
when source_path
|
102
|
+
register(source_path, build_path)
|
103
|
+
|
104
|
+
else
|
105
|
+
tempfile = Tempfile.new File.basename(build_path)
|
106
|
+
|
107
|
+
register(tempfile.path, build_path)
|
108
|
+
tempfiles << tempfile
|
109
|
+
|
110
|
+
tempfile
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_path(source_path)
|
115
|
+
source_path = File.expand_path(source_path)
|
116
|
+
reverse_registry[source_path.to_sym]
|
117
|
+
end
|
118
|
+
|
119
|
+
def source_path(build_path)
|
120
|
+
registry[build_path]
|
121
|
+
end
|
122
|
+
|
123
|
+
def files
|
124
|
+
normalize(FILES_KEY)
|
125
|
+
end
|
126
|
+
|
127
|
+
def templates
|
128
|
+
normalize(TEMPLATES_KEY)
|
129
|
+
end
|
130
|
+
|
131
|
+
def recipes
|
132
|
+
normalize(RECIPES_KEY)
|
133
|
+
end
|
134
|
+
|
135
|
+
def export(dir, options={})
|
136
|
+
close
|
137
|
+
|
138
|
+
options = {
|
139
|
+
:allow_move => true
|
140
|
+
}.merge(options)
|
141
|
+
|
142
|
+
allow_move = options[:allow_move]
|
143
|
+
|
144
|
+
results = {}
|
145
|
+
registry.each_pair do |build_path, source_path|
|
146
|
+
target_path = File.join(dir, build_path)
|
147
|
+
target_dir = File.dirname(target_path)
|
148
|
+
|
149
|
+
unless File.exists?(target_dir)
|
150
|
+
FileUtils.mkdir_p(target_dir)
|
151
|
+
end
|
152
|
+
|
153
|
+
if allow_move && tempfile?(source_path)
|
154
|
+
FileUtils.mv(source_path, target_path)
|
155
|
+
else
|
156
|
+
FileUtils.cp(source_path, target_path)
|
157
|
+
end
|
158
|
+
|
159
|
+
results[build_path] = target_path
|
160
|
+
end
|
161
|
+
results
|
162
|
+
end
|
163
|
+
|
164
|
+
def close
|
165
|
+
tempfiles.each do |tempfile|
|
166
|
+
tempfile.close unless tempfile.closed?
|
167
|
+
end
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def normalize(key)
|
174
|
+
obj = config[key]
|
175
|
+
|
176
|
+
case obj
|
177
|
+
when Hash
|
178
|
+
obj
|
179
|
+
|
180
|
+
when nil
|
181
|
+
config[key] = {}
|
182
|
+
|
183
|
+
when Array
|
184
|
+
hash = {}
|
185
|
+
obj.each {|entry| hash[entry] = entry }
|
186
|
+
config[key] = hash
|
187
|
+
|
188
|
+
when String
|
189
|
+
config[key] = obj.split(':')
|
190
|
+
normalize(key)
|
191
|
+
|
192
|
+
else
|
193
|
+
raise "invalid #{key}: #{obj.inspect}"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'linecook/template'
|
2
|
+
require 'linecook/attributes'
|
3
|
+
require 'linecook/package'
|
4
|
+
require 'linecook/utils'
|
5
|
+
|
6
|
+
module Linecook
|
7
|
+
class Recipe < Template
|
8
|
+
class << self
|
9
|
+
def build(env)
|
10
|
+
package = Package.new(env)
|
11
|
+
|
12
|
+
package.recipes.each do |recipe_name, target_name|
|
13
|
+
new(target_name, env).evaluate(recipe_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
package.close
|
17
|
+
package
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias target erbout
|
22
|
+
|
23
|
+
attr_reader :target_name
|
24
|
+
|
25
|
+
def initialize(target_name, env={})
|
26
|
+
@target_name = target_name
|
27
|
+
@package = Package.init(env)
|
28
|
+
@attributes = Attributes.new(@package.env)
|
29
|
+
@erbout = @package.build(target_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def source_path(*relative_path)
|
33
|
+
path = File.join(*relative_path)
|
34
|
+
@package.manifest[path] or raise "no such file in manifest: #{path.inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def target_path(source_path)
|
38
|
+
@package.build_path(source_path) ||
|
39
|
+
@package.register(source_path, File.join("#{target_name}.d", File.basename(source_path)))
|
40
|
+
end
|
41
|
+
|
42
|
+
def target_file(name, content=nil)
|
43
|
+
tempfile = @package.build File.join("#{target_name}.d", name)
|
44
|
+
|
45
|
+
tempfile << content if content
|
46
|
+
yield(tempfile) if block_given?
|
47
|
+
|
48
|
+
target_path tempfile.path
|
49
|
+
end
|
50
|
+
|
51
|
+
def attrs
|
52
|
+
@attributes.current
|
53
|
+
end
|
54
|
+
|
55
|
+
def attributes(attributes_name)
|
56
|
+
path = source_path('attributes', "#{attributes_name}.rb")
|
57
|
+
|
58
|
+
@attributes.instance_eval(File.read(path), path)
|
59
|
+
@attributes.reset(false)
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def helpers(helper_name)
|
64
|
+
require Utils.underscore(helper_name)
|
65
|
+
extend Utils.constantize(helper_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def evaluate(recipe_name=target_name)
|
69
|
+
path = source_path('recipes', "#{recipe_name}.rb")
|
70
|
+
instance_eval(File.read(path), path)
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def file_path(file_name)
|
75
|
+
path = source_path('files', file_name)
|
76
|
+
target_path path
|
77
|
+
end
|
78
|
+
|
79
|
+
def capture_path(name, &block)
|
80
|
+
content = capture(false) { instance_eval(&block) }
|
81
|
+
target_file(name, content)
|
82
|
+
end
|
83
|
+
|
84
|
+
def recipe_path(recipe_name, target_name = recipe_name)
|
85
|
+
source_path =
|
86
|
+
@package.built?(target_name) ?
|
87
|
+
@package.source_path(target_name) :
|
88
|
+
Recipe.new(target_name, @package).evaluate(recipe_name).target.path
|
89
|
+
|
90
|
+
target_path source_path
|
91
|
+
end
|
92
|
+
|
93
|
+
def template_path(template_name, locals={})
|
94
|
+
path = source_path('templates', "#{template_name}.erb")
|
95
|
+
target_file template_name, Template.build(File.read(path), locals, path)
|
96
|
+
end
|
97
|
+
|
98
|
+
def close
|
99
|
+
@package.close
|
100
|
+
@package.registry
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
# Generated by Linecook, do not edit.
|
4
|
+
module Linecook
|
5
|
+
module Shell
|
6
|
+
module Posix
|
7
|
+
# :stopdoc:
|
8
|
+
COMMENT_LINE = __LINE__ + 2
|
9
|
+
COMMENT = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
10
|
+
# <%= str %>
|
11
|
+
END_OF_TEMPLATE
|
12
|
+
# :startdoc:
|
13
|
+
|
14
|
+
# Writes a comment
|
15
|
+
def comment(str)
|
16
|
+
eval(COMMENT, binding, __FILE__, COMMENT_LINE)
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def _comment(*args, &block) # :nodoc:
|
21
|
+
capture { comment(*args, &block) }
|
22
|
+
end
|
23
|
+
|
24
|
+
# :stopdoc:
|
25
|
+
HEREDOC_LINE = __LINE__ + 2
|
26
|
+
HEREDOC = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
27
|
+
<<<%= options[:indent] ? '-' : ' '%><%= options[:quote] ? "\"#{delimiter}\"" : delimiter %>
|
28
|
+
<% yield %>
|
29
|
+
<%= delimiter %>
|
30
|
+
|
31
|
+
END_OF_TEMPLATE
|
32
|
+
# :startdoc:
|
33
|
+
|
34
|
+
# Makes a heredoc statement surrounding the contents of the block. Options:
|
35
|
+
|
36
|
+
#
|
37
|
+
|
38
|
+
# delimiter the delimiter used, by default HEREDOC_n where n increments
|
39
|
+
|
40
|
+
# indent add '-' before the delimiter
|
41
|
+
|
42
|
+
# quote quotes the delimiter
|
43
|
+
|
44
|
+
def heredoc(options={})
|
45
|
+
delimiter = options[:delimiter] || begin
|
46
|
+
@heredoc_count ||= -1
|
47
|
+
"HEREDOC_#{@heredoc_count += 1}"
|
48
|
+
end
|
49
|
+
eval(HEREDOC, binding, __FILE__, HEREDOC_LINE)
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def _heredoc(*args, &block) # :nodoc:
|
54
|
+
capture { heredoc(*args, &block) }
|
55
|
+
end
|
56
|
+
|
57
|
+
# :stopdoc:
|
58
|
+
NOT_IF_LINE = __LINE__ + 2
|
59
|
+
NOT_IF = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
60
|
+
only_if("! #{cmd}", &block)
|
61
|
+
END_OF_TEMPLATE
|
62
|
+
# :startdoc:
|
63
|
+
|
64
|
+
def not_if(cmd, &block)
|
65
|
+
eval(NOT_IF, binding, __FILE__, NOT_IF_LINE)
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def _not_if(*args, &block) # :nodoc:
|
70
|
+
capture { not_if(*args, &block) }
|
71
|
+
end
|
72
|
+
|
73
|
+
# :stopdoc:
|
74
|
+
ONLY_IF_LINE = __LINE__ + 2
|
75
|
+
ONLY_IF = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
76
|
+
if <%= cmd %>
|
77
|
+
then
|
78
|
+
<% indent { yield } %>
|
79
|
+
fi
|
80
|
+
|
81
|
+
END_OF_TEMPLATE
|
82
|
+
# :startdoc:
|
83
|
+
|
84
|
+
def only_if(cmd)
|
85
|
+
eval(ONLY_IF, binding, __FILE__, ONLY_IF_LINE)
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def _only_if(*args, &block) # :nodoc:
|
90
|
+
capture { only_if(*args, &block) }
|
91
|
+
end
|
92
|
+
|
93
|
+
# :stopdoc:
|
94
|
+
SET_LINE = __LINE__ + 2
|
95
|
+
SET = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
96
|
+
<% if block_given? %>
|
97
|
+
<% reset_file = "LINECOOK_RESET_OPTIONS_#{next_count}" %>
|
98
|
+
<%= reset_file %>=`mktemp /tmp/line_cook_reset_fileXXXXXX`
|
99
|
+
set -o | sed 's/\(.*\) on/set -o \1/' | sed 's/\(.*\) off/set +o \1/' > $<%= reset_file %>
|
100
|
+
<% end %><% options.keys.sort_by {|opt| opt.to_s }.each do |opt| %>
|
101
|
+
set <%= options[opt] ? '-' : '+' %>o <%= opt %>
|
102
|
+
<% end %>
|
103
|
+
<% if block_given? %>
|
104
|
+
|
105
|
+
<% indent { yield } %>
|
106
|
+
|
107
|
+
source $<%= reset_file %>
|
108
|
+
<% end %>
|
109
|
+
|
110
|
+
END_OF_TEMPLATE
|
111
|
+
# :startdoc:
|
112
|
+
|
113
|
+
# Sets bash options for the duration of a block. If no block is given,
|
114
|
+
|
115
|
+
# set simply sets the options as specified.
|
116
|
+
def set(options)
|
117
|
+
eval(SET, binding, __FILE__, SET_LINE)
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def _set(*args, &block) # :nodoc:
|
122
|
+
capture { set(*args, &block) }
|
123
|
+
end
|
124
|
+
|
125
|
+
# :stopdoc:
|
126
|
+
UNSET_LINE = __LINE__ + 2
|
127
|
+
UNSET = "self." + ERB.new(<<'END_OF_TEMPLATE', nil, '<>').src
|
128
|
+
<% keys.each do |key| %>
|
129
|
+
unset <%= key %>
|
130
|
+
<% end %>
|
131
|
+
END_OF_TEMPLATE
|
132
|
+
# :startdoc:
|
133
|
+
|
134
|
+
# Unsets a list of variables.
|
135
|
+
def unset(*keys)
|
136
|
+
eval(UNSET, binding, __FILE__, UNSET_LINE)
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def _unset(*args, &block) # :nodoc:
|
141
|
+
capture { unset(*args, &block) }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|