squared 0.4.14 → 0.5.0

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.
@@ -27,7 +27,7 @@ module Squared
27
27
  base = name
28
28
  @project.each_value { |proj| repo << proj if !proj.parent && check.call(proj) }
29
29
  else
30
- warn log_message(Logger::WARN, name, subject: 'git', hint: 'invalid') if warning
30
+ warn log_message(Logger::WARN, name, subject: 'git', hint: 'invalid', pass: true) if warning
31
31
  return self
32
32
  end
33
33
  if base
@@ -91,13 +91,13 @@ module Squared
91
91
 
92
92
  data = @revdoc
93
93
  last = keys.pop
94
- for key in keys
94
+ keys.each do |key|
95
95
  if data[key].is_a?(Hash)
96
96
  data = data[key]
97
97
  elsif create
98
98
  data = data[key] = {}
99
99
  else
100
- return
100
+ return nil
101
101
  end
102
102
  end
103
103
  data[last] = val
@@ -157,13 +157,14 @@ module Squared
157
157
  class Git < Base
158
158
  OPT_GIT = {
159
159
  common: %w[c=q bare glob-pathspecs icase-pathspecs literal-pathspecs no-optional-locks no-pager
160
- no-replace-objects noglob-pathspecs paginate config-env=q exec-path=p namespace=p].freeze,
160
+ no-replace-objects noglob-pathspecs paginate attr-source=b config-env=q exec-path=p
161
+ namespace=p].freeze,
161
162
  add: %w[A|all e|edit f|force ignore-errors ignore-missing ignore-removal i|interactive no-all
162
163
  no-ignore-removal n|dry-run p|patch pathspec-file-nul renormalize sparse u|update v|verbose
163
164
  chmod=b pathspec-from-file=p].freeze,
164
- branch: %w[a|all create-reflog i|ignore-case q|quiet r|remotes v|verbose vv abbrev=i color=b column=b
165
- contains=b format=q merged=b no-contains=b no-merged=b points-at=b u|set-upstream-to=b sort=q
166
- t|track=b].freeze,
165
+ branch: %w[a|all create-reflog i|ignore-case omit-empty q|quiet r|remotes v|verbose vv abbrev=i color=b
166
+ column=b contains=b format=q merged=b no-contains=b no-merged=b points-at=b u|set-upstream-to=b
167
+ sort=q t|track=b].freeze,
167
168
  checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
168
169
  pathspec-file-nul q|quiet ours theirs conflict=b orphan=b pathspec-from-file=p t|track=b].freeze,
169
170
  diff: {
@@ -171,7 +172,8 @@ module Squared
171
172
  show: %w[s exit-code histogram].freeze
172
173
  }.freeze,
