squared 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -36,7 +36,7 @@ module Squared
36
36
 
37
37
  def find(path: nil, ref: nil)
38
38
  if ref.is_a?(::Symbol) || ref.is_a?(::String)
39
- ret = project_kind.find { |proj| proj.to_sym == ref.to_sym }
39
+ ret = project_kind.find { |proj| proj.ref == ref.to_sym }
40
40
  return ret if ret
41
41
  end
42
42
  project_kind.find { |proj| proj.is_a?(path) } if path
@@ -51,14 +51,14 @@ module Squared
51
51
 
52
52
  @project_kind = []
53
53
 
54
- attr_reader :main, :root, :home, :series, :theme, :warning
55
- attr_accessor :exception, :pipe, :verbose
54
+ attr_reader :main, :root, :home, :series, :theme
55
+ attr_accessor :exception, :warning, :pipe, :verbose
56
56
 
57
- def initialize(main, *, common: true, exception: false, pipe: false, verbose: nil, **)
57
+ def initialize(main, *, exception: false, pipe: false, verbose: nil, **kwargs)
58
58
  @main = main.to_s
59
59
  @home = Pathname.pwd
60
60
  @root = @home.parent
61
- @series = Series.new(TASK_BASE, self)
61
+ @series = Series.new(TASK_BASE)
62
62
  @project = {}
63
63
  @extensions = []
64
64
  @script = {
@@ -68,11 +68,12 @@ module Squared
68
68
  dev: nil,
69
69
  prod: nil
70
70
  }
71
- @theme = common && @verbose ? __get__(:theme)[:workspace] : {}
71
+ @theme = kwargs.key?(:common) && !kwargs[:common] ? {} : __get__(:theme)[:workspace]
72
72
  @exception = exception.is_a?(String) ? !env(exception, ignore: '0').nil? : exception
73
73
  @pipe = pipe.is_a?(String) ? !env(pipe, ignore: '0').nil? : pipe
74
74
  @verbose = verbose.nil? ? !@pipe : verbose
75
- @warning = true
75
+ @warning = @verbose
76
+ __set__(:no_color, true) if @pipe
76
77
  end
77
78
 
78
79
  def build(**kwargs)
@@ -81,82 +82,84 @@ module Squared
81
82
  @project.each_value do |proj|
82
83
  next unless proj.enabled?
83
84
 
84
- series.populate(proj)
85
85
  proj.populate(**kwargs)
86
+ series.populate(proj)
86
87
  end
87
88
 
88
89
  Application.project_kind.each { |obj| obj.populate(self, **kwargs) }
89
90
  @extensions.each { |ext| __send__(ext, **kwargs) }
90
91
 
91
- series[:refresh].clear if series[:refresh].all? { |val| val.end_with?(':build') }
92
-
93
- task default: kwargs[:default] if series.has?(kwargs[:default]) && !task_defined?('default')
94
-
95
- if series.has?('build')
96
- init = ['depend', dev? && series.has?('refresh') ? 'refresh' : 'build']
92
+ __build__(**kwargs)
93
+ series.build(**kwargs)
97
94
 
98
- task default: init[1] unless task_defined?('default')
95
+ yield self if block_given?
96
+ end
99
97
 
100
- if series.has?(init[0]) && !task_defined?('init')
101
- desc 'init'
102
- task init: init
103
- end
98
+ def with(group: nil, ref: nil)
99
+ @group = nil
100
+ @ref = nil
101
+ if group
102
+ @group = group
103
+ elsif ref
104
+ @ref = ref
104
105
  end
105
- series.finalize!(kwargs.fetch(:parallel, []))
106
-
107
- yield self if block_given?
106
+ self
108
107
  end
109
108
 
110
- def run(script, group: nil, ref: nil)
109
+ def run(script, group: @group, ref: @ref)
111
110
  script_command :run, script, group, ref
112
111
  end
113
112
 
