squared 0.0.12 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d9e8c772c9f4d0ce5c54dbeb1b9583d2e477f155036faf34cfc547659c34ec4
4
- data.tar.gz: 87de412a78c0071eabd4b26713cbf84978a92fca6ea1a6dfe18653ddf22c90ee
3
+ metadata.gz: 5d5c87e8fd0e459e55e900839ba9f5f43e51ee1990d1fa103f9de264ae94c4e1
4
+ data.tar.gz: 1e38b9df0a7d3f2b48d6912b880d1c2d593dcf04a1942a01791b84ea8b9e023c
5
5
  SHA512:
6
- metadata.gz: '08475f426b15c41dab20fbead5d7c1ead70f5d80384e0a0772cbe7b101512a4402a1bb1231b2550f7da16aac2796f8411f6a6e3e570ae728d59b03f88fea5960'
7
- data.tar.gz: 5c0334640b20dda82641925cd94b41d76be4cd4e603355fef593a5cd69731ac926febab67f3ffa494267291ec9d89efba2f8a9ac4dde978ab2814a0f8a481a67
6
+ metadata.gz: f4b9df6f9d39a24bd1db9e056ab4b5864e36a6d5daf46403881845e3d1d725033b31a4c9d11274595a74c59dbf13ac77845e96a0c3e2f74c09317a3a1f123a62
7
+ data.tar.gz: fcd0370d7ba7b6b590c9fec4a411a302dde15c8124f832aa5ed1a1e58cef209481ac9d595a5d8d385fefce87a8dc0e53a9208b0da6916c00d3a3e8f853748813
data/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2024-12-7
4
+
5
+ ### Added
6
+
7
+ - Git command show was implemented.
8
+ - Projects can run arbitrarily ordered graphs.
9
+ - Repo can be installed from a nested directory without a Rakefile.
10
+ - Python interpreter can be set using ENV option PIP_PYTHON.
11
+ - Node workspaces can be copied by registry package name.
12
+
13
+ ### Changed
14
+
15
+ - Parallel tasks support using Regexp patterns.
16
+ - Project copy globs were renamed include and exclude.
17
+
18
+ ### Fixed
19
+
20
+ - Project workspaces did not detect for a valid directory.
21
+ - Git pull did not display colors for diff bar chart.
22
+ - Git commit did not fetch latest refs before submitting.
23
+
24
+ ## [0.0.12] - 2024-12-1
25
+
26
+ ### Added
27
+
28
+ - Changelog was created.
29
+
30
+ [0.1.0]: https://github.com/anpham6/squared/releases/tag/v0.1.0-ruby
31
+ [0.0.12]: https://github.com/anpham6/squared/releases/tag/v0.0.12-ruby
data/README.md CHANGED
@@ -129,10 +129,17 @@ REPO_ROOT=/tmp/123 NODE_INSTALL=pnpm repo:init
129
129
  ```sh
130
130
  # NODE_TAG=latest
131
131
  # RUBY_VERSION=2.4.0-3.3.0
132
+ # MANIFEST=nightly,staging,prod,android
132
133
  # BUILD={dev,prod}
133
134
  # DEV={0,1,local}
134
- # DOCS=1
135
+ # DOCS=any
136
+ # PIPE_FAIL={0,1}
135
137
  docker build -t squared --build-arg MANIFEST=prod --build-arg SQUARED=prod .
138
+ docker build -t node --build-arg NODE_TAG=20 --build-arg NODE_INSTALL=pnpm -f Dockerfile.slim . # no docs
139
+ # OR
140
+ # RUBY_TAG=latest
141
+ # NODE_VERSION=22.x
142
+ docker build -t ruby --build-arg RUBY_TAG=3.0 --build-arg NODE_VERSION=20.x --build-arg PIPE_FAIL=0 -f Dockerfile.ruby .
136
143
 
137
144
  # Express
138
145
  docker run -it --name express --rm -p 127.0.0.1:80:80 \
data/README.ruby.md CHANGED
@@ -20,6 +20,7 @@ gem install squared
20
20
 
21
21
  * [Repo](https://source.android.com/docs/setup/reference/repo)
22
22
  * Python 3.6
23
+ * Not compatible with Windows
23
24
 
24
25
  ```sh
