squared 0.4.0 → 0.4.1

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: a6a70feacca1b87fbe9d6da4e71045212f5dc5e9add78e93e8223a5f73b6f6d9
4
- data.tar.gz: b73756bef57213d92fe4ed5f0763945645315a06a8d084bb32e40105ce78d64e
3
+ metadata.gz: f0ee3da01c8f4091c2363f6c8b0821cbc742d7dd95a4fda4e6a26e949ce0c61f
4
+ data.tar.gz: 4642f0e308608a80077cddb81ecc3c03ff58a6baaa066b644c1ae8b922d13668
5
5
  SHA512:
6
- metadata.gz: 34c45acd9506ad1bc7018c0b0f73e1e2db7623d6b42b7b3199ee7cb7394716a1ec13484d15a71d343415ccd4090a1217579416fba8010b5977cbc324bbf7b849
7
- data.tar.gz: 62ac8c5ea8289fcb08dbf1c5e2cca60e06ea5470eb1f8ec1ce667bcce5cc0eec5d67448ac1b2642a7b5af0c2f3e30530f6513374d2642baa2993aca3ad769608
6
+ metadata.gz: 33f08fcd47d1ac5896a5cc231e8466de17f2edbd2d987fb411c21b8db8cf734b880fefbb4454a69e610a35aa86609e94bac4dc44264e3a10a3cd69efd6429186
7
+ data.tar.gz: 5e424cb159c5a00512eca6ea9d8a0328082ecb85a30c9e769cd67bbd21d95b16a5d6f906a22a2f2c2d9fecbad5da2721ee1cc4b09722ffbdcbbcbb0a39d0c985
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.1] - 2025-03-20
4
+
5
+ ### Added
6
+
7
+ - Status logger messages are written to file.
8
+ - Docker command image action push was implemented.
9
+ - Git command show action textconv was implemented.
10
+ - Docker mounts for container command run is supported.
11
+
12
+ ### Removed
13
+
14
+ - Git batch commands pull+s and rebase+s were removed.
15
+
16
+ ## [0.3.6] - 2025-03-12
17
+
18
+ ### Added
19
+
20
+ - Git command stash action clear was implemented.
21
+
22
+ ### Fixed
23
+
24
+ - Git command stash did not validate index argument.
25
+ - Project graph command does not require arguments.
26
+ - Ruby gem command exec did not add project name.
27
+
3
28
  ## [0.4.0] - 2025-03-06
4
29
 
5
30
  ### Added
@@ -37,13 +62,16 @@
37
62
 
38
63
  - Node copy method will only override when key exists.
39
64
  - Base command copy and clean can accept a hash.
40
- - Character methods in Shell common module were removed.
41
65
  - ENV build options are merged with base options.
42
- - Git command diff action cached was removed.
43
66
  - Git log and diff uses H0 alias for HEAD~n commit.
44
67
  - Project events support multiple associated routines.
45
68
  - Git command restore was relocated to "git" task namespace.
46
69
 
70
+ ### Removed
71
+
72
+ - Character methods in Shell common module were removed.
73
+ - Git command diff action cached was removed.
74
+
47
75
  ### Fixed
48
76
 
49
77
  - Git base class did not check for null Logger instance.
@@ -352,7 +380,9 @@
352
380
 
353
381
  - Changelog was created.
354
382
 
383
+ [0.4.1]: https://github.com/anpham6/squared/releases/tag/v0.4.1-ruby
355
384
  [0.4.0]: https://github.com/anpham6/squared/releases/tag/v0.4.0-ruby
385
+ [0.3.6]: https://github.com/anpham6/squared/releases/tag/v0.3.6-ruby
356
386
  [0.3.5]: https://github.com/anpham6/squared/releases/tag/v0.3.5-ruby
357
387
  [0.3.4]: https://github.com/anpham6/squared/releases/tag/v0.3.4-ruby
358
388
  [0.3.3]: https://github.com/anpham6/squared/releases/tag/v0.3.3-ruby
data/README.ruby.md CHANGED
@@ -105,8 +105,11 @@ Workspace::Application
105
105
  variable_set :clean, ["build/sqd/"]
106
106
  end
107
107
  .with(:docker, pass: ["unpack"]) do
