squared 0.1.1 → 0.1.2

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