plist4r 0.0.0 → 0.1.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.
- data/README.rdoc +120 -9
- data/VERSION +1 -1
- data/lib/plist4r.rb +54 -0
- data/lib/plist4r/backend.rb +52 -0
- data/lib/plist4r/backend/example.rb +69 -0
- data/lib/plist4r/backend/haml.rb +74 -0
- data/lib/plist4r/backend/libxml4r.rb +80 -0
- data/lib/plist4r/backend/plutil.rb +19 -0
- data/lib/plist4r/backend/ruby_cocoa.rb +191 -0
- data/lib/plist4r/config.rb +18 -0
- data/lib/plist4r/mixin.rb +7 -0
- data/lib/plist4r/mixin/class_attributes.rb +128 -0
- data/lib/plist4r/mixin/data_methods.rb +63 -0
- data/lib/plist4r/mixin/mixlib_config.rb +178 -0
- data/lib/plist4r/mixin/ordered_hash.rb +168 -0
- data/lib/plist4r/mixin/popen4.rb +193 -0
- data/lib/plist4r/mixin/ruby_stdlib.rb +24 -0
- data/lib/plist4r/plist.rb +256 -0
- data/lib/plist4r/plist_cache.rb +66 -0
- data/lib/plist4r/plist_type.rb +59 -0
- data/lib/plist4r/plist_type/info.rb +0 -0
- data/lib/plist4r/plist_type/launchd.rb +572 -0
- data/lib/plist4r/plist_type/plist.rb +0 -0
- data/plist4r.gemspec +86 -0
- data/spec/examples.rb +399 -0
- metadata +25 -2
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module Plist4r::Backend::Plutil
|
3
|
+
# maybe this should be a helper, included by other backends
|
4
|
+
class << self
|
5
|
+
# use tempfile to write out data
|
6
|
+
# convert it into target format
|
7
|
+
|
8
|
+
# plutil -convert xml1 @filename
|
9
|
+
# plutil -convert binary1 @filename
|
10
|
+
# next step is not supported
|
11
|
+
|
12
|
+
# def validate
|
13
|
+
# system "plutil #{@filename}"
|
14
|
+
# end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,191 @@
|
|
1
|
+
|
2
|
+
require 'plist4r/backend'
|
3
|
+
|
4
|
+
module Plist4r::Backend::RubyCocoa
|
5
|
+
class << self
|
6
|
+
def ruby_cocoa_wrapper_rb
|
7
|
+
@ruby_cocoa_wrapper_rb ||= <<-'EOC'
|
8
|
+
#!/usr/bin/ruby
|
9
|
+
|
10
|
+
include_endpath = "plist4r/mixin/ordered_hash.rb"
|
11
|
+
raise "No path given to include #{include_endpath}" unless ARGV[0] && ARGV[0] =~ /#{include_endpath}$/
|
12
|
+
ordered_hash_rb = ARGV[0]
|
13
|
+
|
14
|
+
require ordered_hash_rb
|
15
|
+
|
16
|
+
class OSX::NSObject
|
17
|
+
def to_ruby
|
18
|
+
case self
|
19
|
+
when OSX::NSDate
|
20
|
+
self.to_time
|
21
|
+
when OSX::NSCFBoolean
|
22
|
+
self.boolValue
|
23
|
+
when OSX::NSNumber
|
24
|
+
self.integer? ? self.to_i : self.to_f
|
25
|
+
when OSX::NSString
|
26
|
+
self.to_s
|
27
|
+
when OSX::NSAttributedString
|
28
|
+
self.string.to_s
|
29
|
+
when OSX::NSArray
|
30
|
+
self.to_a.map { |x| x.is_a?(OSX::NSObject) ? x.to_ruby : x }
|
31
|
+
when OSX::NSDictionary
|
32
|
+
h = ::ActiveSupport::OrderedHash.new
|
33
|
+
self.each do |x, y|
|
34
|
+
x = x.to_ruby if x.is_a?(OSX::NSObject)
|
35
|
+
y = y.to_ruby if y.is_a?(OSX::NSObject)
|
36
|
+
h[x] = y
|
37
|
+
end
|
38
|
+
h
|
39
|
+
else
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Plist
|
46
|
+
def to_xml hash
|
47
|
+
# to_plist defaults to NSPropertyListXMLFormat_v1_0
|
48
|
+
x = hash.to_ruby.to_plist
|
49
|
+
puts "#{x}"
|
50
|
+
end
|
51
|
+
def to_binary hash
|
52
|
+
# Here 200 == NSPropertyListBinaryFormat_v1_0
|
53
|
+
x = hash.to_ruby.to_plist 200
|
54
|
+
puts "#{x}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def open filename
|
58
|
+
plist_dict = ::OSX::NSDictionary.dictionaryWithContentsOfFile(filename)
|
59
|
+
puts "#{plist_dict.to_ruby.inspect}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def save hash, filename, file_format
|
63
|
+
case file_format.to_sym
|
64
|
+
when :xml
|
65
|
+
x = hash.to_plist # NSPropertyListXMLFormat_v1_0
|
66
|
+
when :binary
|
67
|
+
x = hash.to_plist 200 # NSPropertyListBinaryFormat_v1_0
|
68
|
+
when :next_step
|
69
|
+
raise "File format #{file_format.inspect} is not supported by RubyCocoa"
|
70
|
+
else
|
71
|
+
raise "File format #{file_format.inspect} not recognised"
|
72
|
+
end
|
73
|
+
File.open(filename,'w'){ |o| o << x }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class RubyCocoaWrapper
|
78
|
+
include Plist
|
79
|
+
|
80
|
+
def exec stdin
|
81
|
+
begin
|
82
|
+
require 'osx/cocoa'
|
83
|
+
instance_eval stdin
|
84
|
+
exit 0
|
85
|
+
rescue LoadError
|
86
|
+
raise $!
|
87
|
+
rescue
|
88
|
+
raise $!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
stdin = $stdin.read()
|
94
|
+
wrapper = RubyCocoaWrapper.new()
|
95
|
+
wrapper.exec stdin
|
96
|
+
EOC
|
97
|
+
end
|
98
|
+
|
99
|
+
def ruby_cocoa_exec stdin_str
|
100
|
+
rubycocoa_framework = "/System/Library/Frameworks/RubyCocoa.framework"
|
101
|
+
raise "RubyCocoa Framework not found. Searched in: #{rubycocoa_framework}" unless File.exists? rubycocoa_framework
|
102
|
+
|
103
|
+
require 'tempfile'
|
104
|
+
require 'plist4r/mixin/popen4'
|
105
|
+
|
106
|
+
if @rb_script && File.exists?(@rb_script.path)
|
107
|
+
@rb_script ||= Tempfile.new("ruby_cocoa_wrapper.rb") do |o|
|
108
|
+
o << ruby_cocoa_rb
|
109
|
+
end
|
110
|
+
File.chmod 0755, @rb_script.path
|
111
|
+
end
|
112
|
+
|
113
|
+
cmd = @rb_script.path
|
114
|
+
ordered_hash_rb = File.join(File.dirname(__FILE__), "..", "mixin", "ordered_hash.rb")
|
115
|
+
|
116
|
+
pid, stdin, stdout, stderr = Popen4::popen4 [cmd, ordered_hash_rb]
|
117
|
+
|
118
|
+
stdin.puts stdin_str
|
119
|
+
|
120
|
+
stdin.close
|
121
|
+
ignored, status = Process::waitpid2 pid
|
122
|
+
|
123
|
+
stdout_result = stdout.read.strip
|
124
|
+
stderr_result = stderr.read.strip
|
125
|
+
|
126
|
+
return [cmd, status, stdout_result, stderr_result]
|
127
|
+
end
|
128
|
+
|
129
|
+
def from_string plist, string
|
130
|
+
raise "method not implemented yet (unfinished)"
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_xml plist
|
134
|
+
hash = plist.to_hash
|
135
|
+
result = ruby_cocoa_exec "to_xml(\"#{hash}\")"
|
136
|
+
case result[1].exitstatus
|
137
|
+
when 0
|
138
|
+
xml_string = eval result[2]
|
139
|
+
return xml_string
|
140
|
+
else
|
141
|
+
$stderr.puts result[3]
|
142
|
+
raise "Error executing #{result[0]}. See stderr for more information"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_binary plist
|
147
|
+
hash = plist.to_hash
|
148
|
+
result = ruby_cocoa_exec "to_binary(\"#{hash}\")"
|
149
|
+
case result[1].exitstatus
|
150
|
+
when 0
|
151
|
+
binary_string = eval result[2]
|
152
|
+
return binary_string
|
153
|
+
else
|
154
|
+
$stderr.puts result[3]
|
155
|
+
raise "Error executing #{result[0]}. See stderr for more information"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def open plist
|
160
|
+
filename = plist.filename
|
161
|
+
result = ruby_cocoa_exec "open(\"#{filename}\")"
|
162
|
+
case result[1].exitstatus
|
163
|
+
when 0
|
164
|
+
hash = eval result[2]
|
165
|
+
plist.import_hash hash
|
166
|
+
else
|
167
|
+
$stderr.puts result[3]
|
168
|
+
raise "Error executing #{result[0]}. See stderr for more information"
|
169
|
+
end
|
170
|
+
file_format = Plist4r.file_detect_format filename
|
171
|
+
plist.file_format = file_format
|
172
|
+
return plist
|
173
|
+
end
|
174
|
+
|
175
|
+
def save hash, filename, file_format
|
176
|
+
filename = plist.filename_path
|
177
|
+
file_format = plist.file_format || Config[:default_format]
|
178
|
+
raise "#{self} - cant save file of format #{file_format}" unless [:xml,:binary].include? file_format
|
179
|
+
|
180
|
+
hash = plist.to_hash
|
181
|
+
result = ruby_cocoa_exec "save(\"#{hash}\",#{filename},#{file_format})"
|
182
|
+
case result[1].exitstatus
|
183
|
+
when 0
|
184
|
+
return true
|
185
|
+
else
|
186
|
+
raise "Error executing #{result[0]}. See stderr for more information"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
require 'plist4r/mixin/mixlib_config'
|
3
|
+
|
4
|
+
class Plist4r::Config
|
5
|
+
extend Mixlib::Config
|
6
|
+
|
7
|
+
backends [
|
8
|
+
Plist4r::Backend::RubyCocoa,
|
9
|
+
Plist4r::Backend::Haml,
|
10
|
+
Plist4r::Backend::Libxml4r
|
11
|
+
]
|
12
|
+
|
13
|
+
unsupported_keys true
|
14
|
+
raise_any_failure false
|
15
|
+
deafult_format :xml
|
16
|
+
default_path nil
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# class_attributes.rb - Class Attributes
|
2
|
+
# A Feature-complete alternative to @@
|
3
|
+
|
4
|
+
class Object
|
5
|
+
def deep_clone; Marshal::load(Marshal.dump(self)); end
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassAttributes
|
9
|
+
|
10
|
+
def cattr(*args, &block)
|
11
|
+
(class << self; self; end).class_eval do
|
12
|
+
attr_accessor *args
|
13
|
+
end
|
14
|
+
@cattr ||= []
|
15
|
+
@cattr.concat(args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def iattr(*args, &block)
|
19
|
+
(class << self; self; end).class_eval do
|
20
|
+
attr_accessor *args
|
21
|
+
end
|
22
|
+
@iattr ||= []
|
23
|
+
@iattr.concat(args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def oattr(*args, &block)
|
27
|
+
(class << self; self; end).class_eval do
|
28
|
+
attr_accessor *args
|
29
|
+
end
|
30
|
+
@oattr ||= []
|
31
|
+
@oattr.concat(args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def oattr_i(*args, &block)
|
35
|
+
(class << self; self; end).class_eval do
|
36
|
+
attr_accessor *args
|
37
|
+
end
|
38
|
+
@oattr_i ||= []
|
39
|
+
@oattr_i.concat(args)
|
40
|
+
end
|
41
|
+
|
42
|
+
def co_attr(*args, &block)
|
43
|
+
cattr(*args,&block)
|
44
|
+
oattr(*args,&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def co_attr_i(*args, &block)
|
48
|
+
iattr(*args,&block)
|
49
|
+
oattr_i(*args,&block)
|
50
|
+
end
|
51
|
+
|
52
|
+
alias_method :class_inherited_attribute_shared, :cattr
|
53
|
+
alias_method :class_inherited_attribute_independant, :iattr
|
54
|
+
|
55
|
+
alias_method :object_inherited_attribute_shared, :oattr
|
56
|
+
alias_method :object_inherited_attribute_independant, :oattr_i
|
57
|
+
|
58
|
+
alias_method :class_and_object_shared_inherited_attribute, :co_attr
|
59
|
+
alias_method :class_and_object_independant_inherited_attribute, :co_attr_i
|
60
|
+
|
61
|
+
def inherited(subclass)
|
62
|
+
super(subclass) if respond_to?('super')
|
63
|
+
iattr.each do |a|
|
64
|
+
# puts "a=#{a}"
|
65
|
+
subclass.send("#{a}=", send(a).deep_clone)
|
66
|
+
subclass.send("iattr", a.to_sym)
|
67
|
+
end
|
68
|
+
cattr.each do |a|
|
69
|
+
subclass.send("#{a}=", send(a))
|
70
|
+
subclass.send("cattr", a.to_sym)
|
71
|
+
end
|
72
|
+
oattr.each do |a|
|
73
|
+
subclass.send("oattr", a.to_sym)
|
74
|
+
end
|
75
|
+
oattr_i.each do |a|
|
76
|
+
subclass.send("oattr_i", a.to_sym)
|
77
|
+
end
|
78
|
+
subclass.send(:inherit) if subclass.respond_to?('inherit')
|
79
|
+
end
|
80
|
+
|
81
|
+
def inherit(*args, &block)
|
82
|
+
super if respond_to?('super')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
module ObjectPreInitialize
|
87
|
+
private
|
88
|
+
def pre_initialize(*args, &block)
|
89
|
+
super if respond_to?('super')
|
90
|
+
|
91
|
+
class_attrs = self.class.cattr + self.class.iattr
|
92
|
+
|
93
|
+
self.class.oattr.each do |a|
|
94
|
+
sac = self.class.send(a)
|
95
|
+
eval "@#{a.to_s}=sac" if class_attrs.include? a
|
96
|
+
end
|
97
|
+
|
98
|
+
self.class.oattr_i.each do |a|
|
99
|
+
sac = self.class.send(a)
|
100
|
+
eval "@#{a.to_s}=sac.deep_clone" if class_attrs.include? a
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# def postinitialize(*args, &block)
|
105
|
+
# end
|
106
|
+
end
|
107
|
+
|
108
|
+
module OverloadNew
|
109
|
+
def new(*args, &block)
|
110
|
+
newObj = self.allocate
|
111
|
+
newObj.send :extend, ObjectPreInitialize
|
112
|
+
newObj.send :pre_initialize, *args, &block
|
113
|
+
newObj.send :initialize, *args, &block
|
114
|
+
# newObj.send :postinitialize, *args, &block
|
115
|
+
return newObj
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def has_class_attributes
|
120
|
+
extend ClassAttributes
|
121
|
+
end
|
122
|
+
|
123
|
+
def has_class_object_attributes
|
124
|
+
extend ClassAttributes
|
125
|
+
extend OverloadNew
|
126
|
+
end
|
127
|
+
|
128
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
require 'plist4r/mixins/ordered_hash'
|
3
|
+
|
4
|
+
module Plst4r::DataMethods
|
5
|
+
|
6
|
+
def classes_for_key_type
|
7
|
+
{
|
8
|
+
:string => [String],
|
9
|
+
:bool => [TrueClass,FalseClass],
|
10
|
+
:integer => [Fixnum],
|
11
|
+
:array_of_strings => [Array],
|
12
|
+
:hash_of_bools => [Hash],
|
13
|
+
:hash => [Hash],
|
14
|
+
:bool_or_string_or_array_of_strings => [TrueClass,FalseClass,String,Array]
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_keys
|
19
|
+
{}
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing method_symbol, *args, &blk
|
23
|
+
puts "method_missing: #{method_symbol.inspect}, args: #{args.inspect}"
|
24
|
+
valid_keys.each do |key_type, valid_keys_of_those_type|
|
25
|
+
if valid_keys_of_those_type.include?(method_symbol.to_s.camelcase)
|
26
|
+
puts "key_type = #{key_type}, method_symbol.to_s.camelcase = #{method_symbol.to_s.camelcase}, args = #{args.inspect}"
|
27
|
+
return eval("set_or_return key_type, method_symbol.to_s.camelcase, *args, &blk")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_value key_type, key, value
|
33
|
+
unless classes_for_key_type[key_type].include? value.class
|
34
|
+
raise "Key: #{key}, value: #{value.inspect} is of type #{value.class}. Should be: #{classes_for_key_type[key_type].join ", "}"
|
35
|
+
end
|
36
|
+
case key_type
|
37
|
+
when :array_of_strings, :bool_or_string_or_array_of_strings
|
38
|
+
if value.class == Array
|
39
|
+
value.each_index do |i|
|
40
|
+
unless value[i].class == String
|
41
|
+
raise "Element: #{key}[#{i}], value: #{value[i].inspect} is of type #{value[i].class}. Should be: #{classes_for_key_type[:string].join ", "}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
when :hash_of_bools
|
46
|
+
value.each do |k,v|
|
47
|
+
unless [TrueClass,FalseClass].include? v.class
|
48
|
+
raise "Key: #{key}[#{k}], value: #{v.inspect} is of type #{v.class}. Should be: #{classes_for_key_type[:bool].join ", "}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_or_return key_type, key, value=nil
|
55
|
+
puts "#{method_name}, key_type: #{key_type.inspect}, value: #{value.inspect}"
|
56
|
+
if value
|
57
|
+
validate_value key_type, key, value unless key_type == nil
|
58
|
+
@hash[key] = value
|
59
|
+
else
|
60
|
+
@orig[key]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
4
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
5
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
class Object # http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
|
22
|
+
def meta_def name, &blk
|
23
|
+
(class << self; self; end).instance_eval { define_method name, &blk }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Mixlib
|
28
|
+
module Config
|
29
|
+
|
30
|
+
def self.extended(base)
|
31
|
+
class << base; attr_accessor :configuration; end
|
32
|
+
base.configuration = Hash.new
|
33
|
+
end
|
34
|
+
|
35
|
+
# Loads a given ruby file, and runs instance_eval against it in the context of the current
|
36
|
+
# object.
|
37
|
+
#
|
38
|
+
# Raises an IOError if the file cannot be found, or is not readable.
|
39
|
+
#
|
40
|
+
# === Parameters
|
41
|
+
# <string>:: A filename to read from
|
42
|
+
def from_file(filename)
|
43
|
+
self.instance_eval(IO.read(filename), filename, 1)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Pass Mixlib::Config.configure() a block, and it will yield self.configuration.
|
47
|
+
#
|
48
|
+
# === Parameters
|
49
|
+
# <block>:: A block that is sent self.configuration as its argument
|
50
|
+
def configure(&block)
|
51
|
+
block.call(self.configuration)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get the value of a configuration option
|
55
|
+
#
|
56
|
+
# === Parameters
|
57
|
+
# config_option<Symbol>:: The configuration option to return
|
58
|
+
#
|
59
|
+
# === Returns
|
60
|
+
# value:: The value of the configuration option
|
61
|
+
#
|
62
|
+
# === Raises
|
63
|
+
# <ArgumentError>:: If the configuration option does not exist
|
64
|
+
def [](config_option)
|
65
|
+
self.configuration[config_option.to_sym]
|
66
|
+
end
|
67
|
+
|
68
|
+
# Set the value of a configuration option
|
69
|
+
#
|
70
|
+
# === Parameters
|
71
|
+
# config_option<Symbol>:: The configuration option to set (within the [])
|
72
|
+
# value:: The value for the configuration option
|
73
|
+
#
|
74
|
+
# === Returns
|
75
|
+
# value:: The new value of the configuration option
|
76
|
+
def []=(config_option, value)
|
77
|
+
internal_set(config_option,value)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Check if Mixlib::Config has a configuration option.
|
81
|
+
#
|
82
|
+
# === Parameters
|
83
|
+
# key<Symbol>:: The configuration option to check for
|
84
|
+
#
|
85
|
+
# === Returns
|
86
|
+
# <True>:: If the configuration option exists
|
87
|
+
# <False>:: If the configuration option does not exist
|
88
|
+
def has_key?(key)
|
89
|
+
self.configuration.has_key?(key.to_sym)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Merge an incoming hash with our config options
|
93
|
+
#
|
94
|
+
# === Parameters
|
95
|
+
# hash<Hash>:: The incoming hash
|
96
|
+
#
|
97
|
+
# === Returns
|
98
|
+
# result of Hash#merge!
|
99
|
+
def merge!(hash)
|
100
|
+
self.configuration.merge!(hash)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return the set of config hash keys
|
104
|
+
#
|
105
|
+
# === Returns
|
106
|
+
# result of Hash#keys
|
107
|
+
def keys
|
108
|
+
self.configuration.keys
|
109
|
+
end
|
110
|
+
|
111
|
+
# Creates a shallow copy of the internal hash
|
112
|
+
#
|
113
|
+
# === Returns
|
114
|
+
# result of Hash#dup
|
115
|
+
def hash_dup
|
116
|
+
self.configuration.dup
|
117
|
+
end
|
118
|
+
|
119
|
+
# Internal dispatch setter, calling either the real defined method or setting the
|
120
|
+
# hash value directly
|
121
|
+
#
|
122
|
+
# === Parameters
|
123
|
+
# method_symbol<Symbol>:: Name of the method (variable setter)
|
124
|
+
# value<Object>:: Value to be set in config hash
|
125
|
+
#
|
126
|
+
def internal_set(method_symbol,value)
|
127
|
+
method_name = method_symbol.id2name
|
128
|
+
if (self.public_methods - ["[]="]).include?("#{method_name}=")
|
129
|
+
self.send("#{method_name}=", value)
|
130
|
+
else
|
131
|
+
self.configuration[method_symbol] = value
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
protected :internal_set
|
136
|
+
|
137
|
+
# metaprogramming to ensure that the slot for method_symbol
|
138
|
+
# gets set to value after any other logic is run
|
139
|
+
# === Parameters
|
140
|
+
# method_symbol<Symbol>:: Name of the method (variable setter)
|
141
|
+
# blk<Block>:: logic block to run in setting slot method_symbol to value
|
142
|
+
# value<Object>:: Value to be set in config hash
|
143
|
+
#
|
144
|
+
def config_attr_writer(method_symbol, &blk)
|
145
|
+
method_name = "#{method_symbol.to_s}="
|
146
|
+
meta_def method_name do |value|
|
147
|
+
self.configuration[method_symbol] = blk.call(value)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Allows for simple lookups and setting of configuration options via method calls
|
152
|
+
# on Mixlib::Config. If there any arguments to the method, they are used to set
|
153
|
+
# the value of the configuration option. Otherwise, it's a simple get operation.
|
154
|
+
#
|
155
|
+
# === Parameters
|
156
|
+
# method_symbol<Symbol>:: The method called. Must match a configuration option.
|
157
|
+
# *args:: Any arguments passed to the method
|
158
|
+
#
|
159
|
+
# === Returns
|
160
|
+
# value:: The value of the configuration option.
|
161
|
+
#
|
162
|
+
# === Raises
|
163
|
+
# <ArgumentError>:: If the method_symbol does not match a configuration option.
|
164
|
+
def method_missing(method_symbol, *args)
|
165
|
+
num_args = args.length
|
166
|
+
# Setting
|
167
|
+
if num_args > 0
|
168
|
+
method_symbol = $1.to_sym unless (method_symbol.to_s =~ /(.+)=$/).nil?
|
169
|
+
internal_set method_symbol, (num_args == 1 ? args[0] : args)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returning
|
173
|
+
self.configuration[method_symbol]
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|