squared 0.4.19 → 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.
@@ -3,8 +3,8 @@
3
3
  module Squared
4
4
  module Workspace
5
5
  module Git
6
- GIT_REPO = Support.hashobj
7
- GIT_PROTO = %r{\A(https?|ssh|git|file)://}i.freeze
6
+ GIT_REPO = {}
7
+ GIT_PROTO = %r{^(?:https?|ssh|git|file)://}i.freeze
8
8
  private_constant :GIT_REPO, :GIT_PROTO
9
9
 
10
10
  attr_reader :revfile
@@ -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
@@ -58,8 +58,8 @@ module Squared
58
58
  end
59
59
  end
60
60
  key = task_name key
61
- GIT_REPO[main][key] = [uri.to_s, opts]
62
- @kind[key] << Project::Git
61
+ (GIT_REPO[main] ||= {})[key] = [uri.to_s, opts]
62
+ (@kind[key] ||= []) << Project::Git
63
63
  end
64
64
  if cache == true
65
65
  revbuild
@@ -74,7 +74,7 @@ module Squared
74
74
  @revdoc = JSON.parse(@revfile.read) if @revfile.exist?
75
75
  rescue StandardError => e
76
76
  @revfile = nil
77
- warn log_message(Logger::WARN, e, pass: true)
77
+ warn log_message(Logger::WARN, e, pass: true) if @warning
78
78
  self
79
79
  else
80
80
  @revdoc = {} unless @revdoc.is_a?(Hash)
@@ -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
@@ -179,9 +181,6 @@ module Squared
179
181
  }.freeze,
180
182
  git: {
181
183
  add: %w[N|intent-to-add refresh].freeze,
182
- blame: %w[b c l s t w C=im? L=q M=im? S=p color-by-age color-lines first-parent incremental line-porcelain
183
- p|porcelain root score-debug f|show-name e|show-email n|show-number show-stats abbrev=i
184
- contents=p date=q encoding=b ignore-rev=b ignore-revs-file=p reverse=q].freeze,
185
184
  clean: %w[d x X f|force n|dry-run i|interactive q|quiet e|exclude=q].freeze,
186
185
  mv: %w[k f|force n|dry-run v|verbose].freeze,
187
186
  revert: %w[e S=bm? abort continue n|no-commit quit reference skip cleanup=b gpg-sign=b? m|mainline=i
@@ -199,9 +198,9 @@ module Squared
199
198
  branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
200
199
  exclude-hidden=b glob=q grep=q grep-reflog=q n|max-count=i max-parents=i min-parents=i no-walk=b?
201
200
  remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
202
- format: %w[t children combined-all-paths oneline left-right no-diff-merges parents relative-date
203
- show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=b pretty=q?
204
- 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,
205
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
206
205
  find-copies-harder full-index W|function-context w|ignore-all-space ignore-blank-lines
207
206
  ignore-cr-at-eol ignore-space-at-eol b|ignore-space-change D|irreversible-delete graph
@@ -231,12 +230,13 @@ module Squared
231
230
  theirs W|worktree conflict=b pathspec-from-file=p s|source=b].freeze,
232
231
  rev_parse: %w[absolute-git-dir all git-common-dir git-dir is-bare-repository is-inside-git-dir
233
232
  is-inside-work-tree is-shallow-repository local-env-vars no-revs not q|quiet revs-only
234
- shared-index-path show-cdup show-prefix show-superproject-working-tree show-toplevel sq sq-quote
235
- symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q branches=q? default=q
236
- disambiguate=b exclude=q exclude-hidden=b git-path=p glob=q path-format=b? prefix=q remotes=q?
237
- resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
238
- show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
239
- 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,
240
240
  stash: {
241
241
  common: %w[q|quiet].freeze,
242
242
  push: %w[a|all u|include-untracked k|keep-index no-keep-index no-include-untracked pathspec-file-nul
@@ -244,21 +244,10 @@ module Squared
244
244
  pop: %w[index].freeze,
245
245
  apply: %w[index].freeze
246
246
  }.freeze,
247
- status: %w[z u=bm? b|branch long s|short show-stash v|verbose column=b find-renames=i? ignore-submodules=b?
248
- ignored=b? porcelain=b? untracked-files=b?].freeze,
249
- submodule: {
250
- status: %w[cached recursive].freeze,
251
- update: %w[checkout f|force init merge N|no-fetch no-recommend-shallow no-single-branch recommend-shallow
252
- rebase recursive remote single-branch depth=i filter=q jobs=i reference=b ref-format=q].freeze,
253
- branch: %w[b|branch d|default].freeze,
254
- sync: %w[recursive].freeze
255
- }.freeze,
256
- switch: %w[d|detach discard-changes f|force ignore-other-worktrees m|merge q|quiet conflict=b c|create=q
257
- C|force-create=q orphan=q t|track=b].freeze,
258
- tag: %w[n=im cleanup=b create-reflog i|ignore-case color=b? column=b contains=b? format=q merged=b?
259
- no-contains=b? no-merged=b? points-at=q sort=q].freeze,
247
+ status: %w[u|ignore-submodules=bm? ignored=b? untracked-files=b?],
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,
260
250
  no: {
261
- blame: %w[progress].freeze,
262
251
  branch: %w[color color-moved column track].freeze,
263
252
  checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
264
253
  fetch: {
@@ -280,8 +269,6 @@ module Squared
280
269
  rev_parse: %w[flags].freeze,
281
270
  revert: %w[edit gpg-sign rerere-autoupdate].freeze,
282
271
  show: %w[standard-notes].freeze,
283
- status: %w[ahead-behind column renames].freeze,
284
- switch: %w[guess progress recurse-submodules track].freeze,
285
272
  tag: %w[column].freeze
286
273
  }.freeze
287
274
  }.freeze
@@ -301,10 +288,12 @@ module Squared
301
288
  include Rake::DSL
302
289
 
303
290
  def populate(ws, **)
304
- return if ws.series.exclude?(:pull, true) || ws.size == 1
291
+ return if ws.series.exclude?(:pull, true)
292
+
293
+ namespace(name = ws.task_name('git')) do
294
+ all = ws.task_join(name, 'all')
305
295
 
306
- namespace ws.task_name('git') do |ns|
307
- ws.format_desc(all = ws.task_join(ns.scope.path, 'all'), 'stash|rebase|autostash?,depend?')
296
+ ws.format_desc(all, 'stash|rebase|autostash?,depend?')
308
297
  task 'all' do |_, args|
309
298
  args = args.to_a
310
299
  cmd = if args.include?('stash')
@@ -321,7 +310,6 @@ module Squared
321
310
  cmd << ws.task_sync('build')
322
311
  Common::Utils.task_invoke(*cmd, **ws.invokeargs)
323
312
  end
324
-
325
313
  ws.series.sync << all
326
314
  ws.series.multiple << all
327
315
  end
@@ -343,27 +331,25 @@ module Squared
343
331
  'checkout' => %i[commit branch track detach path].freeze,
344
332
  'commit' => %i[add all amend amend-orig fixup].freeze,
345
333
  'diff' => %i[head branch files view between contain].freeze,
346
- 'fetch' => %i[origin remote all].freeze,
334
+ 'fetch' => %i[origin remote].freeze,
347
335
  'files' => %i[cached modified deleted others].freeze,
348
- 'git' => %i[add blame clean mv revert rm status].freeze,
336
+ 'git' => %i[add clean mv revert rm].freeze,
349
337
  'log' => %i[view between contain].freeze,
350
338
  'merge' => %i[commit no-commit send].freeze,
351
- 'pull' => %i[origin remote all].freeze,
339
+ 'pull' => %i[origin remote].freeze,
352
340
  'rebase' => %i[branch onto send].freeze,
353
341
  'refs' => %i[heads tags remote].freeze,
354
- 'reset' => %i[commit index patch mode undo].freeze,
342
+ 'reset' => %i[commit index patch mode].freeze,
355
343
  'restore' => %i[source staged worktree].freeze,
356
344
  'rev' => %i[commit build output].freeze,
357
345
  'show' => %i[format oneline textconv].freeze,
358
- 'stash' => %i[push pop apply branch drop clear list].freeze,
359
- 'submodule' => %i[status update branch url sync].freeze,
360
- 'switch' => %i[branch create detach].freeze,
346
+ 'stash' => %i[push pop apply drop clear list].freeze,
347
+ 'switch' => %i[create detach merge].freeze,
361
348
  'tag' => %i[add sign delete list].freeze
362
349
  })
363
350
 
364
351
  def initialize(*, **)
365
352
  super
366
- @submodule = basepath('.gitmodules').exist?
367
353
  initialize_ref Git.ref if gitpath.exist?
368
354
  end
369
355
 
@@ -373,56 +359,33 @@ module Squared
373
359
 
374
360
  def populate(*, **)
375
361
  super
376
- return unless ref?(Git.ref) || @only
362
+ return unless ref?(Git.ref)
377
363
 
378
364
  namespace name do
379
365
  Git.subtasks do |action, flags|
380
- next if task_pass?(action)
366
+ next if @pass.include?(action)
381
367
 
382
368
  namespace action do
383
369
  flags.each do |flag|
384
370
  case action
385
371
  when 'pull', 'fetch'
386
372
  if flag == :remote
387
- format_desc action, flag, 'remote?,opts*'
373
+ format_desc action, flag, 'remote,opts*'
388
374
  task flag, [:remote] do |_, args|
389
375
  if (remote = args.remote)
390
376
  args = args.extras
391
377
  else
392
378
  remote = choice_remote
393
- args = args.to_a
379
+ args = args.to_a.drop(1)
394
380
  end
395
381
  __send__(action, flag, args, remote: remote)
396
382
  end
397
383
  else
398
- format_desc(action, flag, 'opts*', after: flag == :all && action == 'pull' ? 'pattern*' : nil)
384
+ format_desc action, flag, 'opts*'
399
385
  task flag do |_, args|
400
386
  __send__ action, flag, args.to_a
401
387
  end
402
388
  end
403
- when 'submodule'
404
- break unless @submodule
405
-
406
- case flag
407
- when :branch
408
- format_desc action, flag, 'path,opts*'
409
- task flag, [:path] do |_, args|
410
- path = param_guard(action, flag, args: args, key: :path)
411
- submodule(flag, args.extras, path: path)
412
- end
413
- when :url
414
- format_desc action, flag, 'path,url,opts*'
415
- task flag, [:path, :url] do |_, args|
416
- path = param_guard(action, flag, args: args, key: :path)
417
- url = param_guard(action, flag, args: args, key: :url)
418
- submodule(flag, args.extras, path: path, url: url)
419
- end
420
- else
421
- format_desc action, flag, 'opts*,path*'
422
- task flag do |_, args|
423
- submodule flag, args.to_a
424
- end
425
- end
426
389
  when 'commit'
427
390
  case flag
428
391
  when :all
@@ -436,12 +399,12 @@ module Squared
436
399
  if flag == :fixup
437
400
  ref, squash, pick = choice_commit(accept: [['Auto squash?', true]], reflog: false,
438
401
  values: ['Pick [amend|reword]'])
439
- pick &&= case pick.downcase
440
- when 'a', 'amend'
441
- 'amend'
442
- when 'r', 'reword'
443
- 'reword'
444
- end
402
+ pick = case pick&.downcase
403
+ when 'a', 'amend'
404
+ 'amend'
405
+ when 'r', 'reword'
406
+ 'reword'
407
+ end
445
408
  if squash
446
409
  found = false
447
410
  git_spawn(git_output('log --format=%h'), stdout: false).each do |val|
@@ -453,14 +416,12 @@ module Squared
453
416
  end
454
417
  end
455
418
  end
456
- opts = []
457
- refs = []
458
- unless pick == 'reword'
459
- if flag == :add
460
- opts = param_guard(action, flag, args: args.to_a)
461
- elsif (refs = args.to_a).empty?
462
- refs = readline('Enter file patterns', force: true).shellsplit
463
- end
419
+ refs = pick == 'reword' ? [] : param_guard(action, flag, args: args.to_a)
420
+ if flag == :add
421
+ opts = refs
422
+ refs = []
423
+ else
424
+ opts = []
464
425
  end
465
426
  commit(flag, opts, refs: refs, ref: ref, squash: squash, pick: pick)
466
427
  end
@@ -500,11 +461,9 @@ module Squared
500
461
  end
501
462
  when 'stash'
502
463
  format_desc(action, flag, 'opts*', after: case flag
503
- when :push then 'pathspec*,:'
504
- when :branch then 'name,stash?|:'
464
+ when :push then 'pathspec*'
505
465
  when :clear, :list then nil
506
- else 'stash?|:'
507
- end)
466
+ else 'stash?|:' end)
508
467
  task flag do |_, args|
509
468
  stash flag, args.to_a
510
469
  end
@@ -624,12 +583,12 @@ module Squared
624
583
  format_desc action, flag, 'ref,opts*'
625
584
  task flag, [:commit] do |_, args|
626
585
  commit = commithead args.commit
627
- args = if commit
628
- args.extras
629
- else
630
- commit, opts = choice_commit(values: ['Options'])
631
- OptionPartition.strip(opts)
632
- end
586
+ if commit
587
+ args = args.extras
588
+ else
589
+ commit, opts = choice_commit(values: ['Options'])
590
+ args = OptionPartition.strip(opts)
591
+ end
633
592
  checkout(flag, args, commit: commit)
634
593
  end
635
594
  when :detach
@@ -719,10 +678,10 @@ module Squared
719
678
  when :create
720
679
  format_desc action, flag, '(^)name,ref?=HEAD|:'
721
680
  task flag, [:name, :commit] do |_, args|
722
- branch = param_guard(action, flag, args: args, key: :name)
681
+ target = param_guard(action, flag, args: args, key: :name)
723
682
  commit = commithead args.commit
724
683
  commit, track = choice_commit(values: ['Track? [Y|n]'], force: false) if commit == ':'
725
- switch(flag, branch: branch, commit: commit, track: track)
684
+ switch(flag, target: target, commit: commit, track: track)
726
685
  end
727
686
  when :detach
728
687
  format_desc action, flag, 'ref?=HEAD'
@@ -730,16 +689,11 @@ module Squared
730
689
  commit = commithead(args.commit) || choice_commit(force: false)
731
690
  switch(flag, commit: commit)
732
691
  end
733
- when :branch
734
- format_desc action, flag, 'name|:,opts*'
735
- task flag, [:name] do |_, args|
736
- if (branch = args.name)
737
- args = args.extras
738
- branch = nil if branch == ':'
739
- else
740
- args = []
741
- end
742
- switch(flag, args, branch: branch || choice_refs('Choose a branch'))
692
+ when :merge
693
+ format_desc action, flag, 'branch?'
694
+ task flag, [:branch] do |_, args|
695
+ commit = args.branch || choice_refs('Choose a branch')
696
+ switch(flag, commit: commit)
743
697
  end
744
698
  end
745
699
  when 'reset'
@@ -756,15 +710,14 @@ module Squared
756
710
  when 'h', 'hard' then ['hard']
757
711
  when 's', 'soft' then ['soft']
758
712
  when 'n', 'N' then ['mixed', 'N']
759
- else ['mixed']
760
- end)
713
+ else ['mixed'] end)
761
714
  end