108
- .add("squared", "docker", file: "Dockerfile", context: ".", tag: "latest", args: "--ssh=default", secrets: ["id=github,env=GITHUB_TOKEN"]) do # Docker
109
- series(:clean) do # run | depend | doc | lint | test | copy | clean
108
+ .add("squared", "docker", file: "Dockerfile", context: ".", tag: "latest", registry: "localhost:5000", username: "squared",
109
+ args: "--ssh=default",
110
+ secrets: ["id=github,env=GITHUB_TOKEN"],
111
+ mounts: ["src=.,dst=/project,ro,bind-propagation=rshared"]) do # Docker
112
+ series(:clean) do # run | depend | doc | lint | test | copy | clean
110
113
  File.read(basepath("docker-bake.hcl"))
111
114
  .scan(/\btags\s+=\s+\["([^"]+)"\]/)
112
115
  .each { |val| image(:rm, tag: val.first) }
@@ -118,7 +118,7 @@ module Squared
118
118
  if !val.is_a?(::Numeric)
119
119
  val = val.to_sym
120
120
  ret << val if colors.key?(val) || TEXT_STYLE.include?(val)
121
- elsif val >= 0 && val <= 256
121
+ elsif val.between?(0, 256)
122
122
  ret << val
123
123
  elsif val < 0 && (b = val.to_s.split('.')[1])
124
124
  b = b[0, 3]
@@ -170,10 +170,15 @@ module Squared
170
170
  color ? sub_style(ret, *styles) : ret
171
171
  end
172
172
 
173
- def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR], pass: false)
174
- return false if !pass && level.is_a?(::Numeric) && level < ARG[:LEVEL]
175
-
173
+ def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR], append: true, pass: false)
176
174
  args = args.map(&:to_s)
175
+ if level.is_a?(::Numeric)
176
+ if append && respond_to?(:log)
177
+ ref = log rescue nil
178
+ ref.add(level, message(subject, *args, hint: hint, space: ', ')) if ref.is_a?(Logger)
179
+ end
180
+ return false if !pass && level < ARG[:LEVEL]
181
+ end
177
182
  if args.size > 1 && !hint
178
183
  title = log_title(level, color: false)
179
184
  sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
@@ -209,8 +214,8 @@ module Squared
209
214
 
210
215
  module_function
211
216
 
212
- def message(*args, hint: nil, empty: false)
213
- (empty ? args.reject { |val| val.nil? || val.empty? } : args).join(ARG[:SPACE]) + (hint ? " (#{hint})" : '')
217
+ def message(*args, hint: nil, empty: false, space: ARG[:SPACE])
218
+ (empty ? args.reject { |val| val.nil? || val.empty? } : args).join(space) + (hint ? " (#{hint})" : '')
214
219
  end
215
220
 
216
221
  def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, border: nil, pipe: nil)
