bee 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +1 -1
- data/egg/application.yml +2 -2
- data/egg/application/build.yml +23 -23
- data/egg/package.yml +2 -2
- data/egg/package/build.erb +21 -21
- data/egg/package/egg.yml +2 -2
- data/egg/package/egg_build.erb +5 -5
- data/egg/script.yml +2 -2
- data/egg/script/build.yml +5 -5
- data/egg/sinatra.yml +2 -2
- data/egg/sinatra/build.yml +8 -8
- data/egg/source.yml +2 -2
- data/egg/xmlrpc.yml +2 -2
- data/egg/xmlrpc/build.yml +6 -6
- data/lib/bee.rb +44 -569
- data/lib/bee_console.rb +25 -28
- data/lib/bee_context.rb +138 -0
- data/lib/bee_properties.rb +145 -0
- data/lib/bee_target.rb +287 -0
- metadata +6 -3
    
        data/README
    CHANGED
    
    
    
        data/egg/application.yml
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
              description: "Generate a sample Ruby application project"
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                name: application
         | 
| 7 | 
            +
                description: |
         | 
| 8 8 | 
             
                  This script will create a sample Ruby application project. Build file
         | 
| 9 9 | 
             
                  can run unit tests, generate API documentation, generate GEM archive
         | 
| 10 10 | 
             
                  and build a ZIP distribution file.
         | 
    
        data/egg/application/build.yml
    CHANGED
    
    | @@ -5,30 +5,30 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            # Build properties
         | 
| 7 7 | 
             
            - properties:
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 8 | 
            +
                name:         "<%= name %>"
         | 
| 9 | 
            +
                version:      ~
         | 
| 10 | 
            +
                author:       ~
         | 
| 11 | 
            +
                years:        ~
         | 
| 12 | 
            +
                platform:     "Gem::Platform::RUBY"
         | 
| 13 | 
            +
                summary:      ~
         | 
| 14 | 
            +
                email:        ~
         | 
| 15 | 
            +
                homepage:     ~
         | 
| 16 | 
            +
                rubyforge:    ~
         | 
| 17 | 
            +
                dependencies:
         | 
| 18 18 | 
             
                  bee: [">= 0.7.0"]
         | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 19 | 
            +
                lib_dir:      "lib"
         | 
| 20 | 
            +
                test_dir:     "test"
         | 
| 21 | 
            +
                build_dir:    "build"
         | 
| 22 | 
            +
                api_dir:      "#{build_dir}/api"
         | 
| 23 | 
            +
                gem_spec:     "gem.spec"
         | 
| 24 | 
            +
                gem_spec_erb: "gem.spec.erb"
         | 
| 25 | 
            +
                gem_package:  "#{name}-#{version}.gem"
         | 
| 26 | 
            +
                rdoc_files:   ["#{lib_dir}/*.rb"]
         | 
| 27 | 
            +
                zip_excludes: ["**/CVS", "**/.DS_Store", "**/*~"]
         | 
| 28 | 
            +
                zip_prefix:   "#{name}-#{version}"
         | 
| 29 | 
            +
                zip_archive:  "#{build_dir}/#{name}-#{version}.zip"
         | 
| 30 | 
            +
                clean_dirs:   [:build_dir]
         | 
| 31 | 
            +
                clean_files:  ["**/*~", "**/.#*", "**/.DS_Store", :gem_spec]
         | 
| 32 32 |  | 
| 33 33 | 
             
            # Build targets
         | 
| 34 34 | 
             
            - target: test
         | 
    
        data/egg/package.yml
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
              description: "Generate a bee package project"
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                project_name: bee_hello
         | 
| 7 | 
            +
                description: |
         | 
| 8 8 | 
             
                  This script will create a project for a bee package with sample task (in
         | 
| 9 9 | 
             
                  'lib' directory) and template (in 'egg' directory). A unit test for the
         | 
| 10 10 | 
             
                  task is generated in 'test' directory. Generated build file has a target
         | 
    
        data/egg/package/build.erb
    CHANGED
    
    | @@ -6,28 +6,28 @@ | |
| 6 6 |  | 
| 7 7 | 
             
            # Build properties
         | 
| 8 8 | 
             
            - properties:
         | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 9 | 
            +
                name: <%= project_name %>
         | 
| 10 | 
            +
                version: 0.0.1
         | 
| 11 | 
            +
                author: ~
         | 
| 12 | 
            +
                years: ~
         | 
| 13 | 
            +
                platform: "Gem::Platform::RUBY"
         | 
| 14 | 
            +
                summary: ~
         | 
| 15 | 
            +
                email: ~
         | 
| 16 | 
            +
                homepage: "http://<%= project_name %>.rubyforge.org"
         | 
| 17 | 
            +
                rubyforge: ~
         | 
| 18 | 
            +
                dependencies:
         | 
| 19 19 | 
             
                  "bee": [">= 0.5.0"]
         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 20 | 
            +
                lib_dir: "lib"
         | 
| 21 | 
            +
                test_dir: "test"
         | 
| 22 | 
            +
                build_dir: "build"
         | 
| 23 | 
            +
                readme_erb: "readme.erb"
         | 
| 24 | 
            +
                readme_file: "#{build_dir}/README"
         | 
| 25 | 
            +
                license_file: "LICENSE"
         | 
| 26 | 
            +
                gem_spec_erb: "gem.spec.erb"
         | 
| 27 | 
            +
                gem_spec: "#{build_dir}/gem.spec"
         | 
| 28 | 
            +
                gem_package: "#{name}-#{version}.gem"
         | 
| 29 | 
            +
                clean_dirs: :build_dir
         | 
| 30 | 
            +
                clean_files: ""
         | 
| 31 31 |  | 
| 32 32 | 
             
            # Build targets
         | 
| 33 33 | 
             
            - target: test
         | 
    
        data/egg/package/egg.yml
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
              description: "Generate a project for a Ruby script"
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                project_name: hello
         | 
| 7 | 
            +
                description: |
         | 
| 8 8 | 
             
                  This script will create a project for a Ruby script that might be
         | 
| 9 9 | 
             
                  distributed as a gem. Generated build file has a single target gem
         | 
| 10 10 | 
             
                  to generate the distribution gem.
         | 
    
        data/egg/package/egg_build.erb
    CHANGED
    
    | @@ -3,11 +3,11 @@ | |
| 3 3 | 
             
              default: all
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 6 | 
            +
                name: <%= project_name %>
         | 
| 7 | 
            +
                version: 0.0.1
         | 
| 8 | 
            +
                build: build
         | 
| 9 | 
            +
                gem_spec: "#{build}/gem_spec"
         | 
