squared 0.0.1 → 0.0.3
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.md +5 -5
- data/README.ruby.md +51 -16
- data/lib/squared/common/class.rb +6 -0
- data/lib/squared/common/format.rb +80 -24
- data/lib/squared/common/shell.rb +9 -1
- data/lib/squared/common/system.rb +4 -2
- data/lib/squared/common/task.rb +1 -1
- data/lib/squared/common.rb +38 -16
- data/lib/squared/config.rb +139 -85
- data/lib/squared/repo/project/base.rb +185 -102
- data/lib/squared/repo/project/git.rb +140 -53
- data/lib/squared/repo/project/node.rb +206 -123
- data/lib/squared/repo/project/python.rb +48 -29
- data/lib/squared/repo/project/ruby.rb +77 -68
- data/lib/squared/repo/project.rb +0 -30
- data/lib/squared/repo/workspace.rb +196 -122
- data/lib/squared/repo.rb +3 -3
- data/lib/squared/version.rb +1 -1
- metadata +2 -2
@@ -1,93 +1,139 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
|
+
require 'date'
|
4
5
|
|
5
6
|
module Squared
|
6
7
|
module Repo
|
7
8
|
module Project
|
8
9
|
class Base
|
9
10
|
include Common
|
10
|
-
include Shell
|
11
11
|
include System
|
12
|
+
include Shell
|
12
13
|
include Task
|
13
14
|
include ::Rake::DSL
|
14
15
|
extend Forwardable
|
15
16
|
|
16
17
|
class << self
|
18
|
+
include Common::Task
|
19
|
+
include ::Rake::DSL
|
20
|
+
|
21
|
+
def populate(*); end
|
22
|
+
|
17
23
|
def tasks
|
18
24
|
[].freeze
|
19
25
|
end
|
20
26
|
|
27
|
+
def as_path(val)
|
28
|
+
return val if val.is_a?(::Pathname)
|
29
|
+
|
30
|
+
val.is_a?(::String) ? Pathname.new(val) : nil
|
31
|
+
end
|
32
|
+
|
21
33
|
def to_s
|
22
|
-
|
34
|
+
/[^:]+$/.match(super.to_s)[0]
|
23
35
|
end
|
24
36
|
|
25
37
|
def to_sym
|
26
|
-
|
38
|
+
to_s.downcase.to_sym
|
27
39
|
end
|
28
40
|
end
|
29
41
|
|
30
42
|
@@print_order = 0
|
31
43
|
@@tasks = {}
|
32
44
|
|
33
|
-
|
45
|
+
alias __warn__ warn
|
46
|
+
|
47
|
+
attr_reader :name, :project, :workspace, :group, :path, :logger, :theme
|
48
|
+
attr_accessor :warning
|
34
49
|
|
35
50
|
protected :logger
|
36
51
|
|
37
|
-
def_delegators :logger, :log,
|
52
|
+
def_delegators :logger, :log, :<<, :debug, :info, :warn, :error, :fatal, :unknown
|
38
53
|
|
39
|
-
def initialize(name,
|
54
|
+
def initialize(name, path, workspace, *, group: nil, log: nil, common: true, **kwargs)
|
40
55
|
@name = name.to_s
|
41
|
-
@path = workspace.root_path(
|
56
|
+
@path = workspace.root_path(path.to_s)
|
42
57
|
@project = @path.basename.to_s
|
43
58
|
@workspace = workspace
|
59
|
+
@group = group&.to_s
|
44
60
|
@depend = kwargs[:depend]
|
45
61
|
@doc = kwargs[:doc]
|
46
|
-
@
|
47
|
-
|
48
|
-
opts = env('BUILD', strict: true)
|
49
|
-
raise ArgumentError, message("BUILD_#{name.to_s.upcase}", opts) if opts && run.is_a?(::Array)
|
50
|
-
|
51
|
-
@output = [run, opts]
|
62
|
+
@test = kwargs[:test]
|
63
|
+
@output = [kwargs[:run], nil]
|
52
64
|
@copy = kwargs[:copy]
|
53
65
|
@clean = kwargs[:clean]
|
54
|
-
|
66
|
+
@theme = if common
|
67
|
+
workspace.theme
|
68
|
+
else
|
69
|
+
__get__(:theme)[:project][to_sym] ||= {}
|
70
|
+
end
|
71
|
+
@warning = workspace.warning
|
55
72
|
log = { file: log } unless log.is_a?(::Hash)
|
56
73
|
if (logfile = env('LOG_FILE')).nil? && (auto = env('LOG_AUTO'))
|
57
|
-
require 'date'
|
58
74
|
logfile = case auto
|
59
75
|
when 'y', 'year'
|
60
|
-
"#{name}-#{Date.today.year}.log"
|
76
|
+
"#{@name}-#{Date.today.year}.log"
|
61
77
|
when 'm', 'month'
|
62
|
-
"#{name}-#{Date.today.strftime('%Y-%m')}.log"
|
78
|
+
"#{@name}-#{Date.today.strftime('%Y-%m')}.log"
|
63
79
|
when 'd', 'day', '1'
|
64
|
-
"#{name}-#{Date.today}.log"
|
65
|
-
else
|
66
|
-
log[:file]
|
80
|
+
"#{@name}-#{Date.today}.log"
|
67
81
|
end
|
68
|
-
else
|
69
|
-
logfile = log[:file]
|
70
82
|
end
|
71
|
-
if
|
72
|
-
logfile
|
83
|
+
if logfile ||= log[:file]
|
84
|
+
logfile = Date.today.strftime(logfile)
|
85
|
+
logfile = (dir = env('LOG_DIR')) ? Pathname.new(dir).join(logfile) : Pathname.new(logfile)
|
86
|
+
begin
|
87
|
+
logfile.realdirpath
|
88
|
+
rescue StandardError => e
|
89
|
+
logfile = nil
|
90
|
+
__warn__ e if @warning
|
91
|
+
end
|
73
92
|
end
|
74
|
-
@logger = Logger.new(logfile, level: env('LOG_LEVEL') || log[:level] || Logger::INFO)
|
75
|
-
|
76
|
-
|
93
|
+
@logger = Logger.new(logfile, progname: @name, level: env('LOG_LEVEL') || log[:level] || Logger::INFO)
|
94
|
+
end
|
95
|
+
|
96
|
+
def initialize_build(ref, **kwargs)
|
97
|
+
initialize_script(ref)
|
98
|
+
if (val = env('BUILD', strict: true))
|
99
|
+
@output[0] = val
|
100
|
+
elsif @script && @output[0] != false
|
101
|
+
@output[0] ||= @script[:run]
|
102
|
+
end
|
103
|
+
if env('BUILD', suffix: 'DEV', equals: '0')
|
104
|
+
@dev = false
|
105
|
+
else
|
106
|
+
@dev = kwargs.delete(:dev)
|
107
|
+
if env('BUILD', suffix: 'DEV')
|
108
|
+
@dev = true
|
109
|
+
elsif @dev.nil?
|
110
|
+
@dev = workspace.dev?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def initialize_script(ref)
|
116
|
+
return unless (script = workspace.script(group: group, ref: ref))
|
117
|
+
|
118
|
+
@depend = script[:depend] if @depend.nil?
|
119
|
+
@doc = script[:doc] if @doc.nil?
|
120
|
+
@test = script[:test] if @test.nil?
|
121
|
+
@clean = script[:clean] if @clean.nil?
|
122
|
+
@script = script
|
77
123
|
end
|
78
124
|
|
79
125
|
def populate(*)
|
80
|
-
namespace
|
81
|
-
|
126
|
+
namespace name do
|
127
|
+
workspace.series.each_key do |key|
|
82
128
|
case key
|
83
|
-
when :build, :refresh, :depend, :outdated, :doc, :copy, :clean
|
129
|
+
when :build, :refresh, :depend, :outdated, :doc, :test, :copy, :clean
|
84
130
|
next unless has?(key)
|
85
131
|
else
|
86
|
-
next unless
|
132
|
+
next unless workspace.task_defined?(self, key)
|
87
133
|
end
|
88
|
-
desc message(
|
134
|
+
desc message(name, key)
|
89
135
|
task key do
|
90
|
-
|
136
|
+
__send__(key)
|
91
137
|
end
|
92
138
|
end
|
93
139
|
end
|
@@ -114,12 +160,12 @@ module Squared
|
|
114
160
|
cmd = compose(opts)
|
115
161
|
banner = env('REPO_BUILD') == 'verbose'
|
116
162
|
end
|
117
|
-
run(cmd, exception:
|
163
|
+
run(cmd, exception: workspace.exception, banner: banner)
|
118
164
|
end
|
119
165
|
|
120
166
|
def refresh(*)
|
121
167
|
build
|
122
|
-
key = "#{
|
168
|
+
key = "#{name}:copy"
|
123
169
|
if ::Rake::Task.task_defined?(key)
|
124
170
|
invoke key
|
125
171
|
else
|
@@ -128,82 +174,91 @@ module Squared
|
|
128
174
|
end
|
129
175
|
|
130
176
|
def depend(*)
|
131
|
-
run(@depend, exception:
|
177
|
+
run(@depend, exception: workspace.exception) if @depend
|
178
|
+
end
|
179
|
+
|
180
|
+
def copy(*)
|
181
|
+
run_s @copy
|
132
182
|
end
|
133
183
|
|
134
184
|
def doc
|
135
185
|
build @doc if @doc
|
136
186
|
end
|
137
187
|
|
138
|
-
def
|
139
|
-
|
188
|
+
def test
|
189
|
+
build @test if @test
|
140
190
|
end
|
141
191
|
|
142
192
|
def clean
|
143
|
-
return
|
144
|
-
|
145
|
-
@clean&.each do |path|
|
146
|
-
path = path.to_s
|
147
|
-
if %r{[\\/]$}.match?(path)
|
148
|
-
dir = Pathname.new(path)
|
149
|
-
dir = base_path(dir) unless dir.absolute?
|
150
|
-
next unless dir.directory?
|
193
|
+
return unless @clean
|
151
194
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
195
|
+
if @clean.is_a?(::String)
|
196
|
+
run_s @clean
|
197
|
+
else
|
198
|
+
@clean.each do |val|
|
199
|
+
if (val = val.to_s).match?(%r{[\\/]$})
|
200
|
+
dir = Pathname.new(val)
|
201
|
+
dir = base_path(dir) unless dir.absolute?
|
202
|
+
next unless dir.directory?
|
203
|
+
|
204
|
+
warn "rm -rf #{dir}"
|
205
|
+
dir.rmtree(verbose: true)
|
206
|
+
else
|
207
|
+
files = val.include?('*') ? Dir[base_path(val)] : [base_path(val)]
|
208
|
+
files.each do |file|
|
209
|
+
begin
|
210
|
+
File.delete(file) if File.file?(file)
|
211
|
+
rescue StandardError => e
|
212
|
+
error e
|
213
|
+
end
|
161
214
|
end
|
162
215
|
end
|
163
216
|
end
|
164
217
|
end
|
165
218
|
end
|
166
219
|
|
167
|
-
def
|
168
|
-
|
220
|
+
def base_path(*args)
|
221
|
+
path.join(*args)
|
169
222
|
end
|
170
223
|
|
171
|
-
def
|
172
|
-
|
224
|
+
def inspect
|
225
|
+
"#<#{self.class}: #{name} => #{self}>"
|
173
226
|
end
|
174
227
|
|
175
228
|
def to_s
|
176
|
-
|
229
|
+
path.to_s
|
177
230
|
end
|
178
231
|
|
179
232
|
def to_sym
|
180
|
-
|
233
|
+
name.to_sym
|
181
234
|
end
|
182
235
|
|
183
236
|
def enabled?
|
184
|
-
|
237
|
+
path.directory? && !path.empty?
|
185
238
|
end
|
186
239
|
|
187
240
|
def has?(method)
|
188
|
-
respond_to?(m = :"#{method}?") &&
|
241
|
+
respond_to?(m = :"#{method}?") && __send__(m)
|
189
242
|
end
|
190
243
|
|
191
244
|
def build?
|
192
|
-
|
193
|
-
|
194
|
-
!doc? || !@output[0].nil?
|
245
|
+
!!@output[0]
|
195
246
|
end
|
196
247
|
|
197
248
|
def refresh?
|
198
|
-
build?
|
249
|
+
build? && (copy? || ::Rake::Task.task_defined?("#{name}:copy"))
|
199
250
|
end
|
200
251
|
|
201
252
|
def depend?
|
202
|
-
|
253
|
+
!!@depend
|
203
254
|
end
|
204
255
|
|
205
256
|
def doc?
|
206
|
-
|
257
|
+
!!@doc
|
258
|
+
end
|
259
|
+
|
260
|
+
def test?
|
261
|
+
!!@test
|
207
262
|
end
|
208
263
|
|
209
264
|
def copy?
|
@@ -211,11 +266,7 @@ module Squared
|
|
211
266
|
end
|
212
267
|
|
213
268
|
def clean?
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
def verbose?
|
218
|
-
@workspace.verbose && !pipe?
|
269
|
+
!!@clean
|
219
270
|
end
|
220
271
|
|
221
272
|
protected
|
@@ -227,7 +278,7 @@ module Squared
|
|
227
278
|
info cmd
|
228
279
|
print_item format_banner(cmd, banner: banner)
|
229
280
|
begin
|
230
|
-
shell(cmd, chdir:
|
281
|
+
shell(cmd, chdir: path, exception: exception)
|
231
282
|
rescue StandardError => e
|
232
283
|
error e
|
233
284
|
raise
|
@@ -235,37 +286,33 @@ module Squared
|
|
235
286
|
end
|
236
287
|
|
237
288
|
def run_s(cmd)
|
238
|
-
run(cmd, exception:
|
289
|
+
run(cmd, exception: workspace.exception, banner: verbose?) if cmd.is_a?(::String)
|
239
290
|
end
|
240
291
|
|
241
292
|
def env(key, suffix: nil, equals: nil, strict: false)
|
242
|
-
|
293
|
+
alt = "#{key}_#{name.upcase}"
|
243
294
|
ret = if suffix
|
244
|
-
ENV.fetch(([
|
295
|
+
ENV.fetch(([alt] + as_a(suffix)).join('_'), '')
|
245
296
|
else
|
246
|
-
ENV.fetch(
|
297
|
+
ENV.fetch(alt, strict ? '' : ENV[key]).to_s
|
247
298
|
end
|
248
|
-
|
249
|
-
|
250
|
-
|
299
|
+
if !equals.nil?
|
300
|
+
ret == equals.to_s
|
301
|
+
elsif !ret.empty? && ret != '0'
|
302
|
+
ret
|
303
|
+
end
|
251
304
|
end
|
252
305
|
|
253
306
|
def session(*cmd, options: nil)
|
254
307
|
if (val = ENV["#{(options || cmd.first).upcase}_OPTIONS"])
|
255
|
-
split_escape(val).each
|
256
|
-
cmd << (if opt.start_with?('-')
|
257
|
-
shell_escape(opt).sub('\\=', '=')
|
258
|
-
else
|
259
|
-
opt.size == 1 || /^[a-z]\d+$/i.match?(opt) ? "-#{opt}" : "--#{opt}"
|
260
|
-
end)
|
261
|
-
end
|
308
|
+
split_escape(val).each { |opt| cmd << fill_option(opt) }
|
262
309
|
end
|
263
310
|
@session = JoinSet.new(cmd)
|
264
311
|
end
|
265
312
|
|
266
313
|
def close_session(cmd)
|
267
314
|
return cmd unless cmd.respond_to?(:done)
|
268
|
-
raise ArgumentError, message('none were provided', hint:
|
315
|
+
raise ArgumentError, message('none were provided', hint: name) if cmd.empty?
|
269
316
|
|
270
317
|
@session = nil if cmd == @session
|
271
318
|
cmd.done
|
@@ -277,9 +324,35 @@ module Squared
|
|
277
324
|
puts val unless val.empty? || (val.size == 1 && val.first.nil?)
|
278
325
|
end
|
279
326
|
|
327
|
+
def print_banner(*lines, styles: nil, pad: 0, first: false)
|
328
|
+
n = max_width(lines)
|
329
|
+
ch = ' ' * pad
|
330
|
+
index = -1
|
331
|
+
out = lines.map do |val|
|
332
|
+
index += 1
|
333
|
+
val = ch + val.ljust(n - (pad * 2)) + ch
|
334
|
+
if styles && (!first || index == 0)
|
335
|
+
sub_style(val, *styles)
|
336
|
+
else
|
337
|
+
val
|
338
|
+
end
|
339
|
+
end
|
340
|
+
out << ('-' * n)
|
341
|
+
out.join("\n")
|
342
|
+
end
|
343
|
+
|
344
|
+
def print_footer(*lines)
|
345
|
+
n = max_width(lines)
|
346
|
+
['-' * n, *lines.map { |val| val.ljust(n) }].join("\n")
|
347
|
+
end
|
348
|
+
|
280
349
|
def format_desc(action, flag, opts = nil, req: 'opts*')
|
281
350
|
opts = "#{req}=#{opts.join(',')}" if opts.is_a?(::Array)
|
282
|
-
|
351
|
+
if !flag
|
352
|
+
flag = action
|
353
|
+
action = ''
|
354
|
+
end
|
355
|
+
message(name, action, opts ? "#{flag}[#{opts}]" : flag)
|
283
356
|
end
|
284
357
|
|
285
358
|
def format_banner(cmd, banner: true, multitask: false)
|
@@ -287,16 +360,16 @@ module Squared
|
|
287
360
|
|
288
361
|
if verbose?
|
289
362
|
pad = 0
|
290
|
-
if (args =
|
363
|
+
if (args = theme[:banner])
|
291
364
|
if args.any? { |s| s.to_s.end_with?('!') }
|
292
365
|
pad = 1
|
293
366
|
elsif args.size <= 1
|
294
367
|
args = [:bold] + args
|
295
368
|
end
|
296
369
|
end
|
297
|
-
|
298
|
-
elsif multitask &&
|
299
|
-
"## #{
|
370
|
+
print_banner(cmd.sub(/^\S+/, &:upcase), path.to_s, styles: args, pad: pad, first: pad == 0)
|
371
|
+
elsif multitask && workspace.multitask?
|
372
|
+
"## #{path} ##"
|
300
373
|
end
|
301
374
|
end
|
302
375
|
|
@@ -310,7 +383,7 @@ module Squared
|
|
310
383
|
|
311
384
|
def guard_params(action, flag, args: nil, key: nil, pat: nil)
|
312
385
|
if args && key
|
313
|
-
return unless (val = args[key]).nil? || (pat && !
|
386
|
+
return unless (val = args[key]).nil? || (pat && !val.match?(pat))
|
314
387
|
|
315
388
|
@session = nil
|
316
389
|
raise ArgumentError, message(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
|
@@ -326,12 +399,16 @@ module Squared
|
|
326
399
|
raise ArgumentError, message('parameter', flag, hint: 'missing')
|
327
400
|
end
|
328
401
|
|
402
|
+
def verbose?
|
403
|
+
workspace.verbose
|
404
|
+
end
|
405
|
+
|
329
406
|
def pipe?
|
330
|
-
|
407
|
+
workspace.pipe
|
331
408
|
end
|
332
409
|
|
333
410
|
def invoked_sync?(action)
|
334
|
-
return true if invoked?(
|
411
|
+
return true if invoked?(sync = "#{action}:sync")
|
335
412
|
|
336
413
|
missing = ->(val) { ::Rake::Task.tasks.none? { |item| item.name == val } }
|
337
414
|
check = lambda do |val|
|
@@ -341,15 +418,21 @@ module Squared
|
|
341
418
|
true
|
342
419
|
end
|
343
420
|
end
|
344
|
-
if
|
345
|
-
ret = check.("#{action}:#{
|
421
|
+
if group
|
422
|
+
ret = check.("#{action}:#{group}")
|
346
423
|
return ret unless ret.nil?
|
347
424
|
end
|
348
|
-
if (base =
|
425
|
+
if (base = workspace.find_base(self))
|
349
426
|
ret = check.("#{action}:#{base.to_sym}")
|
350
427
|
return ret unless ret.nil?
|
351
428
|
end
|
352
|
-
invoked?("#{
|
429
|
+
invoked?("#{name}:#{action}") && (!invoked?(action) || missing.(sync))
|
430
|
+
end
|
431
|
+
|
432
|
+
private
|
433
|
+
|
434
|
+
def max_width(lines)
|
435
|
+
[lines.max_by(&:size).size, Project.line_width].max
|
353
436
|
end
|
354
437
|
end
|
355
438
|
end
|