Bee C0 Coverage Information - RCov

lib/bee_build.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
lib/bee_build.rb 285 212
98.60%
98.58%

Key

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.

Coverage Details

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 'syck'
17 require 'yaml'
18 require 'bee_util'
19 require 'bee_context'
20 require 'bee_properties'
21 require 'bee_target'
22 require 'bee_targets'
23 require 'bee_task_packagemanager'
24 
25 module Bee
26   
27   # Class for a build, built from an object resulting from YAML build file parsing.
28   class Build
29     
30     include Bee::Util::BuildErrorMixin
31     include Bee::Util::HashCheckerMixin
32 
33     # Build key.
34     KEY = 'build'
35     # Build entry description.
36     DESCRIPTION = {
37       'build'       => :mandatory, 
38       'default'     => :optional, 
39       'description' => :optional,
40       'context'     => :optional,
41       'extends'     => :optional,
42       'abstract'    => :optional,
43       'alias'       => :optional
44     }
45 
46     # Build file.
47     attr_reader :file
48     # Base directory, that is directory where lives the build file.
49     attr_reader :base
50     # Current directory, where was started the script.
51     attr_reader :here
52     # Build name.
53     attr_reader :name
54     # Parent build.
55     attr_reader :extends
56     # Abstractness.
57     attr_reader :abstract
58     # Build description.
59     attr_reader :description
60     # Build properties.
61     attr_reader :properties
62     # Hash for targets, indexed by target name.
63     attr_reader :targets
64     # Context for Ruby scripts and properties.
65     attr_reader :context
66     # Package manager, for task invocation.
67     attr_reader :package_manager
68     # Build listener, responsible for displaying build status.
69     attr_reader :listener
70     
71     # Load a build from a YAML build file.
72     # - file: YAML build file or URL.
73     # - recursive: tells if we look for build file recursively (defaults to
74     #   nil).
75     # - properties: a hash of additional properties passed on command line.
76     def self.load(file, recursive=nil, properties={})
77       raise "Can't use recursive URL" if recursive and Bee::Util::url?(file)
78       if recursive
79         begin
80           file = Bee::Util::find(file)
81         rescue
82           raise Bee::Util::BuildError.new("Build file '#{file}' " +
83                                           "not found recursively")
84         end
85       end
86       begin
87         yaml = Bee::Util::get_file(file)
88         object = YAML::load(yaml)
89       rescue
90         raise Bee::Util::BuildError.
91            new("Error loading build file '#{file}': #{$!}")
92       end
93       return Build.new(object, file, properties)
94     end
95     
96     # Constructor:
97     # - object: object tree resulting from YAML build file parsing.
98     # - file: build file (nil if none).
99     # - properties: a hash of additional properties passed on command line.
100     # - here: current directory.
101     def initialize(object, file, properties={}, here=Dir.pwd)
102       @file = file
103       @base = get_base(@file)
104       @here = here
105       @properties = Bee::Properties.new
106       @scripts = []
107       @targets = Targets.new(self)
108       parse(object)
109       @properties.overwrite(properties)
110       @properties.defaults({:base => @base, :here => @here})
111       @context = Context.new(@properties.expressions, @scripts)
112       @package_manager = Bee::Task::PackageManager.new(self)
113     end
114 
115     # Run build. Raise a BuildError exception on build error if no listener
116     # was given to be notified of the build failure:
117     # - targets: list of targets to run.
118     # - listener: listener for the build.
119     def run(targets, listener=nil, dry=false)
120       @listener = listener
121       working_directory = Dir.getwd
122       @listener.start(self, dry) if @listener
123       begin
124         error "Abstract build file, must be extended to run" if @abstract
125         if not Bee::Util::url?(@base)
126           Dir.chdir(@base)
127         end
128         @context.evaluate
129         @targets.run(targets, dry)
130         @listener.success() if @listener
131       rescue Bee::Util::BuildError
132         @listener.error($!) if @listener
133         raise $!
134       ensure
135         @listener.stop() if @listener
136         Dir.chdir(working_directory)
137         remove_instance_variable(:@listener)
138       end
139     end
140     
141     private
142 
143     # Parse entries in build object.
144     # - object: object tree resulting from YAML build file parsing.
145     def parse(object)
146       error "Build must be a list" unless object.kind_of?(Array)
147       first = true
148       for entry in object
149         if entry.key?(Build::KEY)
150           parse_build(entry)
151           error "Build info entry must be first one in build file" if not first
152           first = false
153         elsif entry.key?(Properties::KEY)
154           properties = entry[Properties::KEY]
155           # if properties is a string, this is a YAML file to load as a Hash
156           if properties.kind_of?(String)
157             filename = properties
158             begin
159               properties = YAML::load(Bee::Util::get_file(filename, @base))
160               @properties.write(properties)
161             rescue Exception
162               error "Error loading properties file '#{filename}': #{$!}"
163             end
164           else
165             @properties.write(properties)
166           end
167           first = false
168         elsif entry.key?(Target::KEY)
169           @targets.add(entry)
170           first = false
171         else
172           error "Unknown entry:\n#{YAML::dump(entry)}"
173         end
174       end
175       # manage extended builds
176       if @extends
177         for parent in @extends
178           @properties.extend(parent.properties.expressions)
179           @targets.extend(parent.targets)
180         end
181       end
182     end
183     
184     # Parse a build entry.
185     # - entry: the build entry to parse.
186     def parse_build(entry)
187       begin
188         check_hash(entry, Build::DESCRIPTION)
189       rescue
190         error "Error parsing build info entry: #{$!}"
191       end
192       error "Duplicate build info" if @name
193       @name = entry['build']
194       # check that 'default' entry is a string or an array
195       error "'default' entry of the 'build' block must be a string or an array" if
196         entry['default'] and (!entry['default'].kind_of?(String) and
197                               !entry['default'].kind_of?(Array))
198       if entry['default']
199         @targets.default = Array(entry['default'])
200         @targets.default_set = true
201       end
202       # check that 'alias' entry is a hash
203       error "'alias' entry of the 'build' block must be a hash" if
204         entry['alias'] and !entry['alias'].kind_of?(Hash)
205       if entry['alias']
206         @targets.alias = entry['alias']
207         @targets.alias_set = @targets.alias.keys()
208       else
209         @targets.alias_set = []
210       end
211       @description = entry['description']
212       @abstract = entry['abstract']
213       # load parents build if any
214       parents = Array(entry['extends'])
215       if parents.length > 0
216         @extends = []
217         for extended in parents
218           absolute_path = Bee::Util::absolute_path(extended, @base)
219           begin
220             @extends << Bee::Build::load(absolute_path)
221           rescue Exception
222             error "Error loading parent build file '#{extended}': #{$!}"
223           end
224         end
225       end
226       # check that there are no property and target collisions in parents
227       if @extends
228         properties = []
229         collisions = []
230         for parent in @extends
231           parent_properties = parent.properties.expressions.keys
232           collisions += properties & parent_properties
233           properties += parent_properties
234         end
235         collisions = collisions - Bee::Properties::SYSTEM_PROPERTIES
236         collisions = collisions.uniq.map { |e| e.to_s }.sort
237         if collisions.length > 0
238           error "Properties in parents are colliding: #{collisions.join(', ')}"
239         end
240         targets = []
241         collisions = []
242         for parent in @extends
243           parent_targets = parent.targets.hash.keys
244           collisions += targets & parent_targets
245           targets += parent_targets
246         end
247         collisions = collisions.uniq.map { |e| e.to_s }.sort
248         if collisions.length > 0
249           error "Targets in parents are colliding: #{collisions.join(', ')}"
250         end
251       end
252       # load context files if any
253       context = entry['context']
254       @scripts = Array(context) if context
255     end
256     
257     # Get base for a given file.
258     # - file: build file.
259     def get_base(file)
260       if file
261         if Bee::Util::url?(file)
262           return File.dirname(file)
263         else
264           return File.expand_path(File.dirname(file))
265         end
266       else
267         return File.expand_path(Dir.pwd)
268       end
269     end
270 
271   end
272 
273   # Return Bee version. Try to load bee_version file or return UNKNOWN.
274   def version
275     begin
276       require 'bee_version'
277       return Bee::VERSION
278     rescue Exception
279       return 'UNKNOWN'
280     end
281   end
282 
283   module_function :version
284   
285 end

Generated on Fri Oct 09 02:07:48 +0200 2015 with rcov 1.0.0