| 10 | 
            +
                gem_erb: |
         | 
| 11 11 | 
             
                  require 'rubygems'
         | 
| 12 12 | 
             
                  SPEC = Gem::Specification.new do |spec|
         | 
| 13 13 | 
             
                    spec.name = '<%= name %>'
         | 
    
        data/egg/script.yml
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
              description: "Generate a sample Ruby script project"
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                name: script
         | 
| 7 | 
            +
                description: This script will generate a sample Ruby script project.
         | 
| 8 8 |  | 
| 9 9 | 
             
            - target: welcome
         | 
| 10 10 | 
             
              description: "Print information message"
         | 
    
        data/egg/script/build.yml
    CHANGED
    
    | @@ -5,11 +5,11 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            # Build properties
         | 
| 7 7 | 
             
            - properties:
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 8 | 
            +
                name:        "<%= name %>"
         | 
| 9 | 
            +
                version:     "0.0.0"
         | 
| 10 | 
            +
                build:       "build"
         | 
| 11 | 
            +
                clean_dirs:  [:build]
         | 
| 12 | 
            +
                clean_files: ["**/*~", "**/.#*", "**/.DS_Store"]
         | 
| 13 13 |  | 
| 14 14 | 
             
            # Build targets
         | 
| 15 15 | 
             
            - target: zip
         | 
    
        data/egg/sinatra.yml
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
              description: "Generate a Sinatra project"
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                name: sinatra
         | 
| 7 | 
            +
                description: |
         | 
| 8 8 | 
             
                  This script will create a Sinatra project. Generated build file has a 
         | 
| 9 9 | 
             
                  target 'run' to run the server, 'zip' to generate a distribution archive
         | 
| 10 10 | 
             
                  and 'clean' to delete generated files.
         | 
    
        data/egg/sinatra/build.yml
    CHANGED
    
    | @@ -3,14 +3,14 @@ | |
| 3 3 | 
             
              default: all
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 6 | 
            +
                name:         "<%= name %>"
         | 
| 7 | 
            +
                version:      "0.0.0"
         | 
| 8 | 
            +
                build:        "build"
         | 
| 9 | 
            +
                zip_prefix:   "#{name}-#{version}"
         | 
| 10 | 
            +
                zip_file:     "#{build}/#{zip_prefix}.zip"
         | 
| 11 | 
            +
                url:          "http://localhost:4567/hello"
         | 
| 12 | 
            +
                clean_dirs:   [:build]
         | 
| 13 | 
            +
                clean_files:  ["**/*~", "**/.#*", "**/.DS_Store"]
         | 
| 14 14 |  | 
| 15 15 | 
             
            - target: run
         | 
| 16 16 | 
             
              description: Run server
         | 
    
        data/egg/source.yml
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
              description: Generate a sample Ruby source file
         | 
| 4 4 |  | 
| 5 5 | 
             
            - properties:
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                name:        source.rb
         | 
| 7 | 
            +
                description: This script will generate a sample Ruby source file.
         | 
| 8 8 |  | 
| 9 9 | 
             
            - target:      welcome
         | 
| 10 10 | 
             
              description: Print information message
         | 
    
        data/egg/xmlrpc.yml
    CHANGED
    
    
    
        data/egg/xmlrpc/build.yml
    CHANGED
    
    | @@ -5,12 +5,12 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            # Build properties
         | 
| 7 7 | 
             
            - properties:
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 8 | 
            +
                name:        <%= project_name %>
         | 
| 9 | 
            +
                version:     "0.0.0"
         | 
| 10 | 
            +
                build:       "build"
         | 
| 11 | 
            +
                zip:         "#{build}/#{name}-#{version}.zip"
         | 
| 12 | 
            +
                clean_dirs:  [:build]
         | 
| 13 | 
            +
                clean_files: ["**/*~", "**/.#*", "**/.DS_Store"]
         | 
| 14 14 |  | 
| 15 15 | 
             
            # Build targets
         | 
| 16 16 | 
             
            - target: server
         | 
    
        data/lib/bee.rb
    CHANGED
    
    | @@ -15,7 +15,10 @@ | |
| 15 15 | 
             
            require 'rubygems'
         | 
| 16 16 | 
             
            require 'yaml'
         | 
| 17 17 | 
             
            require 'bee_task'
         | 
| 18 | 
            +
            require 'bee_target'
         | 
| 18 19 | 
             
            require 'bee_util'
         | 
| 20 | 
            +
            require 'bee_context'
         | 
| 21 | 
            +
            require 'bee_properties'
         | 
| 19 22 |  | 
| 20 23 | 
             
            # Module for Bee core classes.
         | 
| 21 24 | 
             
            module Bee
         | 
| @@ -36,7 +39,6 @@ module Bee | |
| 36 39 | 
             
                  'description' => :optional,
         | 
| 37 40 | 
             
                  'context'     => :optional,
         | 
| 38 41 | 
             
                  'extends'     => :optional,
         | 
| 39 | 
            -
                  'includes'    => :optional,
         | 
| 40 42 | 
             
                  'abstract'    => :optional
         | 
| 41 43 | 
             
                }
         | 
| 42 44 |  | 
| @@ -50,8 +52,6 @@ module Bee | |
| 50 52 | 
             
                attr_reader :name
         | 
| 51 53 | 
             
                # Parent build.
         | 
| 52 54 | 
             
                attr_reader :extends
         | 
| 53 | 
            -
                # Included builds
         | 
| 54 | 
            -
                attr_reader :includes
         | 
| 55 55 | 
             
                # Abstractness.
         | 
| 56 56 | 
             
                attr_reader :abstract
         | 
| 57 57 | 
             
                # Default target, specified with default entry or fist target in build file.
         | 
| @@ -108,8 +108,8 @@ module Bee | |
| 108 108 | 
             
                  @file = file
         | 
| 109 109 | 
             
                  @base = get_base(@file)
         | 
| 110 110 | 
             
                  @here = here
         | 
| 111 | 
            -
                  @context = Context.new
         | 
| 112 111 | 
             
                  @properties = Properties.new(self)
         | 
| 112 | 
            +
                  @context = Context.new(@properties)
         | 
| 113 113 | 
             
                  @properties.evaluate(@context)
         | 
| 114 114 | 
             
                  @targets = Targets.new(self)
         | 
| 115 115 | 
             
                  parse(object)
         | 
| @@ -172,16 +172,11 @@ module Bee | |
| 172 172 | 
             
                      error "Unknown entry:\n#{YAML::dump(entry)}"
         | 
| 173 173 | 
             
                    end
         | 
| 174 174 | 
             
                  end
         | 
| 175 | 
            -
                  # manage  | 
