Class: Build::Environment

Inherits:
Object
  • Object
show all
Defined in:
lib/build/environment/base.rb,
lib/build/environment/system.rb,
lib/build/environment/flatten.rb,
lib/build/environment/version.rb,
lib/build/environment/evaluator.rb,
lib/build/environment/constructor.rb

Overview

Represents a layered build environment, implemented as a linked list of hashes. It is primarily used for organising build configurations across a wide range of different sub-systems, e.g. platform configuration, target configuration, local project configuration, etc.

Defined Under Namespace

Modules: System Classes: Constructor, Default, Define, Evaluator, Replace

Constant Summary collapse

VERSION =
"1.13.1"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil, values = nil, name: nil, &block) ⇒ Environment

Initialize a new environment with an optional parent, initial values, name, and update block.



15
16
17
18
19
20
21
# File 'lib/build/environment/base.rb', line 15

def initialize(parent = nil, values = nil, name: nil, &block)
	@parent = parent
	@values = (values || {}).to_h
	@update = block
	
	@name = name
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



51
52
53
# File 'lib/build/environment/base.rb', line 51

def name
  @name
end

#parentObject (readonly)

Returns the value of attribute parent.



48
49
50
# File 'lib/build/environment/base.rb', line 48

def parent
  @parent
end

#updateObject (readonly)

Returns the value of attribute update.



50
51
52
# File 'lib/build/environment/base.rb', line 50

def update
  @update
end

#valuesObject (readonly)

Returns the value of attribute values.



49
50
51
# File 'lib/build/environment/base.rb', line 49

def values
  @values
end

Class Method Details

.combine(*environments) ⇒ Object

Flatten the list of environments.



159
160
161
162
163
164
165
166
167
168
169
# File 'lib/build/environment/constructor.rb', line 159

def self.combine(*environments)
	ordered = []
	
	environments.each do |environment|
		environment.flatten_to_array(ordered)
	end
	
	ordered.inject(nil) do |parent, environment|
		environment.dup(parent: parent)
	end
end

.system_environment(env = ENV, **options) ⇒ Object

Construct an environment from a given system environment:



59
60
61
# File 'lib/build/environment/system.rb', line 59

def self.system_environment(env = ENV, **options)
	self.new(nil, Hash[env.map{|key, value| [key.downcase.to_sym, value]}], **options)
end

Instance Method Details

#==(other) ⇒ Object

Compare this environment with another for equality.



26
27
28
29
30
31
32
33
# File 'lib/build/environment/base.rb', line 26

def == other
	self.equal?(other) or
		self.class == other.class and
		@parent == other.parent and
		@values == other.values and
		@update == other.update and
		@name == other.name
end

#[](key) ⇒ Object

Retrieve the value for a key, returning nil if not found.



125
126
127
128
129
# File 'lib/build/environment/base.rb', line 125

def [](key)
	environment = lookup(key)
	
	environment ? environment.values[key] : nil
end

#[]=(key, value) ⇒ Object

Set the value for a key in the current environment layer.



134
135
136
# File 'lib/build/environment/base.rb', line 134

def []=(key, value)
	@values[key] = value
end

#checksum(digester: Digest::SHA1.new) ⇒ Object

Compute a hex digest checksum of the environment’s content.



61
62
63
64
65
# File 'lib/build/environment/flatten.rb', line 61

def checksum(digester: Digest::SHA1.new)
	checksum_recursively(digester)
	
	return digester.hexdigest
end

#construct!(proxy, *arguments, &block) ⇒ Object

Apply a block to this environment using a Constructor proxy, then return the environment.



31
32
33
34
35
36
37
38
39
# File 'lib/build/environment/constructor.rb', line 31

def construct!(proxy, *arguments, &block)
	constructor = Constructor.new(self, proxy)
	
	if block_given?
		constructor.instance_exec(*arguments, &block)
	end
	
	return self
end

#definedObject

Return all key-value pairs in the current layer whose values are Define instances.



54
55
56
# File 'lib/build/environment/flatten.rb', line 54

def defined
	@values.select{|name,value| Define === value}
end

#dup(parent: @parent, values: @values, update: @update, name: @name) ⇒ Object

Create a duplicate of this environment, optionally overriding parent, values, update, or name.



59
60
61
# File 'lib/build/environment/base.rb', line 59

def dup(parent: @parent, values: @values, update: @update, name: @name)
	self.class.new(parent, values.dup, name: name, &update)
end

#eql?(other) ⇒ Boolean