762
715
  print_success if success?(reset(flag, args, commit: commit))
763
716
  end
764
- when :index, :undo
765
- format_desc(action, flag, flag == :index ? 'opts*,pathspec*' : nil)
717
+ when :index
718
+ format_desc action, flag, 'opts*,pathspec*'
766
719
  task flag do |_, args|
767
- reset(flag, flag == :index ? args.to_a : [])
720
+ reset flag, args.to_a
768
721
  end
769
722
  when :mode
770
723
  format_desc action, flag, 'mode,ref?=HEAD|:'
@@ -806,28 +759,28 @@ module Squared
806
759
  when :branch
807
760
  format_desc action, flag, 'upstream,branch?=HEAD,opts*'
808
761
  task flag, [:upstream] do |_, args|
809
- args = if (upstream = args.upstream)
810
- args.extras
811
- else
812
- upstream, opts = choice_refs('Choose upstream branch', values: ['Options'])
813
- OptionPartition.strip(opts)
814
- end
762
+ if (upstream = args.upstream)
763
+ args = args.extras
764
+ else
765
+ upstream, opts = choice_refs('Choose upstream branch', values: ['Options'])
766
+ args = OptionPartition.strip(opts)
767
+ end
815
768
  rebase(flag, args, upstream: upstream)
816
769
  end