| 176 | 
            -
                  if @ | 
| 177 | 
            -
                    @ | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
                  # manage included builds
         | 
| 181 | 
            -
                  if @included
         | 
| 182 | 
            -
                    for include in @included.reverse
         | 
| 183 | 
            -
                      @properties.include(include.properties)
         | 
| 184 | 
            -
                      @targets.include(include.targets)
         | 
| 175 | 
            +
                  # manage extended builds
         | 
| 176 | 
            +
                  if @extends
         | 
| 177 | 
            +
                    for parent in @extends
         | 
| 178 | 
            +
                      @properties.extend(parent.properties)
         | 
| 179 | 
            +
                      @targets.extend(parent.targets)
         | 
| 185 180 | 
             
                    end
         | 
| 186 181 | 
             
                  end
         | 
| 187 182 | 
             
                end
         | 
| @@ -199,33 +194,46 @@ module Bee | |
| 199 194 | 
             
                  @default = entry['default']
         | 
| 200 195 | 
             
                  @targets.default = @default
         | 
| 201 196 | 
             
                  @description = entry['description']
         | 
| 202 | 
            -
                  @extends = entry['extends']
         | 
| 203 | 
            -
                  @includes = Array(entry['includes'])
         | 
| 204 197 | 
             
                  @abstract = entry['abstract']
         | 
| 205 | 
            -
                  # load  | 
| 206 | 
            -
                   | 
| 207 | 
            -
             | 
| 208 | 
            -
                     | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
                      error "Error loading parent build file '#{@extends}': #{$!}"
         | 
| 212 | 
            -
                    end
         | 
| 213 | 
            -
                    @default = @default || @parent.default
         | 
| 214 | 
            -
                    @targets.default = @default
         | 
| 215 | 
            -
                    @description = @description || @parent.description
         | 
| 216 | 
            -
                  end
         | 
| 217 | 
            -
                  # load included build files if any
         | 
| 218 | 
            -
                  if @includes
         | 
| 219 | 
            -
                    @included = []
         | 
| 220 | 
            -
                    for include in @includes
         | 
| 221 | 
            -
                      absolute_path = Bee::Util::absolute_path(include, @base)
         | 
| 198 | 
            +
                  # load parents build if any
         | 
| 199 | 
            +
                  parents = Array(entry['extends'])
         | 
| 200 | 
            +
                  if parents.length > 0
         | 
| 201 | 
            +
                    @extends = []
         | 
| 202 | 
            +
                    for extended in parents
         | 
| 203 | 
            +
                      absolute_path = Bee::Util::absolute_path(extended, @base)
         | 
| 222 204 | 
             
                      begin
         | 
| 223 | 
            -
                        @ | 
| 205 | 
            +
                        @extends << Bee::Build::load(absolute_path)
         | 
| 224 206 | 
             
                      rescue Exception
         | 
| 225 | 
            -
                        error "Error loading  | 
| 207 | 
            +
                        error "Error loading parent build file '#{extended}': #{$!}"
         | 
| 226 208 | 
             
                      end
         | 
| 227 209 | 
             
                    end
         | 
| 228 210 | 
             
                  end
         | 
| 211 | 
            +
                  # check that there are no property and target collisions in parents
         | 
| 212 | 
            +
                  if @extends
         | 
| 213 | 
            +
                    properties = []
         | 
| 214 | 
            +
                    collisions = []
         | 
| 215 | 
            +
                    for parent in @extends
         | 
| 216 | 
            +
                      parent_properties = parent.properties.expressions.keys
         | 
| 217 | 
            +
                      collisions += properties & parent_properties
         | 
| 218 | 
            +
                      properties += parent_properties
         | 
| 219 | 
            +
                    end
         | 
| 220 | 
            +
                    collisions = collisions - Properties::SYSTEM_PROPERTIES
         | 
| 221 | 
            +
                    collisions = collisions.uniq.map { |e| e.to_s }.sort
         | 
| 222 | 
            +
                    if collisions.length > 0
         | 
| 223 | 
            +
                      error "Properties in parents are colliding: #{collisions.join(', ')}"
         | 
| 224 | 
            +
                    end
         | 
| 225 | 
            +
                    targets = []
         | 
| 226 | 
            +
                    collisions = []
         | 
| 227 | 
            +
                    for parent in @extends
         | 
| 228 | 
            +
                      parent_targets = parent.targets.hash.keys
         | 
| 229 | 
            +
                      collisions += targets & parent_targets
         | 
| 230 | 
            +
                      targets += parent_targets
         | 
| 231 | 
            +
                    end
         | 
| 232 | 
            +
                    collisions = collisions.uniq.map { |e| e.to_s }.sort
         | 
| 233 | 
            +
                    if collisions.length > 0
         | 
| 234 | 
            +
                      error "Targets in parents are colliding: #{collisions.join(', ')}"
         | 
| 235 | 
            +
                    end
         | 
| 236 | 
            +
                  end
         | 
| 229 237 | 
             
                  # load context files if any
         | 
| 230 238 | 
             
                  context = entry['context']
         | 
| 231 239 | 
             
                  if context
         | 
| @@ -258,146 +266,6 @@ module Bee | |
| 258 266 |  | 
| 259 267 | 
             
              end
         | 
| 260 268 |  | 
| 261 | 
            -
              # Class to manage properties.
         | 
| 262 | 
            -
              class Properties
         | 
| 263 | 
            -
             | 
| 264 | 
            -
                include Bee::Util::BuildErrorMixin
         | 
| 265 | 
            -
             | 
| 266 | 
            -
                # Key for properties entry.
         | 
| 267 | 
            -
                KEY = 'properties'
         | 
| 268 | 
            -
             | 
| 269 | 
            -
                # List of system properties
         | 
| 270 | 
            -
                SYSTEM_PROPERTIES = [:base, :here]
         | 
| 271 | 
            -
             | 
| 272 | 
            -
                # List of properties in order of evaluation.
         | 
| 273 | 
            -
                attr_reader :list
         | 
| 274 | 
            -
                # Hash of properties by name.
         | 
| 275 | 
            -
                attr_reader :hash
         | 
| 276 | 
            -
             | 
| 277 | 
            -
                # Constructor.
         | 
| 278 | 
            -
                # - build: build object.
         | 
| 279 | 
            -
                def initialize(build)
         | 
| 280 | 
            -
                  @list = []
         | 
| 281 | 
            -
                  @hash = {}
         | 
| 282 | 
            -
                  @build = build
         | 
| 283 | 
            -
                  defaults
         | 
| 284 | 
            -
                end
         | 
| 285 | 
            -
             | 
