squared 0.0.1 → 0.0.2

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,29 +1,34 @@
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
- include Common
10
+ include Common::System
10
11
  include Shell
11
- include System
12
12
  include Task
13
13
  include ::Rake::DSL
14
14
  extend Forwardable
15
15
 
16
16
  class << self
17
+ include Common::Task
18
+ include ::Rake::DSL
19
+
17
20
  def tasks
18
21
  [].freeze
19
22
  end
20
23
 
24
+ def populate(*); end
25
+
21
26
  def to_s
22
- to_sym.to_s.capitalize
27
+ /[^:]+$/.match(super.to_s)[0]
23
28
  end
24
29
 
25
30
  def to_sym
26
- :base
31
+ to_s.downcase.to_sym
27
32
  end
28
33
  end
29
34
 
@@ -34,60 +39,86 @@ module Squared
34
39
 
35
40
  protected :logger
36
41
 
37
- def_delegators :logger, :log, :level=, :<<, :debug, :info, :warn, :error, :fatal, :unknown
42
+ def_delegators :logger, :log, :<<, :debug, :info, :warn, :error, :fatal, :unknown
38
43
 
39
44
  def initialize(name, project, workspace, **kwargs)
40
45
  @name = name.to_s
41
46
  @path = workspace.root_path(project.to_s)
42
47
  @project = @path.basename.to_s
43
48
  @workspace = workspace
49
+ @group = kwargs[:group]&.to_s
44
50
  @depend = kwargs[:depend]
45
51
  @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]
52
+ @test = kwargs[:test]
53
+ @output = [kwargs[:run], nil]
52
54
  @copy = kwargs[:copy]
53
55
  @clean = kwargs[:clean]
54
56
  log = kwargs[:log]
55
57
  log = { file: log } unless log.is_a?(::Hash)
56
58
  if (logfile = env('LOG_FILE')).nil? && (auto = env('LOG_AUTO'))
57
- require 'date'
58
59
  logfile = case auto
59
60
  when 'y', 'year'
60
- "#{name}-#{Date.today.year}.log"
61
+ "#{@name}-#{Date.today.year}.log"
61
62
  when 'm', 'month'
62
- "#{name}-#{Date.today.strftime('%Y-%m')}.log"
63
+ "#{@name}-#{Date.today.strftime('%Y-%m')}.log"
63
64
  when 'd', 'day', '1'
64
- "#{name}-#{Date.today}.log"
65
- else
66
- log[:file]
65
+ "#{@name}-#{Date.today}.log"
67
66
  end
68
- else
69
- logfile = log[:file]
70
67
  end
71
- if (dir = env('LOG_DIR'))
72
- logfile &&= Pathname.new(dir).join(logfile)
68
+ if logfile ||= log[:file]
69
+ logfile = Date.today.strftime(logfile)
70
+ logfile = (dir = env('LOG_DIR')) ? Pathname.new(dir).join(logfile) : Pathname.new(logfile)
71
+ begin
72
+ logfile.realdirpath
73
+ rescue StandardError => e
74
+ logfile = nil
75
+ Warning.warn e
76
+ end
73
77
  end
74
- @logger = Logger.new(logfile, level: env('LOG_LEVEL') || log[:level] || Logger::INFO)
75
- @logger.progname = name
76
- @session = nil
78
+ @logger = Logger.new(logfile, progname: @name, level: env('LOG_LEVEL') || log[:level] || Logger::INFO)
79
+ end
80
+
81
+ def initialize_build(ref, **kwargs)
82
+ initialize_script(ref)
83
+ if (val = env('BUILD', strict: true))
84
+ @output[0] = val
85
+ elsif @script && @output[0] != false
86
+ @output[0] ||= @script[:run]
87
+ end
88
+ if env('BUILD', suffix: 'DEV', equals: '0')
89
+ @dev = false
90
+ else
91
+ @dev = kwargs.delete(:dev)
92
+ if env('BUILD', suffix: 'DEV')
93
+ @dev = true
94
+ elsif @dev.nil?
95
+ @dev = workspace.dev?
96
+ end
97
+ end
98
+ end
99
+
100
+ def initialize_script(ref)
101
+ return unless (script = workspace.script(group: group, ref: ref))
102
+
103
+ @depend = script[:depend] if @depend.nil?
104
+ @doc = script[:doc] if @doc.nil?
105
+ @test = script[:test] if @test.nil?
106
+ @clean = script[:clean] if @clean.nil?
107
+ @script = script
77
108
  end
78
109
 
79
110
  def populate(*)
80
- namespace @name do
81
- @workspace.series.each_key do |key|
111
+ namespace name do
112
+ workspace.series.each_key do |key|
82
113
  case key
83
- when :build, :refresh, :depend, :outdated, :doc, :copy, :clean
114
+ when :build, :refresh, :depend, :outdated, :doc, :test, :copy, :clean
84
115
  next unless has?(key)
85
116
  else
86
- next unless @workspace.task_defined?(self, key)
117
+ next unless workspace.task_defined?(self, key)
87
118
  end
