build-graph 2.1.1 → 2.2.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/build/graph/edge.rb +9 -20
- data/lib/build/graph/node.rb +15 -21
- data/lib/build/graph/task.rb +20 -20
- data/lib/build/graph/version.rb +7 -20
- data/lib/build/graph/walker.rb +44 -41
- data/lib/build/graph.rb +8 -27
- data/license.md +21 -0
- data/readme.md +37 -0
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +39 -142
- metadata.gz.sig +0 -0
- data/spec/build/graph/build_test.rb +0 -85
- data/spec/build/graph/edge_spec.rb +0 -39
- data/spec/build/graph/graph_spec.rb +0 -172
- data/spec/build/graph/inherit_spec.rb +0 -51
- data/spec/build/graph/listing.txt +0 -8
- data/spec/build/graph/node_spec.rb +0 -80
- data/spec/build/graph/process_graph.rb +0 -98
- data/spec/build/graph/program/Benchmark.cpp +0 -72
- data/spec/build/graph/program/Benchmark.cpp.d +0 -1
- data/spec/build/graph/program/Benchmark.cpp.o +0 -0
- data/spec/build/graph/program/Benchmark.h +0 -65
- data/spec/build/graph/program/DictionarySort.h +0 -270
- data/spec/build/graph/program/ParallelMergeSort.h +0 -278
- data/spec/build/graph/program/dictionary-sort +0 -0
- data/spec/build/graph/program/main.cpp +0 -131
- data/spec/build/graph/program/main.cpp.d +0 -1
- data/spec/build/graph/program/main.cpp.o +0 -0
- data/spec/build/graph/task_spec.rb +0 -69
- data/spec/build/graph/walker_spec.rb +0 -125
- data/spec/spec_helper.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1db7b0de55419c77b5c17f17e93f4e62304a93872265545cce248c58d78e1c8
|
|
4
|
+
data.tar.gz: 989d5bae8d7eb3b324648cf64eecdd999c8f5104a849bd5715cab8cd7ad26079
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 93c3f170fb2ad8da49f56d30248e8403e504f8fef5e562f19cd3280cfa60471cc09b0dc440a6d7f3c63fef7c8da25e1da5e6faacce446c91cbb6e3d9ced740fb
|
|
7
|
+
data.tar.gz: '0382b9651118034b7aebdfcfa7a0599adf430172ac3ec0243905728b2a2326ca621c44011d7d5a071308e4c1e3bdb83977292fd6a3f9ef2c0b141488edf27329'
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/lib/build/graph/edge.rb
CHANGED
|
@@ -1,29 +1,16 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
# furnished to do so, subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
|
11
|
-
# all copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
# THE SOFTWARE.
|
|
1
|
+
# frozen_string_literal: true
|
|
20
2
|
|
|
21
|
-
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require "fiber"
|
|
22
7
|
|
|
23
8
|
module Build
|
|
24
9
|
module Graph
|
|
25
10
|
# Represents a set of inputs to a graph node.
|
|
26
11
|
class Edge
|
|
12
|
+
# Create a new edge, optionally pre-populated with a number of pending traversals.
|
|
13
|
+
# @parameter count [Integer] the initial number of pending traversals.
|
|
27
14
|
def initialize(count = 0)
|
|
28
15
|
@fiber = Fiber.current
|
|
29
16
|
|
|
@@ -48,10 +35,12 @@ module Build
|
|
|
48
35
|
succeeded?
|
|
49
36
|
end
|
|
50
37
|
|
|
38
|
+
# @returns [Boolean] whether any traversing task failed.
|
|
51
39
|
def failed?
|
|
52
40
|
@failed.size != 0
|
|
53
41
|
end
|
|
54
42
|
|
|
43
|
+
# @returns [Boolean] whether all traversing tasks succeeded.
|
|
55
44
|
def succeeded?
|
|
56
45
|
@failed.size == 0
|
|
57
46
|
end
|
data/lib/build/graph/node.rb
CHANGED
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
# furnished to do so, subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
|
11
|
-
# all copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
# THE SOFTWARE.
|
|
1
|
+
# frozen_string_literal: true
|
|
20
2
|
|
|
21
|
-
|
|
22
|
-
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require "build/files/state"
|
|
7
|
+
require "build/files"
|
|
23
8
|
|
|
24
9
|
module Build
|
|
25
10
|
module Graph
|
|
@@ -44,6 +29,7 @@ module Build
|
|
|
44
29
|
@inputs.map{|path| path.modified_time}.max
|
|
45
30
|
end
|
|
46
31
|
|
|
32
|
+
# @returns [Boolean] whether any input or output file is missing from the filesystem.
|
|
47
33
|
def missing?
|
|
48
34
|
@outputs.any?{|path| !path.exist?} || @inputs.any?{|path| !path.exist?}
|
|
49
35
|
end
|
|
@@ -74,6 +60,7 @@ module Build
|
|
|
74
60
|
return false
|
|
75
61
|
end
|
|
76
62
|
|
|
63
|
+
# @returns [Boolean] whether this node is equal to another by comparing inputs and outputs.
|
|
77
64
|
def == other
|
|
78
65
|
self.equal?(other) or
|
|
79
66
|
self.class == other.class and
|
|
@@ -81,18 +68,25 @@ module Build
|
|
|
81
68
|
@outputs == other.outputs
|
|
82
69
|
end
|
|
83
70
|
|
|
71
|
+
# @returns [Boolean] whether this node is equal to another, for use in Hash and Set.
|
|
84
72
|
def eql?(other)
|
|
85
73
|
self.equal?(other) or self == other
|
|
86
74
|
end
|
|
87
75
|
|
|
76
|
+
# @returns [Integer] a hash value derived from inputs and outputs.
|
|
88
77
|
def hash
|
|
89
78
|
@inputs.hash ^ @outputs.hash
|
|
90
79
|
end
|
|
91
80
|
|
|
81
|
+
# @returns [String] a human-readable representation of the node.
|
|
92
82
|
def inspect
|
|
93
83
|
"#<#{self.class} #{@inputs.inspect} => #{@outputs.inspect}>"
|
|
94
84
|
end
|
|
95
85
|
|
|
86
|
+
# Create a top-level node that inherits its outputs from its children.
|
|
87
|
+
# @parameter inputs [Build::Files::List] the input files for this node.
|
|
88
|
+
# @parameter outputs [Symbol] the output strategy, defaults to `:inherit`.
|
|
89
|
+
# @returns [Node] the constructed top-level node.
|
|
96
90
|
def self.top(inputs = Files::Paths::NONE, outputs = :inherit, **options, &block)
|
|
97
91
|
self.new(inputs, outputs, block, **options)
|
|
98
92
|
end
|
data/lib/build/graph/task.rb
CHANGED
|
@@ -1,41 +1,35 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
# furnished to do so, subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
|
11
|
-
# all copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
# THE SOFTWARE.
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2015-2026, by Samuel Williams.
|
|
20
5
|
|
|
21
6
|
module Build
|
|
22
7
|
module Graph
|
|
8
|
+
# An error that represents a transient build failure which can be retried.
|
|
23
9
|
class TransientError < StandardError
|
|
24
10
|
end
|
|
25
11
|
|
|
12
|
+
# Mixed in to errors raised when child tasks have failed.
|
|
26
13
|
module ChildrenFailed
|
|
14
|
+
# @returns [String] a human-readable error message.
|
|
27
15
|
def self.to_s
|
|
28
16
|
"Children tasks failed!"
|
|
29
17
|
end
|
|
30
18
|
end
|
|
31
19
|
|
|
20
|
+
# Mixed in to errors raised when tasks generating inputs have failed.
|
|
32
21
|
module InputsFailed
|
|
22
|
+
# @returns [String] a human-readable error message.
|
|
33
23
|
def self.to_s
|
|
34
24
|
"Tasks generating inputs failed!"
|
|
35
25
|
end
|
|
36
26
|
end
|
|
37
27
|
|
|
28
|
+
# Represents a single unit of work within a build graph walk.
|
|
38
29
|
class Task
|
|
30
|
+
# Create a new task associated with the given walker and node.
|
|
31
|
+
# @parameter walker [Walker] the walker driving the graph traversal.
|
|
32
|
+
# @parameter node [Node] the node this task is responsible for updating.
|
|
39
33
|
def initialize(walker, node)
|
|
40
34
|
@walker = walker
|
|
41
35
|
|
|
@@ -124,10 +118,12 @@ module Build
|
|
|
124
118
|
return child_task
|
|
125
119
|
end
|
|
126
120
|
|
|
121
|
+
# @returns [Boolean] whether the task has failed.
|
|
127
122
|
def failed?
|
|
128
123
|
@state == :failed
|
|
129
124
|
end
|
|
130
125
|
|
|
126
|
+
# @returns [Boolean] whether the task has completed successfully.
|
|
131
127
|
def complete?
|
|
132
128
|
@state == :complete
|
|
133
129
|
end
|
|
@@ -142,18 +138,22 @@ module Build
|
|
|
142
138
|
end
|
|
143
139
|
end
|
|
144
140
|
|
|
141
|
+
# Resets the node in the walker if inputs or outputs have changed since the last run.
|
|
145
142
|
def changed!
|
|
146
143
|
@walker.delete(@node) if (@inputs.update! or @outputs.update!)
|
|
147
144
|
end
|
|
148
145
|
|
|
146
|
+
# @returns [Array(String)] the list of root directories for all input and output paths.
|
|
149
147
|
def directories
|
|
150
148
|
(@inputs.roots + @outputs.roots).collect{|path| path.to_s}
|
|
151
149
|
end
|
|
152
150
|
|
|
151
|
+
# @returns [String] a short human-readable summary of the task.
|
|
153
152
|
def to_s
|
|
154
153
|
"#<#{self.class} #{node_string} #{state_string}>"
|
|
155
154
|
end
|
|
156
155
|
|
|
156
|
+
# @returns [String] a detailed human-readable representation including object identity.
|
|
157
157
|
def inspect
|
|
158
158
|
"\#<#{self.class}:0x#{self.object_id.to_s(16)} #{node_string} #{state_string}>"
|
|
159
159
|
end
|
|
@@ -210,7 +210,7 @@ module Build
|
|
|
210
210
|
|
|
211
211
|
# Fail the task with the given error. Any task which is waiting on this task will also fail (eventually).
|
|
212
212
|
def fail!(error)
|
|
213
|
-
|
|
213
|
+
Console.error(self, "Task failed!", exception: error)
|
|
214
214
|
|
|
215
215
|
@error = error
|
|
216
216
|
@state = :failed
|
data/lib/build/graph/version.rb
CHANGED
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
# furnished to do so, subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
|
11
|
-
# all copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
# THE SOFTWARE.
|
|
1
|
+
# frozen_string_literal: true
|
|
20
2
|
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
# @namespace
|
|
21
7
|
module Build
|
|
8
|
+
# @namespace
|
|
22
9
|
module Graph
|
|
23
|
-
VERSION = "2.
|
|
10
|
+
VERSION = "2.2.0"
|
|
24
11
|
end
|
|
25
12
|
end
|
data/lib/build/graph/walker.rb
CHANGED
|
@@ -1,35 +1,23 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
# furnished to do so, subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
|
11
|
-
# all copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
# THE SOFTWARE.
|
|
1
|
+
# frozen_string_literal: true
|
|
20
2
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
require 'build/files/monitor'
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2026, by Samuel Williams.
|
|
24
5
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
6
|
+
require "set"
|
|
7
|
+
require "console"
|
|
8
|
+
require "build/files/monitor"
|
|
9
|
+
|
|
10
|
+
require_relative "task"
|
|
11
|
+
require_relative "node"
|
|
12
|
+
require_relative "edge"
|
|
28
13
|
|
|
29
14
|
module Build
|
|
30
15
|
module Graph
|
|
31
16
|
# A walker walks over a graph and applies a task to each node.
|
|
32
17
|
class Walker
|
|
18
|
+
# Create a walker that instantiates tasks of the given class for each visited node.
|
|
19
|
+
# @parameter task_class [Class] the task class to instantiate; must accept `(walker, node, *args)`.
|
|
20
|
+
# @returns [Walker] a new walker bound to the given task class.
|
|
33
21
|
def self.for(task_class, *args, **options)
|
|
34
22
|
self.new(**options) do |walker, node, parent_task = nil|
|
|
35
23
|
task = task_class.new(walker, node, *args)
|
|
@@ -40,7 +28,9 @@ module Build
|
|
|
40
28
|
end
|
|
41
29
|
end
|
|
42
30
|
|
|
43
|
-
|
|
31
|
+
# Create a walker with a block that is called for each node to create and run a task.
|
|
32
|
+
# @parameter block [Proc] called with `(walker, node, parent_task)` for each visited node.
|
|
33
|
+
def initialize(&block)
|
|
44
34
|
# Node -> Task mapping.
|
|
45
35
|
@tasks = {}
|
|
46
36
|
|
|
@@ -55,13 +45,9 @@ module Build
|
|
|
55
45
|
@failed_tasks = []
|
|
56
46
|
@failed_outputs = Set.new
|
|
57
47
|
|
|
58
|
-
@
|
|
59
|
-
@monitor = Files::Monitor.new(logger: @logger)
|
|
48
|
+
@monitor = Files::Monitor.new
|
|
60
49
|
end
|
|
61
50
|
|
|
62
|
-
# Primarily for debugging from within Task
|
|
63
|
-
attr :logger
|
|
64
|
-
|
|
65
51
|
# An Array of all instantiated tasks.
|
|
66
52
|
attr :tasks
|
|
67
53
|
|
|
@@ -78,16 +64,22 @@ module Build
|
|
|
78
64
|
|
|
79
65
|
attr :monitor
|
|
80
66
|
|
|
67
|
+
# Invoke the walker for each node in the given collection.
|
|
68
|
+
# @parameter nodes [Enumerable] the nodes to update.
|
|
81
69
|
def update(nodes)
|
|
82
70
|
Array(nodes).each do |node|
|
|
83
71
|
self.call(node)
|
|
84
72
|
end
|
|
85
73
|
end
|
|
86
74
|
|
|
75
|
+
# Invoke the walker for a single node, reusing an existing task if the node has already been visited.
|
|
76
|
+
# @parameter node [Node] the node to update.
|
|
77
|
+
# @parameter parent_task [Task | nil] the parent task, if any.
|
|
78
|
+
# @returns [Task] the task associated with the node.
|
|
87
79
|
def call(node, parent_task = nil)
|
|
88
80
|
# We try to fetch the task if it has already been invoked, otherwise we create a new task.
|
|
89
81
|
@tasks.fetch(node) do
|
|
90
|
-
|
|
82
|
+
Console.debug(self){"Update: #{node} #{parent_task.class}"}
|
|
91
83
|
|
|
92
84
|
# This method should add the node
|
|
93
85
|
@update.call(self, node, parent_task)
|
|
@@ -97,10 +89,15 @@ module Build
|
|
|
97
89
|
end
|
|
98
90
|
end
|
|
99
91
|
|
|
92
|
+
# @returns [Boolean] whether any tasks have failed during this walk.
|
|
100
93
|
def failed?
|
|
101
94
|
@failed_tasks.size > 0
|
|
102
95
|
end
|
|
103
96
|
|
|
97
|
+
# Block the current fiber until all tasks generating the given paths have completed.
|
|
98
|
+
# @parameter task [Task] the task waiting on these paths.
|
|
99
|
+
# @parameter paths [Build::Files::List] the paths to wait on.
|
|
100
|
+
# @returns [Boolean] true if all paths are available, false if any failed.
|
|
104
101
|
def wait_on_paths(task, paths)
|
|
105
102
|
# If there are no paths, we are done:
|
|
106
103
|
return true if paths.count == 0
|
|
@@ -113,13 +110,13 @@ module Build
|
|
|
113
110
|
paths.each do |path|
|
|
114
111
|
# Is there a task generating this output?
|
|
115
112
|
if outputs = @outputs[path]
|
|
116
|
-
|
|
113
|
+
Console.debug(self){"Task #{task} is waiting on path #{path}"}
|
|
117
114
|
|
|
118
115
|
# When the output is ready, trigger this edge:
|
|
119
116
|
outputs << edge
|
|
120
117
|
edge.increment!
|
|
121
118
|
elsif !File.exist?(path)
|
|
122
|
-
|
|
119
|
+
Console.warn(self){"Task #{task} is waiting on paths which don't exist and are not being generated!"}
|
|
123
120
|
raise RuntimeError, "File #{path} is not being generated by any active task!"
|
|
124
121
|
# What should we do about paths which haven't been registered as outputs?
|
|
125
122
|
# Either they exist - or they don't.
|
|
@@ -141,7 +138,7 @@ module Build
|
|
|
141
138
|
# If there are no children like this, then done:
|
|
142
139
|
return true if children.size == 0
|
|
143
140
|
|
|
144
|
-
|
|
141
|
+
Console.debug(self){"Task #{parent} is waiting on #{children.count} children"}
|
|
145
142
|
|
|
146
143
|
# Otherwise, construct an edge to track state changes:
|
|
147
144
|
edge = Edge.new
|
|
@@ -160,15 +157,16 @@ module Build
|
|
|
160
157
|
return edge.wait
|
|
161
158
|
end
|
|
162
159
|
|
|
160
|
+
# Register a task as active and record its declared output paths.
|
|
161
|
+
# @parameter task [Task] the task that is beginning execution.
|
|
163
162
|
def enter(task)
|
|
164
|
-
@logger&.debug(self) {"Walker entering: #{task.node}"}
|
|
165
163
|
|
|
166
164
|
@tasks[task.node] = task
|
|
167
165
|
|
|
168
166
|
# In order to wait on outputs, they must be known before entering the task. This might seem odd, but unless we know outputs are being generated, waiting for them to complete is impossible - unless this was somehow specified ahead of time. The implications of this logic is that all tasks must be sequential in terms of output -> input chaning. This is by design and is not a problem in practice.
|
|
169
167
|
|
|
170
168
|
if outputs = task.outputs
|
|
171
|
-
|
|
169
|
+
Console.debug(self) do |buffer|
|
|
172
170
|
buffer.puts "Task will generate outputs:"
|
|
173
171
|
Array(outputs).each do |output|
|
|
174
172
|
buffer.puts output.inspect
|
|
@@ -182,8 +180,9 @@ module Build
|
|
|
182
180
|
end
|
|
183
181
|
end
|
|
184
182
|
|
|
183
|
+
# Mark a task as finished, resolve its output paths and notify any waiting tasks.
|
|
184
|
+
# @parameter task [Task] the task that has finished execution.
|
|
185
185
|
def exit(task)
|
|
186
|
-
@logger&.debug(self) {"Walker exiting: #{task.node}, task #{task.failed? ? 'failed' : 'succeeded'}"}
|
|
187
186
|
|
|
188
187
|
# Fail outputs if the node failed:
|
|
189
188
|
if task.failed?
|
|
@@ -198,7 +197,7 @@ module Build
|
|
|
198
197
|
task.outputs.each do |path|
|
|
199
198
|
path = path.to_s
|
|
200
199
|
|
|
201
|
-
|
|
200
|
+
Console.debug(self){"File #{task.failed? ? 'failed' : 'available'}: #{path}"}
|
|
202
201
|
|
|
203
202
|
if edges = @outputs.delete(path)
|
|
204
203
|
# @logger&.debug "\tUpdating #{edges.count} edges..."
|
|
@@ -214,14 +213,16 @@ module Build
|
|
|
214
213
|
@monitor.add(task)
|
|
215
214
|
end
|
|
216
215
|
|
|
216
|
+
# Remove a node and its associated task from the walker, e.g. after it has been invalidated.
|
|
217
|
+
# @parameter node [Node] the node to remove.
|
|
217
218
|
def delete(node)
|
|
218
|
-
|
|
219
|
-
|
|
219
|
+
|
|
220
220
|
if task = @tasks.delete(node)
|
|
221
221
|
@monitor.delete(task)
|
|
222
222
|
end
|
|
223
223
|
end
|
|
224
224
|
|
|
225
|
+
# Remove all failed tasks from the walker so they can be retried on the next update.
|
|
225
226
|
def clear_failed
|
|
226
227
|
@failed_tasks.each do |task|
|
|
227
228
|
self.delete(task.node)
|
|
@@ -231,6 +232,7 @@ module Build
|
|
|
231
232
|
@failed_outputs = Set.new
|
|
232
233
|
end
|
|
233
234
|
|
|
235
|
+
# Run an update loop, re-executing the given block whenever the monitor detects filesystem changes.
|
|
234
236
|
def run(**options)
|
|
235
237
|
yield
|
|
236
238
|
|
|
@@ -239,6 +241,7 @@ module Build
|
|
|
239
241
|
end
|
|
240
242
|
end
|
|
241
243
|
|
|
244
|
+
# @returns [String] a human-readable summary of the walker state.
|
|
242
245
|
def inspect
|
|
243
246
|
"\#<#{self.class}:0x#{self.object_id.to_s(16)} #{@tasks.count} tasks, #{@failed_tasks.count} failed>"
|
|
244
247
|
end
|
data/lib/build/graph.rb
CHANGED
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
# furnished to do so, subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
|
11
|
-
# all copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
# THE SOFTWARE.
|
|
1
|
+
# frozen_string_literal: true
|
|
20
2
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
require_relative 'graph/walker'
|
|
24
|
-
require_relative 'graph/edge'
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2014-2026, by Samuel Williams.
|
|
25
5
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
6
|
+
require_relative "graph/version"
|
|
7
|
+
require_relative "graph/task"
|
|
8
|
+
require_relative "graph/node"
|
|
9
|
+
require_relative "graph/walker"
|
|
10
|
+
require_relative "graph/edge"
|
data/license.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright, 2014-2026, by Samuel Williams.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/readme.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Build::Graph
|
|
2
|
+
|
|
3
|
+
Build::Graph is a framework for build systems, with specific functionality for dealing with file based processes.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/ioquatix/build-graph/actions?workflow=Test)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Please see the [project documentation](https://ioquatix.github.io/build-graph) for more details.
|
|
10
|
+
|
|
11
|
+
- [Getting Started](https://ioquatix.github.io/build-graphguides/getting-started/index) - This guide explains how to use `build-graph` to build a dependency graph for file-based build systems.
|
|
12
|
+
|
|
13
|
+
## Releases
|
|
14
|
+
|
|
15
|
+
Please see the [project releases](https://ioquatix.github.io/build-graphreleases/index) for all releases.
|
|
16
|
+
|
|
17
|
+
### v2.2.0
|
|
18
|
+
|
|
19
|
+
- Remove `logger` interface.
|
|
20
|
+
|
|
21
|
+
## Contributing
|
|
22
|
+
|
|
23
|
+
We welcome contributions to this project.
|
|
24
|
+
|
|
25
|
+
1. Fork it.
|
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`).
|
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`).
|
|
29
|
+
5. Create new Pull Request.
|
|
30
|
+
|
|
31
|
+
### Developer Certificate of Origin
|
|
32
|
+
|
|
33
|
+
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
|
34
|
+
|
|
35
|
+
### Community Guidelines
|
|
36
|
+
|
|
37
|
+
This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
|
data/releases.md
ADDED
data.tar.gz.sig
CHANGED
|
Binary file
|