squared 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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