squared 0.7.13 → 0.7.15

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: 493f110582768ad2833f1a7a9f873cc5efd129866bf9acd4576b745bbfb6569a
4
- data.tar.gz: 0bcd73d87fa78c2aea93b73bbbef7443fbcac9d4401414c4c62c19813709906a
3
+ metadata.gz: 06724bcbd4880ed30f612cd24df3aaaf3faef5043ffa7211d48ca4cda7c87209
4
+ data.tar.gz: d40c633dafdf27ecdbaf236eaa7643fea3821a3ecae3c152522b50657ef7e5f9
5
5
  SHA512:
6
- metadata.gz: e0f39d08c1481ce320e263ebd17127616d3056bc96d720a55f68a0a279f70babb88f52366a481d12348ce7884b69642db88d4d1b1d6b82907b326f528942579f
7
- data.tar.gz: 0623ff277e624a6e553b2ff3879b48868ab450e7cff1eee030ab06dc09c982dc01e7e18ca9b33d8f2f6a596f0a3c8e2815624426a1399bcc2149081e03a82aef
6
+ metadata.gz: f739d48e406ae786159b843776f4b3c2b3d0e16029de9d6b180ae8921c7596cb7f318fd4f3492419c0c2e2f331ac3c5bb860487035d1bac46a0e71fd7ebb7aee
7
+ data.tar.gz: ad13adfe9feb573756cb277eaa11b1418129db2a9ffce3c99be93e725d2ca72b1c0df5e4886905bbb15a113676ad993f906fc2525fbdfcee552a31db3e4996a9
data/CHANGELOG.md CHANGED
@@ -1,12 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.15] - 2026-11-04
4
+
5
+ ### Added
6
+
7
+ - Git command commit action pathspec was implemented.
8
+ - Common base argument TAB for column alignment was created.
9
+ - Node command package action deny can modify currently approved scripts.
10
+
11
+ ### Changed
12
+
13
+ - Node command package action [approve|deny] uses install-scripts ls.
14
+
15
+ ### Fixed
16
+
17
+ - Bundle exec wrapper as a Hash did not support using alternate Gemfile.
18
+ - Common base ARG data objects were not frozen with __freeze__.
19
+
20
+ ## [0.7.14] - 2026-10-22
21
+
22
+ ### Changed
23
+
24
+ - Python program meson prefix options use local path resolution.
25
+ - Bundle exec wrapper can be configured per application.
26
+
27
+ ### Fixed
28
+
29
+ - Bundle exec wrapper did not accept boolean values.
30
+
31
+ ## [0.6.21] - 2026-10-22
32
+
33
+ ### Fixed
34
+
35
+ - RuboCop did not resolve config to project directory.
36
+ - Python program did not use correct separator for double dash options.
37
+
3
38
  ## [0.7.13] - 2026-09-25
4
39
 
5
40
  ### Fixed
6
41
 
7
42
  - OptionPartition did not parse quoted option values.
8
43
 
9
- ## [0.6.20] - 2026-09-25
44
+ ## [0.6.20]
10
45
 
11
46
  ### Added
12
47
 
@@ -2034,6 +2069,8 @@
2034
2069
 
2035
2070
  - Changelog was created.
2036
2071
 