25
26
  mkdir -p ~/.bin
@@ -30,7 +31,7 @@ chmod a+rx ~/.bin/repo
30
31
 
31
32
  ## Example - Rakefile
32
33
 
33
- Projects from any accessible folder can be added either relative to `REPO_ROOT` or absolutely. The same Rakefile can also manage other similarly cloned repositories remotely by setting the `REPO_ROOT` environment variable to the location. Missing projects will simply be excluded from the task runner.
34
+ Projects from any accessible folder can be added relative to the parent directory (e.g. *REPO_ROOT*) or absolutely. The same Rakefile can also manage other similarly cloned `Repo` repositories remotely by setting the `REPO_ROOT` environment variable to the location. Missing projects will simply be excluded from the task runner.
34
35
 
35
36
  ```ruby
36
37
  require "squared"
@@ -45,7 +46,7 @@ require "squared/app" # All workspace related modules
45
46
 
46
47
  # NODE_ENV = production
47
48
  # REPO_ROOT = /workspaces
48
- # REPO_HOME = /workspaces/squared (Dir.pwd)
49
+ # REPO_HOME = /workspaces/squared
49
50
  # rake = /workspaces/squared/Rakefile
50
51
  # pathname = /workspaces/pathname
51
52
  # optparse = /workspaces/optparse
@@ -88,7 +89,7 @@ Workspace::Application
88
89
  variable_set :clean, ["build/sqd/"]
89
90
  end
90
91
  .style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
91
- .build(default: "status", parallel: ["pull", "fetch", "rebase", "copy", "clean", "outdated:ruby"]) do |workspace|
92
+ .build(default: "build", parallel: ["pull", "fetch", "rebase", "copy", "clean", /^outdated:/]) do |workspace|
92
93
  workspace
93
94
  .enable_aixterm
94
95
  .style({
@@ -130,12 +131,13 @@ Workspace::Application
130
131
  ```ruby
131
132
  Workspace::Application
132
133
  .new(main: "squared")
134
+ .graph(["depend"], ref: :git) # Optional
133
135
  .with(:python) do
134
136
  add("android-docs", "android")
135
137
  add("chrome-docs", "chrome", graph: "android")
136
138
  end
137
139
  .with(:node) do
138
- graph(["build", "copy"]) # Optional
140
+ graph(["build", "copy"]) # Overrides "git"
139
141
  add("e-mc", "emc")
140
142
  add("pi-r", "pir", graph: "emc")
141
143
  add("squared-express", "express", graph: "pir")
@@ -15,7 +15,7 @@ module Squared
15
15
  def_delegators :@data, :+, :each, :each_with_index, :entries, :to_a, :include?
16
16
 
17
17
  def initialize(data = [])
18
- @data = ::Set.new(data)
18
+ @data = Set.new(data)
19
19
  end
20
20
 
21
21
  def add(val)
@@ -29,7 +29,7 @@ module Squared
29
29
  alias inspect to_s
30
30
  end
31
31
 
32
- class JoinSet < ::Set
32
+ class JoinSet < Set
33
33
  def self.to_s
34
34
  super.match(/[^:]+$/)[0]
35
35
  end
@@ -94,7 +94,7 @@ module Squared
94
94
  ret = wrap.(ret, code) unless code.empty?
95
95
  return ret unless data
96
96
 
97
- out = +''
97
+ out = ''.dup
98
98
  data.to_a.each_with_index do |group, i|
99
99
  next if i == 0
100
100
 
@@ -20,17 +20,21 @@ module Squared
20
20
  end
21
21
  end
22
22
 
23
- def copy_d(src, dest, glob: ['**/*'], create: false, verbose: true)
23
+ def copy_d(src, dest, glob: ['**/*'], pass: nil, create: false, verbose: true)
24
24
  src = ::Pathname.new(src)
25
25
  dest = ::Pathname.new(dest)