| 286 | 
            -
                # Write properties. Will raise an error on duplicate definitions.
         | 
| 287 | 
            -
                # - object: object tree resulting from YAML build file parsing or string
         | 
| 288 | 
            -
                #   for a properties file to load.
         | 
| 289 | 
            -
                def write(object)
         | 
| 290 | 
            -
                  properties = object[Properties::KEY]
         | 
| 291 | 
            -
                  if properties.kind_of?(String)
         | 
| 292 | 
            -
                    begin
         | 
| 293 | 
            -
                      source = Bee::Util::get_file(properties, @build.base)
         | 
| 294 | 
            -
                      list = YAML::load(source)
         | 
| 295 | 
            -
                      set_properties(list, false)
         | 
| 296 | 
            -
                    rescue Exception
         | 
| 297 | 
            -
                      error "Error loading properties file '#{properties}': #{$!}"
         | 
| 298 | 
            -
                    end
         | 
| 299 | 
            -
                  else
         | 
| 300 | 
            -
                    set_properties(properties, false)
         | 
| 301 | 
            -
                  end
         | 
| 302 | 
            -
                end
         | 
| 303 | 
            -
             | 
| 304 | 
            -
                # Overwrite properties. Will raise an error if properties don't already
         | 
| 305 | 
            -
                # exist.
         | 
| 306 | 
            -
                # - object: object tree resulting from YAML build file parsing.
         | 
| 307 | 
            -
                def overwrite(object)
         | 
| 308 | 
            -
                  set_properties(object, true)
         | 
| 309 | 
            -
                end
         | 
| 310 | 
            -
             | 
| 311 | 
            -
                # Extend with properties of parent build.
         | 
| 312 | 
            -
                # - properties: properties of parent build.
         | 
| 313 | 
            -
                def extend(properties)
         | 
| 314 | 
            -
                  current_list = @list
         | 
| 315 | 
            -
                  current_hash = @hash
         | 
| 316 | 
            -
                  @list = properties.list
         | 
| 317 | 
            -
                  @hash = properties.hash
         | 
| 318 | 
            -
                  index = 0
         | 
| 319 | 
            -
                  0.upto(current_list.length - 1) do |current|
         | 
| 320 | 
            -
                    name = current_list[current]
         | 
| 321 | 
            -
                    pos = @list.index(name)
         | 
| 322 | 
            -
                    if pos
         | 
| 323 | 
            -
                      sub = current_list[index .. current]
         | 
| 324 | 
            -
                      @list[pos .. pos] = sub
         | 
| 325 | 
            -
                      for name in sub
         | 
| 326 | 
            -
                        @hash[name] = current_hash[name]
         | 
| 327 | 
            -
                      end
         | 
| 328 | 
            -
                      index = current + 1
         | 
| 329 | 
            -
                    end
         | 
| 330 | 
            -
                  end
         | 
| 331 | 
            -
                  tail = current_list[index .. current_list.length() - 1]
         | 
| 332 | 
            -
                  @list += tail
         | 
| 333 | 
            -
                  for name in tail
         | 
| 334 | 
            -
                    @hash[name] = current_hash[name]
         | 
| 335 | 
            -
                  end
         | 
| 336 | 
            -
                end
         | 
| 337 | 
            -
             | 
| 338 | 
            -
                # Include properties of included build.
         | 
| 339 | 
            -
                # - properties: properties of parent build.
         | 
| 340 | 
            -
                def include(properties)
         | 
| 341 | 
            -
                  extend(properties)
         | 
| 342 | 
            -
                end
         | 
| 343 | 
            -
             | 
| 344 | 
            -
                # Evaluate properties in context.
         | 
| 345 | 
            -
                # - context: build context where properties must be evaluated.
         | 
| 346 | 
            -
                def evaluate(context)
         | 
| 347 | 
            -
                  for name in @list
         | 
| 348 | 
            -
                    begin
         | 
| 349 | 
            -
                      value = context.evaluate_object(@hash[name])
         | 
| 350 | 
            -
                    rescue Bee::Util::BuildError
         | 
| 351 | 
            -
                      error "Error evaluating property '#{name}': #{$!}"
         | 
| 352 | 
            -
                    end
         | 
| 353 | 
            -
                    context.set_property(name, value, true)
         | 
| 354 | 
            -
                  end
         | 
| 355 | 
            -
                end
         | 
| 356 | 
            -
             | 
| 357 | 
            -
                private
         | 
| 358 | 
            -
             | 
| 359 | 
            -
                # Set default properties.
         | 
| 360 | 
            -
                def defaults
         | 
| 361 | 
            -
                  set(:base, @build.base, false)
         | 
| 362 | 
            -
                  set(:here, @build.here, false)
         | 
| 363 | 
            -
                end
         | 
| 364 | 
            -
             | 
| 365 | 
            -
                # Set properties.
         | 
| 366 | 
            -
                # - properties: properties as a list of hash if overwrite = false
         | 
| 367 | 
            -
                #   or a hash if overwrite = true.
         | 
| 368 | 
            -
                # - overwrite: tells if we can overwrite existing properties.
         | 
| 369 | 
            -
                def set_properties(properties, overwrite)
         | 
| 370 | 
            -
                  if overwrite
         | 
| 371 | 
            -
                    raise "Properties must be a hash" if not properties.kind_of?(Hash)
         | 
| 372 | 
            -
                    for name in properties.keys
         | 
| 373 | 
            -
                      expression = properties[name]
         | 
| 374 | 
            -
                      set(name, expression, overwrite)
         | 
| 375 | 
            -
                    end
         | 
| 376 | 
            -
                  else
         | 
| 377 | 
            -
                    raise "Properties must be a list" if not properties.kind_of?(Array)
         | 
| 378 | 
            -
                    for property in properties
         | 
| 379 | 
            -
                      name = property.keys[0]
         | 
| 380 | 
            -
                      expression = property[name]
         | 
| 381 | 
            -
                      set(name, expression, overwrite)
         | 
| 382 | 
            -
                    end
         | 
| 383 | 
            -
                  end
         | 
| 384 | 
            -
                end
         | 
| 385 | 
            -
             | 
| 386 | 
            -
                # Set a property.
         | 
| 387 | 
            -
                # - name: property name (as a string or symbol).
         | 
| 388 | 
            -
                # - expression: property expression (as a string) to be evaluated in
         | 
| 389 | 
            -
                #   context to get value.
         | 
| 390 | 
            -
                # - overwrite: tells if we can overwrite existing properties.
         | 
| 391 | 
            -
                def set(name, expression, overwrite)
         | 
| 392 | 
            -
                  name = name.to_sym
         | 