114
- def depend(script, group: nil, ref: nil)
113
+ def depend(script, group: @group, ref: @ref)
115
114
  script_command :depend, script, group, ref
116
115
  end
117
116
 
118
- def clean(script, group: nil, ref: nil)
117
+ def clean(script, group: @group, ref: @ref)
119
118
  script_command :clean, script, group, ref
120
119
  end
121
120
 
122
- def doc(script, group: nil, ref: nil)
121
+ def doc(script, group: @group, ref: @ref)
123
122
  script_command :doc, script, group, ref
124
123
  end
125
124
 
126
- def test(script, group: nil, ref: nil)
125
+ def test(script, group: @group, ref: @ref)
127
126
  script_command :test, script, group, ref
128
127
  end
129
128
 
130
- def add(name, path = nil, ref: nil, **kwargs)
131
- path = root_path((path || name).to_s)
132
- project = if !ref.is_a?(::Class)
133
- Application.find(path: path, ref: ref)
134
- elsif ref < Project::Base
135
- ref
136
- end
137
- instance = (project || Project::Base).new(name, path, self, **kwargs)
138
- @project[n = name.to_sym] = instance
139
- __get__(:project)[n] = instance unless kwargs[:private]
129
+ def add(name, path = nil, **kwargs)
130
+ ref = if kwargs.key?(:ref)
131
+ kwargs.delete(:ref)
132
+ elsif !@ref.is_a?(::Array)
133
+ @ref
134
+ end
135
+ kwargs[:group] = @group if !kwargs.key?(:group) && !@group.is_a?(::Array)
136
+ path = root_path(path || name.to_s)
137
+ proj = ((if !ref.is_a?(::Class)
138
+ Application.find(path: path, ref: ref)
139
+ elsif ref < Project::Base
140
+ ref
141
+ end) || Project::Base).new(name, path, self, **kwargs)
142
+ @project[name = name.to_sym] = proj
143
+ __get__(:project)[name] = proj unless kwargs[:private]
140
144
  self
141
145
  end
142
146
 
143
- def group(name, path, **kwargs)
147
+ def group(name, path, override: {}, **kwargs)
144
148
  root_path(path).children.map do |ent|
145
149
  next unless (dir = Pathname.new(ent)).directory?
146
150
 
147
151
  index = 0
148
152
  basename = dir.basename.to_s.to_sym
149
- override = kwargs.delete(basename)
150
153
  while @project[basename]
151
154
  index += 1
152
155
  basename = :"#{basename}-#{index}"
153
156
  end
154
- [basename, dir, override]
157
+ [basename, dir, override[basename]]
155
158
  end
156
- .each do |basename, dir, override|
157
- opts = kwargs.dup
158
- opts.merge!(override) if override
159
- add(basename, dir, group: name, **opts)
159
+ .each do |basename, dir, opts|
160
+ args = kwargs.dup
161
+ args.merge!(opts) if opts
162
+ add(basename, dir, group: name, **args)
160
163
  end
161
164
  self
162
165
  end
@@ -188,15 +191,17 @@ module Squared
188
191
  end
189
192
 
190
193
  def script(group: nil, ref: nil)
191
- if group || ref
192
- (group && @script[:group][group.to_sym]) || (ref && @script[:ref][ref.to_sym])
194
+ if group
195
+ @script[:group][group.to_sym]
196
+ elsif ref
197
+ @script[:ref][ref.to_sym]
193
198
  else
194
199
  @script[:build]
195
200
  end
196
201
  end
197
202
 
198
- def env(key, equals: nil, ignore: nil, default: nil)
199
- ret = ENV.fetch("#{key}_#{main.gsub(/[^\w]/, '_').upcase}", ENV[key]).to_s
203
+ def env(key, default = nil, equals: nil, ignore: nil)
204
+ ret = ENV.fetch("#{key}_#{main.gsub(/[^\w]+/, '_').upcase}", ENV[key]).to_s
200
205
  return ret == equals.to_s unless equals.nil?
201
206
 
202
207
  ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
