squared 0.1.1 → 0.1.2

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: e2fd23c5964fe7c987966b8d237b569883b2dae5b70d9c120a924e2cc0227873
4
- data.tar.gz: 8ef09d80e13c53fda678aa6a7194e33abf04728fb9d1c17739a5dc6c814e3b03
3
+ metadata.gz: 5fb2101a0fb0c5a8f651bf471b44a5dc3be21c3b87d6e53f708d752b6e8c8ffd
4
+ data.tar.gz: eb322ca0cab89e5f41f719e06e182120efd96280f88a5f2625f3954331500a19
5
5
  SHA512:
6
- metadata.gz: c41b98512dfc370a056716c3af2a599321b6113fa4883ab1f9c6b1418332f6b973560ce2cb1550c3813521eaa326150371ef3e60906cb694d6a6fd41ac1e0f05
7
- data.tar.gz: cedbdcb188a6fb4a8407fc36836ffbeb4b93893217cec168d291845ce9a4f3f4dede9936022b8c950efa48ec21e2f93d013dc7e6fa929397ac80df7d6e3b099a
6
+ metadata.gz: a6947106acb6d33789f3ae79a84e87c3119b799f556a8570920904338b3955b795578f392860fce83260af5b1c17159ba4c64e9f4eeeaed6b5886e06dfe12a06
7
+ data.tar.gz: dd9416a0457a2ead233f32c9592b2061e569161d54482d4ab949fd7acb6ceb6139c26329a4fdb6ea1853ab6f840ab145e17f4b58a386bd68eb066c14ea3f85cd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.2] - 2024-12-23
4
+
5
+ ### Added
6
+
7
+ - Git command tag was implemented.
8
+
9
+ ### Deprecated
10
+
11
+ - Repo static method empty? was relocated into Application.
12
+
13
+ ### Fixed
14
+
15
+ - Namespace prefix was sometimes missing or duplicated.
16
+ - Silent operation used undefined variable.
17
+ - Unnecessary shell option escapes were removed.
18
+ - Ruby command outdated did not display in order when threaded.
19
+ - Regexp uses \A|\z format and not ^|$ for standard matches.
20
+ - Rake being called by a project did not escape options.
21
+ - Workspace did not check base project for Windows filename.
22
+ - Regexp for SemVer did not recognize package names.
23
+
3
24
  ## [0.1.1] - 2024-12-14
4
25
 
5
26
  ### Added
@@ -50,6 +71,7 @@
50
71
 
51
72
  - Changelog was created.
52
73
 
74
+ [0.1.2]: https://github.com/anpham6/squared/releases/tag/v0.1.2-ruby
53
75
  [0.1.1]: https://github.com/anpham6/squared/releases/tag/v0.1.1-ruby
54
76
  [0.1.0]: https://github.com/anpham6/squared/releases/tag/v0.1.0-ruby
55
77
  [0.0.12]: https://github.com/anpham6/squared/releases/tag/v0.0.12-ruby
data/README.ruby.md CHANGED
@@ -37,17 +37,23 @@ Projects from any accessible folder can be added relative to the parent director
37
37
  require "squared"
38
38
 
39
39
  require "squared/workspace"
40
- require "squared/workspace/repo" # Optional
41
- require "squared/workspace/project/node" #
42
- require "squared/workspace/project/python" #
43
- require "squared/workspace/project/ruby" #
40
+ require "squared/workspace/repo" # Optional
41
+ require "squared/workspace/project/node" #
42
+ require "squared/workspace/project/python" #
43
+ require "squared/workspace/project/ruby" #
44
44
  # OR
45
- require "squared/app" # All workspace related modules
45
+ require "squared/app" # All workspace related modules
46
46
 
47
47
  # NODE_ENV = production
48
- # REPO_ROOT = /workspaces
49
- # REPO_HOME = /workspaces/squared
50
- # rake = /workspaces/squared/Rakefile
48
+
49
+ # REPO_ROOT = /workspaces #
50
+ # REPO_HOME = /workspaces/squared # Dir.pwd
51
+ # rake = /workspaces/squared/Rakefile # main?
52
+ # OR
53
+ # REPO_ROOT = /workspaces # Dir.pwd
54
+ # rake = /workspaces/Rakefile #
55
+ # REPO_HOME = /workspaces/squared # main: "squared"
56
+
51
57
  # pathname = /workspaces/pathname
52
58
  # optparse = /workspaces/optparse
53
59
  # log = /workspaces/logger
@@ -9,7 +9,7 @@ module Squared
9
9
  extend Forwardable
10
10
 
11
11
  def self.to_s
12
- super.match(/[^:]+$/)[0]
12
+ super.match(/[^:]+\z/)[0]
13
13
  end
14
14
 
15
15
  def_delegators :@data, :+, :each, :each_with_index, :entries, :to_a, :include?
@@ -31,7 +31,7 @@ module Squared
31
31
 
32
32
  class JoinSet < Set
33
33
  def self.to_s
34
- super.match(/[^:]+$/)[0]
34
+ super.match(/[^:]+\z/)[0]
35
35
  end
36
36
 
37
37
  def initialize(data = [], delim: ' ')
@@ -46,7 +46,7 @@ module Squared
46
46
  if pat && index != 0
47
47
  return val unless (data = pat.match(val))
48
48
 
49
- ret = index == -1 ? data.to_a[1..-1] : data[index]
49
+ ret = index == -1 ? data.to_a.drop(1) : data[index]
50
50
  else
51
51
  ret = val
52
52
  index = 0
@@ -170,7 +170,7 @@ module Squared
170
170
  args = args.map(&:to_s)
171
171
  if args.size > 1
172
172
  title = log_title(level, color: false)