| 393 | 
            -
                  error "Duplicate property definition: '#{name}'" if 
         | 
| 394 | 
            -
                    not overwrite and @hash.has_key?(name)
         | 
| 395 | 
            -
                  @list << name
         | 
| 396 | 
            -
                  @hash[name] = expression
         | 
| 397 | 
            -
                end
         | 
| 398 | 
            -
             | 
| 399 | 
            -
              end
         | 
| 400 | 
            -
             | 
| 401 269 | 
             
              # Class to manage targets in a build.
         | 
| 402 270 | 
             
              class Targets
         | 
| 403 271 |  | 
| @@ -470,25 +338,6 @@ module Bee | |
| 470 338 | 
             
                  @default = @default || parent.default
         | 
| 471 339 | 
             
                end
         | 
| 472 340 |  | 
| 473 | 
            -
                # Include included build file targets.
         | 
| 474 | 
            -
                # - included: included build file targets.
         | 
| 475 | 
            -
                def include(included)
         | 
| 476 | 
            -
                  # set appropriate targets for targets of parent
         | 
| 477 | 
            -
                  for targets in included.hash.values
         | 
| 478 | 
            -
                    for target in targets
         | 
| 479 | 
            -
                      target.targets = self
         | 
| 480 | 
            -
                    end
         | 
| 481 | 
            -
                  end
         | 
| 482 | 
            -
                  # look for targets already defined
         | 
| 483 | 
            -
                  duplicates = @hash.keys & included.hash.keys
         | 
| 484 | 
            -
                  error "Included target(s) '#{duplicates.join('\', \'')}' already defined" if
         | 
| 485 | 
            -
                    duplicates.length > 0
         | 
| 486 | 
            -
                  # insert included targets
         | 
| 487 | 
            -
                  for name in included.hash.keys
         | 
| 488 | 
            -
                    @hash[name] = included.hash[name]
         | 
| 489 | 
            -
                  end
         | 
| 490 | 
            -
                end
         | 
| 491 | 
            -
             | 
| 492 341 | 
             
                # Run targets.
         | 
| 493 342 | 
             
                # - targets: list of target names to run.
         | 
| 494 343 | 
             
                def run(targets, dry)
         | 
| @@ -543,380 +392,6 @@ module Bee | |
| 543 392 | 
             
                  return description
         | 
| 544 393 | 
             
                end
         | 
| 545 394 |  | 
| 546 | 
            -
              end
         | 
| 547 | 
            -
              
         | 
| 548 | 
            -
              # Class for a target. It is built from the YAML build file and manages a
         | 
| 549 | 
            -
              # target, in particular, tasks execution.
         | 
| 550 | 
            -
              class Target
         | 
| 551 | 
            -
                
         | 
| 552 | 
            -
                include Bee::Util::BuildErrorMixin
         | 
| 553 | 
            -
                include Bee::Util::HashCheckerMixin
         | 
| 554 | 
            -
             | 
| 555 | 
            -
                # Target key.
         | 
| 556 | 
            -
                KEY = 'target'
         | 
| 557 | 
            -
                # Target entry description.
         | 
| 558 | 
            -
                DESCRIPTION = {
         | 
| 559 | 
            -
                  'target'      => :mandatory,
         | 
| 560 | 
            -
                  'depends'     => :optional,
         | 
| 561 | 
            -
                  'description' => :optional,
         | 
| 562 | 
            -
                  'script'      => :optional}
         | 
| 563 | 
            -
             | 
| 564 | 
            -
                # Targets for build.
         | 
| 565 | 
            -
                attr_accessor :targets
         | 
| 566 | 
            -
                # Name of the target.
         | 
| 567 | 
            -
                attr_reader :name
         | 
| 568 | 
            -
                # Target dependencies.
         | 
| 569 | 
            -
                attr_accessor :depends
         | 
| 570 | 
            -
                # Target description.
         | 
| 571 | 
            -
                attr_accessor :description
         | 
| 572 | 
            -
                # Script that run in the target.
         | 
| 573 | 
            -
                attr_reader :script
         | 
| 574 | 
            -
                
         | 
| 575 | 
            -
                # Constructor.
         | 
| 576 | 
            -
                # - object: object for target, resulting from YAML parsing.
         | 
| 577 | 
            -
                # - targets: build targets.
         | 
| 578 | 
            -
                def initialize(object, targets)
         | 
| 579 | 
            -
                  check_hash(object, Target::DESCRIPTION)
         | 
| 580 | 
            -
                  @targets = targets
         | 
| 581 | 
            -
                  @name = object[Target::KEY]
         | 
| 582 | 
            -
                  error "Target name cannot be 'null'" if @name == nil
         | 
| 583 | 
            -
                  @depends = object['depends']||[]
         | 
| 584 | 
            -
                  @depends = Array(@depends)
         | 
| 585 | 
            -
                  @description = object['description']
         | 
| 586 | 
            -
                  @script = object['script']
         | 
| 587 | 
            -
                  @script = [@script] if @script.kind_of?(String)
         | 
| 588 | 
            -
                  @script = [] if not @script
         | 
| 589 | 
            -
                end
         | 
| 590 | 
            -
                
         | 
| 591 | 
            -
                # Run target.
         | 
| 592 | 
            -
                # - dry: tells if we run in dry mode. Defaults to false.
         | 
| 593 | 
            -
                def run(dry=false)
         | 
| 594 | 
            -
                  current_dir = Dir.pwd
         | 
| 595 | 
            -
                  begin
         | 
| 596 | 
            -
                    for depend in @depends
         | 
| 597 | 
            -
                      @targets.run_target(depend, dry)
         | 
| 598 | 
            -
                    end
         | 
| 599 | 
            -
                    @targets.build.listener.target(self) if 
         | 
| 600 | 
            -
                      @targets.build.listener and @targets.is_last(self)
         | 
| 601 | 
            -
                    run_block(@script, dry)
         | 
| 602 | 
            -
                  ensure
         | 
| 603 | 
            -
                    Dir.chdir(current_dir)
         | 
| 604 | 
            -
                  end
         | 
| 605 | 
            -
                end
         | 
| 606 | 
            -
                
         | 
| 607 | 
            -
                private
         | 
| 608 | 
            -
                
         | 
| 609 | 
            -
                # Run a task.
         | 
| 610 | 
            -
                # - task: the task to run.
         | 
| 611 | 
            -
                # - dry: whether to just print.
         | 
| 612 | 
            -
                def run_task(task, dry=false)
         | 
| 613 | 
            -
                  @targets.build.listener.task(task) if @targets.build.listener
         | 
| 614 | 
            -
                  case task
         | 
| 615 | 
            -
                  when String
         | 