173
174
  fetch: {
174
- base: %w[multiple progress P|prune-tags refetch stdin u|update-head-ok recurse-submodules-default=b].freeze,
175
+ base: %w[multiple porcelain progress P|prune-tags refetch stdin u|update-head-ok
176
+ recurse-submodules-default=b].freeze,
175
177
  pull: %w[4 6 n t a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet
176
178
  set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
177
179
  recurse-submodules=v refmap=q o|server-option=q shallow-exclude=b shallow-since=v
@@ -196,9 +198,9 @@ module Squared
196
198
  branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
197
199
  exclude-hidden=b glob=q grep=q grep-reflog=q n|max-count=i max-parents=i min-parents=i no-walk=b?
198
200
  remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
199
- format: %w[t children combined-all-paths oneline left-right no-diff-merges parents relative-date
200
- show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=b pretty=q?
201
- show-linear-break=q?].freeze,
201
+ format: %w[t children combined-all-paths dd oneline left-right no-diff-merges parents relative-date
202
+ show-notes-by-default show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q
203
+ notes=b pretty=q? show-linear-break=q?].freeze,
202
204
  diff: %w[p R u z B=bm? C=bm? l=im G=qm I=qm M=bm? O=qm S=qm U=im binary check compact-summary cumulative
203
205
  find-copies-harder full-index W|function-context w|ignore-all-space ignore-blank-lines
204
206
  ignore-cr-at-eol ignore-space-at-eol b|ignore-space-change D|irreversible-delete graph
@@ -228,12 +230,13 @@ module Squared
228
230
  theirs W|worktree conflict=b pathspec-from-file=p s|source=b].freeze,
229
231
  rev_parse: %w[absolute-git-dir all git-common-dir git-dir is-bare-repository is-inside-git-dir
230
232
  is-inside-work-tree is-shallow-repository local-env-vars no-revs not q|quiet revs-only
231
- shared-index-path show-cdup show-prefix show-superproject-working-tree show-toplevel sq sq-quote
232
- symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q branches=q? default=q
233
- disambiguate=b exclude=q exclude-hidden=b git-path=p glob=q path-format=b? prefix=q remotes=q?
234
- resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
235
- show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
236
- expand-tabs=i notes=q show-notes=q?].freeze,
233
+ shared-index-path show-cdup show-prefix show-ref-format show-superproject-working-tree
234
+ show-toplevel sq sq-quote symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q
235
+ branches=q? default=q disambiguate=b exclude=q exclude-hidden=b git-path=p glob=q
236
+ output-object-format=b path-format=b? prefix=q remotes=q? resolve-git-dir=p short=i?
237
+ show-object-format=b? since=q tags=q? until=q].freeze,
238
+ show: %w[t combined-all-paths no-diff-merges remerge-diff show-notes-by-default show-signature diff-merges=b
239
+ encoding=b expand-tabs=i notes=q show-notes=q?].freeze,
237
240
  stash: {
238
241
  common: %w[q|quiet].freeze,
239
242
  push: %w[a|all u|include-untracked k|keep-index no-keep-index no-include-untracked pathspec-file-nul
@@ -242,8 +245,8 @@ module Squared
242
245
  apply: %w[index].freeze
243
246
  }.freeze,
244
247
  status: %w[u|ignore-submodules=bm? ignored=b? untracked-files=b?],
245
- tag: %w[n=im cleanup=b create-reflog i|ignore-case color=b? column=b contains=b? format=q merged=b?
246
- no-contains=b? no-merged=b? points-at=q sort=q].freeze,
248
+ tag: %w[n=im cleanup=b create-reflog i|ignore-case omit-empty color=b? column=b contains=b? format=q merged=b?
249
+ no-contains=b? no-merged=b? points-at=q sort=q trailer=q].freeze,
247
250
  no: {
248
251
  branch: %w[color color-moved column track].freeze,
249
252
  checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
@@ -340,7 +343,7 @@ module Squared
340
343
  'restore' => %i[source staged worktree].freeze,
341
344
  'rev' => %i[commit build output].freeze,
342
345
  'show' => %i[format oneline textconv].freeze,
343
- 'stash' => %i[push pop apply branch drop clear list].freeze,
346
+ 'stash' => %i[push pop apply drop clear list].freeze,
344
347
  'switch' => %i[create detach merge].freeze,
345
348
  'tag' => %i[add sign delete list].freeze
346
349
  })
@@ -367,13 +370,13 @@ module Squared
367
370
  case action
368
371
  when 'pull', 'fetch'
369
372
  if flag == :remote
370
- format_desc action, flag, 'remote?,opts*'
373
+ format_desc action, flag, 'remote,opts*'
371
374
  task flag, [:remote] do |_, args|
372
375
  if (remote = args.remote)
373
376
  args = args.extras
374
377
  else
375
378
  remote = choice_remote
376
- args = args.to_a
379
+ args = args.to_a.drop(1)
377
380
  end
378
381
  __send__(action, flag, args, remote: remote)
379
382
  end
@@ -459,7 +462,6 @@ module Squared
459
462
  when 'stash'
460
463
  format_desc(action, flag, 'opts*', after: case flag
461
464
  when :push then 'pathspec*'
462
- when :branch then 'name,stash?|:'
463
465
  when :clear, :list then nil
464
466
  else 'stash?|:' end)
465
467
  task flag do |_, args|
@@ -914,7 +916,7 @@ module Squared
914
916
  cmd << '--autostash' if option('autostash')
915
917
  else
916
918
  cmd << '--autostash' if flag == :autostash
917
- if (val = option('rebase', ignore: false))
919
+ option('rebase', ignore: false) do |val|
918
920
  cmd << case val
919
921
  when '0', 'false'
920
922
  '--no-rebase'
@@ -928,7 +930,7 @@ module Squared
928
930
  source(sync: sync, sub: if verbose
929
931
  [
930
932
  { pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: color(:red), index: 4 },
931
- { pat: /^(.+)(\|\s+\d+\s+)(\++)(.*)$/, styles: color(:green), index: 3 }
933
+ { pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: color(:green), index: 3 }
932
934
  ]
933
935
  end, **threadargs)
934
936
  end
@@ -943,7 +945,7 @@ module Squared
943
945
  return unless upstream
944
946
 
945
947
  op = OptionPartition.new(opts, OPT_GIT[:rebase], cmd, project: self, no: OPT_GIT[:no][:rebase])
946
- cmd << upstream
948
+ cmd << shell_escape(upstream)
947
949
  append_head op.shift
948
950
  op.clear(pass: false)
949
951
  when :onto
@@ -951,7 +953,7 @@ module Squared
951
953
 
952
954
  cmd << '--interactive' if option('interactive', 'i')
953
955
  cmd << shell_option('onto', commit) if commit
954
- cmd << upstream
956
+ cmd << shell_escape(upstream)
955
957
  append_head branch
956
958
  else
957
959
  return unless VAL_GIT[:rebase][:send].include?(command)
@@ -977,23 +979,26 @@ module Squared
977
979
 
978
980
  cmd = git_session('clone', worktree: false)
979
981
  opts = data[1].dup
980
- if (val = option('depth', ignore: false))
982
+ option('depth', ignore: false) do |val|
981
983
  if (n = val.to_i) > 0
982
984
  opts[:depth] = n
983
985
  else
984
986
  opts.delete(:depth)
985
987
  end
986
988
  end
987
- opts[:origin] = val if (val = option('origin', ignore: false))
988
- if (val = option('branch', strict: true))
989
- opts[:branch] = val
989
+ option('origin', ignore: false) { |val| opts[:origin] = val }
990
+ if (branch = option('branch', strict: true))
991
+ opts[:branch] = branch
990
992
  opts.delete(:revision)
991
- elsif (val = option('revision', strict: true))
992
- opts[:revision] = val
993
- opts.delete(:branch)
994
- opts.delete(:mirror)
993
+ else
994
+ option('revision', strict: true) do |val|
995
+ opts[:revision] = val
996
+ opts.delete(:branch)
997
+ opts.delete(:mirror)
998
+ end
995
999
  end
996
- opts[:local] = val != '0' if (val = option('local', strict: true))
1000
+ option('local', strict: true) { |val| opts[:local] = val != '0' }
1001
+ option('bare') { |val| opts[:bare] = val }
997
1002
  opts.delete(:'recurse-submodules') || opts.delete(:'no-recurse-submodules') if append_submodules(from: :clone)
998
1003
  append_hash opts
999
1004
  cmd << '--quiet' unless verbose
@@ -1013,26 +1018,12 @@ module Squared
1013
1018
  case flag
1014
1019
  when :push
1015
1020
  append_pathspec op.extras
1016
- when :pop, :apply, :drop, :branch
1021
+ when :pop, :apply, :drop
1017
1022
  if op.extras.delete(':')
1018
- if flag == :branch
1019
- if op.empty?
1020
- values = [['Branch name', true]]
1021
- else
1022
- op << op.pop
1023
- end
1024
- end
1025
- out = choice_index('Choose a stash', git_spawn('stash list', stdout: false),
1026
- values: values, column: /^[^@]+@\{(\d+)\}/, force: true)
1027
- if values
1028
- op.merge(out.reverse)
1029
- else
1030
- op << out
1031
- end
1023
+ op << choice_index('Choose a stash', git_spawn('stash list', stdout: false),
1024
+ column: /^[^@]+@\{(\d+)\}/, force: true)
1032
1025
  elsif !op.empty?
1033
- op << op.pop
1034
- elsif flag == :branch
1035
- raise_error 'no branch name'
1026
+ op << shell_escape(op.pop)
1036
1027
  end
1037
1028
  op.clear
1038
1029
  when :clear
@@ -1059,7 +1050,7 @@ module Squared
1059
1050
  cmd = git_session 'status'
1060
1051
  cmd << (option('long') ? '--long' : '--short')
1061
1052
  cmd << '--branch' if option('branch')
1062
- if (val = option('ignore-submodules', ignore: false))
1053
+ option('ignore-submodules', ignore: false) do |val|
1063
1054
  cmd << basic_option('ignore-submodules', case val
1064
1055
  when '0', 'none'
1065
1056
  'none'
@@ -1080,7 +1071,7 @@ module Squared
1080
1071
  { pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
1081
1072
  { pat: /^([A-Z?!])(.+)$/, styles: g },
1082
1073
  { pat: /^(\?\?)(.+)$/, styles: r },
1083
- { pat: /^(## )(.+?)(\.{3})(.+)$/, styles: [nil, g, nil, r], index: -1 }
1074
+ { pat: /^(## )((?~\.{3}))(\.{3})(.+)$/, styles: [nil, g, nil, r], index: -1 }
1084
1075
  ]
1085
1076
  else
1086
1077
  [pat: /^(\t+)([a-z]+: +.+)$/, styles: r, index: 2]
@@ -1094,8 +1085,8 @@ module Squared
1094
1085
  def revbuild(flag = nil, opts = [], sync: nil, **kwargs)
1095
1086
  statusargs = lambda do
1096
1087
  {
1097
- include: relativepath(Array(kwargs[:include]), all: true),
1098
- exclude: relativepath(Array(kwargs[:exclude]), all: true)
1088
+ include: relativepath(as_a(kwargs[:include]), all: true),
1089
+ exclude: relativepath(as_a(kwargs[:exclude]), all: true)
1099
1090
  }
1100
1091
  end
1101
1092
  unless workspace.closed
@@ -1118,9 +1109,9 @@ module Squared
1118
1109
  args = op.to_a
1119
1110
  else
1120
1111
  args = []
1121
- args << basic_option('untracked-files', flag) if (flag = option('untracked-files', prefix: 'git'))
1122
- args << basic_option('ignore-submodules', flag) if (flag = option('ignore-submodules', prefix: 'git'))
1123
- args << basic_option('ignored', flag) if (flag = option('ignored', prefix: 'git'))
1112
+ option('untracked-files', prefix: 'git') { |val| args << basic_option('untracked-files', val) }
1113
+ option('ignore-submodules', prefix: 'git') { |val| args << basic_option('ignore-submodules', val) }
1114
+ option('ignored', prefix: 'git') { |val| args << basic_option('ignored', val) }
1124
1115
  end
1125
1116
  if (cur = workspace.rev_entry(name)) && cur['revision'] == sha && !env('REVBUILD_FORCE')
1126
1117
  files = status_digest(*args, **kwargs)
@@ -1204,14 +1195,13 @@ module Squared
1204
1195
  else
1205
1196
  op = OptionPartition.new(opts, OPT_GIT[:checkout], cmd, project: self, no: OPT_GIT[:no][:checkout],
1206
1197
  first: flag == :path ? matchpathspec : nil)
1207
- if flag == :path
1198
+ if flag == :commit
1199
+ op.append(commit)
1200
+ .clear(pass: false)
1201
+ else
1208
1202
  append_head
1209
1203
  append_pathspec(op.extras, pass: false)
1210
- print_success if success?(source)
1211
- return
1212
1204
  end
1213
- op.append(commit)
1214
- .clear(pass: false)
1215
1205
  end
1216
1206
  source
1217
1207
  end
@@ -1244,16 +1234,16 @@ module Squared
1244
1234
  list_result(ret, 'tags', from: from, grep: op.extras)
1245
1235
  return
1246
1236
  end
1247
- remote ||= option('remote')
1237
+ remote ||= option 'remote'
1248
1238
  source
1249
1239
  git_spawn('push', flag == :delete ? '-d' : nil, remote, *refs.map { |val| shell_quote(val) }) if remote
1250
1240
  end
1251
1241
 
1252
1242
  def log!(flag, opts = [], range: [], index: [])
1253
1243
  cmd, opts = git_session('log', opts: opts)
1254
- op = OptionPartition.new(opts, collect_hash(OPT_GIT[:log]), cmd, project: self,
1255
- no: collect_hash(OPT_GIT[:no][:log]),
1256
- first: matchpathspec)
1244
+ op = OptionPartition.new(opts, collect_hash(OPT_GIT[:log]), cmd,
1245
+ project: self, no: collect_hash(OPT_GIT[:no][:log]),
1246
+ first: matchpathspec)
1257
1247
  case flag
1258
1248
  when :between, :contain
1259
1249
  op << shell_quote(range.join(flag == :between ? '..' : '...'))
@@ -1411,12 +1401,12 @@ module Squared
1411
1401
  stdout = false
1412
1402
  case flag
1413
1403
  when :create
1414
- if (arg = option('track', ignore: false))
1415
- cmd << case arg
1404
+ option('track', ignore: false) do |val|
1405
+ cmd << case val
1416
1406
  when '0', 'false'
1417
1407
  '--no-track'
1418
1408
  when 'direct', 'inherit'
1419
- basic_option('track', arg)
1409
+ basic_option 'track', val
1420
1410
  else
1421
1411
  '--track'
1422
1412
  end
@@ -1438,7 +1428,7 @@ module Squared
1438
1428
  remote&.each do |val|
1439
1429
  source git_output('push', '--delete', *val.split('/', 2).map { |s| shell_quote(s) })
1440
1430
  end
1441
- force, list = refs.partition { |val| val.match?(/^[~^]/) }
1431
+ force, list = refs.partition { |val| val.start_with?(/[~^]/) }
1442
1432
  force.each do |val|
1443
1433
  dr = val[0, 2]
1444
1434
  d = dr.include?('^') ? '-D' : '-d'
@@ -1484,7 +1474,7 @@ module Squared
1484
1474
  data = line.sub(/^\*\s+/, '').split(/\s+/)
1485
1475
  a = sub_style(data[0], styles: theme[:inline])
1486
1476
  b = sub_style(data[1], styles: theme[:extra])
1487
- r = /\A(?:\[(.+?)(?=\]\s)\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
1477
+ r = /\A(?:\[((?~\]\s))\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
1488
1478
  if (r1 = r[1]) && r1 =~ /^(.+):(?: ([a-z]+) (\d+),)? ([a-z]+) (\d+)$/
1489
1479
  write = ->(s1, s2) { "#{s1.capitalize.rjust(7)}: #{sub_style(s2, styles: theme[:warn])}" }
1490
1480
  r1 = $1
@@ -1528,7 +1518,7 @@ module Squared
1528
1518
  when 'y', 'Y', '1', 'true'
1529
1519
  '--track'
1530
1520
  when 'direct', 'inherit'
1531
- basic_option('track', track)
1521
+ basic_option 'track', track
1532
1522
  end
1533
1523
  when :detach, :merge
1534
1524
  cmd << "--#{flag}"
@@ -1564,7 +1554,7 @@ module Squared
1564
1554
  when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
1565
1555
  cmd << basic_option('format', val)
1566
1556
  else
1567
- if format.match?(/^t?format:/) || format.include?('%')
1557
+ if format.start_with?(/t?format:/) || format.include?('%')
1568
1558
  cmd << quote_option('pretty', format)
1569
1559
  else
1570
1560
  opts << format
@@ -1640,20 +1630,19 @@ module Squared
1640
1630
  red = color(:red)
1641
1631
  grep.map! { |val| Regexp.new(val[1..-2]) }
1642
1632
  files = status_data.map! do |a, b|
1643
- next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
1633
+ next unless grep.empty? || grep.any? { |pat| pat.match?(a) }
1644
1634
 
1645
1635
  "#{sub_style(b, styles: red)} #{a}"
1646
1636
  end
1647
1637
  .compact
1648
1638
  unless files.empty?
1649
1639
  files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/,
1650
- accept: [['Add?', false, true]])
1640
+ accept: 'Add?')
1651
1641
  end
1652
1642
  op.swap(list + files)
1653
1643
  end
1654
1644
  end
1655
- return source(git_session('status', '-s'), banner: false) unless append_pathspec(op.extras)
1656
-
1645
+ append_pathspec op.extras
1657
1646
  verbose = flag == :add && !op.arg?('verbose')
1658
1647
  print_success if success?(source) && verbose
1659
1648
  return
@@ -1682,36 +1671,30 @@ module Squared
1682
1671
  private
1683
1672
 
1684
1673
  def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
1685
- multiple: false, from: nil, **kwargs)
1674
+ multiple: false, **kwargs)
1686
1675
  cmd = cmd.target if cmd.is_a?(OptionPartition)
1687
- if io && banner == false
1688
- from = nil
1689
- banner = nil
1690
- else
1691
- banner = nil if banner && (multiple || !banner?)
1692
- if cmd.respond_to?(:done)
1693
- if from.nil? && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z\-]*\z/) })
1694
- from = :"git:#{from}"
1695
- end
1696
- banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
1676
+ banner = nil if banner && (multiple || !banner?)
1677
+ if cmd.respond_to?(:done)
1678
+ if io && banner == false
1679
+ from = nil
1680
+ elsif !from && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z\-]*\z/) })
1681
+ from = :"git:#{from}"
1697
1682
  end
