squared 0.0.10 → 0.0.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71eae17e75e9ebe9a4fbe250f49da6397b169f06ac85c7f77170b9fc575bd63e
4
- data.tar.gz: f68b5c36da52802d0b952c54a406d6d6bde3085308c465c2f058c8c944dce894
3
+ metadata.gz: 2d9e8c772c9f4d0ce5c54dbeb1b9583d2e477f155036faf34cfc547659c34ec4
4
+ data.tar.gz: 87de412a78c0071eabd4b26713cbf84978a92fca6ea1a6dfe18653ddf22c90ee
5
5
  SHA512:
6
- metadata.gz: 515aa7c65dd969fb9dd165a38716695a6c08ccbf0597ef3d7936bcd70750c2c54f661fc44e9dc303d34b8d99947d27939039654ca5ffd43afcf33f917deb2866
7
- data.tar.gz: cfe3827d03d56619de9d3c60a4df2b249ff1f802bc9a6be407b96c5db95fb14faf6b3719e657c83dc046287d62272f1cf2e676fdad67da345abc93675e511474
6
+ metadata.gz: '08475f426b15c41dab20fbead5d7c1ead70f5d80384e0a0772cbe7b101512a4402a1bb1231b2550f7da16aac2796f8411f6a6e3e570ae728d59b03f88fea5960'
7
+ data.tar.gz: 5c0334640b20dda82641925cd94b41d76be4cd4e603355fef593a5cd69731ac926febab67f3ffa494267291ec9d89efba2f8a9ac4dde978ab2814a0f8a481a67
data/README.ruby.md CHANGED
@@ -34,7 +34,14 @@ Projects from any accessible folder can be added either relative to `REPO_ROOT`
34
34
 
35
35
  ```ruby
36
36
  require "squared"
37
- require "squared/workspace/repo" # Repo (optional)
37
+
38
+ require "squared/workspace"
39
+ require "squared/workspace/repo" # Optional
40
+ require "squared/workspace/project/node" #
41
+ require "squared/workspace/project/python" #
42
+ require "squared/workspace/project/ruby" #
43
+ # OR
44
+ require "squared/app" # All workspace related modules
38
45
 
39
46
  # NODE_ENV = production
40
47
  # REPO_ROOT = /workspaces
@@ -52,7 +59,7 @@ require "squared/workspace/repo" # Repo (optional)
52
59
 
53
60
  Workspace::Application
54
61
  .new(Dir.pwd, main: "squared") # Dir.pwd? (main? is implicitly basename)
55
- .banner("group", "project", styles: %i[yellow black], border: "bold") # name | project | path | ref | group?
62
+ .banner("group", "project", styles: ["yellow", "black"], border: "bold") # name | project | path | ref | group? | parent? | version?
56
63
  .repo("https://github.com/anpham6/squared-repo", "nightly", script: ["build:dev", "build:prod"], ref: :node) # Repo (optional)
57
64
  .run("rake install", ref: :ruby)
58
65
  .depend(false, group: "default")
@@ -63,13 +70,17 @@ Workspace::Application
63
70
  "CFLAGS" => "-fPIC -O1"
64
71
  })
65
72
  .add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
66
- .add("logger", copy: { from: "lib", glob: "**/*.rb", gemdir: "~/.rvm/gems/ruby-3.3.5/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
67
- .add("e-mc", "emc", copy: { from: "publish", into: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
68
- .add("pi-r", "pir", copy: { from: "publish", into: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
73
+ .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.3.5/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
74
+ .add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
75
+ .add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
69
76
  .add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
70
- add("publish/sqd-cli", "cli", exclude: [:git])
71
- add("publish/sqd-serve")
77
+ add("publish/sqd-cli", "cli", exclude: [:git]) # rake cli:build
78
+ add("publish/sqd-serve") # rake sqd-serve:build
72
79
  add("publish/sqd-admin", group: "sqd", exclude: [:base])
80
+ # OR
81
+ with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
82
+ # OR
83
+ add(["publish/sqd-cli", "publish/sqd-serve", "publish/sqd-admin"], true, exclude: [:base]) # rake squared:sqd-serve:build
73
84
  end
74
85
  .add("squared/sqd", exclude: [:git]) do
75
86
  variable_set :script, "build:sqd" # Override detection
@@ -77,7 +88,7 @@ Workspace::Application
77
88
  variable_set :clean, ["build/sqd/"]
78
89
  end
79
90
  .style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
80
- .build(default: "status", parallel: ["pull", "fetch", "rebase", "copy", "clean"]) do |workspace|
91
+ .build(default: "status", parallel: ["pull", "fetch", "rebase", "copy", "clean", "outdated:ruby"]) do |workspace|
81
92
  workspace
82
93
  .enable_aixterm
83
94
  .style({
@@ -97,28 +108,80 @@ Workspace::Application
97
108
  .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
98
109
  .group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
99
110
  pathname: {
100
- run: "rake compile" # rake rb:pathname:build
111
+ run: "rake compile" # rake rb:pathname:build
101
112
  }
102
113
  })
103
- .with(:python) do # ref=Symbol | group=String
104
- banner("path", command: false, styles: "yellow") #
105
- doc("make html") # rake rb:doc:python
106
- run(false) # rake rb:build:python (disabled)
107
- exclude(%i[base git]) # Project::Git.ref (superclass)
108
- add("android-docs", "android") # rake rb:android:doc
109
- add("chrome-docs", "chrome") # rake rb:chrome:doc
110
- end #
114
+ .with(:python) do # ref=Symbol | group=String
115
+ banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
116
+ doc("make html") # rake rb:doc:python
117
+ run(false) # rake rb:build:python (disabled)
118
+ exclude(%i[base git]) # Project::Git.ref (superclass)
119
+ add("android-docs", "android") # rake rb:android:doc
120
+ add("chrome-docs", "chrome") # rake rb:chrome:doc
121
+ end #
111
122
  .style("inline", "bold")
112
123
  .build
113
124
  ```
