0001-Fixes-1553-Puppet-and-Facter-cannot-both-install-t.patch

Nigel Kersten, 09/05/2008 07:48 pm

Download (16.5 KB)

View differences:

install.rb
60 60
end
61 61

  
62 62
PREREQS = %w{openssl facter xmlrpc/client xmlrpc/server cgi}
63
MIN_FACTER_VERSION = 1.5
63 64

  
64 65
InstallOptions = OpenStruct.new
65 66

  
......
115 116
    PREREQS.each { |pre|
116 117
        begin
117 118
            require pre
119
            if pre == "facter"
120
              # to_f isn't quite exact for strings like "1.5.1" but is good
121
              # enough for this purpose.
122
              facter_version = Facter.version.to_f
123
              if facter_version < MIN_FACTER_VERSION
124
                puts "Facter version: %s; minimum required: %s; cannot install" % [facter_version, MIN_FACTER_VERSION]
125
                exit -1
126
              end
127
            end
118 128
        rescue LoadError
119 129
            puts "Could not load %s; cannot install" % pre
120 130
            exit -1
lib/puppet/provider/package/appdmg.rb
55 55
            self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
56 56
        end
57 57
        require 'open-uri'
58
        require 'puppet/util/plist'
58
        require 'facter/util/plist'
59 59
        cached_source = source
60 60
        if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
61 61
            cached_source = "/tmp/#{name}"
lib/puppet/provider/package/pkgdmg.rb
70 70
            self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
71 71
        end
72 72
        require 'open-uri'
73
        require 'puppet/util/plist'
73
        require 'facter/util/plist'
74 74
        cached_source = source
75 75
        if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
76 76
            cached_source = "/tmp/#{name}"
lib/puppet/util/plist.rb
1
#--
2
##############################################################
3
# Copyright 2006, Ben Bleything <ben@bleything.net> and      #
4
# Patrick May <patrick@hexane.org>                           #
5
#                                                            #
6
# Distributed under the MIT license.                         #
7
##############################################################
8
#++
9
# = Plist
10
#
11
# This is the main file for plist.  Everything interesting happens in Plist and Plist::Emit.
12

  
13
require 'base64'
14
require 'cgi'
15
require 'stringio'
16

  
17
require 'puppet/util/plist/generator'
18
require 'puppet/util/plist/parser'
19

  
20
module Plist
21
  VERSION = '3.0.0'
22
end
23

  
lib/puppet/util/plist/generator.rb
1
#--###########################################################
2
# Copyright 2006, Ben Bleything <ben@bleything.net> and      #
3
# Patrick May <patrick@hexane.org>                           #
4
#                                                            #
5
# Distributed under the MIT license.                         #
6
##############################################################
7
#++
8
# See Plist::Emit.
9
module Plist
10
  # === Create a plist
11
  # You can dump an object to a plist in one of two ways:
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
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)
45

  
46
      output = wrap(output) if envelope
47

  
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
114
      end
115

  
116
      return output
117
    end
118

  
119
    def self.comment(content)
120
      return "<!-- #{content} -->\n"
121
    end
122

  
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
130

  
131
        out << block.call
132

  
133
        out.lower_indent
134
        out << "</#{type}>"
135
      else
136
        out = "<#{type}>#{contents.to_s}</#{type}>\n"
137
      end
138

  
139
      return out.to_s
140
    end
141

  
142
    def self.wrap(contents)
143
      output = ''
144

  
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"
152

  
153
      return output
154
    end
155

  
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
165
    private
166
    class IndentedString #:nodoc:
167
      attr_accessor :indent_string
168

  
169
      @@indent_level = 0
170

  
171
      def initialize(str = "\t")
172
        @indent_string = str
173
        @contents = ''
174
      end
175

  
176
      def to_s
177
        return @contents
178
      end
179

  
180
      def raise_indent
181
        @@indent_level += 1
182
      end
183

  
184
      def lower_indent
185
        @@indent_level -= 1 if @@indent_level > 0
186
      end
187

  
188
      def <<(val)
189
        if val.is_a? Array
190
          val.each do |f|
191
            self << f
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$/
205
        end
206
      end
207
    end
208
  end
209
end
210

  
211
# we need to add this so sorting hash keys works properly
212
class Symbol #:nodoc:
213
  def <=> (other)
214
    self.to_s <=> other.to_s
215
  end
216
end
217

  
218
class Array #:nodoc:
219
  include Plist::Emit
220
end
221

  
222
class Hash #:nodoc:
223
  include Plist::Emit
224
end
225

  
lib/puppet/util/plist/parser.rb
1
#--###########################################################
2
# Copyright 2006, Ben Bleything <ben@bleything.net> and      #
3
# Patrick May <patrick@hexane.org>                           #
4
#                                                            #
5
# Distributed under the MIT license.                         #
6
##############################################################
7
#++
8
# Plist parses Mac OS X xml property list files into ruby data structures.
9
#
10
# === Load a plist file
11
# This is the main point of the library:
12
#
13
#   r = Plist::parse_xml( filename_or_xml )
14
module Plist
15
# Note that I don't use these two elements much:
16
#
17
#  + Date elements are returned as DateTime objects.
18
#  + Data elements are implemented as Tempfiles
19
#
20
# Plist::parse_xml will blow up if it encounters a data element.
21
# If you encounter such an error, or if you have a Date element which
22
# can't be parsed into a Time object, please send your plist file to
23
# plist@hexane.org so that I can implement the proper support.
24
  def Plist::parse_xml( filename_or_xml )
25
    listener = Listener.new
26
    #parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
27
    parser = StreamParser.new(filename_or_xml, listener)
28
    parser.parse
29
    listener.result
30
  end
31

  
32
  class Listener
33
    #include REXML::StreamListener
34

  
35
    attr_accessor :result, :open
36

  
37
    def initialize
38
      @result = nil
39
      @open   = Array.new
40
    end
41

  
42

  
43
    def tag_start(name, attributes)
44
      @open.push PTag::mappings[name].new
45
    end
46

  
47
    def text( contents )
48
      @open.last.text = contents if @open.last
49
    end
50

  
51
    def tag_end(name)
52
      last = @open.pop
53
      if @open.empty?
54
        @result = last.to_ruby
55
      else
56
        @open.last.children.push last
57
      end
58
    end
59
  end
60

  
61
  class StreamParser
62
    def initialize( filename_or_xml, listener )
63
      @filename_or_xml = filename_or_xml
64
      @listener = listener
65
    end
66

  
67
    TEXT       = /([^<]+)/
68
    XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
69
    DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
70
    COMMENT_START = /\A<!--/u
71
    COMMENT_END = /.*?-->/um
72

  
73

  
74
    def parse
75
      plist_tags = PTag::mappings.keys.join('|')
76
      start_tag  = /<(#{plist_tags})([^>]*)>/i
77
      end_tag    = /<\/(#{plist_tags})[^>]*>/i
78

  
79
      require 'strscan'
80

  
81
      contents = (
82
        if (File.exists? @filename_or_xml)
83
          File.open(@filename_or_xml) {|f| f.read}
84
        else
85
          @filename_or_xml
86
        end
87
      )
88

  
89
      @scanner = StringScanner.new( contents )
90
      until @scanner.eos?
91
        if @scanner.scan(COMMENT_START)
92
          @scanner.scan(COMMENT_END)
93
        elsif @scanner.scan(XMLDECL_PATTERN)
94
        elsif @scanner.scan(DOCTYPE_PATTERN)
95
        elsif @scanner.scan(start_tag)
96
          @listener.tag_start(@scanner[1], nil)
97
          if (@scanner[2] =~ /\/$/)
98
            @listener.tag_end(@scanner[1])
99
          end
100
        elsif @scanner.scan(TEXT)
101
          @listener.text(@scanner[1])
102
        elsif @scanner.scan(end_tag)
103
          @listener.tag_end(@scanner[1])
104
        else
105
          raise "Unimplemented element"
106
        end
107
      end
108
    end
109
  end
110

  
111
  class PTag
112
    @@mappings = { }
113
    def PTag::mappings
114
      @@mappings
115
    end
116

  
117
    def PTag::inherited( sub_class )
118
      key = sub_class.to_s.downcase
119
      key.gsub!(/^plist::/, '' )
120
      key.gsub!(/^p/, '')  unless key == "plist"
121

  
122
      @@mappings[key] = sub_class
123
    end
124

  
125
    attr_accessor :text, :children
126
    def initialize
127
      @children = Array.new
128
    end
129

  
130
    def to_ruby
131
      raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}"
132
    end
133
  end
134

  
135
  class PList < PTag
136
    def to_ruby
137
      children.first.to_ruby if children.first
138
    end
139
  end
140

  
141
  class PDict < PTag
142
    def to_ruby
143
      dict = Hash.new
144
      key = nil
145

  
146
      children.each do |c|
147
        if key.nil?
148
          key = c.to_ruby
149
        else
150
          dict[key] = c.to_ruby
151
          key = nil
152
        end
153
      end
154

  
155
      dict
156
    end
157
  end
158

  
159
  class PKey < PTag
160
    def to_ruby
161
      CGI::unescapeHTML(text || '')
162
    end
163
  end
164

  
165
  class PString < PTag
166
    def to_ruby
167
      CGI::unescapeHTML(text || '')
168
    end
169
  end
170

  
171
  class PArray < PTag
172
    def to_ruby
173
      children.collect do |c|
174
        c.to_ruby
175
      end
176
    end
177
  end
178

  
179
  class PInteger < PTag
180
    def to_ruby
181
      text.to_i
182
    end
183
  end
184

  
185
  class PTrue < PTag
186
    def to_ruby
187
      true
188
    end
189
  end
190

  
191
  class PFalse < PTag
192
    def to_ruby
193
      false
194
    end
195
  end
196

  
197
  class PReal < PTag
198
    def to_ruby
199
      text.to_f
200
    end
201
  end
202

  
203
  require 'date'
204
  class PDate < PTag
205
    def to_ruby
206
      DateTime.parse(text)
207
    end
208
  end
209

  
210
  require 'base64'
211
  class PData < PTag
212
    def to_ruby
213
      data = Base64.decode64(text.gsub(/\s+/, ''))
214

  
215
      begin
216
        return Marshal.load(data)
217
      rescue Exception => e
218
        io = StringIO.new
219
        io.write data
220
        io.rewind
221
        return io
222
      end
223
    end
224
  end
225
end
226

  
227
-