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.
@@ -16,6 +16,7 @@ module Squared
16
16
  outdated: [],
17
17
  refresh: [],
18
18
  doc: [],
19
+ test: [],
19
20
  clean: []
20
21
  }
21
22
  TASK_BASE = {}
@@ -42,20 +43,19 @@ module Squared
42
43
  project_kind.find { |proj| proj.is_a?(path) } if path
43
44
  end
44
45
 
46
+ def to_s
47
+ /[^:]+$/.match(super.to_s)[0]
48
+ end
49
+
45
50
  attr_reader :project_kind
46
51
  end
47
52
 
48
53
  @project_kind = []
49
54
 
50
- attr_reader :main, :root, :home, :series
51
- attr_accessor :script, :manifest, :manifest_url, :exception, :styles, :verbose
52
-
53
- def initialize(main)
54
- prompt = lambda do |path|
55
- return false unless path.directory?
55
+ attr_reader :main, :root, :home, :series, :theme
56
+ attr_accessor :manifest, :manifest_url, :exception, :pipe, :verbose, :warning
56
57
 
57
- confirm "#{log_title(:warn)} \"#{sub_style(path, :bold)}\" is not empty. Continue with installation? [y/N] "
58
- end
58
+ def initialize(main, *, common: true, **)
59
59
  @main = main.to_s
60
60
  @home = if (val = env('REPO_HOME'))
61
61
  home = Pathname.new(val)
@@ -66,7 +66,7 @@ module Squared
66
66
  elsif !@root.exist?
67
67
  @root.mkpath
68
68
  elsif !empty?(@root)
69
- if prompt.(@root)
69
+ if repo_prompt(@root)
70
70
  @override = true
71
71
  else
72
72
  @root = nil
@@ -81,7 +81,7 @@ module Squared
81
81
  if !@root.exist?
82
82
  @root.mkpath
83
83
  elsif !empty?(@root)
84
- raise ArgumentError, message('REPO_ROOT', val, hint: 'exist') unless prompt.(@root)
84
+ raise ArgumentError, message('REPO_ROOT', val, hint: 'exist') unless repo_prompt(@root)
85
85
 
86
86
  @override = true
87
87
  end
@@ -91,60 +91,39 @@ module Squared
91
91
  end
92
92
  @root ||= @home.parent
93
93
  @series = TASK_NAME.dup
94
- @styles = {}
94
+ @theme = common ? __get__(:theme)[:workspace] : {}
95
95
  @project = {}
96
+ @script = {
97
+ group: {},
98
+ ref: {},
99
+ build: nil,
100
+ dev: nil,
101
+ prod: nil
102
+ }
96
103
  @exception = !env('PIPE_FAIL', ignore: '0').nil?
97
104
  @pipe = !env('PIPE_OUT', ignore: '0').nil?
98
- @verbose = true
99
- end
100
-
101
- def repo(url, manifest = 'latest')
102
- @manifest_url = url
103
- @manifest = manifest
104
- self
105
+ @verbose = !@pipe
106
+ @warning = !empty?(@root, init: false)
105
107
  end
106
108
 
107
- def run(script, **kwargs)
108
- @script = case (val = env('REPO_BUILD'))
109
- when 'verbose'
110
- "#{script}:verbose"
111
- when 'silent'
112
- @verbose = false
113
- script
114
- else
115
- val || script
116
- end
117
- @dev = bool_match(env('REPO_DEV'), kwargs[:dev])
118
- @prod = bool_match(env('REPO_PROD'), kwargs[:prod])
119
- self
120
- end
109
+ def build(**kwargs)
110
+ return unless enabled?
121
111
 
122
- def add(name, dir = nil, **kwargs)
123
- path = (dir || name).to_s
124
- ref = kwargs[:ref]
125
- project = if !ref.is_a?(::Class)
126
- Workspace.find(path: root_path(path), ref: ref)
127
- elsif ref < Project::Base
128
- ref
129
- end
130
- instance = (project || Project::Base).new(name, path, self, **kwargs)
131
- @project[n = name.to_sym] = instance
132
- get(:project)[n] = instance
133
- self
134
- end
112
+ default = kwargs[:default]
113
+ parallel = env('REPO_SYNC', ignore: '0') ? [] : (kwargs[:parallel] || []).map!(&:to_sym)
135
114
 
136
- def build(default: nil, parallel: [])
137
115
  group = {}
138
116
  parent = {}
139
- incl = Set.new
117
+ incl = []
140
118
  @project.each do |name, proj|
141
119
  next unless proj.enabled?
142
120
 
143
- @series.each do |key, items|
121
+ series.each do |key, items|
144
122
  target = "#{name}:#{key}"
145
123
  case key
