squared 0.0.10 → 0.0.12
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
- data/README.ruby.md +98 -26
- data/lib/squared/app.rb +10 -0
- data/lib/squared/common/base.rb +12 -16
- data/lib/squared/common/class.rb +26 -1
- data/lib/squared/common/format.rb +79 -24
- data/lib/squared/common/prompt.rb +36 -0
- data/lib/squared/common/shell.rb +4 -3
- data/lib/squared/common/system.rb +15 -47
- data/lib/squared/common/utils.rb +51 -16
- data/lib/squared/common.rb +1 -4
- data/lib/squared/config.rb +48 -43
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +245 -125
- data/lib/squared/workspace/project/base.rb +448 -188
- data/lib/squared/workspace/project/git.rb +97 -113
- data/lib/squared/workspace/project/node.rb +217 -109
- data/lib/squared/workspace/project/python.rb +37 -34
- data/lib/squared/workspace/project/ruby.rb +137 -100
- data/lib/squared/workspace/project.rb +0 -3
- data/lib/squared/workspace/repo.rb +32 -18
- data/lib/squared/workspace/series.rb +82 -53
- data/lib/squared/workspace.rb +6 -5
- data/lib/squared.rb +1 -11
- metadata +4 -3
- data/lib/squared/common/task.rb +0 -24
@@ -8,21 +8,22 @@ module Squared
|
|
8
8
|
module Workspace
|
9
9
|
module Project
|
10
10
|
class Base
|
11
|
-
include Common
|
12
|
-
include Format
|
11
|
+
include Common::Format
|
13
12
|
include System
|
14
13
|
include Shell
|
15
|
-
include Task
|
16
14
|
include Utils
|
17
15
|
include ::Rake::DSL
|
18
16
|
|
19
17
|
SEM_VER = /(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?/.freeze
|
20
18
|
|
21
|
-
VAR_SET = %i[parent global envname theme run script env depend doc test copy clean].freeze
|
19
|
+
VAR_SET = %i[parent global envname dependfile theme run script env depend graph doc test copy clean].freeze
|
22
20
|
private_constant :VAR_SET
|
23
21
|
|
24
22
|
class << self
|
25
23
|
def populate(*); end
|
24
|
+
def batchargs(*); end
|
25
|
+
def aliasargs(*); end
|
26
|
+
def bannerargs(*); end
|
26
27
|
|
27
28
|
def tasks
|
28
29
|
[].freeze
|
@@ -42,32 +43,39 @@ module Squared
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def to_s
|
45
|
-
super.
|
46
|
+
super.match(/[^:]+$/)[0]
|
47
|
+
end
|
48
|
+
|
49
|
+
def config?(*)
|
50
|
+
false
|
46
51
|
end
|
47
52
|
end
|
48
53
|
|
54
|
+
@@tasks = {
|
55
|
+
"#{ref}": {
|
56
|
+
graph: %i[run print].freeze
|
57
|
+
}.freeze
|
58
|
+
}
|
49
59
|
@@print_order = 0
|
50
|
-
@@tasks = {}
|
51
60
|
|
52
|
-
attr_reader :name, :project, :workspace, :
|
53
|
-
|
61
|
+
attr_reader :name, :project, :workspace, :path, :exception, :pipe, :theme, :group, :parent,
|
62
|
+
:dependfile, :verbose
|
54
63
|
|
55
|
-
def initialize(
|
56
|
-
|
57
|
-
common: Common::KEY[:COMMON], pipe: Common::KEY[:PIPE], **kwargs)
|
58
|
-
@name = name.to_s
|
64
|
+
def initialize(workspace, path, name, *, group: nil, graph: nil, pass: nil, exclude: nil,
|
65
|
+
common: ARG[:COMMON], **kwargs)
|
59
66
|
@path = path
|
60
|
-
@project = @path.basename.to_s
|
61
67
|
@workspace = workspace
|
62
|
-
@
|
68
|
+
@name = name.to_s.freeze
|
69
|
+
@project = @path.basename.to_s.freeze
|
70
|
+
@group = group&.to_s.freeze
|
63
71
|
@depend = kwargs[:depend]
|
64
72
|
@doc = kwargs[:doc]
|
65
73
|
@test = kwargs[:test]
|
66
74
|
@copy = kwargs[:copy]
|
67
75
|
@clean = kwargs[:clean]
|
68
|
-
@exception = workspace.exception
|
69
|
-
@pipe = env_pipe(pipe
|
70
|
-
@verbose =
|
76
|
+
@exception = kwargs.key?(:exception) ? env_bool(kwargs[:exception]) : workspace.exception
|
77
|
+
@pipe = kwargs.key?(:pipe) ? env_pipe(kwargs[:pipe]) : workspace.pipe
|
78
|
+
@verbose = kwargs.key?(:verbose) ? kwargs[:verbose] : workspace.verbose
|
71
79
|
@theme = if !@verbose
|
72
80
|
{}
|
73
81
|
elsif common
|
@@ -78,12 +86,16 @@ module Squared
|
|
78
86
|
@output = []
|
79
87
|
@ref = []
|
80
88
|
@children = []
|
89
|
+
@graph = if graph
|
90
|
+
as_a(graph, workspace.prefix ? ->(val) { workspace.task_name(val).to_sym } : :to_sym).freeze
|
91
|
+
end
|
81
92
|
@pass = (pass ? as_a(pass, :to_sym) : []).freeze
|
82
93
|
@exclude = (exclude ? as_a(exclude, :to_sym) : []).freeze
|
83
|
-
@envname = @name.gsub(/[^\w]+/, '_').upcase
|
84
|
-
@desc = @name.split(':').join(
|
94
|
+
@envname = @name.gsub(/[^\w]+/, '_').upcase.freeze
|
95
|
+
@desc = (@name.include?(':') ? @name.split(':').join(ARG[:SPACE]) : @name).freeze
|
96
|
+
@parent = nil
|
85
97
|
@global = false
|
86
|
-
run_set
|
98
|
+
run_set(kwargs[:run], kwargs[:env], opts: kwargs.fetch(:opts, true))
|
87
99
|
initialize_ref(Base.ref)
|
88
100
|
end
|
89
101
|
|
@@ -93,7 +105,7 @@ module Squared
|
|
93
105
|
|
94
106
|
def initialize_build(ref, **kwargs)
|
95
107
|
initialize_ref(ref)
|
96
|
-
if (@script = @workspace.
|
108
|
+
if (@script = @workspace.script_get(group: @group, ref: ref))
|
97
109
|
if @script[:log] && !kwargs.key?(:log)
|
98
110
|
kwargs[:log] = @script[:log]
|
99
111
|
@log = nil
|
@@ -107,7 +119,7 @@ module Squared
|
|
107
119
|
initialize_logger(**kwargs)
|
108
120
|
return if @output[0] == false
|
109
121
|
|
110
|
-
data = @workspace.
|
122
|
+
data = @workspace.script_find(*@ref, @group)
|
111
123
|
if @output[0].nil?
|
112
124
|
if (scr = data[:script])
|
113
125
|
@global = true
|
@@ -140,8 +152,8 @@ module Squared
|
|
140
152
|
return if @log
|
141
153
|
|
142
154
|
log = log.is_a?(::Hash) ? log.dup : { file: log }
|
143
|
-
|
144
|
-
file = case
|
155
|
+
unless (file = env('LOG_FILE'))
|
156
|
+
file = case env('LOG_AUTO')
|
145
157
|
when 'y', 'year'
|
146
158
|
"#{@name}-#{Date.today.year}.log"
|
147
159
|
when 'm', 'month'
|
@@ -152,7 +164,7 @@ module Squared
|
|
152
164
|
end
|
153
165
|
if file ||= log[:file]
|
154
166
|
file = Date.today.strftime(file)
|
155
|
-
file = (dir = env('LOG_DIR')) ?
|
167
|
+
file = (dir = env('LOG_DIR')) ? @workspace.home.join(dir, file) : @workspace.home.join(file)
|
156
168
|
begin
|
157
169
|
file = file.realdirpath
|
158
170
|
rescue StandardError => e
|
@@ -163,7 +175,7 @@ module Squared
|
|
163
175
|
end
|
164
176
|
end
|
165
177
|
log[:progname] ||= @name
|
166
|
-
if (val = env('LOG_LEVEL', ignore:
|
178
|
+
if (val = env('LOG_LEVEL', ignore: false))
|
167
179
|
log[:level] = val
|
168
180
|
end
|
169
181
|
log.delete(:file)
|
@@ -171,10 +183,14 @@ module Squared
|
|
171
183
|
end
|
172
184
|
|
173
185
|
def initialize_env(dev: nil, prod: nil, **)
|
174
|
-
|
175
|
-
@dev = env_match("#{
|
176
|
-
@prod = env_match("#{
|
177
|
-
|
186
|
+
pre = "BUILD_#{@envname}"
|
187
|
+
@dev = env_match("#{pre}_DEV", dev)
|
188
|
+
@prod = env_match("#{pre}_PROD", prod)
|
189
|
+
cmd = @output[0]
|
190
|
+
unless cmd == false || cmd.is_a?(::Array) || (val = env('BUILD', suffix: 'OPTS')).nil?
|
191
|
+
@output[cmd ? 1 : 3] = shell_split(val, join: true)
|
192
|
+
end
|
193
|
+
unless @output[2] == false || (val = env('BUILD', suffix: 'ENV')).nil?
|
178
194
|
begin
|
179
195
|
data = JSON.parse(val)
|
180
196
|
raise_error('invalid JSON object', val, hint: "#{prefix}_ENV") unless data.is_a?(::Hash)
|
@@ -186,10 +202,12 @@ module Squared
|
|
186
202
|
return unless (val = env('BUILD', strict: true))
|
187
203
|
|
188
204
|
@global = false
|
189
|
-
if
|
205
|
+
if val == '0'
|
206
|
+
@output = [false]
|
207
|
+
elsif script?
|
190
208
|
script_set val
|
191
209
|
else
|
192
|
-
run_set
|
210
|
+
run_set val
|
193
211
|
end
|
194
212
|
end
|
195
213
|
|
@@ -198,36 +216,90 @@ module Squared
|
|
198
216
|
end
|
199
217
|
|
200
218
|
def populate(*)
|
201
|
-
check = lambda do |proj, key|
|
202
|
-
workspace.series.include?(key) ? proj.has?(key, Base.ref) : workspace.task_extend?(proj, key)
|
203
|
-
end
|
204
|
-
|
205
219
|
namespace name do
|
206
220
|
workspace.series.each_key do |key|
|
207
|
-
next unless
|
221
|
+
next unless workspace.task_include?(self, key)
|
208
222
|
|
209
|
-
|
210
|
-
|
211
|
-
|
223
|
+
s = workspace.series.name_get(key)
|
224
|
+
unless workspace.task_defined?(name, s)
|
225
|
+
desc message(@desc, s)
|
226
|
+
task s do
|
212
227
|
__send__(key)
|
213
228
|
end
|
214
229
|
end
|
215
|
-
next if (items = @children.select { |item|
|
230
|
+
next if (items = @children.select { |item| workspace.task_include?(item, key) }).empty?
|
216
231
|
|
217
|
-
desc message(@desc,
|
218
|
-
task
|
232
|
+
desc message(@desc, s, 'workspace')
|
233
|
+
task task_join(s, 'workspace') => items.map { |item| task_join(item.name, s) }
|
234
|
+
end
|
235
|
+
next unless ref?(Base.ref)
|
236
|
+
|
237
|
+
@@tasks[Base.ref].each do |action, flags|
|
238
|
+
namespace action do
|
239
|
+
flags.each do |flag|
|
240
|
+
case action
|
241
|
+
when :graph
|
242
|
+
next unless graph?
|
243
|
+
|
244
|
+
if flag == :run
|
245
|
+
desc format_desc(action, flag, 'pass*')
|
246
|
+
task flag, [:pass] do |_, args|
|
247
|
+
graph(pass: args.to_a)
|
248
|
+
end
|
249
|
+
else
|
250
|
+
desc format_desc(action, flag)
|
251
|
+
task flag do
|
252
|
+
out = graph(out: [])
|
253
|
+
emphasize(out, title: path, right: true, border: borderstyle,
|
254
|
+
footer: "dependencies: #{out.size - 1}",
|
255
|
+
sub: [
|
256
|
+
{ pat: /^(#{Regexp.escape(path.to_s)})(.*)$/, styles: theme[:header] },
|
257
|
+
{ pat: /^(#{Regexp.escape(name)})(.*)$/, styles: theme[:active] },
|
258
|
+
{ pat: /^(\s*)([a-z]+: )(\d+)$/, styles: theme[:inline], index: 3 }
|
259
|
+
])
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
219
265
|
end
|
220
266
|
end
|
221
267
|
end
|
222
268
|
|
223
|
-
def
|
224
|
-
|
269
|
+
def with(**kwargs, &blk)
|
270
|
+
@withargs = kwargs.empty? ? nil : kwargs
|
271
|
+
if block_given?
|
272
|
+
instance_eval(&blk)
|
273
|
+
@withargs = nil
|
274
|
+
end
|
275
|
+
self
|
276
|
+
end
|
225
277
|
|
278
|
+
def add(path, name = nil, **kwargs, &blk)
|
279
|
+
if path.is_a?(::String) && (data = %r{^(.+)[\\/]\*+$}.match(path))
|
280
|
+
path = basepath(data[1]).children.select(&:directory?)
|
281
|
+
end
|
282
|
+
if path.is_a?(::Array)
|
283
|
+
name = @name if name == true
|
284
|
+
path.each { |val| add(val, name && task_join(name, File.basename(val)), **kwargs, &blk) }
|
285
|
+
return self
|
286
|
+
elsif !projectpath?(path = basepath(path))
|
287
|
+
return self
|
288
|
+
elsif name.is_a?(::Symbol)
|
289
|
+
name = name.to_s
|
290
|
+
elsif !name.is_a?(::String)
|
291
|
+
name = nil
|
292
|
+
end
|
293
|
+
if @withargs
|
294
|
+
data = @withargs.dup
|
295
|
+
data.merge!(kwargs)
|
296
|
+
kwargs = data
|
297
|
+
end
|
226
298
|
kwargs[:group] = group unless kwargs.key?(:group)
|
227
299
|
kwargs[:ref] = ref unless kwargs.key?(:ref)
|
228
300
|
parent = self
|
229
301
|
proj = nil
|
230
|
-
workspace.add(path, name || path.basename
|
302
|
+
workspace.add(path, name || path.basename, **kwargs) do
|
231
303
|
variable_set :parent, parent
|
232
304
|
proj = self
|
233
305
|
end
|
@@ -236,54 +308,49 @@ module Squared
|
|
236
308
|
self
|
237
309
|
end
|
238
310
|
|
239
|
-
def build(*args, sync:
|
311
|
+
def build(*args, sync: invoked_sync?('build'), **)
|
240
312
|
if args.empty?
|
241
|
-
cmd, opts, var = @output
|
242
|
-
|
313
|
+
cmd, opts, var, flags = @output
|
314
|
+
banner = verbose == 1
|
243
315
|
else
|
244
316
|
cmd = args.shift
|
245
317
|
opts = args.map { |val| shell_quote(val, force: false) }.join(' ')
|
318
|
+
banner = verbose
|
246
319
|
end
|
247
320
|
if cmd
|
248
|
-
|
321
|
+
case opts
|
322
|
+
when ::String
|
249
323
|
cmd = "#{cmd} #{opts}"
|
250
|
-
|
324
|
+
when ::Array
|
251
325
|
cmd = cmd.join(' && ')
|
326
|
+
else
|
327
|
+
cmd = [cmd, compose(opts, script: false)].compact.join(' ') unless opts == false || !respond_to?(:compose)
|
252
328
|
end
|
253
|
-
banner = verbose != false
|
254
329
|
else
|
255
330
|
return unless respond_to?(:compose)
|
256
331
|
|
257
|
-
cmd = compose(opts)
|
258
|
-
banner = verbose == 1
|
332
|
+
cmd = compose(opts, flags, script: true)
|
259
333
|
end
|
260
334
|
run(cmd, var, banner: banner, sync: sync)
|
261
335
|
end
|
262
336
|
|
263
|
-
def
|
264
|
-
|
265
|
-
return if run_task "#{name}:copy"
|
266
|
-
|
267
|
-
copy if copy?
|
337
|
+
def depend(*, sync: invoked_sync?('depend'), **)
|
338
|
+
run(@depend, sync: sync) if @depend
|
268
339
|
end
|
269
340
|
|
270
|
-
def
|
271
|
-
|
341
|
+
def copy(*, sync: invoked_sync?('copy'), **)
|
342
|
+
run_s(@copy, sync: sync) if @copy
|
272
343
|
end
|
273
344
|
|
274
|
-
def
|
275
|
-
|
345
|
+
def doc(*, sync: invoked_sync?('doc'), **)
|
346
|
+
build(@doc, sync: sync) if @doc
|
276
347
|
end
|
277
348
|
|
278
|
-
def
|
279
|
-
build(@
|
349
|
+
def test(*, sync: invoked_sync?('test'), **)
|
350
|
+
build(@test, sync: sync) if @test
|
280
351
|
end
|
281
352
|
|
282
|
-
def
|
283
|
-
build(@test, sync: invoked_sync?('test')) if @test
|
284
|
-
end
|
285
|
-
|
286
|
-
def clean
|
353
|
+
def clean(*)
|
287
354
|
case @clean
|
288
355
|
when ::String
|
289
356
|
run_s(@clean, sync: invoked_sync?('clean'))
|
@@ -291,13 +358,13 @@ module Squared
|
|
291
358
|
as_a(@clean).each do |val|
|
292
359
|
if (val = val.to_s) =~ %r{[\\/]$}
|
293
360
|
dir = Pathname.new(val)
|
294
|
-
dir =
|
361
|
+
dir = basepath(dir) unless dir.absolute?
|
295
362
|
next unless dir.directory?
|
296
363
|
|
297
364
|
log.warn "rm -rf #{dir}"
|
298
365
|
dir.rmtree(verbose: true)
|
299
366
|
else
|
300
|
-
files = val.include?('*') ? Dir[
|
367
|
+
files = val.include?('*') ? Dir[basepath(val)] : [basepath(val)]
|
301
368
|
files.each do |file|
|
302
369
|
begin
|
303
370
|
File.delete(file) if File.file?(file)
|
@@ -310,16 +377,29 @@ module Squared
|
|
310
377
|
end
|
311
378
|
end
|
312
379
|
|
380
|
+
def graph(*, sync: invoked_sync?('graph'), pass: [], out: nil)
|
381
|
+
data = graph_collect(self)
|
382
|
+
data[name] << self unless out
|
383
|
+
run_graph(data, name, out, sync: sync, pass: pass)
|
384
|
+
out
|
385
|
+
end
|
386
|
+
|
313
387
|
def log
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
@log
|
318
|
-
end
|
388
|
+
return @log unless @log.is_a?(::Array)
|
389
|
+
|
390
|
+
@log = Logger.new(enabled? ? @log[0] : nil, **@log[1])
|
319
391
|
end
|
320
392
|
|
321
|
-
def
|
322
|
-
path.join(*args)
|
393
|
+
def basepath(*args, ascend: nil)
|
394
|
+
ret = path.join(*args)
|
395
|
+
return ret unless ascend && !ret.exist?
|
396
|
+
|
397
|
+
path.parent.ascend.each do |dir|
|
398
|
+
target = dir.join(*args)
|
399
|
+
return target if target.exist?
|
400
|
+
break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
|
401
|
+
end
|
402
|
+
ret
|
323
403
|
end
|
324
404
|
|
325
405
|
def color(val)
|
@@ -328,26 +408,43 @@ module Squared
|
|
328
408
|
end
|
329
409
|
|
330
410
|
def variable_set(key, *val, **kwargs)
|
331
|
-
if
|
411
|
+
if variables.include?(key)
|
332
412
|
case key
|
333
413
|
when :run
|
334
|
-
run_set(*val,
|
414
|
+
run_set(*val, **kwargs)
|
335
415
|
when :script
|
336
416
|
script_set(*val, **kwargs)
|
337
417
|
when :env
|
338
|
-
run_set(output[0], *val,
|
418
|
+
run_set(output[0], *val, **kwargs)
|
419
|
+
when :parent
|
420
|
+
@parent = val if (val = val.first).is_a?(Project::Base)
|
421
|
+
when :graph
|
422
|
+
@graph = case val.first
|
423
|
+
when nil, false
|
424
|
+
nil
|
425
|
+
else
|
426
|
+
val.flatten.map!(&:to_s).freeze
|
427
|
+
end
|
428
|
+
when :dependfile
|
429
|
+
@dependfile = basepath(*val)
|
339
430
|
else
|
340
431
|
instance_variable_set :"@#{key}", val.first
|
341
432
|
end
|
342
433
|
else
|
343
|
-
log.warn "variable_set: @#{key} (
|
434
|
+
log.warn "variable_set: @#{key} (private)"
|
344
435
|
end
|
345
436
|
end
|
346
437
|
|
347
|
-
def
|
348
|
-
|
438
|
+
def allref
|
439
|
+
@ref.reverse_each
|
349
440
|
end
|
350
441
|
|
442
|
+
def dependtype(*)
|
443
|
+
@dependindex ? @dependindex.succ : 0
|
444
|
+
end
|
445
|
+
|
446
|
+
def version(*); end
|
447
|
+
|
351
448
|
def inspect
|
352
449
|
"#<#{self.class}: #{name} => #{self}>"
|
353
450
|
end
|
@@ -384,12 +481,16 @@ module Squared
|
|
384
481
|
@output[0].nil? && !!@output[1] && respond_to?(:compose)
|
385
482
|
end
|
386
483
|
|
387
|
-
def
|
388
|
-
|
484
|
+
def depend?
|
485
|
+
!!@depend
|
389
486
|
end
|
390
487
|
|
391
|
-
def
|
392
|
-
@
|
488
|
+
def graph?
|
489
|
+
@graph.is_a?(::Array) && !@graph.empty?
|
490
|
+
end
|
491
|
+
|
492
|
+
def copy?
|
493
|
+
runnable?(@copy) || workspace.task_defined?(name, 'copy')
|
393
494
|
end
|
394
495
|
|
395
496
|
def doc?
|
@@ -400,12 +501,8 @@ module Squared
|
|
400
501
|
!!@test
|
401
502
|
end
|
402
503
|
|
403
|
-
def copy?
|
404
|
-
runnable?(@copy) || workspace.task_defined?("#{name}:copy")
|
405
|
-
end
|
406
|
-
|
407
504
|
def clean?
|
408
|
-
runnable?(@clean) || workspace.task_defined?(
|
505
|
+
runnable?(@clean) || workspace.task_defined?(name, 'clean')
|
409
506
|
end
|
410
507
|
|
411
508
|
def dev?
|
@@ -418,18 +515,22 @@ module Squared
|
|
418
515
|
|
419
516
|
private
|
420
517
|
|
421
|
-
def
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
518
|
+
def variables
|
519
|
+
VAR_SET
|
520
|
+
end
|
521
|
+
|
522
|
+
def puts(*args)
|
523
|
+
puts_oe(*args, pipe: pipe)
|
524
|
+
end
|
525
|
+
|
526
|
+
def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, **)
|
527
|
+
cmd = session_done(cmd)
|
427
528
|
log.info cmd
|
428
529
|
begin
|
429
530
|
if cmd =~ /^\S+:(\S+:?)+$/ && workspace.task_defined?(cmd)
|
430
531
|
print_item if sync
|
431
532
|
log.warn "ENV was discarded: #{var}" if var
|
432
|
-
|
533
|
+
task_invoke(cmd, exception: exception, warning: warning?)
|
433
534
|
else
|
434
535
|
print_item format_banner(cmd, banner: banner) if sync
|
435
536
|
args = var.is_a?(::Hash) ? [var, cmd] : [cmd]
|
@@ -441,52 +542,114 @@ module Squared
|
|
441
542
|
end
|
442
543
|
end
|
443
544
|
|
444
|
-
def run_s(cmd, **kwargs)
|
445
|
-
|
545
|
+
def run_s(*cmd, env: nil, banner: verbose != false, **kwargs)
|
546
|
+
cmd.each { |val| run(val, env, banner: banner, **kwargs) }
|
446
547
|
end
|
447
548
|
|
448
|
-
def
|
449
|
-
|
549
|
+
def run_graph(data, start, out = nil, sync: true, pass: [], done: [], depth: 0, last: false)
|
550
|
+
check = ->(deps) { deps.reject { |val| done.include?(val) } }
|
551
|
+
items = check.(data[start])
|
552
|
+
if out
|
553
|
+
a, b, c, d, e = ARG[:GRAPH]
|
554
|
+
out << case depth
|
555
|
+
when 0
|
556
|
+
start
|
557
|
+
when 1
|
558
|
+
if items.empty?
|
559
|
+
"#{d}#{b * 4} #{start}"
|
560
|
+
else
|
561
|
+
"#{last ? d : c}#{b * 3}#{e} #{start}"
|
562
|
+
end
|
563
|
+
else
|
564
|
+
"#{a}#{' ' * (depth - 1)}#{d}#{b * 2}#{items.empty? ? b : e} #{start}"
|
565
|
+
end
|
566
|
+
end
|
567
|
+
items.each_with_index do |proj, i|
|
568
|
+
next if done.include?(proj)
|
450
569
|
|
451
|
-
|
452
|
-
|
453
|
-
|
570
|
+
j = out ? i == items.size - 1 || check.(items[i + 1..-1]).empty? : false
|
571
|
+
s = proj.name
|
572
|
+
unless start == s || (none = check.(data.fetch(s, [])).empty?)
|
573
|
+
run_graph(data, s, out, sync: sync, pass: pass, done: done, depth: depth.succ, last: j)
|
574
|
+
end
|
575
|
+
if !out
|
576
|
+
if (script = workspace.script_get(group: proj.group, ref: proj.ref))
|
577
|
+
tasks = script[:graph]
|
578
|
+
end
|
579
|
+
(tasks || (dev? ? %w[build copy] : %w[depend build])).each do |meth|
|
580
|
+
next if pass.include?(meth)
|
454
581
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
582
|
+
if workspace.task_defined?(cmd = task_join(s, meth))
|
583
|
+
run(cmd, sync: false, banner: false)
|
584
|
+
elsif proj.has?(meth)
|
585
|
+
proj.__send__(meth.to_sym, sync: sync)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
elsif none
|
589
|
+
a, b, c, d = ARG[:GRAPH]
|
590
|
+
out << if depth == 0
|
591
|
+
"#{i == items.size - 1 ? d : c}#{b * 4} #{s}"
|
592
|
+
else
|
593
|
+
"#{last && depth == 1 ? ' ' : a}#{' ' * depth}#{j ? d : c}#{b * 3} #{s}"
|
594
|
+
end
|
595
|
+
end
|
596
|
+
done << proj
|
462
597
|
end
|
463
|
-
|
464
|
-
|
598
|
+
end
|
599
|
+
|
600
|
+
def graph_collect(target, data: {})
|
601
|
+
deps = []
|
602
|
+
target.instance_variable_get(:@graph)&.each do |val|
|
603
|
+
next unless (proj = workspace.find(name: val))
|
465
604
|
|
466
|
-
|
605
|
+
deps << proj
|
606
|
+
graph_collect(proj, data: data) if proj.graph? && !data.key?(proj.name)
|
607
|
+
deps += data.fetch(val, [])
|
608
|
+
end
|
609
|
+
data[target.name] = deps.uniq.reject { |proj| proj == target }
|
610
|
+
data
|
467
611
|
end
|
468
612
|
|
469
|
-
def
|
470
|
-
|
613
|
+
def env(key, default = nil, suffix: nil, equals: nil, ignore: nil, strict: false)
|
614
|
+
a = "#{key}_#{@envname}"
|
615
|
+
ret = if suffix
|
616
|
+
ENV.fetch("#{a}_#{suffix}", '')
|
617
|
+
else
|
618
|
+
ignore = ['0'].freeze if ignore.nil? && !strict
|
619
|
+
ENV[a] || (strict ? '' : ENV.fetch(key, ''))
|
620
|
+
end
|
621
|
+
return ret == equals.to_s unless equals.nil?
|
622
|
+
|
623
|
+
ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
|
471
624
|
end
|
472
625
|
|
473
|
-
def session(*cmd, prefix:
|
474
|
-
if (val =
|
626
|
+
def session(*cmd, prefix: cmd.first)
|
627
|
+
if (val = env("#{prefix.upcase}_OPTIONS"))
|
475
628
|
split_escape(val).each { |opt| cmd << fill_option(opt) }
|
476
629
|
end
|
477
630
|
@session = JoinSet.new(cmd)
|
478
631
|
end
|
479
632
|
|
480
|
-
def
|
481
|
-
return cmd unless cmd.respond_to?(:done)
|
633
|
+
def session_done(cmd)
|
634
|
+
return cmd.to_s unless cmd.respond_to?(:done)
|
482
635
|
|
483
636
|
raise_error('no args were added', hint: cmd.first || name) unless cmd.size > 1
|
484
637
|
@session = nil if cmd == @session
|
485
638
|
cmd.done
|
486
639
|
end
|
487
640
|
|
641
|
+
def option(*args, prefix: @session&.first, **kwargs)
|
642
|
+
if prefix
|
643
|
+
args.each do |val|
|
644
|
+
ret = env("#{prefix}_#{val.gsub(/\W/, '_')}".upcase, **kwargs)
|
645
|
+
return ret if ret
|
646
|
+
end
|
647
|
+
end
|
648
|
+
nil
|
649
|
+
end
|
650
|
+
|
488
651
|
def print_item(*val)
|
489
|
-
puts
|
652
|
+
puts if @@print_order > 0 && verbose && !stdin?
|
490
653
|
@@print_order += 1
|
491
654
|
puts val unless val.empty? || (val.size == 1 && val.first.nil?)
|
492
655
|
end
|
@@ -497,7 +660,7 @@ module Squared
|
|
497
660
|
if styles.any? { |s| s.to_s.end_with?('!') }
|
498
661
|
pad = 1
|
499
662
|
elsif !client && styles.size <= 1
|
500
|
-
styles = [
|
663
|
+
styles = %i[bold] + styles
|
501
664
|
end
|
502
665
|
end
|
503
666
|
n = Project.max_width(lines)
|
@@ -516,33 +679,37 @@ module Squared
|
|
516
679
|
out.join("\n")
|
517
680
|
end
|
518
681
|
|
519
|
-
def print_footer(*lines, sub: nil,
|
682
|
+
def print_footer(*lines, sub: nil, reverse: false, right: false, **kwargs)
|
683
|
+
border = kwargs.key?(:border) ? kwargs[:border] : borderstyle
|
520
684
|
n = Project.max_width(lines)
|
521
685
|
sub = as_a(sub)
|
522
686
|
lines.map! do |val|
|
523
|
-
s = val.ljust(n)
|
687
|
+
s = right ? val.rjust(n) : val.ljust(n)
|
524
688
|
sub.each { |h| s = sub_style(s, **h) }
|
525
689
|
s
|
526
690
|
end
|
527
|
-
ret = [sub_style('-' * n, styles: border), *lines]
|
691
|
+
ret = [sub_style('-' * n, styles: border || theme[:border]), *lines]
|
528
692
|
ret.reverse! if reverse
|
529
693
|
ret.join("\n")
|
530
694
|
end
|
531
695
|
|
532
|
-
def format_desc(action, flag, opts = nil, req:
|
696
|
+
def format_desc(action, flag, opts = nil, req: nil, arg: 'opts*')
|
533
697
|
opts = "#{arg}=#{opts.join(',')}" if opts.is_a?(::Array)
|
534
|
-
|
698
|
+
out = [@desc]
|
699
|
+
if flag
|
700
|
+
out << action
|
701
|
+
else
|
535
702
|
flag = action
|
536
|
-
action = ''
|
537
703
|
end
|
538
|
-
req
|
539
|
-
|
704
|
+
req &&= opts ? "#{req}," : "[#{req}]"
|
705
|
+
out << (opts ? "#{flag}[#{req}#{opts}]" : "#{flag}#{req}")
|
706
|
+
message(*out)
|
540
707
|
end
|
541
708
|
|
542
|
-
def format_banner(cmd, banner: true
|
543
|
-
return unless banner
|
709
|
+
def format_banner(cmd, banner: true)
|
710
|
+
return unless banner && ARG[:BANNER]
|
544
711
|
|
545
|
-
if (data = workspace.
|
712
|
+
if (data = workspace.banner_get(*@ref, group: group))
|
546
713
|
client = true
|
547
714
|
else
|
548
715
|
data = { command: true, order: %i[path], styles: theme[:banner], border: theme[:border] }
|
@@ -550,13 +717,62 @@ module Squared
|
|
550
717
|
if verbose
|
551
718
|
out = []
|
552
719
|
out << cmd.sub(/^\S+/, &:upcase) if data[:command]
|
553
|
-
data[:order].each
|
720
|
+
data[:order].each do |val|
|
721
|
+
if val.is_a?(::Array)
|
722
|
+
s = ' '
|
723
|
+
found = false
|
724
|
+
val = val.map do |meth|
|
725
|
+
if meth.is_a?(::String)
|
726
|
+
s = ''
|
727
|
+
meth
|
728
|
+
elsif respond_to?(meth)
|
729
|
+
found = true
|
730
|
+
__send__(meth)
|
731
|
+
end
|
732
|
+
end
|
733
|
+
val = val.compact.join(s)
|
734
|
+
next unless found && !val.empty?
|
735
|
+
elsif (val = __send__(val)).nil?
|
736
|
+
next
|
737
|
+
end
|
738
|
+
out << val.to_s
|
739
|
+
end
|
554
740
|
print_banner(*out, styles: data[:styles], border: data[:border], client: client)
|
555
741
|
elsif multiple && workspace.series.multiple?
|
556
742
|
"## #{__send__(data[:order].first || :path)} ##"
|
557
743
|
end
|
558
744
|
end
|
559
745
|
|
746
|
+
def format_list(items, cmd, type, grep: [], from: nil, each: nil)
|
747
|
+
reg = grep.map { |val| Regexp.new(val) }
|
748
|
+
out = []
|
749
|
+
if (pad = items.size) > 0
|
750
|
+
pad = pad.to_s.size
|
751
|
+
items.each_with_index do |val, i|
|
752
|
+
next unless reg.empty? || reg.any? { |pat| pat.match?(val[0]) }
|
753
|
+
|
754
|
+
out << "#{(i + 1).to_s.rjust(pad)}. #{each ? each.(val) : val[0]}"
|
755
|
+
end
|
756
|
+
end
|
757
|
+
if out.empty?
|
758
|
+
out = ["No #{type} were found:", '']
|
759
|
+
unless grep.empty?
|
760
|
+
i = 0
|
761
|
+
out += grep.map { |s| "#{i += 1}. #{s}" }
|
762
|
+
out << ''
|
763
|
+
end
|
764
|
+
if from
|
765
|
+
out << from
|
766
|
+
pat = /^(#{Regexp.escape(out.last)})(.*)$/
|
767
|
+
end
|
768
|
+
else
|
769
|
+
pat = /^(\s*\d+\.)(.+)$/
|
770
|
+
end
|
771
|
+
sub = [headerstyle]
|
772
|
+
sub << { pat: pat, styles: theme[:active] } if pat
|
773
|
+
emphasize(out, title: task_join(name, cmd), border: borderstyle, sub: sub)
|
774
|
+
end
|
775
|
+
|
560
776
|
def empty_status(msg, title, obj, always: false)
|
561
777
|
"#{msg}#{!always && (!obj || obj == 0 || obj.to_s.empty?) ? '' : message(hint: message(title, obj.to_s))}"
|
562
778
|
end
|
@@ -569,22 +785,22 @@ module Squared
|
|
569
785
|
opts.each { |val| @session << val }
|
570
786
|
end
|
571
787
|
|
572
|
-
def append_nocolor
|
573
|
-
@session <<
|
788
|
+
def append_nocolor(flag = nil)
|
789
|
+
@session << '--no-color' if flag || !ARG[:COLOR] || stdin?
|
574
790
|
end
|
575
791
|
|
576
792
|
def guard_params(action, flag, args: nil, key: nil, pat: nil)
|
577
793
|
if args && key
|
578
|
-
|
794
|
+
val = args[key]
|
795
|
+
return val unless val.nil? || (pat && !val.match?(pat))
|
579
796
|
|
580
797
|
@session = nil
|
581
798
|
raise_error(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
|
582
|
-
elsif args.is_a?(::Array)
|
583
|
-
return unless args.empty?
|
584
|
-
|
799
|
+
elsif args.is_a?(::Array) && args.empty?
|
585
800
|
@session = nil
|
586
|
-
raise_error(action, "#{flag}
|
801
|
+
raise_error(action, "#{flag}+", hint: 'empty')
|
587
802
|
end
|
803
|
+
args
|
588
804
|
end
|
589
805
|
|
590
806
|
def pwd_set(done = nil, &blk)
|
@@ -612,39 +828,27 @@ module Squared
|
|
612
828
|
end
|
613
829
|
end
|
614
830
|
|
615
|
-
def
|
616
|
-
unless
|
617
|
-
|
618
|
-
|
831
|
+
def run_set(cmd, val = nil, opts: nil, **)
|
832
|
+
unless @output[1] == false && !@output[0].nil?
|
833
|
+
if opts == false
|
834
|
+
@output[1] = false
|
835
|
+
elsif opts && opts != true
|
836
|
+
@output[1] = opts
|
837
|
+
end
|
619
838
|
end
|
620
|
-
unless
|
621
|
-
val
|
622
|
-
|
839
|
+
unless @output[2] == false
|
840
|
+
if val.is_a?(::Hash)
|
841
|
+
@output[2] = val
|
842
|
+
elsif val == false
|
843
|
+
@output[2] = false
|
844
|
+
end
|
623
845
|
end
|
624
|
-
val
|
625
|
-
end
|
626
|
-
|
627
|
-
def semmajor(cur, want)
|
628
|
-
(cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[5]
|
629
|
-
end
|
630
|
-
|
631
|
-
def scriptargs
|
632
|
-
{ target: script? ? @output[1] : @output[0], ref: ref, group: group, global: @global }
|
633
|
-
end
|
634
|
-
|
635
|
-
def run_set(cmd, val = nil, *, opts: true, **)
|
636
846
|
@output[0] = cmd
|
637
|
-
@output[1] = if cmd && opts
|
638
|
-
env('BUILD', opts.is_a?(::String) ? opts : nil, suffix: 'OPTS')
|
639
|
-
end
|
640
|
-
if val.is_a?(::Hash)
|
641
|
-
@output[2] = val
|
642
|
-
elsif val == false
|
643
|
-
@output[2] = nil
|
644
|
-
end
|
645
847
|
end
|
646
848
|
|
647
|
-
def script_set(cmd,
|
849
|
+
def script_set(cmd, prod: nil, **)
|
850
|
+
return if @output[1] == false && @output[0].nil?
|
851
|
+
|
648
852
|
@output[0] = nil
|
649
853
|
@output[1] = if @global && cmd.is_a?(::Array)
|
650
854
|
cmd[prod == true ? 1 : 0]
|
@@ -653,16 +857,12 @@ module Squared
|
|
653
857
|
end
|
654
858
|
end
|
655
859
|
|
656
|
-
def
|
657
|
-
Pathname.new(val).absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.
|
860
|
+
def projectpath?(val)
|
861
|
+
Pathname.new(val).absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.start_with?('..')
|
658
862
|
end
|
659
863
|
|
660
|
-
def
|
661
|
-
|
662
|
-
end
|
663
|
-
|
664
|
-
def stdin?
|
665
|
-
pipe == 0
|
864
|
+
def semmajor?(cur, want)
|
865
|
+
(cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[5]
|
666
866
|
end
|
667
867
|
|
668
868
|
def runnable?(val)
|
@@ -676,23 +876,83 @@ module Squared
|
|
676
876
|
end
|
677
877
|
end
|
678
878
|
|
679
|
-
def from_sync?(val)
|
680
|
-
if
|
681
|
-
!workspace.task_defined?(
|
682
|
-
elsif workspace.series.sync?(
|
879
|
+
def from_sync?(*val)
|
880
|
+
if task_invoked?(key = task_join(*val))
|
881
|
+
!workspace.task_defined?(key, 'sync')
|
882
|
+
elsif workspace.series.sync?(task_join(key, 'sync'))
|
683
883
|
true
|
684
884
|
end
|
685
885
|
end
|
686
886
|
|
687
887
|
def invoked_sync?(action, val = nil)
|
688
888
|
return true if !val.nil? || from_sync?(ac = workspace.task_name(action))
|
889
|
+
return val if group && !(val = from_sync?(ac, group)).nil?
|
890
|
+
return val if (base = workspace.find_base(self)) && !(val = from_sync?(ac, base.ref)).nil?
|
689
891
|
|
690
|
-
|
691
|
-
|
892
|
+
if task_invoked?(task_join(name, ac)) && (!task_invoked?(ac) || !workspace.task_defined?(ac, 'sync'))
|
893
|
+
true
|
894
|
+
else
|
895
|
+
val = workspace.series.name_get(action)
|
896
|
+
val == action ? false : invoked_sync?(val)
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
900
|
+
def stdin?
|
901
|
+
pipe == 0
|
902
|
+
end
|
903
|
+
|
904
|
+
def warning?
|
905
|
+
workspace.warning
|
906
|
+
end
|
907
|
+
|
908
|
+
def projectmap(files, parent: false)
|
909
|
+
files = files.select { |val| projectpath?(val) } unless parent
|
910
|
+
files.map { |val| val == '.' ? '.' : shell_quote(basepath(val.strip)) }
|
911
|
+
end
|
912
|
+
|
913
|
+
def semver(val)
|
914
|
+
return val if val[3]
|
915
|
+
|
916
|
+
val[3] = '.'
|
917
|
+
val[4] = '0'
|
918
|
+
unless val[1]
|
919
|
+
val[1] = '.'
|
920
|
+
val[2] = '0'
|
921
|
+
end
|
922
|
+
val
|
923
|
+
end
|
924
|
+
|
925
|
+
def semscan(val)
|
926
|
+
val.scan(SEM_VER).first
|
927
|
+
end
|
692
928
|
|
693
|
-
|
929
|
+
def borderstyle
|
930
|
+
if (data = workspace.banner_get(*@ref, group: group))
|
931
|
+
data[:border]
|
932
|
+
end
|
933
|
+
end
|
934
|
+
|
935
|
+
def headerstyle
|
936
|
+
{ pat: /^(\S+)(\s+)$/, styles: theme[:header] }
|
937
|
+
end
|
938
|
+
|
939
|
+
def scriptargs
|
940
|
+
{ target: script? ? @output[1] : @output[0], ref: ref, group: group, global: @global }
|
941
|
+
end
|
942
|
+
|
943
|
+
def indexdata(val)
|
944
|
+
if (data = /\A\^(\d+)(:.+)?\z/.match(val))
|
945
|
+
[data[1].to_i, data[2] ? data[2][1..-1] : nil]
|
946
|
+
end
|
947
|
+
end
|
948
|
+
|
949
|
+
def indexerror(val, list = nil)
|
950
|
+
raise_error("requested index #{val}", hint: list && "of #{list.size}")
|
694
951
|
end
|
695
952
|
end
|
953
|
+
|
954
|
+
Application.impl_project = Base
|
955
|
+
Application.attr_banner = Common::SymSet.new(%i[name project path ref group parent])
|
696
956
|
end
|
697
957
|
end
|
698
958
|
end
|