26
- raise "#{dest} (not found)" if !create && !dest.exist?
26
+ raise "#{dest} (not found)" if !create && !dest.parent.exist?
27
27
 
28
28
  subdir = []
29
29
  files = 0
30
30
  dest.mkpath if create
31
+ if pass
32
+ exclude = []
33
+ (pass.is_a?(::Array) ? pass : [pass]).each { |val| exclude += ::Dir.glob(src.join(val)) }
34
+ end
31
35
  (glob.is_a?(::Array) ? glob : [glob]).each do |val|
32
36
  ::Dir.glob(src.join(val)) do |path|
33
- next if (path = ::Pathname.new(path)).directory?
37
+ next if exclude&.include?(path) || (path = ::Pathname.new(path)).directory?
34
38
 
35
39
  target = dest.join(path.relative_path_from(src))
36
40
  dir = target.dirname
@@ -27,8 +27,12 @@ module Squared
27
27
  end
28
28
  end
29
29
 
30
- def task_invoked?(name)
31
- ::Rake::Task.tasks.any? { |obj| obj.already_invoked && obj.name == name }
30
+ def task_invoked?(*args)
31
+ ::Rake::Task.tasks.any? do |obj|
32
+ next unless obj.already_invoked
33
+
34
+ args.any? { |val| val.is_a?(::Regexp) ? val.match?(obj.name) : val == obj.name }
35
+ end
32
36
  end
33
37
 
34
38
  def env(key, default = nil, suffix: @envname, equals: nil, ignore: nil)
@@ -9,7 +9,7 @@ module Squared
9
9
  class Viewer
10
10
  include Common::Format
11
11
  include Utils
12
- include ::Rake::DSL
12
+ include Rake::DSL
13
13
 
14
14
  def self.to_s
15
15
  super.match(/[^:]+$/)[0]
@@ -51,7 +51,7 @@ module Squared
51
51
  ['path not found', realpath]
52
52
  else
53
53
  @required = true
54
- project ? [project, 'not found'] : %w[name missing]
54
+ project ? [project, 'not found'] : ['name', 'missing']
55
55
  end
56
56
  warn log_message(:warn, msg, subject: self.class, hint: hint)
57
57
  end
@@ -63,18 +63,18 @@ module Squared
63
63
  view = @command && @command != name ? @command : 'view'
64
64
  params = ->(args) { exist? ? [realpath, [args.keys] + args.extras] : [args.keys, args.extras] }
65
65
  namespace view do
66
- if @mime['json'] && (exist? || !::Rake::Task.task_defined?("#{ns}:#{view}:json"))
66
+ if @mime['json'] && (exist? || !Rake::Task.task_defined?("#{ns}:#{view}:json"))
67
67
  desc format_desc(view, 'json')
68
68
  task 'json', [:keys] do |_, args|
69
69
  read_keys(JSON, 'json', *params.(args))
70
70
  end
71
71
  end
72
72
 
73
- if @mime['yaml'] && (exist? || !::Rake::Task.task_defined?("#{ns}:#{view}:yaml"))
73
+ if @mime['yaml'] && (exist? || !Rake::Task.task_defined?("#{ns}:#{view}:yaml"))
74
74
  desc format_desc(view, 'yaml', 'yml')
75
75
  task 'yaml', [:keys] do |_, args|
76
76
  require 'yaml'
77
- read_keys(YAML, 'yaml', *params.(args), ext: %w[yml yaml])
77
+ read_keys(YAML, 'yaml', *params.(args), ext: ['yml', 'yaml'])
78
78
  end
79
79
  end
80
80
  end
@@ -120,7 +120,7 @@ module Squared
120
120
  def also(path, type = nil, name: nil, gem: nil, parse: nil, opts: {})
121
121
  return self if @mime.frozen? || !(file = basepath(path)).exist?
122
122
 
123
- ext = mime_type(file)
123
+ ext = mimetype(file)
124
124
  type = type&.to_s || ext
125
125
  unless parse
126
126
  case type
@@ -140,6 +140,12 @@ module Squared
140
140
  self
141
141
  end
