squared 0.0.9 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -6
- data/README.ruby.md +145 -47
- data/lib/squared/app.rb +10 -0
- data/lib/squared/common/base.rb +17 -15
- data/lib/squared/common/class.rb +20 -3
- data/lib/squared/common/format.rb +104 -46
- data/lib/squared/common/prompt.rb +38 -0
- data/lib/squared/common/shell.rb +16 -7
- data/lib/squared/common/system.rb +8 -38
- data/lib/squared/common/task.rb +3 -2
- data/lib/squared/common/utils.rb +69 -0
- data/lib/squared/common.rb +2 -0
- data/lib/squared/config.rb +31 -26
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +285 -137
- data/lib/squared/workspace/project/base.rb +459 -178
- data/lib/squared/workspace/project/git.rb +95 -114
- data/lib/squared/workspace/project/node.rb +306 -160
- data/lib/squared/workspace/project/python.rb +45 -19
- data/lib/squared/workspace/project/ruby.rb +156 -127
- data/lib/squared/workspace/project.rb +0 -3
- data/lib/squared/workspace/repo.rb +100 -93
- data/lib/squared/workspace/series.rb +82 -52
- data/lib/squared/workspace.rb +5 -4
- data/lib/squared.rb +1 -11
- metadata +5 -2
@@ -7,14 +7,28 @@ module Squared
|
|
7
7
|
include Format
|
8
8
|
include ::Rake::DSL
|
9
9
|
|
10
|
+
SCRIPT_OBJ = {
|
11
|
+
run: nil,
|
12
|
+
script: nil,
|
13
|
+
dev: nil,
|
14
|
+
prod: nil,
|
15
|
+
global: false,
|
16
|
+
env: false
|
17
|
+
}.freeze
|
18
|
+
private_constant :SCRIPT_OBJ
|
19
|
+
|
10
20
|
class << self
|
11
21
|
def implement(*objs)
|
12
22
|
objs.each do |obj|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
23
|
+
next unless obj < base_project
|
24
|
+
|
25
|
+
impl_project.unshift(obj)
|
26
|
+
obj.tasks&.each { |task| impl_series.add(task, obj) }
|
27
|
+
if (args = obj.batchargs)
|
28
|
+
impl_series.batch(*args)
|
29
|
+
end
|
30
|
+
if (args = obj.aliasargs)
|
31
|
+
impl_series.alias(*args)
|
18
32
|
end
|
19
33
|
end
|
20
34
|
end
|
@@ -23,87 +37,109 @@ module Squared
|
|
23
37
|
if ref && (ret = impl_project.find { |proj| proj.ref == ref.to_sym })
|
24
38
|
ret
|
25
39
|
elsif path
|
26
|
-
impl_project.find { |proj| proj.
|
40
|
+
impl_project.find { |proj| proj.config?(path) }
|
27
41
|
end
|
28
42
|
end
|
29
43
|
|
44
|
+
def baseref
|
45
|
+
base_project.ref
|
46
|
+
end
|
47
|
+
|
30
48
|
def to_s
|
31
49
|
super.to_s.match(/[^:]+$/)[0]
|
32
50
|
end
|
33
51
|
|
34
|
-
attr_reader :impl_project, :
|
52
|
+
attr_reader :impl_project, :attr_banner
|
53
|
+
attr_accessor :impl_series, :base_project
|
35
54
|
end
|
36
55
|
|
37
56
|
@impl_project = []
|
38
|
-
@
|
57
|
+
@attr_banner = SymSet.new(%i[name project path ref group parent version])
|
39
58
|
|
40
|
-
attr_reader :root, :home, :main, :prefix, :series, :
|
41
|
-
attr_accessor :exception, :warning, :pipe, :verbose
|
59
|
+
attr_reader :root, :home, :main, :prefix, :exception, :warning, :pipe, :verbose, :theme, :series, :closed
|
42
60
|
|
43
|
-
def initialize(home = Dir.pwd, *, main: nil, prefix: nil,
|
44
|
-
|
45
|
-
@
|
61
|
+
def initialize(home = Dir.pwd, *, main: nil, prefix: nil, verbose: nil,
|
62
|
+
common: ARG[:COMMON], pipe: ARG[:PIPE], exception: ARG[:FAIL], **)
|
63
|
+
@home = Pathname.new(home).realdirpath
|
46
64
|
@root = @home.parent
|
65
|
+
@main = (main || @home.basename).to_s.freeze
|
47
66
|
@prefix = prefix
|
48
67
|
@series = Application.impl_series.new(self)
|
49
68
|
@project = {}
|
50
69
|
@extensions = []
|
51
|
-
@
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
env: false
|
58
|
-
}
|
59
|
-
@exception = exception.is_a?(String) ? !env(exception, ignore: '0').nil? : exception
|
60
|
-
@pipe = pipe.is_a?(String) ? !env(pipe, ignore: '0').nil? : pipe
|
61
|
-
@verbose = verbose.nil? ? !@pipe : verbose
|
62
|
-
@warning = @verbose
|
63
|
-
if kwargs.fetch(:common, true)
|
70
|
+
@pipe = env_pipe(pipe, (ARG[:OUT] && env(ARG[:OUT])) || 1, root: @home)
|
71
|
+
@exception = env_bool(exception)
|
72
|
+
@verbose = verbose.nil? ? @pipe != 0 : verbose
|
73
|
+
@warning = @verbose != false
|
74
|
+
@closed = false
|
75
|
+
if common
|
64
76
|
@theme = __get__(:theme)[:workspace]
|
65
|
-
|
77
|
+
ARG[:COLOR] = false if @pipe == 0 || @pipe.is_a?(::Pathname)
|
66
78
|
else
|
67
79
|
@theme = {}
|
68
80
|
end
|
69
|
-
@
|
81
|
+
@script = {
|
82
|
+
group: {},
|
83
|
+
ref: {},
|
84
|
+
group!: {},
|
85
|
+
ref!: {}
|
86
|
+
}.freeze
|
87
|
+
@banner = {
|
88
|
+
group: {},
|
89
|
+
ref: {}
|
90
|
+
}.freeze
|
91
|
+
initialize_session
|
70
92
|
end
|
71
93
|
|
72
|
-
def
|
73
|
-
|
74
|
-
return unless
|
94
|
+
def initialize_session
|
95
|
+
@envname = @main.gsub(/[^\w]+/, '_').upcase.freeze
|
96
|
+
return unless @pipe.is_a?(::Pathname)
|
97
|
+
|
98
|
+
bord = '#' * Project.line_width
|
99
|
+
puts bord, format('Session started on %s by %s', Time.now.to_s, @main), bord
|
100
|
+
end
|
101
|
+
|
102
|
+
def build(parallel: [], **kwargs)
|
103
|
+
kwargs[:parallel] = parallel.map(&:to_s)
|
104
|
+
return if @closed || !enabled?
|
75
105
|
|
76
106
|
@project.each_value do |proj|
|
77
107
|
next unless proj.enabled?
|
78
108
|
|
79
109
|
proj.populate(**kwargs)
|
80
|
-
series.
|
110
|
+
series.populate(proj)
|
81
111
|
end
|
82
112
|
|
83
113
|
Application.impl_project.each { |obj| obj.populate(self, **kwargs) }
|
84
114
|
@extensions.each { |ext| __send__(ext, **kwargs) }
|
85
115
|
|
86
|
-
series.
|
116
|
+
series.build(**kwargs)
|
87
117
|
__build__(**kwargs)
|
88
118
|
|
89
119
|
yield self if block_given?
|
120
|
+
@closed = true
|
90
121
|
end
|
91
122
|
|
92
|
-
def with(val, &blk)
|
123
|
+
def with(*val, group: nil, **kwargs, &blk)
|
93
124
|
@group = nil
|
94
125
|
@ref = nil
|
95
|
-
|
126
|
+
@withargs = kwargs.empty? ? nil : kwargs
|
127
|
+
val = [group || kwargs[:ref]].compact.flatten if val.empty?
|
128
|
+
kind = val.first
|
129
|
+
val = kind if val.size == 1
|
130
|
+
case kind
|
131
|
+
when ::String
|
96
132
|
@group = val
|
97
|
-
|
98
|
-
instance_eval(&blk)
|
99
|
-
@group = nil
|
100
|
-
end
|
101
|
-
elsif val.is_a?(::Symbol)
|
133
|
+
when ::Symbol
|
102
134
|
@ref = val
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
135
|
+
else
|
136
|
+
raise_error('group{Symbol} | ref{String}', hint: 'missing') if block_given?
|
137
|
+
end
|
138
|
+
if block_given?
|
139
|
+
instance_eval(&blk)
|
140
|
+
@group = nil
|
141
|
+
@ref = nil
|
142
|
+
@withargs = nil
|
107
143
|
end
|
108
144
|
self
|
109
145
|
end
|
@@ -128,50 +164,105 @@ module Squared
|
|
128
164
|
script_command :test, script, group, ref
|
129
165
|
end
|
130
166
|
|
167
|
+
def log(script, group: @group, ref: @ref)
|
168
|
+
script_command :log, script, group, ref
|
169
|
+
end
|
170
|
+
|
131
171
|
def exclude(base, group: @group, ref: @ref)
|
132
172
|
script_command :exclude, as_a(base, :to_sym).freeze, group, ref
|
133
173
|
end
|
134
174
|
|
135
|
-
def
|
175
|
+
def banner(*args, command: true, styles: nil, border: nil, group: @group, ref: @ref)
|
176
|
+
data = { command: command, order: [], styles: check_style(styles, empty: false), border: check_style(border) }
|
177
|
+
args.each do |meth|
|
178
|
+
if meth.is_a?(::Array)
|
179
|
+
found = false
|
180
|
+
meth = meth.select do |val|
|
181
|
+
case val
|
182
|
+
when ::Symbol
|
183
|
+
found = true
|
184
|
+
Application.attr_banner.include?(val)
|
185
|
+
when ::String
|
186
|
+
true
|
187
|
+
else
|
188
|
+
false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
if !found
|
192
|
+
next
|
193
|
+
elsif meth.size == 1
|
194
|
+
meth = meth.first
|
195
|
+
end
|
196
|
+
elsif !Application.attr_banner.include?(meth = meth.to_sym)
|
197
|
+
next
|
198
|
+
end
|
199
|
+
data[:order] << meth
|
200
|
+
end
|
201
|
+
unless !command && data[:order].empty?
|
202
|
+
if group
|
203
|
+
label = :group
|
204
|
+
items = as_a(group)
|
205
|
+
else
|
206
|
+
label = :ref
|
207
|
+
items = ref ? as_a(ref) : %i[_]
|
208
|
+
end
|
209
|
+
items.each { |val| @banner[label][val.to_sym] = data }
|
210
|
+
end
|
211
|
+
self
|
212
|
+
end
|
213
|
+
|
214
|
+
def add(path, val = nil, **kwargs, &blk)
|
215
|
+
if @withargs
|
216
|
+
data = @withargs.dup
|
217
|
+
data.merge!(kwargs)
|
218
|
+
kwargs = data
|
219
|
+
end
|
136
220
|
ref = if kwargs.key?(:ref)
|
221
|
+
kwargs = kwargs.dup unless @withargs
|
137
222
|
kwargs.delete(:ref)
|
138
|
-
elsif
|
223
|
+
elsif @ref.is_a?(::Symbol)
|
139
224
|
@ref
|
140
225
|
end
|
141
|
-
|
142
|
-
|
226
|
+
if @group.is_a?(::String) && !kwargs.key?(:group)
|
227
|
+
kwargs = kwargs.dup unless @withargs
|
228
|
+
kwargs[:group] = @group
|
229
|
+
end
|
230
|
+
path = root_path(path)
|
231
|
+
val = (val || path.basename).to_s
|
232
|
+
name = val.to_sym
|
233
|
+
index = 0
|
234
|
+
while @project[name]
|
235
|
+
index += 1
|
236
|
+
name = :"#{val}-#{index}"
|
237
|
+
end
|
143
238
|
proj = ((if !ref.is_a?(::Class)
|
144
239
|
Application.find(ref, path: path)
|
145
240
|
elsif ref < Project::Base
|
146
241
|
ref
|
147
|
-
end) || Project::Base).new(
|
148
|
-
@project[name
|
242
|
+
end) || Project::Base).new(self, path, task_name(name), **kwargs)
|
243
|
+
@project[name] = proj
|
149
244
|
__get__(:project)[name] = proj unless kwargs[:private]
|
245
|
+
proj.instance_eval(&blk) if block_given?
|
150
246
|
self
|
151
247
|
end
|
152
248
|
|
153
|
-
def group(
|
154
|
-
root_path(path).children.map do |
|
155
|
-
next unless
|
249
|
+
def group(path, val, override: {}, **kwargs, &blk)
|
250
|
+
root_path(path).children.map do |dir|
|
251
|
+
next unless dir.directory?
|
156
252
|
|
157
|
-
index = 0
|
158
253
|
basename = dir.basename.to_s.to_sym
|
159
|
-
|
160
|
-
index += 1
|
161
|
-
basename = :"#{basename}-#{index}"
|
162
|
-
end
|
163
|
-
[basename, dir, override[basename]]
|
254
|
+
[dir, basename, override[basename]]
|
164
255
|
end
|
165
|
-
.each do |
|
256
|
+
.each do |dir, basename, opts|
|
166
257
|
args = kwargs.dup
|
167
258
|
args.merge!(opts) if opts
|
168
|
-
add(
|
259
|
+
add(dir, basename, group: val, **args, &blk)
|
169
260
|
end
|
170
261
|
self
|
171
262
|
end
|
172
263
|
|
173
264
|
def compose(name, &blk)
|
174
|
-
namespace(task_name(name), &blk)
|
265
|
+
namespace(task_name(name), &blk) if block_given?
|
175
266
|
self
|
176
267
|
end
|
177
268
|
|
@@ -191,49 +282,77 @@ module Squared
|
|
191
282
|
end
|
192
283
|
end
|
193
284
|
end
|
194
|
-
apply_style(data || theme, name,
|
285
|
+
apply_style(data || theme, name, args, empty: empty) unless target && !data
|
195
286
|
self
|
196
287
|
end
|
197
288
|
|
198
|
-
def
|
199
|
-
|
289
|
+
def find(path = nil, name: nil)
|
290
|
+
path = root_path(path) if path
|
291
|
+
ret = @project.find { |_, item| (path && item.path == path) || (name && item.name == name.to_s) }&.last
|
292
|
+
return ret unless block_given?
|
200
293
|
|
201
|
-
|
202
|
-
group.to_sym
|
203
|
-
else
|
204
|
-
:"_#{ref || @ref || ''}"
|
205
|
-
end
|
206
|
-
data = { command: command, order: [], styles: check_style(styles, empty: false), border: check_style(border) }
|
207
|
-
order.flatten.each do |val|
|
208
|
-
case (val = val.to_sym)
|
209
|
-
when :name, :project, :path, :ref, :group
|
210
|
-
data[:order] << val
|
211
|
-
end
|
212
|
-
end
|
213
|
-
@banner[key] = data if command || !data[:order].empty?
|
294
|
+
yield ret if ret
|
214
295
|
self
|
215
296
|
end
|
216
297
|
|
217
|
-
def
|
218
|
-
|
219
|
-
@script[:group][group.to_sym]
|
220
|
-
elsif ref
|
221
|
-
@script[:ref][ref.to_sym]
|
222
|
-
elsif (val = @script[:build])
|
223
|
-
r = @script[:ref][:_]
|
224
|
-
g = @script[:group][:_]
|
225
|
-
args.empty? || (!r && !g) || (r && args.include?(r)) || (g && args.include?(g)) ? [val, @script[:env]] : []
|
226
|
-
else
|
227
|
-
[]
|
228
|
-
end
|
298
|
+
def find_base(obj)
|
299
|
+
Application.impl_project.find { |proj| obj.instance_of?(proj) }
|
229
300
|
end
|
230
301
|
|
231
|
-
def
|
232
|
-
@
|
233
|
-
|
234
|
-
|
302
|
+
def task_name(val, desc: false)
|
303
|
+
ret = @prefix ? task_join(@prefix, val) : val.to_s
|
304
|
+
desc ? ret.split(':').join(ARG[:SPACE]) : ret
|
305
|
+
end
|
306
|
+
|
307
|
+
def task_namespace(val, first: false)
|
308
|
+
return nil unless (ret = val.to_s.split(':')).size > 1
|
235
309
|
|
236
|
-
|
310
|
+
first ? ret.first : task_join(*ret[0..-2])
|
311
|
+
end
|
312
|
+
|
313
|
+
def task_join(*val)
|
314
|
+
val.join(':')
|
315
|
+
end
|
316
|
+
|
317
|
+
def task_resolve(obj, key)
|
318
|
+
tasks = []
|
319
|
+
if (base = task_base?(key))
|
320
|
+
tasks << key if obj.has?(key, baseref)
|
321
|
+
elsif (batch = series.batch_get(key))
|
322
|
+
obj.allref.each do |ref|
|
323
|
+
next unless (data = batch[ref])
|
324
|
+
|
325
|
+
data.each do |val|
|
326
|
+
if (items = task_resolve(obj, val)).empty?
|
327
|
+
tasks.clear
|
328
|
+
break
|
329
|
+
end
|
330
|
+
tasks += items
|
331
|
+
end
|
332
|
+
return tasks unless tasks.empty?
|
333
|
+
end
|
334
|
+
elsif task_extend?(obj, key)
|
335
|
+
tasks << key
|
336
|
+
end
|
337
|
+
ret = []
|
338
|
+
if tasks.empty?
|
339
|
+
return [] if (base && !obj.ref?(baseref)) || !(data = series.alias_get(key))
|
340
|
+
|
341
|
+
obj.allref.each do |ref|
|
342
|
+
next unless (alt = data[ref])
|
343
|
+
|
344
|
+
ret = task_resolve(obj, alt)
|
345
|
+
break unless ret.empty?
|
346
|
+
end
|
347
|
+
else
|
348
|
+
tasks.each do |val|
|
349
|
+
target = task_join(obj.name, series.name_get(val))
|
350
|
+
return [] unless task_defined?(target)
|
351
|
+
|
352
|
+
ret << target
|
353
|
+
end
|
354
|
+
end
|
355
|
+
ret
|
237
356
|
end
|
238
357
|
|
239
358
|
def root_path(*args)
|
@@ -244,24 +363,33 @@ module Squared
|
|
244
363
|
home.join(*args)
|
245
364
|
end
|
246
365
|
|
247
|
-
def
|
248
|
-
|
366
|
+
def script_find(*args)
|
367
|
+
args.reverse_each do |val|
|
368
|
+
next unless val && (ret = val.is_a?(::Symbol) ? @script[:ref!][val] : @script[:group!][val.to_sym])
|
369
|
+
|
370
|
+
return ret
|
371
|
+
end
|
372
|
+
@script[:ref!][:_] || SCRIPT_OBJ
|
249
373
|
end
|
250
374
|
|
251
|
-
def
|
252
|
-
|
253
|
-
|
375
|
+
def script_get(group: nil, ref: nil)
|
376
|
+
if group
|
377
|
+
@script[:group][group.to_sym]
|
378
|
+
elsif ref
|
379
|
+
@script[:ref][ref]
|
380
|
+
end
|
254
381
|
end
|
255
382
|
|
256
|
-
def
|
257
|
-
|
383
|
+
def banner_get(*ref, group: nil)
|
384
|
+
ret = nil
|
385
|
+
return ret if group && (ret = @banner[:group][group.to_sym])
|
258
386
|
|
259
|
-
ret = val
|
260
|
-
|
387
|
+
ref.reverse_each { |val| return ret if (ret = @banner[:ref][val]) }
|
388
|
+
@banner[:ref][:_]
|
261
389
|
end
|
262
390
|
|
263
391
|
def to_s
|
264
|
-
root.to_s
|
392
|
+
(home? ? home : root).to_s
|
265
393
|
end
|
266
394
|
|
267
395
|
def inspect
|
@@ -269,42 +397,55 @@ module Squared
|
|
269
397
|
end
|
270
398
|
|
271
399
|
def enabled?
|
272
|
-
!@extensions.empty? || @project.any?
|
400
|
+
!@extensions.empty? || @project.values.any?(&:enabled?)
|
401
|
+
end
|
402
|
+
|
403
|
+
def task_base?(key)
|
404
|
+
series.base?(key)
|
273
405
|
end
|
274
406
|
|
275
407
|
def task_extend?(obj, key)
|
276
408
|
series.extend?(obj, key)
|
277
409
|
end
|
278
410
|
|
279
|
-
def
|
280
|
-
|
411
|
+
def task_include?(obj, key, ref = nil)
|
412
|
+
task_base?(key) ? obj.has?(key, ref || baseref) : task_extend?(obj, key)
|
281
413
|
end
|
282
414
|
|
283
|
-
def
|
284
|
-
|
415
|
+
def task_defined?(*key)
|
416
|
+
::Rake::Task.task_defined?(key.size == 1 ? key.first : task_join(*key))
|
285
417
|
end
|
286
418
|
|
287
|
-
def
|
288
|
-
|
419
|
+
def dev?(**kwargs)
|
420
|
+
script?(:dev, **kwargs)
|
421
|
+
end
|
289
422
|
|
290
|
-
|
423
|
+
def prod?(**kwargs)
|
424
|
+
script?(:prod, **kwargs)
|
291
425
|
end
|
292
426
|
|
293
|
-
|
427
|
+
def home?
|
428
|
+
!(proj = find(home)).nil? && proj.enabled?
|
429
|
+
end
|
294
430
|
|
295
|
-
def
|
296
|
-
|
297
|
-
|
298
|
-
end
|
299
|
-
return unless series.some?(:build)
|
431
|
+
def baseref
|
432
|
+
Application.baseref
|
433
|
+
end
|
300
434
|
|
301
|
-
|
435
|
+
def invokeargs
|
436
|
+
{ exception: exception, warning: warning }
|
437
|
+
end
|
438
|
+
|
439
|
+
private
|
302
440
|
|
303
|
-
|
304
|
-
|
441
|
+
def __build__(default: nil, **)
|
442
|
+
if default && task_defined?(t = task_name(default)) && !task_defined?(n = ::Rake.application.default_task_name)
|
443
|
+
task n => t
|
444
|
+
end
|
445
|
+
end
|
305
446
|
|
306
|
-
|
307
|
-
|
447
|
+
def puts(*args)
|
448
|
+
puts_oe(*args, pipe: pipe)
|
308
449
|
end
|
309
450
|
|
310
451
|
def script_command(task, val, group, ref)
|
@@ -319,23 +460,30 @@ module Squared
|
|
319
460
|
self
|
320
461
|
end
|
321
462
|
|
322
|
-
def
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
end
|
329
|
-
if pat.is_a?(::Regexp)
|
330
|
-
script = script[state == :prod ? 1 : 0] if script.is_a?(::Array)
|
331
|
-
pat.match?(script)
|
463
|
+
def script_set(data, group: nil, ref: nil)
|
464
|
+
data.freeze
|
465
|
+
if group
|
466
|
+
as_a(group).each { |val| @script[:group!][val.to_sym] = data }
|
467
|
+
elsif ref
|
468
|
+
as_a(ref).each { |val| @script[:ref!][val.to_sym] = data }
|
332
469
|
else
|
333
|
-
|
470
|
+
@script[:ref!][:_] = data
|
334
471
|
end
|
335
472
|
end
|
336
473
|
|
337
|
-
def
|
338
|
-
|
474
|
+
def script_obj
|
475
|
+
SCRIPT_OBJ.dup
|
476
|
+
end
|
477
|
+
|
478
|
+
def script?(state, target: nil, pat: nil, group: nil, ref: baseref, global: false)
|
479
|
+
data = script_find(ref, group)
|
480
|
+
if global
|
481
|
+
target = data[:script] || data[:run] if target.nil?
|
482
|
+
pat = data[state] if pat.nil?
|
483
|
+
end
|
484
|
+
return false if state == :prod && data[:dev] == true && data[:global]
|
485
|
+
|
486
|
+
target && pat.is_a?(::Regexp) ? as_a(target).any? { |val| pat.match?(val) } : pat == true
|
339
487
|
end
|
340
488
|
end
|
341
489
|
end
|