1698
- from = nil if from == false
1683
+ banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
1699
1684
  end
1700
1685
  cmd = session_done cmd
1701
1686
  log&.info cmd
1687
+ on :first, from
1702
1688
  banner = if banner
1703
1689
  format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
1704
1690
  end
1705
- on :first, from
1706
1691
  begin
1707
1692
  if io
1708
- ret = if stdout
1709
- `#{cmd}`
1710
- else
1711
- banner ? [IO.popen(cmd), banner, from] : IO.popen(cmd)
1712
- end
1713
- return ret
1714
- elsif stdin? ? sync : stdout
1693
+ return `#{cmd}` if stdout
1694
+
1695
+ return banner ? [IO.popen(cmd), banner, from] : IO.popen(cmd)
1696
+ end
1697
+ if stdin? ? sync : stdout
1715
1698
  print_item banner unless multiple
1716
1699
  ret = `#{cmd}`
1717
1700
  if !ret.empty?
@@ -1719,7 +1702,7 @@ module Squared
1719
1702
  elsif success?(!banner.nil?)
1720
1703
  print_success
1721
1704
  end
1722
- elsif !kwargs[:sub] && (sync || (!exception && !stderr))
1705
+ elsif sync || (!exception && !stderr)
1723
1706
  print_item banner unless multiple
1724
1707
  ret = shell(cmd, exception: exception)
1725
1708
  else
@@ -1912,19 +1895,13 @@ module Squared
1912
1895
  def append_pathspec(files = [], target: @session, expect: false, parent: false, pass: true)
1913
1896
  if session_arg?('pathspec-from-file', target: target)
1914
1897
  option_clear files
1915
- true
1916
1898
  else
1917
- if files.empty? && (val = option('pathspec', target: target))
1918
- files = split_escape val
1919
- end
1899
+ option('pathspec', target: target) { |val| files = split_escape val } if files.empty?
1920
1900
  files = projectmap(files, parent: parent, pass: pass)
1921
1901
  if !files.empty?
1922
1902
  target << '--' << files.join(' ')
1923
- true
1924
1903
  elsif expect
1925
1904
  raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree')
1926
- else
1927
- false
1928
1905
  end
1929
1906
  end
1930
1907
  end
@@ -1941,36 +1918,34 @@ module Squared
1941
1918
  end
1942
1919
 
1943
1920
  def append_submodules(target: @session, from: nil)
1944
- return unless (val = option('recurse-submodules', target: target, ignore: false))
1945
-
1946
- if from == :clone
1947
- case val
1948
- when '0', 'false'
1949
- target << '--no-recurse-submodules'
1950
- when '1', 'true'
1951
- target << '--recurse-submodules'
1952
- else
1953
- projectmap(split_escape(val)).each do |path|
1954
- target << basic_option('recurse-submodules', path)
1921
+ option('recurse-submodules', target: target, ignore: false) do |val|
1922
+ if from == :clone
1923
+ case val
1924
+ when '0', 'false'
1925
+ target << '--no-recurse-submodules'
1926
+ when '1', 'true'
1927
+ target << '--recurse-submodules'
1928
+ else
1929
+ projectmap(split_escape(val)).each do |path|
1930
+ target << basic_option('recurse-submodules', path)
1931
+ end
1955
1932
  end
1933
+ else
1934
+ target << case val
1935
+ when 'no', '0', 'false'
1936
+ '--no-recurse-submodules'
1937
+ when 'yes', 'on-demand'
1938
+ "--recurse-submodules=#{val}"
1939
+ else
1940
+ '--recurse-submodules'
1941
+ end
1956
1942
  end
1957
- else
1958
- target << case val
1959
- when 'no', '0', 'false'
1960
- '--no-recurse-submodules'
1961
- when 'yes', 'on-demand'
1962
- "--recurse-submodules=#{val}"
1963
- else
1964
- '--recurse-submodules'
1965
- end
1966
1943
  end
1967
1944
  end
1968
1945
 
1969
1946
  def foreachref(path, *args, format: nil)
1970
- path = Array(path).map! { |val| "refs/#{val}" }
1971
- format &&= quote_option('format', format)
1972
- ret = git_spawn('for-each-ref', format, *args, *path, stdout: workspace.windows?)
1973
- ret.is_a?(String) ? ret.lines : ret
1947
+ path = as_a(path).map! { |val| "refs/#{val}" }
1948
+ git_spawn('for-each-ref', format && quote_option('format', format), *args, *path, stdout: false)
1974
1949
  end
1975
1950
 
1976
1951
  def git_session(*cmd, opts: nil, worktree: true, **kwargs)
