lib/puppet/util/monkey_patches.rb in puppet-2.7.26 vs lib/puppet/util/monkey_patches.rb in puppet-3.0.0.rc4
- old
+ new
@@ -1,7 +1,15 @@
-unless defined? JRUBY_VERSION
+require 'puppet/util'
+module Puppet::Util::MonkeyPatches
+end
+
+begin
Process.maxgroups = 1024
+rescue Exception
+ # Actually, I just want to ignore it, since various platforms - JRuby,
+ # Windows, and so forth - don't support it, but only because it isn't a
+ # meaningful or implementable concept there.
end
module RDoc
def self.caller(skip=nil)
in_gem_wrapper = false
@@ -55,27 +63,10 @@
# that can cause rspec to fork bomb
# and other strange things like that.
def daemonize
raise NotImplementedError, "Kernel.daemonize is too dangerous, please don't try to use it."
end
-
- # The following code allows callers to make assertions that are only
- # checked when the environment variable PUPPET_ENABLE_ASSERTIONS is
- # set to a non-empty string. For example:
- #
- # assert_that { condition }
- # assert_that(message) { condition }
- if ENV["PUPPET_ENABLE_ASSERTIONS"].to_s != ''
- def assert_that(message = nil)
- unless yield
- raise Exception.new("Assertion failure: #{message}")
- end
- end
- else
- def assert_that(message = nil)
- end
- end
end
# Workaround for yaml_initialize, which isn't supported before Ruby
# 1.8.3.
if RUBY_VERSION == '1.8.1' || RUBY_VERSION == '1.8.2'
@@ -88,18 +79,10 @@
end
r
}
end
-class Fixnum
- # Returns the int itself. This method is intended for compatibility to
- # character constant in Ruby 1.9. 1.8.5 is missing it; add it.
- def ord
- self
- end unless method_defined? 'ord'
-end
-
class Array
# Ruby < 1.8.7 doesn't have this method but we use it in tests
def combination(num)
return [] if num < 0 || num > size
return [[]] if num == 0
@@ -110,10 +93,18 @@
ret += tmp.combination(num - 1).map{|a| a.unshift(e) }
end
end unless method_defined? :combination
alias :count :length unless method_defined? :count
+
+ # Ruby 1.8.5 lacks `drop`, which we don't want to lose.
+ def drop(n)
+ n = n.to_int
+ raise ArgumentError, "attempt to drop negative size" if n < 0
+
+ slice(n, length - n) or []
+ end unless method_defined? :drop
end
class Symbol
# So, it turns out that one of the biggest memory allocation hot-spots in
@@ -137,39 +128,57 @@
def intern
return self
end unless method_defined? :intern
end
-
class String
- def lines(separator = $/)
- lines = split(separator)
- block_given? and lines.each {|line| yield line }
- lines
+ unless method_defined? :lines
+ require 'puppet/util/monkey_patches/lines'
+ include Puppet::Util::MonkeyPatches::Lines
end
end
+require 'fcntl'
class IO
- def lines(separator = $/)
- lines = split(separator)
- block_given? and lines.each {|line| yield line }
- lines
+ unless method_defined? :lines
+ require 'puppet/util/monkey_patches/lines'
+ include Puppet::Util::MonkeyPatches::Lines
end
def self.binread(name, length = nil, offset = 0)
File.open(name, 'rb') do |f|
f.seek(offset) if offset > 0
f.read(length)
end
end unless singleton_methods.include?(:binread)
- def self.binwrite(name, string, offset = 0)
- File.open(name, 'wb') do |f|
- f.write(offset > 0 ? string[offset..-1] : string)
+ def self.binwrite(name, string, offset = nil)
+ # Determine if we should truncate or not. Since the truncate method on a
+ # file handle isn't implemented on all platforms, safer to do this in what
+ # looks like the libc / POSIX flag - which is usually pretty robust.
+ # --daniel 2012-03-11
+ mode = Fcntl::O_CREAT | Fcntl::O_WRONLY | (offset.nil? ? Fcntl::O_TRUNC : 0)
+
+ # We have to duplicate the mode because Ruby on Windows is a bit precious,
+ # and doesn't actually carry over the mode. It won't work to just use
+ # open, either, because that doesn't like our system modes and the default
+ # open bits don't do what we need, which is awesome. --daniel 2012-03-30
+ IO.open(IO::sysopen(name, mode), mode) do |f|
+ # ...seek to our desired offset, then write the bytes. Don't try to
+ # seek past the start of the file, eh, because who knows what platform
+ # would legitimately blow up if we did that.
+ #
+ # Double-check the positioning, too, since destroying data isn't my idea
+ # of a good time. --daniel 2012-03-11
+ target = [0, offset.to_i].max
+ unless (landed = f.sysseek(target, IO::SEEK_SET)) == target
+ raise "unable to seek to target offset #{target} in #{name}: got to #{landed}"
+ end
+
+ f.syswrite(string)
end
end unless singleton_methods.include?(:binwrite)
-
end
class Range
def intersection(other)
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
@@ -194,10 +203,63 @@
yield(self)
self
end unless method_defined?(:tap)
end
+
+########################################################################
+# The return type of `instance_variables` changes between Ruby 1.8 and 1.9
+# releases; it used to return an array of strings in the form "@foo", but
+# now returns an array of symbols in the form :@foo.
+#
+# Nothing else in the stack cares which form you get - you can pass the
+# string or symbol to things like `instance_variable_set` and they will work
+# transparently.
+#
+# Having the same form in all releases of Puppet is a win, though, so we
+# pick a unification and enforce than on all releases. That way developers
+# who do set math on them (eg: for YAML rendering) don't have to handle the
+# distinction themselves.
+#
+# In the sane tradition, we bring older releases into conformance with newer
+# releases, so we return symbols rather than strings, to be more like the
+# future versions of Ruby are.
+#
+# We also carefully support reloading, by only wrapping when we don't
+# already have the original version of the method aliased away somewhere.
+if RUBY_VERSION[0,3] == '1.8'
+ unless Object.respond_to?(:puppet_original_instance_variables)
+
+ # Add our wrapper to the method.
+ class Object
+ alias :puppet_original_instance_variables :instance_variables
+
+ def instance_variables
+ puppet_original_instance_variables.map(&:to_sym)
+ end
+ end
+
+ # The one place that Ruby 1.8 assumes something about the return format of
+ # the `instance_variables` method is actually kind of odd, because it uses
+ # eval to get at instance variables of another object.
+ #
+ # This takes the original code and applies replaces instance_eval with
+ # instance_variable_get through it. All other bugs in the original (such
+ # as equality depending on the instance variables having the same order
+ # without any promise from the runtime) are preserved. --daniel 2012-03-11
+ require 'resolv'
+ class Resolv::DNS::Resource
+ def ==(other) # :nodoc:
+ return self.class == other.class &&
+ self.instance_variables == other.instance_variables &&
+ self.instance_variables.collect {|name| self.instance_variable_get name} ==
+ other.instance_variables.collect {|name| other.instance_variable_get name}
+ end
+ end
+ end
+end
+
# The mv method in Ruby 1.8.5 can't mv directories across devices
# File.rename causes "Invalid cross-device link", which is rescued, but in Ruby
# 1.8.5 it tries to recover with a copy and unlink, but the unlink causes the
# error "Is a directory". In newer Rubies remove_entry is used
# The implementation below is what's used in Ruby 1.8.7 and Ruby 1.9
@@ -236,50 +298,7 @@
end
module_function :mv
alias move mv
module_function :move
- end
-end
-
-# (#19151) Reject all SSLv2 ciphers and handshakes
-require 'openssl'
-class OpenSSL::SSL::SSLContext
- if match = /^1\.8\.(\d+)/.match(RUBY_VERSION)
- older_than_187 = match[1].to_i < 7
- else
- older_than_187 = false
- end
-
- alias __original_initialize initialize
- private :__original_initialize
-
- if older_than_187
- def initialize(*args)
- __original_initialize(*args)
- if bitmask = self.options
- self.options = bitmask | OpenSSL::SSL::OP_NO_SSLv2
- else
- self.options = OpenSSL::SSL::OP_NO_SSLv2
- end
- # These are the default ciphers in recent MRI versions. See
- # https://github.com/ruby/ruby/blob/v1_9_3_392/ext/openssl/lib/openssl/ssl-internal.rb#L26
- self.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW"
- end
- else
- if DEFAULT_PARAMS[:options]
- DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_NO_SSLv2
- else
- DEFAULT_PARAMS[:options] = OpenSSL::SSL::OP_NO_SSLv2
- end
- DEFAULT_PARAMS[:ciphers] << ':!SSLv2'
-
- def initialize(*args)
- __original_initialize(*args)
- params = {
- :options => DEFAULT_PARAMS[:options],
- :ciphers => DEFAULT_PARAMS[:ciphers],
- }
- set_params(params)
- end
end
end