817
770
  when :onto
818
771
  format_desc action, flag, 'ref,upstream,branch?=HEAD'
819
772
  task flag, [:commit, :upstream, :branch] do |_, args|
820
773
  commit = commithead args.commit
821
- args = if commit
822
- upstream = param_guard(action, flag, args: args, key: :upstream)
823
- branch = args.branch
824
- []
825
- else
826
- commit = choice_refs 'Choose "onto" branch'
827
- target, opts = choice_commit(multiple: 2, values: ['Options'], reflog: false)
828
- branch, upstream = target
829
- OptionPartition.strip(opts)
830
- end
774
+ if commit
775
+ upstream = param_guard(action, flag, args: args, key: :upstream)
776
+ branch = args.branch
777
+ args = []
778
+ else
779
+ commit = choice_refs 'Choose "onto" branch'
780
+ target, opts = choice_commit(multiple: 2, values: ['Options'], reflog: false)
781
+ branch, upstream = target
782
+ args = OptionPartition.strip(opts)
783
+ end
831
784
  rebase(flag, args, commit: commit, upstream: upstream, branch: branch)
832
785
  end
833
786
  when :commit, :'no-commit'
@@ -863,7 +816,7 @@ module Squared
863
816
  rev_parse(flag, ref: ref, size: size)
864
817
  end
865
818
  when :build
866
- format_desc action, flag, 'opts*'
819
+ format_desc action, flag, OPT_GIT[:status]
867
820
  task flag do |_, args|
868
821
  revbuild flag, args.to_a
869
822
  end
@@ -880,7 +833,7 @@ module Squared
880
833
  ls_remote(flag, args.extras, remote: args.remote)
881
834
  end
882
835
  else
883
- format_desc(action, flag, 'opts*,pattern*', after: action == 'files' ? 'pathspec*' : nil)
836
+ format_desc action, flag, 'opts*,pattern*'
884
837
  task flag do |_, args|
885
838
  __send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
886
839
  end
@@ -891,13 +844,13 @@ module Squared
891
844
  format_desc action, flag, 'ref,opts*,pathspec*'
892
845
  task flag, [:commit] do |_, args|
893
846
  commit = commithead args.commit
894
- args = if commit
895
- args.extras
896
- else
897
- commit, opts, files = choice_commit(values: ['Options', ['Pathspec', true]])
898
- files = files&.shellsplit
899
- OptionPartition.strip(opts)
900
- end
847
+ if commit
848
+ args = args.extras
849
+ else
850
+ commit, opts, files = choice_commit(values: ['Options', ['Pathspec', true]])
851
+ args = OptionPartition.strip(opts)
852
+ files = files&.shellsplit
853
+ end
901
854
  restore(flag, args, commit: commit, files: files)
902
855
  end
903
856
  when :staged, :worktree
@@ -906,14 +859,19 @@ module Squared
906
859
  args = args.to_a
907
860
  if args.empty? || args.last == ':'
908
861
  files = []
909
- status_data.each { |row| files << row[0] if row[flag == :staged ? 2 : 1].match?(/[AMDRTC]/) }
862
+ status_data.each do |line|
863
+ case (flag == :staged ? line[2] : line[1])
864
+ when /[AMDRTC]/
865
+ files << line[0]
866
+ end
867
+ end
910
868
  unless files.empty?
911
869
  files = choice_index('Select a file', files, multiple: true, force: false,
912
870
  accept: 'Restore?')
913
871
  end
914
872
  args.pop
915
873
  args, glob = args.partition { |val| val.match?(/^(?:[a-z-]+=|[^*]+$)/) }
916
- files.concat(glob)
874
+ (files ||= []).concat(glob)
917
875
  next if args.empty? && files.empty?
918
876
  end
919
877
  restore(flag, args, files: files)
@@ -921,18 +879,13 @@ module Squared
921
879
  end
922
880
  when 'git'
923
881
  before = case flag
924
- when :blame then 'file'
925
882
  when :mv then 'source+,destination'
926
- when :revert then 'commit+'
927
- end
883
+ when :revert then 'commit+' end
928
884
  format_desc(action, flag, 'opts*', before: before, after: case flag
929
- when :add
930
- 'pathspec*,pattern*'
931
- when :clean, :rm, :status
932
- 'pathspec*'
933
- end)
885
+ when :add then 'pathspec*|:pattern:*'
886
+ when :clean, :rm then 'pathspec*' end)
934
887
  task flag do |_, args|
935
- __send__(flag == :status ? :status : :git, flag, args.to_a)
888
+ git flag, args.to_a
936
889
  end
937
890
  end
938
891
  end
@@ -956,13 +909,14 @@ module Squared
956
909
  super
957
910
  end
958
911
 
959
- def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil, hint: nil)
912
+ def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil)
960
913
  cmd, opts = git_session('pull', opts: opts)
961
- cmd << '--autostash' if option('autostash')
962
914
  if flag == :rebase
963
915
  cmd << '--rebase'
916
+ cmd << '--autostash' if option('autostash')
964
917
  else
965
- if (val = option('rebase', ignore: false))
918
+ cmd << '--autostash' if flag == :autostash
919
+ option('rebase', ignore: false) do |val|
966
920
  cmd << case val
967
921
  when '0', 'false'
968
922
  '--no-rebase'
@@ -970,52 +924,15 @@ module Squared
970
924
  VAL_GIT[:rebase][:value].include?(val) ? basic_option('rebase', val) : '--rebase'
971
925
  end
972
926
  end
973
- case flag
974
- when :all
975
- unless git_spawn('status -s -z --untracked-files=all').empty?
976
- if confirm('Stash local changes? [Y/n] ', 'Y')
977
- git_spawn 'stash push --keep-index --quiet'
978
- elsif !(force = confirm('Force checkout? [y/N] ', 'N'))
979
- return
980
- end
981
- printsucc
982
- end
983
- op = OptionPartition.new(opts, OPT_GIT[:pull], cmd, project: self, no: OPT_GIT[:no][:pull])
984
- reg = if op.empty?
985
- []
986
- else
987
- opts = op.uniq(opts)
988
- matchmap op
989
- end
990
- session_done op.target
991
- heads = []
992
- cur = nil
993
- foreachref('heads', format: '%(if)%(HEAD)%(then)* %(end)%(refname:short)').each do |line|
994
- line.chomp!
995
- cur ||= line.delete_prefix!('* ')
996
- heads << line if matchany?(line, reg)
997
- end
998
- raise_error('head not found', hint: 'for-each-ref') unless cur
999
- opts << 'ff-only' if opts.empty? && !option('ff-only', equals: '0')
1000
- (heads.dup << cur).each_with_index do |branch, index|
1001
- next unless (index < heads.size && cur != branch) || index == heads.size
1002
-
1003
- git_spawn 'switch --quiet', force && '--force', shell_quote(branch)
1004
- pull(nil, opts, sync: false, hint: branch) if heads.include?(branch)
1005
- end
1006
- return
1007
- when :autostash
1008
- cmd << '--autostash'
1009
- end
1010
927
  end
1011
928
  append_pull(opts, OPT_GIT[:pull] + OPT_GIT[:fetch][:pull],
1012
929
  no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag, from: :pull)
1013
- source(sync: sync, sub: if stdout?
930
+ source(sync: sync, sub: if verbose
1014
931
  [
1015
932
  { pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: color(:red), index: 4 },
1016
- { pat: /^(.+)(\|\s+\d+\s+)(\++)(.*)$/, styles: color(:green), index: 3 }
933
+ { pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: color(:green), index: 3 }
1017
934
  ]
1018
- end, hint: hint, **threadargs)
935
+ end, **threadargs)
1019
936
  end
1020
937
 
