| Name | Total Lines | Lines of Code | Total Coverage | Code Coverage | 
|---|---|---|---|---|
| lib/bee_context.rb | 201 | 130 | 100.00% | 100.00% | 
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
| 1 # Copyright 2006-2012 Michel Casabianca <michel.casabianca@gmail.com> | 
| 2 # | 
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); | 
| 4 # you may not use this file except in compliance with the License. | 
| 5 # You may obtain a copy of the License at | 
| 6 # | 
| 7 # http://www.apache.org/licenses/LICENSE-2.0 | 
| 8 # | 
| 9 # Unless required by applicable law or agreed to in writing, software | 
| 10 # distributed under the License is distributed on an "AS IS" BASIS, | 
| 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 12 # See the License for the specific language governing permissions and | 
| 13 # limitations under the License. | 
| 14 | 
| 15 require 'rubygems' | 
| 16 require 'bee_util' | 
| 17 require 'bee_properties' | 
| 18 | 
| 19 module Bee | 
| 20 | 
| 21 # Class for build context where properties live as local variables and where | 
| 22 # all scripts (from context or in Ruby tasks) are evaluated. | 
| 23 class Context | 
| 24 | 
| 25 include Bee::Util::BuildErrorMixin | 
| 26 | 
| 27 # The context binding | 
| 28 attr_reader :context_binding | 
| 29 | 
| 30 # Constructor. | 
| 31 # - properties: properties as a hash that gives expression for a given | 
| 32 # property. | 
| 33 # - scripts: list of script files to run in context. | 
| 34 def initialize(properties={}, scripts=[]) | 
| 35 @context_binding = get_binding | 
| 36 @properties = properties | 
| 37 @scripts = scripts | 
| 38 end | 
| 39 | 
| 40 # Evaluate properties and scripts in the context. Should run while running | 
| 41 # the build, not while loading it. | 
| 42 def evaluate | 
| 43 evaluate_default_properties | 
| 44 evaluate_scripts | 
| 45 evaluate_properties | 
| 46 end | 
| 47 | 
| 48 # Return the list of properties (that is the list of local variables of | 
| 49 # context) as an unsorted list of strings. | 
| 50 def properties | 
| 51 return eval('local_variables', @context_binding).map{|var| var.to_s} | 
| 52 end | 
| 53 | 
| 54 # Set a given property in context. | 
| 55 # - name: the property name as a string or symbol. | 
| 56 # - value: the property value as an object. | 
| 57 def set_property(name, value) | 
| 58 begin | 
| 59 eval("#{name} = #{value.inspect}", @context_binding) | 
| 60 rescue Exception | 
| 61 error "Error setting property '#{name} = #{value.inspect}': #{$!}" | 
| 62 end | 
| 63 end | 
| 64 | 
| 65 # Get a given property in context. Raises an error if the property was not | 
| 66 # set. | 
| 67 # - name: the property name. | 
| 68 def get_property(name) | 
| 69 begin | 
| 70 eval("#{name}", @context_binding) | 
| 71 rescue NameError | 
| 72 error "Property '#{name}' was not set" | 
| 73 rescue Exception | 
| 74 error "Error getting property '#{name}': #{$!}" | 
| 75 end | 
| 76 end | 
| 77 | 
| 78 # Evaluate a script in context. | 
| 79 # - source: source of the script to evaluate. | 
| 80 def evaluate_script(source) | 
| 81 eval(source, @context_binding) | 
| 82 end | 
| 83 | 
| 84 # Process a given object, replacing properties references with their | 
| 85 # string value, symbol with their raw value. Property references have | 
| 86 # same form than variable references in ruby strings: '#{variable}' | 
| 87 # will be replaced with variable string value. | 
| 88 # - object: object to process. | 
| 89 def evaluate_object(object) | 
| 90 case object | 
| 91 when NilClass | 
| 92 # nil: return nil | 
| 93 return nil | 
| 94 when String | 
| 95 # string: replace embedded Ruby expressions | 
| 96 object = object.gsub(/#\{.+?\}/) do |match| | 
| 97 expression = match[2..-2] | 
| 98 begin | 
| 99 value = eval(expression, @context_binding) | 
| 100 rescue | 
| 101 error "Error evaluating expression '#{expression}': #{$!}" | 
| 102 end | 
| 103 value | 
| 104 end | 
| 105 return object | 
| 106 when Symbol | 
| 107 # symbol: return property object | 
| 108 property = object.to_s | 
| 109 begin | 
| 110 value = eval("#{property}", @context_binding) | 
| 111 rescue | 
| 112 error "Property '#{property}' was not set" | 
| 113 end | 
| 114 return evaluate_object(value) | 
| 115 when Array | 
| 116 # array: evaluate each element | 
| 117 return object.collect { |element| evaluate_object(element) } | 
| 118 when Hash | 
| 119 # hash: evaluate all keys and values | 
| 120 evaluated = {} | 
| 121 object.each_pair do |key, value| | 
| 122 evaluated[evaluate_object(key)] = evaluate_object(value) | 
| 123 end | 
| 124 return evaluated | 
| 125 else | 
| 126 return object | 
| 127 end | 
| 128 end | 
| 129 | 
| 130 private | 
| 131 | 
| 132 # Evaluate properties in context, except system properties. | 
| 133 def evaluate_properties | 
| 134 for name in (@properties.keys - Bee::Properties::SYSTEM_PROPERTIES) | 
| 135 begin | 
| 136 Thread.current[:stack] = [] | 
| 137 evaluate_property(name) | 
| 138 ensure | 
| 139 Thread.current[:stack] = nil | 
| 140 end | 
| 141 end | 
| 142 end | 
| 143 | 
| 144 # Evaluate default properties in context. | 
| 145 def evaluate_default_properties | 
| 146 for name in Bee::Properties::SYSTEM_PROPERTIES | 
| 147 begin | 
| 148 Thread.current[:stack] = [] | 
| 149 evaluate_property(name) | 
| 150 ensure | 
| 151 Thread.current[:stack] = nil | 
| 152 end | 
| 153 end | 
| 154 end | 
| 155 | 
| 156 # Evaluate a property with given name. | 
| 157 # - name: the name of the property to evaluate. | 
| 158 def evaluate_property(name) | 
| 159 stack = Thread.current[:stack] | 
| 160 error "Circular properties: #{stack.join(', ')}" if stack.include?(name) | 
| 161 begin | 
| 162 stack.push(name) | 
| 163 value = evaluate_object(@properties[name]) | 
| 164 stack.pop | 
| 165 set_property(name, value) | 
| 166 return value | 
| 167 rescue | 
| 168 error "Error evaluating property '#{name}': #{$!}" | 
| 169 end | 
| 170 end | 
| 171 | 
| 172 # Evaluate scripts in the context. | 
| 173 def evaluate_scripts | 
| 174 for script in @scripts | 
| 175 begin | 
| 176 source = Bee::Util::get_file(script, @base) | 
| 177 evaluate_script(source) | 
| 178 rescue Exception | 
| 179 error "Error loading context '#{script}': #{$!}" | 
| 180 end | 
| 181 end | 
| 182 end | 
| 183 | 
| 184 # Catch missing properties as missing methods. | 
| 185 # - name: the name of the missing property or method. | 
| 186 def method_missing(name, *args, &block) | 
| 187 if Thread.current[:stack] | 
| 188 return evaluate_property(name) | 
| 189 else | 
| 190 raise NoMethodError.new("undefined method `#{name}'", name, args) | 
| 191 end | 
| 192 end | 
| 193 | 
| 194 # Get a binding as script context. | 
| 195 def get_binding | 
| 196 return binding | 
| 197 end | 
| 198 | 
| 199 end | 
| 200 | 
| 201 end | 
Generated on Fri Oct 09 02:07:49 +0200 2015 with rcov 1.0.0