173
- sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
173
+ sub = { pat: /\A(#{title})(.+)\z/m, styles: __get__(:theme)[:logger][log_sym(level)] } if color
174
174
  emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub)
175
175
  else
176
176
  msg = [log_title(level, color: color)]
@@ -235,8 +235,8 @@ module Squared
235
235
  sub.each { |h| s = sub_style(s, **h) }
236
236
  s = "| #{s} |"
237
237
  if border
238
- s = sub_style(s, pat: /^(\|)(.+)$/m, styles: border)
239
- s = sub_style(s, pat: /^(.+)(\|)$/m, styles: border, index: 2)
238
+ s = sub_style(s, pat: /\A(\|)(.+)\z/m, styles: border)
239
+ s = sub_style(s, pat: /\A(.+)(\|)\z/m, styles: border, index: 2)
240
240
  end
241
241
  s
242
242
  end
@@ -8,8 +8,8 @@ module Squared
8
8
  def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
9
9
  require 'readline'
10
10
  require 'timeout'
11
- agree = /^#{agree}$/i if agree.is_a?(::String)
12
- cancel = /^#{cancel}$/i if cancel.is_a?(::String)
11
+ agree = /\A#{agree}\z/i if agree.is_a?(::String)
12
+ cancel = /\A#{cancel}\z/i if cancel.is_a?(::String)
13
13
  Timeout.timeout(timeout) do
14
14
  begin
15
15
  while (ch = Readline.readline(msg, true))
@@ -8,38 +8,51 @@ module Squared
8
8
  module Shell
9
9
  module_function
10
10
 
11
- def shell_escape(val, quote: false)
12
- val = val.to_s
13
- return ::Shellwords.escape(val) unless ::Rake::Win32.windows?
11
+ def shell_escape(val, quote: false, force: false)
12
+ if (data = /\A(--?[^= ]+)((=|\s+)(["'])?(.+?)(["'])?)?\z/m.match(val = val.to_s))
13
+ return val unless data[2]
14
14
 
15
- quote ? shell_quote(val, force: false) : val
15
+ join = ->(opt) { data[1] + data[3] + shell_quote(opt) }
16
+ if data[4] == data[6]
17
+ data[4] ? val : join.(data[5])
18
+ else
19
+ join.("#{data[4]}#{data[5]}#{data[6]}")
20
+ end
21
+ elsif Rake::Win32.windows?
22
+ quote ? shell_quote(val, force: force) : val
23
+ else
24
+ Shellwords.escape(val)
25
+ end
16
26
  end
17
27
 
18
28
  def shell_quote(val, force: true)
19
- ret = val.to_s.strip
20
- return ret if (!force && !ret.include?(' ')) || ret =~ /(?:^|\S=|[^=]\s+)(["']).+\1$/m
29
+ val = val.to_s
30
+ return val if (!force && !val.include?(' ')) || val =~ /(?:^|\S=|[^=]\s+)(["']).+\1\z/m
21
31
 
22
- ::Rake::Win32.windows? ? "\"#{double_quote(ret)}\"" : "'#{single_quote(ret)}'"
32
+ Rake::Win32.windows? ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
23
33
  end
24
34
 
25
- def shell_split(val, quote: false, join: false)
26
- ret = ::Shellwords.split(val).map do |opt|
27
- if (data = /^(--?[^= ]+)(=|\s+)?(["'])?(.+?)\3?$/m.match(opt))
28
- next opt unless data[2] && !data[3]
35
+ def shell_split(val, quote: false, join: nil)
36
+ val = Shellwords.split(val).map { |opt| shell_escape(opt, quote: quote) }
37
+ return val unless join
29
38
 
30
- data[1] + data[2] + shell_quote(data[4], force: !::Rake::Win32.windows?)
31
- else
32
- shell_escape(opt, quote: quote)
33
- end
34
- end
35
- join ? ret.join(' ') : ret
39
+ val.join(join.is_a?(::String) ? join : ' ')
40
+ end
41
+
42
+ def shell_option(flag, val = nil, quote: false, escape: true)
43
+ "--#{flag}#{if val
44
+ "=#{if escape
45
+ shell_escape(val, quote: quote)
46
+ else
47
+ quote ? shell_quote(val) : val
48
+ end}"
49
+ end}"
36
50
  end
37
51
 
38
52
  def fill_option(val)
39
- return "-#{val}" if val.size == 1 || val =~ /^[a-z]\d+$/i
53
+ return "-#{val}" if val.size == 1 || val =~ /\A[a-z]\d+\z/i
40
54
 
41
- val = "--#{val}" unless val.start_with?('-')
42
- shell_escape(val).sub('\\=', '=')
55
+ shell_escape(val.start_with?('-') ? val : "--#{val}")
43
56
  end
44
57
 
45
58
  def single_quote(val)
@@ -9,7 +9,7 @@ module Squared
9
9
  module_function
10
10
 
11
11
  def shell(*args, **kwargs)
12
- if RUBY_VERSION =~ /^2\.[0-5]\./
12
+ if RUBY_VERSION < '2.6'
13
13
  exception = kwargs.delete(:exception)
14
14
  ret = system(*args, **kwargs)
15
15
  return ret if ret || !exception
@@ -12,7 +12,7 @@ module Squared
12
12
  include Rake::DSL
13
13
 
14
14
  def self.to_s
15
- super.match(/[^:]+$/)[0]
15
+ super.match(/[^:]+\z/)[0]
16
16
  end
17
17
 
18
18
  attr_reader :main, :name, :project, :theme
@@ -199,17 +199,18 @@ module Squared
199
199
  title = Pathname.new(file)
200
200
  .realpath
201
201
  .to_s
202
- .sub(Regexp.new("^#{Regexp.escape(File.join(Dir.pwd, ''))}"), '')
202
+ .sub(Regexp.new("\\A#{Regexp.escape(File.join(Dir.pwd, ''))}"), '')
203
203
  emphasize(lines, title: title, sub: unless stdin?
204
204
  [
205
- { pat: /^((?:[^:]|(?<! ):(?! ))+)$/, styles: theme[:banner] },
206
- { pat: /^(.*?)(<[^>]+>)(.+)$/m, styles: theme[:undefined], index: 2 },
207
- { pat: /^(.+)( : (?!undefined).+)$/m, styles: theme[:key] },
208
- { pat: /^(.+ : )(-?[\d.]+)(\s*)$/m, styles: theme[:number], index: 2 },
209
- { pat: /^(.+ : ")(.+)("\s*)$/m, styles: theme[:string], index: 2 },
210
- { pat: /^(.+ : \{)(.+)(\}\s*)$/m, styles: theme[:hash], index: 2 },
211
- { pat: /^(.+ : \[)(.+)(\]\s*)$/m, styles: theme[:array], index: 2 },
212
- { pat: /^(.+ : (?!undefined))([^"\[{].*)$/m, styles: theme[:value],
205
+ { pat: /\A((?:[^:]|(?<! ):(?! ))+)\z/, styles: theme[:banner] },
206
+ { pat: /\A(.*?)(<[^>]+>)(.+)\z/m, styles: theme[:undefined], index: 2 },
207
+ { pat: /\A(.+)( : (?!undefined).+)\z/m, styles: theme[:key] },
208
+ { pat: /\A(.+ : )(-?[\d.]+)(\s*)\z/m, styles: theme[:number],
209
+ index: 2 },
210
+ { pat: /\A(.+ : ")(.+)("\s*)\z/m, styles: theme[:string], index: 2 },
211
+ { pat: /\A(.+ : \{)(.+)(\}\s*)\z/m, styles: theme[:hash], index: 2 },
212
+ { pat: /\A(.+ : \[)(.+)(\]\s*)\z/m, styles: theme[:array], index: 2 },
213
+ { pat: /\A(.+ : (?!undefined))([^"\[{].*)\z/m, styles: theme[:value],
213
214
  index: 2 }
214
215
  ]
215
216
  end)
@@ -261,6 +262,8 @@ module Squared
261
262
  end
262
263
 
263
264
  def format_desc(command, *ext, exist: exist?)
265
+ return unless Rake::TaskManager.record_task_metadata
266
+
264
267
  val = "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys+]"
265
268
  message(@prefix, *name.split(':'), command, val, empty: true)
266
269
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
@@ -56,7 +56,7 @@ module Squared
56
56
  end
57
57
 
58
58
  def to_s
59
- super.match(/[^:]+$/)[0]
59
+ super.match(/[^:]+\z/)[0]
60
60
  end
61
61
 
62
62
  attr_reader :kind_project
@@ -70,8 +70,14 @@ module Squared
70
70
  def initialize(home = Dir.pwd, *, main: nil, prefix: nil,
71
71
  verbose: ARG[:VERBOSE], common: ARG[:COMMON], pipe: ARG[:PIPE], exception: ARG[:FAIL], **)
72
72
  @home = Pathname.new(home).realdirpath
73
+ basename = @home.basename.to_s
74
+ if main
75
+ @main = main.to_s.freeze
76
+ @home = @home.join(@main) unless @main == basename || (windows? && @main.downcase == basename.downcase)
77
+ else
78
+ @main = basename.freeze
79
+ end
73
80
  @root = @home.parent
74
- @main = (main || @home.basename).to_s.freeze
75
81
  @prefix = prefix
76
82
  @series = Application.impl_series.new(self)
77
83
  @project = {}
@@ -322,7 +328,7 @@ module Squared
322
328
 
323
329
  def task_name(val, desc: false)
324
330
  ret = @prefix ? task_join(@prefix, val) : val.to_s
325
- desc ? ret.split(':').join(ARG[:SPACE]) : ret
331
+ desc ? message(*ret.split(':')) : ret
326
332
  end
327
333
 
328
334
  def task_namespace(val, first: false)
@@ -383,7 +389,7 @@ module Squared
383
389
 
384
390
  return ret
385
391
  end
386
- @script[:ref!][:_] || SCRIPT_OBJ
392
+ @script[:ref!][:''] || SCRIPT_OBJ
387
393
  end
388
394
 
389
395
  def script_get(*args, group: nil, ref: nil)
@@ -409,7 +415,7 @@ module Squared
409
415
  return ret if group && (ret = @banner[:group][group.to_sym])
410
416
 
411
417
  ref.reverse_each { |val| return ret if (ret = @banner[:ref][val]) }
412
- @banner[:ref][:_]
418
+ @banner[:ref][:'']
413
419
  end
414
420
 
415
421
  def enabled?
@@ -444,6 +450,10 @@ module Squared
444
450
  !(proj = find(home)).nil? && proj.enabled?
445
451
  end
446
452
 
453
+ def windows?
454
+ Rake::Win32.windows?
455
+ end
456
+
447
457
  def rootpath(*args)
448
458
  root.join(*args)
449
459
  end
@@ -505,7 +515,21 @@ module Squared
505
515
  elsif ref
506
516
  as_a(ref).each { |val| @script[:ref!][val.to_sym] = data }
507
517
  else
508
- @script[:ref!][:_] = data
518
+ @script[:ref!][:''] = data
519
+ end
520
+ end
521
+
522
+ def root?(path, pass: [])
523
+ return false unless path.directory?
524
+
525
+ case path.children.size
526
+ when 0
527
+ true
528
+ when 1
529
+ target = path.children.first
530
+ target.to_s == __FILE__ || pass.any? { |val| val == target.basename.to_s }
531
+ else
532
+ false
509
533
  end
510
534
  end
511
535
 
@@ -15,7 +15,7 @@ module Squared
15
15
  include Rake::DSL
16
16
 
17
17
  VAR_SET = %i[parent global envname dependfile theme run script env].freeze
18
- SEM_VER = /(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?/.freeze
18
+ SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
19
19
  private_constant :VAR_SET, :SEM_VER
20
20
 
21
21
  class << self
@@ -46,7 +46,7 @@ module Squared
46
46
  end
47
47
 
48
48
  def to_s
49
- super.match(/[^:]+$/)[0]
49
+ super.match(/[^:]+\z/)[0]
50
50
  end
51
51
  end
52
52
 
@@ -264,9 +264,9 @@ module Squared
264
264
  val
265
265
  end
266
266
  emphasize(out, title: path, right: true, border: borderstyle, sub: [
267
- { pat: /^(#{Regexp.escape(path.to_s)})(.*)$/, styles: theme[:header] },
268
- { pat: /^(#{Regexp.escape(name)})(.*)$/, styles: theme[:active] },
269
- { pat: /^(.+ )(\()(\d+)(\))(.*)$/, styles: theme[:inline], index: 3 }
267
+ { pat: /\A(#{Regexp.escape(path.to_s)})(.*)\z/, styles: theme[:header] },
268
+ { pat: /\A(#{Regexp.escape(name)})(.*)\z/, styles: theme[:active] },
269
+ { pat: /\A(.+ )(\()(\d+)(\))(.*)\z/, styles: theme[:inline], index: 3 }
270
270
  ])
271
271
  end
272
272
  end
@@ -550,7 +550,7 @@ module Squared
550
550
  cmd = session_done(cmd)
551
551
  log.info cmd
552
552
  begin
553
- if cmd =~ /^[^:]+:[^:]/ && workspace.task_defined?(cmd)
553
+ if cmd =~ /\A[^:]+:[^:]/ && workspace.task_defined?(cmd)
554
554
  log.warn "ENV was discarded: #{var}" if var
555
555
  task_invoke(cmd, exception: exception, warning: warning?)
556
556
  else
@@ -749,6 +749,8 @@ module Squared
749
749
  end
750
750
 
751
751
  def format_desc(action, flag, opts = nil, req: nil, arg: 'opts*')
752
+ return unless Rake::TaskManager.record_task_metadata
753
+
752
754
  opts = "#{arg}=#{opts.join(',')}" if opts.is_a?(Array)
753
755
  out = [@desc]
754
756
  if flag
@@ -771,7 +773,7 @@ module Squared
771
773
  end
772
774
  if verbose
773
775
  out = []
774
- out << cmd.sub(/^\S+/, &:upcase) if data[:command]
776
+ out << cmd.sub(/\A\S+/, &:upcase) if data[:command]
775
777
  data[:order].each do |val|
776
778
  if val.is_a?(Array)
777
779
  s = ' '
@@ -793,7 +795,7 @@ module Squared
793
795
  out << val.to_s
794
796
  end
795
797
  print_banner(*out, styles: data[:styles], border: data[:border], client: client)
796
- elsif multiple && workspace.series.multiple?
798
+ elsif workspace.series.multiple?
797
799
  "## #{__send__(data[:order].first || :path)} ##"
798
800
  end
799
801
  end
@@ -818,10 +820,10 @@ module Squared
818
820
  end
819
821
  if from
820
822
  out << from
821
- pat = /^(#{Regexp.escape(out.last)})(.*)$/
823
+ pat = /\A(#{Regexp.escape(out.last)})(.*)\z/m
822
824
  end
823
825
  else
824
- pat = /^(\s*\d+\.)(.+)$/
826
+ pat = /\A(\s*\d+\.)(.+)\z/m
825
827
  end
826
828
  sub = [headerstyle]
827
829
  sub << { pat: pat, styles: theme[:active] } if pat
@@ -833,16 +835,32 @@ module Squared
833
835
  end
834
836
 
835
837
  def append_repeat(flag, opts)
836
- opts.each { |val| @session << "--#{flag}=#{shell_escape(val, quote: true)}" }
838
+ opts.each { |val| @session << shell_option(flag, val, quote: true) }
837
839
  end
838
840
 
839
- def append_value(opts, delim: false)
841
+ def append_value(opts, delim: false, escape: true)
840
842
  @session << '--' if delim && !opts.empty?
841
- opts.each { |val| @session << shell_escape(val) }
843
+ opts.each { |val| @session << (escape ? shell_escape(val) : shell_quote(val)) }
842
844
  end
843
845
 
844
- def append_option(list, **kwargs)
845
- list.each { |val| @session << "--#{val}" if option(val, **kwargs) }
846
+ def append_first(list, flag: true, equals: false, quote: false, **kwargs)
847
+ list.each do |opt|
848
+ next unless (val = option(opt, **kwargs))
849
+
850
+ return @session << (if flag
851
+ shell_option(opt, equals ? val : nil, quote: quote)
852
+ else
853
+ shell_quote(val)
854
+ end)
855
+ end
856
+ end
857
+
858
+ def append_option(list, equals: false, quote: false, **kwargs)
859
+ list.each do |flag|
860
+ next unless (val = option(flag, **kwargs))
861
+
862
+ @session << shell_option(flag, equals ? val : nil, quote: quote)
863
+ end
846
864
  end
847
865
 
848
866
  def append_nocolor(flag = nil)
@@ -1014,7 +1032,7 @@ module Squared
1014
1032
  end
1015
1033
 
1016
1034
  def headerstyle
1017
- { pat: /^(\S+)(\s+)$/, styles: theme[:header] }
1035
+ { pat: /\A(\S+)(\s+)\z/, styles: theme[:header] }
1018
1036
  end
1019
1037
 
1020
1038
  def scriptargs
@@ -4,8 +4,8 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Git < Base
7
- OPT_PULL = %w[all ff-only autostash prune tags depth=n since=d jobs=n dry-run].freeze
8
- OPT_FETCH = %w[prune-tags].concat(OPT_PULL[3..-1]).freeze
7
+ OPT_FETCH = %w[all tags prune append atomic unshallow dry-run depth=i deepen=i since=d jobs=i].freeze
8
+ OPT_PULL = %w[ff ff-only edit autostash squash verify <fetch].freeze
9
9
  private_constant :OPT_PULL, :OPT_FETCH
10
10
 
11
11
  class << self
@@ -17,7 +17,7 @@ module Squared
17
17
  namespace(name = ws.task_name('git')) do
18
18
  all = ws.task_join(name, 'all')
19
19
 
20
- desc ws.task_name("#{all}[git?=rebase|stash,depend?]", desc: true)
20
+ desc Common::Format.message(*"#{all}[git?=rebase|stash,depend?]".split(':'))
21
21
  task 'all', [:git, :depend] do |_, args|
22
22
  cmd = case args.git
23
23
  when 'rebase'
@@ -63,7 +63,8 @@ module Squared
63
63
  reset: %i[head soft mixed hard merge keep submodules].freeze,
64
64
  restore: %i[worktree staged overlay].freeze,
65
65
  rev: %i[commit branch].freeze,
66
- show: %i[oneline pretty format].freeze
66
+ show: %i[oneline pretty format].freeze,
67
+ tag: %i[add delete list merged].freeze
67
68
  }.freeze
68
69
 
69
70
  def initialize(*, **)
@@ -85,7 +86,7 @@ module Squared
85
86
  flags.each do |flag|
86
87
  case action
87
88
  when :pull, :fetch
88
- desc format_desc(action, flag, flag == :pull ? OPT_PULL : OPT_FETCH)
89
+ desc format_desc(action, flag, action == :pull ? OPT_PULL : OPT_FETCH)
89
90
  task flag, [:opts] do |_, args|
90
91
  __send__(action, flag, opts: args.to_a)
91
92
  end
@@ -102,6 +103,32 @@ module Squared
102
103
  __send__(action, flag, files)
103
104
  end
104
105
  end
106
+ when :tag
107
+ case flag
108
+ when :list
109
+ desc format_desc(action, flag, 'pattern*')
110
+ task flag, [:pattern] do |_, args|
111
+ tag(flag, args.to_a)
112
+ end
113
+ when :merged
114
+ desc format_desc(action, flag, 'commit,pattern*')
115
+ task flag, [:commit, :pattern] do |_, args|
116
+ commit = guard_params(action, flag, args: args, key: :commit)
117
+ tag(flag, args.to_a.drop(1), commit: commit)
118
+ end
119
+ when :delete
120
+ desc format_desc(action, flag, 'name+')
121
+ task flag, [:name] do |_, args|
122
+ name = guard_params(action, flag, args: args.to_a)
123
+ tag(flag, name)
124
+ end
125
+ else
126
+ desc format_desc(action, flag, 'name,message?,commit?')
127
+ task flag, [:name, :message, :commit] do |_, args|
128
+ name = guard_params(action, flag, args: args, key: :name)
129
+ tag(flag, [name], message: args.message, commit: args.commit)
130
+ end
131
+ end
105
132
  when :stash
106
133
  if flag == :push
107
134
  desc format_desc(action, flag, 'pathspec*')
@@ -130,7 +157,7 @@ module Squared
130
157
  desc format_desc(action, flag, 'index?=0,pathspec*')
131
158
  task flag, [:pathspec] do |_, args|
132
159
  files = args.to_a
133
- diff(flag, files, index: /^\d+$/.match?(files[0]) && !option('index') ? files.shift.to_i : 0)
160
+ diff(flag, files, index: /\A\d+\z/.match?(files[0]) && !option('index') ? files.shift.to_i : 0)
134
161
  end
135
162
  when :cached
136
163
  desc format_desc(action, flag, 'pathspec*')
@@ -139,9 +166,9 @@ module Squared
139
166
  end
140
167
  when :branch
141
168
  desc format_desc(action, flag, 'name,pathspec*')
142
- task flag, [:name, :pathspec] do |_, args|
169
+ task flag, [:name] do |_, args|
143
170
  branch = guard_params(action, flag, args: args, key: :name)
144
- diff(flag, args.to_a[1..-1] || [], branch: branch)
171
+ diff(flag, args.to_a.drop(1), branch: branch)
145
172
  end
146
173
  when :files
147
174
  desc format_desc(action, flag, 'path1,path2')
@@ -173,7 +200,7 @@ module Squared
173
200
  detach = args.detach
174
201
  commit = args.commit
175
202
  end
176
- guard_params(action, flag, args: { create: create }, key: :create, pat: /^b$/i) if create
203
+ guard_params(action, flag, args: { create: create }, key: :create, pat: /\Ab\z/i) if create
177
204
  checkout(flag, branch: branch, create: create, commit: commit, detach: detach)
178
205
  end
179
206
  when :detach
@@ -191,7 +218,7 @@ module Squared
191
218
  if flag == :head
192
219
  desc format_desc(action, flag, 'ref,pathspec+')
193
220
  task flag, [:ref, :pathspec] do |_, args|
194
- files = guard_params(action, flag, args: args.to_a[1..-1] || [])
221
+ files = guard_params(action, flag, args: args.to_a.drop(1))
195
222
  reset(flag, files, ref: args.ref)
196
223
  end
197
224
  else
@@ -204,15 +231,12 @@ module Squared
204
231
  if flag == :oneline
205
232
  desc format_desc(action, flag, 'object*')
206
233
  task flag, [:object] do |_, args|
207
- objs = args.to_a
208
- show(objs, pretty: 'oneline', abbrev: true)
234
+ show(args.to_a, pretty: 'oneline', abbrev: true)
209
235
  end
210
236
  else
211
237
  desc format_desc(action, flag, 'format,object*')
212
238
  task flag, [:format, :object] do |_, args|
213
- format = guard_params(action, flag, args: args, key: :format)
214
- objs = args.to_a[1..-1] || []
215
- show(objs, "#{flag}": format)
239
+ show(args.to_a.drop(1), "#{flag}": args.format)
216
240
  end
217
241
  end
218
242
  end
@@ -237,8 +261,8 @@ module Squared
237
261
  append_pull opts, OPT_PULL, flag
238
262
  sub = if verbose
239
263
  [
240
- { pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
241
- { pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: :green, index: 3 }
264
+ { pat: /\A(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)\z/, styles: :red, index: 4 },
265
+ { pat: /\A(.+)(\|\s+\d+\s+)(\++)(-*)(.*)\z/, styles: :green, index: 3 }
242
266
  ]
243
267
  end
244
268
  source(sync: sync, sub: sub, **threadargs)
@@ -272,16 +296,16 @@ module Squared
272
296
  def status
273
297
  cmd = git_session 'status', option('long') ? '--long' : '--short'
274
298
  if (val = option('ignore-submodules', ignore: false))
275
- cmd << "--ignore-submodules=#{case val
276
- when '0', 'none'
277
- 'none'
278
- when '1', 'untracked'
279
- 'untracked'
280
- when '2', 'dirty'
281
- 'dirty'
282
- else
283
- 'all'
284
- end}"
299
+ cmd << shell_option('ignore-submodules', case val
300
+ when '0', 'none'
301
+ 'none'
302
+ when '1', 'untracked'
303
+ 'untracked'
304
+ when '2', 'dirty'
305
+ 'dirty'
306
+ else
307
+ 'all'
308
+ end, escape: false)
285
309
  end
286
310
  append_pathspec
287
311
  out, banner = source(io: true)
@@ -291,10 +315,10 @@ module Squared
291
315
  end
292
316
  ret = write_lines(out, banner: banner, sub: if verbose
293
317
  [
294
- { pat: /^(.)([A-Z])(.+)$/, styles: :red, index: 2 },
295
- { pat: /^([A-Z])(.+)$/, styles: :green },
296
- { pat: /^(\?\?)(.+)$/, styles: :red },
297
- { pat: /^(## )(.+)(\.{3})(.+)$/,
318
+ { pat: /\A(.)([A-Z])(.+)\z/, styles: :red, index: 2 },
319
+ { pat: /\A([A-Z])(.+)\z/, styles: :green },
320
+ { pat: /\A(\?\?)(.+)\z/, styles: :red },
321
+ { pat: /\A(## )(.+)(\.{3})(.+)\z/,
298
322
  styles: [nil, :green, nil, :red], index: -1 }
299
323
  ]
300
324
  end)
@@ -339,18 +363,39 @@ module Squared
339
363
  cmd << "--#{flag}" << commit
340
364
  else
341
365
  cmd << "--#{flag}"
342
- append_ours
366
+ append_first %w[ours theirs]
343
367
  append_head
344
368
  append_pathspec files
345
369
  end
346
370
  source
347
371
  end
348
372
 
373
+ def tag(flag, refs, message: nil, commit: nil)
374
+ cmd = git_session 'tag'
375
+ case flag
376
+ when :add
377
+ if option('sign')
378
+ cmd << '--sign'
379
+ else
380
+ out = cmd.to_s
381
+ cmd << '--annotate' if %w[-s --sign -u --local-user].none? { |val| out.include?(" #{val}") }
382
+ end
383
+ append_message message
384
+ append_value(refs, escape: false)
385
+ append_head commit
386
+ when :delete, :list, :merged
387
+ cmd << shell_option(flag, commit)
388
+ append_option(%w[contains sort] + (flag == :list ? ['merged'] : []), equals: true) unless flag == :delete
389
+ append_value(refs, escape: false)
390
+ end
391
+ source
392
+ end
393
+
349
394
  def rev(flag, ref: nil, size: nil)
350
395
  git_session 'rev-parse', if flag == :branch
351
396
  '--abbrev-ref'
352
397
  else
353
- (n = size.to_i) > 0 ? "--short=#{[n, 5].max}" : '--verify'
398
+ (n = size.to_i) > 0 ? shell_option('short', [n, 5].max, escape: false) : '--verify'
354
399
  end
355
400
  append_commit ref
356
401
  source
@@ -375,7 +420,7 @@ module Squared
375
420
  def diff(flag, files = [], branch: nil, index: 0)
376
421
  cmd = git_session 'diff'
377
422
  unless flag == :files
378
- if /^#[0-9a-f]{5,40}\#$/.match?(sha = files.first)
423
+ if /\A#\h{5,40}\#\z/.match?(sha = files.first)
379
424
  sha = sha[1..-2]
380
425
  files.shift
381
426
  else
@@ -383,7 +428,7 @@ module Squared
383
428
  end
384
429
  end
385
430
  if (val = option('unified')).to_i > 0
386
- cmd << "--unified=#{val}"
431
+ cmd << shell_option('unified', val, escape: false)
387
432
  end
388
433
  append_nocolor
389
434
  case flag
@@ -425,14 +470,14 @@ module Squared
425
470
  upstream = false
426
471
  source('git fetch --no-tags --quiet', io: true, banner: false)
427
472
  source('git branch -vv --list', io: true, banner: false).first.each do |val|
428
- next unless (data = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
473
+ next unless (data = /\A\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
429
474
 
430
475
  branch = data[1]
431
476
  sha = data[2]
432
477
  if !data[3]
433
478
  unless (origin = option('repository', prefix: 'git', ignore: false))
434
479
  out = source('git log -n1 --format=%h%d', io: true, stdout: true, banner: false).first
435
- if (data = /^#{sha} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/m.match(out))
480
+ if (data = /\A#{sha} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)\z/.match(out))
436
481
  split_escape(data[1]).each do |val|
437
482
  next unless val.end_with?("/#{branch}")
438
483
 
@@ -442,7 +487,7 @@ module Squared
442
487
  end
443
488
  end
444
489
  upstream = !origin.nil?
445
- elsif (data = Regexp.new("^(.+)/#{Regexp.escape(branch)}$").match(data[3]))
490
+ elsif (data = Regexp.new("\\A(.+)/#{Regexp.escape(branch)}\\z").match(data[3]))
446
491
  origin = data[1]
447
492
  end
448
493
  break
@@ -478,27 +523,25 @@ module Squared
478
523
 
479
524
  def restore(flag, files)
480
525
  git_session 'restore', "--#{flag}"
481
- append_ours
526
+ append_first %w[ours theirs]
482
527
  append_pathspec(files, expect: true)
483
528
  source(stdout: true)
484
529
  end
485
530
 
486
531
  def show(objs, pretty: nil, format: nil, abbrev: nil)
487
532
  cmd = git_session 'show'
488
- case (flag = pretty&.downcase)
489
- when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
490
- cmd << "--pretty=#{flag}"
491
- else
492
- if pretty
493
- cmd << "--pretty=#{shell_escape("tformat:#{pretty}", quote: true)}"
494
- elsif format
495
- cmd << "--format=#{shell_escape(format, quote: true)}"
496
- end
533
+ if (flag = pretty || format)
534
+ cmd << case (val = flag.downcase)
535
+ when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
536
+ shell_option('format', val, escape: false)
537
+ else
538
+ shell_option('pretty', flag, escape: false, quote: true)
539
+ end
497
540
  end
498
541
  if (abbrev ||= option('abbrev')) == true
499
542
  cmd << '--abbrev-commit'
500
543
  elsif abbrev.to_i > 0
501
- cmd << "--abbrev=#{abbrev}"
544
+ cmd << shell_option('abbrev', abbrev, escape: false)
502
545
  end
503
546
  append_value objs
504
547
  source(exception: false)
@@ -511,7 +554,7 @@ module Squared
511
554
  cmd = session_done(cmd)
512
555
  log.info cmd
513
556
  banner = format_banner(cmd.gsub(File.join(path, ''), ''), banner: banner)
514
- cmd = cmd.sub(/^git\b/, "git --work-tree=#{shell_quote(path)} --git-dir=#{shell_quote(gitpath)}")
557
+ cmd = cmd.sub(/\Agit\b/, "git --work-tree=#{shell_quote(path)} --git-dir=#{shell_quote(gitpath)}")
515
558
  begin
516
559
  if io
517
560
  [stdout ? `#{cmd}` : IO.popen(cmd), banner]
@@ -580,8 +623,8 @@ module Squared
580
623
  if size > 0
581
624
  styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
582
625
  styles << :bold if styles.size <= 1
583
- puts print_footer("#{size} #{size == 1 ? type.sub(/s$/, '') : type}",
584
- sub: { styles: styles, pat: /^(\d+)(.+)$/ })
626
+ puts print_footer("#{size} #{size == 1 ? type.sub(/s\z/, '') : type}",
627
+ sub: { styles: styles, pat: /\A(\d+)(.+)\z/ })
585
628
  else
586
629
  puts empty_status("No #{type} were #{action}", 'grep', grep)
587
630
  end
@@ -589,11 +632,14 @@ module Squared
589
632
 
590
633
  def append_pull(opts, list, flag = nil)
591
634
  append_submodules flag
635
+ list = list.grep_v(/[^a-z\-]/)
592
636
  opts.each do |opt|
593
- if list.include?(opt) || opt.match(/^(?:depth|jobs)=\d+$/)
637
+ if list.include?(opt) || opt.match(/^(?:de(?:pth|epen)|jobs)=\d+$/)
594
638
  @session << "--#{opt}"
595
- elsif opt.match(/^since=(.+)$/) && (val = Date.parse($1))
596
- @session << "--shallow-since=\"#{val.strftime('%F %T')}\""
639
+ elsif opt.match(/^(?:shallow-)?since=(.+)$/) && (val = Date.parse($1))
640
+ @session << shell_option('shallow-since', val.strftime('%F %T'), escape: false, quote: true)
641
+ elsif opt.end_with?('!') && list.include?(opt = opt[0..-2])
642
+ @session << "--no-#{opt}"
597
643
  end
598
644
  end
599
645
  end
@@ -616,19 +662,13 @@ module Squared
616
662
  end
617
663
 
618
664
  def append_message(val)
619
- @session << "--message=\"#{double_quote(val)}\"" if val
665
+ @session << "--message=\"#{double_quote(val)}\"" unless val.to_s.empty?
620
666
  end
621
667
 
622
- def append_head
623
- @session << (option('head') || option('tree-ish'))
624
- end
668
+ def append_head(val = nil)
669
+ return @session << val if val
625
670
 
626
- def append_ours
627
- if option('ours')
628
- @session << '--ours'
629
- elsif option('theirs')
630
- @session << '--theirs'
631
- end
671
+ append_first(%w[head tree-ish object], flag: false, ignore: false)
632
672
  end
633
673
 
634
674
  def append_submodules(flag = nil)
@@ -12,11 +12,11 @@ module Squared
12
12
  end
13
13
 
14
14
  def batchargs
15
- [ref, { refresh: %i[build copy] }]
15
+ [ref, { refresh: %i[build copy] }].freeze
16
16
  end
17
17
 
18
18
  def aliasargs
19
- [ref, { refresh: :build }]
19
+ [ref, { refresh: :build }].freeze
20
20
  end
21
21
 
22
22
  def bannerargs
@@ -103,7 +103,7 @@ module Squared
103
103
  when :install
104
104
  desc format_desc(action, flag)
105
105
  task flag do
106
- depend(flag)
106
+ depend flag
107
107
  end
108
108
  when :outdated
109
109
  desc format_desc(action, flag, %w[prune interactive dry-run].freeze, arg: 'opts?')
@@ -144,7 +144,7 @@ module Squared
144
144
  items += as_a(also) if also
145
145
  return if items.empty?
146
146
 
147
- print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
147
+ print_item unless @output[0] || !verbose || task_invoked?(/\Acopy(?::#{Node.ref}|$)/)
148
148
  items.each do |dir|
149
149
  case dir
150
150
  when Pathname
@@ -243,7 +243,7 @@ module Squared
243
243
  end
244
244
  cmd << '--prod' if flag && prod?
245
245
  if (val = option('public-hoist-pattern', ignore: false))
246
- split_escape(val).each { |opt| cmd << "--public-hoist-pattern=#{shell_escape(opt, quote: true)}" }
246
+ split_escape(val).each { |opt| cmd << shell_option('public-hoist-pattern', opt, quote: true) }
247
247
  end
248
248
  cmd << '--ignore-workspace' if env('NODE_WORKSPACES', equals: '0')
249
249
  append_nocolor option('no-color')
@@ -279,10 +279,7 @@ module Squared
279
279
  end
280
280
  log.info cmd
281
281
  banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}")
282
- if sync
283
- print_item banner
284
- banner = nil
285
- end
282
+ print_item banner if sync
286
283
  begin
287
284
  data = pwd_set { `#{cmd} --json --loglevel=error` }
288
285
  json = JSON.parse(doc = dependfile.read)
@@ -316,8 +313,9 @@ module Squared
316
313
  avail << [key, file, latest, true]
317
314
  next
318
315
  end
316
+ current = val['current'] || file
319
317
  want = rev == :major && (ver = latest.match(SEM_VER)) && !ver[6] ? latest : val['wanted']
320
- next unless (val['current'] != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
318
+ next unless (current != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
321
319
 
322
320
  f = semscan(file)
323
321
  w = semscan(want)
@@ -345,7 +343,7 @@ module Squared
345
343
  end
346
344
  found << [key, file, want, index, major, f, w]
347
345
  elsif !major
348
- avail << [key, file, latest, false]
346
+ avail << [key, file, latest, latest != current]
349
347
  end
350
348
  end
351
349
  end
@@ -366,7 +364,7 @@ module Squared
366
364
  end
367
365
  puts print_footer(empty_status(msg, hint, pending + val))
368
366
  end
369
- print_item banner if banner
367
+ print_item banner unless sync
370
368
  if !found.empty?
371
369
  col1 = size_col.(found, 0) + 4
372
370
  col2 = size_col.(found, 1) + 4
@@ -465,8 +463,8 @@ module Squared
465
463
  major = flag == :major
466
464
  emphasize("version: #{out}", title: name, border: borderstyle, sub: [
467
465
  headerstyle,
468
- { pat: /^(version:)( )(\S+)(.*)$/, styles: color(major ? :green : :yellow), index: 3 },
469
- { pat: /^(version:)(.*)$/, styles: theme[major ? :major : :active] }
466
+ { pat: /\A(version:)( )(\S+)(.*)\z/, styles: color(major ? :green : :yellow), index: 3 },
467
+ { pat: /\A(version:)(.*)\z/, styles: theme[major ? :major : :active] }
470
468
  ])
471
469
  elsif stdin?
472
470
  puts out
@@ -653,19 +651,19 @@ module Squared
653
651
  end
654
652
  elsif pnpm?
655
653
  if silent
656
- @session << '--reporter=silent'
654
+ @session << shell_option('reporter', 'silent', escape: false)
657
655
  level ||= 'error'
658
656
  end
659
657
  case level
660
658
  when 'debug', 'info', 'warn', 'error'
661
- @session << "--loglevel=#{level}"
659
+ @session << shell_option('loglevel', level, escape: false)
662
660
  end
663
661
  elsif silent
664
- @session << '--loglevel=silent'
662
+ @session << shell_option('loglevel', 'silent', escape: false)
665
663
  else
666
664
  case level
667
665
  when 'error', 'warn', 'notice', 'http', 'info', 'verbose', 'silly'
668
- @session << "--loglevel=#{level}"
666
+ @session << shell_option('loglevel', level, escape: false)
669
667
  end
670
668
  end
671
669
  end
@@ -80,7 +80,7 @@ module Squared
80
80
  if flag == :target
81
81
  task flag, [:dir, :opts] do |_, args|
82
82
  dir = guard_params(action, flag, args: args, key: :dir)
83
- depend(flag, dir: dir, opts: args.to_a[1..-1] || [])
83
+ depend(flag, dir: dir, opts: args.to_a.drop(1))
84
84
  end
85
85
  else
86
86
  task flag do |_, args|
@@ -106,7 +106,7 @@ module Squared
106
106
  cmd << '--user'
107
107
  append_pip opts, OPT_USER
108
108
  when :target
109
- cmd << "--target=#{shell_escape(basepath(dir), quote: true)}"
109
+ cmd << shell_option('target', basepath(dir), quote: true)
110
110
  append_pip opts, OPT_USER + ['upgrade']
111
111
  append_eager opts
112
112
  when :upgrade
@@ -164,21 +164,20 @@ module Squared
164
164
 
165
165
  def append_pip(opts = [], list = [])
166
166
  opts.each do |opt|
167
- next unless list.include?(opt) || OPT_GENERAL.include?(opt) || (v = opt.match(/^v+$/))
167
+ next unless list.include?(opt) || OPT_GENERAL.include?(opt) || (v = opt.match(/^verbose|(v+)$/))
168
168
 
169
169
  @session << case opt
170
170
  when 'venv'
171
171
  '--require-virtualenv'
172
172
  else
173
- (v ? "-#{v[0]}" : "--#{opt}")
173
+ (v && v[1] ? "-#{v[1]}" : "--#{opt}")
174
174
  end
175
175
  end
176
- if (val = option('proxy', ignore: false))
177
- @session << "--proxy=#{shell_escape(val, quote: true)}"
178
- end
179
- @session << "--python=#{shell_escape(basepath(val), quote: true)}" if (val = option('python', ignore: false))
180
- @session << "--log=#{shell_escape(basepath(val), quote: true)}" if (val = option('log', ignore: false))
181
- @session << '--user' if option('user')
176
+ val = nil
177
+ @session << shell_option('proxy', val, quote: true) if (val = option('proxy'))
178
+ @session << shell_option('python', basepath(val), quote: true) if (val = option('python'))
179
+ @session << shell_option('log', basepath(val), quote: true) if (val = option('log', ignore: false))
180
+ @session << '--user' if !list.empty? && option('user')
182
181
  @session << '--no-input' if option('no-input')
183
182
  append_nocolor option('no-color')
184
183
  end
@@ -103,9 +103,10 @@ module Squared
103
103
  elsif exception
104
104
  indexerror n, list
105
105
  else
106
- next log.warn "rake task #{n} of #{list.size} (out of range)"
106
+ log.warn "rake task #{n} of #{list.size} (out of range)"
107
+ next
107
108
  end
108
- rake(args.extras.empty? ? cmd : "#{cmd}[#{args.extras.join(',')}]")
109
+ rake(args.extras.empty? ? cmd : "#{cmd}#{shell_escape("[#{args.extras.join(',')}]")}")
109
110
  else
110
111
  rake(*args.to_a)
111
112
  end
@@ -182,20 +183,20 @@ module Squared
182
183
  when :redownload, :local, :'prefer-local'
183
184
  cmd = bundle_session 'install', "--#{flag}"
184
185
  if (val = option('trust-policy', ignore: false))
185
- cmd << "--trust-policy=#{case val
186
- when '0'
187
- 'NoSecurity'
188
- when '1'
189
- 'AlmostNoSecurity'
190
- when '2'
191
- 'LowSecurity'
192
- when '3'
193
- 'MediumSecurity'
194
- when '4'
195
- 'HighSecurity'
196
- else
197
- val
198
- end}"
186
+ cmd << shell_option('trust-policy', case val
187
+ when '0'
188
+ 'NoSecurity'
189
+ when '1'
190
+ 'AlmostNoSecurity'
191
+ when '2'
192
+ 'LowSecurity'
193
+ when '3'
194
+ 'MediumSecurity'
195
+ when '4'
196
+ 'HighSecurity'
197
+ else
198
+ val
199
+ end, escape: false)
199
200
  end
200
201
  append_bundle opts, OPT_INSTALL
201
202
  else
@@ -218,7 +219,7 @@ module Squared
218
219
  return unless into
219
220
 
220
221
  dest = Pathname.new(into).realpath
221
- print_item unless @output[0] || task_invoked?(/^copy(?::#{Ruby.ref}|$)/)
222
+ print_item unless @output[0] || task_invoked?(/\Acopy(?::#{Ruby.ref}|\z)/)
222
223
  glob = as_a(glob || '**/*')
223
224
  as_a(from).each_with_index do |val, i|
224
225
  a = basepath(val)
@@ -235,14 +236,13 @@ module Squared
235
236
  cmd = session_done(cmd)
236
237
  log.info cmd
237
238
  banner = format_banner(cmd)
238
- if sync
239
- print_item banner
240
- banner = nil
241
- end
239
+ print_item banner if sync
242
240
  start = 0
243
241
  found = 0
244
242
  major = 0
245
243
  pwd_set do
244
+ buffer = []
245
+ out = ->(val) { sync ? puts(val) : buffer << val }
246
246
  IO.popen("#{cmd} --no-color").each do |line|
247
247
  if start > 0
248
248
  unless stdin?
@@ -302,24 +302,24 @@ module Squared
302
302
  when :yellow
303
303
  found += 1
304
304
  end
305
- styles = styles.compact
306
- .map { |s| s == :green || s == :yellow ? color(s) : s }
307
- .flatten
308
- line = sub_style(line, pat: /^((?:\S+\s+){2})(#{Regexp.escape(l)})(.*)$/, styles: styles,
309
- index: 2)
305
+ styles = styles.compact.map { |s| color(s) }.flatten
306
+ line = sub_style(line, pat: /^((?:\S+\s+){2})(#{Regexp.escape(l)})(.*)$/, index: 2, styles: styles)
310
307
  end
311
308
  end
312
- puts "#{start.to_s.rjust(2)}. #{line}"
309
+ out.("#{start.to_s.rjust(2)}. #{line}")
313
310
  start += 1
314
311
  elsif line =~ /^Gem /
315
- print_item banner if banner
316
312
  unless stdin?
317
313
  sub = { pat: /^(.+)(?<!\dm)(Gem|Latest)(.+)$/, styles: theme[:header], index: 2 }
318
- puts print_footer(" # #{line.chomp}", reverse: true, sub: [sub, sub])
314
+ out.(print_footer(" # #{line.chomp}", reverse: true, sub: [sub, sub]))
319
315
  end
320
316
  start += 1
321
317
  end
322
318
  end
319
+ unless sync
320
+ print_item banner
321
+ puts buffer
322
+ end
323
323
  if found > 0
324
324
  begin
325
325
  if major == 0 && (data = /\b(?:source\s+(["'])(.+?)\1|remote:\s+(\S+))/.match(dependfile.read))
@@ -353,7 +353,7 @@ module Squared
353
353
  cmd << '--all'
354
354
  append_repeat 'skip', opts
355
355
  when :version
356
- cmd << project << "--version=#{shell_escape(version)}"
356
+ cmd << project << shell_option('version', version)
357
357
  end
358
358
  run_rb
359
359
  end
@@ -364,11 +364,11 @@ module Squared
364
364
  end
365
365
 
366
366
  def rake(*cmd)
367
- file = shell_quote(Rake.application.rakefile)
367
+ rakefile = shell_option('rakefile', Rake.application.rakefile, quote: true, escape: false)
368
368
  if cmd.empty?
369
- run_s("rake --rakefile=#{file}", chdir: workspace.pwd)
369
+ run_s("rake #{rakefile}", chdir: workspace.pwd)
370
370
  else
371
- run_s(*cmd.map { |val| "rake --rakefile=#{file} #{val}" }, chdir: workspace.pwd, banner: false)
371
+ run_s(*cmd.map { |val| "rake #{rakefile} #{val}" }, chdir: workspace.pwd, banner: false)
372
372
  end
373
373
  end
374
374
 
@@ -429,7 +429,7 @@ module Squared
429
429
  if list.include?(opt)
430
430
  @session << "--#{opt}"
431
431
  elsif opt.match(/^g(?:roup)?=(.+)$/)
432
- @session << "--group=#{shell_escape($1)}"
432
+ @session << shell_option('group', $1)
433
433
  end
434
434
  end
435
435
  end
@@ -437,7 +437,7 @@ module Squared
437
437
  def gem_session(*cmd)
438
438
  ret = session('gem', *cmd)
439
439
  if (val = option('config-file', ignore: false))
440
- ret << "--config-file=#{shell_escape(basepath(val), quote: true)}"
440
+ ret << shell_option('config-file', basepath(val), quote: true)
441
441
  end
442
442
  ret << '--norc' if option('norc')
443
443
  ret
@@ -456,7 +456,7 @@ module Squared
456
456
  pass = Rake::VERSION >= '13.0.4'
457
457
  pwd_set(pass: pass) do
458
458
  IO.popen("rake#{pass ? " -C #{shell_quote(path)}" : ''} -AT").each do |line|
459
- next unless (data = /^rake ((?:[^\[: ]+:?)+)(\[[^\]]+\])?/.match(line))
459
+ next unless (data = /\Arake ((?:[^\[: ]+:?)+)(\[[^\]]+\])?/.match(line))
460
460
 
461
461
  ret << [data[1], data[2]]
462
462
  end
@@ -33,11 +33,11 @@ module Squared
33
33
 
34
34
  def repo(url, manifest = 'latest', run: nil, script: nil, dev: nil, prod: nil, ref: @ref, group: @group)
35
35
  @home = if (val = env('REPO_HOME'))
36
- home = Pathname.new(val)
37
- if main == home.basename.to_s
38
- @root = home.parent
39
- if home.exist?
40
- @root = nil unless home.directory?
36
+ path = Pathname.new(val)
37
+ if main == path.basename.to_s
38
+ @root = path.parent
39
+ if path.exist?
40
+ @root = nil unless path.directory?
41
41
  elsif !@root.exist?
42
42
  @root.mkpath
43
43
  elsif !repo_install?
@@ -45,7 +45,7 @@ module Squared
45
45
  end
46
46
  end
47
47
  raise_error('REPO_HOME', val, hint: 'invalid') unless @root
48
- home.realdirpath
48
+ path.realdirpath
49
49
  elsif (val = env('REPO_ROOT'))
50
50
  @root = Pathname.new(val).realdirpath
51
51
  if !@root.exist?
@@ -54,12 +54,12 @@ module Squared
54
54
  raise_error('REPO_ROOT', val, hint: 'exist') unless repo_confirm
55
55
  end
56
56
  @root.join(main).realdirpath
57
+ elsif repo_install?(parent: true) && (!@home.exist? || @root.join(main) == @home)
58
+ @home
57
59
  elsif repo_install?(@home)
58
60
  @home.join(main)
59
- elsif @home != pwd && repo_install?(pwd)
60
- pwd.join(main)
61
61
  else
62
- @home
62
+ (path = pwd) == @home || !repo_install?(path) ? @home : path.join(main)
63
63
  end
64
64
  @root = @home.parent
65
65
  @manifest_url = url
@@ -106,7 +106,7 @@ module Squared
106
106
  found = true
107
107
  end
108
108
  script_set(data, group: group, ref: ref) unless found
109
- @warning = env_match('REPO_WARN', @warning && !Repo.empty?(@root), suffix: @envname) != false
109
+ @warning = env_match('REPO_WARN', @warning && !root?(@root, pass: ['.repo']), suffix: @envname) != false
110
110
  @extensions << :__repo__
111
111
  elsif script || run
112
112
  if script
@@ -153,7 +153,7 @@ module Squared
153
153
  status = lambda do |val, alt = nil|
154
154
  return 'inactive' unless (ver = branch || alt)
155
155
 
156
- message(@prefix, 'repo', val.sub('{0}', 'opts*=force,rebase,detach,gc,no-update,no-fail'), ver, empty: true)
156
+ message(task_name('repo'), val.sub('{0}', 'opts*=force,rebase,detach,gc,no-update,no-fail'), ver)
157
157
  end
158
158
 
159
159
  namespace(name = task_name('repo')) do |repo|
@@ -230,7 +230,7 @@ module Squared
230
230
  end
231
231
 
232
232
  def repo_install?(dir = root, parent: false)
233
- return true if Repo.empty?(dir) || dir.join('.repo').directory?
233
+ return true if root?(dir, pass: ['.repo']) || dir.join('.repo').directory?
234
234
 
235
235
  parent && root.children.none? { |ent| ent.directory? && ent.basename.to_s[0] != '.' && ent != home }
236
236
  end
@@ -97,8 +97,9 @@ module Squared
97
97
  items.concat(tasks)
98
98
  end
99
99
  if tasks.size > 1 && (data = batch_get(key)) && data.keys.any? { |ref| proj.ref?(ref) }
100
- desc ws.task_name(t = ws.task_join(proj.name, key), desc: true)
101
- task ws.task_name(t) => tasks
100
+ t = ws.task_join(proj.name, key)
101
+ desc Common::Format.message(*t.split(':'))
102
+ task t => tasks
102
103
  end
103
104
  next unless (b = ws.find_base(proj)) && (n = b.ref.to_s) != g
104
105
 
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.1.1
4
+ version: 0.1.2
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-12-15 00:00:00.000000000 Z
11
+ date: 2024-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake