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.
@@ -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
- to_sym.to_s.capitalize
34
+ /[^:]+$/.match(super.to_s)[0]
23
35
  end
24
36
 
25
37
  def to_sym
26
- :base
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
- attr_reader :name, :project, :workspace, :group, :path, :logger
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, :level=, :<<, :debug, :info, :warn, :error, :fatal, :unknown
52
+ def_delegators :logger, :log, :<<, :debug, :info, :warn, :error, :fatal, :unknown
38
53
 
39
- def initialize(name, project, workspace, **kwargs)
54
+ def initialize(name, path, workspace, *, group: nil, log: nil, common: true, **kwargs)
40
55
  @name = name.to_s
41
- @path = workspace.root_path(project.to_s)
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
- @group = kwargs[:group]&.to_s
47
- run = kwargs[:run]
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
- log = kwargs[:log]
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 (dir = env('LOG_DIR'))
72
- logfile &&= Pathname.new(dir).join(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
- @logger.progname = name
76
- @session = nil
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 @name do
81
- @workspace.series.each_key do |key|
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 @workspace.task_defined?(self, key)
132
+ next unless workspace.task_defined?(self, key)
87
133
  end
88
- desc message(@name, key)
134
+ desc message(name, key)
89
135
  task key do
90
- send(key)
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: @workspace.exception, banner: banner)
163
+ run(cmd, exception: workspace.exception, banner: banner)
118
164
  end
119
165
 
120
166
  def refresh(*)
121
167
  build
122
- key = "#{@name}:copy"
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: @workspace.exception) if @depend
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 copy(*)
139
- run_s @copy
188
+ def test
189
+ build @test if @test
140
190
  end
141
191
 
142
192
  def clean
143
- return run_s @clean if @clean.is_a?(::String)
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
- warn "rm -rf #{dir}"
153
- dir.rmtree(verbose: true)
154
- else
155
- files = path.include?('*') ? Dir[base_path(path)] : [base_path(path)]
156
- files.each do |val|
157
- begin
158
- File.delete(val) if File.file?(val)
159
- rescue StandardError => e
160
- warn e
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 styles
168
- @workspace.styles
220
+ def base_path(*args)
221
+ path.join(*args)
169
222
  end
170
223
 
171
- def base_path(*args)
172
- @path.join(*args)
224
+ def inspect
225
+ "#<#{self.class}: #{name} => #{self}>"
173
226
  end
174
227
 
175
228
  def to_s
176
- @path.to_s
229
+ path.to_s
177
230
  end
178
231
 
179
232
  def to_sym
180
- @name.to_sym
233
+ name.to_sym
181
234
  end
182
235
 
183
236
  def enabled?
184
- @path.directory? && !@path.empty?
237
+ path.directory? && !path.empty?
185
238
  end
186
239
 
187
240
  def has?(method)
188
- respond_to?(m = :"#{method}?") && send(m)
241
+ respond_to?(m = :"#{method}?") && __send__(m)
189
242
  end
190
243
 
191
244
  def build?
192
- return false if @output[0] == false
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
- !@depend.nil?
253
+ !!@depend
203
254
  end
204
255
 
205
256
  def doc?
206
- !@doc.nil?
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
- !@clean.nil?
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: @path, exception: exception)
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: @workspace.exception, banner: verbose?) if cmd.is_a?(::String)
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
- val = "#{key}_#{@name.upcase}"
293
+ alt = "#{key}_#{name.upcase}"
243
294
  ret = if suffix
244
- ENV.fetch(([val] + as_a(suffix)).join('_'), '')
295
+ ENV.fetch(([alt] + as_a(suffix)).join('_'), '')
245
296
  else
246
- ENV.fetch(val, strict ? '' : ENV[key]).to_s
297
+ ENV.fetch(alt, strict ? '' : ENV[key]).to_s
247
298
  end
248
- return ret == equals.to_s unless equals.nil?
249
-
250
- ret unless ret.empty? || ret == '0'
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 do |opt|
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: @name) if cmd.empty?
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
- message(@name, action, opts ? "#{flag}[#{opts}]" : flag)
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 = styles[:banner])
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
- Project.banner(cmd.sub(/^\S+/, &:upcase), @path.to_s, styles: args, pad: pad, first: pad == 0)
298
- elsif multitask && @workspace.multitask?
299
- "## #{@path} ##"
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 && !pat.match?(val))
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
- @workspace.pipe?
407
+ workspace.pipe
331
408
  end
332
409
 
333
410
  def invoked_sync?(action)
334
- return true if invoked?(group = "#{action}:sync")
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 @group
345
- ret = check.("#{action}:#{@group}")
421
+ if group
422
+ ret = check.("#{action}:#{group}")
346
423
  return ret unless ret.nil?
347
424
  end
348
- if (base = @workspace.find_base(self))
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?("#{@name}:#{action}") && (!invoked?(action) || missing.(group))
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