squared 0.5.26 → 0.6.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 +89 -300
- data/README.md +104 -72
- data/lib/squared/common/base.rb +1 -30
- data/lib/squared/common/format.rb +40 -38
- data/lib/squared/common/prompt.rb +58 -40
- data/lib/squared/common/shell.rb +71 -63
- data/lib/squared/common/system.rb +70 -38
- data/lib/squared/common/utils.rb +31 -16
- data/lib/squared/config.rb +27 -34
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +87 -113
- data/lib/squared/workspace/project/base.rb +552 -427
- data/lib/squared/workspace/project/docker.rb +419 -320
- data/lib/squared/workspace/project/git.rb +379 -374
- data/lib/squared/workspace/project/node.rb +502 -285
- data/lib/squared/workspace/project/python.rb +375 -255
- data/lib/squared/workspace/project/ruby.rb +697 -397
- data/lib/squared/workspace/project/support/class.rb +213 -238
- data/lib/squared/workspace/repo.rb +47 -44
- data/lib/squared/workspace/series.rb +14 -23
- data/lib/squared/workspace/support/base.rb +3 -24
- data/lib/squared/workspace/support/variables.rb +48 -0
- data/lib/squared/workspace/support.rb +1 -1
- data/lib/squared/workspace.rb +4 -6
- metadata +3 -3
- data/lib/squared/workspace/support/data.rb +0 -11
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
unless defined?(Readline)
|
|
4
|
+
if RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.7'
|
|
5
|
+
require 'readline'
|
|
6
|
+
else
|
|
7
|
+
begin
|
|
8
|
+
require 'reline'
|
|
9
|
+
Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
|
|
10
|
+
Readline = Reline
|
|
11
|
+
rescue LoadError
|
|
12
|
+
require 'readline'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
3
17
|
module Squared
|
|
4
18
|
module Common
|
|
5
19
|
module Prompt
|
|
6
20
|
module_function
|
|
7
21
|
|
|
8
|
-
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts:
|
|
9
|
-
require 'readline'
|
|
22
|
+
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 3, timeout: 60)
|
|
10
23
|
require 'timeout'
|
|
11
24
|
if agree == 'Y' && cancel == 'N' && !msg.match?(%r{\[(?:Yn|nY|Y/n|y/N)\]})
|
|
12
25
|
case default
|
|
@@ -38,9 +51,8 @@ module Squared
|
|
|
38
51
|
end
|
|
39
52
|
end
|
|
40
53
|
|
|
41
|
-
def choice(msg, list = nil, min: 1, max: 1, multiple: false,
|
|
42
|
-
attempts:
|
|
43
|
-
require 'readline'
|
|
54
|
+
def choice(msg, list = nil, min: 1, max: 1, multiple: false, index: false, grep: nil, border: nil, auto: true,
|
|
55
|
+
force: true, attempts: 3, timeout: 0)
|
|
44
56
|
require 'timeout'
|
|
45
57
|
if list
|
|
46
58
|
grep &&= Array(grep).map { |val| Regexp.new(val) }
|
|
@@ -52,40 +64,51 @@ module Squared
|
|
|
52
64
|
puts '%2d. %s' % [items.size, val]
|
|
53
65
|
end
|
|
54
66
|
max = items.size
|
|
55
|
-
|
|
67
|
+
raise ArgumentError, 'empty selection list' if max == 0
|
|
68
|
+
|
|
56
69
|
min = grep ? 1 : [min, max].min
|
|
57
70
|
if auto
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
auto.times { puts } if auto.is_a?(::Numeric)
|
|
72
|
+
if border == true
|
|
73
|
+
puts print_footer
|
|
74
|
+
elsif border
|
|
75
|
+
puts print_footer(border: border)
|
|
76
|
+
end
|
|
77
|
+
msg = "#{msg + (force ? ':' : '?')} [#{min}-#{max}#{if (n = multiple)
|
|
78
|
+
"|,#{n.is_a?(::Numeric) ? "{#{n}}" : '*'}"
|
|
79
|
+
end}] "
|
|
61
80
|
end
|
|
62
81
|
end
|
|
63
|
-
|
|
82
|
+
between = ->(s) { s.match?(/^\d+$/) && s.to_i.between?(min, max) }
|
|
64
83
|
Timeout.timeout(timeout) do
|
|
65
84
|
while (ch = Readline.readline(msg))
|
|
66
85
|
unless (ch = ch.strip).empty?
|
|
67
86
|
if multiple
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
k = if ch == '*'
|
|
88
|
+
(min..max).to_a
|
|
89
|
+
else
|
|
90
|
+
ch.split(/\s*,\s*/).map! do |s|
|
|
91
|
+
if s =~ /^(\d+)-(\d+)$/
|
|
92
|
+
next unless between.call($1) && between.call($2)
|
|
73
93
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
i = $1.to_i
|
|
95
|
+
j = $2.to_i
|
|
96
|
+
next (i..j).to_a if i < j
|
|
97
|
+
elsif between.call(s)
|
|
98
|
+
s.to_i
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
unless k.include?(nil)
|
|
103
|
+
k.flatten!
|
|
104
|
+
k.uniq!
|
|
105
|
+
k.sort!
|
|
106
|
+
unless multiple.is_a?(::Numeric) && multiple != k.size
|
|
107
|
+
return index || !items ? k : k.map! { |i| items[i.pred] }
|
|
79
108
|
end
|
|
80
109
|
end
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
b.uniq!
|
|
84
|
-
b.sort!
|
|
85
|
-
return items ? b.map! { |i| items[i - 1] } : b unless multiple.is_a?(::Numeric) && multiple != b.size
|
|
86
|
-
end
|
|
87
|
-
elsif valid.call(ch)
|
|
88
|
-
return items ? items[ch.to_i - 1] : ch.to_i
|
|
110
|
+
elsif between.call(ch)
|
|
111
|
+
return index || !items ? ch.to_i : items[ch.to_i.pred]
|
|
89
112
|
end
|
|
90
113
|
end
|
|
91
114
|
attempts -= 1
|
|
@@ -98,12 +121,11 @@ module Squared
|
|
|
98
121
|
puts
|
|
99
122
|
exit 0
|
|
100
123
|
else
|
|
101
|
-
|
|
124
|
+
[] if multiple
|
|
102
125
|
end
|
|
103
126
|
end
|
|
104
127
|
|
|
105
128
|
def readline(msg, history = false, force: nil, multiline: nil, &blk)
|
|
106
|
-
require 'readline'
|
|
107
129
|
multiline = if multiline && Readline.respond_to?(:readmultiline)
|
|
108
130
|
multiline.is_a?(::Enumerable) || block_given? ? multiline : [multiline.to_s]
|
|
109
131
|
end
|
|
@@ -113,20 +135,16 @@ module Squared
|
|
|
113
135
|
elsif block_given?
|
|
114
136
|
Readline.readmultiline(msg, history, &blk)
|
|
115
137
|
else
|
|
116
|
-
Readline.readmultiline(msg, history)
|
|
117
|
-
next if line.strip.empty?
|
|
118
|
-
|
|
119
|
-
multiline.any? { |val| line.split.last.end_with?(val.to_s) }
|
|
120
|
-
end
|
|
138
|
+
Readline.readmultiline(msg, history) { |line| multiline.any? { |val| line.split.last.end_with?(val.to_s) } }
|
|
121
139
|
end
|
|
122
140
|
end
|
|
123
141
|
case force
|
|
124
142
|
when ::TrueClass, ::FalseClass
|
|
125
|
-
msg = "#{msg}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
msg = "#{msg}%s%s " % if multiline
|
|
144
|
+
[' ', multiline.is_a?(::Enumerable) ? "{#{multiline.to_a.join('|')}}" : multiline]
|
|
145
|
+
else
|
|
146
|
+
[force ? ':' : '?', '']
|
|
147
|
+
end
|
|
130
148
|
ret = (prompt.call || '').strip
|
|
131
149
|
multiline.each { |val| break if ret.delete_suffix!(val.to_s) } if multiline.is_a?(::Enumerable)
|
|
132
150
|
exit 1 if force && ret.empty?
|
data/lib/squared/common/shell.rb
CHANGED
|
@@ -6,14 +6,11 @@ require 'shellwords'
|
|
|
6
6
|
module Squared
|
|
7
7
|
module Common
|
|
8
8
|
module Shell
|
|
9
|
-
QUOTE_VALUE = /\A(["'])(.*)\1\z/m.freeze
|
|
10
|
-
private_constant :QUOTE_VALUE
|
|
11
|
-
|
|
12
9
|
module_function
|
|
13
10
|
|
|
14
11
|
def shell_escape(val, quote: false, force: false, double: false, option: false, override: false)
|
|
15
|
-
if (r = /\A(--?)([
|
|
16
|
-
if (data = r[2].match(
|
|
12
|
+
if (r = /\A(--?)([^= ]+)((=|\s+)(["'])?(?(5)(.*)\5|(.*)))?\z/m.match(val = val.to_s))
|
|
13
|
+
if (data = r[2].match(/\A(["'])(.+)\1\z/))
|
|
17
14
|
double = data[1] == '"'
|
|
18
15
|
override = true
|
|
19
16
|
elsif !r[3] || r[6]
|
|
@@ -28,9 +25,9 @@ module Squared
|
|
|
28
25
|
|
|
29
26
|
r[7]
|
|
30
27
|
end
|
|
31
|
-
r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt,
|
|
32
|
-
elsif option && val =~ /\A(
|
|
33
|
-
return val if $2.match?(
|
|
28
|
+
r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt, double: double, force: force, override: override)
|
|
29
|
+
elsif option && val =~ /\A([^=]+)=(.+)\z/m
|
|
30
|
+
return val if $2.match?(/\A(["']).+\1\z/m)
|
|
34
31
|
|
|
35
32
|
"#{$1}=%s" % if $2.include?(' ')
|
|
36
33
|
shell_quote($2, option: false)
|
|
@@ -40,7 +37,7 @@ module Squared
|
|
|
40
37
|
Shellwords.escape($2)
|
|
41
38
|
end
|
|
42
39
|
elsif Rake::Win32.windows?
|
|
43
|
-
quote ? shell_quote(val,
|
|
40
|
+
quote ? shell_quote(val, double: double, force: force) : val
|
|
44
41
|
elsif val.empty?
|
|
45
42
|
''
|
|
46
43
|
else
|
|
@@ -48,67 +45,46 @@ module Squared
|
|
|
48
45
|
end
|
|
49
46
|
end
|
|
50
47
|
|
|
51
|
-
def shell_quote(val, option: true, force: true, double: false,
|
|
48
|
+
def shell_quote(val, option: true, force: true, double: false, override: false)
|
|
52
49
|
val = val.to_s
|
|
53
50
|
return val if (!force && !val.include?(' ')) || val.empty?
|
|
54
|
-
return val if option && val.match?(/\A(?:-[^=\s-](?:=|\s+)?|(--)?[^=\s-][^=\s]*(?(1)(?:=|\s+)|=))(["']).+\2\z/m)
|
|
55
51
|
|
|
56
|
-
if val
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return val
|
|
61
|
-
end
|
|
62
|
-
case preserve
|
|
63
|
-
when false
|
|
64
|
-
base = $2
|
|
65
|
-
when '"'
|
|
66
|
-
base = $2 if $1 == "'"
|
|
67
|
-
when "'"
|
|
68
|
-
base = $2 if $1 == '"'
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
q = -> { (base || val).gsub("'\\\\''", "'") }
|
|
72
|
-
if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
|
73
|
-
"\"#{q.call.gsub(/(?<!\\)"/, '\\"')}\""
|
|
52
|
+
if option && val.match?(/(?:\A|\A[^=\s]+(?:=|\s+)|#{Rake::Win32.windows? ? '[\\\/]' : '\/'})(["']).+\1\z/mo)
|
|
53
|
+
val
|
|
54
|
+
elsif double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
|
55
|
+
"\"#{val.gsub(/(?<!\\)"/, '\\"')}\""
|
|
74
56
|
else
|
|
75
|
-
"'#{
|
|
57
|
+
"'#{val.gsub("'", "'\\\\''")}'"
|
|
76
58
|
end
|
|
77
59
|
end
|
|
78
60
|
|
|
79
|
-
def shell_option(flag, val = nil,
|
|
80
|
-
|
|
61
|
+
def shell_option(flag, val = nil, sep: '=', escape: true, quote: true, force: true, double: false, merge: false,
|
|
62
|
+
override: false)
|
|
81
63
|
flag = flag.to_s
|
|
82
|
-
if flag =~
|
|
64
|
+
if flag =~ /\A(["'])(.+)\1\z/
|
|
83
65
|
double = $1 == '"'
|
|
84
66
|
flag = $2
|
|
85
67
|
escape = false
|
|
86
68
|
override = true
|
|
87
69
|
end
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
elsif quote
|
|
107
|
-
shell_quote(val, option: option, force: force, double: double, override: override)
|
|
108
|
-
else
|
|
109
|
-
val
|
|
110
|
-
end}"
|
|
111
|
-
end}"
|
|
70
|
+
b = if flag[0] == '-'
|
|
71
|
+
flag[1] == '-' ? sep : ' '
|
|
72
|
+
elsif flag.size == 1
|
|
73
|
+
a = '-'
|
|
74
|
+
merge ? '' : ' '
|
|
75
|
+
else
|
|
76
|
+
a = '--'
|
|
77
|
+
sep
|
|
78
|
+
end
|
|
79
|
+
"#{a}#{flag}#{unless val.nil?
|
|
80
|
+
"#{b}#{if escape
|
|
81
|
+
shell_escape(val, quote: quote, double: double, override: override)
|
|
82
|
+
elsif quote
|
|
83
|
+
shell_quote(val, option: false, force: force, double: double, override: override)
|
|
84
|
+
else
|
|
85
|
+
val
|
|
86
|
+
end}"
|
|
87
|
+
end}"
|
|
112
88
|
end
|
|
113
89
|
|
|
114
90
|
def shell_split(val, join: nil, **kwargs)
|
|
@@ -118,12 +94,45 @@ module Squared
|
|
|
118
94
|
ret.join(join.is_a?(::String) ? join : ' ')
|
|
119
95
|
end
|
|
120
96
|
|
|
97
|
+
def shell_parse(val, escape: false, force: true, **kwargs)
|
|
98
|
+
a = []
|
|
99
|
+
b = []
|
|
100
|
+
c = []
|
|
101
|
+
d = []
|
|
102
|
+
e = [a, b]
|
|
103
|
+
j = -1
|
|
104
|
+
val.shellsplit.each_with_index do |opt, i|
|
|
105
|
+
if opt == '--'
|
|
106
|
+
e = [c, d]
|
|
107
|
+
elsif opt =~ /\A--?[^=]+(=|\z)/
|
|
108
|
+
j = $1 == '=' ? -1 : i
|
|
109
|
+
e[0] << [opt]
|
|
110
|
+
elsif j >= 0
|
|
111
|
+
e[0][j] << opt
|
|
112
|
+
else
|
|
113
|
+
e[1] << shell_quote(opt, option: false, force: force)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
ret = [[a, b], [], [c, d]].flat_map do |e, f|
|
|
117
|
+
next '--' unless e
|
|
118
|
+
|
|
119
|
+
e.flat_map do |item|
|
|
120
|
+
if item.size == 1
|
|
121
|
+
fill_option(item.first)
|
|
122
|
+
else
|
|
123
|
+
flag = item.shift
|
|
124
|
+
item.map! { |s| shell_option(flag, s, escape: escape, force: force, **kwargs) }
|
|
125
|
+
end
|
|
126
|
+
end.concat(f)
|
|
127
|
+
end
|
|
128
|
+
ret.pop if ret.last == '--'
|
|
129
|
+
ret
|
|
130
|
+
end
|
|
131
|
+
|
|
121
132
|
def shell_bin(name, env: true)
|
|
122
|
-
|
|
123
|
-
key
|
|
124
|
-
|
|
125
|
-
shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
|
|
126
|
-
option: false, force: false, double: true)
|
|
133
|
+
key = name.upcase
|
|
134
|
+
shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name, option: false, force: false,
|
|
135
|
+
double: true)
|
|
127
136
|
end
|
|
128
137
|
|
|
129
138
|
def line_width(lines)
|
|
@@ -132,7 +141,6 @@ module Squared
|
|
|
132
141
|
end
|
|
133
142
|
|
|
134
143
|
def fill_option(val, **kwargs)
|
|
135
|
-
return val unless val.is_a?(::String)
|
|
136
144
|
return "-#{val}" if val.match?(/\A(?:[a-z]\d*|\d)\z/i)
|
|
137
145
|
|
|
138
146
|
shell_escape(val.start_with?('-') ? val : "--#{val}", **kwargs)
|
|
@@ -6,10 +6,28 @@ require 'rake'
|
|
|
6
6
|
module Squared
|
|
7
7
|
module Common
|
|
8
8
|
module System
|
|
9
|
+
class << self
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def parse_link(val)
|
|
13
|
+
case val
|
|
14
|
+
when ::TrueClass, 's'
|
|
15
|
+
1
|
|
16
|
+
when 'r'
|
|
17
|
+
2
|
|
18
|
+
when 'h'
|
|
19
|
+
3
|
|
20
|
+
else
|
|
21
|
+
raise ArgumentError, "unrecognized 'link' flag: #{val}" if val
|
|
22
|
+
|
|
23
|
+
0
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
9
28
|
module_function
|
|
10
29
|
|
|
11
30
|
def shell(*args, name: :system, **kwargs)
|
|
12
|
-
kwargs.delete(:exception) unless name == :system
|
|
13
31
|
if RUBY_ENGINE == 'jruby' && Rake::Win32.windows?
|
|
14
32
|
e = kwargs[:exception]
|
|
15
33
|
if (dir = kwargs[:chdir]) && ((pwd = Dir.pwd) != dir)
|
|
@@ -25,16 +43,16 @@ module Squared
|
|
|
25
43
|
else
|
|
26
44
|
return Kernel.send(name, *args, **kwargs)
|
|
27
45
|
end
|
|
28
|
-
return ret unless e && !ret
|
|
46
|
+
return ret unless e && !ret && name == :system
|
|
29
47
|
|
|
30
48
|
raise $?.to_s
|
|
31
49
|
end
|
|
32
50
|
|
|
33
|
-
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil,
|
|
34
|
-
|
|
51
|
+
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, preserve: nil, force: false, verbose: true,
|
|
52
|
+
pass: nil, hidden: false)
|
|
35
53
|
base = Pathname.new(src)
|
|
36
54
|
target = Pathname.new(dest)
|
|
37
|
-
raise
|
|
55
|
+
raise Errno::ENOENT, dest.cleanpath.to_s unless create || target.parent.exist?
|
|
38
56
|
|
|
39
57
|
subdir = {}
|
|
40
58
|
target.mkpath if create
|
|
@@ -58,53 +76,67 @@ module Squared
|
|
|
58
76
|
end
|
|
59
77
|
count = 0
|
|
60
78
|
soft = 0
|
|
79
|
+
type = System.send :parse_link, link
|
|
61
80
|
subdir.each do |dir, files|
|
|
62
|
-
|
|
63
|
-
files.dup
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
if link == 'hard'
|
|
74
|
-
FileUtils.ln(file, dir, force: force, verbose: false)
|
|
75
|
-
else
|
|
76
|
-
FileUtils.ln_s(file, dir, force: force, verbose: false)
|
|
81
|
+
unless type == 0
|
|
82
|
+
items = files.dup
|
|
83
|
+
files.clear
|
|
84
|
+
items.each do |file|
|
|
85
|
+
if file.exist?
|
|
86
|
+
if !file.symlink?
|
|
87
|
+
files << file
|
|
88
|
+
elsif !force
|
|
89
|
+
next
|
|
77
90
|
end
|
|
78
|
-
soft += 1
|
|
79
91
|
end
|
|
92
|
+
case type
|
|
93
|
+
when 1
|
|
94
|
+
FileUtils.ln_s(file, dir, force: force, verbose: false)
|
|
95
|
+
when 2
|
|
96
|
+
FileUtils.ln_s(file.relative_path_from(dir), dir, force: force, verbose: false)
|
|
97
|
+
else
|
|
98
|
+
FileUtils.ln(file, dir, force: force, verbose: false)
|
|
99
|
+
end
|
|
100
|
+
soft += 1
|
|
80
101
|
end
|
|
81
102
|
end
|
|
82
103
|
next if files.empty?
|
|
83
104
|
|
|
84
|
-
out = FileUtils.cp(files, dir, verbose: false)
|
|
105
|
+
out = FileUtils.cp(files, dir, preserve: preserve, verbose: false)
|
|
85
106
|
count += out.size
|
|
86
107
|
end
|
|
87
108
|
puts [target.realpath, subdir.size, soft > 0 ? "#{count}+#{soft}" : count].join(' => ') if verbose
|
|
88
109
|
end
|
|
89
110
|
|
|
90
|
-
def copy_guard(src, dest, link: nil, force: false, verbose: true)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
def copy_guard(*src, dest, base: '.', create: false, link: nil, preserve: nil, force: false, verbose: true)
|
|
112
|
+
src = src.compact.flatten
|
|
113
|
+
dest = Pathname.new(dest).realdirpath
|
|
114
|
+
base = Pathname.new(base).realpath
|
|
115
|
+
dir = if dest.directory?
|
|
116
|
+
true
|
|
117
|
+
elsif src.size > 1
|
|
118
|
+
raise Errno::ENOENT, dest.cleanpath.to_s unless create && !dest.exist?
|
|
119
|
+
|
|
120
|
+
dest.mkpath
|
|
121
|
+
true
|
|
122
|
+
end
|
|
123
|
+
targets = src.map! { |file| [base + file, dir ? dest + File.basename(file) : dest] }
|
|
124
|
+
return if !force && (targets = targets.reject { |to| to[1].exist? }).empty?
|
|
125
|
+
|
|
126
|
+
type = System.send :parse_link, link
|
|
127
|
+
targets.each do |file, to|
|
|
128
|
+
case type
|
|
129
|
+
when 0
|
|
130
|
+
FileUtils.cp(file, to, preserve: preserve, verbose: verbose)
|
|
131
|
+
when 1
|
|
132
|
+
FileUtils.ln_s(file, to, force: force, verbose: verbose)
|
|
133
|
+
when 2
|
|
134
|
+
FileUtils.ln_s(file.relative_path_from(dir ? to.dirname : to), to, force: force, verbose: verbose)
|
|
135
|
+
else
|
|
136
|
+
FileUtils.ln(file, to, force: force, verbose: verbose)
|
|
98
137
|
end
|
|
99
138
|
end
|
|
100
|
-
|
|
101
|
-
when 'hard', 1
|
|
102
|
-
FileUtils.ln(src, dest, force: force, verbose: verbose)
|
|
103
|
-
when ::TrueClass, 'soft', 0
|
|
104
|
-
FileUtils.ln_s(src, dest, force: force, verbose: verbose)
|
|
105
|
-
else
|
|
106
|
-
FileUtils.cp(src, dest, verbose: verbose)
|
|
107
|
-
end
|
|
139
|
+
nil
|
|
108
140
|
end
|
|
109
141
|
end
|
|
110
142
|
end
|
data/lib/squared/common/utils.rb
CHANGED
|
@@ -9,21 +9,44 @@ module Squared
|
|
|
9
9
|
module Utils
|
|
10
10
|
module_function
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
|
|
12
|
+
def as_a(obj, *meth, flat: nil, compact: false, &blk)
|
|
13
|
+
return [] if obj.nil?
|
|
14
|
+
|
|
15
|
+
unless obj.is_a?(::Array)
|
|
16
|
+
obj = if obj.respond_to?(:to_ary)
|
|
17
|
+
obj.to_ary
|
|
18
|
+
elsif obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
|
|
19
|
+
val
|
|
20
|
+
else
|
|
21
|
+
[obj]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
obj = flat.is_a?(::Numeric) ? obj.flatten(flat) : obj.flatten if flat
|
|
25
|
+
obj = obj.compact if compact
|
|
26
|
+
obj = obj.map(&meth.shift) until meth.empty?
|
|
27
|
+
return obj unless block_given?
|
|
28
|
+
|
|
29
|
+
obj.select(&blk)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def split_escape(val, char: ',', &blk)
|
|
33
|
+
ret = val.split(/\s*(?<!\\)#{char}\s*/)
|
|
34
|
+
return ret unless block_given?
|
|
35
|
+
|
|
36
|
+
ret.each(&blk)
|
|
14
37
|
end
|
|
15
38
|
|
|
16
39
|
def split_option(val)
|
|
17
40
|
val = val.strip
|
|
18
41
|
return [val, '', ''] unless (i = val.index('='))
|
|
19
42
|
|
|
20
|
-
last = val[
|
|
43
|
+
last = val[i.succ..-1].strip
|
|
21
44
|
quote = ''
|
|
22
45
|
if last =~ /\A(["'])(.+)\1\z/
|
|
23
46
|
last = $2
|
|
24
47
|
quote = $1
|
|
25
48
|
end
|
|
26
|
-
[val[0..
|
|
49
|
+
[val[0..i.pred], last, quote]
|
|
27
50
|
end
|
|
28
51
|
|
|
29
52
|
def task_invoke(*cmd, args: [], exception: true, warning: true)
|
|
@@ -105,15 +128,15 @@ module Squared
|
|
|
105
128
|
end
|
|
106
129
|
end
|
|
107
130
|
|
|
108
|
-
def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil)
|
|
131
|
+
def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil, **)
|
|
109
132
|
ret = env_value(key, suffix: suffix, strict: strict)
|
|
110
|
-
return
|
|
133
|
+
return Array(equals).any? { |val| val.to_s == ret } unless equals.nil?
|
|
111
134
|
|
|
112
135
|
ret.empty? || (ignore && Array(ignore).any? { |val| val.to_s == ret }) ? default : ret
|
|
113
136
|
end
|
|
114
137
|
|
|
115
138
|
def env_key(*val)
|
|
116
|
-
val.join('_').
|
|
139
|
+
val.join('_').gsub(/\W+/, '_').upcase
|
|
117
140
|
end
|
|
118
141
|
|
|
119
142
|
def env_value(key, default = '', suffix: nil, strict: false)
|
|
@@ -150,19 +173,11 @@ module Squared
|
|
|
150
173
|
end
|
|
151
174
|
|
|
152
175
|
def env_pipe(key, default = 1, suffix: nil, strict: false, root: nil)
|
|
153
|
-
out = 1
|
|
154
176
|
case key
|
|
155
177
|
when ::String
|
|
156
178
|
case (ret = env_value(key, suffix: suffix, strict: strict))
|
|
157
179
|
when '0', '1', '2'
|
|
158
180
|
return ret.to_i
|
|
159
|
-
else
|
|
160
|
-
out = default if default.is_a?(::Numeric)
|
|
161
|
-
if ret.include?(File::SEPARATOR)
|
|
162
|
-
default = ret
|
|
163
|
-
elsif key.include?(File::SEPARATOR)
|
|
164
|
-
default = key
|
|
165
|
-
end
|
|
166
181
|
end
|
|
167
182
|
when ::Numeric
|
|
168
183
|
return key if key.between?(0, 2)
|
|
@@ -173,7 +188,7 @@ module Squared
|
|
|
173
188
|
(root ? Pathname.new(root) + default : Pathname.new(default)).realdirpath
|
|
174
189
|
rescue StandardError => e
|
|
175
190
|
warn e
|
|
176
|
-
|
|
191
|
+
1
|
|
177
192
|
end
|
|
178
193
|
end
|
|
179
194
|
|