@@ -240,47 +245,36 @@ module Squared
240
245
  ::Rake::Task.task_defined?(key)
241
246
  end
242
247
 
243
- def dev?(script: nil, pat: nil, global: nil)
244
- with?(:dev, script: script, pat: pat, global: global || (pat.nil? && global.nil?))
248
+ def dev?(global: nil, **kwargs)
249
+ script?(:dev, global: global.nil? ? kwargs[:pat].nil? : global, **kwargs)
245
250
  end
246
251
 
247
- def prod?(script: nil, pat: nil, global: false)
252
+ def prod?(global: false, **kwargs)
248
253
  return false if global && (@script[:dev] == true || !@script[:prod])
249
254
 
250
- with?(:prod, script: script, pat: pat, global: global)
255
+ script?(:prod, global: global, **kwargs)
251
256
  end
252
257
 
253
- protected
254
-
255
- def confirm(msg, agree: 'Y', cancel: 'N', default: nil, attempts: 5, timeout: 15)
256
- require 'readline'
257
- require 'timeout'
258
- agree = /^#{agree}$/i if agree.is_a?(String)
259
- cancel = /^#{cancel}$/i if cancel.is_a?(String)
260
- Timeout.timeout(timeout) do
261
- begin
262
- while (ch = Readline.readline(msg, true))
263
- ch = ch.chomp
264
- ch = default if ch.empty?
265
- case ch
266
- when agree
267
- return true
268
- when cancel
269
- return false
270
- end
271
- attempts -= 1
272
- exit 1 unless attempts >= 0
273
- end
274
- rescue Interrupt
275
- puts
276
- exit 0
277
- else
278
- false
279
- end
258
+ private
259
+
260
+ def __build__(**kwargs)
261
+ if !task_defined?('default') && (default = kwargs[:default]) && !series.has?(default)
262
+ task default: default
280
263
  end
281
- end
264
+ return unless series.has?('build')
282
265
 
283
- private
266
+ if (refresh = series[:refresh]).all? { |val| val.end_with?(':build') }
267
+ refresh.clear
268
+ end
269
+ init = ['depend', dev? && series.has?('refresh') ? 'refresh' : 'build']
270
+
271
+ task default: init[1] unless task_defined?('default')
272
+
273
+ return if task_defined?('init') || !series.has?(init[0])
274
+
275
+ desc 'init'
276
+ task init: init
277
+ end
284
278
 
285
279
  def script_command(task, val, group, ref)
286
280
  if group
@@ -294,8 +288,10 @@ module Squared
294
288
  self
295
289
  end
296
290
 
297
- def with?(state, script: nil, pat: nil, global: false)
298
- if global
291
+ def script?(state, script: nil, pat: nil, ref: nil, group: nil, global: false)
292
+ gr = @script[:ref][:_]
293
+ gg = @script[:group][:_]
294
+ if global && ((!ref && !group) || (!gr && !gg) || (ref && ref == gr) || (group && group == gg))
299
295
  pat = @script[state] if pat.nil?
300
296
  script ||= @script[:build]
301
297
  end
@@ -13,12 +13,9 @@ module Squared
13
13
  include Task
14
14
  include ::Rake::DSL
15
15
 
16
- SEM_VER = /^(\d+)(\.)(\d+)(?:(\.)(\d+))?$/.freeze
16
+ SEM_VER = /(\d+)(?:(\.)(\d+))?(?:(\.)(\d+))?/.freeze
17
17
 
18
18
  class << self
19
- include Common::Task
20
- include ::Rake::DSL
21
-
22
19
  def populate(*); end
23
20
 
24
21
  def tasks
@@ -34,24 +31,24 @@ module Squared
34
31
  end
35
32
  end
36
33
 
37
- def to_s
38
- super.to_s.match(/[^:]+$/)[0]
34
+ def ref
35
+ @ref ||= to_s.downcase.to_sym
39
36
  end
40
37
 