@@ -12,6 +12,19 @@ module Squared
12
12
  val.split(/\s*(?<!\\)#{char}\s*/o)
13
13
  end
14
14
 
15
+ def split_option(val)
16
+ val = val.strip
17
+ return [val, '', ''] unless (i = val.index('='))
18
+
19
+ last = val[i + 1..-1].strip
20
+ quote = ''
21
+ if last =~ /^(["'])(.+)\1$/
22
+ last = $2
23
+ quote = $1
24
+ end
25
+ [val[0..i - 1], last, quote]
26
+ end
27
+
15
28
  def task_invoke(*cmd, args: [], exception: true, warning: true)
16
29
  cmd.each { |name| Rake::Task[name].invoke(*args) }
17
30
  rescue StandardError => e
@@ -141,7 +154,7 @@ module Squared
141
154
  return ret.to_i
142
155
  end
143
156
  when ::Numeric
144
- return key if key >= 0 && key <= 2
157
+ return key if key.between?(0, 2)
145
158
  end
146
159
  default
147
160
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.4.0'
4
+ VERSION = '0.4.1'
5
5
  end
@@ -264,7 +264,7 @@ module Squared
264
264
 
265
265
  format_desc action, flag, '(-)project*'
266
266
  task flag do |_, args|
267
- args = param_guard(action, flag, args: args.to_a.reject { |val| name == val.to_s })
267
+ args = args.to_a.reject { |val| name == val.to_s }
268
268
  if flag == :run
269
269
  graph args
270
270
  else
@@ -871,7 +871,7 @@ module Squared
871
871
  log&.warn "ENV was discarded: #{var}" if var
872
872
  task_invoke(cmd, exception: exception, warning: warning?)
873
873
  else
874
- print_item format_banner(cmd, banner: banner) if sync
874
+ print_item format_banner(cmd, banner: banner) if sync && !env('BANNER', equals: '0')
875
875
  args = var.is_a?(Hash) ? [var, cmd] : [cmd]
876
876
  shell(*args, chdir: chdir, exception: exception)
877
877
  end
@@ -970,7 +970,13 @@ module Squared
970
970
  next if pass.include?(meth)
971
971
 
972
972
  if workspace.task_defined?(cmd = task_join(proj.name, meth))
973
+ if ENV.key?(key = "BANNER_#{proj.name.upcase}")
974
+ key = nil
975
+ else
976
+ ENV[key] = '0'
977
+ end
973
978
  run(cmd, sync: false, banner: false)
979
+ ENV.delete(key) if key
974
980
  elsif proj.has?(meth, tasks || group ? nil : workspace.baseref)
975
981
  proj.__send__(meth.to_sym, sync: sync)
976
982
  end
@@ -42,7 +42,7 @@ module Squared
42
42
  env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b health-retries=i
43
43
  health-start-interval=b health-start-period=b health-timeout=b h|hostname=e io-maxbandwidth=b
44
44
  io-maxiops=b ip=b ip6=e ipc=b isolation=b kernel-memory=b l|label=q label-file=p link=b
45
- link-local-ip=b log-driver=b log-opt=q mac-address=e memory-swappiness=b mount=q name=b network=b
45
+ link-local-ip=b log-driver=b log-opt=q mac-address=e memory-swappiness=b mount=qq name=b network=b
46
46
  network-alias=b oom-score-adj=b pid=b platform=b p|publish=e pull=b restart=b runtime=b
47
47
  security-opt=q shm-size=b sig-proxy=b? stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q
48
48
  ulimit=q user=e userns=b uts=b v|volume=q volume-driver=b volumes-from=b w|workdir=q].freeze,
@@ -61,11 +61,17 @@ module Squared
61
61
  }.freeze,
62
62
  image: {
63
63
  list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
64
- push: %w[disable-content-trust=b? platform=b q|quiet].freeze,
64
+ push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
65
65
  rm: %w[f|force no-prune].freeze
66
66
  }.freeze
67
67
  }.freeze
68
- private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER
68
+ VAL_DOCKER = {
69
+ run: {
70
+ bind: %w[type source src destination dst target readonly ro bind-propagation].freeze,
71
+ tmpfs: %w[type destination dst target tmpfs-size tmpfs-mode].freeze
72
+ }.freeze
73
+ }.freeze
74
+ private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
69
75
 
70
76
  class << self
71
77
  def tasks
@@ -82,7 +88,7 @@ module Squared
82
88
  @@tasks[ref] = {
83
89
  'build' => %i[tag context bake].freeze,
84
90
  'compose' => %i[build run exec up].freeze,
85
- 'image' => %i[list rm].freeze,
91
+ 'image' => %i[list rm push].freeze,
86
92
  'container' => %i[run exec update commit inspect diff start stop restart pause unpause top stats kill
87
93
  rm].freeze
88
94
  }.freeze
@@ -90,14 +96,15 @@ module Squared
90
96
  attr_reader :context
91
97
  attr_accessor :tag
92
98
 
93
- def initialize(*, file: nil, context: nil, tag: nil, secrets: nil, registry: nil, **kwargs)
99
+ def initialize(*, file: nil, context: nil, tag: nil, secrets: nil, mounts: [], registry: nil, **kwargs)
94
100
  super
95
101
  return unless dockerfile(file).exist?
96
102
 
97
103
  @context = context
98
104
  @tag = tag || "#{@project}:latest"
105
+ @mounts = mounts
99
106
  @secrets = secrets
100
- @registry = registry
107
+ @registry = [registry, kwargs[:username]].compact.join('/')
101
108
  initialize_ref Docker.ref
102
109
  initialize_logger(**kwargs)
103
110
  initialize_env(**kwargs)
@@ -169,9 +176,18 @@ module Squared
169
176
  end
170
177
  end
171
178
  when 'image'