Check equality using the ‘==` operator.

Returns:

  • (Boolean)


38
39
40
# File 'lib/build/environment/base.rb', line 38

def eql?(other)
	self == other
end

#evaluate(**options) ⇒ Object

Flatten and evaluate all values, returning a new single-layer environment.



35
36
37
# File 'lib/build/environment/flatten.rb', line 35

def evaluate(**options)
	self.class.new(nil, self.to_h, **options)
end

#evaluatorObject

Create a new Evaluator for this environment.



28
29
30
# File 'lib/build/environment/flatten.rb', line 28

def evaluator
	Evaluator.new(self)
end

#exportObject

Make a hash appropriate for a process environment



64
65
66
# File 'lib/build/environment/system.rb', line 64

def export
	System.convert_to_shell(self)
end

#fetch(key, *default, &block) ⇒ Object

Retrieve the value for a key, with support for a default value or block.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/build/environment/base.rb', line 110

def fetch(key, *default, &block)
	if environment = lookup(key)
		return environment.values[key]
	elsif block_given?
		yield(key, *default)
	elsif !default.empty?
		return default.first
	else
		raise KeyError.new("Environment missing #{key}")
	end
end

#flatten(**options) ⇒ Object

Merge all environment layers into a single-level environment without evaluating values.



42
43
44
45
46
47
48
49
50
# File 'lib/build/environment/flatten.rb', line 42

def flatten(**options)
	hash = {}
	
	flatten_to_hash(hash)
	
	options[:name] ||= self.name
	
	return self.class.new(nil, hash, **options)
end

#flatten_to_array(array) ⇒ Object

Recursively collect this environment and its ancestors into an array, parent first.



190
191
192
193
194
195
196
# File 'lib/build/environment/constructor.rb', line 190

def flatten_to_array(array)
	if @parent
		@parent.flatten_to_array(array)
	end
	
	array << self
end

#freezeObject

Freeze this environment and its entire parent chain, making it immutable.



65
66
67
68
69
70
71
72
73
# File 'lib/build/environment/base.rb', line 65

def freeze
	return self if frozen?
	
	@parent.freeze
	@values.freeze
	@update.freeze
	
	super
end

#hashObject

Compute a hash value for this environment based on its parent, values, update, and name.



44
45
46
# File 'lib/build/environment/base.rb', line 44

def hash
	@parent.hash ^ @values.hash ^ @update.hash ^ @name.hash
end

#include?(key) ⇒ Boolean Also known as: key?

Check whether the key exists in this environment or any parent layer.

Returns:

  • (Boolean)


89
90
91
92
93
94
95
# File 'lib/build/environment/base.rb', line 89

def include?(key)
	if @values.include?(key)
		true
	elsif @parent
		@parent.include?(key)
	end
end

#lookup(name) ⇒ Object

Find the environment layer that contains the given key.



78
79
80
81
82
83
84
# File 'lib/build/environment/base.rb', line 78

def lookup(name)
	if @values.include? name
		self
	elsif @parent
		@parent.lookup(name)
	end
end

#merge(**options, &block) ⇒ Object

Create a new child environment inheriting from this one, with optional keyword options and block.



175
176
177
# File 'lib/build/environment/constructor.rb', line 175

def merge(**options, &block)
	self.class.new(self, **options, &block)
end

#sizeObject

Count the total number of key-value pairs across all layers.



101
102
103
# File 'lib/build/environment/base.rb', line 101

def size
	@values.size + (@parent ? @parent.size : 0)
end

#to_aObject

Convert the hierarchy of environments to an array where the parent comes before the child.



180
181
182
183
184
185
186
# File 'lib/build/environment/constructor.rb', line 180

def to_a
	flat = []
	
	flatten_to_array(flat)
	
	return flat
end

#to_hObject

Evaluate all environment layers into a single flat hash with all values resolved.



13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/build/environment/flatten.rb', line 13

def to_h
	hash = {}
	
	# Flatten this chain of environments:
	flatten_to_hash(hash)
	
	# Evaluate all items to their respective object value:
	evaluator = Evaluator.new(hash)
	
	# Evaluate all the individual environment values so that they are flat:
	Hash[hash.map{|key, value| [key, evaluator.object_value(value)]}]
end

#to_sObject

Return a human-readable string representation of this environment.



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/build/environment/base.rb', line 140

def to_s
	buffer = String.new("\#<#{self.class} ")
	
	if @name
		buffer << @name.inspect << " "
	end
	
	if @update
		buffer << @update.source_location.join(":") << " "
	end
	
	buffer << @values.to_s << ">"
	
	return buffer
end