114
125
 
115
- **NOTE**: The use of "**ref**" (class name) is only necessary when running `repo:init` for the first time into an empty directory.
126
+ **NOTE**: The use of "**ref**" (class name) is only necessary when initializing an empty directory (e.g. *rake repo:init*).
127
+
128
+ ### Graph
129
+
130
+ ```ruby
131
+ Workspace::Application
132
+ .new(main: "squared")
133
+ .with(:python) do
134
+ add("android-docs", "android")
135
+ add("chrome-docs", "chrome", graph: "android")
136
+ end
137
+ .with(:node) do
138
+ graph(["build", "copy"]) # Optional
139
+ add("e-mc", "emc")
140
+ add("pi-r", "pir", graph: "emc")
141
+ add("squared-express", "express", graph: "pir")
142
+ add("squared", graph: ["chrome", "express"])
143
+ end
144
+ .with(:ruby) do
145
+ add("pathname")
146
+ add("fileutils", graph: "pathname")
147
+ add("optparse")
148
+ add("rake", graph: ["fileutils", "optparse"])
149
+ end
150
+ .build
151
+ ```
152
+
153
+ ```sh
154
+ rake pir:graph # emc + pir
155
+ rake express:graph # emc + pir + express
156
+ rake chrome:graph # android + chrome
157
+ rake graph:python # same
158
+ rake squared:graph # android + chrome + emc + pir + express + squared
159
+ rake graph:node # same
160
+ rake rake:graph # pathname + fileutils + optparse + rake
161
+ rake graph:ruby # same
162
+ rake graph # graph:node + graph:ruby
163
+ ```
164
+
165
+ ### Batch
166
+
167
+ ```ruby
168
+ Workspace::Series.batch(:ruby, :node, {
169
+ stage: %i[graph test],
170
+ reset: %i[stash pull]
171
+ })
172
+ ```
173
+
174
+ ### Rename
175
+
176
+ ```ruby
177
+ Workspace::Series.rename("depend", "install")
178
+ ```
116
179
 
117
180
  ## Usage
118
181
 
119
182
  ```sh
120
- rake -T # List tasks
121
- rake # rake status (usually "build")
183
+ rake -T # List tasks
184
+ rake # rake status (usually "build")
122
185
 
123
186
  # GIT_OPTIONS=rebase
124
187
  rake pull # All except "default" + "app"
@@ -145,6 +208,7 @@ rake build:app # squared + cli + sqd-serve
145
208
  rake squared:build:workspace # cli + sqd-serve
146
209
  rake pull:sqd # sqd-admin
147
210
  rake squared:pull:workspace # sqd-serve + sqd-admin
211
+ rake squared:outdated:workspace # cli + sqd-serve + sqd-admin
148
212
  ```
149
213
 
150
214
  ## Methods
@@ -153,6 +217,7 @@ Task:
153
217
 
154
218
  * run
155
219
  * depend