1021
938
  def rebase(flag = nil, opts = [], sync: invoked_sync?('rebase', flag), commit: nil, upstream: nil, branch: nil,
@@ -1028,7 +945,7 @@ module Squared
1028
945
  return unless upstream
1029
946
 
1030
947
  op = OptionPartition.new(opts, OPT_GIT[:rebase], cmd, project: self, no: OPT_GIT[:no][:rebase])
1031
- cmd << upstream
948
+ cmd << shell_escape(upstream)
1032
949
  append_head op.shift
1033
950
  op.clear(pass: false)
1034
951
  when :onto
@@ -1036,13 +953,9 @@ module Squared
1036
953
 
1037
954
  cmd << '--interactive' if option('interactive', 'i')
1038
955
  cmd << shell_option('onto', commit) if commit
1039
- cmd << upstream
956
+ cmd << shell_escape(upstream)
1040
957
  append_head branch
1041
958
  else
1042
- unless gitpath('REBASE_HEAD').exist?
1043
- puts log_message(Logger::INFO, name, 'no rebase in progress', hint: command) if stdout?
1044
- return
1045
- end
1046
959
  return unless VAL_GIT[:rebase][:send].include?(command)
1047
960
 
1048
961
  cmd << "--#{command}"
@@ -1056,7 +969,6 @@ module Squared
1056
969
 
1057
970
  def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
1058
971
  opts = git_session('fetch', opts: opts).last
1059
- opts << 'all' if flag == :all || option('all')
1060
972
  append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
1061
973
  remote: remote, flag: flag, from: :fetch)
1062
974
  source(sync: sync, **threadargs)
@@ -1067,23 +979,26 @@ module Squared
1067
979
 
1068
980
  cmd = git_session('clone', worktree: false)
1069
981
  opts = data[1].dup
1070
- if (val = option('depth', ignore: false))
982
+ option('depth', ignore: false) do |val|
1071
983
  if (n = val.to_i) > 0
1072
984
  opts[:depth] = n
1073
985
  else
1074
986
  opts.delete(:depth)
1075
987
  end
1076
988
  end
1077
- opts[:origin] = val if (val = option('origin', ignore: false))
1078
- if (val = option('branch', strict: true))
1079
- opts[:branch] = val
989
+ option('origin', ignore: false) { |val| opts[:origin] = val }
990
+ if (branch = option('branch', strict: true))
991
+ opts[:branch] = branch
1080
992
  opts.delete(:revision)
1081
- elsif (val = option('revision', strict: true))
1082
- opts[:revision] = val
1083
- opts.delete(:branch)
1084
- 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
1085
999
  end
1086
- 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 }
1087
1002
  opts.delete(:'recurse-submodules') || opts.delete(:'no-recurse-submodules') if append_submodules(from: :clone)
1088
1003
  append_hash opts
1089
1004
  cmd << '--quiet' unless verbose
@@ -1096,34 +1011,19 @@ module Squared
1096
1011
  cmd, opts = git_session('stash', flag, opts: opts)
1097
1012
  list = OPT_GIT[:stash][:common] + OPT_GIT[:stash].fetch(flag, [])
1098
1013
  if flag == :list
1099
- list += collect_hash OPT_GIT[:log]
1100
- no = collect_hash OPT_GIT[:no][:log]
1014
+ list += collect_hash(OPT_GIT[:log])
1015
+ no = collect_hash(OPT_GIT[:no][:log])
1101
1016
  end
1102
1017
  op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: flag == :push ? matchpathspec : nil)
1103
1018
  case flag
1104
1019
  when :push
1105
- op.append?('message', readline('Enter message', force: true), force: true) if op.remove(':')
1106
1020
  append_pathspec op.extras
1107
- when :pop, :apply, :drop, :branch
1108
- if op.remove(':')
1109
- if flag == :branch
1110
- if op.empty?
1111
- values = [['Branch name', true]]
1112
- else
1113
- op << op.pop
1114
- end
1115
- end
1116
- out = choice_index('Choose a stash', git_spawn('stash list', stdout: false),
1117
- values: values, column: /^[^@]+@\{(\d+)\}/, force: true)
1118
- if values
1119
- op.merge(out.reverse)
1120
- else
1121
- op << out
1122
- end
1021
+ when :pop, :apply, :drop
1022
+ if op.extras.delete(':')
1023
+ op << choice_index('Choose a stash', git_spawn('stash list', stdout: false),
1024
+ column: /^[^@]+@\{(\d+)\}/, force: true)
1123
1025
  elsif !op.empty?
1124
- op << op.pop
1125
- elsif flag == :branch
1126
- raise_error 'no branch name'
1026
+ op << shell_escape(op.pop)
1127
1027
  end
1128
1028
  op.clear
1129
1029
  when :clear
@@ -1140,35 +1040,30 @@ module Squared
1140
1040
  end
1141
1041
  else
1142
1042
  git_session('stash', 'push', opts: opts)
1143
- append_option(OptionPartition.select(OPT_GIT[:stash][:push], no: false), no: true, ignore: false)
1043
+ append_option(OPT_GIT[:stash][:push].grep_v(/[=|]/), no: true, ignore: false)
1144
1044
  append_message
1145
1045
  end
1146
1046
  source(banner: !quiet?, sync: sync, **threadargs)
1147
1047
  end
1148
1048
 
1149
- def status(flag = nil, opts = [])
1150
- cmd, opts = git_session('status', opts: opts)
1151
- if flag
1152
- op = OptionPartition.new(opts, OPT_GIT[:status], cmd, project: self, no: OPT_GIT[:no][:status])
1153
- append_pathspec op.extras
1154
- else
1155
- cmd << (option('long') ? '--long' : '--short')
1156
- cmd << '--branch' if option('branch')
1157
- if (val = option('ignore-submodules', ignore: false))
1158
- cmd << basic_option('ignore-submodules', case val
1159
- when '0', 'none'
1160
- 'none'
1161
- when '1', 'untracked'
1162
- 'untracked'
1163
- when '2', 'dirty'
1164
- 'dirty'
1165
- else
1166
- 'all'
1167
- end)
1168
- end
1169
- append_pathspec
1049
+ def status(*)
1050
+ cmd = git_session 'status'
1051
+ cmd << (option('long') ? '--long' : '--short')
1052
+ cmd << '--branch' if option('branch')
1053
+ option('ignore-submodules', ignore: false) do |val|
1054
+ cmd << basic_option('ignore-submodules', case val
1055
+ when '0', 'none'
1056
+ 'none'
1057
+ when '1', 'untracked'
1058
+ 'untracked'
1059
+ when '2', 'dirty'
1060
+ 'dirty'
1061
+ else
1062
+ 'all'
1063
+ end)
1170
1064
  end
1171
- if stdout?
1065
+ append_pathspec
1066
+ if verbose
1172
1067
  r = color(:red)
1173
1068
  g = color(:green)
1174
1069
  sub = if session_arg?('short')
@@ -1176,7 +1071,7 @@ module Squared
1176
1071
  { pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
1177
1072
  { pat: /^([A-Z?!])(.+)$/, styles: g },
1178
1073
  { pat: /^(\?\?)(.+)$/, styles: r },
1179
- { pat: /^(## )(.+?)(\.{3})(.+)$/, styles: [nil, g, nil, r], index: -1 }
1074
+ { pat: /^(## )((?~\.{3}))(\.{3})(.+)$/, styles: [nil, g, nil, r], index: -1 }
1180
1075
  ]
1181
1076
  else
1182
1077
  [pat: /^(\t+)([a-z]+: +.+)$/, styles: r, index: 2]
@@ -1190,8 +1085,8 @@ module Squared
1190
1085
  def revbuild(flag = nil, opts = [], sync: nil, **kwargs)
1191
1086
  statusargs = lambda do
1192
1087
  {
1193
- include: relativepath(Array(kwargs[:include]), all: true),
1194
- 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)
1195
1090
  }
1196
1091
  end
1197
1092
  unless workspace.closed
@@ -1209,19 +1104,19 @@ module Squared
1209
1104
  kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.call : @revbuild || {}
1210
1105
  case flag
1211
1106
  when :build
1212
- op = OptionPartition.new(opts, %w[ignore-submodules=b? ignored=b? untracked-files=b?], project: self)
1107
+ op = OptionPartition.new(opts, OPT_GIT[:status], project: self)
1213
1108
  op.clear(append: true)
1214
1109
  args = op.to_a
1215
1110
  else
1216
1111
  args = []
1217
- args << basic_option('untracked-files', flag) if (flag = option('untracked-files', prefix: 'git'))
1218
- args << basic_option('ignore-submodules', flag) if (flag = option('ignore-submodules', prefix: 'git'))
1219
- 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) }
1220
1115
  end
1221
1116
  if (cur = workspace.rev_entry(name)) && cur['revision'] == sha && !env('REVBUILD_FORCE')
1222
1117
  files = status_digest(*args, **kwargs)
1223
1118
  if cur['files'].size == files.size && cur['files'].find { |key, val| files[key] != val }.nil?
1224
- if stdout?
1119
+ if verbose
1225
1120
  if (since = workspace.rev_timesince(name, 'build'))
1226
1121
  puts log_message(Logger::INFO, name, 'no changes', subject: 'revbuild', hint: "#{since} ago")
1227
1122
  else
@@ -1236,7 +1131,10 @@ module Squared
1236
1131
  rescue StandardError => e
1237
1132
  warn log_message(Logger::WARN, e, pass: true) if warning?
1238
1133
  else
1239
- print_status(name, subject: 'revbuild', start: start, from: :completed)
1134
+ if verbose
1135
+ msg = sub_style('completed', styles: theme[:active])
1136
+ puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
1137
+ end
1240
1138
  workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
1241
1139
  sync: sync, utc: 'build')
