facter 1.5.4 → 1.5.5
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.
Potentially problematic release.
This version of facter might be problematic. Click here for more details.
- data/CHANGELOG +75 -22
- data/COPYING +289 -623
- data/Rakefile +60 -55
- data/bin/facter +39 -26
- data/conf/osx/PackageInfo.plist +30 -30
- data/conf/osx/createpackage.sh +17 -17
- data/conf/osx/preflight +1 -1
- data/install.rb +226 -226
- data/lib/facter.rb +12 -12
- data/lib/facter/architecture.rb +14 -3
- data/lib/facter/ec2.rb +35 -0
- data/lib/facter/hardwareisa.rb +1 -1
- data/lib/facter/id.rb +1 -1
- data/lib/facter/ipaddress.rb +41 -41
- data/lib/facter/kernel.rb +2 -2
- data/lib/facter/kernelmajversion.rb +5 -0
- data/lib/facter/lsb.rb +5 -5
- data/lib/facter/lsbmajdistrelease.rb +1 -1
- data/lib/facter/macaddress.rb +6 -6
- data/lib/facter/manufacturer.rb +8 -8
- data/lib/facter/memory.rb +5 -4
- data/lib/facter/netmask.rb +4 -4
- data/lib/facter/network.rb +4 -5
- data/lib/facter/operatingsystem.rb +13 -7
- data/lib/facter/operatingsystemrelease.rb +5 -5
- data/lib/facter/selinux.rb +45 -0
- data/lib/facter/timezone.rb +1 -1
- data/lib/facter/uniqueid.rb +2 -2
- data/lib/facter/uptime.rb +3 -3
- data/lib/facter/util/confine.rb +12 -12
- data/lib/facter/util/ip.rb +18 -22
- data/lib/facter/util/macosx.rb +5 -0
- data/lib/facter/util/manufacturer.rb +37 -37
- data/lib/facter/util/plist/generator.rb +181 -179
- data/lib/facter/util/plist/parser.rb +162 -163
- data/lib/facter/util/resolution.rb +2 -2
- data/lib/facter/util/uptime.rb +10 -12
- data/lib/facter/util/values.rb +14 -0
- data/lib/facter/virtual.rb +54 -34
- data/spec/unit/data/darwin_ifconfig_all_with_multiple_interfaces +10 -0
- data/spec/unit/operatingsystem.rb +36 -0
- data/spec/unit/selinux.rb +48 -0
- data/spec/unit/util/confine.rb +70 -5
- data/spec/unit/util/ip.rb +29 -3
- metadata +89 -77
- data/documentation/custom.page +0 -22
- data/documentation/index.page +0 -19
data/lib/facter/timezone.rb
CHANGED
data/lib/facter/uniqueid.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
Facter.add(:uniqueid) do
|
2
|
-
setcode 'hostid',
|
3
|
-
confine :operatingsystem => %w{Solaris Linux Fedora RedHat CentOS SuSE SLES Debian Ubuntu Gentoo AIX}
|
2
|
+
setcode 'hostid', '/bin/sh'
|
3
|
+
confine :operatingsystem => %w{Solaris Linux Fedora RedHat CentOS SuSE SLES Debian Ubuntu Gentoo AIX OEL OVS}
|
4
4
|
end
|
data/lib/facter/uptime.rb
CHANGED
@@ -12,9 +12,9 @@ if FileTest.exists?("/proc/uptime")
|
|
12
12
|
|
13
13
|
%w{days hours seconds}.each do |label|
|
14
14
|
Facter.add("uptime_" + label) do
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
setcode do
|
16
|
+
Facter::Util::Uptime.get_uptime_period(uptime, label)
|
17
|
+
end
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
data/lib/facter/util/confine.rb
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
# A restricting tag for fact resolution mechanisms. The tag must be true
|
2
2
|
# for the resolution mechanism to be suitable.
|
3
|
+
|
4
|
+
require 'facter/util/values'
|
5
|
+
|
3
6
|
class Facter::Util::Confine
|
4
7
|
attr_accessor :fact, :values
|
5
8
|
|
9
|
+
include Facter::Util::Values
|
10
|
+
|
6
11
|
# Add the restriction. Requires the fact name, an operator, and the value
|
7
12
|
# we're comparing to.
|
8
13
|
def initialize(fact, *values)
|
9
14
|
raise ArgumentError, "The fact name must be provided" unless fact
|
10
15
|
raise ArgumentError, "One or more values must be provided" if values.empty?
|
11
|
-
fact = fact.to_s if fact.is_a? Symbol
|
12
16
|
@fact = fact
|
13
|
-
@values = values
|
14
|
-
if value.is_a? String
|
15
|
-
value
|
16
|
-
else
|
17
|
-
value.to_s
|
18
|
-
end
|
19
|
-
end
|
17
|
+
@values = values
|
20
18
|
end
|
21
19
|
|
22
20
|
def to_s
|
@@ -29,13 +27,15 @@ class Facter::Util::Confine
|
|
29
27
|
Facter.debug "No fact for %s" % @fact
|
30
28
|
return false
|
31
29
|
end
|
32
|
-
value = fact.value
|
30
|
+
value = convert(fact.value)
|
33
31
|
|
34
32
|
return false if value.nil?
|
35
33
|
|
36
|
-
@values.each
|
37
|
-
|
38
|
-
|
34
|
+
@values.each do |v|
|
35
|
+
v = convert(v)
|
36
|
+
next unless v.class == value.class
|
37
|
+
return true if value == v
|
38
|
+
end
|
39
39
|
return false
|
40
40
|
end
|
41
41
|
end
|
data/lib/facter/util/ip.rb
CHANGED
@@ -5,20 +5,20 @@ module Facter::Util::IP
|
|
5
5
|
# a given platform or set of platforms.
|
6
6
|
REGEX_MAP = {
|
7
7
|
:linux => {
|
8
|
-
:ipaddress
|
9
|
-
:macaddress
|
10
|
-
:netmask
|
8
|
+
:ipaddress => /inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
|
9
|
+
:macaddress => /(?:ether|HWaddr)\s+(\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2})/,
|
10
|
+
:netmask => /Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
|
11
11
|
},
|
12
|
-
:bsd
|
13
|
-
:aliases
|
14
|
-
:ipaddress
|
15
|
-
:macaddress
|
16
|
-
:netmask
|
12
|
+
:bsd => {
|
13
|
+
:aliases => [:openbsd, :netbsd, :freebsd, :darwin],
|
14
|
+
:ipaddress => /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
|
15
|
+
:macaddress => /(?:ether|lladdr)\s+(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)/,
|
16
|
+
:netmask => /netmask\s+0x(\w{8})/
|
17
17
|
},
|
18
18
|
:sunos => {
|
19
|
-
:
|
20
|
-
:macaddress
|
21
|
-
:netmask
|
19
|
+
:ipaddress => /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
|
20
|
+
:macaddress => /(?:ether|lladdr)\s+(\w?\w:\w?\w:\w?\w:\w?\w:\w?\w:\w?\w)/,
|
21
|
+
:netmask => /netmask\s+(\w{8})/
|
22
22
|
}
|
23
23
|
}
|
24
24
|
|
@@ -45,17 +45,13 @@ module Facter::Util::IP
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def self.get_interfaces
|
48
|
-
|
49
|
-
|
50
|
-
output = Facter::Util::IP.get_all_interface_output()
|
48
|
+
return [] unless output = Facter::Util::IP.get_all_interface_output()
|
51
49
|
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
[]
|
58
|
-
end
|
50
|
+
# Our regex appears to be stupid, in that it leaves colons sitting
|
51
|
+
# at the end of interfaces. So, we have to trim those trailing
|
52
|
+
# characters. I tried making the regex better but supporting all
|
53
|
+
# platforms with a single regex is probably a bit too much.
|
54
|
+
output.scan(/^\w+[.:]?\d+[.:]?\d*[.:]?\w*/).collect { |i| i.sub(/:$/, '') }
|
59
55
|
end
|
60
56
|
|
61
57
|
def self.get_all_interface_output
|
@@ -124,7 +120,7 @@ module Facter::Util::IP
|
|
124
120
|
output_int = get_single_interface_output(interface)
|
125
121
|
|
126
122
|
if interface != /^lo[0:]?\d?/
|
127
|
-
output_int.
|
123
|
+
output_int.each_line do |s|
|
128
124
|
if s =~ regex
|
129
125
|
value = $1
|
130
126
|
if label == 'netmask' && convert_from_hex?(kernel)
|
data/lib/facter/util/macosx.rb
CHANGED
@@ -58,6 +58,11 @@ module Facter::Util::Macosx
|
|
58
58
|
[ "productName", "productVersion", "buildVersion" ].each do |option|
|
59
59
|
ver["macosx_#{option}"] = %x{sw_vers -#{option}}.strip
|
60
60
|
end
|
61
|
+
productversion = ver["macosx_productVersion"]
|
62
|
+
if not productversion.nil?
|
63
|
+
ver["macosx_productversion_major"] = productversion.scan(/(\d+\.\d+)/)[0][0]
|
64
|
+
ver["macosx_productversion_minor"] = productversion.scan(/(\d+)\.(\d+)\.(\d+)/)[0].last
|
65
|
+
end
|
61
66
|
ver
|
62
67
|
end
|
63
68
|
end
|
@@ -2,45 +2,45 @@
|
|
2
2
|
# Support methods for manufacturer specific facts
|
3
3
|
|
4
4
|
module Facter::Manufacturer
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
output=%x{/usr/sbin/dmidecode 2>/dev/null}
|
12
|
-
when 'OpenBSD', 'FreeBSD'
|
13
|
-
return nil unless FileTest.exists?("/usr/local/sbin/dmidecode")
|
14
|
-
|
15
|
-
output=%x{/usr/local/sbin/dmidecode 2>/dev/null}
|
16
|
-
when 'NetBSD'
|
17
|
-
return nil unless FileTest.exists?("/usr/pkg/sbin/dmidecode")
|
5
|
+
def self.dmi_find_system_info(name)
|
6
|
+
splitstr="Handle"
|
7
|
+
case Facter.value(:kernel)
|
8
|
+
when 'Linux'
|
9
|
+
return nil unless FileTest.exists?("/usr/sbin/dmidecode")
|
18
10
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
splitstr="ID SIZE TYPE"
|
23
|
-
output=%x{/usr/sbin/smbios 2>/dev/null}
|
11
|
+
output=%x{/usr/sbin/dmidecode 2>/dev/null}
|
12
|
+
when 'OpenBSD', 'FreeBSD'
|
13
|
+
return nil unless FileTest.exists?("/usr/local/sbin/dmidecode")
|
24
14
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
15
|
+
output=%x{/usr/local/sbin/dmidecode 2>/dev/null}
|
16
|
+
when 'NetBSD'
|
17
|
+
return nil unless FileTest.exists?("/usr/pkg/sbin/dmidecode")
|
18
|
+
|
19
|
+
output=%x{/usr/pkg/sbin/dmidecode 2>/dev/null}
|
20
|
+
when 'SunOS'
|
21
|
+
return nil unless FileTest.exists?("/usr/sbin/smbios")
|
22
|
+
splitstr="ID SIZE TYPE"
|
23
|
+
output=%x{/usr/sbin/smbios 2>/dev/null}
|
24
|
+
|
25
|
+
else
|
26
|
+
return
|
27
|
+
end
|
28
|
+
name.each_pair do |key,v|
|
29
|
+
v.each do |v2|
|
30
|
+
v2.each_pair do |value,facterkey|
|
31
|
+
output.split(splitstr).each do |line|
|
32
|
+
if line =~ /#{key}/ and ( line =~ /#{value} 0x\d+ \(([-\w].*)\)\n*./ or line =~ /#{value} ([-\w].*)\n*./ )
|
33
|
+
result = $1
|
34
|
+
Facter.add(facterkey) do
|
35
|
+
confine :kernel => [ :linux, :freebsd, :netbsd, :openbsd, :sunos ]
|
36
|
+
setcode do
|
37
|
+
result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -7,220 +7,222 @@
|
|
7
7
|
#++
|
8
8
|
# See Plist::Emit.
|
9
9
|
module Plist
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
# * <tt>Plist::Emit.dump(obj)</tt>
|
14
|
-
# * <tt>obj.to_plist</tt>
|
15
|
-
# * This requires that you mixin the <tt>Plist::Emit</tt> module, which is already done for +Array+ and +Hash+.
|
16
|
-
#
|
17
|
-
# The following Ruby classes are converted into native plist types:
|
18
|
-
# Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
|
19
|
-
# * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the <array> and <dict> containers (respectively).
|
20
|
-
# * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a <data> element.
|
21
|
-
# * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to <tt>Marshal.dump</tt> and the result placed in a <data> element.
|
22
|
-
#
|
23
|
-
# For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
|
24
|
-
module Emit
|
25
|
-
# Helper method for injecting into classes. Calls <tt>Plist::Emit.dump</tt> with +self+.
|
26
|
-
def to_plist(envelope = true)
|
27
|
-
return Plist::Emit.dump(self, envelope)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Helper method for injecting into classes. Calls <tt>Plist::Emit.save_plist</tt> with +self+.
|
31
|
-
def save_plist(filename)
|
32
|
-
Plist::Emit.save_plist(self, filename)
|
33
|
-
end
|
34
|
-
|
35
|
-
# The following Ruby classes are converted into native plist types:
|
36
|
-
# Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
|
10
|
+
# === Create a plist
|
11
|
+
# You can dump an object to a plist in one of two ways:
|
37
12
|
#
|
38
|
-
#
|
13
|
+
# * <tt>Plist::Emit.dump(obj)</tt>
|
14
|
+
# * <tt>obj.to_plist</tt>
|
15
|
+
# * This requires that you mixin the <tt>Plist::Emit</tt> module, which is already done for +Array+ and +Hash+.
|
39
16
|
#
|
40
|
-
#
|
17
|
+
# The following Ruby classes are converted into native plist types:
|
18
|
+
# Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
|
19
|
+
# * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the <array> and <dict> containers (respectively).
|
20
|
+
# * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a <data> element.
|
21
|
+
# * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to <tt>Marshal.dump</tt> and the result placed in a <data> element.
|
41
22
|
#
|
42
|
-
#
|
43
|
-
|
44
|
-
|
23
|
+
# For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
|
24
|
+
module Emit
|
25
|
+
# Helper method for injecting into classes. Calls <tt>Plist::Emit.dump</tt> with +self+.
|
26
|
+
def to_plist(envelope = true)
|
27
|
+
return Plist::Emit.dump(self, envelope)
|
28
|
+
end
|
45
29
|
|
46
|
-
|
30
|
+
# Helper method for injecting into classes. Calls <tt>Plist::Emit.save_plist</tt> with +self+.
|
31
|
+
def save_plist(filename)
|
32
|
+
Plist::Emit.save_plist(self, filename)
|
33
|
+
end
|
47
34
|
|
48
|
-
|
49
|
-
|
35
|
+
# The following Ruby classes are converted into native plist types:
|
36
|
+
# Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
|
37
|
+
#
|
38
|
+
# Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes.
|
39
|
+
#
|
40
|
+
# +IO+ and +StringIO+ objects are encoded and placed in <data> elements; other objects are <tt>Marshal.dump</tt>'ed unless they implement +to_plist_node+.
|
41
|
+
#
|
42
|
+
# The +envelope+ parameters dictates whether or not the resultant plist fragment is wrapped in the normal XML/plist header and footer. Set it to false if you only want the fragment.
|
43
|
+
def self.dump(obj, envelope = true)
|
44
|
+
output = plist_node(obj)
|
50
45
|
|
51
|
-
|
52
|
-
def self.save_plist(obj, filename)
|
53
|
-
File.open(filename, 'wb') do |f|
|
54
|
-
f.write(obj.to_plist)
|
55
|
-
end
|
56
|
-
end
|
46
|
+
output = wrap(output) if envelope
|
57
47
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
output
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
48
|
+
return output
|
49
|
+
end
|
50
|
+
|
51
|
+
# Writes the serialized object's plist to the specified filename.
|
52
|
+
def self.save_plist(obj, filename)
|
53
|
+
File.open(filename, 'wb') do |f|
|
54
|
+
f.write(obj.to_plist)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def self.plist_node(element)
|
60
|
+
output = ''
|
61
|
+
|
62
|
+
if element.respond_to? :to_plist_node
|
63
|
+
output << element.to_plist_node
|
64
|
+
else
|
65
|
+
case element
|
66
|
+
when Array
|
67
|
+
if element.empty?
|
68
|
+
output << "<array/>\n"
|
69
|
+
else
|
70
|
+
output << tag('array') {
|
71
|
+
element.collect {|e| plist_node(e)}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
when Hash
|
75
|
+
if element.empty?
|
76
|
+
output << "<dict/>\n"
|
77
|
+
else
|
78
|
+
inner_tags = []
|
79
|
+
|
80
|
+
element.keys.sort.each do |k|
|
81
|
+
v = element[k]
|
82
|
+
inner_tags << tag('key', CGI::escapeHTML(k.to_s))
|
83
|
+
inner_tags << plist_node(v)
|
84
|
+
end
|
85
|
+
|
86
|
+
output << tag('dict') {
|
87
|
+
inner_tags
|
88
|
+
}
|
89
|
+
end
|
90
|
+
when true, false
|
91
|
+
output << "<#{element}/>\n"
|
92
|
+
when Time
|
93
|
+
output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
94
|
+
when Date # also catches DateTime
|
95
|
+
output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
96
|
+
when String, Symbol, Fixnum, Bignum, Integer, Float
|
97
|
+
output << tag(element_type(element), CGI::escapeHTML(element.to_s))
|
98
|
+
when IO, StringIO
|
99
|
+
element.rewind
|
100
|
+
contents = element.read
|
101
|
+
# note that apple plists are wrapped at a different length then
|
102
|
+
# what ruby's base64 wraps by default.
|
103
|
+
# I used #encode64 instead of #b64encode (which allows a length arg)
|
104
|
+
# because b64encode is b0rked and ignores the length arg.
|
105
|
+
data = "\n"
|
106
|
+
Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
|
107
|
+
output << tag('data', data)
|
108
|
+
else
|
109
|
+
output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' )
|
110
|
+
data = "\n"
|
111
|
+
Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
|
112
|
+
output << tag('data', data )
|
113
|
+
end
|
84
114
|
end
|
85
115
|
|
86
|
-
output
|
87
|
-
inner_tags
|
88
|
-
}
|
89
|
-
end
|
90
|
-
when true, false
|
91
|
-
output << "<#{element}/>\n"
|
92
|
-
when Time
|
93
|
-
output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
94
|
-
when Date # also catches DateTime
|
95
|
-
output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
96
|
-
when String, Symbol, Fixnum, Bignum, Integer, Float
|
97
|
-
output << tag(element_type(element), CGI::escapeHTML(element.to_s))
|
98
|
-
when IO, StringIO
|
99
|
-
element.rewind
|
100
|
-
contents = element.read
|
101
|
-
# note that apple plists are wrapped at a different length then
|
102
|
-
# what ruby's base64 wraps by default.
|
103
|
-
# I used #encode64 instead of #b64encode (which allows a length arg)
|
104
|
-
# because b64encode is b0rked and ignores the length arg.
|
105
|
-
data = "\n"
|
106
|
-
Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
|
107
|
-
output << tag('data', data)
|
108
|
-
else
|
109
|
-
output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' )
|
110
|
-
data = "\n"
|
111
|
-
Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
|
112
|
-
output << tag('data', data )
|
116
|
+
return output
|
113
117
|
end
|
114
|
-
end
|
115
118
|
|
116
|
-
|
117
|
-
|
119
|
+
def self.comment(content)
|
120
|
+
return "<!-- #{content} -->\n"
|
121
|
+
end
|
118
122
|
|
119
|
-
|
120
|
-
|
121
|
-
|
123
|
+
def self.tag(type, contents = '', &block)
|
124
|
+
out = nil
|
125
|
+
|
126
|
+
if block_given?
|
127
|
+
out = IndentedString.new
|
128
|
+
out << "<#{type}>"
|
129
|
+
out.raise_indent
|
122
130
|
|
123
|
-
|
124
|
-
out = nil
|
131
|
+
out << block.call
|
125
132
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
133
|
+
out.lower_indent
|
134
|
+
out << "</#{type}>"
|
135
|
+
else
|
136
|
+
out = "<#{type}>#{contents.to_s}</#{type}>\n"
|
137
|
+
end
|
130
138
|
|
131
|
-
|
139
|
+
return out.to_s
|
140
|
+
end
|
132
141
|
|
133
|
-
|
134
|
-
|
135
|
-
else
|
136
|
-
out = "<#{type}>#{contents.to_s}</#{type}>\n"
|
137
|
-
end
|
142
|
+
def self.wrap(contents)
|
143
|
+
output = ''
|
138
144
|
|
139
|
-
|
140
|
-
|
145
|
+
output << '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
|
146
|
+
output << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n"
|
147
|
+
output << '<plist version="1.0">' + "\n"
|
148
|
+
|
149
|
+
output << contents
|
150
|
+
|
151
|
+
output << '</plist>' + "\n"
|
141
152
|
|
142
|
-
|
143
|
-
|
153
|
+
return output
|
154
|
+
end
|
144
155
|
|
145
|
-
|
146
|
-
|
147
|
-
|
156
|
+
def self.element_type(item)
|
157
|
+
return case item
|
158
|
+
when String, Symbol; 'string'
|
159
|
+
when Fixnum, Bignum, Integer; 'integer'
|
160
|
+
when Float; 'real'
|
161
|
+
else
|
162
|
+
raise "Don't know about this data type... something must be wrong!"
|
163
|
+
end
|
164
|
+
end
|
148
165
|
|
149
|
-
|
166
|
+
private
|
150
167
|
|
151
|
-
|
168
|
+
class IndentedString #:nodoc:
|
169
|
+
attr_accessor :indent_string
|
152
170
|
|
153
|
-
|
154
|
-
end
|
171
|
+
@@indent_level = 0
|
155
172
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
else
|
194
|
-
# if it's already indented, don't bother indenting further
|
195
|
-
unless val =~ /\A#{@indent_string}/
|
196
|
-
indent = @indent_string * @@indent_level
|
197
|
-
|
198
|
-
@contents << val.gsub(/^/, indent)
|
199
|
-
else
|
200
|
-
@contents << val
|
201
|
-
end
|
202
|
-
|
203
|
-
# it already has a newline, don't add another
|
204
|
-
@contents << "\n" unless val =~ /\n$/
|
173
|
+
def initialize(str = "\t")
|
174
|
+
@indent_string = str
|
175
|
+
@contents = ''
|
176
|
+
end
|
177
|
+
|
178
|
+
def to_s
|
179
|
+
return @contents
|
180
|
+
end
|
181
|
+
|
182
|
+
def raise_indent
|
183
|
+
@@indent_level += 1
|
184
|
+
end
|
185
|
+
|
186
|
+
def lower_indent
|
187
|
+
@@indent_level -= 1 if @@indent_level > 0
|
188
|
+
end
|
189
|
+
|
190
|
+
def <<(val)
|
191
|
+
if val.is_a? Array
|
192
|
+
val.each do |f|
|
193
|
+
self << f
|
194
|
+
end
|
195
|
+
else
|
196
|
+
# if it's already indented, don't bother indenting further
|
197
|
+
unless val =~ /\A#{@indent_string}/
|
198
|
+
indent = @indent_string * @@indent_level
|
199
|
+
|
200
|
+
@contents << val.gsub(/^/, indent)
|
201
|
+
else
|
202
|
+
@contents << val
|
203
|
+
end
|
204
|
+
|
205
|
+
# it already has a newline, don't add another
|
206
|
+
@contents << "\n" unless val =~ /\n$/
|
207
|
+
end
|
208
|
+
end
|
205
209
|
end
|
206
|
-
end
|
207
210
|
end
|
208
|
-
end
|
209
211
|
end
|
210
212
|
|
211
213
|
# we need to add this so sorting hash keys works properly
|
212
214
|
class Symbol #:nodoc:
|
213
|
-
|
214
|
-
|
215
|
-
|
215
|
+
def <=> (other)
|
216
|
+
self.to_s <=> other.to_s
|
217
|
+
end
|
216
218
|
end
|
217
219
|
|
218
220
|
class Array #:nodoc:
|
219
|
-
|
221
|
+
include Plist::Emit
|
220
222
|
end
|
221
223
|
|
222
224
|
class Hash #:nodoc:
|
223
|
-
|
225
|
+
include Plist::Emit
|
224
226
|
end
|
225
227
|
|
226
228
|
# $Id: generator.rb 1781 2006-10-16 01:01:35Z luke $
|