220
+ * graph
156
221
  * test
157
222
  * doc
158
223
  * clean
@@ -179,14 +244,21 @@ Non-task:
179
244
  ### Build
180
245
 
181
246
  ```ruby
247
+ # :env :run :opts
182
248
  # LD_LIBRARY_PATH="path/to/lib" CFLAGS="-Wall" gcc a.c -o a.o -c
183
249
  BUILD_${NAME} # gcc a.c -o a.o
184
- BUILD_${NAME}_OPTS # -c
185
- BUILD_${NAME}_ENV # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (json)
186
-
187
- # Scripts
188
- BUILD_${NAME}_DEV # pattern,0,1
189
- BUILD_${NAME}_PROD # pattern,0,1
250
+ BUILD_OPTS_${NAME} # -c
251
+ BUILD_ENV_${NAME} # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (hash/json)
252
+
253
+ # :env :opts :script
254
+ # NODE_ENV="production" NO_COLOR="1" npm run --loglevel=error --workspaces=false build:dev
255
+ BUILD_${NAME} # build:dev
256
+ BUILD_OPTS_${NAME} # --loglevel=error --workspaces=false
257
+ BUILD_ENV_${NAME} # {"NODE_ENV":"production","NO_COLOR":"1"} (hash/json)
258
+ BUILD_DEV_${NAME} # pattern,0,1 (:dev)
259
+ BUILD_PROD_${NAME} # pattern,0,1 (:prod)
260
+
261
+ BUILD_${NAME}=0 # skip project
190
262
  ```
191
263
 
192
264
  These options also support the project specific suffix `${NAME}`. (e.g. LOG_FILE_SQUARED)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'workspace'
4
+ require_relative 'workspace/repo'
5
+ require_relative 'workspace/project/node'
6
+ require_relative 'workspace/project/python'
7
+ require_relative 'workspace/project/ruby'
8
+ require_relative 'config'
9
+
10
+ Common = Squared::Common
@@ -2,10 +2,16 @@
2
2
 
3
3
  module Squared
4
4
  module Common
5
- KEY = {
5
+ ARG = {
6
6
  PIPE: 1,
7
+ OUT: nil,
8
+ VERBOSE: nil,
7
9
  FAIL: false,
8
- COMMON: true
10
+ COMMON: true,
11
+ BANNER: true,
12
+ SPACE: ' => ',
13
+ GRAPH: ['│', '─', '├', '└', '┬'],
14
+ COLOR: ENV.fetch('NO_COLOR', '').empty?
9
15
  }
10
16
  VAR = {
11
17
  project: {},
@@ -70,6 +76,7 @@ module Squared
70
76
  end
71
77
 
72
78
  def __freeze__
79
+ ARG.freeze
73
80
  VAR.each_value(&:freeze)
74
81
  VAR[:theme].each_value(&:freeze)
75
82
  VAR.freeze
@@ -77,30 +84,19 @@ module Squared
77
84
 
78
85
  module_function
79
86
 
80
- def env(key, default = nil, equals: nil, ignore: nil, **)
81
- ret = ENV.fetch(key, '')
82
- return ret == equals.to_s unless equals.nil?
83
-
84
- ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
85
- end
86
-
87
- def message(*args, hint: nil)
88
- args.reject(&:empty?).join(' => ') + (hint ? " (#{hint})" : '')
89
- end
90
-
91
87
  def as_a(obj, meth = nil, flat: nil, compact: false)
92
88
  return [] if obj.nil?
93
89
 
94
90
  unless obj.is_a?(::Array)
95
- obj = if !obj.is_a?(::Hash) && obj.respond_to?(:to_a) && (val = obj.to_a).is_a?(::Array)
91
+ obj = if obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
96
92
  val
97
93
  else
98
94
  [obj]
99
95
  end
100
96
  end
101
97
  obj = obj.flatten(flat.is_a?(::Numeric) ? flat : nil) if flat
102
- obj = obj.map(&meth) if meth
103
- compact ? obj.compact : obj
98
+ obj = obj.compact if compact
99
+ meth ? obj.map(&meth) : obj
104
100
  end
105
101
  end
106
102
  end
@@ -1,12 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
+ require 'forwardable'
4
5
 
5
6
  module Squared
6
7
  module Common
8
+ class SymSet
9
+ extend Forwardable
10
+
11
+ def self.to_s
12
+ super.match(/[^:]+$/)[0]
13
+ end
14
+
15
+ def_delegators :@data, :+, :each, :each_with_index, :entries, :to_a, :include?
16
+
17
+ def initialize(data = [])
18
+ @data = ::Set.new(data)
19
+ end
20
+
21
+ def add(val)
22
+ @data.add(val.to_sym)
23
+ end
24
+
25
+ def to_s
26
+ @data.to_s.sub('Set', SymSet.to_s)
27
+ end
28
+
29
+ alias inspect to_s
30
+ end
31
+
7
32
  class JoinSet < ::Set
8
33
  def self.to_s
9
- super.to_s.match(/[^:]+$/)[0]
34
+ super.match(/[^:]+$/)[0]
10
35
  end
11
36
 
12
37
  def initialize(data = [], delim: ' ')
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
3
4
  require 'logger'
4
5
 
5
6
  require_relative 'base'
@@ -40,7 +41,7 @@ module Squared
40
41
  private
41
42
 
42
43
  def sub_style(val, *args, styles: nil, pat: nil, index: 1)
43
- return val unless ENV.fetch('NO_COLOR', '').empty? && !__get__(:no_color)
44
+ return val unless ARG[:COLOR]
44
45
 
45
46
  if pat && index != 0
46
47
  return val unless (data = pat.match(val))
@@ -106,7 +107,7 @@ module Squared
106
107
  out
107
108
  end
108
109
 
109
- def check_style(*args, empty: true)
110
+ def check_style(args, empty: true)
110
111
  ret = []
111
112
  colors = __get__(:colors)
112
113
  as_a(args, flat: true, compact: true).each do |val|
@@ -123,7 +124,7 @@ module Squared
123
124
  ret if empty || !ret.empty?
124
125
  end
125
126
 
126
- def apply_style(data, key, *args, empty: true)
127
+ def apply_style(data, key, args, empty: true)
127
128
  return if data.is_a?(::Symbol) && (data = __get__(:theme)[data]).nil?
128
129
 
129
130
  set = ->(k, v) { data[k] = check_style(v, empty: empty) }
@@ -137,15 +138,15 @@ module Squared
137
138
  def log_sym(level)
138
139
  if level.is_a?(::Numeric)
139
140
  case level
140
- when Logger::DEBUG
141
+ when ::Logger::DEBUG
141
142
  :debug
142
- when Logger::INFO
143
+ when ::Logger::INFO
143
144
  :info
144
- when Logger::WARN
145
+ when ::Logger::WARN
145
146
  :warn
146
- when Logger::ERROR
147
+ when ::Logger::ERROR
147
148
  :error
148
- when Logger::FATAL
149
+ when ::Logger::FATAL
149
150
  :fatal
150
151
  else
151
152
  :unknown
@@ -155,7 +156,7 @@ module Squared
155
156
  end
156
157
  end
157
158
 
158
- def log_title(level, color: true)
159
+ def log_title(level, color: ARG[:COLOR])
159
160
  theme = __get__(:theme)[:logger]
160
161
  styles = theme[level = log_sym(level)] || theme[level = :unknown]
161
162
  case (ret = +level.to_s.upcase)
@@ -165,7 +166,7 @@ module Squared
165
166
  color ? sub_style(ret, *styles) : ret
166
167
  end
167
168
 
168
- def log_message(level, *args, subject: nil, hint: nil, color: true)
169
+ def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR])
169
170
  args = args.map(&:to_s)
170
171
  if args.size > 1
171
172
  title = log_title(level, color: false)
@@ -183,49 +184,103 @@ module Squared
183
184
  end
184
185
  end
185
186
 
186
- def raise_error(*args, hint: nil, kind: ArgumentError)
187
- raise kind, message(*args, hint: hint)
187
+ def puts_oe(*args, pipe: 1)
188
+ if pipe.is_a?(::Pathname)
189
+ begin
190
+ ::File.open(pipe, 'a') do |f|
191
+ br = ::File::SEPARATOR == '\\' ? "\r\n" : "\n"
192
+ args.flatten.each { |val| f.write("#{strip_style(val.chomp)}#{br}") }
193
+ end
194
+ return
195
+ rescue StandardError
196
+ pipe = 2
197
+ end
198
+ end
199
+ (pipe == 2 ? $stderr : $stdout).puts(*args)
188
200
  end
189
201
 
190
202
  module_function
191
203
 
