class Configuration
A configuration represents a mapping between package/dependency names and actual source locations. Usually, there is only one configuration, but in some cases it is useful to have more than one, e.g. one for local development using local source code, one for continuous integration, and one for deployment.
Definitions
def initialize(context, package, name, packages = [], **options)
Initialize a new configuration.
Signature
-
parameter
contextContext The project context.
-
parameter
packagePackage The package.
-
parameter
nameString The configuration name.
-
parameter
packagesArray The list of packages.
Implementation
def initialize(context, package, name, packages = [], **options)
super context, package, name
@options = DEFAULT_OPTIONS.merge(options)
@packages = Build::Dependency::Set.new(packages)
@imports = Build::Dependency::Set.new
@visibility = :private
# A list of named targets for specific purposes:
@targets = Hash.new{|hash,key| hash[key] = Array.new}
end
def freeze
Make the configuration immutable to prevent modification after targets and packages are resolved.
Implementation
def freeze
return self if frozen?
@options.freeze
@packages.freeze
@imports.freeze
@visibility.freeze
@targets.default = [].freeze
@targets.freeze
super
end
def environment
Create an environment for this configuration.
Signature
-
returns
Build::Environment The build environment.
Implementation
def environment
configuration = self
Build::Environment.new(name: self.name) do
default build_path configuration.build_path
default platforms_path configuration.build_path
end
end
attr :visibility
Controls how the configuration is exposed in the context.
def public?
Whether this configuration is publicly accessible (not hidden from listings).
Signature
-
returns
Boolean True if public.
Implementation
def public?
@visibility == :public
end
def public!
Mark this configuration as publicly visible in listings and help output.
Implementation
def public!
@visibility = :public
end
attr :targets
A table of named targets for specific purposes.
attr :options
Options used to bind packages to this configuration.
attr :packages
A list of packages which are required by this configuration.
attr :imports
A list of other configurations to include when materialising the list of packages.
def require(name, **options)
Specifies that this configuration depends on an external package of some sort.
Implementation
def require(name, **options)
options = @options.merge(options)
@packages << Package.new(packages_path + name.to_s, name, options)
if options[:import] == true
import(name, false)
elsif String === options[:import]
import(options[:import])
end
end
def import(name, explicit = true)
Specifies that this package will import additional configuration records from another definition.
Implementation
def import(name, explicit = true)
@imports << Import.new(name, explicit, @options.dup)
end
def group
Create a group for configuration options which will be only be active within the group block.
Implementation
def group
options = @options.dup
yield
@options = options
end
def []=(key, value)
Set a configuration option.
Implementation
def []= key, value
@options[key] = value
end
def [](key)
Access configuration-specific settings that control build behavior and environment variables.
Implementation
def [] key
@options[key]
end
def packages_path
The path where packages will be located when fetched.
Implementation
def packages_path
context.root + "teapot/packages/#{name}"
end
def build_path
The path where built products will be placed.
Implementation
def build_path
context.root + "teapot/build/#{name}"
end
def lock_path
Get the path to the lock file.
Signature
-
returns
Build::Files::Path The lock file path.
Implementation
def lock_path
context.root + "#{@name}-lock.yml"
end
def lock_store
Get the lock store for persisting state.
Signature
-
returns
YAML::Store The lock store.
Implementation
def lock_store
::YAML::Store.new(lock_path.to_s)
end
def to_s
Signature
-
returns
String The string representation.
Implementation
def to_s
"#<#{self.class} #{@name.dump} visibility=#{@visibility}>"
end
def traverse(configurations, imported = Build::Dependency::Set.new, &block)
Process all import directives and return a new configuration based on the current configuration. Import directives bring packages and other import directives from the specififed configuration definition.
Implementation
def traverse(configurations, imported = Build::Dependency::Set.new, &block)
yield self # Whatever happens here, should ensure that...
@imports.each do |import|
# So we don't get into some crazy cycle:
next if imported.include?(import)
# Mark it as being imported:
imported << import
# ... by here, the configuration is available:
if configuration = configurations[import.name]
configuration.traverse(configurations, imported, &block)
end
end
end
def merge(configuration)
Merge an external configuration into this configuration. We won't override already defined packages.
Implementation
def merge(configuration)
configuration.packages.each do |package|
# The top level configuration will override packages that are defined by imported configurations. This is desirable behaviour, as it allows us to flatten the configuration but provide overrides if required.
unless @packages.include? package
package = Package.new(packages_path + package.name, package.name, @options.merge(package.options))
@packages << package
yield package
end
end
configuration.imports.each do |import|
unless @imports.include? import
@imports << Import.new(import.name, import.explicit, @options.merge(import.options))
end
end
configuration.targets.each do |key, value|
@targets[key] += value
end
return self
end