automate-it 0.9.0
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.hgignore +10 -0
- data/.loadpath +5 -0
- data/.project +17 -0
- data/CHANGES.txt +314 -0
- data/Hoe.rake +40 -0
- data/Manifest.txt +164 -0
- data/README.txt +40 -0
- data/Rakefile +256 -0
- data/TESTING.txt +57 -0
- data/TODO.txt +50 -0
- data/TUTORIAL.txt +391 -0
- data/automate-it.gemspec +25 -0
- data/bin/ai +3 -0
- data/bin/aifield +75 -0
- data/bin/aissh +93 -0
- data/bin/aitag +134 -0
- data/bin/automateit +133 -0
- data/docs/friendly_errors.txt +50 -0
- data/docs/previews.txt +86 -0
- data/examples/basic/Rakefile +26 -0
- data/examples/basic/config/automateit_env.rb +16 -0
- data/examples/basic/config/fields.yml +3 -0
- data/examples/basic/config/tags.yml +7 -0
- data/examples/basic/dist/README.txt +9 -0
- data/examples/basic/dist/myapp_server.erb +30 -0
- data/examples/basic/install.log +15 -0
- data/examples/basic/lib/README.txt +10 -0
- data/examples/basic/recipes/README.txt +4 -0
- data/examples/basic/recipes/install.rb +61 -0
- data/examples/basic/recipes/uninstall.rb +6 -0
- data/gpl.txt +674 -0
- data/helpers/cpan_wrapper.pl +220 -0
- data/helpers/which.cmd +7 -0
- data/lib/automateit.rb +55 -0
- data/lib/automateit/account_manager.rb +114 -0
- data/lib/automateit/account_manager/base.rb +138 -0
- data/lib/automateit/account_manager/etc.rb +128 -0
- data/lib/automateit/account_manager/nscd.rb +33 -0
- data/lib/automateit/account_manager/passwd_expect.rb +40 -0
- data/lib/automateit/account_manager/passwd_pty.rb +69 -0
- data/lib/automateit/account_manager/posix.rb +138 -0
- data/lib/automateit/address_manager.rb +88 -0
- data/lib/automateit/address_manager/base.rb +171 -0
- data/lib/automateit/address_manager/bsd.rb +28 -0
- data/lib/automateit/address_manager/freebsd.rb +59 -0
- data/lib/automateit/address_manager/linux.rb +42 -0
- data/lib/automateit/address_manager/openbsd.rb +66 -0
- data/lib/automateit/address_manager/portable.rb +37 -0
- data/lib/automateit/address_manager/sunos.rb +34 -0
- data/lib/automateit/cli.rb +85 -0
- data/lib/automateit/common.rb +65 -0
- data/lib/automateit/constants.rb +35 -0
- data/lib/automateit/download_manager.rb +48 -0
- data/lib/automateit/edit_manager.rb +321 -0
- data/lib/automateit/error.rb +10 -0
- data/lib/automateit/field_manager.rb +103 -0
- data/lib/automateit/interpreter.rb +631 -0
- data/lib/automateit/package_manager.rb +257 -0
- data/lib/automateit/package_manager/apt.rb +27 -0
- data/lib/automateit/package_manager/cpan.rb +101 -0
- data/lib/automateit/package_manager/dpkg.rb +54 -0
- data/lib/automateit/package_manager/egg.rb +64 -0
- data/lib/automateit/package_manager/gem.rb +201 -0
- data/lib/automateit/package_manager/pear.rb +95 -0
- data/lib/automateit/package_manager/pecl.rb +80 -0
- data/lib/automateit/package_manager/portage.rb +69 -0
- data/lib/automateit/package_manager/yum.rb +65 -0
- data/lib/automateit/platform_manager.rb +49 -0
- data/lib/automateit/platform_manager/darwin.rb +30 -0
- data/lib/automateit/platform_manager/debian.rb +26 -0
- data/lib/automateit/platform_manager/freebsd.rb +29 -0
- data/lib/automateit/platform_manager/gentoo.rb +26 -0
- data/lib/automateit/platform_manager/lsb.rb +44 -0
- data/lib/automateit/platform_manager/openbsd.rb +28 -0
- data/lib/automateit/platform_manager/struct.rb +80 -0
- data/lib/automateit/platform_manager/sunos.rb +39 -0
- data/lib/automateit/platform_manager/uname.rb +29 -0
- data/lib/automateit/platform_manager/windows.rb +40 -0
- data/lib/automateit/plugin.rb +7 -0
- data/lib/automateit/plugin/base.rb +32 -0
- data/lib/automateit/plugin/driver.rb +256 -0
- data/lib/automateit/plugin/manager.rb +224 -0
- data/lib/automateit/project.rb +493 -0
- data/lib/automateit/root.rb +17 -0
- data/lib/automateit/service_manager.rb +93 -0
- data/lib/automateit/service_manager/chkconfig.rb +39 -0
- data/lib/automateit/service_manager/rc_update.rb +37 -0
- data/lib/automateit/service_manager/sysv.rb +139 -0
- data/lib/automateit/service_manager/update_rcd.rb +35 -0
- data/lib/automateit/shell_manager.rb +316 -0
- data/lib/automateit/shell_manager/base_link.rb +67 -0
- data/lib/automateit/shell_manager/link.rb +24 -0
- data/lib/automateit/shell_manager/portable.rb +523 -0
- data/lib/automateit/shell_manager/symlink.rb +32 -0
- data/lib/automateit/shell_manager/which_base.rb +30 -0
- data/lib/automateit/shell_manager/which_unix.rb +16 -0
- data/lib/automateit/shell_manager/which_windows.rb +20 -0
- data/lib/automateit/tag_manager.rb +127 -0
- data/lib/automateit/tag_manager/struct.rb +121 -0
- data/lib/automateit/tag_manager/tag_parser.rb +93 -0
- data/lib/automateit/tag_manager/yaml.rb +29 -0
- data/lib/automateit/template_manager.rb +56 -0
- data/lib/automateit/template_manager/base.rb +181 -0
- data/lib/automateit/template_manager/erb.rb +17 -0
- data/lib/ext/metaclass.rb +17 -0
- data/lib/ext/object.rb +18 -0
- data/lib/ext/shell_escape.rb +7 -0
- data/lib/hashcache.rb +22 -0
- data/lib/helpful_erb.rb +63 -0
- data/lib/inactive_support.rb +53 -0
- data/lib/inactive_support/basic_object.rb +6 -0
- data/lib/inactive_support/clean_logger.rb +127 -0
- data/lib/inactive_support/core_ext/array/extract_options.rb +19 -0
- data/lib/inactive_support/core_ext/blank.rb +50 -0
- data/lib/inactive_support/core_ext/class/attribute_accessors.rb +48 -0
- data/lib/inactive_support/core_ext/class/inheritable_attributes.rb +140 -0
- data/lib/inactive_support/core_ext/enumerable.rb +63 -0
- data/lib/inactive_support/core_ext/hash/keys.rb +54 -0
- data/lib/inactive_support/core_ext/module/aliasing.rb +70 -0
- data/lib/inactive_support/core_ext/numeric/time.rb +91 -0
- data/lib/inactive_support/core_ext/string/inflections.rb +153 -0
- data/lib/inactive_support/core_ext/symbol.rb +14 -0
- data/lib/inactive_support/core_ext/time/conversions.rb +96 -0
- data/lib/inactive_support/duration.rb +96 -0
- data/lib/inactive_support/inflections.rb +53 -0
- data/lib/inactive_support/inflector.rb +282 -0
- data/lib/nested_error.rb +33 -0
- data/lib/nitpick.rb +33 -0
- data/lib/queued_logger.rb +68 -0
- data/lib/tempster.rb +250 -0
- data/misc/index_gem_repository.rb +304 -0
- data/misc/setup_egg.rb +12 -0
- data/misc/setup_gem_dependencies.sh +6 -0
- data/misc/setup_rubygems.sh +21 -0
- metadata +279 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
# == TagManager::YAML
|
2
|
+
#
|
3
|
+
# A TagManager driver that reads tags from a YAML file.
|
4
|
+
class AutomateIt::TagManager::YAML < AutomateIt::TagManager::Struct
|
5
|
+
depends_on :nothing
|
6
|
+
|
7
|
+
def suitability(method, *args) # :nodoc:
|
8
|
+
return 5
|
9
|
+
end
|
10
|
+
|
11
|
+
# Options:
|
12
|
+
# * :file -- File to read tags from. The file is preprocessed with ERB and
|
13
|
+
# must produce YAML content.
|
14
|
+
def setup(opts={})
|
15
|
+
if filename = opts.delete(:file)
|
16
|
+
contents = _read(filename)
|
17
|
+
output = HelpfulERB.new(contents, filename).result
|
18
|
+
|
19
|
+
text = AutomateIt::TagManager::TagParser.normalize(output)
|
20
|
+
opts[:struct] = ::YAML::load(text)
|
21
|
+
end
|
22
|
+
super(opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def _read(filename)
|
26
|
+
return File.read(filename)
|
27
|
+
end
|
28
|
+
private :_read
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# == TemplateManager
|
2
|
+
#
|
3
|
+
# TemplateManager renders templates to files.
|
4
|
+
#
|
5
|
+
# See the #render method for details.
|
6
|
+
class AutomateIt::TemplateManager < AutomateIt::Plugin::Manager
|
7
|
+
alias_methods :render
|
8
|
+
|
9
|
+
# Render a template.
|
10
|
+
#
|
11
|
+
# You may specify the +source+ and +target+ as arguments or options. For
|
12
|
+
# example, <tt>render(:file => "input", :to => "output")</tt> is the same as
|
13
|
+
# <tt>render("input", "output")</tt>.
|
14
|
+
#
|
15
|
+
# Options:
|
16
|
+
# * :file -- Read the template from this file.
|
17
|
+
# * :text -- Read the template from this string.
|
18
|
+
# * :to -- Render to a file, otherwise returns the rendered string.
|
19
|
+
# * :locals -- Hash of variables passed to template as local variables.
|
20
|
+
# * :dependencies -- Array of filenames to check timestamps on, only used
|
21
|
+
# when :check is :timestamp.
|
22
|
+
# * :backup -- Make a backup? Default is true.
|
23
|
+
# * :force -- Render without making a check. Default is false.
|
24
|
+
# * :check -- Determines when to render, otherwise uses value of
|
25
|
+
# +default_check+, possible values:
|
26
|
+
# * :compare -- Only render if rendered template is different than the
|
27
|
+
# target's contents or if the target doesn't exist.
|
28
|
+
# * :timestamp -- Only render if the target is older than the template and
|
29
|
+
# dependencies.
|
30
|
+
# * :exists -- Only render if the target doesn't exist.
|
31
|
+
#
|
32
|
+
# For example, if the file +my_template_file+ contains:
|
33
|
+
#
|
34
|
+
# Hello <%=entity%>!
|
35
|
+
#
|
36
|
+
# You could then execute:
|
37
|
+
#
|
38
|
+
# render("my_template_file", "/tmp/out", :check => :compare,
|
39
|
+
# :locals => {:entity => "world"})
|
40
|
+
#
|
41
|
+
# And this will create a <tt>/tmp/out</tt> file with:
|
42
|
+
#
|
43
|
+
# Hello world!
|
44
|
+
def render(*options) dispatch(*options) end
|
45
|
+
|
46
|
+
# Get name of default algorithm for performing checks.
|
47
|
+
def default_check() dispatch() end
|
48
|
+
|
49
|
+
# Set name of default algorithms to perform checks, e.g., :compare. See the
|
50
|
+
# #render :check option for list of check algorithms.
|
51
|
+
def default_check=(value) dispatch(value) end
|
52
|
+
end # class TemplateManager
|
53
|
+
|
54
|
+
# Drivers
|
55
|
+
require 'automateit/template_manager/base.rb'
|
56
|
+
require 'automateit/template_manager/erb.rb'
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# == TemplateManager::BaseDriver
|
2
|
+
#
|
3
|
+
# Base class for all TemplateManager drivers.
|
4
|
+
class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
|
5
|
+
# Name of default algorithm for performing checks, e.g., :compare
|
6
|
+
attr_accessor :default_check
|
7
|
+
|
8
|
+
# Options:
|
9
|
+
# * :default_check - Set the #default_check, e.g., :compare
|
10
|
+
def setup(opts={})
|
11
|
+
super(opts)
|
12
|
+
if opts[:default_check]
|
13
|
+
@default_check = opts[:default_check]
|
14
|
+
else
|
15
|
+
@default_check ||= :compare
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#.......................................................................
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
# Return Array of +dependencies+ newer than +filename+. Will be empty if
|
24
|
+
# +filename+ is newer than all of the +dependencies+.
|
25
|
+
def _newer(filename, *dependencies)
|
26
|
+
updated = []
|
27
|
+
timestamp = _mtime(filename)
|
28
|
+
for dependency in dependencies
|
29
|
+
updated << dependency if _mtime(dependency) > timestamp
|
30
|
+
end
|
31
|
+
return updated
|
32
|
+
end
|
33
|
+
|
34
|
+
# Does +filename+ exist?
|
35
|
+
def _exists?(filename)
|
36
|
+
return File.exists?(filename)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the contents of +filename+.
|
40
|
+
def _read(filename)
|
41
|
+
begin
|
42
|
+
result = File.read(filename)
|
43
|
+
return result
|
44
|
+
rescue Errno::ENOENT => e
|
45
|
+
if writing?
|
46
|
+
raise e
|
47
|
+
else
|
48
|
+
return ""
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Write +contents+ to +filename+.
|
54
|
+
def _write(filename, contents)
|
55
|
+
File.open(filename, "w+"){|writer| writer.write(contents)} if writing?
|
56
|
+
return true
|
57
|
+
end
|
58
|
+
|
59
|
+
# Backup +filename+.
|
60
|
+
def _backup(filename)
|
61
|
+
interpreter.backup(filename)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return the modification date for +filename+.
|
65
|
+
def _mtime(filename)
|
66
|
+
return _exists? ? File.mtime(filename) : nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# Render a template specified in the block. It takes the same arguments and
|
70
|
+
# returns the same results as the #render call.
|
71
|
+
#
|
72
|
+
# This method is used by the #render methods for different template drivers
|
73
|
+
# and provides all the logic for parsing arguments, figuring out if a
|
74
|
+
# template should be rendered, what to do with the rendering, etc.
|
75
|
+
#
|
76
|
+
# This method calls the supplied +block+ with a hash containing:
|
77
|
+
# * :text -- Template's text.
|
78
|
+
# * :filename -- Template's filename, or nil if none. The template
|
79
|
+
# * :binder -- Binding containing the locals as variables.
|
80
|
+
# * :locals -- Hash of locals.
|
81
|
+
# * :opts -- Hash of options passed to the #_render_helper.
|
82
|
+
#
|
83
|
+
# The supplied block must return the text of the rendered template.
|
84
|
+
#
|
85
|
+
# See the TemplateManager::ERB#render method for a usage example.
|
86
|
+
def _render_helper(*options, &block) # :yields: block_opts
|
87
|
+
args, opts = args_and_opts(*options)
|
88
|
+
source_filename = args[0] || opts[:file]
|
89
|
+
target_filename = args[1] || opts[:to]
|
90
|
+
source_text = opts[:text]
|
91
|
+
opts[:backup] = true if opts[:backup].nil?
|
92
|
+
|
93
|
+
raise ArgumentError.new("No source specified with :file or :text") if not source_filename and not source_text
|
94
|
+
raise Errno::ENOENT.new(source_filename) if writing? and source_filename and not _exists?(source_filename)
|
95
|
+
|
96
|
+
begin
|
97
|
+
# source_filename, target_filename, opts={}
|
98
|
+
opts[:check] ||= @default_check
|
99
|
+
target_exists = target_filename && _exists?(target_filename)
|
100
|
+
updates = []
|
101
|
+
|
102
|
+
if target_filename
|
103
|
+
unless opts[:force]
|
104
|
+
case opts[:check]
|
105
|
+
when :exists
|
106
|
+
if target_exists
|
107
|
+
log.debug(PNOTE+"Rendering for '#{target_filename}' skipped because it already exists")
|
108
|
+
return false
|
109
|
+
else
|
110
|
+
log.info(PNOTE+"Rendering '#{target_filename}' because of it doesn't exist")
|
111
|
+
end
|
112
|
+
when :timestamp
|
113
|
+
if target_exists
|
114
|
+
updates = _newer(target_filename, \
|
115
|
+
*[source_filename, opts[:dependencies]].reject{|t| t.nil?}.flatten)
|
116
|
+
if updates.empty?
|
117
|
+
log.debug(PNOTE+"Rendering for '#{target_filename}' skipped because dependencies haven't been updated")
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
target_contents = target_exists ? _read(target_filename) : ""
|
126
|
+
source_text ||= _read(source_filename)
|
127
|
+
|
128
|
+
if source_text.blank? and preview?
|
129
|
+
return true
|
130
|
+
end
|
131
|
+
|
132
|
+
binder = nil
|
133
|
+
if opts[:locals]
|
134
|
+
# Create a binding that the template can get variables from without
|
135
|
+
# polluting the Driver's namespace.
|
136
|
+
callback = lambda{
|
137
|
+
code = ""
|
138
|
+
for key in opts[:locals].keys
|
139
|
+
code << "#{key} = opts[:locals][:#{key}]\n"
|
140
|
+
end
|
141
|
+
eval code
|
142
|
+
binding
|
143
|
+
}
|
144
|
+
binder = callback.call
|
145
|
+
end
|
146
|
+
|
147
|
+
block_opts = {
|
148
|
+
:binder => binder,
|
149
|
+
:filename => source_filename,
|
150
|
+
:text => source_text,
|
151
|
+
:locals => opts[:locals],
|
152
|
+
:opts => opts,
|
153
|
+
}
|
154
|
+
output = block.call(block_opts)
|
155
|
+
|
156
|
+
if target_filename
|
157
|
+
case opts[:check]
|
158
|
+
when :compare
|
159
|
+
if not target_exists
|
160
|
+
log.info(PNOTE+"Rendering '#{target_filename}' because of it doesn't exist")
|
161
|
+
elsif output == target_contents
|
162
|
+
log.debug(PNOTE+"Rendering for '#{target_filename}' skipped because contents are the same")
|
163
|
+
return false
|
164
|
+
else
|
165
|
+
log.info(PNOTE+"Rendering '#{target_filename}' because its contents changed")
|
166
|
+
end
|
167
|
+
when :timestamp
|
168
|
+
log.info(PNOTE+"Rendering '#{target_filename}' because of updated: #{updates.join(' ')}")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
_backup(target_filename) if target_exists and opts[:backup]
|
173
|
+
|
174
|
+
return(target_filename ? _write(target_filename, output) : output)
|
175
|
+
ensure
|
176
|
+
if opts[:mode] or opts[:user] or opts[:group]
|
177
|
+
interpreter.chperm(target_filename, :mode => opts[:mode], :user => opts[:user], :group => opts[:group])
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# == TemplateManager::ERB
|
2
|
+
#
|
3
|
+
# Renders ERB templates for TemplateManager.
|
4
|
+
class AutomateIt::TemplateManager::ERB < AutomateIt::TemplateManager::BaseDriver
|
5
|
+
depends_on :nothing
|
6
|
+
|
7
|
+
def suitability(method, *args) # :nodoc:
|
8
|
+
return 1
|
9
|
+
end
|
10
|
+
|
11
|
+
# See documentation for TemplateManager#render
|
12
|
+
def render(*options)
|
13
|
+
return _render_helper(*options) do |o|
|
14
|
+
HelpfulERB.new(o[:text], o[:filename]).result(o[:binder])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# The hidden singleton lurks behind everyone
|
5
|
+
def metaclass; class << self; self; end; end
|
6
|
+
def meta_eval(&blk); metaclass.instance_eval(&blk); end
|
7
|
+
|
8
|
+
# Adds methods to a metaclass
|
9
|
+
def meta_def name, &blk
|
10
|
+
meta_eval { define_method name, &blk }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Defines an instance method within a class
|
14
|
+
def class_def name, &blk
|
15
|
+
class_eval { define_method name, &blk }
|
16
|
+
end
|
17
|
+
end
|
data/lib/ext/object.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class Object
|
2
|
+
# Lists methods unique to an instance.
|
3
|
+
def unique_methods
|
4
|
+
(public_methods - Object.methods).sort.map(&:to_sym)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Lists methods unique to a class.
|
8
|
+
def self.unique_methods
|
9
|
+
(public_methods - Object.methods).sort.map(&:to_sym)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a list of arguments and an options hash. Source taken from RSpec.
|
13
|
+
def args_and_opts(*args)
|
14
|
+
options = Hash === args.last ? args.pop : {}
|
15
|
+
return args, options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/lib/hashcache.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# A very simple cache. Works just like a Hash, but can optionally store values
|
2
|
+
# during the fetch process.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
# hc = HashCache.new
|
6
|
+
# hc.fetch("foo")
|
7
|
+
# => nil
|
8
|
+
# hc.fetch("foo"){:bar} # Block gets called because 'foo' is nil
|
9
|
+
# => :bar
|
10
|
+
# hc.fetch("foo"){raise "Block won't be called because 'foo' is cached"}
|
11
|
+
# => :bar
|
12
|
+
class HashCache < Hash
|
13
|
+
def fetch(key, &block)
|
14
|
+
if has_key?(key)
|
15
|
+
self[key]
|
16
|
+
elsif block
|
17
|
+
self[key] = block.call
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/helpful_erb.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'nested_error'
|
3
|
+
|
4
|
+
class HelpfulERB
|
5
|
+
class Error < ::NestedError; end
|
6
|
+
|
7
|
+
# ERB object
|
8
|
+
attr_accessor :erb
|
9
|
+
|
10
|
+
attr_accessor :lines_before
|
11
|
+
|
12
|
+
attr_accessor :lines_after
|
13
|
+
|
14
|
+
# Template filename
|
15
|
+
attr_accessor :filename
|
16
|
+
|
17
|
+
def initialize(text, filename=nil, opts={})
|
18
|
+
@text = text
|
19
|
+
@filename = filename
|
20
|
+
@lines_before = opts[:before] || 5
|
21
|
+
@lines_after = opts[:before] || 1
|
22
|
+
|
23
|
+
@erb = ::ERB.new(@text, nil, '-')
|
24
|
+
@erb.filename = @filename if @filename
|
25
|
+
end
|
26
|
+
|
27
|
+
def result(binder=nil)
|
28
|
+
begin
|
29
|
+
return @erb.result(binder)
|
30
|
+
rescue Exception => e
|
31
|
+
stack = caller 0
|
32
|
+
for i in 0..e.backtrace.size
|
33
|
+
l = e.backtrace[i]
|
34
|
+
#puts "%s %s" % [i, l];
|
35
|
+
break if l =~ /^([^:]+):(\d+):in `(render|result)'$/
|
36
|
+
end
|
37
|
+
template = $1
|
38
|
+
line_number = $2.to_i
|
39
|
+
raise Exception.new("Caught ERB error but couldn't find line number in backtrace:\n#{e.backtrace.join("\n")}") unless line_number
|
40
|
+
|
41
|
+
lines = @text.split(/\n/)
|
42
|
+
|
43
|
+
min = line_number - @lines_before
|
44
|
+
min = 0 if min < 0
|
45
|
+
|
46
|
+
max = line_number + @lines_after
|
47
|
+
max = lines.size if max > lines.size
|
48
|
+
|
49
|
+
width = max.to_s.size
|
50
|
+
|
51
|
+
msg = "Problem with template '#{template}' at line #{line_number}:\n"
|
52
|
+
for i in min..max
|
53
|
+
n = i+1
|
54
|
+
marker = n == line_number ? "*" : ""
|
55
|
+
msg << "\n%2s %#{width}i %s" % [marker, n, lines[i]]
|
56
|
+
end
|
57
|
+
msg << "\n\n(#{e.exception.class}) #{e.message}"
|
58
|
+
|
59
|
+
|
60
|
+
raise NestedError.new(msg, e)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# == InactiveSupport
|
2
|
+
#
|
3
|
+
# InactiveSupport is a subset of features copied from the Rails ActiveSupport
|
4
|
+
# 2.0.2 library, and retain the same ownership and licensing as the originals.
|
5
|
+
#
|
6
|
+
# Using this subset of ActiveSupport makes AutomateIt:
|
7
|
+
# * More reliable: InactiveSupport is guaranteed correctly to work because it's
|
8
|
+
# part of AutomateIt. This is in contrast to ActiveSupport, which is
|
9
|
+
# versioned separately and regularly introduces new bugs and breaks backwards
|
10
|
+
# compatibility, which makes it unsuitable as a library.
|
11
|
+
# * Easier and faster install: Installing AutomateIt is easier and faster
|
12
|
+
# because it no longer needs the ActiveSupport and Builder gems..
|
13
|
+
# * Quicker startup: InactiveSupport loads in a fraction of the time that
|
14
|
+
# ActiveSupport takes.
|
15
|
+
|
16
|
+
require 'inactive_support/core_ext/array/extract_options' # [].extract_options
|
17
|
+
class Array
|
18
|
+
include InactiveSupport::CoreExtensions::Array::ExtractOptions
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'inactive_support/core_ext/blank' # foo.blank?
|
22
|
+
require 'inactive_support/core_ext/symbol' # [:foo, :bar].map(&:to_s)
|
23
|
+
require 'inactive_support/core_ext/module/aliasing' # alias_method_chain
|
24
|
+
require 'inactive_support/core_ext/class/attribute_accessors' # cattr_accessor
|
25
|
+
require 'inactive_support/core_ext/class/inheritable_attributes' # inheritable_cattr_accessor
|
26
|
+
require 'inactive_support/core_ext/enumerable' # sum
|
27
|
+
|
28
|
+
require 'inactive_support/core_ext/numeric/time' # 1.day
|
29
|
+
class Numeric
|
30
|
+
include InactiveSupport::CoreExtensions::Numeric::Time
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'inactive_support/core_ext/string/inflections' # "asdf".demodulize.underscore
|
34
|
+
class String
|
35
|
+
include InactiveSupport::CoreExtensions::String::Inflections
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'inactive_support/core_ext/hash/keys' # {:foo => :bar}.stringify_keys
|
39
|
+
class Hash
|
40
|
+
include InactiveSupport::CoreExtensions::Hash::Keys
|
41
|
+
end
|
42
|
+
|
43
|
+
# since used with rails, this is conflict
|
44
|
+
#require 'inactive_support/basic_object' # Ruby 1.9 compatibility
|
45
|
+
require 'inactive_support/duration' # adds dates
|
46
|
+
|
47
|
+
require 'inactive_support/core_ext/time/conversions' # to_formatted_s
|
48
|
+
class Time
|
49
|
+
include InactiveSupport::CoreExtensions::Time::Conversions
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#require 'inactive_support/clean_logger' # cleans up Logger output
|