squared 0.6.5 → 0.6.7

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.
@@ -429,7 +429,7 @@ module Squared
429
429
  .sort { |a, b| b <=> a }
430
430
  .push('latest', 'system'),
431
431
  accept: [accept_y('Confirm?')],
432
- values: 'Options', force: true)
432
+ values: 'Options')
433
433
  OptionPartition.strip(opts)
434
434
  end
435
435
  asdf(flag, args, version: version)
@@ -537,7 +537,7 @@ module Squared
537
537
  end
538
538
  d = append_hash(d, target: []).join(' ') if d.is_a?(Hash)
539
539
  if a
540
- cmd << [a, d, b].compact.join(' ')
540
+ cmd << [replace_bin(a), d, b].compact.join(' ')
541
541
  else
542
542
  next unless respond_to?(:compose)
543
543
 
@@ -551,7 +551,7 @@ module Squared
551
551
  if cmd
552
552
  return run_b(cmd, sync: sync, from: from) if cmd.is_a?(Proc) || cmd.is_a?(Method)
553
553
 
554
- cmd = as_get cmd, from
554
+ cmd = replace_bin as_get(cmd, from)
555
555
  opts = compose(opts, script: false) if opts && respond_to?(:compose)
556
556
  flags = append_hash(flags, target: []).join(' ') if flags.is_a?(Hash)
557
557
  cmd = case opts
@@ -1158,7 +1158,7 @@ module Squared
1158
1158
  path.parent.ascend.each do |dir|
1159
1159
  target = dir.join(*args)
1160
1160
  return target if target.exist?
1161
- break if (ascend && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
1161
+ break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
1162
1162
  end
1163
1163
  ret
1164
1164
  end
@@ -1249,7 +1249,7 @@ module Squared
1249
1249
  single: false, last: false, context: nil)
