automate-it 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|