41
- def to_sym
42
- to_s.downcase.to_sym
38
+ def to_s
39
+ super.to_s.match(/[^:]+$/)[0]
43
40
  end
44
41
  end
45
42
 
46
43
  @@print_order = 0
47
44
  @@tasks = {}
48
45
 
49
- attr_reader :name, :project, :workspace, :group, :path, :log, :theme
46
+ attr_reader :name, :project, :workspace, :group, :path, :theme
50
47
  attr_accessor :warning
51
48
 
52
- def initialize(name, path, workspace, *, group: nil, log: nil, common: true, **kwargs)
49
+ def initialize(name, path, workspace, *, group: nil, **kwargs)
53
50
  @name = name.to_s
54
- @path = workspace.root_path(path.to_s)
51
+ @path = path
55
52
  @project = @path.basename.to_s
56
53
  @workspace = workspace
57
54
  @group = group&.to_s
@@ -61,40 +58,50 @@ module Squared
61
58
  @output = [kwargs[:run], nil]
62
59
  @copy = kwargs[:copy]
63
60
  @clean = kwargs[:clean]
61
+ @exclude = as_a(kwargs[:exclude])
64
62
  @warning = workspace.warning
65
63
  @theme = if !workspace.verbose
66
64
  {}
67
- elsif common
65
+ elsif kwargs.fetch(:common, true)
68
66
  workspace.theme
69
67
  else
70
68
  __get__(:theme)[:project][to_sym] ||= {}
71
69
  end
72
- log = { file: log } unless log.is_a?(::Hash)
73
- if (logfile = env('LOG_FILE')).nil? && (auto = env('LOG_AUTO'))
74
- logfile = case auto
75
- when 'y', 'year'
76
- "#{@name}-#{Date.today.year}.log"
77
- when 'm', 'month'
78
- "#{@name}-#{Date.today.strftime('%Y-%m')}.log"
79
- when 'd', 'day', '1'
80
- "#{@name}-#{Date.today}.log"
81
- end
70
+ initialize_logger(**kwargs)
71
+ end
72
+
73
+ def initialize_logger(log: nil, **)
74
+ log = log.is_a?(::Hash) ? log.dup : { file: log }
75
+ if (file = env('LOG_FILE')).nil? && (auto = env('LOG_AUTO'))
76
+ file = case auto
77
+ when 'y', 'year'
78
+ "#{@name}-#{Date.today.year}.log"
79
+ when 'm', 'month'
80
+ "#{@name}-#{Date.today.strftime('%Y-%m')}.log"
81
+ when 'd', 'day', '1'
82
+ "#{@name}-#{Date.today}.log"
83
+ end
82
84
  end
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)
85
+ if file ||= log[:file]
86
+ file = Date.today.strftime(file)
87
+ file = (dir = env('LOG_DIR')) ? Pathname.new(dir).join(file) : Pathname.new(file)
86
88
  begin
87
- logfile.realdirpath
89
+ file = file.realdirpath
88
90
  rescue StandardError => e
89
- logfile = nil
91
+ raise if @workspace.exception
92
+
93
+ file = nil
90
94
  warn e if @warning
91
95
  end
92
96
  end
93
- @log = Logger.new(logfile, progname: @name, level: env('LOG_LEVEL') || log[:level] || Logger::INFO)
97
+ log[:progname] = @name
98
+ log[:level] = env('LOG_LEVEL', log[:level] || Logger::INFO, ignore: nil)
99
+ log.delete(:file)
100
+ @log = [file, log]
94
101
  end
95
102
 
96
103
  def initialize_build(ref, **kwargs)
97
- initialize_script(ref)
104
+ initialize_script(ref, **kwargs)
98
105
  if (val = env('BUILD', strict: true))
99
106
  @output[0] = val
100
107
  elsif @script && @output[0] != false
@@ -106,11 +113,11 @@ module Squared
106
113
  elsif env('BUILD', suffix: 'DEV')
107
114
  @dev = true
108
115
  elsif @dev.nil?
