plist4r 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|