142
142
 
143
+ def enabled?
144
+ return File.exist?(realpath) if exist?
145
+
146
+ !@required || !!project&.enabled?
147
+ end
148
+
143
149
  def extensions
144
150
  exist? ? [@ext.sub('.', '')] : @mime.keys
145
151
  end
@@ -154,12 +160,6 @@ module Squared
154
160
  "#<#{self.class}: #{name} => #{exist? ? realpath : "#{main} {#{extensions.join(', ')}}"}>"
155
161
  end
156
162
 
157
- def enabled?
158
- return File.exist?(realpath) if exist?
159
-
160
- !@required || !!project&.enabled?
161
- end
162
-
163
163
  private
164
164
 
165
165
  def puts(*args)
@@ -167,7 +167,7 @@ module Squared
167
167
  end
168
168
 
169
169
  def read_keys(reader, type, file, keys, ext: [type])
170
- if file && (mime = mime_type(file)) && basepath(file).exist?
170
+ if file && (mime = mimetype(file)) && basepath(file).exist?
171
171
  raise_error(file, mime, hint: 'invalid') unless ext.include?(mime)
172
172
  else
173
173
  if ext.include?(mime)
@@ -227,7 +227,7 @@ module Squared
227
227
  if val.nil?
228
228
  val = data
229
229
  items.each do |name|
230
- raise name unless val.is_a?(::Hash) && val.key?(name)
230
+ raise name unless val.is_a?(Hash) && val.key?(name)
231
231
 
232
232
  val = val[name]
233
233
  end
@@ -256,15 +256,28 @@ module Squared
256
256
  end
257
257
  end
258
258
 
259
- def basepath(file)
260
- project ? project.basepath(file) : Pathname.new(file).realdirpath
261
- end
262
-
263
259
  def task_name(val)
264
260
  @prefix ? "#{@prefix}:#{val}" : val.to_s
265
261
  end
266
262
 
267
- def mime_type(file)
263
+ def format_desc(command, *ext, exist: exist?)
264
+ val = "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys+]"
265
+ message(@prefix, *name.split(':'), command, val, empty: true)
266
+ end
267
+
268
+ def exist?
269
+ !@ext.empty? && (!@required || !project.nil?)
270
+ end
271
+
272
+ def warning?
273
+ project ? project.workspace.warning : true
274
+ end
275
+
276
+ def stdin?
277
+ pipe == 0
278
+ end
279
+
280
+ def mimetype(file)
268
281
  case (ret = File.extname(file).sub('.', '').downcase)
269
282
  when 'yml'
270
283
  'yaml'
@@ -277,25 +290,12 @@ module Squared
277
290
  end
278
291
  end
279
292
 
280
- def format_desc(command, *ext, exist: exist?)
281
- val = "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys+]"
282
- message(@prefix, *name.split(':'), command, val, empty: true)
283
- end
284
-
285
293
  def realpath
286
294
  basepath(file = main + @ext).to_s rescue file
287
295
  end
288
296
 
289
- def exist?
290
- !@ext.empty? && (!@required || !project.nil?)
291
- end
292
-
293
- def warning?
294
- project ? project.workspace.warning : true
295
- end
296
-
297
- def stdin?
298
- pipe == 0
297
+ def basepath(file)
298
+ project ? project.basepath(file) : Pathname.new(file).realdirpath
299
299
  end
300
300
  end
301
301
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.0.12'
4
+ VERSION = '0.1.0'
5
5
  end
@@ -5,7 +5,7 @@ module Squared
5
5
  class Application
6
6
  include Common::Format
7
7
  include Utils
8
- include ::Rake::DSL
8
+ include Rake::DSL
9
9
 