1250
1250
  tag = ->(proj) { "#{proj.name}#{"@#{proj.version}" if SEM_VER.match?(proj.version)}" }
1251
1251
  uniq = lambda do |name|
1252
- next [] unless (ret = data[name])
1252
+ return [] unless (ret = data[name])
1253
1253
 
1254
1254
  ret.dup.each do |proj|
1255
1255
  next if proj.name == name
@@ -1358,13 +1358,7 @@ module Squared
1358
1358
  obj.enabled? ? [obj] : []
1359
1359
  else
1360
1360
  workspace.find(group: val, ref: val.to_sym)
1361
- end.sort do |a, b|
1362
- if a.parent == b
1363
- -1
1364
- else
1365
- b.parent == a ? 1 : 0
1366
- end
1367
- end.each do |proj|
1361
+ end.sort.each do |proj|
1368
1362
  next if pass.include?(name = proj.name)
1369
1363
 
1370
1364
  if proj.graph? && !data.key?(name) && !root.include?(name)
@@ -1528,7 +1522,9 @@ module Squared
1528
1522
  end
1529
1523
 
1530
1524
  def print_error(*args, loglevel: Logger::WARN, **kwargs)
1531
- warn log_message(loglevel, *args, **kwargs) if warning?
1525
+ return unless warning?
1526
+
1527
+ warn log_message(loglevel, *args, **kwargs)
1532
1528
  end
1533
1529
 
1534
1530
  def print_run(cmd, banner = true, verbose: nil, **)
@@ -1696,8 +1692,8 @@ module Squared
1696
1692
  msg.subhint(obj.is_a?(Numeric) ? "#{obj} #{title}" : message(title, obj.to_s))
1697
1693
  end
1698
1694
 
1699
- def append_repeat(flag, opts, target: @session)
1700
- opts.each { |val| target << shell_option(flag, val) }
1695
+ def append_repeat(flag, opts, target: @session, **kwargs)
1696
+ opts.each { |val| target << shell_option(flag, val, **kwargs) }
1701
1697
  end
1702
1698
 
1703
1699
  def append_hash(data, target: @session || [], build: false)
@@ -1722,6 +1718,8 @@ module Squared
1722
1718
  target << basic_option(key, val)
1723
1719
  when FalseClass
1724
1720
  target << shell_option(key).sub(/^--(?!no-)/, '--no-')
1721
+ when Pathname
1722
+ target << shell_option(key, val, escape: false)
1725
1723
  else
1726
1724
  target << shell_option(key, (val if val.is_a?(String)))
1727
1725
  end
@@ -1774,20 +1772,18 @@ module Squared
1774
1772
  return if list.empty?
1775
1773
 
1776
1774
  kwargs[:ignore] = false if no && !kwargs.key?(:ignore)
1777
- [].tap do |ret|
1778
- list.flatten.each do |flag|
1779
- next unless (val = option(flag, target: target, **kwargs))
1775
+ ret = []
1776
+ list.flatten.each do |flag|
1777
+ next unless (val = option(flag, target: target, **kwargs))
1780
1778
 
1781
- if no && val == '0'
1782
- flag = "no-#{flag}"
1783
- val = nil
1784
- end
1785
- ret << shell_option(flag, (val if equals), escape: escape, quote: quote, force: force)
1779
+ if no && val == '0'
1780
+ flag = "no-#{flag}"
1781
+ val = nil
1786
1782
  end
1787
- next if ret.empty?
1788
-
1789
- merge_list target, ret
1783
+ ret << shell_option(flag, (val if equals), escape: escape, quote: quote, force: force)
1790
1784
  end
1785
+ merge_list target, ret unless ret.empty?
1786
+ ret
1791
1787
  end
1792
1788
 
1793
1789
  def append_nocolor(target: @session)
@@ -1870,6 +1866,13 @@ module Squared
1870
1866
  ret
1871
1867
  end
1872
1868
 
1869
+ def replace_bin(val)
1870
+ a, b = val.split(' ', 2)
1871
+ return val if val.start_with?(/["']/) || a.include?(File::Separator)
1872
+
1873
+ [shell_bin(a), b].compact.join(' ')
1874
+ end
1875
+
1873
1876
  def parse_json(val, kind: Hash, hint: nil)
1874
1877
  ret = JSON.parse(val)
1875
1878
  raise_error 'invalid JSON'.subhint(kind.name), val, hint: hint if kind && !ret.is_a?(kind)
@@ -2003,10 +2006,15 @@ module Squared
2003
2006
  nil
2004
2007
  end
2005
2008
 
2006
- def command(*args)
2007
- return args.join(' && ') unless workspace.powershell?
2008
-
2009
- "powershell.exe -Command #{shell_quote("& {#{args.join(' ; ')}}", option: false, double: true)}"
2009
+ def command(*args, verbose: true)
2010
+ out = unless verbose
2011
+ [">#{File::NULL}", '2>&1'].tap { |a| a.reverse if File::NULL == 'NUL' }.unshift('').join(' ')
2012
+ end
2013
+ if workspace.powershell?
2014
+ "#{shell_bin('powershell.exe')} -Command \"& {#{args.join(' ; ')}}\"#{out}"
2015
+ else
2016
+ args.map! { |val| "#{val}#{out}" }.join(' && ')
2017
+ end
2010
2018
  end
2011
2019
 
2012
2020
  def relativepath(*list, all: false)
@@ -2117,7 +2125,11 @@ module Squared
2117
2125
  end
2118
2126
  end
2119
2127
 
2120
- def semgte?(val, other)
2128
+ def semgte?(val, other = nil)
2129
+ unless other
2130
+ other = val
2131
+ val = RUBY_VERSION
2132
+ end
2121
2133
  semcmp(val, other) != 1
2122
2134
  end
2123
2135
 
@@ -2210,13 +2222,15 @@ module Squared
2210
2222
  end
2211
2223
 
2212
2224
  def pwd_set(pass: false, exception: self.exception, dryrun: false, from: nil)
2213
- pwd = Dir.pwd
2214
- return yield if (path.to_s == pwd || pass == true) && (workspace.mri? || !workspace.windows?)
2225
+ return yield if (path.to_s == Dir.pwd || pass == true) && (workspace.mri? || !workspace.windows?)
2215
2226
 
2216
- Dir.chdir path
2217
- yield.tap { Dir.chdir pwd }
2227
+ pwd = Dir.pwd
2228
+ Dir.chdir(path)
2229
+ yield
2218
2230
  rescue StandardError => e
2219
2231
  on_error(e, from, exception: exception, dryrun: dryrun)
2232
+ ensure
2233
+ Dir.chdir(pwd) if pwd
2220
2234
  end
2221
2235
 
2222
2236
  def run_set(cmd, val = nil, opts: nil, global: false, **)
@@ -13,7 +13,7 @@ module Squared
13
13
  buildx: {
14
14
  common: %w[builder=b D|debug],
15
15
  build: %w[add-host=q annotation=q attest=q build-arg=qq build-context=qq cache-from=q cache-to=q
16
- cgroup-parent=b iidfile=p label=q a-file=p network=b no-cache-filter=b o|output=q platform=b
16
+ cgroup-parent=b iidfile=p label=q network=b no-cache-filter=b o|output=q platform=q
17
17
  q|quiet secret=qq shm-size=b ssh=qq t|tag=b target=b ulimit=q].freeze,
18
18
  bake: %w[print list=q set=q].freeze,
19
19
  shared: %w[check load no-cache pull push allow=q call=b? f|file=p metadata-file=p progress=b provenance=q
@@ -40,22 +40,21 @@ module Squared
40
40
  rm t|tty use-api-socket add-host=q annotation=q a|attach=b blkio-weight=i blkio-weight-device=i
41
41
  cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p device=q device-cgroup-rule=q
42
42
  device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
43
- disable-content-trust=b? dns=q dns-option=q dns-search=q domainname=b entrypoint=q e|env=qq
44
- env-file=p expose=q gpus=q group-add=b health-cmd=q health-interval=b health-retries=i
45
- health-start-interval=q health-start-period=q health-timeout=q io-maxbandwidth=b io-maxiops=b
46
- ip=b ip6=q ipc=b isolation=b kernel-memory=b l|label=q label-file=q link=b link-local-ip=q
47
- log-driver=b log-opt=q mac-address=q m|memory=b memory-reservation=b memory-swap=n
48
- memory-swappiness=n mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n
49
- platform=b p|publish=q pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b
50
- stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q
51
- volume-driver=b volumes-from=b w|workdir=q].freeze,
52
- run: %w[d|detach detach-keys=q hostname=q sig-proxy=b?].freeze,
43
+ dns=q dns-option=q dns-search=q domainname=b entrypoint=q e|env=qq env-file=p expose=q gpus=q
44
+ group-add=b health-cmd=q health-interval=b health-retries=i health-start-interval=q
45
+ health-start-period=q health-timeout=q hostname=q io-maxbandwidth=b io-maxiops=b ip=b ip6=q ipc=b
46
+ isolation=b l|label=q label-file=q link=b link-local-ip=q log-driver=b log-opt=q mac-address=q
47
+ m|memory=b memory-reservation=b memory-swap=n memory-swappiness=n mount=qq name=b network=b
48
+ network-alias=b oom-score-adj=b pid=b pids-limit=n platform=q p|publish=q pull=b restart=b
49
+ runtime=b security-opt=q shm-size=b stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q
50
+ ulimit=q u|user=b userns=b uts=b v|volume=q volume-driver=b volumes-from=b w|workdir=q].freeze,
51
+ run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
53
52
  update: %w[blkio-weight=i cpu-period=i cpu-quota=i cpu-rt-period=i cpu-rt-runtime=i c|cpu-shares=i cpus=f
54
- cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
53
+ cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=n pids-limit=n
55
54
  restart=q].freeze,
56
- exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
55
+ exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p u|user=e
57
56
  w|workdir=q].freeze,
58
- commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
57
+ commit: %w[no-pause a|author=q c|change=q m|message=q pause=b?].freeze,
59
58
  inspect: %w[s|size f|format=q type=b].freeze,
60
59
  start: %w[a|attach i|interactive detach-keys=q].freeze,
61
60
  stop: %w[s|signal=b t|timeout=i].freeze,
@@ -65,9 +64,9 @@ module Squared
65
64
  }.freeze,
66
65
  image: {
67
66
  ls: %w[a|all digests no-trunc q|quiet tree f|filter=q format=q].freeze,
68
- push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
69
- rm: %w[f|force no-prune platform=b].freeze,
70
- save: %w[o|output=p platform=b].freeze
67
+ push: %w[a|all-tags platform=q q|quiet].freeze,
68
+ rm: %w[f|force no-prune platform=q].freeze,
69
+ save: %w[o|output=p platform=q].freeze
71
70
  }.freeze,
72
71
  network: {
73
72
  connect: %w[alias=b driver-opt=q gw-priority=n ip=b ip6=q link=b link-local-ip=q].freeze,
@@ -154,33 +153,34 @@ module Squared
154
153
  task action, [:command] do |_, args|
155
154
  command = param_guard(action, 'command', args: args, key: :command)
156
155
  args = args.extras
157
- cmd = docker_output(command, case command
156
+ cmd = docker_output command, case command
158
157
  when 'image', 'container', 'network'
159
158
  'ls'
160
159
  when 'compose'
161
160
  'ps'
162
161
  else
163
162
  raise_error ArgumentError, 'unrecognized command', hint: command
164
- end)
163
+ end
165
164
  cmd << '-a' if has_value!(args, 'a', 'all') && command != 'network'
166
165
  data = VAL_DOCKER[:ls][command.to_sym]
167
- if has_value!(args, 's', 'standard')
168
- cols = data.first(data.index('CreatedAt'))
169
- else
170
- cols = []
171
- args.each do |val|
172
- if val =~ /^(\d+)$/
173
- cols << data[$1.to_i.pred]
174
- elsif val =~ /^(\d+)(-|\.{2,3})(\d+)$/
175
- j = $1.to_i.pred
176
- k = $3.to_i - ($2 == '..' ? 2 : 1)
177
- cols.concat(data[j..k]) if k > j
178
- end
179
- end
180
- if cols.empty?
181
- cols = choice_index('Select a column', data, multiple: true, force: true, attempts: 1)
182
- end
183
- end
166
+ cols = if has_value!(args, 's', 'standard')
167
+ data.first(data.index('CreatedAt'))
168
+ else
169
+ [].tap do |out|
170
+ args.each do |val|
171
+ if val =~ /^(\d+)$/
172
+ out << data[$1.to_i.pred]
173
+ elsif val =~ /^(\d+)(-|\.{2,3})(\d+)$/
174
+ j = $1.to_i.pred
175
+ k = $3.to_i - ($2 == '..' ? 2 : 1)
176
+ out.concat(data[j..k]) if k > j
177
+ end
178
+ end
179
+ next unless out.empty?
180
+
181
+ out.replace(choice_index('Select a column', data, multiple: true, attempts: 1))
182
+ end
183
+ end
184
184
  cmd << quote_option('format', "table #{cols.map! { |val| "{{.#{val}}}" }.join("\t")}")
185
185
  run(cmd, banner: false, from: :ls)
186
186
  end
@@ -417,7 +417,7 @@ module Squared
417
417
  lines = IO.popen(cmd.temp('--services')).map(&:strip).reject(&:empty?)
418
418
  return list_empty(hint: status) if lines.empty?
419
419
 
420
- service = choice_index('Choose a service', lines, multiple: true, force: true, attempts: 1)
420
+ service = choice_index('Choose a service', lines, multiple: true, attempts: 1)
421
421
  end
422
422
  docker_session('compose', command, '--', *service)
423
423
  else
@@ -545,11 +545,12 @@ module Squared
545
545
  if opts.size == op.size
546
546
  index = 0
547
547
  name = nil
548
- opts.reverse_each do |opt|
549
- if (name = opt[/^name=["']?(.+?)["']?$/, 1])
550
- opts.delete(opt)
551
- break
552
- end
548
+ opts.reverse_each do |val|
549
+ next unless (arg = OptionPartition.parse_arg!('name', val))
550
+
551
+ name = arg[1]
552
+ opts.delete(val)
553
+ break
553
554
  end
554
555
  list_image(:run, from: from) do |val|
555
556
  container(:run, if name
@@ -732,21 +733,17 @@ module Squared
732
733
  end
733
734
 
734
735
  def append_tag(val, target: @session)
736
+ ver = option('version', target: target, ignore: false)
735
737
  case val
736
738
  when String
737
739
  split_escape val
738
- when Array
739
- val
740
740
  else
741
- []
742
- end.yield_self do |list|
743
- ver = option('version', target: target, ignore: false)
744
- list.each do |s|
745
- s = "#{s}:#{ver}" if ver && (!s.include?(':') || s.delete_suffix!(':latest'))
746
- target << basic_option('tag', tagname(s))
747
- end
748
- target
741
+ Array(val)
742
+ end.each do |s|
743
+ s = "#{s}:#{ver}" if ver && (!s.include?(':') || s.delete_suffix!(':latest'))
744
+ target << basic_option('tag', tagname(s))
749
745
  end
746
+ target
750
747
  end
751
748
 
752
749
  def filter_ps(flag, from = :'container:ps')
@@ -873,14 +870,12 @@ module Squared
873
870
  "--format='table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.CreatedSince}}\t{{.Size}}'"]
874
871
  end
875
872
  lines = `#{docker_output(cmd)}`.lines
876
- header = lines.shift
877
- if lines.empty?
878
- puts log_message('none found', subject: name, hint: "docker #{cmd.split(' ', 3)[0...2].join(' ')}")
873
+ if lines.size <= 1
874
+ puts log_message('none found', subject: name, hint: "docker #{cmd.split(' ', 3)[0, 2].join(' ')}")
879
875
  return
880
876
  end
881
- puts " # #{header}"
877
+ puts " # #{lines.shift}"
882
878
  multiple = false
883
- parse = ->(val) { val.split(/\s+/)[0] }
884
879
  ctx = flag.to_s
885
880
  case flag
886
881
  when :run, :exec
@@ -915,7 +910,7 @@ module Squared
915
910
  else
916
911
  cmd << opts << '--'
917
912
  end
918
- cmd.merge(Array(out).map! { |val| parse.call(val) })
913
+ cmd.merge(Array(out).map! { |val| val.split(/\s+/, 2).first })
919
914
  cmd << args
920
915
  success?(run(cmd), ctx.start_with?(/network|tag|save/))
921
916
  end
@@ -29,7 +29,7 @@ module Squared
29
29
  base = name.to_s
30
30
  each { |proj| repo << proj if !proj.parent && check.call(proj) }
31
31
  else
32
- warn log_message(Logger::WARN, name, subject: 'git', hint: 'invalid') if warning
32
+ warn log_warn(name, subject: 'git', hint: 'invalid') if warning
33
33
  return self
34
34
  end
35
35
  end
@@ -86,7 +86,7 @@ module Squared
86
86
  @revdoc = JSON.parse(@revfile.read) if @revfile.exist?
87
87
  rescue StandardError => e
88
88
  @revfile = nil
89
- warn log_message(Logger::WARN, e, pass: true)
89
+ warn log_warn(e, pass: true)
90
90
  self
91
91
  else
92
92
  @revdoc = {} unless @revdoc.is_a?(Hash)
@@ -142,7 +142,7 @@ module Squared
142
142
  File.write(@revfile, JSON.pretty_generate(@revdoc))
143
143
  rescue StandardError => e
144
144
  log&.debug e
145
- warn log_message(Logger::WARN, e, pass: true) if warning?
145
+ warn log_warn(e, pass: true) if warning
146
146
  ensure
147
147
  @revlock = false
148
148
  end
@@ -580,17 +580,17 @@ module Squared
580
580
  when '--'
581
581
  grep << '--' if grep.empty?
582
582
  break
583
- when 'a', 'all-match'
583
+ when /^a(ll-match)?$/
584
584
  opts << 'all-match'
585
- when 'in', 'invert-grep'
585
+ when /^in(vert-grep)?$/
586
586
  opts << 'invert-grep'
587
587
  when 'i', 'E', 'F', 'P'
588
588
  opts << last
589
589
  else
590
- if last =~ /^(?:f(?:-ormat)?)=(.+)$/
590
+ if last =~ /^(f(-ormat)?)=(.+)$/
591
591
  opts.shift
592
592
  opts << "format=#{$1}"
593
- elsif last =~ /^(?:max(?:-count)?)=(\d+)$/
593
+ elsif last =~ /^(max(-count)?)=(\d+)$/
594
594
  opts << "max-count=#{$1}"
595
595
  else
596
596
  grep << last
@@ -883,6 +883,8 @@ module Squared
883
883
  rev_parse(flag, ref: ref, size: size)
884
884
  end
885
885
  when :build
886
+ next unless build?
887
+
886
888
  format_desc action, flag, 'opts*'
887
889
  task flag do |_, args|
888
890
  revbuild flag, args.to_a
@@ -1167,7 +1169,7 @@ module Squared
1167
1169
  end
1168
1170
  end
1169
1171
  out = choice_index('Choose a stash', git_spawn('stash list', stdout: false),
1170
- values: values, column: /^[^@]+@\{(\d+)}/, force: true)
1172
+ values: values, column: /^[^@]+@\{(\d+)\}/)
1171
1173
  if values
1172
1174
  op.merge(out.reverse)
1173
1175
  else
@@ -1276,9 +1278,7 @@ module Squared
1276
1278
  files = status_digest(*args, **kwargs)
1277
1279
  if cur['files'].size == files.size && cur['files'].find { |key, val| files[key] != val }.nil?
1278
1280
  workspace.rev_timeutc(name, 'build') unless (since = workspace.rev_timesince(name, 'build'))
1279
- if stdout?
1280
- puts log_message(['revbuild', 'no changes'], subject: name, hint: ("#{since} ago" if since))
1281
- end
1281
+ puts log_message(['revbuild', 'no changes'], subject: name, hint: ("#{since} ago" if since)) if stdout?
1282
1282
  return
1283
1283
  end
1284
1284
  end
@@ -1513,13 +1513,14 @@ module Squared
1513
1513
  append_pathspec op.extras
1514
1514
  end
1515
1515
  co = git_session('commit', options: false)
1516
- pu = git_output 'push', upstream && '--set-upstream'
1516
+ pu = git_output 'push'
1517
+ co << '--amend' if amend
1518
+ pu << '--set-upstream' if upstream
1517
1519
  if dryrun?
1518
- op.delete('--dry-run')
1520
+ op.adjoin('--dry-run')
1519
1521
  co << '--dry-run'
1520
1522
  pu << '--dry-run'
1521
1523
  end
1522
- co << '--amend' if amend
1523
1524
  if message
1524
1525
  append_message message
1525
1526
  elsif flag == :'amend-orig' || option('edit', equals: '0')
@@ -1527,13 +1528,12 @@ module Squared
1527
1528
  end
1528
1529
  pu << '--force-with-lease' if amend
1529
1530
  pu.merge(repotrack(origin, branch))
1530
- puts if pass
1531
1531
  adding = git_spawn 'diff --name-only --no-color'
1532
1532
  source op
1533
1533
  cached = git_spawn 'diff --cached --name-only --no-color'
1534
1534
  if amend || !cached.empty? || dryrun?
1535
1535
  if adding.empty? && !cached.empty? && banner?
1536
- puts(cached.lines.map! { |val| "cached #{shell_quote(val.chomp)}" })
1536
+ puts(cached.lines(chomp: true).map! { |val| "cached #{shell_quote(val)}" })
1537
1537
  end
1538
1538
  source co
1539
1539
  source pu
@@ -1553,7 +1553,8 @@ module Squared
1553
1553
  case flag
1554
1554
  when :commit, :'no-commit'
1555
1555
  op = OptionPartition.new(opts, OPT_GIT[:merge], cmd, project: self, no: OPT_GIT[:no][:merge])
1556
- op << "--#{flag}" << '--'
1556
+ op << "--#{flag}"
1557
+ op.delim
1557
1558
  if branch
1558
1559
  op << branch
1559
1560
  op.clear(pass: false)
@@ -1643,13 +1644,15 @@ module Squared
1643
1644
  git_spawn 'fetch --all --prune --quiet' if option('sync')
1644
1645
  cmd << '-vv --no-abbrev --list'
1645
1646
  out, banner, from = source(io: true)
1646
- ret = write_lines(out, grep: [/^\*\s+#{Regexp.escape(head)}\s/], banner: banner, first: true) do |line|
1647
+ first = workspace.size > 1
1648
+ grep = first ? [/^\*\s+#{Regexp.escape(head)}\s/] : []
1649
+ ret = write_lines(out, grep: grep, banner: banner, first: first) do |line, index|
1647
1650
  next line if stdin?
1648
1651
 
1649
- data = line.sub(/^\*\s+/, '').split(/\s+/)
1650
- a = sub_style data[0], theme[:inline]
1651
- b = sub_style data[1], theme[:extra]
1652
- r = /\A(?:\[((?~\]\s))\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
1652
+ data = line.sub(/^\*?\s+/, '').split(/\s+/, 3)
1653
+ a = sub_style(data[0], theme[:inline], styles: (:underline if !first && line.start_with?('*')))
1654
+ b = commitstyle data[1]
1655
+ r = /\A(?:\[((?~\]\s))\]\s)?(.+)\z/m.match(data[2])
1653
1656
  if (r1 = r[1]) && r1 =~ /^(.+):(?: ([a-z]+) (\d+),)? ([a-z]+) (\d+)$/
1654
1657
  write = ->(s1, s2) { "#{s1.capitalize.rjust(7)}: #{sub_style(s2, theme[:warn])}" }
1655
1658
  r1 = $1
@@ -1657,7 +1660,7 @@ module Squared
1657
1660
  r3 = write.call($4, $5)
1658
1661
  end
1659
1662
  r1 = nil if r1 == "origin/#{data[0]}"
1660
- [" Branch: #{a.subhint(r1)}", r2, r3, " Commit: #{b}", "Message: #{r[2]}"]
1663
+ ["#{"\n" unless index == 0} Branch: #{a.subhint(r1)}", r2, r3, " Commit: #{b}", "Message: #{r[2]}"]
1661
1664
  .compact
1662
1665
  .join("\n")
1663
1666
  end
@@ -1690,7 +1693,7 @@ module Squared
1690
1693
  basic_option 'track', track
1691
1694
  end
1692
1695
  when :detach
1693
- cmd << "--#{flag}"
1696
+ cmd << '--detach'
1694
1697
  end
1695
1698
  append_head commit
1696
1699
  end
@@ -1738,7 +1741,7 @@ module Squared
1738
1741
  case format
1739
1742
  when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
1740
1743
  cmd << basic_option('format', format)
1741
- when /(?:^t?format:|%)/
1744
+ when /^t?format:|%/
1742
1745
  cmd << quote_option('pretty', format)
1743
1746
  else
1744
1747
  opts << format if format
@@ -1754,7 +1757,7 @@ module Squared
1754
1757
  cmd, opts = git_session('rev-parse', opts: opts)
1755
1758
  case flag
1756
1759
  when :commit
1757
- cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
1760
+ cmd << (size.to_i.zero? ? '--verify' : basic_option('short', [size.to_i, 5].max))
1758
1761
  append_commit(ref, head: true)
1759
1762
  when :branch
1760
1763
  cmd << '--abbrev-ref'
@@ -1823,15 +1826,14 @@ module Squared
1823
1826
  grep, pathspec = op.partition { |val| OptionPartition.pattern?(val) }
1824
1827
  unless grep.empty? && !pathspec.empty?
1825
1828
  grep.map! { |val| Regexp.new(val[1..-2]) }
1826
- files = [].tap do |out|
1827
- status_data.each do |a, b|
1828
- next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
1829
+ files = []
1830
+ status_data.each do |a, b|
1831
+ next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
1829
1832
 
1830
- out << "#{sub_style(b, color(:red))} #{a}"
1831
- end
1833
+ files << "#{sub_style(b, color(:red))} #{a}"
1832
1834
  end
1833
1835
  unless files.empty?
1834
- files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/,
1836
+ files = choice_index('Select files', files, multiple: true, trim: /^\S+\s/,
1835
1837
  accept: [accept_y('Add?')])
1836
1838
  end
1837
1839
  op.swap(pathspec + files)
@@ -1850,8 +1852,8 @@ module Squared
1850
1852
  if op.include?('--')
1851
1853
  op.add_path(val)
1852
1854
  elsif op.exist?(val, glob: true)
1853
- op << '--'
1854
- op.add_path(val)
1855
+ op.delim
1856
+ .add_path(val)
1855
1857
  else
1856
1858
  op.add_quote(val)
1857
1859
  end
@@ -1951,7 +1953,7 @@ module Squared
1951
1953
  out = []
1952
1954
  data.each do |line|
1953
1955
  next if grep&.none? { |pat| pat.match?(line) }
1954
- next if block_given? && !(line = yield line)
1956
+ next if block_given? && !(line = yield(line, ret))
1955
1957
 
1956
1958
  if loglevel
1957
1959
  log&.add loglevel, line
@@ -1993,16 +1995,24 @@ module Squared
1993
1995
  end
1994
1996
  args = []
1995
1997
  args << quote_option('sort', sort) if sort
1996
- args << shell_option('count', env('GIT_COUNT', ARG[:CHOICE])) if count
1998
+ args << basic_option('count', env('GIT_COUNT', ARG[:CHOICE])) if count
1997
1999
  choice_index(msg, foreachref(type, *args, format: format), trim: trim, **kwargs)
1998
2000
  end
1999
2001
 
2000
2002
  def choice_commit(count: true, reflog: true, force: true, **kwargs)
2001
2003
  kwargs[:attempts] ||= 1 unless force
2002
2004
  cmd = git_output(reflog && env('GIT_REFLOG') ? 'reflog' : 'log')
2003
- cmd << quote_option('format', '(%h) %s')
2005
+ cmd << quote_option('format', "#{commitstyle('%h')} %s")
2004
2006
  cmd << basic_option('max-count', env('GIT_COUNT', ARG[:CHOICE])) if count
2005
- choice_index('Choose a commit', git_spawn(cmd, stdout: false), column: /\((\w+)\)/, force: force, **kwargs)
2007
+ ret = choice_index('Choose a commit', git_spawn(cmd, stdout: false), column: /^(\S+)/, force: force, **kwargs)
2008
+ case ret
2009
+ when Array
2010
+ ret.map!(&:stripstyle)
2011
+ when String
2012
+ ret.stripstyle
2013
+ else
2014
+ ret
2015
+ end
2006
2016
  end
2007
2017
 
2008
2018
  def choice_remote(force: false, **kwargs)
@@ -2026,13 +2036,13 @@ module Squared
2026
2036
  end
2027
2037
 
2028
2038
  def status_data(*args)
2029
- [].tap do |ret|
2030
- git_spawn('status -z -uall', *args).split("\x0").each do |line|
2031
- next unless line =~ /^(.)(.) (.+)$/
2039
+ ret = []
2040
+ git_spawn('status -z -uall', *args).split("\x0").each do |line|
2041
+ next unless line =~ /^(.)(.) (.+)$/
2032
2042
 
2033
- ret << [$3, $2, $1]
2034
- end
2043
+ ret << [$3, $2, $1]
2035
2044
  end
2045
+ ret
2036
2046
  end
2037
2047
 
2038
2048
  def append_pull(opts, list, flag:, from:, target: @session, no: nil, remote: nil)
@@ -2108,7 +2118,9 @@ module Squared
2108
2118
 
2109
2119
  def append_message(val = nil, target: @session)
2110
2120
  val = messageopt if val.to_s.empty?
2111
- target << quote_option('message', val) if val
2121
+ return unless val
2122
+
2123
+ target << quote_option('message', val)
2112
2124
  end
2113
2125
 
2114
2126
  def append_head(val = nil, target: @session)
@@ -2205,6 +2217,10 @@ module Squared
2205
2217
  s.start_with?(/\d/) ? "@~#{s}" : "@#{s}"
2206
2218
  end
2207
2219
 
2220
+ def commitstyle(val)
2221
+ sub_style(val, theme[:extra] || color(:yellow))
2222
+ end
2223
+
2208
2224
  def matchhead(val)
2209
2225
  val =~ /^(?:(?:HEAD|@)([~^]\d*)?|H(\d+))$/ ? $2 || $1 || '' : nil
2210
2226
  end