109
- @dev = workspace.dev?
116
+ @dev = !group.nil? && workspace.dev?(group: group, global: true)
110
117
  end
111
118
  end
112
119
 
113
- def initialize_script(ref)
120
+ def initialize_script(ref, **)
114
121
  return unless (script = workspace.script(group: group, ref: ref))
115
122
 
116
123
  @depend = script[:depend] if @depend.nil?
@@ -121,6 +128,8 @@ module Squared
121
128
  end
122
129
 
123
130
  def populate(*)
131
+ return if @exclude.include?(Base.ref)
132
+
124
133
  namespace name do
125
134
  workspace.series.each_key do |key|
126
135
  next unless Application::WORKSPACE_KEYS.include?(key) ? has?(key) : workspace.task_include?(self, key)
@@ -154,7 +163,7 @@ module Squared
154
163
  cmd = compose(opts)
155
164
  banner = env('REPO_BUILD') == 'verbose'
156
165
  end
157
- run(cmd, exception: workspace.exception, banner: banner, sync: sync)
166
+ run(cmd, banner: banner, sync: sync)
158
167
  end
159
168
 
160
169
  def refresh(*)
@@ -168,11 +177,11 @@ module Squared
168
177
  end
169
178
 
170
179
  def depend(*)
171
- run(@depend, exception: workspace.exception, sync: invoked_sync?('depend')) if @depend
180
+ run(@depend, sync: invoked_sync?('depend')) if @depend
172
181
  end
173
182
 
174
183
  def copy(*)
175
- run_s(@copy, sync: invoked_sync?('copy'))
184
+ run_s(@copy, sync: invoked_sync?('copy')) if @copy
176
185
  end
177
186
 
178
187
  def doc
@@ -212,6 +221,12 @@ module Squared
212
221
  end
213
222
  end
214
223
 
224
+ def log
225
+ return @log unless @log.is_a?(::Array)
226
+
227
+ @log = Logger.new(enabled? ? @log[0] : nil, **@log[1])
228
+ end
229
+
215
230
  def base_path(*args)
216
231
  path.join(*args)
217
232
  end
@@ -245,7 +260,7 @@ module Squared
245
260
  end
246
261
 
247
262
  def depend?
248
- !!@depend
263
+ @depend != false && (!@depend.nil? || has?('outdated'))
249
264
  end
250
265
 
251
266
  def doc?
@@ -264,16 +279,25 @@ module Squared
264
279
  !!@clean
265
280
  end
266
281
 
282
+ def dev?
283
+ !!@dev
284
+ end
285
+
267
286
  protected
268
287
 
269
- def run(cmd = @session, exception: false, banner: true, sync: true, req: nil)
288
+ def run(cmd = @session, exception: workspace.exception, banner: true, sync: true, req: nil, **)
270
289
  return if req && !base_path(req).exist?
271
290
 
272
291
  cmd = close_session(cmd)
273
292
  log.info cmd
274
- print_item format_banner(cmd, banner: banner) if sync
275
293
  begin
276
- shell(cmd, chdir: path, exception: exception)
294
+ if cmd =~ /^\S+:(\S+:?)+$/ && workspace.task_defined?(cmd)
295
+ print_item if sync
296
+ invoke(cmd, exception: exception)
297
+ else
298
+ print_item format_banner(cmd, banner: banner) if sync
299
+ shell(cmd, chdir: path, exception: exception)
300
+ end
277
301
  rescue StandardError => e
278
302
  log.error e
279
303
  raise
@@ -281,11 +305,11 @@ module Squared
281
305
  end
282
306
 
283
307
  def run_s(cmd, **kwargs)
284
- run(cmd, exception: workspace.exception, banner: verbose?, **kwargs) if cmd.is_a?(::String)
308
+ run(cmd, banner: verbose?, **kwargs) if cmd.is_a?(::String)
285
309
  end
286
310
 