@@ -2008,23 +1983,22 @@ module Squared
2008
1983
 
2009
1984
  def repotrack(origin, branch, quote: true)
2010
1985
  i = origin.index('/')
2011
- branch = "#{branch}:#{origin[(i + 1)..-1]}" unless origin.end_with?("/#{branch}")
2012
- ret = [origin[0..(i - 1)], branch]
2013
- quote ? ret.map! { |val| shell_quote(val) } : ret
1986
+ branch = "#{branch}:#{origin[i + 1..-1]}" unless origin.end_with?("/#{branch}")
1987
+ [origin[0..i - 1], branch].tap { |ret| ret.map! { |val| shell_quote(val) } if quote }
2014
1988
  end
2015
1989
 
2016
1990
  def commithash(val)
2017
- val[/\A:(\h{5,40})\z/, 1] || val[/\A#\{(\h{5,40})\}\z/, 1]
1991
+ val[/\A:(\h{5,40})\z/, 1]
2018
1992
  end
2019
1993
 
2020
1994
  def commithead(val)
2021
1995
  return val unless (s = matchhead(val))
2022
1996
 
2023
- s.match?(/^\d/) ? "@~#{s}" : "@#{s}"
1997
+ s.start_with?(/\d/) ? "@~#{s}" : "@#{s}"
2024
1998
  end
2025
1999
 
2026
2000
  def matchhead(val)
2027
- val && val =~ /^(?:(?:HEAD|@)([~^]\d*)?|H(\d+))$/ ? $2 || $1 || '' : nil
2001
+ val =~ /^(?:(?:HEAD|@)([~^]\d*)?|H(\d+))$/ ? $2 || $1 || '' : nil
2028
2002
  end
2029
2003
 
2030
2004
  def matchpathspec