146
- when :build, :refresh, :depend, :outdated, :doc, :copy, :clean
147
- next unless proj.has?(key) || ::Rake::Task.task_defined?(target)
124
+ when :build, :refresh, :depend, :copy, :outdated, :doc, :test, :clean
125
+ valid = proj.has?(key) || ::Rake::Task.task_defined?(target)
126
+ next unless valid || (key == :refresh && series[:build].include?(target = "#{name}:build"))
148
127
  else
149
128
  next unless task_defined?(proj, key)
150
129
  end
@@ -156,19 +135,20 @@ module Squared
156
135
  end
157
136
  next unless (base = find_base(proj))
158
137
 
159
- id = base.to_sym.to_s
160
- next if id == proj.group
161
-
162
- incl << id
163
- (parent[:"#{key}:#{id}"] ||= []).push(target)
138
+ unless (id = base.to_sym.to_s) == proj.group
139
+ incl << id
140
+ (parent[:"#{key}:#{id}"] ||= []).push(target)
141
+ end
164
142
  end
165
- proj.populate
143
+ proj.populate(**kwargs)
166
144
  end
167
- @series.merge!(parent) if incl.size > 1
168
- @series.merge!(group)
169
- if @manifest_url && (empty?(@root) || @override)
145
+ series.merge!(parent) if incl.uniq.size > 1
146
+ series.merge!(group)
147
+ series[:refresh].clear if series[:refresh].all? { |target| target.end_with?(':build') }
148
+
149
+ if repo?
170
150
  branch = env('REPO_MANIFEST') || read_manifest
171
- target = branch || @manifest
151
+ target = branch || manifest
172
152
  stage = nil
173
153
  failfast = true
174
154
  cmd = []
@@ -217,7 +197,7 @@ module Squared
217
197
  parse_opts.(args)
218
198
  stage = :init
219
199
  puts if newline
220
- system("repo init -u #{@manifest_url} -m #{args.manifest || target}.xml", chdir: @root)
200
+ system("repo init -u #{manifest_url} -m #{args.manifest || target}.xml", chdir: root)
221
201
  repo[:all].invoke
222
202
  end
223
203
 
@@ -230,48 +210,36 @@ module Squared
230
210
  cmd << '--fail-fast' if failfast
231
211
  puts if newline && stage != :init
232
212
  begin
233
- shell("repo sync #{cmd.join(' ')}", chdir: @root, exception: failfast)
213
+ shell("repo sync #{cmd.join(' ')}", chdir: root, exception: failfast)
234
214
  rescue StandardError => e
235
- emphasize(e, title: "rake stash repo:#{stage || :sync}")
215
+ emphasize(e, title: "rake stash repo:#{stage || 'sync'}")
236
216
  raise
237
217
  end
238
218
  end
239
219
  end
240
220
  end
241
- return unless enabled?
242
221
 
243
- multi = env('REPO_SYNC', ignore: '0') ? [] : parallel.map(&:to_sym)
244
- output = dev? ? :refresh : :build
222
+ Workspace.project_kind.each { |obj| obj.populate(self, **kwargs) }
245
223
 
246
- task default: default || output
224
+ if !series[:build].empty?
225
+ init = [:depend, dev? && !series[:refresh].empty? ? :refresh : :build]
247
226
 
248
- desc 'all[git?=rebase|stash]'
249
- task :all, [:git] do |_, args|
250
- sync = ->(key) { multi.include?(key) ? :"#{key}:sync" : key }
251
- pull = case args.git
252
- when 'rebase'
253
- sync.(:rebase)
254
- when 'stash'
255
- invoke sync.(:stash)
256
- sync.(:pull)
257
- else
258
- sync.(:pull)
259
- end
260
- invoke(pull, exception: @exception)
261
- invoke(output, exception: @exception)
262
- end
227
+ task default: default || init[1]
263
228
 
264
- desc 'init'
265
- task init: [:depend, output]
229
+ desc 'init'
230
+ task init: init
231
+ elsif default && !series[default].empty?
232
+ task default: default
233
+ end
266
234
 
267
- @series.each do |key, items|
235
+ series.each do |key, items|
268
236
  next if items.empty?
269
237
 
270
- unless (valid = multi.include?(key))
238
+ unless (valid = parallel.include?(key))
271
239
  group = key.to_s
272
- valid = multi.include?(group.split(':').first.to_sym) if group.include?(':')
240
+ valid = parallel.include?(group.split(':').first.to_sym) if group.include?(':')
273
241
  end
274
- if valid
242
+ if valid && items.size > 1
275
243
  desc "#{key} (thread)"
276
244
  multitask key => items
277
245
 
@@ -282,50 +250,129 @@ module Squared
282
250
  task key => items
283
251
  end
284
252
  end