172
- format_desc(action, flag, flag == :rm ? 'id*,opts*' : 'opts*,args*')
173
- task flag do |_, args|
174
- image flag, args.to_a
179
+ case flag
180
+ when :push
181
+ format_desc action, flag, 'tag,registry/username?,opts*'
182
+ task flag, [:tag] do |_, args|
183
+ tag = param_guard(action, flag, args: args, key: :tag)
184
+ image(flag, args.to_a.drop(1), id: tag)
185
+ end
186
+ else
187
+ format_desc(action, flag, flag == :rm ? 'id*,opts*' : 'opts*,args*')
188
+ task flag do |_, args|
189
+ image flag, args.to_a
190
+ end
175
191
  end
176
192
  end
177
193
  end
@@ -299,7 +315,39 @@ module Squared
299
315
  out = option_sanitize(opts, list, first: flag == :exec).first
300
316
  from = :"container:#{flag}"
301
317
  case flag
302
- when :exec, :run
318
+ when :run, :exec
319
+ if flag == :run && !session_arg?('mount')
320
+ run = VAL_DOCKER[:run]
321
+ both = run[:bind] + run[:tmpfs]
322
+ diff = run[:bind].reject { |val| run[:tmpfs].include?(val) }
323
+ delim = Regexp.new(",\\s*(?=#{both.join('|')})")
324
+ as_a(@mounts).each do |val|
325
+ args = []
326
+ tmpfs = true
327
+ val.split(delim).each do |opt|
328
+ k, v, q = split_option(opt)
329
+ next unless both.include?(k)
330
+
331
+ if k == 'type'
332
+ tmpfs = false if v == 'bind'
333
+ next
334
+ elsif diff.include?(k)
335
+ tmpfs = false
336
+ end
337
+ case k
338
+ when 'readonly', 'ro'
339
+ args << k
340
+ next
341
+ when 'source', 'src', 'destination', 'dst', 'target'
342
+ v = basepath(v)
343
+ v = shell_quote(v, option: false, force: false) if q == ''
344
+ tmpfs = false if k[0] == 's'
345
+ end
346
+ args << "#{k}=#{q + v + q}"
347
+ end
348
+ cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
349
+ end
350
+ end
303
351
  append_command(flag, id.to_s.empty? ? tag : id, out, target: cmd, from: from)
304
352
  when :update
305
353
  raise_error('missing container', hint: from) if out.empty?
@@ -405,12 +453,14 @@ module Squared
405
453
  end
406
454
  when :push
407
455
  id ||= tag
456
+ registry ||= out.shift || @registry
408
457
  raise_error(id ? "unknown args: #{out.join(', ')}" : 'no id/tag given', hint: from) unless id && out.empty?
409
- reg = (registry || @registry).chomp('/')
410
- uri = shell_quote("#{reg}/#{id}")
458
+ raise_error('username/registry not provided', hint: from) unless registry
459
+ registry.chomp!('/')
460
+ uri = shell_quote("#{registry}/#{id}")
411
461
  cmd << uri
412
462
  img = docker_output 'image', 'tag', id, uri
413
- return unless confirm_command(img.to_s, cmd.to_s, target: id, as: reg, title: from)
463
+ return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
414
464
 
415
465
  run(img, exception: true, sync: false, banner: false)
416
466
  end
@@ -145,6 +145,8 @@ module Squared
145
145
 
146
146
  module Project
147
147
  class Git < Base
148
+ include Prompt
149
+
148
150
  OPT_GIT = {
149
151
  common: %w[bare p|paginate P|no-pager glob-pathspecs icase-pathspecs literal-pathspecs no-optional-locks
150
152
  no-replace-objects noglob-pathspecs c=q config-env=q exec-path=p namespace=p].freeze,
@@ -300,10 +302,6 @@ module Squared
300
302
  %i[pull rebase fetch clone stash status branch revbuild].freeze
301
303
  end
302
304
 
303
- def batchargs
304
- [ref, { 'pull+s': %i[stash pull], 'rebase+s': %i[stash rebase] }]
305
- end
306
-
307
305
  def config?(val)
308
306
  return false unless (val = as_path(val))
309
307
 
@@ -326,8 +324,8 @@ module Squared
326
324
  'refs' => %i[heads tags remote].freeze,
327
325
  'reset' => %i[commit index patch mode].freeze,
328
326
  'rev' => %i[commit branch output parseopt build].freeze,
329
- 'show' => %i[format oneline].freeze,
330
- 'stash' => %i[push pop apply drop list].freeze,
327
+ 'show' => %i[format oneline textconv].freeze,
328
+ 'stash' => %i[push pop apply drop clear list].freeze,
331
329
  'tag' => %i[add delete list].freeze
332
330
  }.freeze
