Class: Teapot::Configuration

Inherits:
Definition show all
Defined in:
lib/teapot/configuration.rb

Overview

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.

Defined Under Namespace

Classes: Import

Constant Summary collapse

DEFAULT_OPTIONS =
{
	:import => true
}.freeze

Instance Attribute Summary collapse

Attributes inherited from Definition

#context, #description, #name, #package

Instance Method Summary collapse

Methods inherited from Definition

#inspect, #path

Constructor Details

#initialize(context, package, name, packages = [], **options) ⇒ Configuration

Initialize a new configuration.



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/teapot/configuration.rb', line 28

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

Instance Attribute Details

#importsObject (readonly)

A list of other configurations to include when materialising the list of packages.



92
93
94
# File 'lib/teapot/configuration.rb', line 92

def imports
  @imports
end

#optionsObject (readonly)

Options used to bind packages to this configuration.



86
87
88
# File 'lib/teapot/configuration.rb', line 86

def options
  @options
end

#packagesObject (readonly)

A list of packages which are required by this configuration.



89
90
91
# File 'lib/teapot/configuration.rb', line 89

def packages
  @packages
end

#targetsObject (readonly)

A table of named targets for specific purposes.



83
84
85
# File 'lib/teapot/configuration.rb', line 83

def targets
  @targets
end

#visibilityObject (readonly)

Controls how the configuration is exposed in the context.



69
70
71
# File 'lib/teapot/configuration.rb', line 69

def visibility
  @visibility
end

Instance Method Details

#[](key) ⇒ Object

Access configuration-specific settings that control build behavior and environment variables.



127
128
129
# File 'lib/teapot/configuration.rb', line 127

def [] key
	@options[key]
end

#[]=(key, value) ⇒ Object

Set a configuration option.



122
123
124
# File 'lib/teapot/configuration.rb', line 122

def []= key, value
	@options[key] = value
end

#build_pathObject Also known as: platforms_path

The path where built products will be placed.



137
138
139
# File 'lib/teapot/configuration.rb', line 137

def build_path
	context.root + "teapot/build/#{name}"
end

#environmentObject

Create an environment for this configuration.



59
60
61
62
63
64
65
66
# File 'lib/teapot/configuration.rb', line 59

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

#freezeObject

Make the configuration immutable to prevent modification after targets and packages are resolved.



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/teapot/configuration.rb', line 43

def freeze
	return self if frozen?
	
	@options.freeze
	@packages.freeze
	@imports.freeze
	@visibility.freeze
	
	@targets.default = [].freeze
	@targets.freeze
	
	super
end

#groupObject

Create a group for configuration options which will be only be active within the group block.



113
114
115
116
117
118
119
# File 'lib/teapot/configuration.rb', line 113

def group
	options = @options.dup
	
	yield
	
	@options = options
end

#import(name, explicit = true) ⇒ Object

Specifies that this package will import additional configuration records from another definition.



108
109
110
# File 'lib/teapot/configuration.rb', line 108

def import(name, explicit = true)
	@imports << Import.new(name, explicit, @options.dup)
end

#lock_pathObject

Get the path to the lock file.



145
146
147
# File 'lib/teapot/configuration.rb', line 145

def lock_path
	context.root + "#{@name}-lock.yml"
end

#lock_storeObject

Get the lock store for persisting state.



151
152
153
# File 'lib/teapot/configuration.rb', line 151

def lock_store
	::YAML::Store.new(lock_path.to_s)
end

#merge(configuration) ⇒ Object

Merge an external configuration into this configuration. We won’t override already defined packages.



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/teapot/configuration.rb', line 179

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

#packages_pathObject

The path where packages will be located when fetched.



132
133
134
# File 'lib/teapot/configuration.rb', line 132

def packages_path
	context.root + "teapot/packages/#{name}"
end

#public!Object

Mark this configuration as publicly visible in listings and help output.



78
79
80
# File 'lib/teapot/configuration.rb', line 78

def public!
	@visibility = :public
end

#public?Boolean

Whether this configuration is publicly accessible (not hidden from listings).

Returns:

  • (Boolean)


73
74
75
# File 'lib/teapot/configuration.rb', line 73

def public?
	@visibility == :public
end

#require(name, **options) ⇒ Object

Specifies that this configuration depends on an external package of some sort.



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/teapot/configuration.rb', line 95

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

#to_sObject



156
157
158
# File 'lib/teapot/configuration.rb', line 156

def to_s
	"#<#{self.class} #{@name.dump} visibility=#{@visibility}>"
end

#traverse(configurations, imported = Build::Dependency::Set.new) {|_self| ... } ⇒ Object

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.

Yields:

  • (_self)

Yield Parameters:



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/teapot/configuration.rb', line 161

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