squared 0.3.6 → 0.4.1
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 +70 -2
- data/README.md +13 -2
- data/README.ruby.md +171 -88
- data/lib/squared/app.rb +1 -0
- data/lib/squared/common/base.rb +6 -1
- data/lib/squared/common/class.rb +1 -1
- data/lib/squared/common/format.rb +32 -15
- data/lib/squared/common/prompt.rb +2 -2
- data/lib/squared/common/shell.rb +52 -39
- data/lib/squared/common/utils.rb +68 -2
- data/lib/squared/config.rb +1 -1
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +16 -13
- data/lib/squared/workspace/project/base.rb +429 -123
- data/lib/squared/workspace/project/docker.rb +622 -0
- data/lib/squared/workspace/project/git.rb +427 -164
- data/lib/squared/workspace/project/node.rb +48 -50
- data/lib/squared/workspace/project/python.rb +115 -25
- data/lib/squared/workspace/project/ruby.rb +33 -35
- data/lib/squared/workspace/project.rb +7 -1
- data/lib/squared/workspace/repo.rb +9 -4
- data/lib/squared/workspace/series.rb +1 -1
- metadata +3 -2
@@ -28,12 +28,16 @@ module Squared
|
|
28
28
|
bright_cyan!: '106',
|
29
29
|
bright_white!: '107'
|
30
30
|
}.freeze
|
31
|
+
AIX_GRAPH = ['│', '─', '├', '└', '┬'].freeze
|
32
|
+
AIX_BORDER = ['│', '─', '╭', '╮', '╯', '╰', '├', '┤', '┬', '┴'].freeze
|
31
33
|
TEXT_STYLE = [:bold, :dim, :italic, :underline, :blinking, nil, :inverse, :hidden, :strikethrough].freeze
|
32
|
-
private_constant :AIX_TERM, :TEXT_STYLE
|
34
|
+
private_constant :AIX_TERM, :AIX_GRAPH, :AIX_BORDER, :TEXT_STYLE
|
33
35
|
|
34
36
|
def enable_aixterm
|
35
37
|
unless (colors = __get__(:colors)).frozen?
|
36
38
|
colors.merge!(AIX_TERM)
|
39
|
+
ARG[:GRAPH] = AIX_GRAPH
|
40
|
+
ARG[:BORDER] = AIX_BORDER
|
37
41
|
end
|
38
42
|
block_given? ? yield(self) : self
|
39
43
|
end
|
@@ -114,7 +118,7 @@ module Squared
|
|
114
118
|
if !val.is_a?(::Numeric)
|
115
119
|
val = val.to_sym
|
116
120
|
ret << val if colors.key?(val) || TEXT_STYLE.include?(val)
|
117
|
-
elsif val
|
121
|
+
elsif val.between?(0, 256)
|
118
122
|
ret << val
|
119
123
|
elsif val < 0 && (b = val.to_s.split('.')[1])
|
120
124
|
b = b[0, 3]
|
@@ -166,16 +170,23 @@ module Squared
|
|
166
170
|
color ? sub_style(ret, *styles) : ret
|
167
171
|
end
|
168
172
|
|
169
|
-
def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR])
|
173
|
+
def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR], append: true, pass: false)
|
170
174
|
args = args.map(&:to_s)
|
171
|
-
if
|
175
|
+
if level.is_a?(::Numeric)
|
176
|
+
if append && respond_to?(:log)
|
177
|
+
ref = log rescue nil
|
178
|
+
ref.add(level, message(subject, *args, hint: hint, space: ', ')) if ref.is_a?(Logger)
|
179
|
+
end
|
180
|
+
return false if !pass && level < ARG[:LEVEL]
|
181
|
+
end
|
182
|
+
if args.size > 1 && !hint
|
172
183
|
title = log_title(level, color: false)
|
173
184
|
sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
|
174
185
|
emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub)
|
175
186
|
else
|
176
187
|
msg = [log_title(level, color: color)]
|
177
188
|
if subject
|
178
|
-
msg << (color ? sub_style(subject, :
|
189
|
+
msg << (color ? sub_style(subject, styles: (@theme && @theme[:subject]) || :bold) : subject)
|
179
190
|
else
|
180
191
|
msg += args
|
181
192
|
args.clear
|
@@ -185,6 +196,8 @@ module Squared
|
|
185
196
|
end
|
186
197
|
|
187
198
|
def puts_oe(*args, pipe: 1)
|
199
|
+
return if args.first == false && args.size == 1
|
200
|
+
|
188
201
|
if pipe.is_a?(Pathname)
|
189
202
|
begin
|
190
203
|
File.open(pipe, 'a') do |f|
|
@@ -201,8 +214,8 @@ module Squared
|
|
201
214
|
|
202
215
|
module_function
|
203
216
|
|
204
|
-
def message(*args, hint: nil, empty: false)
|
205
|
-
(empty ? args.reject { |val| val.nil? || val.empty? } : args).join(
|
217
|
+
def message(*args, hint: nil, empty: false, space: ARG[:SPACE])
|
218
|
+
(empty ? args.reject { |val| val.nil? || val.empty? } : args).join(space) + (hint ? " (#{hint})" : '')
|
206
219
|
end
|
207
220
|
|
208
221
|
def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, border: nil, pipe: nil)
|
@@ -226,27 +239,31 @@ module Squared
|
|
226
239
|
require 'io/console'
|
227
240
|
(n = [n, $stdout.winsize[1] - 4].min) rescue nil
|
228
241
|
end
|
242
|
+
b0, b1, b2, b3, b4, b5, b6, b7 = ARG[:BORDER]
|
229
243
|
out = []
|
230
|
-
|
231
|
-
|
244
|
+
draw = lambda do |a, b|
|
245
|
+
ret = a + (b1 * (n + 2)) + b
|
246
|
+
ret = sub_style(ret, styles: border) if border
|
247
|
+
ret
|
248
|
+
end
|
232
249
|
sub = as_a(sub)
|
233
250
|
pr = lambda do |line|
|
234
251
|
s = line.ljust(n)
|
235
252
|
sub.each { |h| s = sub_style(s, **h) }
|
236
|
-
s = "
|
253
|
+
s = "#{b0} #{s} #{b0}"
|
237
254
|
if border
|
238
|
-
s = sub_style(s, pat: /\A(
|
239
|
-
s = sub_style(s, pat: /\A(.+)(
|
255
|
+
s = sub_style(s, pat: /\A(#{Regexp.escape(b0)})(.+)\z/m, styles: border)
|
256
|
+
s = sub_style(s, pat: /\A(.+)(#{Regexp.escape(b0)})\z/m, styles: border, index: 2)
|
240
257
|
end
|
241
258
|
s
|
242
259
|
end
|
243
|
-
out <<
|
260
|
+
out << draw.(b2, b3)
|
244
261
|
if title
|
245
262
|
out += title.map { |t| pr.(t) }
|
246
|
-
out <<
|
263
|
+
out << draw.(b6, b7)
|
247
264
|
end
|
248
265
|
lines.each { |line| out << pr.(line) }
|
249
|
-
out <<
|
266
|
+
out << draw.(b5, b4)
|
250
267
|
if footer
|
251
268
|
unless sub.empty? && !right
|
252
269
|
footer.map! do |s|
|
@@ -8,8 +8,8 @@ module Squared
|
|
8
8
|
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
|
9
9
|
require 'readline'
|
10
10
|
require 'timeout'
|
11
|
-
agree =
|
12
|
-
cancel =
|
11
|
+
agree = /^#{agree}$/i if agree.is_a?(::String)
|
12
|
+
cancel = /^#{cancel}$/i if cancel.is_a?(::String)
|
13
13
|
Timeout.timeout(timeout) do
|
14
14
|
begin
|
15
15
|
while (ch = Readline.readline(msg, true))
|
data/lib/squared/common/shell.rb
CHANGED
@@ -8,78 +8,91 @@ module Squared
|
|
8
8
|
module Shell
|
9
9
|
module_function
|
10
10
|
|
11
|
-
def shell_escape(val, quote: false, force: false)
|
12
|
-
if (
|
13
|
-
return val if !
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def shell_escape(val, quote: false, force: false, double: false, override: false)
|
12
|
+
if (r = /\A(--?)([^= ]+)((=|\s+)(["'])?(.+?)(["'])?)?\z/m.match(val = val.to_s))
|
13
|
+
return val if !r[3] || (!r[5] && r[6].match?(/\s/))
|
14
|
+
|
15
|
+
combine = lambda do |opt|
|
16
|
+
if r[2] =~ /^(["'])(.+)\1$/
|
17
|
+
double = $1 == '"'
|
18
|
+
r[2] = $2
|
19
|
+
override = true
|
20
|
+
end
|
21
|
+
r[1] + r[2] + r[4] + shell_quote(opt, double: double, force: force, override: override)
|
22
|
+
end
|
23
|
+
if r[5] == r[7]
|
24
|
+
r[5] ? val : combine.(r[6])
|
18
25
|
else
|
19
|
-
|
26
|
+
force = true
|
27
|
+
combine.(r[5] + r[6] + r[7])
|
20
28
|
end
|
21
29
|
elsif Rake::Win32.windows?
|
22
|
-
quote ? shell_quote(val, force: force) : val
|
30
|
+
quote ? shell_quote(val, double: double, force: force) : val
|
23
31
|
else
|
24
32
|
Shellwords.escape(val)
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
28
|
-
def shell_quote(val, force: true)
|
36
|
+
def shell_quote(val, option: true, force: true, double: false, override: false)
|
29
37
|
val = val.to_s
|
30
|
-
return val if (!force && !val.include?(' ')) || val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m)
|
31
|
-
|
32
|
-
Rake::Win32.windows? || ARG[:QUOTE] == '"' ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
|
33
|
-
end
|
34
|
-
|
35
|
-
def shell_split(val, escape: true, quote: false, join: nil)
|
36
|
-
val = Shellwords.split(val)
|
37
|
-
val = val.map { |opt| shell_escape(opt, quote: quote) } if escape
|
38
|
-
return val unless join
|
38
|
+
return val if (!force && !val.include?(' ')) || (option && val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m))
|
39
39
|
|
40
|
-
|
40
|
+
if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
41
|
+
"\"#{val.gsub(/(?<!\\)"/, '\\"')}\""
|
42
|
+
else
|
43
|
+
"'#{val.gsub("'", "'\\\\''")}'"
|
44
|
+
end
|
41
45
|
end
|
42
46
|
|
43
|
-
def shell_option(flag, val = nil, escape: true, quote: true, force: true
|
47
|
+
def shell_option(flag, val = nil, escape: true, quote: true, force: true, double: false, override: false,
|
48
|
+
merge: false)
|
44
49
|
flag = flag.to_s
|
50
|
+
if flag =~ /^(["'])(.+)\1$/
|
51
|
+
double = $1 == '"'
|
52
|
+
flag = $2
|
53
|
+
escape = false
|
54
|
+
override = true
|
55
|
+
end
|
45
56
|
if flag[0] == '-'
|
46
57
|
b = flag[1] == '-' ? '=' : ' '
|
58
|
+
elsif flag.size == 1
|
59
|
+
a = '-'
|
60
|
+
b = merge ? '' : ' '
|
47
61
|
else
|
48
|
-
a
|
62
|
+
a = '--'
|
63
|
+
b = '='
|
49
64
|
end
|
50
65
|
"#{a}#{flag}#{if val
|
51
66
|
"#{b}#{if escape
|
52
|
-
shell_escape(val, quote: quote)
|
67
|
+
shell_escape(val, quote: quote, double: double, override: override)
|
53
68
|
else
|
54
|
-
quote ? shell_quote(val, force: force) : val
|
69
|
+
quote ? shell_quote(val, force: force, double: double, override: override) : val
|
55
70
|
end}"
|
56
71
|
end}"
|
57
72
|
end
|
58
73
|
|
59
|
-
def
|
60
|
-
|
74
|
+
def shell_split(val, escape: true, quote: false, join: nil)
|
75
|
+
ret = Shellwords.split(val)
|
76
|
+
return ret if join == false
|
61
77
|
|
62
|
-
|
63
|
-
|
78
|
+
ret = ret.map { |opt| shell_escape(opt, quote: quote) } if escape
|
79
|
+
return ret unless join
|
64
80
|
|
65
|
-
|
66
|
-
shell_option(flag, val, escape: false)
|
81
|
+
ret.join(join.is_a?(::String) ? join : ' ')
|
67
82
|
end
|
68
83
|
|
69
|
-
def
|
70
|
-
|
71
|
-
end
|
84
|
+
def fill_option(val, double: false)
|
85
|
+
return "-#{val}" if val.match?(/^[a-z]\d*$/i)
|
72
86
|
|
73
|
-
|
74
|
-
val.gsub("'", "'\\\\''")
|
87
|
+
shell_escape(val.start_with?('-') ? val : "--#{val}", double: double)
|
75
88
|
end
|
76
89
|
|
77
|
-
def
|
78
|
-
|
90
|
+
def quote_option(flag, val, double: false)
|
91
|
+
shell_option(flag, val, escape: false, double: double)
|
79
92
|
end
|
80
93
|
|
81
|
-
def
|
82
|
-
val
|
94
|
+
def basic_option(flag, val, merge: false)
|
95
|
+
shell_option(flag, val, escape: false, force: false, merge: merge)
|
83
96
|
end
|
84
97
|
end
|
85
98
|
end
|
data/lib/squared/common/utils.rb
CHANGED
@@ -8,6 +8,23 @@ module Squared
|
|
8
8
|
module Utils
|
9
9
|
module_function
|
10
10
|
|
11
|
+
def split_escape(val, char: ',')
|
12
|
+
val.split(/\s*(?<!\\)#{char}\s*/o)
|
13
|
+
end
|
14
|
+
|
15
|
+
def split_option(val)
|
16
|
+
val = val.strip
|
17
|
+
return [val, '', ''] unless (i = val.index('='))
|
18
|
+
|
19
|
+
last = val[i + 1..-1].strip
|
20
|
+
quote = ''
|
21
|
+
if last =~ /^(["'])(.+)\1$/
|
22
|
+
last = $2
|
23
|
+
quote = $1
|
24
|
+
end
|
25
|
+
[val[0..i - 1], last, quote]
|
26
|
+
end
|
27
|
+
|
11
28
|
def task_invoke(*cmd, args: [], exception: true, warning: true)
|
12
29
|
cmd.each { |name| Rake::Task[name].invoke(*args) }
|
13
30
|
rescue StandardError => e
|
@@ -31,8 +48,57 @@ module Squared
|
|
31
48
|
Rake::Task.tasks.any? do |obj|
|
32
49
|
next unless obj.already_invoked
|
33
50
|
|
34
|
-
args.any? { |val| val.is_a?(::Regexp) ? obj.name
|
51
|
+
args.any? { |val| val.is_a?(::Regexp) ? obj.name.match?(val) : val == obj.name }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def time_format(epoch, clock: false, pass: [])
|
56
|
+
ss = 1000
|
57
|
+
mm = 60 * ss
|
58
|
+
hh = 60 * mm
|
59
|
+
dd = 24 * hh
|
60
|
+
hm = pass.include?('s')
|
61
|
+
time = []
|
62
|
+
if !clock && (d = epoch / dd) > 0
|
63
|
+
time << "#{d}d"
|
64
|
+
epoch -= d * dd
|
65
|
+
end
|
66
|
+
if (h = epoch / hh) > 0
|
67
|
+
time << (clock ? h.to_s : "#{h}h")
|
68
|
+
epoch -= h * hh
|
35
69
|
end
|
70
|
+
if (m = epoch / mm) > 0
|
71
|
+
time << (clock ? m.to_s.rjust(2, '0') : "#{m}m")
|
72
|
+
epoch -= m * mm
|
73
|
+
elsif clock
|
74
|
+
time << '00'
|
75
|
+
end
|
76
|
+
unless hm
|
77
|
+
if (s = epoch / ss) > 0
|
78
|
+
time << (clock ? s.to_s.rjust(2, '0') : "#{s}s")
|
79
|
+
epoch -= s * ss
|
80
|
+
elsif clock
|
81
|
+
time << '00'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
if clock
|
85
|
+
time.join(':')
|
86
|
+
else
|
87
|
+
time << "#{epoch}ms" unless hm || pass.include?('ms')
|
88
|
+
time.join(' ')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def time_offset(val = nil)
|
93
|
+
val = DateTime.parse(val) if val.is_a?(::String)
|
94
|
+
cur = DateTime.now
|
95
|
+
ret = 0
|
96
|
+
if (r = /^([+-])(\d+):(\d+):(\d+)$/.match((val || cur).strftime('%::z')))
|
97
|
+
ret += (r[1] == '+' ? -1 : 1) * ((r[2].to_i * 60 * 60) + (r[3].to_i * 60) + r[4].to_i) * 1000
|
98
|
+
end
|
99
|
+
return ret unless val
|
100
|
+
|
101
|
+
(cur.strftime('%Q').to_i + time_offset) - (val.strftime('%Q').to_i + ret)
|
36
102
|
end
|
37
103
|
|
38
104
|
def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil)
|
@@ -88,7 +154,7 @@ module Squared
|
|
88
154
|
return ret.to_i
|
89
155
|
end
|
90
156
|
when ::Numeric
|
91
|
-
return key if key
|
157
|
+
return key if key.between?(0, 2)
|
92
158
|
end
|
93
159
|
default
|
94
160
|
end
|
data/lib/squared/config.rb
CHANGED
@@ -90,7 +90,7 @@ module Squared
|
|
90
90
|
@required = true
|
91
91
|
project ? [project, 'not found'] : ['name', 'missing']
|
92
92
|
end
|
93
|
-
warn log_message(Logger::WARN, msg, subject: self.class, hint: hint)
|
93
|
+
warn log_message(Logger::WARN, msg, subject: self.class, hint: hint, pass: true)
|
94
94
|
end
|
95
95
|
|
96
96
|
def build
|
data/lib/squared/version.rb
CHANGED
@@ -173,7 +173,7 @@ module Squared
|
|
173
173
|
when Symbol
|
174
174
|
@ref = val
|
175
175
|
else
|
176
|
-
raise_error
|
176
|
+
raise_error 'missing group or ref' if block_given?
|
177
177
|
end
|
178
178
|
if block_given?
|
179
179
|
instance_eval(&blk)
|
@@ -357,7 +357,7 @@ module Squared
|
|
357
357
|
}
|
358
358
|
data.each do |key, val|
|
359
359
|
key = key.to_s
|
360
|
-
if /\A(\\A|\^)/
|
360
|
+
if key.match?(/\A(\\A|\^)/) || key.match?(/(\\z|\$)\z/)
|
361
361
|
@describe[:replace] << [Regexp.new(key), val]
|
362
362
|
else
|
363
363
|
@describe[val.is_a?(Regexp) ? :pattern : :alias][key.to_s] = val
|
@@ -415,15 +415,14 @@ module Squared
|
|
415
415
|
val = name || task_join(*args)
|
416
416
|
found = false
|
417
417
|
replace = lambda do |data, out|
|
418
|
-
|
419
|
-
|
420
|
-
end
|
418
|
+
index = data.size
|
419
|
+
data.to_a.reverse_each { |group| out.sub!("%#{index -= 1}", group) }
|
421
420
|
out
|
422
421
|
end
|
423
|
-
@describe[:replace].each do |pat,
|
424
|
-
next unless
|
422
|
+
@describe[:replace].each do |pat, tmpl|
|
423
|
+
next unless val =~ pat
|
425
424
|
|
426
|
-
val = replace.(
|
425
|
+
val = replace.($~, tmpl.dup)
|
427
426
|
found = true
|
428
427
|
end
|
429
428
|
if (out = @describe[:alias][val])
|
@@ -431,14 +430,14 @@ module Squared
|
|
431
430
|
found = true
|
432
431
|
else
|
433
432
|
@describe[:pattern].each do |key, pat|
|
434
|
-
next unless
|
433
|
+
next unless val =~ pat
|
435
434
|
|
436
|
-
val = replace.(
|
435
|
+
val = replace.($~, key.dup)
|
437
436
|
found = true
|
438
437
|
break
|
439
438
|
end
|
440
439
|
end
|
441
|
-
args =
|
440
|
+
args = split_escape(val, char: ':').map! { |s| s.gsub('\\:', ':') } if found
|
442
441
|
end
|
443
442
|
desc message(*args, **kwargs)
|
444
443
|
end
|
@@ -564,7 +563,7 @@ module Squared
|
|
564
563
|
|
565
564
|
key = task_join(task_localname(obj.name), key)
|
566
565
|
end
|
567
|
-
@pass[:pattern].any? { |item| item.is_a?(Regexp) ? key
|
566
|
+
@pass[:pattern].any? { |item| item.is_a?(Regexp) ? key.to_s.match?(item) : key == item }
|
568
567
|
end
|
569
568
|
|
570
569
|
def task_defined?(*key)
|
@@ -587,6 +586,10 @@ module Squared
|
|
587
586
|
Rake::Win32.windows?
|
588
587
|
end
|
589
588
|
|
589
|
+
def docker?
|
590
|
+
File.exist?('/.dockerenv')
|
591
|
+
end
|
592
|
+
|
590
593
|
def rootpath(*args)
|
591
594
|
root.join(*args)
|
592
595
|
end
|
@@ -693,7 +696,7 @@ module Squared
|
|
693
696
|
end
|
694
697
|
return false if state == :prod && data[:dev] == true && data[:global]
|
695
698
|
|
696
|
-
target && pat.is_a?(Regexp) ? as_a(target).any? { |val| val
|
699
|
+
target && pat.is_a?(Regexp) ? as_a(target).any? { |val| val.match?(pat) } : pat == true
|
697
700
|
end
|
698
701
|
|
699
702
|
def scriptobj
|