6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
# File 'lib/kanrisuru/os_package/include.rb', line 6
def os_include(mod, opts = {})
os_method_properties = mod.instance_variable_get(:@os_method_properties)
os_method_names = os_method_properties.keys
os_methods = mod.instance_variable_get(:@os_methods)
public_methods = mod.instance_methods(false) - os_methods.to_a
private_methods = mod.private_instance_methods(false)
protected_methods = mod.protected_instance_methods(false)
include_methods = (public_methods + protected_methods + private_methods).flatten
include_method_bindings = proc do
include_methods.each do |method_name|
define_method method_name do |*args, &block|
unbound_method = mod.instance_method(method_name)
bind_method(unbound_method, *args, &block)
end
end
private_methods.each { |method_name| private(method_name) }
protected_methods.each { |method_name| protected(method_name) }
private
if RUBY_VERSION < '2.7'
define_method 'bind_method' do |unbound_method, *args, &block|
unbound_method.bind(self).call(*args, &block)
end
else
define_method 'bind_method' do |unbound_method, *args, &block|
unbound_method.bind_call(self, *args, &block)
end
end
end
namespace = opts[:namespace]
namespace_class = nil
namespace_instance = nil
if namespace
if Kanrisuru::Remote::Host.instance_variable_defined?("@#{namespace}")
namespace_class = Kanrisuru::Remote::Host.const_get(Kanrisuru::Util.camelize(namespace))
namespace_instance = Kanrisuru::Remote::Host.instance_variable_get("@#{namespace}")
else
namespace_class = Kanrisuru::Remote::Host.const_set(Kanrisuru::Util.camelize(namespace), Class.new)
namespace_instance = Kanrisuru::Remote::Host.instance_variable_set("@#{namespace}", namespace_class.new)
class_eval do
define_method namespace do
namespace_instance.instance_variable_set(:@host, self)
namespace_instance
end
end
end
namespace_class.class_eval(&include_method_bindings)
else
class_eval(&include_method_bindings)
end
class_eval do
os_method_names.each do |method_name|
if namespace
namespace_class.class_eval do
define_method method_name do |*args, &block|
unbound_method = nil
host = namespace_instance.instance_variable_get(:@host)
os_method_cache = host.instance_variable_get(:@os_method_cache) || {}
if os_method_cache.key?("#{namespace}.#{method_name}")
unbound_method = os_method_cache["#{namespace}.#{method_name}"]
else
defined_method_name = host.resolve_os_method_name(os_method_properties, method_name)
unless defined_method_name
raise NoMethodError, "undefined method `#{method_name}' for #{self.class}"
end
unbound_method = mod.instance_method(defined_method_name)
raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless unbound_method
os_method_cache["#{namespace}.#{method_name}"] = unbound_method
host.instance_variable_set(:@os_method_cache, os_method_cache)
end
bind_method(unbound_method, *args, &block)
end
end
else
define_method method_name do |*args, &block|
unbound_method = nil
host = self
os_method_cache = host.instance_variable_get(:@os_method_cache) || {}
if os_method_cache.key?(method_name)
unbound_method = os_method_cache[method_name]
else
defined_method_name = host.resolve_os_method_name(os_method_properties, method_name)
raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless defined_method_name
unbound_method = mod.instance_method(defined_method_name)
raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless unbound_method
os_method_cache[method_name] = unbound_method
host.instance_variable_set(:@os_method_cache, os_method_cache)
end
bind_method(unbound_method, *args, &block)
end
end
end
def resolve_os_method_name(properties, method_name)
kernel = os.kernel.downcase
release = os.release.downcase
properties[method_name].each do |property|
os_name = property[:os_name]
strict = property[:options] ? property[:options][:strict] : false
except = property[:options] ? property[:options][:except] : ''
next if except && (except == release || except.include?(release))
if release == os_name || kernel == os_name ||
(Kanrisuru::Util::OsFamily.family_include_distribution?(os_name, release) && !strict) ||
(Kanrisuru::Util::OsFamily.upstream_include_distribution?(os_name, release) && !strict)
return property[:method_name]
end
end
nil
end
end
end
|