sleeping_king_studios-tasks 0.2.0 → 0.3.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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9380cfb581917cac00ae5102325dd895fcbd1364b4d8a53844f9ead55a41173
|
4
|
+
data.tar.gz: 69647411117043bf53bf24c4f47231de7d970de6c3adff412cc4a5228af7939e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 563983af6ab016118a21b810e8c5b2f61ef915ddee3bdce425f8945c5bf2bfb5dfc21a14acf8a07a7c08776443fd0cf7e46e5f96ff2c708a88f0834e4d856e51
|
7
|
+
data.tar.gz: 0b2d75151cc7513903514ed8f60041c5b7e73b2723373ceedb7f904a65059e8815f100f9cb54f745c6619274650f3ca7b2da063b50082b5548159fcf0d3918d9
|
data/CHANGELOG.md
CHANGED
@@ -29,8 +29,8 @@ module SleepingKingStudios::Tasks
|
|
29
29
|
end # method base_command
|
30
30
|
|
31
31
|
def build_command **kwargs
|
32
|
-
env = build_environment(kwargs)
|
33
|
-
opts = build_options(kwargs)
|
32
|
+
env = build_environment(**kwargs)
|
33
|
+
opts = build_options(**kwargs)
|
34
34
|
|
35
35
|
"#{env} #{base_command} #{opts}".strip
|
36
36
|
end # method build_command
|
@@ -52,7 +52,7 @@ module SleepingKingStudios::Tasks
|
|
52
52
|
end # method build_options
|
53
53
|
|
54
54
|
def stream_process command
|
55
|
-
|
55
|
+
unbundled_env do
|
56
56
|
IO.popen(command) do |io|
|
57
57
|
loop do
|
58
58
|
char = io.getc
|
@@ -60,11 +60,21 @@ module SleepingKingStudios::Tasks
|
|
60
60
|
char ? print(char) : break
|
61
61
|
end # loop
|
62
62
|
end # popen
|
63
|
-
end #
|
63
|
+
end # with_unbundled_env
|
64
64
|
end # method stream_process
|
65
65
|
|
66
66
|
def tools
|
67
67
|
SleepingKingStudios::Tools::Toolbelt.new
|
68
68
|
end # method tools
|
69
|
+
|
70
|
+
def unbundled_env
|
71
|
+
# :nocov:
|
72
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
73
|
+
Bundler.with_unbundled_env { yield }
|
74
|
+
else
|
75
|
+
Bundler.with_clean_env { yield }
|
76
|
+
end
|
77
|
+
# :nocov:
|
78
|
+
end
|
69
79
|
end # class
|
70
80
|
end # module
|
@@ -0,0 +1,280 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tools/core_tools'
|
4
|
+
require 'sleeping_king_studios/tools/toolbox'
|
5
|
+
|
6
|
+
# :nocov:
|
7
|
+
module SleepingKingStudios::Tools::Toolbox
|
8
|
+
# Abstract base class for defining configuration objects.
|
9
|
+
class Configuration # rubocop:disable Metrics/ClassLength
|
10
|
+
# Class methods for configuration objects.
|
11
|
+
module ClassMethods
|
12
|
+
DEFAULT_OPTION = Object.new.freeze
|
13
|
+
|
14
|
+
# Defines a nested namespace for the configuration object.
|
15
|
+
#
|
16
|
+
# A namespace is represented by a nested configuration object, which has
|
17
|
+
# its own options and namespaces.
|
18
|
+
#
|
19
|
+
# @param namespace_name [String] The name of the namespace.
|
20
|
+
#
|
21
|
+
# @yield namespace If a block is given, that block will be executed in the
|
22
|
+
# context of the newly created namespace.
|
23
|
+
#
|
24
|
+
# @return [Configuration] the created namespace object.
|
25
|
+
def namespace(namespace_name, &block)
|
26
|
+
guard_abstract_class!
|
27
|
+
|
28
|
+
namespace =
|
29
|
+
(@namespaces ||= {}).fetch(namespace_name) do
|
30
|
+
@namespaces[namespace_name] = define_namespace namespace_name
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace.instance_exec(namespace, &block) if block_given?
|
34
|
+
|
35
|
+
namespace
|
36
|
+
end
|
37
|
+
|
38
|
+
# Defines an option for the configuration object.
|
39
|
+
#
|
40
|
+
# A configuration option has a name and a value. It can be defined with a
|
41
|
+
# default value, or to allow or prohibit nil values or restrict possible
|
42
|
+
# values to a given set.
|
43
|
+
#
|
44
|
+
# @param option_name [String] The name of the option.
|
45
|
+
# @param allow_nil [true, false] If false, setting the option value to nil
|
46
|
+
# or an empty value will raise an error, as will trying to access the
|
47
|
+
# value when it has not been set. Defaults to false.
|
48
|
+
# @param default [Object] The default value for the option. If this is not
|
49
|
+
# set, the default value for the option will be nil.
|
50
|
+
# @param enum [Array] An enumerable list of valid values for the option.
|
51
|
+
def option(
|
52
|
+
option_name,
|
53
|
+
allow_nil: false,
|
54
|
+
default: DEFAULT_OPTION,
|
55
|
+
enum: nil
|
56
|
+
)
|
57
|
+
guard_abstract_class!
|
58
|
+
|
59
|
+
options = {
|
60
|
+
allow_nil: allow_nil,
|
61
|
+
default: default,
|
62
|
+
enum: enum
|
63
|
+
}
|
64
|
+
|
65
|
+
define_option_accessor option_name, options
|
66
|
+
define_option_mutator option_name, options
|
67
|
+
|
68
|
+
option_name.intern
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def define_namespace(namespace_name)
|
74
|
+
namespace =
|
75
|
+
Class.new(SleepingKingStudios::Tools::Toolbox::Configuration)
|
76
|
+
|
77
|
+
define_namespace_accessor(namespace_name, namespace)
|
78
|
+
|
79
|
+
namespace
|
80
|
+
end
|
81
|
+
|
82
|
+
def define_namespace_accessor(namespace_name, namespace_class)
|
83
|
+
namespace_ivar = :"@#{namespace_name}"
|
84
|
+
|
85
|
+
define_method namespace_name do |&block|
|
86
|
+
if instance_variable_defined?(namespace_ivar)
|
87
|
+
return instance_variable_get(namespace_ivar).tap do |config|
|
88
|
+
block&.call(config)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
initialize_namespace(namespace_name, namespace_class, &block)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def define_option_accessor(option_name, options)
|
97
|
+
define_method option_name do
|
98
|
+
get_value(option_name, options)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def define_option_mutator(option_name, options)
|
103
|
+
writer_name = :"#{option_name}="
|
104
|
+
|
105
|
+
define_method writer_name do |value|
|
106
|
+
set_value(option_name, value, options)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def guard_abstract_class!
|
111
|
+
return unless self == SleepingKingStudios::Tools::Toolbox::Configuration
|
112
|
+
|
113
|
+
raise "can't define namespace or option on abstract class"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
extend ClassMethods
|
117
|
+
|
118
|
+
DEFAULT_OPTION = ClassMethods::DEFAULT_OPTION
|
119
|
+
|
120
|
+
# @param data [Hash, Object] The data source used to populate configuration
|
121
|
+
# values. Can be a Hash or a data object. If the data source is nil, or no
|
122
|
+
# data source is given, values will be set to their respective defaults.
|
123
|
+
#
|
124
|
+
# @yieldparam [Class] The singleton class of the new configuration object.
|
125
|
+
def initialize(data = nil)
|
126
|
+
@data = convert_data_to_struct(data)
|
127
|
+
@root_namespace = self
|
128
|
+
|
129
|
+
return unless block_given?
|
130
|
+
|
131
|
+
SleepingKingStudios::Tools::CoreTools
|
132
|
+
.deprecate('Configuration#initialize with a block')
|
133
|
+
|
134
|
+
yield(singleton_class)
|
135
|
+
end
|
136
|
+
|
137
|
+
def [](key)
|
138
|
+
send(key) if respond_to?(key)
|
139
|
+
end
|
140
|
+
|
141
|
+
def []=(key, value)
|
142
|
+
send(:"#{key}=", value) if respond_to?(key)
|
143
|
+
end
|
144
|
+
|
145
|
+
def dig(*keys)
|
146
|
+
keys.reduce(self) do |config, key|
|
147
|
+
value = config[key]
|
148
|
+
|
149
|
+
return value if value.nil?
|
150
|
+
|
151
|
+
value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def fetch(key, default = DEFAULT_OPTION)
|
156
|
+
return send(key) if respond_to?(key)
|
157
|
+
|
158
|
+
return default unless default == DEFAULT_OPTION
|
159
|
+
|
160
|
+
return yield(key) if block_given?
|
161
|
+
|
162
|
+
raise KeyError, "key not found: #{key.inspect}"
|
163
|
+
end
|
164
|
+
|
165
|
+
protected
|
166
|
+
|
167
|
+
attr_accessor :root_namespace
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
attr_reader :data
|
172
|
+
|
173
|
+
def blank_value?(value)
|
174
|
+
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
175
|
+
end
|
176
|
+
|
177
|
+
def convert_data_to_struct(data)
|
178
|
+
return data unless data.is_a?(Hash)
|
179
|
+
|
180
|
+
return Object.new if data.empty?
|
181
|
+
|
182
|
+
obj = Struct.new(*data.keys).new
|
183
|
+
|
184
|
+
data.each do |key, value|
|
185
|
+
val = value.is_a?(Hash) ? convert_data_to_struct(value) : value
|
186
|
+
|
187
|
+
obj.send :"#{key}=", val
|
188
|
+
end
|
189
|
+
|
190
|
+
obj
|
191
|
+
end
|
192
|
+
|
193
|
+
def evaluate_default(default)
|
194
|
+
return default unless default.is_a?(Proc)
|
195
|
+
|
196
|
+
root_namespace.instance_exec(&default)
|
197
|
+
end
|
198
|
+
|
199
|
+
def get_default_value(options)
|
200
|
+
value = evaluate_default(options[:default])
|
201
|
+
|
202
|
+
validate_value value, options
|
203
|
+
|
204
|
+
value
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_method_value(name, options)
|
208
|
+
value = data.send(name)
|
209
|
+
|
210
|
+
if value.nil? && options[:default] != DEFAULT_OPTION
|
211
|
+
value = evaluate_default(options[:default])
|
212
|
+
end
|
213
|
+
|
214
|
+
validate_value(value, options)
|
215
|
+
|
216
|
+
value
|
217
|
+
end
|
218
|
+
|
219
|
+
def get_value(name, options)
|
220
|
+
if data.respond_to?(name)
|
221
|
+
get_method_value(name, options)
|
222
|
+
elsif instance_variable_defined?(:"@#{name}")
|
223
|
+
instance_variable_get(:"@#{name}")
|
224
|
+
elsif options[:default] != DEFAULT_OPTION
|
225
|
+
get_default_value(options)
|
226
|
+
else
|
227
|
+
validate_value(nil, options)
|
228
|
+
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def initialize_namespace(namespace_name, namespace_class, &block)
|
234
|
+
data = get_value(namespace_name, default: Object.new)
|
235
|
+
config = namespace_class.new(data)
|
236
|
+
|
237
|
+
config.root_namespace = root_namespace || self
|
238
|
+
|
239
|
+
instance_variable_set(:"@#{namespace_name}", config)
|
240
|
+
|
241
|
+
block.call(config) if block_given?
|
242
|
+
|
243
|
+
config
|
244
|
+
end
|
245
|
+
|
246
|
+
def invalid_value_message(value, options)
|
247
|
+
array_tools = ::SleepingKingStudios::Tools::ArrayTools
|
248
|
+
valid_options =
|
249
|
+
array_tools
|
250
|
+
.humanize_list(
|
251
|
+
options[:enum].map(&:inspect),
|
252
|
+
last_separator: ' or '
|
253
|
+
)
|
254
|
+
|
255
|
+
"expected option to be #{valid_options}, but was #{value.inspect}"
|
256
|
+
end
|
257
|
+
|
258
|
+
def set_value(name, value, options)
|
259
|
+
writer_name = :"#{name}="
|
260
|
+
|
261
|
+
validate_value value, options
|
262
|
+
|
263
|
+
if data.respond_to?(writer_name)
|
264
|
+
data.send(writer_name, value)
|
265
|
+
else
|
266
|
+
# Store values locally if data source is immutable.
|
267
|
+
instance_variable_set(:"@#{name}", value)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def validate_value(value, options)
|
272
|
+
return if blank_value?(value) && options[:allow_nil]
|
273
|
+
|
274
|
+
return unless options[:enum] && !options[:enum].include?(value)
|
275
|
+
|
276
|
+
raise invalid_value_message(value, options)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
# :nocov:
|
metadata
CHANGED
@@ -1,49 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sleeping_king_studios-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob "Merlin" Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rake
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '12.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '12.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: thor
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.19'
|
34
17
|
- - ">="
|
35
18
|
- !ruby/object:Gem::Version
|
36
19
|
version: 0.19.4
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
37
23
|
type: :runtime
|
38
24
|
prerelease: false
|
39
25
|
version_requirements: !ruby/object:Gem::Requirement
|
40
26
|
requirements:
|
41
|
-
- - "~>"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '0.19'
|
44
27
|
- - ">="
|
45
28
|
- !ruby/object:Gem::Version
|
46
29
|
version: 0.19.4
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
47
33
|
- !ruby/object:Gem::Dependency
|
48
34
|
name: sleeping_king_studios-tools
|
49
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,6 +248,7 @@ files:
|
|
262
248
|
- lib/sleeping_king_studios/tasks/task.rb
|
263
249
|
- lib/sleeping_king_studios/tasks/task_group.rb
|
264
250
|
- lib/sleeping_king_studios/tasks/version.rb
|
251
|
+
- lib/sleeping_king_studios/tools/toolbox/configuration.rb
|
265
252
|
homepage: http://sleepingkingstudios.com
|
266
253
|
licenses:
|
267
254
|
- MIT
|
@@ -281,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
281
268
|
- !ruby/object:Gem::Version
|
282
269
|
version: '0'
|
283
270
|
requirements: []
|
284
|
-
rubygems_version: 3.
|
271
|
+
rubygems_version: 3.1.2
|
285
272
|
signing_key:
|
286
273
|
specification_version: 4
|
287
274
|
summary: A tasks toolkit for rapid development.
|