1242
1140
  end
@@ -1266,9 +1164,6 @@ module Squared
1266
1164
  when :patch
1267
1165
  cmd << '--patch'
1268
1166
  append_pathspec(refs, pass: false)
1269
- when :undo
1270
- cmd << '--hard HEAD@{1}'
1271
- ref = false
1272
1167
  end
1273
1168
  unless ref == false
1274
1169
  append_commit(ref, head: true)
@@ -1279,7 +1174,7 @@ module Squared
1279
1174
 
1280
1175
  def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil, merge: false)
1281
1176
  cmd, opts = git_session('checkout', opts: opts)
1282
- append_option 'force', 'f', 'merge'
1177
+ append_option 'force', 'merge'
1283
1178
  case flag
1284
1179
  when :branch
1285
1180
  cmd << '--detach' if detach == 'd' || option('detach')
@@ -1300,14 +1195,13 @@ module Squared
1300
1195
  else
1301
1196
  op = OptionPartition.new(opts, OPT_GIT[:checkout], cmd, project: self, no: OPT_GIT[:no][:checkout],
1302
1197
  first: flag == :path ? matchpathspec : nil)
1303
- if flag == :path
1198
+ if flag == :commit
1199
+ op.append(commit)
1200
+ .clear(pass: false)
1201
+ else
1304
1202
  append_head
1305
1203
  append_pathspec(op.extras, pass: false)
1306
- print_success if success?(source)
1307
- return
1308
1204
  end
1309
- op.append(commit)
1310
- .clear(pass: false)
1311
1205
  end
1312
1206
  source
1313
1207
  end
@@ -1321,7 +1215,7 @@ module Squared
1321
1215
  elsif !session_arg?('s', 'sign', 'u', 'local-user')
1322
1216
  cmd << '--annotate'
1323
1217
  end
1324
- cmd << '--force' if option('force', 'f')
1218
+ cmd << '--force' if option('force')
1325
1219
  if !commit && message && (sha = commithash(message))
1326
1220
  commit = sha
1327
1221
  message = nil
@@ -1340,19 +1234,19 @@ module Squared
1340
1234
  list_result(ret, 'tags', from: from, grep: op.extras)
1341
1235
  return
1342
1236
  end
1343
- remote ||= option('remote')
1237
+ remote ||= option 'remote'
1344
1238
  source
1345
1239
  git_spawn('push', flag == :delete ? '-d' : nil, remote, *refs.map { |val| shell_quote(val) }) if remote
1346
1240
  end
1347
1241
 
1348
1242
  def log!(flag, opts = [], range: [], index: [])
1349
1243
  cmd, opts = git_session('log', opts: opts)
1350
- op = OptionPartition.new(opts, collect_hash(OPT_GIT[:log]), cmd, project: self,
1351
- no: collect_hash(OPT_GIT[:no][:log]),
1352
- 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)
1353
1247
  case flag
1354
1248
  when :between, :contain
1355
- op.add_quote(range.join(flag == :between ? '..' : '...'))
1249
+ op << shell_quote(range.join(flag == :between ? '..' : '...'))
1356
1250
  else
1357
1251
  op.merge(index)
1358
1252
  end
@@ -1375,18 +1269,19 @@ module Squared
1375
1269
  op << '--no-index'
1376
1270
  append_pathspec(refs, parent: true)
1377
1271
  else
1378
- op << '--merge-base' if option('merge-base')
1379
1272
  case flag
1380
1273
  when :view
1274
+ op << '--merge-base' if option('merge-base')
1381
1275
  op.merge(range)
1382
1276
  when :between, :contain
1383
1277
  op.delete('--merge-base')
1384
- op.add_quote(range.join(flag == :between ? '..' : '...'))
1278
+ op << shell_quote(range.join(flag == :between ? '..' : '...'))
1385
1279
  else
1386
- op.add_quote(branch) if branch
1280
+ op << '--merge-base' if option('merge-base')
1281
+ op << shell_quote(branch) if branch
1387
1282
  if !index.empty?
1388
1283
  if op.arg?('cached')
1389
- raise_error("one commit only: #{index.join(', ')}", hint: 'cached') if index.size > 1
1284
+ raise_error("one commit only: #{index.join(', ')}", hint: '--cached') if index.size > 1
1390
1285
  op << index.first
1391
1286
  else
1392
1287
  op.merge(index)
@@ -1438,16 +1333,16 @@ module Squared
1438
1333
  branch, origin, hint = line.split('...')
1439
1334
  if hint && !hint.match?(/^\[(\D+0,\D+0)\]$/)
1440
1335
  raise_error('work tree is not usable', hint: hint[1..-2])
1441
- elsif !origin || origin.empty?
1336
+ elsif origin.empty?
1442
1337
  return nil if pass
1443
1338
  break if dryrun
1444
1339
 
1445
1340
  unless (origin = option('upstream', prefix: 'git', ignore: false))
1446
1341
  if (origin = choice_refs('Choose an upstream', 'remotes', attempts: 1, force: false))
1447
1342
  git_spawn 'branch', quote_option('set-upstream-to', origin)
1448
- break
1343
+ else
1344
+ origin = readline('Enter an upstream', force: true)
1449
1345
  end
1450
- origin = readline('Enter an upstream', force: true)
1451
1346
  end
1452
1347
  raise_error('missing remote name', hint: origin) unless origin.include?('/')
1453
1348
  upstream = true
@@ -1482,7 +1377,6 @@ module Squared
1482
1377
 
1483
1378
  def merge(flag, opts = [], command: nil, branch: nil)
1484
1379
  cmd, opts = git_session('merge', opts: opts)
1485
- display = false
1486
1380
  case flag
1487
1381
  when :commit, :'no-commit'
1488
1382
  op = OptionPartition.new(opts, OPT_GIT[:merge], cmd, project: self, no: OPT_GIT[:no][:merge])
@@ -1495,16 +1389,11 @@ module Squared
1495
1389
  append_commit(*op.extras)
1496
1390
  end
1497
1391
  else
1498
- unless gitpath('MERGE_HEAD').exist?
1499
- puts log_message(Logger::INFO, name, 'no merge in progress', hint: command) if stdout?
1500
- return
1501
- end
1502
1392
  return unless VAL_GIT[:merge][:send].include?(command)
1503
1393
 
1504
1394
  cmd << "--#{command}"
1505
- display = command == 'abort'
1506
1395
  end
1507
- print_success if success?(source, display)
1396
+ source
1508
1397
  end
1509
1398
 
1510
1399
  def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil, remote: nil)
@@ -1512,17 +1401,17 @@ module Squared
1512
1401
  stdout = false
1513
1402
  case flag
1514
1403
  when :create
1515
- if (arg = option('track', ignore: false))
1516
- cmd << case arg
1404
+ option('track', ignore: false) do |val|
1405
+ cmd << case val
1517
1406
  when '0', 'false'
1518
1407
  '--no-track'
