diff options
Diffstat (limited to 'lib/puppet/string')
23 files changed, 0 insertions, 768 deletions
diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb deleted file mode 100644 index 0f5032ffb..000000000 --- a/lib/puppet/string/action.rb +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -require 'puppet/string' -require 'puppet/string/option' - -class Puppet::String::Action - attr_reader :name - - def to_s - "#{@string}##{@name}" - end - - def initialize(string, name, attrs = {}) - raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ - @string = string - @name = name.to_sym - @options = {} - attrs.each do |k, v| send("#{k}=", v) end - end - - # Initially, this was defined to allow the @action.invoke pattern, which is - # a very natural way to invoke behaviour given our introspection - # capabilities. Heck, our initial plan was to have the string delegate to - # the action object for invocation and all. - # - # It turns out that we have a binding problem to solve: @string was bound to - # the parent class, not the subclass instance, and we don't pass the - # appropriate context or change the binding enough to make this work. - # - # We could hack around it, by either mandating that you pass the context in - # to invoke, or try to get the binding right, but that has probably got - # subtleties that we don't instantly think of – especially around threads. - # - # So, we are pulling this method for now, and will return it to life when we - # have the time to resolve the problem. For now, you should replace... - # - # @action = @string.get_action(name) - # @action.invoke(arg1, arg2, arg3) - # - # ...with... - # - # @action = @string.get_action(name) - # @string.send(@action.name, arg1, arg2, arg3) - # - # I understand that is somewhat cumbersome, but it functions as desired. - # --daniel 2011-03-31 - # - # PS: This code is left present, but commented, to support this chunk of - # documentation, for the benefit of the reader. - # - # def invoke(*args, &block) - # @string.send(name, *args, &block) - # end - - def when_invoked=(block) - # We need to build an instance method as a wrapper, using normal code, to - # be able to expose argument defaulting between the caller and definer in - # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. - # - # In future this also gives us a place to hook in additional behaviour - # such as calling out to the action instance to validate and coerce - # parameters, which avoids any exciting context switching and all. - # - # Hopefully we can improve this when we finally shuffle off the last of - # Ruby 1.8 support, but that looks to be a few "enterprise" release eras - # away, so we are pretty stuck with this for now. - # - # Patches to make this work more nicely with Ruby 1.9 using runtime - # version checking and all are welcome, but they can't actually help if - # the results are not totally hidden away in here. - # - # Incidentally, we though about vendoring evil-ruby and actually adjusting - # the internal C structure implementation details under the hood to make - # this stuff work, because it would have been cleaner. Which gives you an - # idea how motivated we were to make this cleaner. Sorry. --daniel 2011-03-31 - - internal_name = "#{@name} implementation, required on Ruby 1.8".to_sym - file = __FILE__ + "+eval" - line = __LINE__ + 1 - wrapper = "def #{@name}(*args, &block) - args << {} unless args.last.is_a? Hash - args << block if block_given? - self.__send__(#{internal_name.inspect}, *args) - end" - - if @string.is_a?(Class) - @string.class_eval do eval wrapper, nil, file, line end - @string.define_method(internal_name, &block) - else - @string.instance_eval do eval wrapper, nil, file, line end - @string.meta_def(internal_name, &block) - end - end - - def add_option(option) - option.aliases.each do |name| - if conflict = get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - elsif conflict = @string.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@string}" - end - end - - option.aliases.each do |name| - @options[name] = option - end - - option - end - - def option?(name) - @options.include? name.to_sym - end - - def options - (@options.keys + @string.options).sort - end - - def get_option(name) - @options[name.to_sym] || @string.get_option(name) - end -end diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb deleted file mode 100644 index e7c03273b..000000000 --- a/lib/puppet/string/action_builder.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'puppet/string' -require 'puppet/string/action' - -class Puppet::String::ActionBuilder - attr_reader :action - - def self.build(string, name, &block) - raise "Action #{name.inspect} must specify a block" unless block - new(string, name, &block).action - end - - private - def initialize(string, name, &block) - @string = string - @action = Puppet::String::Action.new(string, name) - instance_eval(&block) - end - - # Ideally the method we're defining here would be added to the action, and a - # method on the string would defer to it, but we can't get scope correct, - # so we stick with this. --daniel 2011-03-24 - def when_invoked(&block) - raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action - @action.when_invoked = block - end - - def option(*declaration, &block) - option = Puppet::String::OptionBuilder.build(@action, *declaration, &block) - @action.add_option(option) - end -end diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb deleted file mode 100644 index 9f0aa7582..000000000 --- a/lib/puppet/string/action_manager.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'puppet/string/action_builder' - -module Puppet::String::ActionManager - # Declare that this app can take a specific action, and provide - # the code to do so. - def action(name, &block) - @actions ||= {} - raise "Action #{name} already defined for #{self}" if action?(name) - action = Puppet::String::ActionBuilder.build(self, name, &block) - @actions[action.name] = action - end - - # This is the short-form of an action definition; it doesn't use the - # builder, just creates the action directly from the block. - def script(name, &block) - @actions ||= {} - raise "Action #{name} already defined for #{self}" if action?(name) - @actions[name] = Puppet::String::Action.new(self, name, :when_invoked => block) - end - - def actions - @actions ||= {} - result = @actions.keys - - if self.is_a?(Class) and superclass.respond_to?(:actions) - result += superclass.actions - elsif self.class.respond_to?(:actions) - result += self.class.actions - end - result.sort - end - - def get_action(name) - @actions ||= {} - result = @actions[name.to_sym] - if result.nil? - if self.is_a?(Class) and superclass.respond_to?(:get_action) - result = superclass.get_action(name) - elsif self.class.respond_to?(:get_action) - result = self.class.get_action(name) - end - end - return result - end - - def action?(name) - actions.include?(name.to_sym) - end -end diff --git a/lib/puppet/string/catalog.rb b/lib/puppet/string/catalog.rb deleted file mode 100644 index 441c7ee7d..000000000 --- a/lib/puppet/string/catalog.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:catalog, '0.0.1') do - action(:apply) do - when_invoked do |catalog, options| - report = Puppet::Transaction::Report.new("apply") - report.configuration_version = catalog.version - - Puppet::Util::Log.newdestination(report) - - begin - benchmark(:notice, "Finished catalog run") do - catalog.apply(:report => report) - end - rescue => detail - puts detail.backtrace if Puppet[:trace] - Puppet.err "Failed to apply catalog: #{detail}" - end - - report.finalize_report - report - end - end - - action(:download) do - when_invoked do |certname, facts, options| - Puppet::Resource::Catalog.terminus_class = :rest - facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} - catalog = nil - retrieval_duration = thinmark do - catalog = Puppet::String[:catalog, '0.0.1'].find(certname, facts_to_upload) - end - catalog = catalog.to_ral - catalog.finalize - catalog.retrieval_duration = retrieval_duration - catalog.write_class_file - catalog - end - end -end diff --git a/lib/puppet/string/catalog/select.rb b/lib/puppet/string/catalog/select.rb deleted file mode 100644 index 11670e2e7..000000000 --- a/lib/puppet/string/catalog/select.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Select and show a list of resources of a given type. -Puppet::String.define(:catalog, '0.0.1') do - action :select do - when_invoked do |host, type, options| - catalog = Puppet::Resource::Catalog.indirection.find(host) - - catalog.resources.reject { |res| res.type != type }.each { |res| puts res } - end - end -end diff --git a/lib/puppet/string/certificate.rb b/lib/puppet/string/certificate.rb deleted file mode 100644 index e8773ae2e..000000000 --- a/lib/puppet/string/certificate.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'puppet/string/indirector' -require 'puppet/ssl/host' - -Puppet::String::Indirector.define(:certificate, '0.0.1') do - # REVISIT: This should use a pre-invoke hook to run the common code that - # needs to happen before we invoke any action; that would be much nicer than - # the "please repeat yourself" stuff found in here right now. - # - # option "--ca-location LOCATION" do - # type [:whatever, :location, :symbols] - # hook :before do |value| - # Puppet::SSL::Host.ca_location = value - # end - # end - # - # ...but should I pass the arguments as well? - # --daniel 2011-04-05 - option "--ca-location LOCATION" - - action :generate do - when_invoked do |name, options| - Puppet::SSL::Host.ca_location = options[:ca_location].to_sym - host = Puppet::SSL::Host.new(name) - host.generate_certificate_request - host.certificate_request.class.indirection.save(host.certificate_request) - end - end - - action :list do - when_invoked do |options| - Puppet::SSL::Host.ca_location = options[:ca_location].to_sym - Puppet::SSL::Host.indirection.search("*", { - :for => :certificate_request, - }).map { |h| h.inspect } - end - end - - action :sign do - when_invoked do |name, options| - Puppet::SSL::Host.ca_location = options[:ca_location].to_sym - host = Puppet::SSL::Host.new(name) - host.desired_state = 'signed' - Puppet::SSL::Host.indirection.save(host) - end - end -end diff --git a/lib/puppet/string/certificate_request.rb b/lib/puppet/string/certificate_request.rb deleted file mode 100644 index 218b40b98..000000000 --- a/lib/puppet/string/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:certificate_request, '0.0.1') do -end diff --git a/lib/puppet/string/certificate_revocation_list.rb b/lib/puppet/string/certificate_revocation_list.rb deleted file mode 100644 index 9731b4f2d..000000000 --- a/lib/puppet/string/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:certificate_revocation_list, '0.0.1') do -end diff --git a/lib/puppet/string/config.rb b/lib/puppet/string/config.rb deleted file mode 100644 index 8a9417148..000000000 --- a/lib/puppet/string/config.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/string' - -Puppet::String.define(:config, '0.0.1') do - action(:print) do - when_invoked do |*args| - options = args.pop - Puppet.settings[:configprint] = args.join(",") - Puppet.settings.print_config_options - nil - end - end -end diff --git a/lib/puppet/string/configurer.rb b/lib/puppet/string/configurer.rb deleted file mode 100644 index 257f97e90..000000000 --- a/lib/puppet/string/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/string' - -Puppet::String.define(:configurer, '0.0.1') do - action(:synchronize) do - when_invoked do |certname, options| - facts = Puppet::String[:facts, '0.0.1'].find(certname) - catalog = Puppet::String[:catalog, '0.0.1'].download(certname, facts) - report = Puppet::String[:catalog, '0.0.1'].apply(catalog) - report - end - end -end diff --git a/lib/puppet/string/facts.rb b/lib/puppet/string/facts.rb deleted file mode 100644 index 6bd9904b0..000000000 --- a/lib/puppet/string/facts.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'puppet/string/indirector' -require 'puppet/node/facts' - -Puppet::String::Indirector.define(:facts, '0.0.1') do - set_default_format :yaml - - # Upload our facts to the server - action(:upload) do - when_invoked do |options| - Puppet::Node::Facts.indirection.terminus_class = :facter - facts = Puppet::Node::Facts.indirection.find(Puppet[:certname]) - Puppet::Node::Facts.indirection.terminus_class = :rest - Puppet::Node::Facts.indirection.save(facts) - Puppet.notice "Uploaded facts for '#{Puppet[:certname]}'" - nil - end - end -end diff --git a/lib/puppet/string/file.rb b/lib/puppet/string/file.rb deleted file mode 100644 index cc5737f28..000000000 --- a/lib/puppet/string/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:file, '0.0.1') do - set_indirection_name :file_bucket_file -end diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb deleted file mode 100644 index 0c7d043bb..000000000 --- a/lib/puppet/string/indirector.rb +++ /dev/null @@ -1,94 +0,0 @@ -require 'puppet' -require 'puppet/string' - -class Puppet::String::Indirector < Puppet::String - option "--terminus TERMINUS" do - desc "REVISIT: You can select a terminus, which has some bigger effect -that we should describe in this file somehow." - end - - def self.indirections - Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort - end - - def self.terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort - end - - def call_indirection_method(method, *args) - options = args.pop - options.has_key?(:terminus) and set_terminus(options[:terminus]) - - begin - result = indirection.__send__(method, *args) - rescue => detail - puts detail.backtrace if Puppet[:trace] - raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" - end - - indirection.reset_terminus_class - return result - end - - action :destroy do - when_invoked { |*args| call_indirection_method(:destroy, *args) } - end - - action :find do - when_invoked { |*args| call_indirection_method(:find, *args) } - end - - action :save do - when_invoked { |*args| call_indirection_method(:save, *args) } - end - - action :search do - when_invoked { |*args| call_indirection_method(:search, *args) } - end - - # Print the configuration for the current terminus class - action :info do - when_invoked do |*args| - options = args.pop - options.has_key?(:terminus) and set_terminus(options[:terminus]) - - if t = indirection.terminus_class - puts "Run mode '#{Puppet.run_mode.name}': #{t}" - else - $stderr.puts "No default terminus class for run mode '#{Puppet.run_mode.name}'" - end - - indirection.reset_terminus_class - end - end - - attr_accessor :from - - def indirection_name - @indirection_name || name.to_sym - end - - # Here's your opportunity to override the indirection name. By default - # it will be the same name as the string. - def set_indirection_name(name) - @indirection_name = name - end - - # Return an indirection associated with an string, if one exists - # One usually does. - def indirection - unless @indirection - @indirection = Puppet::Indirector::Indirection.instance(indirection_name) - @indirection or raise "Could not find terminus for #{indirection_name}" - end - @indirection - end - - def set_terminus(from) - begin - indirection.terminus_class = from - rescue => detail - raise "Could not set '#{indirection.name}' terminus to '#{from}' (#{detail}); valid terminus types are #{self.class.terminus_classes(indirection.name).join(", ") }" - end - end -end diff --git a/lib/puppet/string/key.rb b/lib/puppet/string/key.rb deleted file mode 100644 index 95aceade5..000000000 --- a/lib/puppet/string/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:key, '0.0.1') do -end diff --git a/lib/puppet/string/node.rb b/lib/puppet/string/node.rb deleted file mode 100644 index bc31a2cf3..000000000 --- a/lib/puppet/string/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:node, '0.0.1') do - set_default_format :yaml -end diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb deleted file mode 100644 index 352f7e5ef..000000000 --- a/lib/puppet/string/option.rb +++ /dev/null @@ -1,82 +0,0 @@ -require 'puppet/string' - -class Puppet::String::Option - attr_reader :parent - attr_reader :name - attr_reader :aliases - attr_reader :optparse - attr_accessor :desc - - def takes_argument? - !!@argument - end - def optional_argument? - !!@optional_argument - end - - def initialize(parent, *declaration, &block) - @parent = parent - @optparse = [] - - # Collect and sort the arguments in the declaration. - dups = {} - declaration.each do |item| - if item.is_a? String and item.to_s =~ /^-/ then - unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then - raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" - end - @optparse << item - - # Duplicate checking... - name = optparse_to_name(item) - if dup = dups[name] then - raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" - else - dups[name] = item - end - else - raise ArgumentError, "#{item.inspect} is not valid for an option argument" - end - end - - if @optparse.empty? then - raise ArgumentError, "No option declarations found while building" - end - - # Now, infer the name from the options; we prefer the first long option as - # the name, rather than just the first option. - @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) - @aliases = @optparse.map { |o| optparse_to_name(o) } - - # Do we take an argument? If so, are we consistent about it, because - # incoherence here makes our life super-difficult, and we can more easily - # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 - @argument = @optparse.any? { |o| o =~ /[ =]/ } - if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then - raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" - end - - # Is our argument optional? The rules about consistency apply here, also, - # just like they do to taking arguments at all. --daniel 2011-03-30 - @optional_argument = @optparse.any? { |o| o.include? "[" } - if @optional_argument and not @optparse.all? { |o| o.include? "[" } then - raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" - end - end - - # to_s and optparse_to_name are roughly mirrored, because they are used to - # transform strings to name symbols, and vice-versa. This isn't a full - # bidirectional transformation though. - def to_s - @name.to_s.tr('_', '-') - end - - def optparse_to_name(declaration) - unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then - raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" - end - name = found.captures.first.tr('-', '_') - raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ - name.to_sym - end -end diff --git a/lib/puppet/string/option_builder.rb b/lib/puppet/string/option_builder.rb deleted file mode 100644 index da0d213fb..000000000 --- a/lib/puppet/string/option_builder.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'puppet/string/option' - -class Puppet::String::OptionBuilder - attr_reader :option - - def self.build(string, *declaration, &block) - new(string, *declaration, &block).option - end - - private - def initialize(string, *declaration, &block) - @string = string - @option = Puppet::String::Option.new(string, *declaration) - block and instance_eval(&block) - @option - end - - # Metaprogram the simple DSL from the option class. - Puppet::String::Option.instance_methods.grep(/=$/).each do |setter| - next if setter =~ /^=/ # special case, darn it... - - dsl = setter.sub(/=$/, '') - define_method(dsl) do |value| @option.send(setter, value) end - end -end diff --git a/lib/puppet/string/option_manager.rb b/lib/puppet/string/option_manager.rb deleted file mode 100644 index f952ad4f0..000000000 --- a/lib/puppet/string/option_manager.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'puppet/string/option_builder' - -module Puppet::String::OptionManager - # Declare that this app can take a specific option, and provide - # the code to do so. - def option(*declaration, &block) - add_option Puppet::String::OptionBuilder.build(self, *declaration, &block) - end - - def add_option(option) - option.aliases.each do |name| - if conflict = get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - end - - actions.each do |action| - action = get_action(action) - if conflict = action.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{action}" - end - end - end - - option.aliases.each { |name| @options[name] = option } - option - end - - def options - @options ||= {} - result = @options.keys - - if self.is_a?(Class) and superclass.respond_to?(:options) - result += superclass.options - elsif self.class.respond_to?(:options) - result += self.class.options - end - result.sort - end - - def get_option(name) - @options ||= {} - result = @options[name.to_sym] - unless result then - if self.is_a?(Class) and superclass.respond_to?(:get_option) - result = superclass.get_option(name) - elsif self.class.respond_to?(:get_option) - result = self.class.get_option(name) - end - end - return result - end - - def option?(name) - options.include? name.to_sym - end -end diff --git a/lib/puppet/string/report.rb b/lib/puppet/string/report.rb deleted file mode 100644 index da3ca8504..000000000 --- a/lib/puppet/string/report.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:report, '0.0.1') do - action(:submit) do - when_invoked do |report, options| - begin - Puppet::Transaction::Report.terminus_class = :rest - report.save - rescue => detail - puts detail.backtrace if Puppet[:trace] - Puppet.err "Could not send report: #{detail}" - end - end - end -end diff --git a/lib/puppet/string/resource.rb b/lib/puppet/string/resource.rb deleted file mode 100644 index 9838be0fa..000000000 --- a/lib/puppet/string/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:resource, '0.0.1') do -end diff --git a/lib/puppet/string/resource_type.rb b/lib/puppet/string/resource_type.rb deleted file mode 100644 index 8ca31ea6c..000000000 --- a/lib/puppet/string/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:resource_type, '0.0.1') do -end diff --git a/lib/puppet/string/status.rb b/lib/puppet/string/status.rb deleted file mode 100644 index 41de2bb99..000000000 --- a/lib/puppet/string/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:status, '0.0.1') do -end diff --git a/lib/puppet/string/string_collection.rb b/lib/puppet/string/string_collection.rb deleted file mode 100644 index ecd99359d..000000000 --- a/lib/puppet/string/string_collection.rb +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- -require 'puppet/string' - -module Puppet::String::StringCollection - SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ - - @strings = Hash.new { |hash, key| hash[key] = {} } - - def self.strings - unless @loaded - @loaded = true - $LOAD_PATH.each do |dir| - next unless FileTest.directory?(dir) - Dir.chdir(dir) do - Dir.glob("puppet/string/v*/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| - iname = file.sub(/\.rb/, '') - begin - require iname - rescue Exception => detail - puts detail.backtrace if Puppet[:trace] - raise "Could not load #{iname} from #{dir}/#{file}: #{detail}" - end - end - end - end - end - return @strings.keys - end - - def self.validate_version(version) - !!(SEMVER_VERSION =~ version.to_s) - end - - def self.cmp_versions(a, b) - a, b = [a, b].map do |x| - parts = SEMVER_VERSION.match(x).to_a[1..4] - parts[0..2] = parts[0..2].map { |e| e.to_i } - parts - end - - cmp = a[0..2] <=> b[0..2] - if cmp == 0 - cmp = a[3] <=> b[3] - cmp = +1 if a[3].empty? && !b[3].empty? - cmp = -1 if b[3].empty? && !a[3].empty? - end - cmp - end - - def self.[](name, version) - @strings[underscorize(name)][version] if string?(name, version) - end - - def self.string?(name, version) - name = underscorize(name) - return true if @strings[name].has_key?(version) - - # We always load the current version file; the common case is that we have - # the expected version and any compatibility versions in the same file, - # the default. Which means that this is almost always the case. - # - # We use require to avoid executing the code multiple times, like any - # other Ruby library that we might want to use. --daniel 2011-04-06 - begin - require "puppet/string/#{name}" - - # If we wanted :current, we need to index to find that; direct version - # requests just work™ as they go. --daniel 2011-04-06 - if version == :current then - # We need to find current out of this. This is the largest version - # number that doesn't have a dedicated on-disk file present; those - # represent "experimental" versions of strings, which we don't fully - # support yet. - # - # We walk the versions from highest to lowest and take the first version - # that is not defined in an explicitly versioned file on disk as the - # current version. - # - # This constrains us to only ship experimental versions with *one* - # version in the file, not multiple, but given you can't reliably load - # them except by side-effect when you ignore that rule this seems safe - # enough... - # - # Given those constraints, and that we are not going to ship a versioned - # interface that is not :current in this release, we are going to leave - # these thoughts in place, and just punt on the actual versioning. - # - # When we upgrade the core to support multiple versions we can solve the - # problems then; as lazy as possible. - # - # We do support multiple versions in the same file, though, so we sort - # versions here and return the last item in that set. - # - # --daniel 2011-04-06 - latest_ver = @strings[name].keys.sort {|a, b| cmp_versions(a, b) }.last - @strings[name][:current] = @strings[name][latest_ver] - end - rescue LoadError => e - raise unless e.message =~ %r{-- puppet/string/#{name}$} - # ...guess we didn't find the file; return a much better problem. - end - - # Now, either we have the version in our set of strings, or we didn't find - # the version they were looking for. In the future we will support - # loading versioned stuff from some look-aside part of the Ruby load path, - # but we don't need that right now. - # - # So, this comment is a place-holder for that. --daniel 2011-04-06 - return !! @strings[name].has_key?(version) - end - - def self.register(string) - @strings[underscorize(string.name)][string.version] = string - end - - def self.underscorize(name) - unless name.to_s =~ /^[-_a-z]+$/i then - raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid string name" - end - - name.to_s.downcase.split(/[-_]/).join('_').to_sym - end -end |