| 616 | 
            -
                    # shell script
         | 
| 617 | 
            -
                    run_shell(task, dry)
         | 
| 618 | 
            -
                  when Hash
         | 
| 619 | 
            -
                    if task.keys.length > 1
         | 
| 620 | 
            -
                      # construct
         | 
| 621 | 
            -
                      run_construct(task, dry)
         | 
| 622 | 
            -
                    else
         | 
| 623 | 
            -
                      if task.key?('rb')
         | 
| 624 | 
            -
                        # ruby script
         | 
| 625 | 
            -
                        script = task['rb']
         | 
| 626 | 
            -
                        run_ruby(script, dry)
         | 
| 627 | 
            -
                      elsif task.key?('sh')
         | 
| 628 | 
            -
                        # shell script
         | 
| 629 | 
            -
                        script = task['sh']
         | 
| 630 | 
            -
                        run_shell(script, dry)
         | 
| 631 | 
            -
                      elsif task.key?('super')
         | 
| 632 | 
            -
                        # call super target
         | 
| 633 | 
            -
                        targets.call_super(self, dry)
         | 
| 634 | 
            -
                      else
         | 
| 635 | 
            -
                        # must be a task
         | 
| 636 | 
            -
                        run_bee_task(task, dry)
         | 
| 637 | 
            -
                      end
         | 
| 638 | 
            -
                    end
         | 
| 639 | 
            -
                  end
         | 
| 640 | 
            -
                end
         | 
| 641 | 
            -
                
         | 
| 642 | 
            -
                # Run a given shell script.
         | 
| 643 | 
            -
                # - script: the scrip to run.
         | 
| 644 | 
            -
                def run_shell(script, dry=false)
         | 
| 645 | 
            -
                  @listener.task(script) if @listener
         | 
| 646 | 
            -
                  return if dry
         | 
| 647 | 
            -
                  evaluated_script = @targets.build.context.evaluate_object(script)
         | 
| 648 | 
            -
                  if evaluated_script != ''
         | 
| 649 | 
            -
                    system(evaluated_script)
         | 
| 650 | 
            -
                    error "Script exited with value #{$?}" if $? != 0
         | 
| 651 | 
            -
                  end
         | 
| 652 | 
            -
                end
         | 
| 653 | 
            -
                
         | 
| 654 | 
            -
                # Run a given shell script.
         | 
| 655 | 
            -
                # - script: the scrip to run.
         | 
| 656 | 
            -
                # - dry: tells if we run in dry mode.
         | 
| 657 | 
            -
                def run_ruby(script, dry=false)
         | 
| 658 | 
            -
                  @listener.task(script) if @listener
         | 
| 659 | 
            -
                  return if dry
         | 
| 660 | 
            -
                  begin
         | 
| 661 | 
            -
                    @targets.build.context.evaluate_script(script)
         | 
| 662 | 
            -
                  rescue Exception
         | 
| 663 | 
            -
                    error "Error running Ruby script: #{$!}"
         | 
| 664 | 
            -
                  end
         | 
| 665 | 
            -
                end
         | 
| 666 | 
            -
                
         | 
| 667 | 
            -
                # Run a given bee task.
         | 
| 668 | 
            -
                # - task: task to run as a Hash.
         | 
| 669 | 
            -
                def run_bee_task(task, dry=false)
         | 
| 670 | 
            -
                  @listener.task(task) if @listener
         | 
| 671 | 
            -
                  return if dry
         | 
| 672 | 
            -
                  @targets.build.package_manager.run_task(task)
         | 
| 673 | 
            -
                end
         | 
| 674 | 
            -
             | 
| 675 | 
            -
                # Run a given construct.
         | 
| 676 | 
            -
                # - construct: construct to run as a Hash.
         | 
| 677 | 
            -
                def run_construct(construct, dry=false)
         | 
| 678 | 
            -
                  @listener.task(construct) if @listener
         | 
| 679 | 
            -
                  return if dry
         | 
| 680 | 
            -
                  # if construct
         | 
| 681 | 
            -
                  if construct.keys.include?('if')
         | 
| 682 | 
            -
                    construct_if(construct, dry)
         | 
| 683 | 
            -
                  # while construct
         | 
| 684 | 
            -
                  elsif construct.keys.include?('while')
         | 
| 685 | 
            -
                    construct_while(construct, dry)
         | 
| 686 | 
            -
                  # for construct
         | 
| 687 | 
            -
                  elsif construct.keys.include?('for')
         | 
| 688 | 
            -
                    construct_for(construct, dry)
         | 
| 689 | 
            -
                  # try construct
         | 
| 690 | 
            -
                  elsif construct.keys.include?('try')
         | 
| 691 | 
            -
                    construct_try(construct, dry)
         | 
| 692 | 
            -
                  else
         | 
| 693 | 
            -
                    error "Unknown construct '#{construct.keys.join('-')}'"
         | 
| 694 | 
            -
                  end
         | 
| 695 | 
            -
                end
         | 
| 696 | 
            -
             | 
| 697 | 
            -
                # Run if construct.
         | 
| 698 | 
            -
                # - task: the construct as a hash.
         | 
| 699 | 
            -
                # - dry: tells if we run in dry mode.
         | 
| 700 | 
            -
                def construct_if(task, dry)
         | 
| 701 | 
            -
                  # test entries
         | 
| 702 | 
            -
                  error "If-then-else construct must include 'then' entry" if
         | 
| 703 | 
            -
                    not task.keys.include?('then')
         | 
| 704 | 
            -
                  unknown_keys = task.keys - ['if', 'then', 'else']
         | 
| 705 | 
            -
                  error "If-then-else construct may only include 'if', 'then' and 'else' entries" if
         | 
| 706 | 
            -
                    unknown_keys.length > 0
         | 
| 707 | 
            -
                  error "If entry in if-then-else construct must be a string" if
         | 
| 708 | 
            -
                    not task['if'].kind_of?(String)
         | 
| 709 | 
            -
                  error "Then entry in if-then-else construct must be a list" if
         | 
| 710 | 
            -
                    not task['then'].kind_of?(Array)
         | 
| 711 | 
            -
                  error "Else entry in if-then-else construct must be a list" if
         | 
| 712 | 
            -
                    task['else'] and not task['else'].kind_of?(Array)
         | 
| 713 | 
            -
                  # evaluate condition in the build context
         | 
| 714 | 
            -
                  if evaluate(task['if'])
         | 
| 715 | 
            -
                    run_block(task['then'], dry)
         | 
| 716 | 
            -
                  else
         | 
| 717 | 
            -
                    run_block(task['else'], dry) if task['else']
         | 