10
10
  SCRIPT_OBJ = {
11
11
  run: nil,
@@ -71,12 +71,12 @@ module Squared
71
71
  @extensions = []
72
72
  @pipe = env_pipe(pipe, (ARG[:OUT] && env(ARG[:OUT])) || 1, root: @home)
73
73
  @exception = env_bool(exception)
74
- @verbose = env_bool(verbose, verbose.nil? || verbose.is_a?(::String) ? @pipe != 0 : verbose)
74
+ @verbose = env_bool(verbose, verbose.nil? || verbose.is_a?(String) ? @pipe != 0 : verbose)
75
75
  @warning = @verbose != false
76
76
  @closed = false
77
77
  if common
78
78
  @theme = __get__(:theme)[:workspace]
79
- ARG[:COLOR] = false if @pipe == 0 || @pipe.is_a?(::Pathname)
79
+ ARG[:COLOR] = false if @pipe == 0 || @pipe.is_a?(Pathname)
80
80
  else
81
81
  @theme = {}
82
82
  end
@@ -95,7 +95,7 @@ module Squared
95
95
 
96
96
  def initialize_session
97
97
  @envname = @main.gsub(/[^\w]+/, '_').upcase.freeze
98
- return unless @pipe.is_a?(::Pathname)
98
+ return unless @pipe.is_a?(Pathname)
99
99
 
100
100
  bord = '#' * Project.line_width
101
101
  puts bord, format('Session started on %s by %s', Time.now.to_s, @main), bord
@@ -104,7 +104,13 @@ module Squared
104
104
  def build(parallel: [], **kwargs)
105
105
  return self unless enabled? && !@closed
106
106
 
107
- kwargs[:parallel] = parallel.map(&:to_s)
107
+ if kwargs[:pattern].is_a?(Array)
108
+ kwargs[:parallel] = parallel.map(&:to_s)
109
+ else
110
+ kwargs[:pattern] = []
111
+ kwargs[:parallel] = parallel.reject { |val| val.is_a?(Regexp) && (kwargs[:pattern] << val) }
112
+ .map(&:to_s)
113
+ end
108
114
  @project.each_value do |proj|
109
115
  next unless proj.enabled?
110
116
 
@@ -131,9 +137,9 @@ module Squared
131
137
  kind = val.first
132
138
  val = kind if val.size == 1
133
139
  case kind
134
- when ::String
140
+ when String
135
141
  @group = val
136
- when ::Symbol
142
+ when Symbol
137
143
  @ref = val
138
144
  else
139
145
  raise_error('group{Symbol} | ref{String}', hint: 'missing') if block_given?
@@ -182,14 +188,14 @@ module Squared
182
188
  def banner(*args, command: true, styles: nil, border: nil, group: @group, ref: @ref)
183
189
  data = { command: command, order: [], styles: check_style(styles, empty: false), border: check_style(border) }
184
190
  args.each do |meth|
185
- if meth.is_a?(::Array)
191
+ if meth.is_a?(Array)
186
192
  found = false
187
193
  meth = meth.select do |val|
188
194
  case val
189
- when ::Symbol
195
+ when Symbol
190
196
  found = true
191
197
  Application.attr_banner.include?(val)
192
- when ::String
198
+ when String
193
199
  true
194
200
  else
195
201
  false
@@ -227,10 +233,10 @@ module Squared
227
233
  ref = if kwargs.key?(:ref)
228
234
  kwargs = kwargs.dup unless @withargs
229
235
  kwargs.delete(:ref)
230
- elsif @ref.is_a?(::Symbol)
236
+ elsif @ref.is_a?(Symbol)
231
237
  @ref
232
238
  end
233
- if @group.is_a?(::String) && !kwargs.key?(:group)
239
+ if @group.is_a?(String) && !kwargs.key?(:group)
234
240
  kwargs = kwargs.dup unless @withargs
235
241
  kwargs[:group] = @group
236
242
  end
@@ -242,7 +248,7 @@ module Squared
242
248
  index += 1
243
249
  name = "#{project}-#{index}"
244
250
  end
245
- proj = ((if !ref.is_a?(::Class)
251
+ proj = ((if !ref.is_a?(Class)
246
252
  Application.find(ref, path: path)
247
253
  elsif ref < Project::Base
248
254
  ref
@@ -359,18 +365,33 @@ module Squared
359
365
  ret
360
366
  end
361
367
 
368
+ def task_sync(key)
369
+ key = task_name(key)
370
+ task_defined?(ret = task_join(key, 'sync')) ? ret : key
371
+ end
372
+
362
373
  def script_find(*args)
363
374
  args.reverse_each do |val|
364
- next unless val && (ret = val.is_a?(::Symbol) ? @script[:ref!][val] : @script[:group!][val.to_sym])
375
+ next unless val && (ret = val.is_a?(Symbol) ? @script[:ref!][val] : @script[:group!][val.to_sym])
365
376
 
366
377
  return ret
367
378
  end
368
379
  @script[:ref!][:_] || SCRIPT_OBJ
369
380
  end
370
381
 
371
- def script_get(group: nil, ref: nil)
382
+ def script_get(*args, group: nil, ref: nil)
372
383
  if group
373
384
  @script[:group][group.to_sym]
385
+ elsif ref.is_a?(Array)
386
+ ref = ref.each
387
+ end
388
+ if ref.instance_of?(Enumerator)
389
+ ref.each do |key|
390
+ next unless (ret = @script[:ref][key])
391
+
392
+ return ret if args.empty? || args.any? { |val| ret.key?(val) }
393
+ end
394
+ nil
374
395
  elsif ref
375
396
  @script[:ref][ref]
376
397
  end
@@ -384,14 +405,6 @@ module Squared
384
405
  @banner[:ref][:_]
385
406
  end
386
407
 
387
- def to_s
388
- (home? ? home : root).to_s
389
- end
390
-
391
- def inspect
392
- "#<#{self.class}: #{main} => #{self}>"
393
- end
394
-
395
408
  def enabled?
396
409
  !@extensions.empty? || @project.values.any?(&:enabled?)
397
410
  end
@@ -409,7 +422,7 @@ module Squared
409
422
  end
410
423
 
411
424
  def task_defined?(*key)
412
- ::Rake::Task.task_defined?(key.size == 1 ? key.first : task_join(*key))
425
+ Rake::Task.task_defined?(key.size == 1 ? key.first : task_join(*key))
413
426
  end
414
427
 
415
428
  def dev?(**kwargs)
@@ -432,6 +445,10 @@ module Squared
432
445
  home.join(*args)
433
446
  end
434
447
 
448
+ def pwd
449
+ Pathname.new(Rake.application.original_dir)
450
+ end
451
+
435
452
  def baseref
436
453
  Application.baseref
437
454
  end
@@ -440,14 +457,22 @@ module Squared
440
457
  { exception: exception, warning: warning }
441
458
  end
442
459
 
460
+ def to_s
461
+ (home? ? home : root).to_s
462
+ end
463
+
464
+ def inspect
465
+ "#<#{self.class}: #{main} => #{self}>"
466
+ end
467
+
443
468
  public :task_join
444
469
 
445
470
  private
446
471
 
447
472
  def __build__(default: nil, **)
448
- if default && task_defined?(t = task_name(default)) && !task_defined?(n = ::Rake.application.default_task_name)
449
- task n => t
450
- end
473
+ return unless default && task_defined?(out = task_name(default))
474
+
475
+ task Rake.application.default_task_name => out
451
476
  end
452
477
 
453
478
  def puts(*args)
@@ -477,10 +502,6 @@ module Squared
477
502
  end
478
503
  end
479
504
 
480
- def script_obj
481
- SCRIPT_OBJ.dup
482
- end
483
-
484
505
  def script?(state, target: nil, pat: nil, group: nil, ref: baseref, global: false)
485
506
  data = script_find(ref, group)
486
507
  if global
@@ -489,7 +510,11 @@ module Squared
489
510
  end
490
511
  return false if state == :prod && data[:dev] == true && data[:global]
491
512
 
492
- target && pat.is_a?(::Regexp) ? as_a(target).any? { |val| pat.match?(val) } : pat == true
513
+ target && pat.is_a?(Regexp) ? as_a(target).any? { |val| pat.match?(val) } : pat == true
514
+ end
515
+
516
+ def scriptobj
517
+ SCRIPT_OBJ.dup
493
518
  end
494
519
  end
495
520
  end