class Batali::BFile
Custom file loading class
Attributes
@return [String] path to cache
Public Class Methods
@return [Proc] cookbook convert
# File lib/batali/b_file.rb, line 126 def self.cookbook_coerce proc do |v| v = [v].flatten.compact if v.size == 1 && v.first.is_a?(Hash) Cookbook.new(v.first) else name, args = v.first, v.slice(1, v.size) if args.empty? args = Smash.new elsif args.size == 1 && args.first.is_a?(Hash) args = args.first else args = Smash.new(:constraint => args.map(&:to_s)) end Cookbook.new(Smash.new(:name => name).merge(args)) end end end
Create a new BFile
instance
@param b_file [String] path to file @param cache_path [String] path to cache directory @return [self]
# File lib/batali/b_file.rb, line 119 def initialize(b_file, cache_path) b_file = Utility.clean_path(b_file) @cache = cache_path super(b_file) end
Public Instance Methods
Search environments for cookbooks and restraints
@return [TrueClass]
# File lib/batali/b_file.rb, line 216 def auto_discover!(environment = nil) debug "Starting cookbook auto-discovery" unless discover raise "Attempting to perform auto-discovery but auto-discovery is not enabled!" end environment_items = Dir.glob(Utility.join_path(File.dirname(path), "environments", "*.{json,rb}")).map do |e_path| result = parse_environment(e_path) if result[:name] && result[:cookbooks] Smash.new( result[:name] => result[:cookbooks], ) end end.compact.inject(Smash.new) { |m, n| m.merge(n) } environment_items.each do |e_name, items| next if environment && e_name != environment debug "Discovery processing of environment: #{e_name}" items.each do |ckbk_name, constraints| ckbk = cookbook.detect do |c| c.name == ckbk_name end if ckbk unless ckbk.constraint debug "Skipping constraint merging due to lack of original constraints: #{ckbk.inspect}" next end new_constraints = ckbk.constraint.dup new_constraints += constraints requirement = UnitRequirement.new(*new_constraints) new_constraints = flatten_constraints(requirement.requirements) debug "Discovery merged constraints for #{ckbk.name}: #{new_constraints.inspect}" ckbk.constraint.replace(new_constraints) else debug "Discovery added cookbook #{ckbk_name}: #{constraints.inspect}" cookbook.push( Cookbook.new( :name => ckbk_name, :constraint => constraints, ) ) end end end debug "Completed cookbook auto-discovery" true end
Protected Instance Methods
Convert constraint for merging
@param constraint [String] @param [Array<String>]
# File lib/batali/b_file.rb, line 268 def convert_constraint(constraint) comp, ver = constraint.split(" ", 2).map(&:strip) if comp == "~>" ver = UnitVersion.new(ver) [">= #{ver}", "< #{ver.bump}"] else [constraint] end end
Proxy debug output
# File lib/batali/b_file.rb, line 364 def debug(s) Batali.debug(s) end
Consume list of constraints and generate compressed list that satisfies all defined constraints.
@param constraints [Array<Array<String, UnitVersion>>] @return [Array<Array<String, UnitVersion>>] @note if an explict constraint is provided, only it will be returned
# File lib/batali/b_file.rb, line 285 def flatten_constraints(constraints) grouped = constraints.group_by(&:first) grouped = Smash[ grouped.map do |comp, items| versions = items.map(&:last) if comp.start_with?(">") [comp, [versions.min]] elsif comp.start_with?("<") [comp, [versions.max]] else [comp, versions] end end ] if grouped["="] grouped[">="] ||= [] grouped["<="] ||= [] grouped["="].each do |ver| grouped[">="] << ver grouped["<="] << ver end grouped.delete("=") end if grouped[">"] || grouped[">="] if grouped[">="] && (grouped[">"].nil? || grouped[">="].min <= grouped[">"].min) grouped[">="] = [grouped[">="].min] grouped.delete(">") else grouped[">"] = [grouped[">"].min] grouped.delete(">=") end end if grouped["<"] || grouped["<="] if grouped["<="] && (grouped["<"].nil? || grouped["<="].max >= grouped["<"].max) grouped["<="] = [grouped["<="].max] grouped.delete("<") else grouped["<"] = [grouped["<"].max] grouped.delete("<=") end end grouped.map do |comp, vers| vers.map do |version| "#{comp} #{version}" end end.flatten end
Read environment file and return defined cookbook constraints
@param path [String] path to environment @return [Smash]
# File lib/batali/b_file.rb, line 337 def parse_environment(path) path = Utility.clean_path(path) case File.extname(path) when ".json" env = MultiJson.load( File.read(path) ).to_smash when ".rb" struct = Struct.new struct.set_state!(:value_collapse => true) struct.instance_eval(File.read(path), path, 1) env = struct._dump.to_smash else raise "Unexpected file format encountered! (#{File.extname(path)})" end Smash.new( :name => env[:name], :cookbooks => Smash[ env.fetch( :cookbook_versions, Smash.new ).map { |k, v| [k, v.to_s.split(",")] } ], ) end