192
- def emphasize(val, title: nil, cols: nil, sub: nil, pipe: nil)
204
+ def message(*args, hint: nil, empty: false)
205
+ (empty ? args.reject { |val| val.nil? || val.empty? } : args).join(ARG[:SPACE]) + (hint ? " (#{hint})" : '')
206
+ end
207
+
208
+ def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, border: nil, pipe: nil)
193
209
  n = 0
194
- if title
195
- title = title.to_s
196
- n = title.size
210
+ max = ->(v) { n = [n, v.max_by(&:size).size].max }
211
+ set = lambda do |v|
212
+ ret = as_a(v, :to_s)
213
+ max.(ret)
214
+ ret
197
215
  end
216
+ title &&= set.(title)
217
+ footer &&= set.(footer)
198
218
  if val.is_a?(::Array)
199
- lines = val
219
+ lines = val.map(&:to_s)
200
220
  else
201
221
  lines = val.to_s.lines.map(&:chomp)
202
- lines[0] = "#{val.class}: #{lines.first}" if (err = val.is_a?(::StandardError))
222
+ lines[0] = "#{val.class}: #{lines.first}" if (err = val.is_a?(StandardError))
203
223
  end
204
- n = cols || [n, lines.max_by(&:size).size].max
224
+ n = cols || max.(lines)
205
225
  if $stdout.tty?
206
226
  require 'io/console'
207
227
  (n = [n, $stdout.winsize[1] - 4].min) rescue nil
208
228
  end
209
229
  out = []
210
230
  bord = '-' * (n + 4)
211
- sub = [sub] if sub && !sub.is_a?(::Array)
231
+ bord = sub_style(bord, styles: border) if border
232
+ sub = as_a(sub)
212
233
  pr = lambda do |line|
213
234
  s = line.ljust(n)
214
- sub&.each { |h| s = sub_style(s, **h) }
215
- "| #{s} |"
235
+ sub.each { |h| s = sub_style(s, **h) }
236
+ s = "| #{s} |"
237
+ if border
238
+ s = sub_style(s, pat: /^(\|)(.+)$/m, styles: border)
239
+ s = sub_style(s, pat: /^(.+)(\|)$/m, styles: border, index: 2)
240
+ end
241
+ s
216
242
  end
217
243
  out << bord
218
- out << pr.(title) << bord if title
244
+ if title
245
+ out += title.map { |t| pr.(t) }
246
+ out << bord
247
+ end
219
248
  lines.each { |line| out << pr.(line) }
220
249
  out << bord
250
+ if footer
251
+ unless sub.empty? && !right
252
+ footer.map! do |s|
253
+ s = s.rjust(n + 4) if right
254
+ sub.each { |h| s = sub_style(s, **h) }
255
+ s
256
+ end
257
+ end
258
+ out += footer
259
+ end
221
260
  if block_given?
222
261
  yield out
223
- elsif pipe.respond_to?(:puts)
262
+ elsif pipe
263
+ case pipe
264
+ when 0
265
+ pipe = $stdin
266
+ when 2
267
+ pipe = $stderr
268
+ else
269
+ pipe = $stdout unless pipe.respond_to?(:puts)
270
+ end
224
271
  pipe.puts out
225
272
  else
226
273
  err ? warn(out) : puts(out)
227
274
  end
228
275
  end