| 718 | 
            -
                  end
         | 
| 719 | 
            -
                end
         | 
| 720 | 
            -
             | 
| 721 | 
            -
                # Run while construct.
         | 
| 722 | 
            -
                # - task: the construct as a hash.
         | 
| 723 | 
            -
                # - dry: tells if we run in dry mode.
         | 
| 724 | 
            -
                def construct_while(task, dry)
         | 
| 725 | 
            -
                  # test entries
         | 
| 726 | 
            -
                  error "While-do construct must include 'do' entry" if
         | 
| 727 | 
            -
                    not task.keys.include?('do')
         | 
| 728 | 
            -
                  unknown_keys = task.keys - ['while', 'do']
         | 
| 729 | 
            -
                  error "While-do construct may only include 'while' and 'do' entries" if
         | 
| 730 | 
            -
                    unknown_keys.length > 0
         | 
| 731 | 
            -
                  error "While entry in while-do construct must be a string" if
         | 
| 732 | 
            -
                    not task['while'].kind_of?(String)
         | 
| 733 | 
            -
                  error "Do entry in while-do construct must be a list" if
         | 
| 734 | 
            -
                    not task['do'].kind_of?(Array)
         | 
| 735 | 
            -
                  # evaluate condition in the build context
         | 
| 736 | 
            -
                  while evaluate(task['while'])
         | 
| 737 | 
            -
                    run_block(task['do'], dry)
         | 
| 738 | 
            -
                  end
         | 
| 739 | 
            -
                end
         | 
| 740 | 
            -
             | 
| 741 | 
            -
                # Run for construct.
         | 
| 742 | 
            -
                # - task: the construct as a hash.
         | 
| 743 | 
            -
                # - dry: tells if we run in dry mode.
         | 
| 744 | 
            -
                def construct_for(task, dry)
         | 
| 745 | 
            -
                  # test entries
         | 
| 746 | 
            -
                  error "For-in-do construct must include 'in' and 'do' entries" if
         | 
| 747 | 
            -
                    not task.keys.include?('in') or not task.keys.include?('do')
         | 
| 748 | 
            -
                  unknown_keys = task.keys - ['for', 'in', 'do']
         | 
| 749 | 
            -
                  error "For-in-do construct may only include 'for', 'in' and 'do' entries" if
         | 
| 750 | 
            -
                    unknown_keys.length > 0
         | 
| 751 | 
            -
                  error "For entry in for-in-do construct must be a string" if
         | 
| 752 | 
            -
                    not task['for'].kind_of?(String)
         | 
| 753 | 
            -
                  error "In entry in for-in-do construct must be a list or a string" if
         | 
| 754 | 
            -
                    not task['in'].kind_of?(Enumerable) and not task['in'].kind_of?(String)
         | 
| 755 | 
            -
                  error "Do entry in for-in-do construct must be a list" if
         | 
| 756 | 
            -
                    not task['do'].kind_of?(Array)
         | 
| 757 | 
            -
                  # iterate over list
         | 
| 758 | 
            -
                  if task['in'].kind_of?(String)
         | 
| 759 | 
            -
                    enumerable = evaluate(@targets.build.context.
         | 
| 760 | 
            -
                                          evaluate_object(task['in']))
         | 
| 761 | 
            -
                  else
         | 
| 762 | 
            -
                    enumerable = task['in']
         | 
| 763 | 
            -
                  end
         | 
| 764 | 
            -
                  for element in enumerable
         | 
| 765 | 
            -
                    begin
         | 
| 766 | 
            -
                      @targets.build.context.set_property(task['for'], element)
         | 
| 767 | 
            -
                    rescue
         | 
| 768 | 
            -
                      error "Error setting property '#{task['for']}'"
         | 
| 769 | 
            -
                    end
         | 
| 770 | 
            -
                    run_block(task['do'], dry)
         | 
| 771 | 
            -
                  end
         | 
| 772 | 
            -
                end
         | 
| 773 | 
            -
             | 
| 774 | 
            -
                # Run try-catch construct.
         | 
| 775 | 
            -
                # - task: the construct as a hash.
         | 
| 776 | 
            -
                # - dry: tells if we run in dry mode.
         | 
| 777 | 
            -
                def construct_try(task, dry)
         | 
| 778 | 
            -
                  # test entries
         | 
| 779 | 
            -
                  error "Try-catch construct must include 'catch' entry" if
         | 
| 780 | 
            -
                    not task.keys.include?('catch')
         | 
| 781 | 
            -
                  unknown_keys = task.keys - ['try', 'catch']
         | 
| 782 | 
            -
                  error "Try-catch construct may only include 'try' and 'catch' entries" if
         | 
| 783 | 
            -
                    unknown_keys.length > 0
         | 
| 784 | 
            -
                  error "Try entry in try-catch construct must be a list" if
         | 
| 785 | 
            -
                    not task['try'].kind_of?(Array)
         | 
| 786 | 
            -
                  error "Catch entry in try-catch construct must be a list" if
         | 
| 787 | 
            -
                    not task['catch'].kind_of?(Array)
         | 
| 788 | 
            -
                  # try and catch errors
         | 
| 789 | 
            -
                  begin
         | 
| 790 | 
            -
                    run_block(task['try'], dry)
         | 
| 791 | 
            -
                  rescue
         | 
| 792 | 
            -
                    @targets.build.listener.recover if @targets.build.listener
         | 
| 793 | 
            -
                    run_block(task['catch'], dry)
         | 
| 794 | 
            -
                  end
         | 
| 795 | 
            -
                end
         | 
| 796 | 
            -
             | 
| 797 | 
            -
                # Run a block, that is a list of tasks.
         | 
| 798 | 
            -
                # - block: the block to run as a list of tasks.
         | 
| 799 | 
            -
                # - dry: tells if we run in dry mode.
         | 
| 800 | 
            -
                def run_block(block, dry)
         | 
| 801 | 
            -
                  for task in block
         | 
| 802 | 
            -
                    run_task(task, dry)
         | 
| 803 | 
            -
                  end   
         | 
| 804 | 
            -
                end
         | 
| 805 | 
            -
             | 
| 806 | 
            -
                # Evaluate a given expression and raise a BuildError if an error happens.
         | 
| 807 | 
            -
                def evaluate(expression)
         | 
| 808 | 
            -
                  begin
         | 
| 809 | 
            -
                    return @targets.build.context.evaluate_script(expression)
         | 
| 810 | 
            -
                  rescue
         | 
| 811 | 
            -
                    error "Error evaluating expression: #{$!}"
         | 
| 812 | 
            -
                  end
         | 
| 813 | 
            -
                end
         | 