287
- def env(key, equals: nil, ignore: ['0'].freeze, default: nil, suffix: nil, strict: false)
288
- a = "#{key}_#{name.upcase}"
311
+ def env(key, default = nil, equals: nil, ignore: ['0'].freeze, suffix: nil, strict: false)
312
+ a = "#{key}_#{name.gsub(/[^\w]+/, '_').upcase}"
289
313
  b = ''
290
314
  if suffix
291
315
  a = [a, suffix].flatten.join('_')
@@ -328,7 +352,7 @@ module Squared
328
352
  styles = [:bold] + styles
329
353
  end
330
354
  end
331
- n = max_width(lines)
355
+ n = Project.max_width(lines)
332
356
  ch = ' ' * pad
333
357
  index = -1
334
358
  out = lines.map do |val|
@@ -344,15 +368,17 @@ module Squared
344
368
  out.join("\n")
345
369
  end
346
370
 
347
- def print_footer(*lines, sub: nil, border: theme[:border])
348
- n = max_width(lines)
371
+ def print_footer(*lines, sub: nil, border: theme[:border], reverse: false)
372
+ n = Project.max_width(lines)
349
373
  sub = as_a(sub)
350
374
  lines.map! do |val|
351
375
  s = val.ljust(n)
352
376
  sub.each { |h| s = sub_style(s, **h) }
353
377
  s
354
378
  end
355
- [sub_style('-' * n, styles: border), *lines].join("\n")
379
+ ret = [sub_style('-' * n, styles: border), *lines]
380
+ ret.reverse! if reverse
381
+ ret.join("\n")
356
382
  end
357
383
 
358
384
  def format_desc(action, flag, opts = nil, req: 'opts*')
@@ -374,8 +400,8 @@ module Squared
374
400
  end
375
401
  end
376
402
 
377
- def empty_status(msg, title, obj)
378
- "#{msg}#{!obj || obj == 0 || obj.to_s.empty? ? '' : message(hint: message(title, obj.to_s))}"
403
+ def empty_status(msg, title, obj, always: false)
404
+ "#{msg}#{!always && (!obj || obj == 0 || obj.to_s.empty?) ? '' : message(hint: message(title, obj.to_s))}"
379
405
  end
380
406
 
381
407
  def append_nocolor
@@ -394,10 +420,33 @@ module Squared
394
420
  @session = nil
395
421
  raise_error(action, "#{flag}[]", hint: 'empty')
396
422
  end
397
- return unless action.to_s.empty?
423
+ end
398
424
 
399
- @session = nil
400
- raise_error('parameter', flag, hint: 'missing')
425
+ def store_pwd(done = nil)
426
+ if @pwd
427
+ Dir.chdir(@pwd)
428
+ @pwd = nil
429
+ elsif !done && Dir.pwd != path.to_s
430
+ @pwd = Dir.pwd
431
+ Dir.chdir(path)
432
+ @pwd
433
+ end
434
+ end
435
+
436
+ def semver(val)
437
+ unless val[3]
438
+ val[3] = '.'
439
+ val[4] = '0'
440
+ end
441
+ unless val[1]
442
+ val[1] = '.'
443
+ val[2] = '0'
444
+ end
445
+ val
446
+ end
447
+
448
+ def semmajor(cur, want)
449
+ cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]
401
450
  end
402
451
 
403
452
  def verbose?
@@ -423,17 +472,11 @@ module Squared
423
472
  return ret unless ret.nil?
424
473
  end
425
474
  if (base = workspace.find_base(self))
426
- ret = check.("#{action}:#{base.to_sym}")
475
+ ret = check.("#{action}:#{base.ref}")
427
476
  return ret unless ret.nil?
428
477
  end
429
478
  invoked?("#{name}:#{action}") && (!invoked?(action) || !workspace.task_defined?("#{action}:sync"))
430
479
  end
431
-
432
- private
433
-
434
- def max_width(lines)
435
- [lines.max_by(&:size).size, Project.line_width].max
436
- end
437
480
  end
438
481
  end
439
482
  end