squared 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -0
- data/README.ruby.md +21 -15
- data/lib/squared/common/format.rb +6 -4
- data/lib/squared/common/prompt.rb +3 -3
- data/lib/squared/common/shell.rb +9 -5
- data/lib/squared/common/system.rb +3 -3
- data/lib/squared/common/utils.rb +9 -0
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +25 -16
- data/lib/squared/workspace/project/base.rb +201 -140
- data/lib/squared/workspace/project/docker.rb +83 -70
- data/lib/squared/workspace/project/git.rb +234 -152
- data/lib/squared/workspace/project/node.rb +87 -34
- data/lib/squared/workspace/project/python.rb +55 -22
- data/lib/squared/workspace/project/ruby.rb +101 -58
- data/lib/squared/workspace/project/support/class.rb +66 -17
- data/lib/squared/workspace/repo.rb +47 -43
- data/lib/squared/workspace/series.rb +4 -4
- data/lib/squared/workspace/support/base.rb +17 -0
- data/lib/squared/workspace/support.rb +1 -0
- data/lib/squared/workspace.rb +0 -8
- data/squared.gemspec +2 -2
- metadata +2 -1
@@ -3,8 +3,8 @@
|
|
3
3
|
module Squared
|
4
4
|
module Workspace
|
5
5
|
module Git
|
6
|
-
GIT_REPO =
|
7
|
-
GIT_PROTO = %r{
|
6
|
+
GIT_REPO = Support.hashobj
|
7
|
+
GIT_PROTO = %r{\A(https?|ssh|git|file)://}i.freeze
|
8
8
|
private_constant :GIT_REPO, :GIT_PROTO
|
9
9
|
|
10
10
|
attr_reader :revfile
|
@@ -181,6 +181,9 @@ module Squared
|
|
181
181
|
}.freeze,
|
182
182
|
git: {
|
183
183
|
add: %w[N|intent-to-add refresh].freeze,
|
184
|
+
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
|
185
|
+
p|porcelain root score-debug f|show-name e|show-email n|show-number show-stats abbrev=i
|
186
|
+
contents=p date=q encoding=b ignore-rev=b ignore-revs-file=p reverse=q].freeze,
|
184
187
|
clean: %w[d x X f|force n|dry-run i|interactive q|quiet e|exclude=q].freeze,
|
185
188
|
mv: %w[k f|force n|dry-run v|verbose].freeze,
|
186
189
|
revert: %w[e S=bm? abort continue n|no-commit quit reference skip cleanup=b gpg-sign=b? m|mainline=i
|
@@ -244,10 +247,21 @@ module Squared
|
|
244
247
|
pop: %w[index].freeze,
|
245
248
|
apply: %w[index].freeze
|
246
249
|
}.freeze,
|
247
|
-
status: %w[u
|
250
|
+
status: %w[z u=bm? b|branch long s|short show-stash v|verbose column=b find-renames=i? ignore-submodules=b?
|
251
|
+
ignored=b? porcelain=b? untracked-files=b?].freeze,
|
252
|
+
submodule: {
|
253
|
+
status: %w[cached recursive].freeze,
|
254
|
+
update: %w[checkout f|force init merge N|no-fetch no-recommend-shallow no-single-branch recommend-shallow
|
255
|
+
rebase recursive remote single-branch depth=i filter=q jobs=i reference=b ref-format=q].freeze,
|
256
|
+
branch: %w[b|branch d|default].freeze,
|
257
|
+
sync: %w[recursive].freeze
|
258
|
+
}.freeze,
|
259
|
+
switch: %w[d|detach discard-changes f|force ignore-other-worktrees m|merge q|quiet conflict=b c|create=q
|
260
|
+
C|force-create=q orphan=q t|track=b].freeze,
|
248
261
|
tag: %w[n=im cleanup=b create-reflog i|ignore-case omit-empty color=b? column=b contains=b? format=q merged=b?
|
249
262
|
no-contains=b? no-merged=b? points-at=q sort=q trailer=q].freeze,
|
250
263
|
no: {
|
264
|
+
blame: %w[progress].freeze,
|
251
265
|
branch: %w[color color-moved column track].freeze,
|
252
266
|
checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
|
253
267
|
fetch: {
|
@@ -269,6 +283,8 @@ module Squared
|
|
269
283
|
rev_parse: %w[flags].freeze,
|
270
284
|
revert: %w[edit gpg-sign rerere-autoupdate].freeze,
|
271
285
|
show: %w[standard-notes].freeze,
|
286
|
+
status: %w[ahead-behind column renames].freeze,
|
287
|
+
switch: %w[guess progress recurse-submodules track].freeze,
|
272
288
|
tag: %w[column].freeze
|
273
289
|
}.freeze
|
274
290
|
}.freeze
|
@@ -290,10 +306,8 @@ module Squared
|
|
290
306
|
def populate(ws, **)
|
291
307
|
return if ws.series.exclude?(:pull, true)
|
292
308
|
|
293
|
-
namespace(
|
294
|
-
all = ws.task_join(
|
295
|
-
|
296
|
-
ws.format_desc(all, 'stash|rebase|autostash?,depend?')
|
309
|
+
namespace(ws.task_name('git')) do |ns|
|
310
|
+
ws.format_desc(all = ws.task_join(ns.scope.path, 'all'), 'stash|rebase|autostash?,depend?')
|
297
311
|
task 'all' do |_, args|
|
298
312
|
args = args.to_a
|
299
313
|
cmd = if args.include?('stash')
|
@@ -310,6 +324,7 @@ module Squared
|
|
310
324
|
cmd << ws.task_sync('build')
|
311
325
|
Common::Utils.task_invoke(*cmd, **ws.invokeargs)
|
312
326
|
end
|
327
|
+
|
313
328
|
ws.series.sync << all
|
314
329
|
ws.series.multiple << all
|
315
330
|
end
|
@@ -331,25 +346,27 @@ module Squared
|
|
331
346
|
'checkout' => %i[commit branch track detach path].freeze,
|
332
347
|
'commit' => %i[add all amend amend-orig fixup].freeze,
|
333
348
|
'diff' => %i[head branch files view between contain].freeze,
|
334
|
-
'fetch' => %i[origin remote].freeze,
|
349
|
+
'fetch' => %i[origin remote all].freeze,
|
335
350
|
'files' => %i[cached modified deleted others].freeze,
|
336
|
-
'git' => %i[add clean mv revert rm].freeze,
|
351
|
+
'git' => %i[add blame clean mv revert rm status].freeze,
|
337
352
|
'log' => %i[view between contain].freeze,
|
338
353
|
'merge' => %i[commit no-commit send].freeze,
|
339
|
-
'pull' => %i[origin remote].freeze,
|
354
|
+
'pull' => %i[origin remote all].freeze,
|
340
355
|
'rebase' => %i[branch onto send].freeze,
|
341
356
|
'refs' => %i[heads tags remote].freeze,
|
342
|
-
'reset' => %i[commit index patch mode].freeze,
|
357
|
+
'reset' => %i[commit index patch mode undo].freeze,
|
343
358
|
'restore' => %i[source staged worktree].freeze,
|
344
359
|
'rev' => %i[commit build output].freeze,
|
345
360
|
'show' => %i[format oneline textconv].freeze,
|
346
361
|
'stash' => %i[push pop apply branch drop clear list].freeze,
|
347
|
-
'
|
362
|
+
'submodule' => %i[status update branch url sync].freeze,
|
363
|
+
'switch' => %i[branch create detach].freeze,
|
348
364
|
'tag' => %i[add sign delete list].freeze
|
349
365
|
})
|
350
366
|
|
351
367
|
def initialize(*, **)
|
352
368
|
super
|
369
|
+
@submodule = basepath('.gitmodules').exist?
|
353
370
|
initialize_ref Git.ref if gitpath.exist?
|
354
371
|
end
|
355
372
|
|
@@ -359,11 +376,11 @@ module Squared
|
|
359
376
|
|
360
377
|
def populate(*, **)
|
361
378
|
super
|
362
|
-
return unless ref?(Git.ref)
|
379
|
+
return unless ref?(Git.ref) || @only
|
363
380
|
|
364
381
|
namespace name do
|
365
382
|
Git.subtasks do |action, flags|
|
366
|
-
next if
|
383
|
+
next if task_pass?(action)
|
367
384
|
|
368
385
|
namespace action do
|
369
386
|
flags.each do |flag|
|
@@ -381,11 +398,34 @@ module Squared
|
|
381
398
|
__send__(action, flag, args, remote: remote)
|
382
399
|
end
|
383
400
|
else
|
384
|
-
format_desc
|
401
|
+
format_desc(action, flag, 'opts*', after: flag == :all && action == 'pull' ? 'pattern*' : nil)
|
385
402
|
task flag do |_, args|
|
386
403
|
__send__ action, flag, args.to_a
|
387
404
|
end
|
388
405
|
end
|
406
|
+
when 'submodule'
|
407
|
+
break unless @submodule
|
408
|
+
|
409
|
+
case flag
|
410
|
+
when :branch
|
411
|
+
format_desc action, flag, 'path,opts*'
|
412
|
+
task flag, [:path] do |_, args|
|
413
|
+
path = param_guard(action, flag, args: args, key: :path)
|
414
|
+
submodule(flag, args.extras, path: path)
|
415
|
+
end
|
416
|
+
when :url
|
417
|
+
format_desc action, flag, 'path,url,opts*'
|
418
|
+
task flag, [:path, :url] do |_, args|
|
419
|
+
path = param_guard(action, flag, args: args, key: :path)
|
420
|
+
url = param_guard(action, flag, args: args, key: :url)
|
421
|
+
submodule(flag, args.extras, path: path, url: url)
|
422
|
+
end
|
423
|
+
else
|
424
|
+
format_desc action, flag, 'opts*,path*'
|
425
|
+
task flag do |_, args|
|
426
|
+
submodule flag, args.to_a
|
427
|
+
end
|
428
|
+
end
|
389
429
|
when 'commit'
|
390
430
|
case flag
|
391
431
|
when :all
|
@@ -625,10 +665,7 @@ module Squared
|
|
625
665
|
task flag, [:upstream, :name] do |_, args|
|
626
666
|
if (ref = args.upstream)
|
627
667
|
target = args.name
|
628
|
-
if ref.
|
629
|
-
ref = ref[1..-1]
|
630
|
-
remote = true
|
631
|
-
end
|
668
|
+
remote = true if ref.delete_prefix!('~')
|
632
669
|
else
|
633
670
|
ref, remote, target = choice_refs('Choose a remote', 'remotes', accept: [['Push?', true]],
|
634
671
|
values: ['Enter branch name'])
|
@@ -681,10 +718,10 @@ module Squared
|
|
681
718
|
when :create
|
682
719
|
format_desc action, flag, '(^)name,ref?=HEAD|:'
|
683
720
|
task flag, [:name, :commit] do |_, args|
|
684
|
-
|
721
|
+
branch = param_guard(action, flag, args: args, key: :name)
|
685
722
|
commit = commithead args.commit
|
686
723
|
commit, track = choice_commit(values: ['Track? [Y|n]'], force: false) if commit == ':'
|
687
|
-
switch(flag,
|
724
|
+
switch(flag, branch: branch, commit: commit, track: track)
|
688
725
|
end
|
689
726
|
when :detach
|
690
727
|
format_desc action, flag, 'ref?=HEAD'
|
@@ -692,11 +729,16 @@ module Squared
|
|
692
729
|
commit = commithead(args.commit) || choice_commit(force: false)
|
693
730
|
switch(flag, commit: commit)
|
694
731
|
end
|
695
|
-
when :
|
696
|
-
format_desc action, flag, '
|
697
|
-
task flag, [:
|
698
|
-
|
699
|
-
|
732
|
+
when :branch
|
733
|
+
format_desc action, flag, 'name|:,opts*'
|
734
|
+
task flag, [:name] do |_, args|
|
735
|
+
if (branch = args.name)
|
736
|
+
args = args.extras
|
737
|
+
branch = nil if branch == ':'
|
738
|
+
else
|
739
|
+
args = []
|
740
|
+
end
|
741
|
+
switch(flag, args, branch: branch || choice_refs('Choose a branch'))
|
700
742
|
end
|
701
743
|
end
|
702
744
|
when 'reset'
|
@@ -717,10 +759,10 @@ module Squared
|
|
717
759
|
end
|
718
760
|
print_success if success?(reset(flag, args, commit: commit))
|
719
761
|
end
|
720
|
-
when :index
|
721
|
-
format_desc
|
762
|
+
when :index, :undo
|
763
|
+
format_desc(action, flag, flag == :index ? 'opts*,pathspec*' : nil)
|
722
764
|
task flag do |_, args|
|
723
|
-
reset
|
765
|
+
reset(flag, flag == :index ? args.to_a : [])
|
724
766
|
end
|
725
767
|
when :mode
|
726
768
|
format_desc action, flag, 'mode,ref?=HEAD|:'
|
@@ -819,7 +861,7 @@ module Squared
|
|
819
861
|
rev_parse(flag, ref: ref, size: size)
|
820
862
|
end
|
821
863
|
when :build
|
822
|
-
format_desc action, flag,
|
864
|
+
format_desc action, flag, 'opts*'
|
823
865
|
task flag do |_, args|
|
824
866
|
revbuild flag, args.to_a
|
825
867
|
end
|
@@ -836,7 +878,7 @@ module Squared
|
|
836
878
|
ls_remote(flag, args.extras, remote: args.remote)
|
837
879
|
end
|
838
880
|
else
|
839
|
-
format_desc
|
881
|
+
format_desc(action, flag, 'opts*,pattern*', after: action == 'files' ? 'pathspec*' : nil)
|
840
882
|
task flag do |_, args|
|
841
883
|
__send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
|
842
884
|
end
|
@@ -862,19 +904,14 @@ module Squared
|
|
862
904
|
args = args.to_a
|
863
905
|
if args.empty? || args.last == ':'
|
864
906
|
files = []
|
865
|
-
status_data.each
|
866
|
-
case (flag == :staged ? line[2] : line[1])
|
867
|
-
when /[AMDRTC]/
|
868
|
-
files << line[0]
|
869
|
-
end
|
870
|
-
end
|
907
|
+
status_data.each { |row| files << row[0] if row[flag == :staged ? 2 : 1].match?(/[AMDRTC]/) }
|
871
908
|
unless files.empty?
|
872
909
|
files = choice_index('Select a file', files, multiple: true, force: false,
|
873
910
|
accept: 'Restore?')
|
874
911
|
end
|
875
912
|
args.pop
|
876
913
|
args, glob = args.partition { |val| val.match?(/^(?:[a-z-]+=|[^*]+$)/) }
|
877
|
-
|
914
|
+
files.concat(glob)
|
878
915
|
next if args.empty? && files.empty?
|
879
916
|
end
|
880
917
|
restore(flag, args, files: files)
|
@@ -882,13 +919,17 @@ module Squared
|
|
882
919
|
end
|
883
920
|
when 'git'
|
884
921
|
before = case flag
|
922
|
+
when :blame then 'file'
|
885
923
|
when :mv then 'source+,destination'
|
886
924
|
when :revert then 'commit+' end
|
887
925
|
format_desc(action, flag, 'opts*', before: before, after: case flag
|
888
|
-
when :add
|
889
|
-
|
926
|
+
when :add
|
927
|
+
'pathspec*,pattern*'
|
928
|
+
when :clean, :rm, :status
|
929
|
+
'pathspec*'
|
930
|
+
end)
|
890
931
|
task flag do |_, args|
|
891
|
-
git flag, args.to_a
|
932
|
+
__send__(flag == :status ? :status : :git, flag, args.to_a)
|
892
933
|
end
|
893
934
|
end
|
894
935
|
end
|
@@ -912,11 +953,44 @@ module Squared
|
|
912
953
|
super
|
913
954
|
end
|
914
955
|
|
915
|
-
def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil)
|
956
|
+
def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil, hint: nil)
|
916
957
|
cmd, opts = git_session('pull', opts: opts)
|
917
|
-
|
958
|
+
cmd << '--autostash' if option('autostash')
|
959
|
+
case flag
|
960
|
+
when :rebase
|
918
961
|
cmd << '--rebase'
|
919
|
-
|
962
|
+
when :all
|
963
|
+
unless git_spawn('status -s -z --untracked-files=all').empty?
|
964
|
+
if confirm('Stash local changes?', 'Y')
|
965
|
+
git_spawn 'stash push --keep-index --quiet'
|
966
|
+
elsif !(force = confirm('Force checkout?', 'N'))
|
967
|
+
return
|
968
|
+
end
|
969
|
+
end
|
970
|
+
op = OptionPartition.new(opts, OPT_GIT[:pull], cmd, project: self, no: OPT_GIT[:no][:pull])
|
971
|
+
reg = if op.empty?
|
972
|
+
[]
|
973
|
+
else
|
974
|
+
opts = opts.reject { |val| op.extras.include?(val) }
|
975
|
+
matchmap op
|
976
|
+
end
|
977
|
+
session_done op.target
|
978
|
+
heads = []
|
979
|
+
cur = nil
|
980
|
+
foreachref('heads', format: '%(if)%(HEAD)%(then)* %(end)%(refname:short)').each do |line|
|
981
|
+
line.chomp!
|
982
|
+
cur ||= line.delete_prefix!('* ')
|
983
|
+
heads << line if matchany?(line, reg)
|
984
|
+
end
|
985
|
+
raise_error('head not found', hint: 'for-each-ref') unless cur
|
986
|
+
opts << 'ff-only' if opts.empty? && !option('ff-only', equals: '0')
|
987
|
+
(heads.dup << cur).each_with_index do |branch, index|
|
988
|
+
next unless (index < heads.size && cur != branch) || index == heads.size
|
989
|
+
|
990
|
+
git_spawn 'switch --quiet', force && '--force', shell_quote(branch)
|
991
|
+
pull(nil, opts, sync: false, hint: branch) if heads.include?(branch)
|
992
|
+
end
|
993
|
+
return
|
920
994
|
else
|
921
995
|
cmd << '--autostash' if flag == :autostash
|
922
996
|
option('rebase', ignore: false) do |val|
|
@@ -935,7 +1009,7 @@ module Squared
|
|
935
1009
|
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: color(:red), index: 4 },
|
936
1010
|
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(.*)$/, styles: color(:green), index: 3 }
|
937
1011
|
]
|
938
|
-
end, **threadargs)
|
1012
|
+
end, hint: hint, **threadargs)
|
939
1013
|
end
|
940
1014
|
|
941
1015
|
def rebase(flag = nil, opts = [], sync: invoked_sync?('rebase', flag), commit: nil, upstream: nil, branch: nil,
|
@@ -972,6 +1046,7 @@ module Squared
|
|
972
1046
|
|
973
1047
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
974
1048
|
opts = git_session('fetch', opts: opts).last
|
1049
|
+
opts << 'all' if flag == :all || option('all')
|
975
1050
|
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
|
976
1051
|
remote: remote, flag: flag, from: :fetch)
|
977
1052
|
source(sync: sync, **threadargs)
|
@@ -1014,15 +1089,15 @@ module Squared
|
|
1014
1089
|
cmd, opts = git_session('stash', flag, opts: opts)
|
1015
1090
|
list = OPT_GIT[:stash][:common] + OPT_GIT[:stash].fetch(flag, [])
|
1016
1091
|
if flag == :list
|
1017
|
-
list += collect_hash
|
1018
|
-
no = collect_hash
|
1092
|
+
list += collect_hash OPT_GIT[:log]
|
1093
|
+
no = collect_hash OPT_GIT[:no][:log]
|
1019
1094
|
end
|
1020
1095
|
op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: flag == :push ? matchpathspec : nil)
|
1021
1096
|
case flag
|
1022
1097
|
when :push
|
1023
1098
|
append_pathspec op.extras
|
1024
1099
|
when :pop, :apply, :drop, :branch
|
1025
|
-
if op.
|
1100
|
+
if op.remove(':')
|
1026
1101
|
if flag == :branch
|
1027
1102
|
if op.empty?
|
1028
1103
|
values = [['Branch name', true]]
|
@@ -1055,29 +1130,34 @@ module Squared
|
|
1055
1130
|
end
|
1056
1131
|
else
|
1057
1132
|
git_session('stash', 'push', opts: opts)
|
1058
|
-
append_option(OPT_GIT[:stash][:push]
|
1133
|
+
append_option(OptionPartition.select(OPT_GIT[:stash][:push], no: false), no: true, ignore: false)
|
1059
1134
|
append_message
|
1060
1135
|
end
|
1061
1136
|
source(banner: !quiet?, sync: sync, **threadargs)
|
1062
1137
|
end
|
1063
1138
|
|
1064
|
-
def status(
|
1065
|
-
cmd = git_session
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1139
|
+
def status(flag = nil, opts = [])
|
1140
|
+
cmd, opts = git_session('status', opts: opts)
|
1141
|
+
if flag
|
1142
|
+
op = OptionPartition.new(opts, OPT_GIT[:status], cmd, project: self, no: OPT_GIT[:no][:status])
|
1143
|
+
append_pathspec op.extras
|
1144
|
+
else
|
1145
|
+
cmd << (option('long') ? '--long' : '--short')
|
1146
|
+
cmd << '--branch' if option('branch')
|
1147
|
+
option('ignore-submodules', ignore: false) do |val|
|
1148
|
+
cmd << basic_option('ignore-submodules', case val
|
1149
|
+
when '0', 'none'
|
1150
|
+
'none'
|
1151
|
+
when '1', 'untracked'
|
1152
|
+
'untracked'
|
1153
|
+
when '2', 'dirty'
|
1154
|
+
'dirty'
|
1155
|
+
else
|
1156
|
+
'all'
|
1157
|
+
end)
|
1158
|
+
end
|
1159
|
+
append_pathspec
|
1079
1160
|
end
|
1080
|
-
append_pathspec
|
1081
1161
|
if verbose
|
1082
1162
|
r = color(:red)
|
1083
1163
|
g = color(:green)
|
@@ -1119,7 +1199,7 @@ module Squared
|
|
1119
1199
|
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.call : @revbuild || {}
|
1120
1200
|
case flag
|
1121
1201
|
when :build
|
1122
|
-
op = OptionPartition.new(opts,
|
1202
|
+
op = OptionPartition.new(opts, %w[ignore-submodules=b? ignored=b? untracked-files=b?], project: self)
|
1123
1203
|
op.clear(append: true)
|
1124
1204
|
args = op.to_a
|
1125
1205
|
else
|
@@ -1146,10 +1226,7 @@ module Squared
|
|
1146
1226
|
rescue StandardError => e
|
1147
1227
|
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1148
1228
|
else
|
1149
|
-
|
1150
|
-
msg = sub_style('completed', styles: theme[:active])
|
1151
|
-
puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
|
1152
|
-
end
|
1229
|
+
print_status(name, subject: 'revbuild', start: start, from: :completed)
|
1153
1230
|
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
|
1154
1231
|
sync: sync, utc: 'build')
|
1155
1232
|
end
|
@@ -1179,6 +1256,9 @@ module Squared
|
|
1179
1256
|
when :patch
|
1180
1257
|
cmd << '--patch'
|
1181
1258
|
append_pathspec(refs, pass: false)
|
1259
|
+
when :undo
|
1260
|
+
cmd << '--hard HEAD@{1}'
|
1261
|
+
ref = false
|
1182
1262
|
end
|
1183
1263
|
unless ref == false
|
1184
1264
|
append_commit(ref, head: true)
|
@@ -1189,20 +1269,15 @@ module Squared
|
|
1189
1269
|
|
1190
1270
|
def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil, merge: false)
|
1191
1271
|
cmd, opts = git_session('checkout', opts: opts)
|
1192
|
-
append_option 'force', 'merge'
|
1272
|
+
append_option 'force', 'f', 'merge'
|
1193
1273
|
case flag
|
1194
1274
|
when :branch
|
1195
1275
|
cmd << '--detach' if detach == 'd' || option('detach')
|
1196
1276
|
append_option('track', equals: true)
|
1197
1277
|
cmd << (create ? quote_option(create, branch) : branch) << commit
|
1198
1278
|
when :track
|
1199
|
-
|
1200
|
-
|
1201
|
-
opt = 'B'
|
1202
|
-
branch = branch[1..-1]
|
1203
|
-
end
|
1204
|
-
cmd << quote_option(opt || 'b', branch)
|
1205
|
-
end
|
1279
|
+
|
1280
|
+
cmd << quote_option(branch.delete_prefix!('^') ? 'B' : 'b', branch) if branch
|
1206
1281
|
cmd << '--track' << shell_quote(origin)
|
1207
1282
|
when :detach
|
1208
1283
|
cmd << '-m' if merge
|
@@ -1231,7 +1306,7 @@ module Squared
|
|
1231
1306
|
elsif !session_arg?('s', 'sign', 'u', 'local-user')
|
1232
1307
|
cmd << '--annotate'
|
1233
1308
|
end
|
1234
|
-
cmd << '--force' if option('force')
|
1309
|
+
cmd << '--force' if option('force', 'f')
|
1235
1310
|
if !commit && message && (sha = commithash(message))
|
1236
1311
|
commit = sha
|
1237
1312
|
message = nil
|
@@ -1262,7 +1337,7 @@ module Squared
|
|
1262
1337
|
first: matchpathspec)
|
1263
1338
|
case flag
|
1264
1339
|
when :between, :contain
|
1265
|
-
op
|
1340
|
+
op.add_quote(range.join(flag == :between ? '..' : '...'))
|
1266
1341
|
else
|
1267
1342
|
op.merge(index)
|
1268
1343
|
end
|
@@ -1291,13 +1366,13 @@ module Squared
|
|
1291
1366
|
op.merge(range)
|
1292
1367
|
when :between, :contain
|
1293
1368
|
op.delete('--merge-base')
|
1294
|
-
op
|
1369
|
+
op.add_quote(range.join(flag == :between ? '..' : '...'))
|
1295
1370
|
else
|
1296
1371
|
op << '--merge-base' if option('merge-base')
|
1297
|
-
op
|
1372
|
+
op.add_quote(branch) if branch
|
1298
1373
|
if !index.empty?
|
1299
1374
|
if op.arg?('cached')
|
1300
|
-
raise_error("one commit only: #{index.join(', ')}", hint: '
|
1375
|
+
raise_error("one commit only: #{index.join(', ')}", hint: 'cached') if index.size > 1
|
1301
1376
|
op << index.first
|
1302
1377
|
else
|
1303
1378
|
op.merge(index)
|
@@ -1427,13 +1502,13 @@ module Squared
|
|
1427
1502
|
'--track'
|
1428
1503
|
end
|
1429
1504
|
end
|
1430
|
-
cmd << '--force' if option('force')
|
1505
|
+
cmd << '--force' if option('force', 'f')
|
1431
1506
|
cmd << shell_quote(target)
|
1432
1507
|
cmd << shell_quote(ref) if ref
|
1433
1508
|
when :track
|
1434
1509
|
raise_error('invalid upstream', hint: ref) unless ref.include?('/')
|
1435
|
-
if ref.
|
1436
|
-
cmd << '--unset-upstream' << shell_quote(ref
|
1510
|
+
if ref.delete_prefix!('^')
|
1511
|
+
cmd << '--unset-upstream' << shell_quote(ref)
|
1437
1512
|
remote = false
|
1438
1513
|
stdout = true
|
1439
1514
|
else
|
@@ -1442,7 +1517,7 @@ module Squared
|
|
1442
1517
|
end
|
1443
1518
|
when :delete
|
1444
1519
|
remote&.each do |val|
|
1445
|
-
source git_output('push
|
1520
|
+
source git_output('push --delete', *val.split('/', 2).map { |s| shell_quote(s) })
|
1446
1521
|
end
|
1447
1522
|
force, list = refs.partition { |val| val.start_with?(/[~^]/) }
|
1448
1523
|
force.each do |val|
|
@@ -1458,7 +1533,7 @@ module Squared
|
|
1458
1533
|
remote = nil
|
1459
1534
|
when :move, :copy
|
1460
1535
|
flag = "-#{flag.to_s[0]}"
|
1461
|
-
cmd << (option('force') ? flag.upcase : flag)
|
1536
|
+
cmd << (option('force', 'f') ? flag.upcase : flag)
|
1462
1537
|
refs.compact.each { |val| cmd << shell_quote(val) }
|
1463
1538
|
stdout = true
|
1464
1539
|
when :current
|
@@ -1468,7 +1543,7 @@ module Squared
|
|
1468
1543
|
when :list
|
1469
1544
|
op = OptionPartition.new(opts, OPT_GIT[:branch], cmd << '--list',
|
1470
1545
|
project: self, no: OPT_GIT[:no][:branch], single: /\Av+\z/)
|
1471
|
-
op.each { |val| op
|
1546
|
+
op.each { |val| op.add_quote(val) }
|
1472
1547
|
out, banner, from = source(io: true)
|
1473
1548
|
print_item banner
|
1474
1549
|
ret = write_lines(out, sub: [
|
@@ -1514,33 +1589,47 @@ module Squared
|
|
1514
1589
|
if !ref
|
1515
1590
|
print_success if flag == :create
|
1516
1591
|
elsif remote && target
|
1517
|
-
source git_output('push
|
1592
|
+
source git_output('push -u', shell_quote(ref.split('/', 2).first), shell_quote(target))
|
1518
1593
|
end
|
1519
1594
|
end
|
1520
1595
|
|
1521
|
-
def switch(flag, opts = [],
|
1522
|
-
cmd = git_session('switch', opts: opts)
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1596
|
+
def switch(flag, opts = [], branch: nil, commit: nil, track: nil)
|
1597
|
+
cmd, opts = git_session('switch', opts: opts)
|
1598
|
+
cmd << '--force' if option('force', 'f')
|
1599
|
+
if flag == :branch
|
1600
|
+
op = OptionPartition.new(opts, OPT_GIT[:switch], cmd, project: self, no: OPT_GIT[:no][:switch])
|
1601
|
+
op.add_quote(branch)
|
1602
|
+
else
|
1603
|
+
case flag
|
1604
|
+
when :create
|
1605
|
+
cmd << quote_option(branch.delete_prefix!('^') ? 'C' : 'c', branch)
|
1606
|
+
cmd << case (track ||= option('track', ignore: false))
|
1607
|
+
when 'n', 'N', '0', 'false'
|
1608
|
+
'--no-track'
|
1609
|
+
when 'y', 'Y', '1', 'true'
|
1610
|
+
'--track'
|
1611
|
+
when 'direct', 'inherit'
|
1612
|
+
basic_option 'track', track
|
1613
|
+
end
|
1614
|
+
when :detach
|
1615
|
+
cmd << "--#{flag}"
|
1529
1616
|
end
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
when :
|
1540
|
-
|
1617
|
+
append_head commit
|
1618
|
+
end
|
1619
|
+
source
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
def submodule(flag, opts = [], path: nil, url: nil)
|
1623
|
+
cmd, opts = git_session('submodule', opts: opts)
|
1624
|
+
op = OptionPartition.new(opts, OPT_GIT[:submodule].fetch(flag, []), cmd, project: self)
|
1625
|
+
case flag
|
1626
|
+
when :branch, :url
|
1627
|
+
op << '--'
|
1628
|
+
op.add_path(path) if path
|
1629
|
+
op.add_quote(url) if url
|
1630
|
+
else
|
1631
|
+
op.splice(path: true)
|
1541
1632
|
end
|
1542
|
-
cmd << '--force' if option('force')
|
1543
|
-
append_head commit
|
1544
1633
|
source
|
1545
1634
|
end
|
1546
1635
|
|
@@ -1609,7 +1698,7 @@ module Squared
|
|
1609
1698
|
cmd, opts = git_session('ls-remote', '--refs', opts: opts)
|
1610
1699
|
cmd << "--#{flag}" unless flag == :remote
|
1611
1700
|
op = OptionPartition.new(opts, OPT_GIT[:ls_remote], cmd, project: self)
|
1612
|
-
op
|
1701
|
+
op.add_quote(remote) if remote
|
1613
1702
|
out, banner, from = source(io: true)
|
1614
1703
|
print_item banner
|
1615
1704
|
ret = write_lines(out, grep: op.extras, prefix: "refs/#{flag}/")
|
@@ -1619,6 +1708,7 @@ module Squared
|
|
1619
1708
|
def ls_files(flag, opts = [])
|
1620
1709
|
cmd, opts = git_session('ls-files', "--#{flag}", opts: opts)
|
1621
1710
|
op = OptionPartition.new(opts, OPT_GIT[:ls_files], cmd, project: self)
|
1711
|
+
op.splice(path: true, pattern: true)
|
1622
1712
|
out, banner, from = source(io: true)
|
1623
1713
|
print_item banner
|
1624
1714
|
ret = write_lines(out, grep: op.extras)
|
@@ -1627,10 +1717,16 @@ module Squared
|
|
1627
1717
|
|
1628
1718
|
def git(flag, opts = [])
|
1629
1719
|
cmd, opts = git_session(flag, opts: opts)
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1720
|
+
op = OptionPartition.new(opts, OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, []), cmd,
|
1721
|
+
project: self, no: OPT_GIT[:no][flag], first: case flag
|
1722
|
+
when :blame, :revert
|
1723
|
+
nil
|
1724
|
+
else matchpathspec end)
|
1633
1725
|
case flag
|
1726
|
+
when :blame
|
1727
|
+
raise_error 'no file found' unless (n = op.index { |s| (path + s).file? })
|
1728
|
+
op << '--' << shell_quote(path + op.delete_at(n))
|
1729
|
+
op.clear
|
1634
1730
|
when :revert
|
1635
1731
|
if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
|
1636
1732
|
op.clear
|
@@ -1641,16 +1737,16 @@ module Squared
|
|
1641
1737
|
end
|
1642
1738
|
when :add, :clean
|
1643
1739
|
if flag == :add && !op.arg?('pathspec-from-file')
|
1644
|
-
grep, list = op.
|
1645
|
-
|
1646
|
-
red = color(:red)
|
1740
|
+
grep, list = op.partition { |val| OptionPartition.pattern?(val) }
|
1741
|
+
unless grep.empty? && !list.empty?
|
1647
1742
|
grep.map! { |val| Regexp.new(val[1..-2]) }
|
1648
|
-
files =
|
1649
|
-
|
1743
|
+
files = [].tap do |out|
|
1744
|
+
status_data.each do |a, b|
|
1745
|
+
next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
|
1650
1746
|
|
1651
|
-
|
1747
|
+
out << "#{sub_style(b, styles: color(:red))} #{a}"
|
1748
|
+
end
|
1652
1749
|
end
|
1653
|
-
.compact
|
1654
1750
|
unless files.empty?
|
1655
1751
|
files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/,
|
1656
1752
|
accept: [['Add?', false, true]])
|
@@ -1658,7 +1754,7 @@ module Squared
|
|
1658
1754
|
op.swap(list + files)
|
1659
1755
|
end
|
1660
1756
|
end
|
1661
|
-
return source(git_session('status
|
1757
|
+
return source(git_session('status -s'), banner: false) unless append_pathspec(op.extras)
|
1662
1758
|
|
1663
1759
|
verbose = flag == :add && !op.arg?('verbose')
|
1664
1760
|
print_success if success?(source) && verbose
|
@@ -1688,7 +1784,7 @@ module Squared
|
|
1688
1784
|
private
|
1689
1785
|
|
1690
1786
|
def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
|
1691
|
-
multiple: false, from: nil, **kwargs)
|
1787
|
+
multiple: false, hint: nil, from: nil, **kwargs)
|
1692
1788
|
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
1693
1789
|
if io && banner == false
|
1694
1790
|
from = nil
|
@@ -1706,7 +1802,8 @@ module Squared
|
|
1706
1802
|
cmd = session_done cmd
|
1707
1803
|
log&.info cmd
|
1708
1804
|
banner = if banner
|
1709
|
-
|
1805
|
+
banner = (banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), '')
|
1806
|
+
format_banner(hint ? "#{banner} (#{hint})" : banner, banner: true)
|
1710
1807
|
end
|
1711
1808
|
on :first, from
|
1712
1809
|
begin
|
@@ -1745,11 +1842,7 @@ module Squared
|
|
1745
1842
|
end
|
1746
1843
|
end
|
1747
1844
|
rescue StandardError => e
|
1748
|
-
|
1749
|
-
ret = on :error, from, e
|
1750
|
-
raise if exception && ret != true
|
1751
|
-
|
1752
|
-
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1845
|
+
on_error(e, from, pass: true)
|
1753
1846
|
nil
|
1754
1847
|
else
|
1755
1848
|
on :last, from
|
@@ -1758,16 +1851,7 @@ module Squared
|
|
1758
1851
|
end
|
1759
1852
|
|
1760
1853
|
def write_lines(data, grep: [], prefix: nil, sub: nil, banner: nil, loglevel: nil, pass: false, first: false)
|
1761
|
-
grep =
|
1762
|
-
grep.map do |val|
|
1763
|
-
if val.is_a?(Regexp)
|
1764
|
-
val
|
1765
|
-
else
|
1766
|
-
val = ".*#{val}" if prefix && !val.sub!(/\A(\^|\\A)/, '')
|
1767
|
-
Regexp.new("#{prefix}#{val == '*' ? '.+' : val}")
|
1768
|
-
end
|
1769
|
-
end
|
1770
|
-
end
|
1854
|
+
grep = grep.empty? ? nil : matchmap(grep, prefix)
|
1771
1855
|
sub = nil if stdin?
|
1772
1856
|
ret = 0
|
1773
1857
|
out = []
|
@@ -1841,8 +1925,7 @@ module Squared
|
|
1841
1925
|
glob = kwargs.fetch(:include, [])
|
1842
1926
|
pass = kwargs.fetch(:exclude, [])
|
1843
1927
|
ret = {}
|
1844
|
-
status_data(*args).each do |
|
1845
|
-
file = line.first
|
1928
|
+
status_data(*args).each do |file,|
|
1846
1929
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1847
1930
|
next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1848
1931
|
|
@@ -1852,17 +1935,17 @@ module Squared
|
|
1852
1935
|
end
|
1853
1936
|
|
1854
1937
|
def status_data(*args)
|
1855
|
-
|
1856
|
-
|
1857
|
-
|
1938
|
+
[].tap do |ret|
|
1939
|
+
git_spawn('status -z -uall', *args).split("\x0").each do |line|
|
1940
|
+
next unless line =~ /^(.)(.) (.+)$/
|
1858
1941
|
|
1859
|
-
|
1942
|
+
ret << [$3, $2, $1]
|
1943
|
+
end
|
1860
1944
|
end
|
1861
|
-
ret
|
1862
1945
|
end
|
1863
1946
|
|
1864
1947
|
def append_pull(opts, list, target: @session, flag: nil, no: nil, remote: nil, from: nil)
|
1865
|
-
target << '--force' if option('force', target: target)
|
1948
|
+
target << '--force' if option('force', 'f', target: target)
|
1866
1949
|
append_submodules(target: target, from: from)
|
1867
1950
|
return if !remote && opts.empty?
|
1868
1951
|
|
@@ -1920,7 +2003,7 @@ module Squared
|
|
1920
2003
|
option_clear files
|
1921
2004
|
true
|
1922
2005
|
else
|
1923
|
-
option('pathspec', target: target) { |val| files = split_escape
|
2006
|
+
option('pathspec', target: target) { |val| files = split_escape(val) } if files.empty?
|
1924
2007
|
files = projectmap(files, parent: parent, pass: pass)
|
1925
2008
|
if !files.empty?
|
1926
2009
|
target << '--' << files.join(' ')
|
@@ -1978,12 +2061,11 @@ module Squared
|
|
1978
2061
|
end
|
1979
2062
|
|
1980
2063
|
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
1981
|
-
dir = worktree ? [
|
2064
|
+
dir = worktree ? [quote_option('work-tree', path), quote_option('git-dir', gitpath)] : []
|
1982
2065
|
return session('git', *dir, *cmd, **kwargs) unless opts
|
1983
2066
|
|
1984
2067
|
op = OptionPartition.new(opts, OPT_GIT[:common], dir, project: self)
|
1985
|
-
|
1986
|
-
[ret, op.extras]
|
2068
|
+
[session('git', *op.to_a, *cmd, **kwargs), op.extras]
|
1987
2069
|
end
|
1988
2070
|
|
1989
2071
|
def git_output(*cmd, **kwargs)
|