1519
1408
  when 'direct', 'inherit'
1520
- basic_option('track', arg)
1409
+ basic_option 'track', val
1521
1410
  else
1522
1411
  '--track'
1523
1412
  end
1524
1413
  end
1525
- cmd << '--force' if option('force', 'f')
1414
+ cmd << '--force' if option('force')
1526
1415
  cmd << shell_quote(target)
1527
1416
  cmd << shell_quote(ref) if ref
1528
1417
  when :track
@@ -1537,12 +1426,14 @@ module Squared
1537
1426
  end
1538
1427
  when :delete
1539
1428
  remote&.each do |val|
1540
- source git_output('push --delete', *val.split('/', 2).map { |s| shell_quote(s) })
1429
+ source git_output('push', '--delete', *val.split('/', 2).map { |s| shell_quote(s) })
1541
1430
  end
1542
- force, list = refs.partition { |val| val.match?(/^[~^]/) }
1431
+ force, list = refs.partition { |val| val.start_with?(/[~^]/) }
1543
1432
  force.each do |val|
1544
- r = '-r' if val.delete!('~')
1545
- source git_output('branch', val.delete!('^') ? '-D' : '-d', r, shell_quote(val))
1433
+ dr = val[0, 2]
1434
+ d = dr.include?('^') ? '-D' : '-d'
1435
+ r = '-r' if dr.include?('~')
1436
+ source git_output('branch', d, r, shell_quote(val.sub(/^[~^]+/, '')))
1546
1437
  end
1547
1438
  return if list.empty?
1548
1439
 
@@ -1550,9 +1441,8 @@ module Squared
1550
1441
  append_value list
1551
1442
  remote = nil
1552
1443
  when :move, :copy
1553
- s = "-#{flag.to_s[0]}"
1554
- s.upcase! if option('force', 'f')
1555
- cmd << s
1444
+ flag = "-#{flag.to_s[0]}"
1445
+ cmd << (option('force') ? flag.upcase : flag)
1556
1446
  refs.compact.each { |val| cmd << shell_quote(val) }
1557
1447
  stdout = true
1558
1448
  when :current
@@ -1562,7 +1452,7 @@ module Squared
1562
1452
  when :list
1563
1453
  op = OptionPartition.new(opts, OPT_GIT[:branch], cmd << '--list',
1564
1454
  project: self, no: OPT_GIT[:no][:branch], single: /\Av+\z/)
1565
- op.each { |val| op.add_quote(val) }
1455
+ op.each { |val| op << shell_quote(val) }
1566
1456
  out, banner, from = source(io: true)
1567
1457
  print_item banner
1568
1458
  ret = write_lines(out, sub: [
@@ -1572,19 +1462,19 @@ module Squared
1572
1462
  list_result(ret, 'branches', from: from)
1573
1463
  return
1574
1464
  else
1575
- if (head = git_spawn('rev-parse --abbrev-ref HEAD').chomp).empty?
1465
+ head = git_spawn('rev-parse --abbrev-ref HEAD').chomp
1466
+ if head.empty?
1576
1467
  ret = 0
1577
1468
  else
1578
1469
  git_spawn 'fetch --all --prune --quiet' if option('sync')
1579
- cmd << '-vv --no-abbrev --list'
1580
- out, banner, from = source(io: true)
1470
+ out, banner, from = source(cmd << '-vv --no-abbrev --list', io: true)
1581
1471
  ret = write_lines(out, grep: [/^\*\s+#{Regexp.escape(head)}\s/], banner: banner, first: true) do |line|
1582
1472
  next line if stdin?
1583
1473
 
1584
1474
  data = line.sub(/^\*\s+/, '').split(/\s+/)
1585
1475
  a = sub_style(data[0], styles: theme[:inline])
1586
1476
  b = sub_style(data[1], styles: theme[:extra])
1587
- r = /\A(?:\[(.+?)(?=\]\s)\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
1477
+ r = /\A(?:\[((?~\]\s))\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
1588
1478
  if (r1 = r[1]) && r1 =~ /^(.+):(?: ([a-z]+) (\d+),)? ([a-z]+) (\d+)$/
1589
1479
  write = ->(s1, s2) { "#{s1.capitalize.rjust(7)}: #{sub_style(s2, styles: theme[:warn])}" }
1590
1480
  r1 = $1
@@ -1608,55 +1498,33 @@ module Squared
1608
1498
  if !ref
1609
1499
  print_success if flag == :create
1610
1500
  elsif remote && target
1611
- source git_output('push -u', shell_quote(ref.split('/', 2).first), shell_quote(target))
1612
- end
1613
- end
1614
-
1615
- def switch(flag, opts = [], branch: nil, commit: nil, track: nil)
1616
- cmd, opts = git_session('switch', opts: opts)
1617
- cmd << '--force' if option('force', 'f')
1618
- if flag == :branch
1619
- op = OptionPartition.new(opts, OPT_GIT[:switch], cmd, project: self, no: OPT_GIT[:no][:switch])
1620
- op.add_quote(branch)
1621
- else
1622
- case flag
1623
- when :create
1624
- c = 'c'
1625
- if target.start_with?('^')
1626
- target = target[1..-1]
1627
- c = c.upcase
1628
- end
1629
- cmd << quote_option(c, target)
1630
- cmd << case (track ||= option('track', ignore: false))
1631
- when 'n', 'N', '0', 'false'
1632
- '--no-track'
1633
- when 'y', 'Y', '1', 'true'
1634
- '--track'
1635
- when 'direct', 'inherit'
1636
- basic_option 'track', track
1637
- end
1638
- when :detach
1639
- cmd << "--#{flag}"
1640
- end
1641
- append_head commit
1501
+ source git_output('push', '-u', shell_quote(ref.split('/', 2).first), shell_quote(target))
1642
1502
  end
1643
- source
1644
1503
  end
1645
1504
 
1646
- def submodule(flag, opts = [], path: nil, url: nil)
1647
- cmd, opts = git_session('submodule', opts: opts)
1648
- op = OptionPartition.new(opts, OPT_GIT[:submodule].fetch(flag, []), cmd, project: self)
1505
+ def switch(flag, opts = [], target: nil, commit: nil, track: nil)
1506
+ cmd = git_session('switch', opts: opts).first
1649
1507
  case flag
1650
- when :branch, :url
1651
- op.adjoin("set-#{flag}")
1652
- op << '--'
1653
- op.add_path(path) if path
1654
- op.add_quote(url) if url
1655
- else
1656
- op.adjoin(flag)
1657
- op << '--recursive' if option('recursive', 'r')
1658
- op.splice(path: true)
1508
+ when :create
1509
+ c = 'c'
1510
+ if target.start_with?('^')
1511
+ target = target[1..-1]
1512
+ c = c.upcase
1513
+ end
1514
+ cmd << quote_option(c, target)
1515
+ cmd << case (track ||= option('track', ignore: false))
1516
+ when 'n', 'N', '0', 'false'
1517
+ '--no-track'
1518
+ when 'y', 'Y', '1', 'true'
1519
+ '--track'
1520
+ when 'direct', 'inherit'
1521
+ basic_option 'track', track
1522
+ end
1523
+ when :detach, :merge
1524
+ cmd << "--#{flag}"
1659
1525
  end
1526
+ cmd << '--force' if option('force')
1527
+ append_head commit
1660
1528
  source
1661
1529
  end
1662
1530
 
@@ -1679,15 +1547,19 @@ module Squared
1679
1547
  source(banner: false)
1680
1548
  return
1681
1549
  when :oneline
1682
- format = flag.to_s
1550
+ format = 'oneline'
1683
1551
  end
1684
- case format
1685
- when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
1686
- cmd << basic_option('format', format)
1687
- when /(?:^t?format:|%)/
1688
- cmd << quote_option('pretty', format)
1689
- else
1690
- opts << format if format
1552
+ if format
1553
+ case (val = format.downcase)
1554
+ when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
1555
+ cmd << basic_option('format', val)
1556
+ else
1557
+ if format.start_with?(/t?format:/) || format.include?('%')
1558
+ cmd << quote_option('pretty', format)
1559
+ else
1560
+ opts << format
1561
+ end
1562
+ end
1691
1563
  end
1692
1564
  op = OptionPartition.new(opts, OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff], cmd,
1693
1565
  project: self,
@@ -1721,7 +1593,7 @@ module Squared
1721
1593
  cmd, opts = git_session('ls-remote', '--refs', opts: opts)
1722
1594
  cmd << "--#{flag}" unless flag == :remote
1723
1595
  op = OptionPartition.new(opts, OPT_GIT[:ls_remote], cmd, project: self)
1724
- op.add_quote(remote) if remote
1596
+ op << shell_quote(remote) if remote
1725
1597
  out, banner, from = source(io: true)
1726
1598
  print_item banner
1727
1599
  ret = write_lines(out, grep: op.extras, prefix: "refs/#{flag}/")
@@ -1731,7 +1603,6 @@ module Squared
1731
1603
  def ls_files(flag, opts = [])
1732
1604
  cmd, opts = git_session('ls-files', "--#{flag}", opts: opts)
1733
1605
  op = OptionPartition.new(opts, OPT_GIT[:ls_files], cmd, project: self)
1734
- op.splice(path: true, pattern: true)
1735
1606
  out, banner, from = source(io: true)
1736
1607
  print_item banner
1737
1608
  ret = write_lines(out, grep: op.extras)
@@ -1740,17 +1611,10 @@ module Squared
1740
1611
 
1741
1612
  def git(flag, opts = [])
1742
1613
  cmd, opts = git_session(flag, opts: opts)
1743
- op = OptionPartition.new(opts, OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, []), cmd,
1744
- project: self, no: OPT_GIT[:no][flag], first: case flag
1745
- when :blame, :revert
1746
- nil
1747
- else matchpathspec
1748
- end)
1614
+ list = OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, [])
1615
+ op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GIT[:no][flag],
1616
+ first: flag == :revert ? nil : matchpathspec)
1749
1617
  case flag
1750
- when :blame
1751
- raise_error 'no file found' unless (n = op.index { |s| (path + s).file? })
1752
- op << '--' << shell_quote(path + op.delete_at(n))
1753
- op.clear
1754
1618
  when :revert
1755
1619
  if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
1756
1620
  op.clear
@@ -1761,26 +1625,26 @@ module Squared
1761
1625
  end
1762
1626
  when :add, :clean
1763
1627
  if flag == :add && !op.arg?('pathspec-from-file')
1764
- grep, list = op.partition { |val| OptionPartition.pattern?(val) }
1765
- unless grep.empty? && !list.empty?
1628
+ grep, list = op.extras.partition { |val| val.start_with?(':') && val.end_with?(':') }
1629
+ if list.empty? || !grep.empty?
1630
+ red = color(:red)
1766
1631
  grep.map! { |val| Regexp.new(val[1..-2]) }
1767
- files = [].tap do |out|
1768
- status_data.each do |a, b|
1769
- next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
1632
+ files = status_data.map! do |a, b|
1633
+ next unless grep.empty? || grep.any? { |pat| pat.match?(a) }
1770
1634
 
1771
- out << "#{sub_style(b, styles: color(:red))} #{a}"
1772
- end
1635
+ "#{sub_style(b, styles: red)} #{a}"
1773
1636
  end
1637
+ .compact
1774
1638
  unless files.empty?
1775
1639
  files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/,
1776
- accept: [['Add?', false, true]])
1640
+ accept: 'Add?')
1777
1641
  end
1778
1642
  op.swap(list + files)
1779
1643
  end
1780
1644
  end
1781
- return source(git_session('status -s'), banner: false) unless append_pathspec(op.extras)
1782
-
1783
- print_success if success?(source, flag == :add && !op.arg?('verbose'))
1645
+ append_pathspec op.extras
1646
+ verbose = flag == :add && !op.arg?('verbose')
1647
+ print_success if success?(source) && verbose
1784
1648
  return
1785
1649
  when :mv
1786
1650
  refs = projectmap op.extras
@@ -1807,37 +1671,30 @@ module Squared
1807
1671
  private
1808
1672
 
1809
1673
  def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
1810
- multiple: false, hint: nil, from: nil, send: :system, **kwargs)
1674
+ multiple: false, **kwargs)
1811
1675
  cmd = cmd.target if cmd.is_a?(OptionPartition)
1812
- if io && banner == false
1813
- from = nil
1814
- banner = nil
1815
- else
1816
- banner = nil if banner && (multiple || !banner?)
1817
- if cmd.respond_to?(:done)
1818
- if from.nil? && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z-]*\z/) })
1819
- from = :"git:#{from}"
1820
- end
1821
- 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}"
1822
1682
  end
1823
- from = nil if from == false
1683
+ banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
1824
1684
  end
1825
1685
  cmd = session_done cmd
1826
1686
  log&.info cmd
1687
+ on :first, from
1827
1688
  banner = if banner
1828
- banner = (banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), '')
1829
- format_banner(hint ? "#{banner} (#{hint})" : banner, banner: true)
1689
+ format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
1830
1690
  end
1831
- on :first, from
1832
1691
  begin
1833
1692
  if io
1834
- ret = if stdout
1835
- `#{cmd}`
1836
- else
1837
- banner ? [IO.popen(cmd), banner, from] : IO.popen(cmd)
1838
- end
1839
- return ret
1840
- 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
1841
1698
  print_item banner unless multiple
1842
1699
  ret = `#{cmd}`
1843
1700
  if !ret.empty?
@@ -1845,9 +1702,9 @@ module Squared
1845
1702
  elsif success?(!banner.nil?)
1846
1703
  print_success
1847
1704
  end
1848
- elsif !kwargs[:sub] && (sync || (!exception && !stderr))
1705
+ elsif sync || (!exception && !stderr)
1849
1706
  print_item banner unless multiple
1850
- ret = shell(cmd, name: send, exception: exception)
1707
+ ret = shell(cmd, exception: exception)
1851
1708
  else
1852
1709
  require 'open3'
1853
1710
  if stderr
@@ -1865,7 +1722,11 @@ module Squared
1865
1722
  end
1866
1723
  end
1867
1724
  rescue StandardError => e
1868
- on_error(e, from, pass: true)
1725
+ log&.error e
1726
+ ret = on(:error, from, e)
1727
+ raise if exception && ret != true
1728
+
1729
+ warn log_message(Logger::WARN, e, pass: true) if warning?
1869
1730
  nil
1870
1731
  else
1871
1732
  on :last, from
@@ -1874,7 +1735,16 @@ module Squared
1874
1735
  end
1875
1736
 
1876
1737
  def write_lines(data, grep: [], prefix: nil, sub: nil, banner: nil, loglevel: nil, pass: false, first: false)
1877
- grep = grep.empty? ? nil : matchmap(grep, prefix)
1738
+ grep = unless grep.empty?
1739
+ grep.map do |val|
1740
+ if val.is_a?(Regexp)
1741
+ val
1742
+ else
1743
+ val = ".*#{val}" if prefix && !val.sub!(/\A(\^|\\A)/, '')
1744
+ Regexp.new("#{prefix}#{val == '*' ? '.+' : val}")
1745
+ end
1746
+ end
1747
+ end
1878
1748
  sub = nil if stdin?
1879
1749
  ret = 0
1880
1750
  out = []
@@ -1905,7 +1775,7 @@ module Squared
1905
1775
  def list_result(size, type, grep: [], action: 'found', from: nil)
1906
1776
  if size == 0
1907
1777
  puts empty_status("No #{type} were #{action}", 'grep', grep.join(', '))
1908
- elsif stdout?
1778
+ elsif verbose
1909
1779
  styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
1910
1780
  styles << :bold if styles.size <= 1
1911
1781
  puts print_footer("#{size} #{size == 1 ? type.sub(/(?:(?<!l)e)?s\z/, '') : type}",
@@ -1948,7 +1818,8 @@ module Squared
1948
1818
  glob = kwargs.fetch(:include, [])
1949
1819
  pass = kwargs.fetch(:exclude, [])
1950
1820
  ret = {}
1951
- status_data(*args).each do |file,|
1821
+ status_data(*args).each do |line|
1822
+ file = line.first
1952
1823
  next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
1953
1824
  next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
1954
1825
 
@@ -1958,17 +1829,17 @@ module Squared
1958
1829
  end
1959
1830
 
1960
1831
  def status_data(*args)
1961
- [].tap do |ret|
1962
- git_spawn('status -z -uall', *args).split("\x0").each do |line|
1963
- next unless line =~ /^(.)(.) (.+)$/
1832
+ ret = []
1833
+ git_spawn('status -z -uall', *args).split("\x0").each do |line|
1834
+ next unless line =~ /^(.)(.) (.+)$/
1964
1835
 
1965
- ret << [$3, $2, $1]
1966
- end
1836
+ ret << [$3, $2, $1]
1967
1837
  end
1838
+ ret
1968
1839
  end
1969
1840
 
1970
1841
  def append_pull(opts, list, target: @session, flag: nil, no: nil, remote: nil, from: nil)
1971
- target << '--force' if option('force', 'f', target: target)
1842
+ target << '--force' if option('force', target: target)
1972
1843
  append_submodules(target: target, from: from)
1973
1844
  return if !remote && opts.empty?
1974
1845
 
@@ -1980,9 +1851,11 @@ module Squared
1980
1851
  when 'rebase'
1981
1852
  op << basic_option($1, $2) if VAL_GIT[:rebase][:value].include?($2)
1982
1853
  when 'shallow-since'
1983
- op.append?($1) { Date.parse($2)&.strftime('%F %T') }
1854
+ next unless (val = Date.parse($2))
1855
+
1856
+ op << quote_option($1, val.strftime('%F %T'))
1984
1857
  when 'recurse-submodules'
1985
- op.append?($1, $2, type: :basic)
1858
+ op << basic_option($1, $2) unless op.arg?('recurse-submodules')
1986
1859
  when 'refspec'
1987
1860
  refspec << shell_escape($2, quote: true)
1988
1861
  end
@@ -1992,7 +1865,7 @@ module Squared
1992
1865
  op.errors << opt
1993
1866
  end
1994
1867
  end
1995
- op << '--verbose' if (flag || from == :fetch) && stdout? && !op.arg?('quiet')
1868
+ op << '--verbose' if (flag || from == :fetch) && verbose && !op.arg?('quiet')
1996
1869
  if remote
1997
1870
  op.append(remote, delim: true)
1998
1871
  if (val = option('refspec', target: target, strict: true))
@@ -2005,7 +1878,7 @@ module Squared
2005
1878
  op.swap.merge(op.map! { |opt| shell_escape(opt, quote: true) })
2006
1879
  return
2007
1880
  elsif option('all')
2008
- op << '--all'
1881
+ cmd << '--all'
2009
1882
  end
2010
1883
  op.clear(errors: true, subject: flag.to_s) if flag
2011
1884
  end
@@ -2022,19 +1895,13 @@ module Squared
2022
1895
  def append_pathspec(files = [], target: @session, expect: false, parent: false, pass: true)
2023
1896
  if session_arg?('pathspec-from-file', target: target)
2024
1897
  option_clear files
2025
- true
2026
1898
  else
2027
- if files.empty? && (val = option('pathspec', target: target))
2028
- files = split_escape val
2029
- end
1899
+ option('pathspec', target: target) { |val| files = split_escape val } if files.empty?
2030
1900
  files = projectmap(files, parent: parent, pass: pass)
2031
1901
  if !files.empty?
2032
1902
  target << '--' << files.join(' ')
2033
- true
2034
1903
  elsif expect
2035
1904
  raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree')
2036
- else
2037
- false
2038
1905
  end
2039
1906
  end
2040
1907
  end
@@ -2051,61 +1918,51 @@ module Squared
2051
1918
  end
2052
1919
 
2053
1920
  def append_submodules(target: @session, from: nil)
2054
- return unless (val = option('recurse-submodules', target: target, ignore: false))
2055
-
2056
- if from == :clone
2057
- case val
2058
- when '0', 'false'
2059
- target << '--no-recurse-submodules'
2060
- when '1', 'true'
2061
- target << '--recurse-submodules'
2062
- else
2063
- projectmap(split_escape(val)).each do |path|
2064
- 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
2065
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
2066
1942
  end
2067
- else
2068
- target << case val
2069
- when 'no', '0', 'false'
2070
- '--no-recurse-submodules'
2071
- when 'yes', 'on-demand'
2072
- "--recurse-submodules=#{val}"
2073
- else
2074
- '--recurse-submodules'
2075
- end
2076
1943
  end
2077
1944
  end
2078
1945
 
2079
1946
  def foreachref(path, *args, format: nil)
2080
- path = Array(path).map! { |val| "refs/#{val}" }
2081
- format &&= quote_option('format', format)
2082
- ret = git_spawn('for-each-ref', format, *args, *path, stdout: workspace.windows?)
2083
- 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)
2084
1949
  end
2085
1950
 
2086
1951
  def git_session(*cmd, opts: nil, worktree: true, **kwargs)
2087
- dir = worktree ? [quote_option('work-tree', path), quote_option('git-dir', gitpath)] : []
1952
+ dir = worktree ? ["--work-tree=#{shell_quote(path)}", "--git-dir=#{shell_quote(gitpath)}"] : []
2088
1953
  return session('git', *dir, *cmd, **kwargs) unless opts
2089
1954
 
2090
1955
  op = OptionPartition.new(opts, OPT_GIT[:common], dir, project: self)
2091
- [session('git', *op.to_a, *cmd, **kwargs), op.extras]
1956
+ ret = session('git', *op.to_a, *cmd, **kwargs)
1957
+ [ret, op.extras]
2092
1958
  end
2093
1959
 
2094
1960
  def git_output(*cmd, **kwargs)
2095
1961
  git_session(*cmd, main: false, options: false, **kwargs)
2096
1962
  end
2097
1963
 
2098
- def git_spawn(*cmd, exception: true, io: true, sync: true, stdout: true, banner: false, **kwargs)
2099
- kwargs[:send] = if sync
2100
- :system
2101
- else
2102
- exception = false
2103
- io = false
2104
- stdout = false
2105
- :spawn
2106
- end
2107
- source(cmd.first.is_a?(Set) ? cmd.first : git_output(*cmd), exception: exception, io: io, sync: sync,
2108
- stdout: stdout, banner: banner, **kwargs)
1964
+ def git_spawn(*cmd, stdout: true)
1965
+ source(cmd.first.is_a?(Set) ? cmd.first : git_output(*cmd), io: true, banner: false, stdout: stdout)
2109
1966
  end
2110
1967
 
2111
1968
  def dryrun?(*, target: @session, **)
@@ -2120,29 +1977,28 @@ module Squared
2120
1977
  target.include?('--quiet') || (target.include?('-q') && stripext(target.first) == 'git')
2121
1978
  end
2122
1979
 
2123
- def gitpath(*args)
2124
- path.join('.git', *args)
1980
+ def gitpath
1981
+ path + '.git'
2125
1982
  end
2126
1983
 
2127
1984
  def repotrack(origin, branch, quote: true)
2128
1985
  i = origin.index('/')
2129
- branch = "#{branch}:#{origin[(i + 1)..-1]}" unless origin.end_with?("/#{branch}")
2130
- ret = [origin[0..(i - 1)], branch]
2131
- 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 }
2132
1988
  end
2133
1989
 
2134
1990
  def commithash(val)
2135
- val[/\A:(\h{5,40})\z/, 1] || val[/\A#\{(\h{5,40})\}\z/, 1]
1991
+ val[/\A:(\h{5,40})\z/, 1]
2136
1992
  end
2137
1993
 
2138
1994
  def commithead(val)
2139
1995
  return val unless (s = matchhead(val))
2140
1996
 
2141
- s.match?(/^\d/) ? "@~#{s}" : "@#{s}"
1997
+ s.start_with?(/\d/) ? "@~#{s}" : "@#{s}"
2142
1998
  end
2143
1999
 
2144
2000
  def matchhead(val)
2145
- val && val =~ /^(?:(?:HEAD|@)([~^]\d*)?|H(\d+))$/ ? $2 || $1 || '' : nil
2001
+ val =~ /^(?:(?:HEAD|@)([~^]\d*)?|H(\d+))$/ ? $2 || $1 || '' : nil
2146
2002
  end
2147
2003
 
2148
2004
  def matchpathspec