253
+
254
+ yield self if block_given?
255
+ end
256
+
257
+ def repo(url, manifest = 'latest', run: nil, dev: nil, prod: nil)
258
+ @manifest_url = url
259
+ @manifest = manifest
260
+ script = case (val = env('REPO_BUILD'))
261
+ when 'verbose'
262
+ run ? "#{run}:verbose" : nil
263
+ when 'silent'
264
+ @verbose = false
265
+ @warning = false
266
+ run
267
+ else
268
+ val || run
269
+ end
270
+ case env('REPO_WARN')
271
+ when '0'
272
+ @warning = false
273
+ when '1'
274
+ @warning = true
275
+ end
276
+ script ? run(script, dev: bool_match(env('REPO_DEV'), dev), prod: bool_match(env('REPO_DEV'), prod)) : self
277
+ end
278
+
279
+ def run(script, group: nil, ref: nil, **kwargs)
280
+ if group || ref
281
+ script_command :run, script, group, ref
282
+ else
283
+ @script[:build] = script
284
+ @script[:dev] = kwargs[:dev]
285
+ @script[:prod] = kwargs[:prod]
286
+ self
287
+ end
288
+ end
289
+
290
+ def depend(script, group: nil, ref: nil)
291
+ script_command :depend, script, group, ref
292
+ end
293
+
294
+ def clean(script, group: nil, ref: nil)
295
+ script_command :clean, script, group, ref
296
+ end
297
+
298
+ def doc(script, group: nil, ref: nil)
299
+ script_command :doc, script, group, ref
300
+ end
301
+
302
+ def test(script, group: nil, ref: nil)
303
+ script_command :test, script, group, ref
285
304
  end
286
305
 
287
- def compose(name, &block)
288
- namespace(name, &block)
306
+ def add(name, path = nil, **kwargs)
307
+ path = root_path((path || name).to_s)
308
+ ref = kwargs[:ref]
309
+ project = if !ref.is_a?(::Class)
310
+ Workspace.find(path: path, ref: ref)
311
+ elsif ref < Project::Base
312
+ ref
313
+ end
314
+ instance = (project || Project::Base).new(name, path, self, **kwargs)
315
+ @project[n = name.to_sym] = instance
316
+ __get__(:project)[n] = instance unless kwargs[:private]
289
317
  self
290
318
  end
291
319
 
292
- def apply(&block)
293
- instance_eval(&block)
320
+ def compose(name, &blk)
321
+ namespace(name, &blk)
294
322
  self
295
323
  end
296
324
 
297
- def style(name, *args)
298
- set = ->(k, v) { @styles[k.to_sym] = check_style(v, empty: false) }
299
- if name.is_a?(Hash)
300
- name.each { |k, v| set.(k, v || args.flatten) }
301
- else
302
- set.(name, args.flatten)
325
+ def apply(&blk)
326
+ instance_eval(&blk)
327
+ self
328
+ end
329
+
330
+ def style(name, *args, target: nil, empty: false)
331
+ data = nil
332
+ if target
333
+ as_a(target).each_with_index do |val, i|
334
+ if i == 0
335
+ break unless (data = __get__(:theme)[val.to_sym])
336
+ else
337
+ data = data[val.to_sym] ||= {}
338
+ end
339
+ end
340
+ return unless data
303
341
  end
342
+ apply_style(data || theme, name, *args, empty: empty)
304
343
  self
305
344
  end
306
345
 
346
+ def script(group: nil, ref: nil)
347
+ if group || ref
348
+ (group && @script[:group][group.to_sym]) || (ref && @script[:ref][ref.to_sym])
349
+ else
350
+ @script[:build]
351
+ end
352
+ end
353
+
307
354
  def env(key, equals: nil, ignore: nil)
308
- ret = ENV.fetch("#{key}_#{@main.gsub(/[^\w]/, '_').upcase}", ENV[key]).to_s
355
+ ret = ENV.fetch("#{key}_#{main.gsub(/[^\w]/, '_').upcase}", ENV[key]).to_s
309
356
  return ret == equals.to_s if equals
310
357
 
311
358
  ret.empty? || as_a(ignore).any? { |val| ret == val.to_s } ? nil : ret
312
359
  end
313
360
 
314
- def read_manifest
361
+ def read_manifest(*)
315
362
  require 'rexml/document'
316
363
  file = root_path('.repo/manifest.xml')
317
364
  return unless file.exist?
318
365
 
319
- doc = REXML::Document.new(File.read(file))
366
+ doc = REXML::Document.new(file.read)
320
367
  doc.elements['manifest/include'].attributes['name']&.sub('.xml', '')
321
368
  end
322
369
 
323
370
  def root_path(*args)
324
- @root.join(*args)
371
+ root.join(*args)
325
372
  end
326
373
 
327
374
  def home_path(*args)
328
- @home.join(*args)
375
+ home.join(*args)
329
376
  end
330
377
 
331
378
  def find_base(obj)
@@ -345,17 +392,20 @@ module Squared
345
392
  end