88
- desc message(@name, key)
119
+ desc message(name, key)
89
120
  task key do
90
- send(key)
121
+ __send__(key)
91
122
  end
92
123
  end
93
124
  end
@@ -114,12 +145,12 @@ module Squared
114
145
  cmd = compose(opts)
115
146
  banner = env('REPO_BUILD') == 'verbose'
116
147
  end
117
- run(cmd, exception: @workspace.exception, banner: banner)
148
+ run(cmd, exception: workspace.exception, banner: banner)
118
149
  end
119
150
 
120
151
  def refresh(*)
121
152
  build
122
- key = "#{@name}:copy"
153
+ key = "#{name}:copy"
123
154
  if ::Rake::Task.task_defined?(key)
124
155
  invoke key
125
156
  else
@@ -128,36 +159,43 @@ module Squared
128
159
  end
129
160
 
130
161
  def depend(*)
131
- run(@depend, exception: @workspace.exception) if @depend
162
+ run(@depend, exception: workspace.exception) if @depend
132
163
  end
133
164
 
134
165
  def doc
135
166
  build @doc if @doc
136
167
  end
137
168
 
169
+ def test
170
+ build @test if @test
171
+ end
172
+
138
173
  def copy(*)
139
174
  run_s @copy
140
175
  end
141
176
 
142
177
  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?
178
+ return unless @clean
151
179
 
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
180
+ if @clean.is_a?(::String)
181
+ run_s @clean
182
+ else
183
+ @clean.each do |val|
184
+ if (val = val.to_s).match?(%r{[\\/]$})
185
+ dir = Pathname.new(val)
186
+ dir = base_path(dir) unless dir.absolute?
187
+ next unless dir.directory?
188
+
189
+ warn "rm -rf #{dir}"
190
+ dir.rmtree(verbose: true)
191
+ else
192
+ files = val.include?('*') ? Dir[base_path(val)] : [base_path(val)]
193
+ files.each do |file|
194
+ begin
195
+ File.delete(file) if File.file?(file)
196
+ rescue StandardError => e
197
+ warn e
198
+ end
161
199
  end
162
200
  end
163
201
  end
@@ -165,45 +203,51 @@ module Squared
165
203
  end
166
204
 
167
205
  def styles
168
- @workspace.styles
206
+ workspace.styles
169
207
  end
170
208
 
171
209
  def base_path(*args)
172
- @path.join(*args)
210
+ path.join(*args)
211
+ end
212
+
213
+ def inspect
214
+ "#<#{self.class}: #{name} => #{self}>"
173
215
  end
174
216
 
175
217
  def to_s
176
- @path.to_s
218
+ path.to_s
177
219
  end
178
220
 
179
221
  def to_sym
180
- @name.to_sym
222
+ name.to_sym
181
223
  end
182
224
 
183
225
  def enabled?
184
- @path.directory? && !@path.empty?
226
+ path.directory? && !path.empty?
185
227
  end
186
228
 
187
229
  def has?(method)
188
- respond_to?(m = :"#{method}?") && send(m)
230
+ respond_to?(m = :"#{method}?") && __send__(m)
189
231
  end
190
232
 
191
233
  def build?
192
- return false if @output[0] == false
193
-
194
- !doc? || !@output[0].nil?
234
+ !!@output[0]
195
235
  end
196
236
 
197
237
  def refresh?
198
- build?
238
+ build? && (copy? || ::Rake::Task.task_defined?("#{name}:copy"))
199
239
  end
200
240
 
201
241
  def depend?
202
- !@depend.nil?
242
+ !!@depend
203
243
  end
204
244
 
205
245
  def doc?
206
- !@doc.nil?
246
+ !!@doc
247
+ end
248
+
249
+ def test?
250
+ !!@test
207
251
  end
208
252
 
209
253
  def copy?
@@ -211,11 +255,7 @@ module Squared
211
255
  end
212
256
 
213
257
  def clean?
214
- !@clean.nil?
215
- end
216
-
217
- def verbose?
218
- @workspace.verbose && !pipe?
258
+ !!@clean
219
259
  end
220
260
 
221
261
  protected
@@ -227,7 +267,7 @@ module Squared
227
267
  info cmd
228
268
  print_item format_banner(cmd, banner: banner)
229
269
  begin
230
- shell(cmd, chdir: @path, exception: exception)
270
+ shell(cmd, chdir: path, exception: exception)
231
271
  rescue StandardError => e
232
272
  error e
233
273
  raise
@@ -235,37 +275,33 @@ module Squared
235
275
  end
236
276
 
237
277
  def run_s(cmd)
238
- run(cmd, exception: @workspace.exception, banner: verbose?) if cmd.is_a?(::String)
278
+ run(cmd, exception: workspace.exception, banner: verbose?) if cmd.is_a?(::String)
239
279
  end
240
280
 
241
281
  def env(key, suffix: nil, equals: nil, strict: false)
242
- val = "#{key}_#{@name.upcase}"
282
+ alt = "#{key}_#{name.upcase}"
243
283
  ret = if suffix
244
- ENV.fetch(([val] + as_a(suffix)).join('_'), '')
284
+ ENV.fetch(([alt] + as_a(suffix)).join('_'), '')
245
285
  else
246
- ENV.fetch(val, strict ? '' : ENV[key]).to_s
286
+ ENV.fetch(alt, strict ? '' : ENV[key]).to_s
247
287
  end
248
- return ret == equals.to_s unless equals.nil?
249
-
250
- ret unless ret.empty? || ret == '0'
288
+ if !equals.nil?
289
+ ret == equals.to_s
290
+ elsif !ret.empty? && ret != '0'
291
+ ret
292
+ end
251
293
  end
252
294
 
253
295
  def session(*cmd, options: nil)
254
296
  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
297
+ split_escape(val).each { |opt| cmd << fill_option(opt) }
262
298
  end
263
299
  @session = JoinSet.new(cmd)
264
300
  end
265
301
 
266
302
  def close_session(cmd)
267
303
  return cmd unless cmd.respond_to?(:done)
268
- raise ArgumentError, message('none were provided', hint: @name) if cmd.empty?
304
+ raise ArgumentError, message('none were provided', hint: name) if cmd.empty?
269
305
 
270
306
  @session = nil if cmd == @session
271
307
  cmd.done
@@ -277,9 +313,35 @@ module Squared
277
313
  puts val unless val.empty? || (val.size == 1 && val.first.nil?)
278
314
  end
279
315
 
316
+ def print_banner(*lines, styles: nil, pad: 0, first: false)
317
+ n = max_width(lines)
318
+ ch = ' ' * pad
319
+ index = -1
320
+ out = lines.map do |val|
321
+ index += 1
322
+ val = ch + val.ljust(n - (pad * 2)) + ch
323
+ if styles && (!first || index == 0)
324
+ sub_style(val, *styles)
325
+ else
326
+ val
327
+ end
328
+ end
329
+ out << ('-' * n)
330
+ out.join("\n")
331
+ end
332
+
333
+ def print_footer(*lines)
334
+ n = max_width(lines)
335
+ ['-' * n, *lines.map { |val| val.ljust(n) }].join("\n")
336
+ end
337
+
280
338
  def format_desc(action, flag, opts = nil, req: 'opts*')
281
339
  opts = "#{req}=#{opts.join(',')}" if opts.is_a?(::Array)
282
- message(@name, action, opts ? "#{flag}[#{opts}]" : flag)
340
+ if !flag
341
+ flag = action
342
+ action = ''
343
+ end
344
+ message(name, action, opts ? "#{flag}[#{opts}]" : flag)
283
345
  end
284
346
 
285
347
  def format_banner(cmd, banner: true, multitask: false)
@@ -294,9 +356,9 @@ module Squared
294
356
  args = [:bold] + args
295
357
  end
296
358
  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} ##"
359
+ print_banner(cmd.sub(/^\S+/, &:upcase), path.to_s, styles: args, pad: pad, first: pad == 0)
360
+ elsif multitask && workspace.multitask?
361
+ "## #{path} ##"
300
362
  end
301
363
  end
302
364
 
@@ -310,7 +372,7 @@ module Squared
310
372
 
311
373
  def guard_params(action, flag, args: nil, key: nil, pat: nil)
312
374
  if args && key
313
- return unless (val = args[key]).nil? || (pat && !pat.match?(val))
375
+ return unless (val = args[key]).nil? || (pat && !val.match?(pat))
314
376
 
315
377
  @session = nil
316
378
  raise ArgumentError, message(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
@@ -326,12 +388,16 @@ module Squared
326
388
  raise ArgumentError, message('parameter', flag, hint: 'missing')
327
389
  end
328
390
 
391
+ def verbose?
392
+ workspace.verbose
393
+ end
394
+
329
395
  def pipe?
330
- @workspace.pipe?
396
+ workspace.pipe
331
397
  end
332
398
 
333
399
  def invoked_sync?(action)
334
- return true if invoked?(group = "#{action}:sync")
400
+ return true if invoked?(sync = "#{action}:sync")
335
401
 
336
402
  missing = ->(val) { ::Rake::Task.tasks.none? { |item| item.name == val } }
337
403
  check = lambda do |val|
@@ -341,15 +407,21 @@ module Squared
341
407
  true
342
408
  end
343
409
  end
344
- if @group
345
- ret = check.("#{action}:#{@group}")
410
+ if group
411
+ ret = check.("#{action}:#{group}")
346
412
  return ret unless ret.nil?
347
413
  end
348
- if (base = @workspace.find_base(self))
414
+ if (base = workspace.find_base(self))
349
415
  ret = check.("#{action}:#{base.to_sym}")
350
416
  return ret unless ret.nil?
351
417
  end
352
- invoked?("#{@name}:#{action}") && (!invoked?(action) || missing.(group))
418
+ invoked?("#{name}:#{action}") && (!invoked?(action) || missing.(sync))
419
+ end
420
+
421
+ private
422
+
423
+ def max_width(lines)
424
+ [lines.max_by(&:size).size, Project.line_width].max
353
425
  end
354
426
  end
355
427
  end