333
331
 
@@ -579,12 +577,18 @@ module Squared
579
577
  when :oneline
580
578
  format_desc action, flag, 'opts*,object*'
581
579
  task flag do |_, args|
582
- show 'oneline', args.to_a.push('abbrev-commit')
580
+ show flag, args.to_a.push('abbrev-commit')
583
581
  end
584
582
  when :format
585
583
  format_desc action, flag, 'format?,opts*,object*'
586
584
  task flag, [:format] do |_, args|
587
- show args.format, args.extras
585
+ show(flag, args.extras, format: args.format)
586
+ end
587
+ when :textconv
588
+ format_desc action, flag, 'files+'
589
+ task flag do |_, args|
590
+ files = param_guard(action, flag, args: args.to_a)
591
+ show(flag, files: files)
588
592
  end
589
593
  end
590
594
  when 'rebase', 'merge'
@@ -783,8 +787,15 @@ module Squared
783
787
  when :push
784
788
  append_pathspec refs
785
789
  when :pop, :apply, :drop
786
- cmd << shell_quote(refs.pop)
787
- option_clear refs
790
+ unless refs.empty?
791
+ cmd << shell_escape(refs.pop)
792
+ option_clear refs
793
+ end
794
+ when :clear
795
+ if confirm("Remove #{sub_style('all', styles: theme[:active])} the stash entries? [y/N] ", 'N')
796
+ source(stdout: true)
797
+ end
798
+ return
788
799
  when :list
789
800
  out, banner, from = source(io: true)
790
801
  print_item banner
@@ -1218,8 +1229,21 @@ module Squared
1218
1229
  source(stdout: stdout)
1219
1230
  end
1220
1231
 
1221
- def show(format, opts = [])
1232
+ def show(flag, opts = [], format: nil, files: [])
1222
1233
  cmd, opts = git_session('show', opts: opts)
1234
+ case flag
1235
+ when :textconv
1236
+ cmd << '--textconv'
1237
+ files = files.map { |val| Dir[val] }
1238
+ .flatten
1239
+ .select { |val| projectpath?(val) }
1240
+ .map { |val| shell_quote("HEAD:#{val}") }
1241
+ append_value files
1242
+ source(banner: false)
1243
+ return
1244
+ when :oneline
1245
+ format = flag.to_s
1246
+ end
1223
1247
  if format
1224
1248
  case (val = format.downcase)
1225
1249
  when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
@@ -4,8 +4,6 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Node < Git
7
- include Prompt
8
-
9
7
  OPT_NPM = {
10
8
  common: %w[dry-run include-workspace-root workspaces=b? w|workspace=b].freeze,
11
9
  install: %w[prefer-dedupe package-lock-only cpu=b libc=b os=b].freeze,
@@ -40,7 +40,6 @@ module Squared
40
40
 
41
41
  class << self
42
42
  def populate(*); end
43
- def batchargs(*); end
44
43
 
45
44
  def tasks
46
45
  [:outdated].freeze
@@ -39,7 +39,6 @@ module Squared
39
39
 
40
40
  class << self
41
41
  def populate(*); end
42
- def batchargs(*); end
43
42
 
44
43
  def tasks
45
44
  [:outdated].freeze
@@ -155,7 +154,7 @@ module Squared
155
154
  when 'gem'
156
155
  case flag
157
156
  when :outdated, :build, :push, :exec
158
- format_desc action, flag, 'opts*'
157
+ format_desc(action, flag, 'opts*', before: flag == :exec ? 'command+' : nil)
159
158
  task flag do |_, args|
160
159
  gemx flag, args.to_a
161
160
  end
@@ -471,7 +470,7 @@ module Squared
471
470
  end
472
471
  when :exec
473
472
  raise_error('no command given', hint: flag) if out.empty?
474
- cmd << out.join(' ')
473
+ cmd << project << out.join(' ')
475
474
  else
476
475
  raise_error('no gemname given', hint: flag) if out.empty? && !session_arg?('system')
477
476
  if flag == :pristine
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-06 00:00:00.000000000 Z
10
+ date: 2025-03-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rake