346
393
  end
347
394
 
348
- def empty?(dir)
349
- return true if dir.empty? || dir.join('.repo').directory?
350
- return true if dir.children.size == 1 && dir.join(dir.children.first).to_s == __FILE__
395
+ def to_s
396
+ root.to_s
397
+ end
351
398
 
352
- dir == @root && !env('REPO_ROOT').nil? && @root.children.none? do |path|
353
- path.directory? && !path.basename.to_s.start_with?('.') && path.to_s != @home.to_s
354
- end
399
+ def inspect
400
+ "#<#{self.class}: #{main} => #{self}>"
355
401
  end
356
402
 
357
403
  def enabled?
358
- !@series[:build].empty? || !@series[:doc].empty?
404
+ repo? || @project.any? { |_, proj| proj.enabled? }
405
+ end
406
+
407
+ def repo?
408
+ !manifest_url.nil? && (empty?(root) || @override)
359
409
  end
360
410
 
361
411
  def multitask?
@@ -366,22 +416,27 @@ module Squared
366
416
  end
367
417
  end
368
418
 
419
+ def empty?(dir, init: true)
420
+ return true if dir.empty? || (init && dir.join('.repo').directory?)
421
+ return true if dir.children.size == 1 && dir.join(dir.children.first).to_s == __FILE__
422
+
423
+ dir == root && !env('REPO_ROOT').nil? && root.children.none? do |path|
424
+ path.directory? && !path.basename.to_s.start_with?('.') && path.to_s != home.to_s
425
+ end
426
+ end
427
+
369
428
  def task_defined?(obj, key)
370
429
  obj.is_a?(TASK_BASE[key])
371
430
  end
372
431
 
373
- def dev?(pat = nil, script: nil)
374
- with?(pat, script: script, state: @dev)
432
+ def dev?(script: nil, pat: nil, global: nil)
433
+ with?(:dev, script: script, pat: pat, global: (pat.nil? && global.nil?) || global)
375
434
  end
376
435
 
377
- def prod?(pat = nil, script: nil)
378
- return false if @dev == true || !@prod
379
-
380
- with?(pat, script: script, state: @prod)
381
- end
436
+ def prod?(script: nil, pat: nil, global: false)
437
+ return false if global && (@script[:dev] == true || !@script[:prod])
382
438
 
383
- def pipe?
384
- @pipe
439
+ with?(:prod, script: script, pat: pat, global: global)
385
440
  end
386
441
 
387
442
  protected
@@ -414,11 +469,30 @@ module Squared
414
469
 
415
470
  private
416
471
 
417
- def with?(pat, script: nil, state: nil)
418
- pat = state if pat.nil?
472
+ def script_command(task, val, group, ref)
473
+ if group
474
+ label = :group
475
+ items = as_a(group)
476
+ else
477
+ label = :ref
478
+ items = as_a(ref)
479
+ end
480
+ items.each { |name| (@script[label][name.to_sym] ||= {})[task] = val }
481
+ self
482
+ end
483
+
484
+ def repo_prompt(path)
485
+ return false unless path.directory?
486
+
487
+ confirm "#{log_title(:warn)} \"#{sub_style(path, :bold)}\" is not empty. Continue with installation? [y/N] "
488
+ end
489
+
490
+ def with?(state, script: nil, pat: nil, global: false)
491
+ pat = @script[state] if pat.nil? && global
419
492
  return pat == true unless pat.is_a?(::Regexp)
493
+ return false if !script && !global
420
494
 
421
- pat.match?(script || @script)
495
+ pat.match?(script || @script[:build])
422
496
  end
423
497
  end
424
498
  end
data/lib/squared/repo.rb CHANGED
@@ -9,7 +9,7 @@ module Squared
9
9
  project id
10
10
  else
11
11
  (id = Pathname.new(id).realdirpath.to_s) rescue nil if id.is_a?(::String)
12
- get(:project).find { |_, val| val.path.to_s == id.to_s }
12
+ __get__(:project).find { |_, val| val.path.to_s == id.to_s }
13
13
  end
14
14
  end
15
15
  ret.size == 1 ? ret.first : ret
@@ -19,7 +19,7 @@ module Squared
19
19
  ret = project(name)
20
20
  return ret if ret&.path&.directory?
21
21
 
22
- raise NoMethodError, message('project is not initialized', name)
22
+ raise NoMethodError, "project is not initialized (#{name})"
23
23
  end
24
24
 
25
25
  def project?(name)
@@ -29,7 +29,7 @@ module Squared
29
29
  private
30
30
 
31
31
  def project(name)
32
- get(:project)[name.to_sym]
32
+ __get__(:project)[name.to_sym]
33
33
  end
34
34
  end
35
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-29 00:00:00.000000000 Z
11
+ date: 2024-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake