squared 0.1.7 → 0.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
- data/CHANGELOG.md +61 -37
- data/README.md +3 -0
- data/README.ruby.md +126 -46
- data/lib/squared/app.rb +0 -2
- data/lib/squared/common/base.rb +20 -14
- data/lib/squared/common/class.rb +18 -1
- data/lib/squared/common/format.rb +17 -17
- data/lib/squared/common/prompt.rb +1 -1
- data/lib/squared/common/shell.rb +22 -14
- data/lib/squared/common/system.rb +56 -20
- data/lib/squared/common/utils.rb +6 -6
- data/lib/squared/config.rb +130 -82
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +168 -51
- data/lib/squared/workspace/project/base.rb +361 -152
- data/lib/squared/workspace/project/git.rb +731 -281
- data/lib/squared/workspace/project/node.rb +175 -104
- data/lib/squared/workspace/project/python.rb +190 -75
- data/lib/squared/workspace/project/ruby.rb +340 -176
- data/lib/squared/workspace/repo.rb +37 -46
- data/lib/squared/workspace/series.rb +16 -14
- data/squared.gemspec +0 -1
- metadata +3 -20
@@ -14,7 +14,7 @@ module Squared
|
|
14
14
|
include Utils
|
15
15
|
include Rake::DSL
|
16
16
|
|
17
|
-
VAR_SET = %i[parent global envname dependfile theme run script env].freeze
|
17
|
+
VAR_SET = %i[parent global envname dependfile theme run script env pass].freeze
|
18
18
|
SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
|
19
19
|
private_constant :VAR_SET, :SEM_VER
|
20
20
|
|
@@ -50,18 +50,17 @@ module Squared
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
@@tasks = {
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
}
|
53
|
+
(@@tasks = {})[ref] = {
|
54
|
+
'graph' => %i[run print].freeze
|
55
|
+
}.freeze
|
56
|
+
@@task_desc = Rake::TaskManager.record_task_metadata
|
58
57
|
@@print_order = 0
|
59
58
|
|
60
|
-
attr_reader :name, :project, :workspace, :path, :
|
61
|
-
:
|
59
|
+
attr_reader :name, :project, :workspace, :path, :theme, :exception, :pipe, :verbose,
|
60
|
+
:group, :parent, :dependfile
|
62
61
|
|
63
62
|
def initialize(workspace, path, name, *, group: nil, graph: nil, pass: nil, exclude: nil,
|
64
|
-
common: ARG[:COMMON], **kwargs)
|
63
|
+
first: {}, last: {}, error: {}, common: ARG[:COMMON], **kwargs)
|
65
64
|
@path = path
|
66
65
|
@workspace = workspace
|
67
66
|
@name = name.to_s.freeze
|
@@ -72,6 +71,7 @@ module Squared
|
|
72
71
|
@test = kwargs[:test]
|
73
72
|
@copy = kwargs[:copy]
|
74
73
|
@clean = kwargs[:clean]
|
74
|
+
@version = kwargs[:version]
|
75
75
|
@exception = kwargs.key?(:exception) ? env_bool(kwargs[:exception]) : workspace.exception
|
76
76
|
@pipe = kwargs.key?(:pipe) ? env_pipe(kwargs[:pipe]) : workspace.pipe
|
77
77
|
@verbose = kwargs.key?(:verbose) ? kwargs[:verbose] : workspace.verbose
|
@@ -88,8 +88,13 @@ module Squared
|
|
88
88
|
@graph = if graph
|
89
89
|
as_a(graph, workspace.prefix ? ->(val) { workspace.task_name(val).to_sym } : :to_sym).freeze
|
90
90
|
end
|
91
|
-
@pass = (pass ? as_a(pass
|
91
|
+
@pass = (pass ? as_a(pass) : []).freeze
|
92
92
|
@exclude = (exclude ? as_a(exclude, :to_sym) : []).freeze
|
93
|
+
@events = {
|
94
|
+
first: first,
|
95
|
+
last: last,
|
96
|
+
error: error
|
97
|
+
}
|
93
98
|
@envname = @name.gsub(/[^\w]+/, '_').upcase.freeze
|
94
99
|
@desc = (@name.include?(':') ? @name.split(':').join(ARG[:SPACE]) : @name).freeze
|
95
100
|
@parent = nil
|
@@ -115,6 +120,7 @@ module Squared
|
|
115
120
|
@clean = @script[:clean] if @clean.nil?
|
116
121
|
@exclude = @script[:exclude] if @exclude.empty? && @script.key?(:exclude)
|
117
122
|
end
|
123
|
+
initialize_events(ref, **kwargs)
|
118
124
|
initialize_logger(**kwargs)
|
119
125
|
return if @output[0] == false
|
120
126
|
|
@@ -147,6 +153,12 @@ module Squared
|
|
147
153
|
end
|
148
154
|
end
|
149
155
|
|
156
|
+
def initialize_events(ref, **)
|
157
|
+
return unless (events = @workspace.events_get(group: @group, ref: ref))
|
158
|
+
|
159
|
+
events.each { |task, data| data.each { |ev, blk| (@events[ev] ||= {})[task] ||= blk } }
|
160
|
+
end
|
161
|
+
|
150
162
|
def initialize_logger(log: nil, **)
|
151
163
|
return if @log
|
152
164
|
|
@@ -187,17 +199,19 @@ module Squared
|
|
187
199
|
@prod = env_match("#{pre}_PROD", prod)
|
188
200
|
cmd = @output[0]
|
189
201
|
unless cmd == false || cmd.is_a?(Array) || (val = env('BUILD', suffix: 'OPTS')).nil?
|
190
|
-
@output[cmd ? 1 : 3] = shell_split(val,
|
202
|
+
@output[cmd ? 1 : 3] = shell_split(val, join: true)
|
191
203
|
end
|
192
204
|
unless @output[2] == false || (val = env('BUILD', suffix: 'ENV')).nil?
|
193
205
|
begin
|
194
206
|
data = JSON.parse(val)
|
195
207
|
raise_error('invalid JSON object', val, hint: "#{prefix}_ENV") unless data.is_a?(Hash)
|
196
|
-
@output[2] = data
|
197
208
|
rescue StandardError => e
|
198
|
-
log
|
209
|
+
log.warn e
|
210
|
+
else
|
211
|
+
@output[2] = data
|
199
212
|
end
|
200
213
|
end
|
214
|
+
@version = val if (val = env('BUILD', suffix: 'VERSION'))
|
201
215
|
return unless (val = env('BUILD', strict: true))
|
202
216
|
|
203
217
|
@global = false
|
@@ -214,49 +228,37 @@ module Squared
|
|
214
228
|
Base.ref
|
215
229
|
end
|
216
230
|
|
217
|
-
def populate(
|
218
|
-
|
219
|
-
|
220
|
-
next unless workspace.task_include?(self, key)
|
221
|
-
|
222
|
-
s = workspace.series.name_get(key)
|
223
|
-
unless workspace.task_defined?(name, s)
|
224
|
-
desc message(@desc, s)
|
225
|
-
task s do
|
226
|
-
__send__(key)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
next if (items = @children.select { |item| workspace.task_include?(item, key) }).empty?
|
230
|
-
|
231
|
-
desc message(@desc, s, 'workspace')
|
232
|
-
task task_join(s, 'workspace') => items.map { |item| task_join(item.name, s) }
|
233
|
-
end
|
234
|
-
next unless ref?(Base.ref)
|
231
|
+
def populate(keys, **)
|
232
|
+
task_build keys
|
233
|
+
return unless ref?(Base.ref)
|
235
234
|
|
235
|
+
namespace name do
|
236
236
|
@@tasks[Base.ref].each do |action, flags|
|
237
|
+
next if @pass.include?(action)
|
238
|
+
|
237
239
|
namespace action do
|
238
240
|
flags.each do |flag|
|
239
241
|
case action
|
240
|
-
when
|
242
|
+
when 'graph'
|
241
243
|
next unless graph?
|
242
244
|
|
243
245
|
check = lambda do |args|
|
244
246
|
next args if (args = args.to_a).empty?
|
245
247
|
|
246
|
-
|
248
|
+
param_guard(action, flag, args: args.reject { |val| name == val.to_s })
|
247
249
|
end
|
248
250
|
|
249
|
-
|
251
|
+
format_desc action, flag, 'project*'
|
250
252
|
if flag == :run
|
251
|
-
task flag
|
253
|
+
task flag do |_, args|
|
252
254
|
graph check.(args)
|
253
255
|
end
|
254
256
|
else
|
255
|
-
task flag
|
257
|
+
task flag do |_, args|
|
256
258
|
out, done = graph(check.(args), out: [])
|
257
259
|
out.map! do |val|
|
258
260
|
done.each_with_index do |proj, i|
|
259
|
-
next unless
|
261
|
+
next unless Regexp.new(" #{Regexp.escape(proj.name)}(?:@\\d|\\z)") =~ val
|
260
262
|
|
261
263
|
val += " (#{i.succ})"
|
262
264
|
break
|
@@ -277,6 +279,10 @@ module Squared
|
|
277
279
|
end
|
278
280
|
end
|
279
281
|
|
282
|
+
def generate(keys, **)
|
283
|
+
task_build keys
|
284
|
+
end
|
285
|
+
|
280
286
|
def with(**kwargs, &blk)
|
281
287
|
@withargs = kwargs.empty? ? nil : kwargs
|
282
288
|
if block_given?
|
@@ -291,7 +297,7 @@ module Squared
|
|
291
297
|
if val.directory? && !val.empty?
|
292
298
|
true
|
293
299
|
else
|
294
|
-
log
|
300
|
+
log.warn "workspace \"#{val}\" (#{val.empty? ? 'empty' : 'not found'})"
|
295
301
|
false
|
296
302
|
end
|
297
303
|
end
|
@@ -329,7 +335,19 @@ module Squared
|
|
329
335
|
self
|
330
336
|
end
|
331
337
|
|
332
|
-
def
|
338
|
+
def inject(obj, *args, **kwargs, &blk)
|
339
|
+
return self unless enabled?
|
340
|
+
|
341
|
+
out = obj.link(self, *args, **kwargs, &blk) if obj.respond_to?(:link)
|
342
|
+
if !out
|
343
|
+
warn log_message(:warn, 'link not compatible', subject: obj.to_s, hint: name)
|
344
|
+
elsif out.respond_to?(:build)
|
345
|
+
out.build
|
346
|
+
end
|
347
|
+
self
|
348
|
+
end
|
349
|
+
|
350
|
+
def build(*args, from: :build, sync: invoked_sync?('build'), **)
|
333
351
|
if args.empty?
|
334
352
|
cmd, opts, var, flags = @output
|
335
353
|
banner = verbose == 1
|
@@ -343,59 +361,71 @@ module Squared
|
|
343
361
|
when String
|
344
362
|
cmd = "#{cmd} #{opts}"
|
345
363
|
when Array
|
346
|
-
cmd =
|
364
|
+
cmd = cmd.join(' && ')
|
347
365
|
else
|
348
366
|
cmd = [cmd, compose(opts, script: false)].compact.join(' ') unless opts == false || !respond_to?(:compose)
|
349
367
|
end
|
350
368
|
else
|
351
369
|
return unless respond_to?(:compose)
|
352
370
|
|
353
|
-
cmd = compose(opts, flags, script: true)
|
371
|
+
cmd = compose(opts, flags, from: from, script: true)
|
354
372
|
end
|
355
|
-
run(cmd, var, banner: banner, sync: sync)
|
373
|
+
run(cmd, var, from: from, banner: banner, sync: sync)
|
356
374
|
end
|
357
375
|
|
358
376
|
def depend(*, sync: invoked_sync?('depend'), **)
|
359
|
-
|
377
|
+
return unless @depend
|
378
|
+
|
379
|
+
run(@depend, from: :depend, sync: sync)
|
360
380
|
end
|
361
381
|
|
362
382
|
def copy(*, sync: invoked_sync?('copy'), **)
|
363
|
-
|
383
|
+
return unless @copy
|
384
|
+
|
385
|
+
run_s(@copy, from: :copy, sync: sync)
|
364
386
|
end
|
365
387
|
|
366
388
|
def doc(*, sync: invoked_sync?('doc'), **)
|
367
|
-
|
389
|
+
return unless @doc
|
390
|
+
|
391
|
+
build(@doc, from: :doc, sync: sync)
|
368
392
|
end
|
369
393
|
|
370
394
|
def test(*, sync: invoked_sync?('test'), **)
|
371
|
-
|
395
|
+
return unless @test
|
396
|
+
|
397
|
+
build(@test, from: :test, sync: sync)
|
372
398
|
end
|
373
399
|
|
374
|
-
def clean(
|
400
|
+
def clean(*, sync: invoked_sync?('clean'), **)
|
401
|
+
return unless @clean
|
402
|
+
|
403
|
+
on :first, :clean
|
375
404
|
case @clean
|
376
405
|
when String
|
377
|
-
run_s(@clean, sync:
|
406
|
+
run_s(@clean, from: :clean, sync: sync)
|
378
407
|
when Enumerable
|
379
|
-
|
380
|
-
val
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
408
|
+
as_a(@clean).each do |val|
|
409
|
+
if val =~ %r{[\\/]$}
|
410
|
+
dir = Pathname.new(val.to_s)
|
411
|
+
dir = basepath(dir) unless dir.absolute?
|
412
|
+
next unless dir.directory?
|
413
|
+
|
414
|
+
log.warn "rm -rf #{dir}"
|
415
|
+
dir.rmtree
|
385
416
|
else
|
386
|
-
files = val.include?('*') ? Dir[
|
417
|
+
files = val.include?('*') ? Dir[basepath(val)] : [basepath(val)]
|
387
418
|
files.each do |file|
|
388
|
-
next unless File.file?(file)
|
389
|
-
|
390
419
|
begin
|
391
|
-
File.delete(file)
|
420
|
+
File.delete(file) if File.file?(file)
|
392
421
|
rescue StandardError => e
|
393
|
-
log
|
422
|
+
log.error e
|
394
423
|
end
|
395
424
|
end
|
396
425
|
end
|
397
426
|
end
|
398
427
|
end
|
428
|
+
on :last, :clean
|
399
429
|
end
|
400
430
|
|
401
431
|
def graph(start = [], tasks = nil, sync: invoked_sync?('graph'), pass: [], out: nil)
|
@@ -411,9 +441,37 @@ module Squared
|
|
411
441
|
end
|
412
442
|
pass.concat(split_escape(val)) if (val = env('GRAPH_PASS', strict: true))
|
413
443
|
data = graph_collect(self, start)
|
414
|
-
|
415
|
-
|
416
|
-
|
444
|
+
unless out
|
445
|
+
data[name] << self
|
446
|
+
on :first, :graph
|
447
|
+
end
|
448
|
+
begin
|
449
|
+
done = graph_branch(self, data, tasks, out, sync: sync, pass: pass)
|
450
|
+
rescue StandardError => e
|
451
|
+
ret = on(:error, :graph, e)
|
452
|
+
raise unless ret == true
|
453
|
+
end
|
454
|
+
if out
|
455
|
+
[out, done]
|
456
|
+
else
|
457
|
+
on :last, :graph
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
def first(key, *args, **kwargs, &blk)
|
462
|
+
event(:first, key, *args, **kwargs, &blk)
|
463
|
+
end
|
464
|
+
|
465
|
+
def last(key, *args, **kwargs, &blk)
|
466
|
+
event(:last, key, *args, **kwargs, &blk)
|
467
|
+
end
|
468
|
+
|
469
|
+
def error(key, *args, **kwargs, &blk)
|
470
|
+
event(:error, key, *args, **kwargs, &blk)
|
471
|
+
end
|
472
|
+
|
473
|
+
def event(name, key, *args, **kwargs, &blk)
|
474
|
+
(@events[name.to_sym] ||= {})[key.to_sym] = [block_given? ? [blk] + args : args, kwargs]
|
417
475
|
end
|
418
476
|
|
419
477
|
def variable_set(key, *val, **kwargs)
|
@@ -440,11 +498,11 @@ module Squared
|
|
440
498
|
instance_variable_set :"@#{key}", val.first
|
441
499
|
end
|
442
500
|
else
|
443
|
-
log
|
501
|
+
log.warn "variable_set: @#{key} (private)"
|
444
502
|
end
|
445
503
|
end
|
446
504
|
|
447
|
-
def enabled?(ref = nil)
|
505
|
+
def enabled?(ref = nil, **)
|
448
506
|
return false if ref && !ref?(ref)
|
449
507
|
|
450
508
|
path.directory? && !path.empty?
|
@@ -500,7 +558,13 @@ module Squared
|
|
500
558
|
@prod != false && workspace.prod?(pat: @prod, **scriptargs)
|
501
559
|
end
|
502
560
|
|
503
|
-
def
|
561
|
+
def task_include?(key, ref = nil)
|
562
|
+
workspace.task_include?(self, key, ref) && !@pass.include?(key.to_s)
|
563
|
+
end
|
564
|
+
|
565
|
+
def version(*)
|
566
|
+
@version
|
567
|
+
end
|
504
568
|
|
505
569
|
def dependtype(*)
|
506
570
|
@dependindex ? @dependindex.succ : 0
|
@@ -528,6 +592,10 @@ module Squared
|
|
528
592
|
ret
|
529
593
|
end
|
530
594
|
|
595
|
+
def localname
|
596
|
+
workspace.task_localname(name)
|
597
|
+
end
|
598
|
+
|
531
599
|
def inspect
|
532
600
|
"#<#{self.class}: #{name} => #{self}>"
|
533
601
|
end
|
@@ -546,12 +614,13 @@ module Squared
|
|
546
614
|
puts_oe(*args, pipe: pipe)
|
547
615
|
end
|
548
616
|
|
549
|
-
def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, chdir: path, **)
|
617
|
+
def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, chdir: path, from: nil, **)
|
550
618
|
cmd = session_done(cmd)
|
551
|
-
log
|
619
|
+
log.info cmd
|
620
|
+
on :first, from if from
|
552
621
|
begin
|
553
|
-
if cmd
|
554
|
-
log
|
622
|
+
if cmd.match?(/\A[^:]+:[^:]/) && workspace.task_defined?(cmd)
|
623
|
+
log.warn "ENV was discarded: #{var}" if var
|
555
624
|
task_invoke(cmd, exception: exception, warning: warning?)
|
556
625
|
else
|
557
626
|
print_item format_banner(cmd, banner: banner) if sync
|
@@ -559,17 +628,28 @@ module Squared
|
|
559
628
|
shell(*args, chdir: chdir, exception: exception)
|
560
629
|
end
|
561
630
|
rescue StandardError => e
|
562
|
-
log
|
563
|
-
|
631
|
+
log.error e
|
632
|
+
ret = on(:error, from, e) if from
|
633
|
+
raise unless ret == true
|
634
|
+
else
|
635
|
+
on :last, from if from
|
564
636
|
end
|
565
637
|
end
|
566
638
|
|
567
|
-
def run_s(*cmd, env: nil, banner: verbose != false, **kwargs)
|
568
|
-
|
639
|
+
def run_s(*cmd, env: nil, sync: true, banner: verbose != false, from: nil, **kwargs)
|
640
|
+
on :first, from if from
|
641
|
+
begin
|
642
|
+
cmd.each { |val| run(val, env, sync: sync, banner: banner, **kwargs) }
|
643
|
+
rescue StandardError => e
|
644
|
+
ret = on(:error, from, e) if from
|
645
|
+
raise unless ret == true
|
646
|
+
end
|
647
|
+
on :last, from if from
|
569
648
|
end
|
570
649
|
|
571
|
-
def
|
572
|
-
|
650
|
+
def graph_branch(target, data, tasks = nil, out = nil, sync: true, pass: [], done: [], depth: 0, last: false,
|
651
|
+
single: false)
|
652
|
+
tag = ->(proj) { "#{proj.name}#{SEM_VER =~ proj.version ? "@#{proj.version}" : ''}" }
|
573
653
|
check = ->(deps) { deps.reject { |val| done.include?(val) } }
|
574
654
|
dedupe = lambda do |name|
|
575
655
|
next [] unless (ret = data[name])
|
@@ -581,6 +661,7 @@ module Squared
|
|
581
661
|
end
|
582
662
|
ret
|
583
663
|
end
|
664
|
+
start = target.name
|
584
665
|
if depth == 0
|
585
666
|
items = check.(dedupe.(start))
|
586
667
|
single = items.size == 1
|
@@ -589,24 +670,24 @@ module Squared
|
|
589
670
|
end
|
590
671
|
if out
|
591
672
|
a, b, c, d, e = ARG[:GRAPH]
|
673
|
+
f = tag.(target)
|
592
674
|
out << case depth
|
593
675
|
when 0
|
594
|
-
|
676
|
+
f
|
595
677
|
when 1
|
596
678
|
if items.empty?
|
597
|
-
"#{d}#{b * 4} #{
|
679
|
+
"#{d}#{b * 4} #{f}"
|
598
680
|
else
|
599
|
-
"#{last ? d : c}#{b * 3}#{e} #{
|
681
|
+
"#{last ? d : c}#{b * 3}#{e} #{f}"
|
600
682
|
end
|
601
683
|
else
|
602
|
-
"#{single ? ' ' : a}#{' ' * (depth - 1)}#{last ? d : c}#{b * 3}#{items.empty? ? b : e} #{
|
684
|
+
"#{single ? ' ' : a}#{' ' * (depth - 1)}#{last ? d : c}#{b * 3}#{items.empty? ? b : e} #{f}"
|
603
685
|
end
|
604
686
|
end
|
605
687
|
items.each_with_index do |proj, i|
|
606
688
|
next if done.include?(proj)
|
607
689
|
|
608
|
-
|
609
|
-
t = dedupe.(s)
|
690
|
+
t = dedupe.(proj.name)
|
610
691
|
j = if out
|
611
692
|
if i == items.size - 1 || check.(post = items[i + 1..-1]).empty?
|
612
693
|
true
|
@@ -614,35 +695,35 @@ module Squared
|
|
614
695
|
post.reject { |pr| t.include?(pr) }.empty?
|
615
696
|
end
|
616
697
|
end
|
617
|
-
unless start ==
|
618
|
-
|
619
|
-
|
698
|
+
unless start == proj.name || (none = check.(t).empty?)
|
699
|
+
graph_branch(proj, data, tasks, out, sync: sync, pass: pass, done: done, depth: depth.succ,
|
700
|
+
single: single, last: j == true)
|
620
701
|
end
|
621
702
|
if !out
|
622
|
-
|
703
|
+
if !tasks && (script = workspace.script_get(:graph, group: proj.group, ref: proj.allref))
|
623
704
|
group = script[:graph]
|
624
705
|
end
|
625
706
|
(tasks || group || (dev? ? ['build', 'copy'] : ['depend', 'build'])).each do |meth|
|
626
707
|
next if pass.include?(meth)
|
627
708
|
|
628
|
-
if workspace.task_defined?(cmd = task_join(
|
709
|
+
if workspace.task_defined?(cmd = task_join(proj.name, meth))
|
629
710
|
run(cmd, sync: false, banner: false)
|
630
|
-
elsif proj.has?(meth)
|
711
|
+
elsif proj.has?(meth, tasks || group ? nil : workspace.baseref)
|
631
712
|
proj.__send__(meth.to_sym, sync: sync)
|
632
713
|
end
|
633
714
|
end
|
634
715
|
elsif none
|
635
716
|
a, b, c, d = ARG[:GRAPH]
|
636
717
|
out << if depth == 0
|
637
|
-
"#{i == items.size - 1 ? d : c}#{b * 4} #{
|
718
|
+
"#{i == items.size - 1 ? d : c}#{b * 4} #{tag.(proj)}"
|
638
719
|
else
|
639
|
-
|
720
|
+
s = ''.dup
|
640
721
|
k = 0
|
641
722
|
while k < depth
|
642
|
-
|
723
|
+
s += "#{(last && !j) || (j && k > 0 && k == depth - 1) || single ? ' ' : a} "
|
643
724
|
k += 1
|
644
725
|
end
|
645
|
-
|
726
|
+
s + "#{j ? d : c}#{b * 3} #{tag.(proj)}"
|
646
727
|
end
|
647
728
|
end
|
648
729
|
done << proj
|
@@ -653,11 +734,20 @@ module Squared
|
|
653
734
|
def graph_collect(target, start = [], data: {})
|
654
735
|
deps = []
|
655
736
|
(start.empty? ? target.instance_variable_get(:@graph) : start)&.each do |val|
|
656
|
-
|
737
|
+
if (obj = workspace.find(name: val))
|
738
|
+
next unless obj.enabled?
|
657
739
|
|
658
|
-
|
659
|
-
|
660
|
-
|
740
|
+
items = [obj]
|
741
|
+
else
|
742
|
+
items = workspace.find(group: val, ref: val.to_sym)
|
743
|
+
end
|
744
|
+
items.each do |proj|
|
745
|
+
graph_collect(proj, data: data) if proj.graph? && !data.key?(proj.name)
|
746
|
+
next if (objs = data.fetch(proj.name, [])).include?(target)
|
747
|
+
|
748
|
+
deps << proj
|
749
|
+
deps += objs
|
750
|
+
end
|
661
751
|
end
|
662
752
|
data[target.name] = deps.uniq.reject { |proj| proj == target }
|
663
753
|
data
|
@@ -678,16 +768,22 @@ module Squared
|
|
678
768
|
ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
|
679
769
|
end
|
680
770
|
|
681
|
-
def session(*cmd, prefix: cmd.first)
|
682
|
-
prefix =
|
683
|
-
if (val =
|
684
|
-
|
771
|
+
def session(*cmd, prefix: cmd.first, main: true, options: true)
|
772
|
+
prefix = prefix.to_s.upcase
|
773
|
+
if (val = PATH[prefix] || PATH[prefix.to_sym])
|
774
|
+
cmd[0] = shell_quote(val, force: false)
|
685
775
|
end
|
686
|
-
|
776
|
+
split_escape(val).each { |opt| cmd << fill_option(opt) } if options && (val = env("#{prefix}_OPTIONS"))
|
777
|
+
ret = JoinSet.new(cmd.flatten(1))
|
778
|
+
main ? @session = ret : ret
|
779
|
+
end
|
780
|
+
|
781
|
+
def session_output(*cmd, **kwargs)
|
782
|
+
session(*cmd, main: false, options: false, **kwargs)
|
687
783
|
end
|
688
784
|
|
689
785
|
def session_done(cmd)
|
690
|
-
return cmd
|
786
|
+
return cmd unless cmd.respond_to?(:done)
|
691
787
|
|
692
788
|
raise_error('no args were added', hint: cmd.first || name) unless cmd.size > 1
|
693
789
|
@session = nil if cmd == @session
|
@@ -697,13 +793,47 @@ module Squared
|
|
697
793
|
def option(*args, prefix: @session&.first, **kwargs)
|
698
794
|
if prefix
|
699
795
|
args.each do |val|
|
700
|
-
ret = env("#{
|
796
|
+
ret = env("#{prefix}_#{val.gsub(/\W/, '_')}".upcase, **kwargs)
|
701
797
|
return ret if ret
|
702
798
|
end
|
703
799
|
end
|
704
800
|
nil
|
705
801
|
end
|
706
802
|
|
803
|
+
def option_partition(opts, list, target: @session, no: [], first: false, pass: ['='])
|
804
|
+
out = []
|
805
|
+
bare = []
|
806
|
+
reg, list = list.partition do |val|
|
807
|
+
next unless (n = val.index('='))
|
808
|
+
|
809
|
+
bare << val[0..n - 1] if val.end_with?('?')
|
810
|
+
true
|
811
|
+
end
|
812
|
+
list += bare
|
813
|
+
no = no.map { |val| (n = val.index('=')) ? val[0..n - 1] : val }
|
814
|
+
found = false
|
815
|
+
opts.each do |opt|
|
816
|
+
next out << opt if found
|
817
|
+
|
818
|
+
if list.include?(opt)
|
819
|
+
target << (opt.size == 1 ? "-#{opt}" : "--#{opt}")
|
820
|
+
elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
|
821
|
+
target << "--no-#{name}"
|
822
|
+
else
|
823
|
+
out << opt
|
824
|
+
found = true if first && pass.none? { |val| opt.include?(val) }
|
825
|
+
end
|
826
|
+
end
|
827
|
+
pat = Regexp.new("^(#{reg.map { |val| val[0..val.index('=') - 1] }.join('|')})=(.+)$")
|
828
|
+
[out, pat]
|
829
|
+
end
|
830
|
+
|
831
|
+
def option_clear(params, target: @session, **kwargs)
|
832
|
+
kwargs[:subject] ||= target&.first
|
833
|
+
kwargs[:hint] ||= 'not used'
|
834
|
+
warn log_message(:warn, params.join(', '), **kwargs) unless params.empty?
|
835
|
+
end
|
836
|
+
|
707
837
|
def print_item(*val)
|
708
838
|
puts if @@print_order > 0 && verbose && !stdin?
|
709
839
|
@@print_order += 1
|
@@ -716,7 +846,7 @@ module Squared
|
|
716
846
|
if styles.any? { |s| s.to_s.end_with?('!') }
|
717
847
|
pad = 1
|
718
848
|
elsif !client && styles.size <= 1
|
719
|
-
styles =
|
849
|
+
styles = [:bold] + styles
|
720
850
|
end
|
721
851
|
end
|
722
852
|
n = Project.max_width(lines)
|
@@ -749,32 +879,33 @@ module Squared
|
|
749
879
|
ret.join("\n")
|
750
880
|
end
|
751
881
|
|
752
|
-
def format_desc(action, flag, opts = nil,
|
753
|
-
return unless
|
882
|
+
def format_desc(action, flag, opts = nil, **kwargs)
|
883
|
+
return unless @@task_desc
|
754
884
|
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
out << action
|
759
|
-
else
|
760
|
-
flag = action
|
761
|
-
end
|
762
|
-
req &&= opts ? "#{req}," : "[#{req}]"
|
763
|
-
out << (opts ? "#{flag}[#{req}#{opts}]" : "#{flag}#{req}")
|
764
|
-
message(*out)
|
885
|
+
ret = [@desc, action]
|
886
|
+
ret << flag if flag
|
887
|
+
workspace.format_desc(ret, opts, **kwargs)
|
765
888
|
end
|
766
889
|
|
767
890
|
def format_banner(cmd, banner: true)
|
768
891
|
return unless banner && ARG[:BANNER]
|
769
892
|
|
770
893
|
if (data = workspace.banner_get(*@ref, group: group))
|
894
|
+
return if data.empty?
|
895
|
+
|
771
896
|
client = true
|
772
897
|
else
|
773
|
-
data = { command: true, order:
|
898
|
+
data = { command: true, order: [:path], styles: theme[:banner], border: theme[:border] }
|
774
899
|
end
|
775
900
|
if verbose
|
776
901
|
out = []
|
777
|
-
|
902
|
+
if data[:command]
|
903
|
+
if /\A(?:"((?:[^"]|(?<=\\)")+)"|'((?:[^']|(?<=\\)')+)'|(\S+)) /.match(cmd)
|
904
|
+
path = $3 || $2 || $1
|
905
|
+
cmd = cmd.sub(path, File.basename(path).upcase)
|
906
|
+
end
|
907
|
+
out << cmd
|
908
|
+
end
|
778
909
|
data[:order].each do |val|
|
779
910
|
if val.is_a?(Array)
|
780
911
|
s = ' '
|
@@ -804,14 +935,15 @@ module Squared
|
|
804
935
|
def format_list(items, cmd, type, grep: [], from: nil, each: nil)
|
805
936
|
reg = grep.map { |val| Regexp.new(val) }
|
806
937
|
out = []
|
807
|
-
|
808
|
-
pad =
|
938
|
+
unless items.empty?
|
939
|
+
pad = items.size.to_s.size
|
809
940
|
items.each_with_index do |val, i|
|
810
|
-
next unless reg.empty? || reg.any? { |pat|
|
941
|
+
next unless reg.empty? || reg.any? { |pat| val[0] =~ pat }
|
811
942
|
|
812
943
|
out << "#{(i + 1).to_s.rjust(pad)}. #{each ? each.(val) : val[0]}"
|
813
944
|
end
|
814
945
|
end
|
946
|
+
sub = [headerstyle]
|
815
947
|
if out.empty?
|
816
948
|
out = ["No #{type} were found:", '']
|
817
949
|
unless grep.empty?
|
@@ -821,56 +953,83 @@ module Squared
|
|
821
953
|
end
|
822
954
|
if from
|
823
955
|
out << from
|
824
|
-
pat = /\A(#{Regexp.escape(
|
956
|
+
pat = /\A(#{Regexp.escape(from)})(.*)\z/
|
825
957
|
end
|
826
958
|
else
|
827
|
-
pat = /\A(\s*\d+\.)(.+)\z/
|
959
|
+
pat = /\A(\s*\d+\.)(.+)\z/
|
960
|
+
unless grep.empty?
|
961
|
+
footer = "#{out.size} found"
|
962
|
+
sub << { pat: /\A(\d+)( .+)\z/, styles: theme[:inline] }
|
963
|
+
end
|
828
964
|
end
|
829
|
-
sub = [headerstyle]
|
830
965
|
sub << { pat: pat, styles: theme[:active] } if pat
|
831
|
-
emphasize(out, title: task_join(name, cmd), border: borderstyle, sub: sub)
|
966
|
+
emphasize(out, title: task_join(name, cmd), border: borderstyle, sub: sub, footer: footer, right: true)
|
832
967
|
end
|
833
968
|
|
834
969
|
def empty_status(msg, title, obj, always: false)
|
835
970
|
"#{msg}#{!always && (!obj || obj == 0 || obj.to_s.empty?) ? '' : message(hint: message(title, obj.to_s))}"
|
836
971
|
end
|
837
972
|
|
838
|
-
def append_repeat(flag, opts)
|
839
|
-
opts.each { |val|
|
973
|
+
def append_repeat(flag, opts, target: @session)
|
974
|
+
opts.each { |val| target << shell_option(flag, val, quote: true) }
|
840
975
|
end
|
841
976
|
|
842
|
-
def append_value(opts, delim: false, escape: true)
|
843
|
-
|
844
|
-
|
977
|
+
def append_value(opts, target: @session, delim: false, escape: true)
|
978
|
+
return if opts.empty?
|
979
|
+
|
980
|
+
target << '--' if delim
|
981
|
+
opts.each { |val| target << (escape ? shell_escape(val) : shell_quote(val)) }
|
845
982
|
end
|
846
983
|
|
847
|
-
def
|
984
|
+
def append_hash(opts, target: @session)
|
985
|
+
out = target.to_s
|
986
|
+
opts.each do |key, val|
|
987
|
+
key = key.to_s
|
988
|
+
key = "--#{key}" unless key[0] == '-'
|
989
|
+
next if out =~ Regexp.new(" #{key}(?: |=|$)")
|
990
|
+
|
991
|
+
case val
|
992
|
+
when String
|
993
|
+
append_repeat(key, [val], target: target)
|
994
|
+
when Array
|
995
|
+
append_repeat(key, val, target: target)
|
996
|
+
when Numeric
|
997
|
+
target << (key + (key.start_with?('--') ? '=' : '') + val)
|
998
|
+
when false
|
999
|
+
target << key.sub(/^--(?!no-)/, '--no-')
|
1000
|
+
else
|
1001
|
+
target << key
|
1002
|
+
end
|
1003
|
+
end
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
def append_first(list, target: @session, flag: true, equals: false, quote: false, escape: true, **kwargs)
|
848
1007
|
list.each do |opt|
|
849
1008
|
next unless (val = option(opt, **kwargs))
|
850
1009
|
|
851
|
-
return
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
1010
|
+
return target << (if flag
|
1011
|
+
shell_option(opt, equals ? val : nil, quote: quote, escape: escape)
|
1012
|
+
else
|
1013
|
+
shell_quote(val)
|
1014
|
+
end)
|
856
1015
|
end
|
857
1016
|
end
|
858
1017
|
|
859
|
-
def append_option(list, equals: false, quote: false, **kwargs)
|
1018
|
+
def append_option(list, target: @session, equals: false, quote: false, escape: true, **kwargs)
|
860
1019
|
list.each do |flag|
|
861
1020
|
next unless (val = option(flag, **kwargs))
|
862
1021
|
|
863
|
-
|
1022
|
+
target << shell_option(flag, equals ? val : nil, quote: quote, escape: escape)
|
864
1023
|
end
|
865
1024
|
end
|
866
1025
|
|
867
|
-
def append_nocolor(
|
868
|
-
|
1026
|
+
def append_nocolor(target: @session)
|
1027
|
+
target << '--no-color' if !ARG[:COLOR] || stdin? || option('no-color', ignore: false)
|
869
1028
|
end
|
870
1029
|
|
871
|
-
def
|
1030
|
+
def param_guard(action, flag, args: nil, key: nil, pat: nil)
|
872
1031
|
if args && key
|
873
|
-
val = args
|
1032
|
+
val = args[key]
|
874
1033
|
return val unless val.nil? || (pat && !val.match?(pat))
|
875
1034
|
|
876
1035
|
@session = nil
|
@@ -919,17 +1078,48 @@ module Squared
|
|
919
1078
|
ret && !ret.empty? ? ret : [val]
|
920
1079
|
end
|
921
1080
|
|
922
|
-
def
|
1081
|
+
def colormap(val)
|
1082
|
+
val.compact.map { |s| color(s) }.flatten
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
def on(event, action, *args, **kwargs)
|
1086
|
+
return unless (obj = @events[event][action])
|
1087
|
+
|
1088
|
+
if obj.is_a?(Array) && obj[1].is_a?(Hash)
|
1089
|
+
opts = kwargs.empty? ? obj[1] : obj[1].merge(kwargs)
|
1090
|
+
target = obj[0]
|
1091
|
+
else
|
1092
|
+
opts = kwargs
|
1093
|
+
target = obj
|
1094
|
+
end
|
1095
|
+
as_a(target, flat: true).each do |cmd|
|
1096
|
+
case cmd
|
1097
|
+
when Proc, Method
|
1098
|
+
cmd.call(*args, **opts)
|
1099
|
+
when String
|
1100
|
+
run_s(cmd, **opts)
|
1101
|
+
end
|
1102
|
+
end
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
def pwd_set(done = nil, pass: false, from: nil, &blk)
|
923
1106
|
pwd = Pathname.pwd
|
924
1107
|
if block_given?
|
925
|
-
|
926
|
-
|
1108
|
+
begin
|
1109
|
+
if path == pwd || pass == true || (pass.is_a?(String) && semscan(pass).join >= RUBY_VERSION)
|
1110
|
+
ret = instance_eval(&blk)
|
1111
|
+
else
|
1112
|
+
Dir.chdir(path)
|
1113
|
+
ret = instance_eval(&blk)
|
1114
|
+
Dir.chdir(pwd)
|
1115
|
+
end
|
1116
|
+
rescue StandardError => e
|
1117
|
+
log.error e
|
1118
|
+
ret = on(:error, from, e) if from
|
1119
|
+
raise if exception && ret != true
|
927
1120
|
else
|
928
|
-
|
929
|
-
ret = instance_eval(&blk)
|
930
|
-
Dir.chdir(pwd)
|
1121
|
+
ret
|
931
1122
|
end
|
932
|
-
ret
|
933
1123
|
elsif @pwd == pwd
|
934
1124
|
@pwd = nil
|
935
1125
|
pwd unless done
|
@@ -974,9 +1164,28 @@ module Squared
|
|
974
1164
|
end
|
975
1165
|
end
|
976
1166
|
|
1167
|
+
def task_build(keys)
|
1168
|
+
namespace name do
|
1169
|
+
keys.each do |key|
|
1170
|
+
next unless workspace.task_include?(self, key)
|
1171
|
+
|
1172
|
+
action = workspace.series.name_get(key)
|
1173
|
+
unless @pass.include?(key.to_s) || workspace.task_defined?(name, action)
|
1174
|
+
workspace.task_desc(@desc, action)
|
1175
|
+
task action do
|
1176
|
+
__send__(key)
|
1177
|
+
end
|
1178
|
+
end
|
1179
|
+
next if (items = @children.select { |item| item.task_include?(key) }).empty?
|
1180
|
+
|
1181
|
+
workspace.task_desc(@desc, action, 'workspace')
|
1182
|
+
task task_join(action, 'workspace') => items.map { |item| task_join(item.name, action) }
|
1183
|
+
end
|
1184
|
+
end
|
1185
|
+
end
|
1186
|
+
|
977
1187
|
def projectpath?(val)
|
978
|
-
val
|
979
|
-
val.absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.start_with?(File.join('..', ''))
|
1188
|
+
Pathname.new(val).absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.start_with?('..')
|
980
1189
|
end
|
981
1190
|
|
982
1191
|
def semmajor?(cur, want)
|
@@ -1003,7 +1212,7 @@ module Squared
|
|
1003
1212
|
end
|
1004
1213
|
|
1005
1214
|
def invoked_sync?(action, val = nil)
|
1006
|
-
return true if
|
1215
|
+
return true if val || from_sync?(ac = workspace.task_name(action))
|
1007
1216
|
return val if group && !(val = from_sync?(ac, group)).nil?
|
1008
1217
|
return val if (base = workspace.find_base(self)) && !(val = from_sync?(ac, base.ref)).nil?
|
1009
1218
|
|
@@ -1011,7 +1220,7 @@ module Squared
|
|
1011
1220
|
true
|
1012
1221
|
else
|
1013
1222
|
val = workspace.series.name_get(action)
|
1014
|
-
val
|
1223
|
+
val != action && invoked_sync?(val)
|
1015
1224
|
end
|
1016
1225
|
end
|
1017
1226
|
|