276
+
277
+ def strip_style(val)
278
+ val.gsub(/\x1B\[(\d+;?)+m/, '')
279
+ end
280
+
281
+ def raise_error(*args, hint: nil, kind: ArgumentError)
282
+ raise kind, message(*args, hint: hint, empty: true)
283
+ end
229
284
  end
230
285
  end
231
286
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Squared
4
+ module Common
5
+ module Prompt
6
+ module_function
7
+
8
+ def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
9
+ require 'readline'
10
+ require 'timeout'
11
+ agree = /^#{agree}$/i if agree.is_a?(::String)
12
+ cancel = /^#{cancel}$/i if cancel.is_a?(::String)
13
+ Timeout.timeout(timeout) do
14
+ begin
15
+ while (ch = Readline.readline(msg, true))
16
+ ch = ch.chomp
17
+ case (ch.empty? ? default : ch)
18
+ when agree
19
+ return true
20
+ when cancel
21
+ return false
22
+ end
23
+ attempts -= 1
24
+ exit 1 unless attempts >= 0
25
+ end
26
+ rescue Interrupt
27
+ puts
28
+ exit 0
29
+ else
30
+ false
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -9,9 +9,10 @@ module Squared
9
9
  module_function
10
10
 
11
11
  def shell_escape(val, quote: false)
12
- return Shellwords.escape(val) unless ::Rake::Win32.windows?
12
+ val = val.to_s
13
+ return ::Shellwords.escape(val) unless ::Rake::Win32.windows?
13
14
 
14
- quote ? shell_quote(opt, force: false) : opt
15
+ quote ? shell_quote(val, force: false) : val
15
16
  end
16
17
 
17
18
  def shell_quote(val, force: true)
@@ -22,7 +23,7 @@ module Squared
22
23
  end
23
24
 
24
25
  def shell_split(val, quote: false, join: false)
25
- ret = Shellwords.split(val).map do |opt|
26
+ ret = ::Shellwords.split(val).map do |opt|
26
27
  if (data = /^(--?[^= ]+)(=|\s+)?(["'])?(.+?)\3?$/m.match(opt))
27
28
  next opt unless data[2] && !data[3]
28
29
 
@@ -8,67 +8,37 @@ module Squared
8
8
  module System
9
9
  module_function
10
10
 
11
- def shell(*cmd, **kwargs)
11
+ def shell(*args, **kwargs)
12
12
  if RUBY_VERSION =~ /^2\.[0-5]\./
13
13
  exception = kwargs.delete(:exception)
14
- ret = system(*cmd, **kwargs)
15
- raise $?.to_s if !ret && exception
14
+ ret = system(*args, **kwargs)
15
+ return ret if ret || !exception
16
16
 
17
- ret
17
+ raise $?.to_s
18
18
  else
19
- system(*cmd, **kwargs)
20
- end
21
- end
22
-
23
- def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
24
- require 'readline'
25
- require 'timeout'
26
- agree = /^#{agree}$/i if agree.is_a?(::String)
27
- cancel = /^#{cancel}$/i if cancel.is_a?(::String)
28
- Timeout.timeout(timeout) do
29
- begin
30
- while (ch = Readline.readline(msg, true))
31
- ch = ch.chomp
32
- ch = default if ch.empty?
33
- case ch
34
- when agree
35
- return true
36
- when cancel
37
- return false
38
- end
39
- attempts -= 1
40
- exit 1 unless attempts >= 0
41
- end
42
- rescue Interrupt
43
- puts
44
- exit 0
45
- else
46
- false
47
- end
19
+ system(*args, **kwargs)
48
20
  end
49
21
  end
50
22
 
51
23
  def copy_d(src, dest, glob: ['**/*'], create: false, verbose: true)
52
- src = Pathname.new(src)
53
- dest = Pathname.new(dest)
24
+ src = ::Pathname.new(src)
25
+ dest = ::Pathname.new(dest)
54
26
  raise "#{dest} (not found)" if !create && !dest.exist?
55
27
 
56
28
  subdir = []
57
29
  files = 0
58
30
  dest.mkpath if create
59
- glob = [glob] unless glob.is_a?(::Array)
60
- glob.each do |val|
61
- Dir.glob(src.join(val)) do |path|
62
- ent = Pathname.new(path)
63
- next if ent.directory?
31
+ (glob.is_a?(::Array) ? glob : [glob]).each do |val|
32
+ ::Dir.glob(src.join(val)) do |path|
33
+ next if (path = ::Pathname.new(path)).directory?
64
34
 
65
- target = dest.join(ent.relative_path_from(src))
35
+ target = dest.join(path.relative_path_from(src))
66
36
  dir = target.dirname
67
37
  unless subdir.include?(dir.to_s)
68
38
  dir.mkpath
69
39
  subdir << dir.to_s
70
40
  end
71
- copy_f ent, target
41
+ copy_f path, target
72
42
  files += 1
73
43
  end
74
44
  end
@@ -77,15 +47,13 @@ module Squared
77
47
 
78
48
  def copy_f(src, dest, overwrite: true, verbose: false)
79
49
  unless overwrite
80
- path = Pathname.new(dest)
81
- if path.directory?
82
- src = [src] unless src.is_a?(::Array)
83
- src = src.reject { |val| path.join(File.basename(val)).exist? }
50
+ if (path = ::Pathname.new(dest)).directory?
51
+ src = (src.is_a?(::Array) ? src : [src]).reject { |val| path.join(::File.basename(val)).exist? }
84
52
  elsif path.exist?
85
53
  return
86
54
  end
87
55
  end
88
- FileUtils.cp(src, dest, verbose: verbose)
56
+ ::FileUtils.cp(src, dest, verbose: verbose)
89
57
  end
90
58
  end
91
59
  end