loom-core 0.0.1
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 +1 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +99 -0
- data/Guardfile +54 -0
- data/Rakefile +6 -0
- data/bin/loom +185 -0
- data/lib/env/development.rb +1 -0
- data/lib/loom.rb +44 -0
- data/lib/loom/all.rb +20 -0
- data/lib/loom/config.rb +106 -0
- data/lib/loom/core_ext.rb +37 -0
- data/lib/loom/dsl.rb +60 -0
- data/lib/loom/facts.rb +13 -0
- data/lib/loom/facts/all.rb +2 -0
- data/lib/loom/facts/fact_file_provider.rb +86 -0
- data/lib/loom/facts/fact_set.rb +138 -0
- data/lib/loom/host_spec.rb +32 -0
- data/lib/loom/inventory.rb +124 -0
- data/lib/loom/logger.rb +141 -0
- data/lib/loom/method_signature.rb +174 -0
- data/lib/loom/mods.rb +4 -0
- data/lib/loom/mods/action_proxy.rb +105 -0
- data/lib/loom/mods/all.rb +3 -0
- data/lib/loom/mods/mod_loader.rb +80 -0
- data/lib/loom/mods/module.rb +113 -0
- data/lib/loom/pattern.rb +15 -0
- data/lib/loom/pattern/all.rb +7 -0
- data/lib/loom/pattern/definition_context.rb +74 -0
- data/lib/loom/pattern/dsl.rb +176 -0
- data/lib/loom/pattern/hook.rb +28 -0
- data/lib/loom/pattern/loader.rb +48 -0
- data/lib/loom/pattern/reference.rb +71 -0
- data/lib/loom/pattern/reference_set.rb +169 -0
- data/lib/loom/pattern/result_reporter.rb +77 -0
- data/lib/loom/runner.rb +209 -0
- data/lib/loom/shell.rb +12 -0
- data/lib/loom/shell/all.rb +10 -0
- data/lib/loom/shell/api.rb +48 -0
- data/lib/loom/shell/cmd_result.rb +33 -0
- data/lib/loom/shell/cmd_wrapper.rb +164 -0
- data/lib/loom/shell/core.rb +226 -0
- data/lib/loom/shell/harness_blob.rb +26 -0
- data/lib/loom/shell/harness_command_builder.rb +50 -0
- data/lib/loom/shell/session.rb +25 -0
- data/lib/loom/trap.rb +44 -0
- data/lib/loom/version.rb +3 -0
- data/lib/loomext/all.rb +4 -0
- data/lib/loomext/corefacts.rb +6 -0
- data/lib/loomext/corefacts/all.rb +8 -0
- data/lib/loomext/corefacts/facter_provider.rb +24 -0
- data/lib/loomext/coremods.rb +5 -0
- data/lib/loomext/coremods/all.rb +13 -0
- data/lib/loomext/coremods/exec.rb +50 -0
- data/lib/loomext/coremods/files.rb +104 -0
- data/lib/loomext/coremods/net.rb +33 -0
- data/lib/loomext/coremods/package/adapter.rb +100 -0
- data/lib/loomext/coremods/package/package.rb +62 -0
- data/lib/loomext/coremods/user.rb +82 -0
- data/lib/loomext/coremods/vm.rb +0 -0
- data/lib/loomext/coremods/vm/all.rb +6 -0
- data/lib/loomext/coremods/vm/vbox.rb +84 -0
- data/loom.gemspec +39 -0
- data/loom/inventory.yml +13 -0
- data/scripts/harness.sh +242 -0
- data/spec/loom/host_spec_spec.rb +101 -0
- data/spec/loom/inventory_spec.rb +154 -0
- data/spec/loom/method_signature_spec.rb +275 -0
- data/spec/loom/pattern/dsl_spec.rb +207 -0
- data/spec/loom/shell/cmd_wrapper_spec.rb +239 -0
- data/spec/loom/shell/harness_blob_spec.rb +42 -0
- data/spec/loom/shell/harness_command_builder_spec.rb +36 -0
- data/spec/runloom.sh +35 -0
- data/spec/scripts/harness_spec.rb +385 -0
- data/spec/spec_helper.rb +94 -0
- data/spec/test.loom +370 -0
- data/spec/test_loom_spec.rb +57 -0
- metadata +287 -0
data/lib/loom/logger.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Loom
|
4
|
+
class Logger
|
5
|
+
COLOR_MAP = {
|
6
|
+
:d => :green,
|
7
|
+
:i => :blue,
|
8
|
+
:w => :yellow,
|
9
|
+
:e => :red,
|
10
|
+
:f => :pink
|
11
|
+
}
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def configure(config)
|
15
|
+
device = configure_device config.log_device
|
16
|
+
|
17
|
+
logger = ::Logger.new device
|
18
|
+
class << logger
|
19
|
+
include LoggerDebugLevels
|
20
|
+
end
|
21
|
+
raise "missing logger debug methods" unless logger.respond_to? :debug1
|
22
|
+
|
23
|
+
logger.level = case config.log_level
|
24
|
+
when Symbol, String
|
25
|
+
::Logger.const_get config.log_level.to_s.upcase
|
26
|
+
when Integer
|
27
|
+
# Negative numbers can be used for detailed debug levels
|
28
|
+
config.log_level
|
29
|
+
end
|
30
|
+
|
31
|
+
colorize = config.log_colorize && device.tty?
|
32
|
+
logger.formatter = default_formatter colorize
|
33
|
+
|
34
|
+
if config.log_colorize && !device.tty?
|
35
|
+
logger.warn "disabled log colorization for non-tty"
|
36
|
+
end
|
37
|
+
|
38
|
+
logger
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def configure_device(device_value)
|
43
|
+
case device_value
|
44
|
+
when :stderr, 'stderr'
|
45
|
+
STDERR
|
46
|
+
when :stdout, 'stdout'
|
47
|
+
STDOUT
|
48
|
+
when :devnull, 'devnull'
|
49
|
+
File.new '/dev/null', 'a'
|
50
|
+
when Integer
|
51
|
+
IO.new device_value, 'a'
|
52
|
+
when String
|
53
|
+
File.new device_value, 'a'
|
54
|
+
when StringIO
|
55
|
+
device_value
|
56
|
+
else
|
57
|
+
raise ConfigError, "log_device => #{device_value}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def default_formatter(colorize)
|
62
|
+
lambda do |severity, datetime, progname, msg|
|
63
|
+
s_key = severity[0].downcase.to_sym
|
64
|
+
if colorize && COLOR_MAP[s_key]
|
65
|
+
severity = Styleizer.apply severity, COLOR_MAP[s_key]
|
66
|
+
progname = Styleizer.apply progname, :bold, :dark_gray
|
67
|
+
end
|
68
|
+
|
69
|
+
if progname
|
70
|
+
"[%s] (%s): %s\n" % [severity, progname, msg]
|
71
|
+
else
|
72
|
+
"[%s] %s\n" % [severity, msg]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module LoggerDebugLevels
|
79
|
+
NUM_DEBUG_LEVELS = 6
|
80
|
+
|
81
|
+
##
|
82
|
+
# Adds methods debug1, debug2, ... debug6 for more detailed
|
83
|
+
# debug levels. Set a negative index +logger.level+ to enable
|
84
|
+
# lower levels, e.g. logger.level = -6 for debug6 messages.
|
85
|
+
(1..NUM_DEBUG_LEVELS).to_a.each do |debug_level|
|
86
|
+
debug_method_name = "debug#{debug_level}"
|
87
|
+
|
88
|
+
define_method debug_method_name do |*args, &block|
|
89
|
+
severity = debug_level * -1
|
90
|
+
return if severity < self.level
|
91
|
+
|
92
|
+
debug_at_level severity, *args, &block
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def format_severity(severity)
|
97
|
+
if severity < ::Logger::DEBUG
|
98
|
+
return "D" + severity.abs.to_s
|
99
|
+
else
|
100
|
+
super(severity)[0]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
def debug_at_level(severity, progname=nil, &block)
|
106
|
+
raise 'block required for super debug loggers' unless block_given?
|
107
|
+
raise 'progname required for super debug loggers' unless progname
|
108
|
+
|
109
|
+
add severity, nil, progname, &block
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class Styleizer
|
114
|
+
class << self
|
115
|
+
|
116
|
+
STYLE_CODES = {
|
117
|
+
:bold => 1,
|
118
|
+
:red => 31,
|
119
|
+
:green => 32,
|
120
|
+
:yellow => 33,
|
121
|
+
:blue => 34,
|
122
|
+
:pink => 35,
|
123
|
+
:light_blue => 36,
|
124
|
+
:light_gray => 37,
|
125
|
+
:dark_gray => 90
|
126
|
+
}
|
127
|
+
|
128
|
+
def apply(str, *styles)
|
129
|
+
return str unless str
|
130
|
+
styles.reduce(str) { |str, style| styleize STYLE_CODES[style], str }
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
def styleize(color_code, str)
|
135
|
+
"\e[#{color_code}m#{str}\e[0m"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module Loom
|
2
|
+
|
3
|
+
# Used to analyze the arguments of a method.
|
4
|
+
class MethodSignature
|
5
|
+
|
6
|
+
module ParamType
|
7
|
+
REQ = :req
|
8
|
+
OPT = :opt
|
9
|
+
REST = :rest
|
10
|
+
KEYREQ = :keyreq
|
11
|
+
KEY = :key
|
12
|
+
KEYREST = :keyrest
|
13
|
+
BLOCK = :block
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param proc_or_method [#parameters] A {Proc} or {Method}
|
17
|
+
def initialize(proc_or_method)
|
18
|
+
@parameter_list = proc_or_method.parameters
|
19
|
+
@req_args = find_by_type ParamType::REQ
|
20
|
+
@opt_args = find_by_type ParamType::OPT
|
21
|
+
@rest_args = find_by_type ParamType::REST
|
22
|
+
@keyreq_args = find_by_type ParamType::KEYREQ
|
23
|
+
@key_args = find_by_type ParamType::KEY
|
24
|
+
@keyrest_args = find_by_type ParamType::KEYREST
|
25
|
+
@block_args = find_by_type ParamType::BLOCK
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :req_args, :opt_args, :rest_args, :keyreq_args, :key_args,
|
29
|
+
:keyrest_args, :block_args
|
30
|
+
|
31
|
+
def find_by_type(type)
|
32
|
+
@parameter_list.find_all { |tuple| tuple.first == type }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Defines has_xyz_args? methods for each {ParamType}.
|
36
|
+
def method_missing(name, *args)
|
37
|
+
match_data = name.to_s.match /^has_([^?]+)_args\?$/
|
38
|
+
if match_data
|
39
|
+
method = "%s_args" % [match_data[1]]
|
40
|
+
!self.send(method.to_sym).empty?
|
41
|
+
else
|
42
|
+
super name, *args
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class MatchSpec
|
47
|
+
|
48
|
+
class Builder
|
49
|
+
def initialize
|
50
|
+
@map = {
|
51
|
+
:req_args => 0,
|
52
|
+
:opt_args => 0,
|
53
|
+
:has_rest_args => false,
|
54
|
+
:keyreq_args => 0,
|
55
|
+
:key_args => 0,
|
56
|
+
:has_keyrest_args => false,
|
57
|
+
:has_block => false
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing(name, value, *args)
|
62
|
+
@map[name.to_sym] = value
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def build
|
67
|
+
MatchSpec.new(@map || {})
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
def builder
|
73
|
+
Builder.new
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param req_args [Fixnum] Number of required args, nil for any.
|
78
|
+
# @param opt_args [Fixnum] Number of optional args, nil for any.
|
79
|
+
# @param has_rest_args [Boolean] Whether a *args is defined, nil
|
80
|
+
# for any. If +has_rest_args+ is true then any number of req or opt
|
81
|
+
# args will satisfy this match.
|
82
|
+
# @param keyreq_args [Fixnum] Number of required keyward args, nil
|
83
|
+
# for any.
|
84
|
+
# @param key_args [Fixnum] Number of optional keyward args, nil
|
85
|
+
# for any.
|
86
|
+
# @param has_keyrest_args [Boolean] Whether a **opts is defined,
|
87
|
+
# nil for any. If +has_keyrest_args+ is true, then any number of
|
88
|
+
# keyreq or key args will satisfy this match for name named opts.
|
89
|
+
# @param has_block [Boolean] Whether a block is defined, nil for any.
|
90
|
+
def initialize(
|
91
|
+
req_args: nil,
|
92
|
+
opt_args: nil,
|
93
|
+
has_rest_args: nil,
|
94
|
+
keyreq_args: nil,
|
95
|
+
key_args: nil,
|
96
|
+
has_keyrest_args: nil,
|
97
|
+
has_block: nil)
|
98
|
+
@req_args = req_args
|
99
|
+
@opt_args = opt_args
|
100
|
+
@has_rest_args = has_rest_args
|
101
|
+
@keyreq_args = keyreq_args
|
102
|
+
@key_args = key_args
|
103
|
+
@has_keyrest_args = has_keyrest_args
|
104
|
+
@has_block = has_block
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [Boolean]
|
108
|
+
def match?(method)
|
109
|
+
method_sig = MethodSignature.new method
|
110
|
+
|
111
|
+
# *args definition matches any call.
|
112
|
+
return true if @has_rest_args
|
113
|
+
|
114
|
+
check_ordered_args(method_sig) &&
|
115
|
+
check_keyword_args(method_sig) &&
|
116
|
+
check_block_args(method_sig)
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
def check_ordered_args(method_sig)
|
121
|
+
rest = check_rest(method_sig)
|
122
|
+
if rest && method_sig.has_rest_args?
|
123
|
+
Loom.log.debug1(self) { "returning from failed addon look"}
|
124
|
+
return true
|
125
|
+
end
|
126
|
+
|
127
|
+
return rest &&
|
128
|
+
check_req_args(method_sig) &&
|
129
|
+
check_opt_args(method_sig);
|
130
|
+
end
|
131
|
+
|
132
|
+
def check_rest(method_sig)
|
133
|
+
@has_rest_args.nil? || method_sig.has_rest_args? == @has_rest_args
|
134
|
+
end
|
135
|
+
|
136
|
+
def check_req_args(method_sig)
|
137
|
+
@req_args.nil? || @req_args == method_sig.req_args.size
|
138
|
+
end
|
139
|
+
|
140
|
+
def check_opt_args(method_sig)
|
141
|
+
@opt_args.nil? || @opt_args == method_sig.opt_args.size
|
142
|
+
end
|
143
|
+
|
144
|
+
def check_keyword_args(method_sig)
|
145
|
+
return true if @has_keyrest_args
|
146
|
+
|
147
|
+
return check_keyrest(method_sig) &&
|
148
|
+
check_keyreq_args(method_sig) &&
|
149
|
+
check_key_args(method_sig);
|
150
|
+
end
|
151
|
+
|
152
|
+
def check_keyrest(method_sig)
|
153
|
+
@has_keyrest_args.nil? || method_sig.has_keyrest_args? == @has_keyrest_args
|
154
|
+
end
|
155
|
+
|
156
|
+
def check_keyreq_args(method_sig)
|
157
|
+
@keyreq_args.nil? ||
|
158
|
+
@keyreq_args == method_sig.keyreq_args.size ||
|
159
|
+
method_sig.has_keyrest_args?
|
160
|
+
end
|
161
|
+
|
162
|
+
def check_key_args(method_sig)
|
163
|
+
@key_args.nil? ||
|
164
|
+
@key_args == method_sig.key_args.size ||
|
165
|
+
method_sig.has_keyrest_args?
|
166
|
+
end
|
167
|
+
|
168
|
+
def check_block_args(method_sig)
|
169
|
+
return true if @has_block.nil?
|
170
|
+
return method_sig.has_block_args? == @has_block
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/loom/mods.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# TODO: The method names in this file are atrocious and confusing, need to
|
2
|
+
# rethink these names and simplify this class.
|
3
|
+
module Loom::Mods
|
4
|
+
class ActionProxy
|
5
|
+
|
6
|
+
def initialize(mod, shell_api)
|
7
|
+
@mod = mod
|
8
|
+
@shell_api = shell_api
|
9
|
+
@nested_action_proxies = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def proxy_for_namespace(ns=nil)
|
13
|
+
ns.nil? ? self : @nested_action_proxies[ns]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def new_action_map
|
20
|
+
ActionMap.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def subclass_for_action_map(action_map)
|
24
|
+
sub_class = Class.new ActionProxy
|
25
|
+
sub_class.install_action_map action_map
|
26
|
+
sub_class
|
27
|
+
end
|
28
|
+
|
29
|
+
def install_action_map(action_map)
|
30
|
+
install_root_actions action_map
|
31
|
+
install_namespace_action_proxies action_map
|
32
|
+
end
|
33
|
+
|
34
|
+
def install_root_actions(action_map)
|
35
|
+
action_map.action_tuples.each do |tuple|
|
36
|
+
public_action_name = tuple[0]
|
37
|
+
# TODO: What I've done here w/ bound_action_name (remapping methods
|
38
|
+
# from a given name to a flattened namespace on the Mod object) is
|
39
|
+
# very very strange. Just storing/binding/calling a Proc would be more
|
40
|
+
# idiomatic.
|
41
|
+
bound_action_name = tuple[1]
|
42
|
+
|
43
|
+
define_method public_action_name do |*args, &block|
|
44
|
+
# TODO: Effectively this is the API for all mods, but it's burried
|
45
|
+
# here in the middle of nowhere. Add documentation - or make it
|
46
|
+
# easier to read.
|
47
|
+
Loom.log.debug2(self) do
|
48
|
+
"proxy to mod #{@mod} => #{public_action_name}: #{args} #{block}"
|
49
|
+
end
|
50
|
+
|
51
|
+
@mod.send bound_action_name, *args, &block
|
52
|
+
end
|
53
|
+
Loom.log.debug2 self do
|
54
|
+
"defined action proxy action: #{public_action_name} => #{bound_action_name}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# This gets a bit tricky
|
61
|
+
def install_namespace_action_proxies(action_map)
|
62
|
+
action_map.ns_actionmaps.each do |ns, ns_action_map|
|
63
|
+
@nested_action_proxy_klasses ||= {}
|
64
|
+
@nested_action_proxy_klasses[self.hash] ||= {}
|
65
|
+
@nested_action_proxy_klasses[self.hash][ns] ||=
|
66
|
+
ActionProxy.subclass_for_action_map ns_action_map
|
67
|
+
action_proxy_klass = @nested_action_proxy_klasses[self.hash][ns]
|
68
|
+
|
69
|
+
define_method ns do
|
70
|
+
@nested_action_proxies[ns] ||= action_proxy_klass.new @mod
|
71
|
+
end
|
72
|
+
Loom.log.debug2 self do
|
73
|
+
"defined action proxy ns: #{ns}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
class ActionMap
|
81
|
+
|
82
|
+
attr_reader :action_tuples, :ns_actionmaps
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
@action_tuples = []
|
86
|
+
@ns_actionmaps = {}
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_action(action_name, bound_method_name, namespace=nil)
|
90
|
+
if namespace.nil?
|
91
|
+
tuple = [action_name, bound_method_name]
|
92
|
+
@action_tuples << tuple unless namespace
|
93
|
+
else
|
94
|
+
# Adds an action name to a nested ActionMap
|
95
|
+
add_namespace(namespace).add_action action_name, bound_method_name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
def add_namespace(ns)
|
101
|
+
@ns_actionmaps[ns] ||= ActionMap.new
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Loom::Mods
|
2
|
+
|
3
|
+
AliasRegisteredError = Class.new Loom::LoomError
|
4
|
+
AnonymousModLoadError = Class.new Loom::LoomError
|
5
|
+
ModDefinedError = Class.new Loom:: LoomError
|
6
|
+
ModNotRegisteredError = Class.new Loom::LoomError
|
7
|
+
|
8
|
+
class ModLoader
|
9
|
+
def initialize(loom_config)
|
10
|
+
@loom_config = loom_config
|
11
|
+
end
|
12
|
+
|
13
|
+
def verify_shell_cmds(shell, mod_klass)
|
14
|
+
Loom.log.debug2(self) { "verifying cmds for mod => #{mod_klass}" }
|
15
|
+
mod_klass.required_commands.each do |cmd|
|
16
|
+
begin
|
17
|
+
shell.verify_which cmd
|
18
|
+
rescue Loom::Shell::VerifyError
|
19
|
+
Loom.log.error "unable to use mod #{mod_klass}, missing required command => #{cmd}"
|
20
|
+
raise $!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
|
27
|
+
def register_mod(klass, name, **opts)
|
28
|
+
name = name.to_sym
|
29
|
+
raise AnonymousModLoadError, 'cannot load anonymous mods' unless name
|
30
|
+
raise ModDefinedError, name if instance_methods.include? name
|
31
|
+
|
32
|
+
define_mod_factory name, klass
|
33
|
+
Loom.log.debug1(self) { "registered mod => #{klass} as #{name}" }
|
34
|
+
|
35
|
+
opts.each do |k,v|
|
36
|
+
case k
|
37
|
+
when :alias
|
38
|
+
[v].flatten.each { |v| alias_module klass, v }
|
39
|
+
else
|
40
|
+
raise "unknown option #{k}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO: add some documentation here, this is the entrypoint for all mod
|
46
|
+
# factories and returning the ActionProxy or running a ModBlock. This is
|
47
|
+
# just as hidden as ActionProxy+install_root_actions+
|
48
|
+
def define_mod_factory(name, mod_klass)
|
49
|
+
raise ModDefinedError, name if instance_methods.include? name
|
50
|
+
registered_mods[mod_klass.name] = [name]
|
51
|
+
|
52
|
+
define_method name do |shell, *args, &pattern_block|
|
53
|
+
Loom.log.debug3(self) do
|
54
|
+
"handling mod call => #{mod_klass}##{name} #{args} #{pattern_block}"
|
55
|
+
end
|
56
|
+
verify_shell_cmds shell, mod_klass
|
57
|
+
|
58
|
+
mod = mod_klass.new shell, @loom_config
|
59
|
+
mod.execute *args, &pattern_block
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def registered_mods
|
64
|
+
@registered_mods ||= {}
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def alias_module(klass, alias_name)
|
69
|
+
raise ModNotRegisteredError, klass unless registered_mods[klass.name]
|
70
|
+
raise AliasRegisteredError, alias_name if instance_methods.include? alias_name
|
71
|
+
|
72
|
+
original_method = registered_mods[klass.name].first
|
73
|
+
registered_mods[klass.name] << alias_name
|
74
|
+
|
75
|
+
alias_method alias_name.to_sym, original_method
|
76
|
+
Loom.log.debug1(self) { "mod aliased => #{original_method} as #{alias_name}" }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|