| 814 | 
            -
             | 
| 815 | 
            -
              end
         | 
| 816 | 
            -
              
         | 
| 817 | 
            -
              # Class for Ruby scripts context. All embedded Ruby scripts run in this
         | 
| 818 | 
            -
              # context where build properties are defined as Ruby variables.
         | 
| 819 | 
            -
              class Context
         | 
| 820 | 
            -
                
         | 
| 821 | 
            -
                include Bee::Util::BuildErrorMixin
         | 
| 822 | 
            -
                
         | 
| 823 | 
            -
                # The binding of this context.
         | 
| 824 | 
            -
                attr_reader :context_binding
         | 
| 825 | 
            -
                
         | 
| 826 | 
            -
                # Constructor.
         | 
| 827 | 
            -
                def initialize
         | 
| 828 | 
            -
                  @context_binding = get_binding
         | 
| 829 | 
            -
                end
         | 
| 830 | 
            -
                
         | 
| 831 | 
            -
                # Set a given property in context.
         | 
| 832 | 
            -
                # - name: the property name.
         | 
| 833 | 
            -
                # - value: the property value.
         | 
| 834 | 
            -
                # - override: tells if we can overwrite an existing value.
         | 
| 835 | 
            -
                def set_property(name, value, overwrite=true)
         | 
| 836 | 
            -
                  error "Property '#{name}' was already defined" if 
         | 
| 837 | 
            -
                    !overwrite and properties.include?(name.to_s)
         | 
| 838 | 
            -
                  begin
         | 
| 839 | 
            -
                    eval("#{name} = #{value.inspect}", @context_binding)
         | 
| 840 | 
            -
                  rescue Exception
         | 
| 841 | 
            -
                    error "Error setting property '#{name} = #{value.inspect}': #{$!}"
         | 
| 842 | 
            -
                  end
         | 
| 843 | 
            -
                end
         | 
| 844 | 
            -
                
         | 
| 845 | 
            -
                # Get a given property in context.
         | 
| 846 | 
            -
                # - name: the property name.
         | 
| 847 | 
            -
                # - strict: raise an error if given property was not set.
         | 
| 848 | 
            -
                def get_property(name, strict=false)
         | 
| 849 | 
            -
                  error "Property '#{name}' was not set" if 
         | 
| 850 | 
            -
                    strict and !properties.include?(name.to_s)
         | 
| 851 | 
            -
                  begin
         | 
| 852 | 
            -
                    eval("#{name}", @context_binding)
         | 
| 853 | 
            -
                  rescue NameError
         | 
| 854 | 
            -
                    error "Property '#{name}' was not set"
         | 
| 855 | 
            -
                  rescue Exception
         | 
| 856 | 
            -
                    error "Error getting property '#{name}': #{$!}"
         | 
| 857 | 
            -
                  end
         | 
| 858 | 
            -
                end
         | 
| 859 | 
            -
                
         | 
| 860 | 
            -
                # Return list of properties (as local variables of binding).
         | 
| 861 | 
            -
                def properties
         | 
| 862 | 
            -
                  return eval('local_variables', @context_binding).map{ |var| var.to_s }
         | 
| 863 | 
            -
                end
         | 
| 864 | 
            -
                
         | 
| 865 | 
            -
                # Evaluate a script in context.
         | 
| 866 | 
            -
                # - script: source of the script to evaluate.
         | 
| 867 | 
            -
                def evaluate_script(script)
         | 
| 868 | 
            -
                  eval(script, @context_binding)
         | 
| 869 | 
            -
                end
         | 
| 870 | 
            -
                
         | 
| 871 | 
            -
                # Process a given object, replacing properties references with their
         | 
| 872 | 
            -
                # string value, symbol with their raw value. Property references have
         | 
| 873 | 
            -
                # same form than variable references in ruby strings: '#{variable}'
         | 
| 874 | 
            -
                # will be replaced with variable string value.
         | 
| 875 | 
            -
                # - object: object to process.
         | 
| 876 | 
            -
                def evaluate_object(object)
         | 
| 877 | 
            -
                  case object
         | 
| 878 | 
            -
                  when NilClass
         | 
| 879 | 
            -
                    # nil: return nil
         | 
| 880 | 
            -
                    return nil
         | 
| 881 | 
            -
                  when String
         | 
| 882 | 
            -
                    # string: replace embedded Ruby expressions
         | 
| 883 | 
            -
                    object = object.gsub(/#\{.+?\}/) do |match|
         | 
| 884 | 
            -
                      expression = match[2..-2]
         | 
| 885 | 
            -
                      begin
         | 
| 886 | 
            -
                        value = evaluate_script(expression)
         | 
| 887 | 
            -
                      rescue
         | 
| 888 | 
            -
                        error "Error evaluating expression '#{expression}': #{$!}"
         | 
| 889 | 
            -
                      end
         | 
| 890 | 
            -
                      value
         | 
| 891 | 
            -
                    end
         | 
| 892 | 
            -
                    return object 
         | 
| 893 | 
            -
                  when Symbol
         | 
| 894 | 
            -
                    # symbol: return property object
         | 
| 895 | 
            -
                    property = object.to_s
         | 
| 896 | 
            -
                    value = get_property(property, true)
         | 
| 897 | 
            -
                    return evaluate_object(value)
         | 
| 898 | 
            -
                  when Array
         | 
| 899 | 
            -
                    # array: evaluate each element
         | 
| 900 | 
            -
                    return object.collect { |element| evaluate_object(element) }
         | 
| 901 | 
            -
                  when Hash
         | 
| 902 | 
            -
                    # hash: evaluate all keys and values
         | 
| 903 | 
            -
                    evaluated = {}
         | 
| 904 | 
            -
                    object.each_pair do |key, value| 
         | 
| 905 | 
            -
                      evaluated[evaluate_object(key)] = evaluate_object(value)
         | 
| 906 | 
            -
                    end
         | 
| 907 | 
            -
                    return evaluated
         | 
| 908 | 
            -
                  else
         | 
| 909 | 
            -
                    return object
         | 
| 910 | 
            -
                  end
         | 
| 911 | 
            -
                end
         | 
| 912 | 
            -
                
         | 
| 913 | 
            -
                private
         | 
| 914 | 
            -
                
         | 
| 915 | 
            -
                # Get a binding as script context.
         | 
| 916 | 
            -
                def get_binding
         | 
| 917 | 
            -
                  return binding
         | 
| 918 | 
            -
                end
         | 
| 919 | 
            -
                
         | 
| 920 | 
            -
              end
         | 
| 395 | 
            +
              end  
         | 
| 921 396 |  | 
| 922 397 | 
             
            end
         |