2072
+ [0.7.15]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.15
2073
+ [0.7.14]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.14
2037
2074
  [0.7.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.13
2038
2075
  [0.7.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.12
2039
2076
  [0.7.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.11
@@ -2048,6 +2085,7 @@
2048
2085
  [0.7.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.2
2049
2086
  [0.7.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.1
2050
2087
  [0.7.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.0
2088
+ [0.6.21]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.21
2051
2089
  [0.6.20]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.20
2052
2090
  [0.6.19]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.19
2053
2091
  [0.6.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.18
data/README.md CHANGED
@@ -10,11 +10,11 @@
10
10
  | 2024-12-07 | 0.1.0 | 2.4.0 | 3.3.6 | |
11
11
  | 2025-01-07 | 0.2.0 | | 3.4.0 | |
12
12
  | 2025-02-07 | 0.3.0 | | 3.4.1 | |
13
- | 2025-03-06 | 0.4.0 | | 3.4.2 | * |
14
- | 2025-06-16 | 0.5.0 | 2.5.0 | 3.4.4 | * |
13
+ | 2025-03-06 | 0.4.0 | | 3.4.2 | |
14
+ | 2025-06-16 | 0.5.0 | 2.5.0 | 3.4.4 | |
15
15
  | ---------- | ----- | ----- | ----- | --- |
16
16
  | 2025-08-23 | 0.5.5 | | 3.4.5 | |
17
- | 2025-10-31 | 0.6.0 | | 3.4.7 | * |
17
+ | 2025-10-31 | 0.6.0 | | 3.4.7 | |
18
18
  | 2026-01-07 | 0.7.0 | 2.5.0 | 4.0.0 | * |
19
19
 
20
20
  The range chart indicates the *latest* Ruby tested against at the time of release.
@@ -13,6 +13,7 @@ module Squared
13
13
  STRICT: false,
14
14
  BANNER: true,
15
15
  CHOICE: 25,
16
+ TAB: 4,
16
17
  QUOTE: "'",
17
18
  SPACE: ' => ',
18
19
  SUCCESS: 'Success',
@@ -102,6 +103,7 @@ module Squared
102
103
 
103
104
  def __freeze__
104
105
  PATH.freeze
106
+ ARG.each_value { |val| val.freeze if val.is_a?(::Hash) || val.is_a?(::Array) }
105
107
  ARG.freeze
106
108
  VAR.each_value(&:freeze)
107
109
  VAR[:theme].each_value { |val| val.freeze.each_value(&:freeze) }
@@ -295,7 +295,7 @@ module Squared
295
295
  if footer
296
296
  unless sub.empty? && !right
297
297
  footer.map! do |s|
298
- s = s.rjust(n + 4) if right
298
+ s = s.rjust(n + ARG[:TAB]) if right
299
299
  sub.each { |h| sub_style!(s, **h) }
300
300
  s
301
301
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.7.13'
4
+ VERSION = '0.7.15'
5
5
  end
@@ -1166,10 +1166,20 @@ module Squared
1166
1166
  ret = basepath(*args)
1167
1167
  return ret unless ascend && !ret.exist?
1168
1168
 
1169
+ case ascend
1170
+ when String, Pathname
1171
+ root = Pathname.new(ascend).cleanpath
1172
+ root = nil unless root.absolute? && root.directory?
1173
+ end
1169
1174
  path.parent.ascend.each do |dir|
1170
1175
  target = dir.join(*args)
1171
1176
  return target if target.exist?
1172
- break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
1177
+
1178
+ if root
1179
+ break if dir == root
1180
+ elsif workspace.root == dir || parent&.path == dir || (ascend.is_a?(String) && dir.join(ascend).exist?)
1181
+ break
1182
+ end
1173
1183
  end
1174
1184
  ret
1175
1185
  end
@@ -1872,7 +1882,7 @@ module Squared
1872
1882
  out << ''
1873
1883
  end
1874
1884
  if from
1875
- out << from
1885
+ out << (from = from.to_s)
1876
1886
  /\A(#{Regexp.escape(from)})(.*)\z/
1877
1887
  end
1878
1888
  else
@@ -902,7 +902,7 @@ module Squared
902
902
 
903
903
  puts "#{g + f} #{key}: #{Array(data[key]).join(', ')}" unless data[key].to_s.empty?
904
904
  end
905
- w = 9 + flag.to_s.size + 4 + ee.size
905
+ w = 9 + flag.to_s.size + ARG[:TAB] + ee.size
906
906
  puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), theme[:inline])
907
907
  index += 1
908
908
  next unless confirm("#{h + b}?", no ? 'N' : 'Y')
@@ -334,7 +334,7 @@ module Squared
334
334
  subtasks({
335
335
  'branch' => %i[create track delete move copy list all current].freeze,
336
336
  'checkout' => %i[commit branch track detach path].freeze,
337
- 'commit' => %i[add all amend amend-orig fixup].freeze,
337
+ 'commit' => %i[add all pathspec amend amend-orig fixup].freeze,
338
338
  'diff' => %i[head branch files view between contain].freeze,
339
339
  'range-diff' => %i[view between contain].freeze,
340
340
  'fetch' => %i[origin remote all].freeze,
@@ -455,7 +455,7 @@ module Squared
455
455
  if flag == :add
456
456
  opts = param_guard(action, flag, args: args.to_a)
457
457
  elsif (refs = args.to_a).empty?
458
- refs = readline('Enter file patterns', force: true).shellsplit
458
+ refs = readline('Enter glob patterns', force: true).shellsplit
459
459
  end
460
460
  end
461
461
  commit(flag, opts, refs: refs, ref: ref, squash: squash, pick: pick)
@@ -1548,7 +1548,7 @@ module Squared
1548
1548
  fixup = flag == :fixup
1549
1549
  amend = flag.match?(/^amend/) && !fixup
1550
1550
  unless flag == :add || pick == 'reword'
1551
- pathspec = if flag == :all || ((fixup || amend) && refs.size == 1 && refs.first == '*')
1551
+ pathspec = if flag == :all || ((flag == :pathspec || fixup || amend) && refs.size == 1 && refs.first == '*')
1552
1552
  '--all'
1553
1553
  elsif (refs = projectmap(refs)).empty?
1554
1554
  raise 'no qualified pathspec'
@@ -11,7 +11,7 @@ module Squared
11
11
  install_a: %w[audit=! bin-links=! engine-strict=!? foreground-scripts=!? fund=! ignore-scripts=!?
12
12
  install-links=!? package-lock=! strict-peer-deps=!? include=b install-strategy=b omit=b].freeze,
13
13
  install_b: %w[no-save B|save-bundle D|save-dev O|save-optional save-peer P|save-prod g|global=!?
14
- S|save=!?].freeze,
14
+ min-release-age=i min-release-age-exclude=q S|save=!?].freeze,
15
15
  install_c: %w[allow-directory=b? allow-file=b? allow-git=b? allow-remote=b?].freeze,
16
16
  run: %w[foreground-scripts=!? if-present=!? ignore-scripts=!? script-shell=p].freeze,
17
17
  exec: %w[c|call=q package=b].freeze,
@@ -316,27 +316,40 @@ module Squared
316
316
  when 'package'
317
317
  case flag
318
318
  when :approve, :deny
319
- format_desc action, flag, 'name*|:,opts*'
319
+ format_desc(action, flag, 'opts*', before: flag == :approve ? 'name*|:' : 'name*|:|::')
320
320
  task flag do |_, args|
321
321
  args = args.to_a
322
- if args.first == ':'
322
+ if args.first == ':' || (all = args.first == '::')
323
323
  args.shift
324
+ list = []
325
+ pad = 0
326
+ size = ->(s) { pad = [pad, s.size].max }
324
327
  pwd_set do
325
- pad = 0
326
- list = IO.popen(npm_output('approve-scripts --allow-scripts-pending').to_s)
327
- .each_with_object([]) do |line, out|
328
- next unless line =~ /^\s+([a-z\d@][^@]*)@(\S+)/
329
-
330
- pad = [pad, $1.size].max
331
- out << [$1, $2]
332
- end
333
- .map { |name, ver| name.ljust(pad + 4) + ver }
334
- if list.empty?
335
- puts log_message('no packages to review', subject: name, hint: "#{flag}-scripts")
336
- exit 0
328
+ json = JSON.parse(`#{npm_output('install-scripts ls --json')}`)
329
+ json&.fetch('allowScripts', [])&.each do |data|
330
+ line = data['changes']&.find { |item| item['change'] == 'pending' }
331
+ next unless line && line['key'] =~ /^(.+)@([^@]+)$/
332
+
333
+ size.call($1)
334
+ list << [$1, $2]
335
+ end
336
+ if all
337
+ current = read_package 'allowScripts'
338
+ current&.each_pair do |key, val|
339
+ next unless val
340
+
341
+ md = key.match(/^(.+?)(?:@([^@]+))?$/)
342
+ size.call(md[1])
343
+ list << [md[1], sub_style(md[2] || 'any', theme[:inline])]
344
+ end
337
345
  end
338
- args.concat(choice_index('Select packages', list, multiple: true, column: /^(\S+)/))
339
346
  end
347
+ if list.empty?
348
+ puts log_message('no packages to review', subject: name, hint: "#{flag}-scripts")
349
+ exit 0
350
+ end
351
+ list.map! { |name, ver| name.ljust(pad + ARG[:TAB]) + ver }
352
+ args.concat(choice_index('Select packages', list, multiple: true, column: /^(\S+)/))
340
353
  end
341
354
  package flag, args
342
355
  end
@@ -709,7 +722,7 @@ module Squared
709
722
  append_platform
710
723
  end
711
724
  end
712
- cmd << '--package-lock=false' << 'save=false' if nolockfile?('npm')
725
+ cmd << '--package-lock=false' << '--save=false' if nolockfile?('npm')
713
726
  cmd << '--ignore-scripts' if option('ignore-scripts')
714
727
  end
715
728
  if add
@@ -835,9 +848,9 @@ module Squared
835
848
  end
836
849
  print_item banner unless sync
837
850
  if !found.empty?
838
- col1 = width.call(found, 0) + 4
839
- col2 = width.call(found, 1) + 4
840
- col3 = pad.call(found.size, found).size + 2 + col1 + col2 + width.call(found, 2)
851
+ col1 = width.call(found, 0) + ARG[:TAB]
852
+ col2 = width.call(found, 1) + ARG[:TAB]
853
+ col3 = pad.call(found.size, found).size + (ARG[:TAB] / 2) + col1 + col2 + width.call(found, 2)
841
854
  packages = []
842
855
  pat = ->(a) { /("#{Regexp.escape(a[0])}"\s*:\s*)"([~^])#{'?' if a[4]}#{Regexp.escape(a[1])}"/ }
843
856
  edit = lambda do |a, pkg, mod|
@@ -933,9 +946,9 @@ module Squared
933
946
  end
934
947
  end
935
948
  elsif !avail.empty?
936
- col1 = width.call(avail, 0) + 4
949
+ col1 = width.call(avail, 0) + ARG[:TAB]
937
950
  col2 = width.call(avail, 1)
938
- col3 = width.call(avail, 2) + 4
951
+ col3 = width.call(avail, 2) + ARG[:TAB]
939
952
  avail.each_with_index do |item, i|
940
953
  a, b, c, d = item
941
954
  a = a.ljust(col1)
@@ -79,12 +79,12 @@ module Squared
79
79
  OPT_MESON = {
80
80
  build: %w[D=q clearcache debug errorlogs fatal-meson-warnings pkgconfig.relocatable prefer-static
81
81
  python.allow-limited-api reconfigure stdsplit strip vsenv werror wipe auto-features=b backend=b
82
- bindir=p build.cmake-prefix-path=p build.pkg-config-path=p buildtype=b cmake-prefix-path=p
83
- cross-file=p datadir=p default-library=b default-both-libraries=b force-fallback-for=q genvslite=b
84
- includedir=p infodir=p install-umask=b layout=b libdir=p libexecdir=p licensedir=p localedir=p
85
- localstatedir=p mandir=p native-file=p optimization=b pkg-config-path=p prefix=p
86
- python.bytecompile=i python.platlibdir=p python.purelibdir=p python.install-env=b sbindir=p
87
- sharedstatedir=p sysconfdir=p unity=b unity-size=i warnlevel=b wrap-mode=b].freeze,
82
+ bindir=q build.cmake-prefix-path=p build.pkg-config-path=p buildtype=b cmake-prefix-path=p
83
+ cross-file=p datadir=q default-library=b default-both-libraries=b force-fallback-for=q genvslite=b
84
+ includedir=q infodir=q install-umask=b layout=b libdir=q libexecdir=q licensedir=q localedir=q
85
+ localstatedir=q mandir=q native-file=p optimization=b pkg-config-path=p prefix=p
86
+ python.bytecompile=b python.platlibdir=p python.purelibdir=p python.install-env=b sbindir=q
87
+ sharedstatedir=q sysconfdir=q unity=b unity-size=i warnlevel=b wrap-mode=b].freeze,
88
88
  compile: %w[clean v|verbose j|jobs=i l|load-average=b ninja-args=q vs-args=q xcode-args=q].freeze
89
89
  }.freeze
90
90
  PASS_PYTHON = {
@@ -276,7 +276,7 @@ module Squared
276
276
  args = args.to_a
277
277
  if args.empty?
278
278
  args = readline('Enter command', force: true).split(' ', 2)
279
- elsif args.size == 1 && option('interactive', notequals: '0', prefix: ref)
279
+ elsif args.size == 1 && option('interactive', notequals: '0', prefix: 'python')
280
280
  args << readline('Enter arguments', force: false) unless args.first.include?(' ')
281
281
  end
282
282
  venv_init
@@ -346,18 +346,18 @@ module Squared
346
346
  case flag
347
347
  when :upgrade
348
348
  task flag, [:strategy] do |_, args|
349
- install flag, (case args.strategy
350
- when 'eager'
351
- 'eager'
352
- when /^only-if|needed$/
353
- 'only-if-needed'
354
- end.yield_self do |val|
355
- if val
356
- args.extras << "upgrade-strategy=#{val}"
357
- else
358
- args.to_a
359
- end
360
- end)
349
+ val = case args.strategy
350
+ when 'eager'
351
+ 'eager'
352
+ when /^only-if/, /needed$/
353
+ 'only-if-needed'
354
+ end
355
+ args = if val
356
+ args.extras << "upgrade-strategy=#{val}"
357
+ else
358
+ args.to_a
359
+ end
360
+ install flag, args
361
361
  end
362
362
  when :requirement, :target
363
363
  task flag, [:path] do |_, args|
@@ -738,7 +738,7 @@ module Squared
738
738
  op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_PYTHON[:common],
739
739
  session('python', path: !venv?),
740
740
  project: self, strict: strict?, multiple: [/^-c/], single: singleopt(:python),
741
- args: true, stdin: true)
741
+ sep: ' ', args: true, stdin: true)
742
742
  op.concat(args)
743
743
  if op.include?('-')
744
744
  op.exist?(add: true)
@@ -937,7 +937,8 @@ module Squared
937
937
  pre = preopts(quiet: quiet)
938
938
  return session(name, *pre, *cmd, path: !venv?) unless opts
939
939
 
940
- op = OptionPartition.new(opts, common, project: self, strict: strict?, single: singleopt(name.to_sym))
940
+ op = OptionPartition.new(opts, common, project: self, strict: strict?, sep: name == 'python' ? ' ' : '=',
941
+ single: singleopt(name.to_sym))
941
942
  [session(name, *pre, *op.to_a, *cmd, path: !venv?), op.extras]
942
943
  end
943
944
 
@@ -226,9 +226,10 @@ module Squared
226
226
  serve_set kwargs[:serve]
227
227
  gemfile_set kwargs[:gemspec]
228
228
  self.autodetect = autodetect
229
- @bundle = { exec: exec.is_a?(String) ? basepath!(exec) : false }
229
+ @bundle = { exec: exec }
230
230
  @steepfile = basepath! steep if steep
231
- @rubocopfile = Pathname.new(rubocop).realpath rescue basepath!(Dir.home, '.rubocop.yml') if rubocop
231
+ rubocop = rootpath('.rubocop.yml', ascend: Dir.home) if rubocop == true
232
+ @rubocopfile = basepath! rubocop if rubocop
232
233
  @rubygems = kwargs.fetch(:rubygems, 0)
233
234
  return unless rakefile && @output[0].nil? && @copy.nil? && !version && !self.autodetect
234
235
 
@@ -945,7 +946,7 @@ module Squared
945
946
  end
946
947
  s = '%2d. %s' % [start, line]
947
948
  if ia
948
- unless confirm_semver(s.ljust(col + 4 + line.size - n), type)
949
+ unless confirm_semver(s.ljust(col + ARG[:TAB] + line.size - n), type)
949
950
  start += 1
950
951
  next
951
952
  end
@@ -1563,7 +1564,7 @@ module Squared
1563
1564
 
1564
1565
  def rdbg(*args, banner: verbose?, with: nil, pass: PASS_RUBY[:rdbg], **kwargs)
1565
1566
  opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
1566
- cmd = session 'rdbg'
1567
+ cmd = session(*bundle_args('rdbg'))
1567
1568
  args.each_with_index do |val, index|
1568
1569
  break if val == '--'
1569
1570
  next unless exist?(val, type: 'f')
@@ -1846,7 +1847,7 @@ module Squared
1846
1847
  end
1847
1848
 
1848
1849
  def ruby_session(*cmd, **kwargs)
1849
- session('ruby', *preopts, *cmd, **kwargs)
1850
+ session(*bundle_args('ruby'), *preopts, *cmd, **kwargs)
1850
1851
  end
1851
1852
 
1852
1853
  def gem_session(*cmd, **kwargs)
@@ -1864,11 +1865,10 @@ module Squared
1864
1865
  end
1865
1866
 
1866
1867
  def rbs_session(*cmd, opts: nil)
1867
- args = bundle_args 'rbs'
1868
- return session(*args, *cmd) unless opts
1868
+ return session(*bundle_args('rbs'), *cmd) unless opts
1869
1869
 
1870
1870
  op = OptionPartition.new(opts, OPT_RUBY[:rbs], project: self, strict: strict?)
1871
- [session(*args, *op.to_a, *cmd), op.extras]
1871
+ [session(*bundle_args('rbs'), *op.to_a, *cmd), op.extras]
1872
1872
  end
1873
1873
 
1874
1874
  def gem_output(*cmd, **kwargs)
@@ -1876,7 +1876,7 @@ module Squared
1876
1876
  end
1877
1877
 
1878
1878
  def ruby_output(*cmd, **kwargs)
1879
- session_output('ruby', *cmd, **kwargs)
1879
+ session_output(*bundle_args('ruby'), *cmd, **kwargs)
1880
1880
  end
1881
1881
 
1882
1882
  def bundle_output(*cmd, **kwargs)
@@ -1888,11 +1888,20 @@ module Squared
1888
1888
  end
1889
1889
 
1890
1890
  def bundle_args(*args)
1891
- if (val = @bundle[:exec])
1892
- args.unshift(quote_option('gemfile', val)) unless val == true
1893
- args.unshift('bundle', 'exec')
1891
+ return args unless (val = @bundle[:exec])
1892
+
1893
+ app = args.first
1894
+ if val.is_a?(Hash)
1895
+ val = val[app.to_s] || val[app.to_sym]
1896
+ elsif app == 'ruby'
1897
+ return args
1898
+ end
1899
+ case val
1900
+ when String, Pathname
1901
+ val = basepath!(val, type: 'f')
1902
+ args.unshift("--gemfile=#{shell_escape(val.relative_path_from(path), quote: true)}") if val
1894
1903
  end
1895
- args
1904
+ val ? args.unshift('bundle', 'exec') : args
1896
1905
  end
1897
1906
 
1898
1907
  def bundle_load
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.13
4
+ version: 0.7.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham