squared 0.6.8 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +106 -1
- data/README.md +239 -200
- data/lib/squared/common/format.rb +9 -10
- data/lib/squared/common/prompt.rb +27 -24
- data/lib/squared/common/shell.rb +16 -17
- data/lib/squared/common/system.rb +29 -20
- data/lib/squared/common/utils.rb +43 -54
- data/lib/squared/config.rb +17 -16
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +292 -160
- data/lib/squared/workspace/project/base.rb +557 -454
- data/lib/squared/workspace/project/docker.rb +153 -133
- data/lib/squared/workspace/project/git.rb +187 -150
- data/lib/squared/workspace/project/node.rb +90 -88
- data/lib/squared/workspace/project/python.rb +237 -140
- data/lib/squared/workspace/project/ruby.rb +457 -329
- data/lib/squared/workspace/project/support/class.rb +12 -6
- data/lib/squared/workspace/project/support/optionpartition.rb +62 -43
- data/lib/squared/workspace/project/support/utils.rb +68 -0
- data/lib/squared/workspace/project.rb +0 -7
- data/lib/squared/workspace/repo.rb +234 -169
- data/lib/squared/workspace/series.rb +91 -86
- data/lib/squared/workspace/support/base.rb +15 -1
- metadata +3 -2
|
@@ -84,7 +84,7 @@ module Squared
|
|
|
84
84
|
def revbuild(file: nil)
|
|
85
85
|
@revfile = @home.join(file || "#{@main}.revb")
|
|
86
86
|
@revdoc = JSON.parse(@revfile.read) if @revfile.exist?
|
|
87
|
-
rescue
|
|
87
|
+
rescue => e
|
|
88
88
|
@revfile = nil
|
|
89
89
|
warn log_warn(e, pass: true)
|
|
90
90
|
self
|
|
@@ -117,7 +117,7 @@ module Squared
|
|
|
117
117
|
|
|
118
118
|
def rev_timesince(*keys, clock: false)
|
|
119
119
|
epoch = time_epoch - rev_entry(*keys).to_i
|
|
120
|
-
rescue
|
|
120
|
+
rescue
|
|
121
121
|
nil
|
|
122
122
|
else
|
|
123
123
|
time_format(epoch, clock: clock)
|
|
@@ -140,7 +140,7 @@ module Squared
|
|
|
140
140
|
rev_timeutc(name, utc) if utc
|
|
141
141
|
end
|
|
142
142
|
File.write(@revfile, JSON.pretty_generate(@revdoc))
|
|
143
|
-
rescue
|
|
143
|
+
rescue => e
|
|
144
144
|
log&.debug e
|
|
145
145
|
warn log_warn(e, pass: true) if warning
|
|
146
146
|
ensure
|
|
@@ -190,7 +190,8 @@ module Squared
|
|
|
190
190
|
revert: %w[e S=bm? n|no-commit reference cleanup=b gpg-sign=b? m|mainline=i s|signoff strategy=b
|
|
191
191
|
X|strategy-option=b].freeze,
|
|
192
192
|
rm: %w[r cached f|force n|dry-run ignore-unmatch pathspec-file-nul q|quiet sparse
|
|
193
|
-
pathspec-from-file=p].freeze
|
|
193
|
+
pathspec-from-file=p].freeze,
|
|
194
|
+
'sparse-checkout': %w[cone sparse-index no-cone no-sparse-index skip-checks].freeze
|
|
194
195
|
}.freeze,
|
|
195
196
|
log: {
|
|
196
197
|
base: %w[L=qm all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
|
|
@@ -242,6 +243,10 @@ module Squared
|
|
|
242
243
|
show-object-format=b? since=q tags=q? until=q].freeze,
|
|
243
244
|
show: %w[t combined-all-paths no-diff-merges remerge-diff show-notes-by-default show-signature diff-merges=b
|
|
244
245
|
encoding=b expand-tabs=i notes=q show-notes=q?].freeze,
|
|
246
|
+
sparse_checkout: {
|
|
247
|
+
add: %w[skip-checks].freeze,
|
|
248
|
+
clean: %w[n f v].freeze
|
|
249
|
+
}.freeze,
|
|
245
250
|
stash: {
|
|
246
251
|
common: %w[q|quiet].freeze,
|
|
247
252
|
push: %w[a|all u|include-untracked k|keep-index no-keep-index no-include-untracked pathspec-file-nul p|patch
|
|
@@ -287,6 +292,10 @@ module Squared
|
|
|
287
292
|
rev_parse: %w[flags].freeze,
|
|
288
293
|
revert: %w[edit gpg-sign rerere-autoupdate].freeze,
|
|
289
294
|
show: %w[standard-notes].freeze,
|
|
295
|
+
sparse_checkout: {
|
|
296
|
+
reapply: %w[cone sparse-index].freeze,
|
|
297
|
+
clean: %w[dry-run force verbose].freeze
|
|
298
|
+
}.freeze,
|
|
290
299
|
status: %w[ahead-behind column renames].freeze,
|
|
291
300
|
switch: %w[guess progress recurse-submodules track].freeze,
|
|
292
301
|
tag: %w[column].freeze
|
|
@@ -326,7 +335,7 @@ module Squared
|
|
|
326
335
|
'diff' => %i[head branch files view between contain].freeze,
|
|
327
336
|
'fetch' => %i[origin remote all].freeze,
|
|
328
337
|
'files' => %i[cached modified deleted others].freeze,
|
|
329
|
-
'git' => %i[add blame clean grep mv revert rm status].freeze,
|
|
338
|
+
'git' => %i[add blame clean grep mv revert rm sparse-checkout status].freeze,
|
|
330
339
|
'log' => %i[view grep between contain].freeze,
|
|
331
340
|
'merge' => %i[commit no-commit send].freeze,
|
|
332
341
|
'pull' => %i[origin remote all].freeze,
|
|
@@ -334,8 +343,9 @@ module Squared
|
|
|
334
343
|
'refs' => %i[heads tags remote].freeze,
|
|
335
344
|
'reset' => %i[commit index patch mode undo].freeze,
|
|
336
345
|
'restore' => %i[source staged worktree].freeze,
|
|
337
|
-
'rev' => %i[commit build output].freeze,
|
|
346
|
+
'rev' => %i[commit branch build output].freeze,
|
|
338
347
|
'show' => %i[format oneline textconv].freeze,
|
|
348
|
+
'sparse-checkout' => %i[add reapply list clean disable].freeze,
|
|
339
349
|
'stash' => %i[push pop apply branch drop clear list all staged worktree].freeze,
|
|
340
350
|
'submodule' => %i[status update branch url sync].freeze,
|
|
341
351
|
'switch' => %i[branch create detach].freeze,
|
|
@@ -479,9 +489,8 @@ module Squared
|
|
|
479
489
|
])
|
|
480
490
|
choice_remote
|
|
481
491
|
end
|
|
482
|
-
tag(flag, refs: [name], message: message, commit: commit, remote: remote)
|
|
483
|
-
|
|
484
|
-
end
|
|
492
|
+
ret = tag(flag, refs: [name], message: message, commit: commit, remote: remote)
|
|
493
|
+
success?(ret, !remote)
|
|
485
494
|
end
|
|
486
495
|
end
|
|
487
496
|
when 'stash'
|
|
@@ -505,16 +514,15 @@ module Squared
|
|
|
505
514
|
args.shift
|
|
506
515
|
index = choice_commit(multiple: true)
|
|
507
516
|
else
|
|
508
|
-
index = []
|
|
509
|
-
args.each do |val|
|
|
517
|
+
index = args.each_with_object([]) do |val, out|
|
|
510
518
|
if matchhead(val)
|
|
511
|
-
|
|
519
|
+
out << commithead(val)
|
|
512
520
|
elsif (sha = commithash(val))
|
|
513
|
-
|
|
521
|
+
out << sha
|
|
514
522
|
elsif val.start_with?('^')
|
|
515
|
-
|
|
523
|
+
out << shell_quote(val)
|
|
516
524
|
else
|
|
517
|
-
break
|
|
525
|
+
break out
|
|
518
526
|
end
|
|
519
527
|
end
|
|
520
528
|
args = args.drop(index.size)
|
|
@@ -547,11 +555,10 @@ module Squared
|
|
|
547
555
|
args.shift
|
|
548
556
|
index = choice_commit(multiple: true)
|
|
549
557
|
else
|
|
550
|
-
index = []
|
|
551
|
-
|
|
552
|
-
break unless (sha = commithead(val) || commithash(val))
|
|
558
|
+
index = args.each_with_object([]) do |val, out|
|
|
559
|
+
break out unless (sha = commithead(val) || commithash(val))
|
|
553
560
|
|
|
554
|
-
|
|
561
|
+
out << sha
|
|
555
562
|
end
|
|
556
563
|
args = args.drop(index.size)
|
|
557
564
|
end
|
|
@@ -697,12 +704,12 @@ module Squared
|
|
|
697
704
|
format_desc action, flag, '[^~]name*,:?'
|
|
698
705
|
task flag do |_, args|
|
|
699
706
|
refs = args.to_a
|
|
700
|
-
if refs.empty? || (
|
|
707
|
+
if refs.empty? || (i = refs.last == ':')
|
|
701
708
|
accept = ['Delete?']
|
|
702
|
-
accept << accept_b('Force?') unless
|
|
703
|
-
remote = choice_refs('Choose a branch',
|
|
709
|
+
accept << accept_b('Force?') unless i
|
|
710
|
+
remote = choice_refs('Choose a branch', i ? 'remotes' : 'heads', multiple: true,
|
|
704
711
|
accept: accept)
|
|
705
|
-
if
|
|
712
|
+
if i
|
|
706
713
|
refs.pop
|
|
707
714
|
else
|
|
708
715
|
refs = remote.first
|
|
@@ -882,6 +889,12 @@ module Squared
|
|
|
882
889
|
end
|
|
883
890
|
rev_parse(flag, ref: ref, size: size)
|
|
884
891
|
end
|
|
892
|
+
when :branch
|
|
893
|
+
format_desc action, flag, 'ref?=HEAD|upstream|push'
|
|
894
|
+
task flag, [:ref] do |_, args|
|
|
895
|
+
ret = rev_parse(flag, ref: args.ref || 'upstream')
|
|
896
|
+
puts ret unless ret.empty?
|
|
897
|
+
end
|
|
885
898
|
when :build
|
|
886
899
|
next unless build?
|
|
887
900
|
|
|
@@ -927,20 +940,28 @@ module Squared
|
|
|
927
940
|
task flag do |_, args|
|
|
928
941
|
args = args.to_a
|
|
929
942
|
if args.empty? || args.last == ':'
|
|
930
|
-
files = []
|
|
931
|
-
|
|
943
|
+
files = status_data.each_with_object([]) do |row, out|
|
|
944
|
+
out << row[0] if row[flag == :staged ? 2 : 1].match?(/[AMDRTC]/)
|
|
945
|
+
end
|
|
932
946
|
unless files.empty?
|
|
933
947
|
files = choice_index('Select a file', files, multiple: true, force: false,
|
|
934
948
|
accept: 'Restore?')
|
|
935
949
|
end
|
|
936
950
|
args.pop
|
|
937
|
-
args, glob = args.partition { |val| val.match?(/^(
|
|
951
|
+
args, glob = args.partition { |val| val.match?(/^([a-z-]+=|[^*]+$)/) }
|
|
938
952
|
files.concat(glob)
|
|
939
953
|
next if args.empty? && files.empty?
|
|
940
954
|
end
|
|
941
955
|
restore(flag, args, files: files)
|
|
942
956
|
end
|
|
943
957
|
end
|
|
958
|
+
when 'sparse-checkout'
|
|
959
|
+
break unless matchfile(gitpath('config.worktree'), /\bsparseCheckout\s+=\s+true/)
|
|
960
|
+
|
|
961
|
+
format_desc(action, flag, 'opts*', after: ('dir+' if flag == :add))
|
|
962
|
+
task flag do |_, args|
|
|
963
|
+
sparse_checkout flag, args.to_a
|
|
964
|
+
end
|
|
944
965
|
when 'git'
|
|
945
966
|
before = case flag
|
|
946
967
|
when :blame
|
|
@@ -955,6 +976,8 @@ module Squared
|
|
|
955
976
|
'pathspec*,pattern*'
|
|
956
977
|
when :grep
|
|
957
978
|
'tree*,pathspec*'
|
|
979
|
+
when :'sparse-checkout'
|
|
980
|
+
'dir+'
|
|
958
981
|
when :clean, :rm, :status
|
|
959
982
|
'pathspec*'
|
|
960
983
|
end
|
|
@@ -1019,12 +1042,11 @@ module Squared
|
|
|
1019
1042
|
heads = []
|
|
1020
1043
|
cur = nil
|
|
1021
1044
|
foreachref('heads', format: '%(if)%(HEAD)%(then)* %(end)%(refname:short)').each do |line|
|
|
1022
|
-
line.chomp!
|
|
1023
1045
|
cur ||= line.delete_prefix!('* ')
|
|
1024
|
-
heads << line if matchany?(
|
|
1046
|
+
heads << line if matchany?(reg, line)
|
|
1025
1047
|
end
|
|
1026
1048
|
raise_error 'head not found', hint: 'for-each-ref' unless cur
|
|
1027
|
-
opts << 'ff-only' if opts.empty? &&
|
|
1049
|
+
opts << 'ff-only' if opts.empty? && option('ff-only', notequals: '0')
|
|
1028
1050
|
(heads.dup << cur).each_with_index do |branch, i|
|
|
1029
1051
|
next unless (i < heads.size && cur != branch) || i == heads.size
|
|
1030
1052
|
|
|
@@ -1038,12 +1060,16 @@ module Squared
|
|
|
1038
1060
|
end
|
|
1039
1061
|
append_pull(opts, OPT_GIT[:pull] + OPT_GIT[:fetch][:pull],
|
|
1040
1062
|
flag: flag, from: :pull, remote: remote, no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull])
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1063
|
+
if sync
|
|
1064
|
+
source(hint: hint)
|
|
1065
|
+
else
|
|
1066
|
+
source(sync: false, sub: if stdout?
|
|
1067
|
+
[
|
|
1068
|
+
opt_style(color(:red), /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, 4),
|
|
1069
|
+
opt_style(color(:green), /^(.+)(\|\s+\d+\s+)(\++)(.*)$/, 3)
|
|
1070
|
+
]
|
|
1071
|
+
end, hint: hint, **threadargs)
|
|
1072
|
+
end
|
|
1047
1073
|
end
|
|
1048
1074
|
|
|
1049
1075
|
def rebase(flag = nil, opts = [], sync: invoked_sync?('rebase', flag), commit: nil, upstream: nil, branch: nil,
|
|
@@ -1075,7 +1101,7 @@ module Squared
|
|
|
1075
1101
|
|
|
1076
1102
|
cmd << "--#{command}"
|
|
1077
1103
|
end
|
|
1078
|
-
source
|
|
1104
|
+
source(sync: sync)
|
|
1079
1105
|
end
|
|
1080
1106
|
|
|
1081
1107
|
def autostash(*, sync: invoked_sync?('autostash'), **)
|
|
@@ -1087,7 +1113,11 @@ module Squared
|
|
|
1087
1113
|
opts << 'all' if flag == :all || option('all')
|
|
1088
1114
|
append_pull(opts, collect_hash(OPT_GIT[:fetch]), flag: flag, from: :fetch, remote: remote,
|
|
1089
1115
|
no: collect_hash(OPT_GIT[:no][:fetch]))
|
|
1090
|
-
|
|
1116
|
+
if sync
|
|
1117
|
+
source
|
|
1118
|
+
else
|
|
1119
|
+
source(sync: false, **threadargs)
|
|
1120
|
+
end
|
|
1091
1121
|
end
|
|
1092
1122
|
|
|
1093
1123
|
def clone(*, sync: invoked_sync?('clone'), **)
|
|
@@ -1128,7 +1158,7 @@ module Squared
|
|
|
1128
1158
|
append_hash opts
|
|
1129
1159
|
cmd << '--quiet' if option('quiet') || !verbose
|
|
1130
1160
|
append_value(data[0], path, delim: true)
|
|
1131
|
-
source(banner: sync && !quiet?, multiple: !sync || quiet?)
|
|
1161
|
+
source(sync: sync, banner: sync && !quiet?, multiple: !sync || quiet?)
|
|
1132
1162
|
end
|
|
1133
1163
|
|
|
1134
1164
|
def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
|
|
@@ -1195,10 +1225,14 @@ module Squared
|
|
|
1195
1225
|
end
|
|
1196
1226
|
else
|
|
1197
1227
|
git_session('stash', 'push', opts: opts)
|
|
1198
|
-
append_option(OptionPartition.select(OPT_GIT[:stash][:push], no: false), no: true, ignore: false)
|
|
1228
|
+
append_option(*OptionPartition.select(OPT_GIT[:stash][:push], no: false), no: true, ignore: false)
|
|
1199
1229
|
append_message
|
|
1200
1230
|
end
|
|
1201
|
-
|
|
1231
|
+
if sync
|
|
1232
|
+
source(banner: !quiet?)
|
|
1233
|
+
else
|
|
1234
|
+
source(sync: false, banner: !quiet?, **threadargs)
|
|
1235
|
+
end
|
|
1202
1236
|
end
|
|
1203
1237
|
|
|
1204
1238
|
def status(flag = nil, opts = [])
|
|
@@ -1211,12 +1245,10 @@ module Squared
|
|
|
1211
1245
|
cmd << '--branch' if option('branch')
|
|
1212
1246
|
option('ignore-submodules', ignore: false) do |val|
|
|
1213
1247
|
cmd << basic_option('ignore-submodules', case val
|
|
1214
|
-
when '0', '
|
|
1248
|
+
when 'none', '0', 'false'
|
|
1215
1249
|
'none'
|
|
1216
|
-
when '
|
|
1217
|
-
|
|
1218
|
-
when '2', 'dirty'
|
|
1219
|
-
'dirty'
|
|
1250
|
+
when 'untracked', 'dirty'
|
|
1251
|
+
val
|
|
1220
1252
|
else
|
|
1221
1253
|
'all'
|
|
1222
1254
|
end)
|
|
@@ -1242,7 +1274,7 @@ module Squared
|
|
|
1242
1274
|
list_result(ret, 'files', action: 'modified', from: from)
|
|
1243
1275
|
end
|
|
1244
1276
|
|
|
1245
|
-
def revbuild(flag = nil, opts = [],
|
|
1277
|
+
def revbuild(flag = nil, opts = [], **kwargs)
|
|
1246
1278
|
kw = lambda do
|
|
1247
1279
|
{
|
|
1248
1280
|
include: relativepath(*Array(kwargs[:include]), all: true),
|
|
@@ -1260,7 +1292,7 @@ module Squared
|
|
|
1260
1292
|
sha = git_spawn('rev-parse --verify HEAD').chomp
|
|
1261
1293
|
return if sha.empty?
|
|
1262
1294
|
|
|
1263
|
-
sync = invoked_sync?('revbuild', flag)
|
|
1295
|
+
sync = kwargs.fetch(:sync) { invoked_sync?('revbuild', flag) }
|
|
1264
1296
|
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? kw.call : @revbuild || {}
|
|
1265
1297
|
case flag
|
|
1266
1298
|
when :build
|
|
@@ -1283,11 +1315,11 @@ module Squared
|
|
|
1283
1315
|
end
|
|
1284
1316
|
end
|
|
1285
1317
|
start = time_epoch
|
|
1286
|
-
build(*@output, sync: sync, from:
|
|
1287
|
-
rescue
|
|
1318
|
+
build(*@output, sync: sync, from: symjoin('git', 'revbuild'))
|
|
1319
|
+
rescue => e
|
|
1288
1320
|
print_error(e, pass: true)
|
|
1289
1321
|
else
|
|
1290
|
-
print_status('revbuild', subject: name, start: start
|
|
1322
|
+
print_status('revbuild', subject: name, start: start)
|
|
1291
1323
|
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
|
|
1292
1324
|
sync: sync, utc: 'build')
|
|
1293
1325
|
end
|
|
@@ -1341,9 +1373,9 @@ module Squared
|
|
|
1341
1373
|
cmd << '-m' if merge
|
|
1342
1374
|
cmd << '--detach' << commit
|
|
1343
1375
|
else
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1376
|
+
op = OptionPartition.new(opts, OPT_GIT[:checkout] + OPT_GIT[:log][:diff_context], cmd,
|
|
1377
|
+
project: self, no: OPT_GIT[:no][:checkout],
|
|
1378
|
+
first: (matchpathspec if flag == :path))
|
|
1347
1379
|
if flag == :path
|
|
1348
1380
|
append_head
|
|
1349
1381
|
append_pathspec(op.extras, pass: false)
|
|
@@ -1383,8 +1415,10 @@ module Squared
|
|
|
1383
1415
|
list_result(ret, 'tags', grep: op.extras, from: from)
|
|
1384
1416
|
return
|
|
1385
1417
|
end
|
|
1386
|
-
remote ||= option('remote')
|
|
1387
|
-
|
|
1418
|
+
if (ret = source) && (remote ||= option('remote'))
|
|
1419
|
+
git_spawn('push', ('-d' if flag == :delete), remote, *refs.quote!)
|
|
1420
|
+
end
|
|
1421
|
+
ret
|
|
1388
1422
|
end
|
|
1389
1423
|
|
|
1390
1424
|
def log!(flag, opts = [], range: [], index: [], grep: [])
|
|
@@ -1488,7 +1522,7 @@ module Squared
|
|
|
1488
1522
|
format = '%(if)%(HEAD)%(then)%(refname:short)...%(upstream:short)...%(upstream:track)%(end)'
|
|
1489
1523
|
git_spawn 'fetch --no-tags --quiet'
|
|
1490
1524
|
foreachref('heads', format: format).each do |line|
|
|
1491
|
-
next if
|
|
1525
|
+
next if line.empty?
|
|
1492
1526
|
|
|
1493
1527
|
branch, origin, hint = line.split('...')
|
|
1494
1528
|
if hint && !hint.match?(/^\[(\D+0,\D+0)\]$/)
|
|
@@ -1533,7 +1567,7 @@ module Squared
|
|
|
1533
1567
|
cached = git_spawn 'diff --cached --name-only --no-color'
|
|
1534
1568
|
if amend || !cached.empty? || dryrun?
|
|
1535
1569
|
if adding.empty? && !cached.empty? && banner?
|
|
1536
|
-
puts(cached.lines(chomp: true).map
|
|
1570
|
+
puts(cached.lines(chomp: true).map { |val| "cached #{shell_quote(val)}" })
|
|
1537
1571
|
end
|
|
1538
1572
|
source co
|
|
1539
1573
|
source pu
|
|
@@ -1605,7 +1639,7 @@ module Squared
|
|
|
1605
1639
|
end
|
|
1606
1640
|
when :delete
|
|
1607
1641
|
remote&.each { |val| source git_output('push --delete', *val.split('/', 2).quote!) }
|
|
1608
|
-
force, list = refs.partition { |val| val.start_with?(
|
|
1642
|
+
force, list = refs.partition { |val| val.start_with?('~', '^') }
|
|
1609
1643
|
force.each do |val|
|
|
1610
1644
|
r = '-r' if val.delete!('~')
|
|
1611
1645
|
source git_output('branch', val.delete!('^') ? '-D' : '-d', r, shell_quote(val))
|
|
@@ -1712,7 +1746,7 @@ module Squared
|
|
|
1712
1746
|
op << '--recursive' if option('r', 'recursive')
|
|
1713
1747
|
op.splice(path: true)
|
|
1714
1748
|
end
|
|
1715
|
-
|
|
1749
|
+
success?(source, flag == :branch)
|
|
1716
1750
|
end
|
|
1717
1751
|
|
|
1718
1752
|
def restore(flag, opts = [], commit: nil, files: nil)
|
|
@@ -1732,7 +1766,7 @@ module Squared
|
|
|
1732
1766
|
cmd << '--textconv'
|
|
1733
1767
|
append_value(files.flat_map { |val| Dir[val] }
|
|
1734
1768
|
.select { |val| projectpath?(val) }
|
|
1735
|
-
.map
|
|
1769
|
+
.map { |val| shell_quote("HEAD:#{val}") })
|
|
1736
1770
|
source(banner: false)
|
|
1737
1771
|
return
|
|
1738
1772
|
when :oneline
|
|
@@ -1760,8 +1794,13 @@ module Squared
|
|
|
1760
1794
|
cmd << (size.to_i.zero? ? '--verify' : basic_option('short', [size.to_i, 5].max))
|
|
1761
1795
|
append_commit(ref, head: true)
|
|
1762
1796
|
when :branch
|
|
1763
|
-
cmd << '--abbrev-ref'
|
|
1764
|
-
|
|
1797
|
+
cmd << '--abbrev-ref' << '--symbolic-full-name' << shell_quote(case ref
|
|
1798
|
+
when 'upstream', 'push'
|
|
1799
|
+
"@{#{ref}}"
|
|
1800
|
+
else
|
|
1801
|
+
ref
|
|
1802
|
+
end)
|
|
1803
|
+
return git_spawn(cmd, exception: false).chomp
|
|
1765
1804
|
when :output
|
|
1766
1805
|
if opts.delete('sq-quote')
|
|
1767
1806
|
cmd << '--sq-quote'
|
|
@@ -1773,6 +1812,20 @@ module Squared
|
|
|
1773
1812
|
source(banner: verbose?)
|
|
1774
1813
|
end
|
|
1775
1814
|
|
|
1815
|
+
def sparse_checkout(flag, opts = [])
|
|
1816
|
+
cmd, opts = git_session('sparse-checkout', flag, opts: opts)
|
|
1817
|
+
op = OptionPartition.new(opts, OPT_GIT[:sparse_checkout].fetch(flag, []), cmd,
|
|
1818
|
+
project: self, no: OPT_GIT[:no][:sparse_checkout][flag])
|
|
1819
|
+
case flag
|
|
1820
|
+
when :add
|
|
1821
|
+
append_pathspec(op.detach, expect: true, resolve: false, pass: false)
|
|
1822
|
+
when :clean
|
|
1823
|
+
op << '--dry-run' unless op.arg?('n', 'f', 'force')
|
|
1824
|
+
end
|
|
1825
|
+
op.clear
|
|
1826
|
+
success?(source, flag != :list)
|
|
1827
|
+
end
|
|
1828
|
+
|
|
1776
1829
|
def ls_remote(flag, opts = [], remote: nil)
|
|
1777
1830
|
cmd, opts = git_session('ls-remote --refs', opts: opts)
|
|
1778
1831
|
cmd << "--#{flag}" unless flag == :remote
|
|
@@ -1802,10 +1855,12 @@ module Squared
|
|
|
1802
1855
|
list.concat(OPT_GIT[:log][:diff_context])
|
|
1803
1856
|
when :revert
|
|
1804
1857
|
list.concat(VAL_GIT[:rebase][:send])
|
|
1858
|
+
when :'sparse-checkout'
|
|
1859
|
+
cmd << 'set'
|
|
1805
1860
|
end
|
|
1806
1861
|
op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GIT[:no][flag], single: /\A\d+\z/,
|
|
1807
1862
|
first: case flag
|
|
1808
|
-
when :blame, :revert then nil
|
|
1863
|
+
when :blame, :revert, :'sparse-checkout' then nil
|
|
1809
1864
|
else matchpathspec
|
|
1810
1865
|
end)
|
|
1811
1866
|
case flag
|
|
@@ -1826,12 +1881,12 @@ module Squared
|
|
|
1826
1881
|
grep, pathspec = op.partition { |val| OptionPartition.pattern?(val) }
|
|
1827
1882
|
unless grep.empty? && !pathspec.empty?
|
|
1828
1883
|
grep.map! { |val| Regexp.new(val[1..-2]) }
|
|
1829
|
-
files =
|
|
1830
|
-
status_data.each do |a, b|
|
|
1884
|
+
files = status_data.map do |a, b|
|
|
1831
1885
|
next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
|
|
1832
1886
|
|
|
1833
|
-
|
|
1887
|
+
"#{sub_style(b, color(:red))} #{a}"
|
|
1834
1888
|
end
|
|
1889
|
+
.compact
|
|
1835
1890
|
unless files.empty?
|
|
1836
1891
|
files = choice_index('Select files', files, multiple: true, trim: /^\S+\s/,
|
|
1837
1892
|
accept: [accept_y('Add?')])
|
|
@@ -1840,13 +1895,12 @@ module Squared
|
|
|
1840
1895
|
end
|
|
1841
1896
|
end
|
|
1842
1897
|
return source(git_session('status -s'), banner: false) unless append_pathspec(op.extras)
|
|
1843
|
-
return success?(source) if flag == :add && !op.arg?('verbose')
|
|
1844
1898
|
when :mv
|
|
1845
1899
|
refs = projectmap op.extras
|
|
1846
1900
|
raise_error 'no source/destination' unless refs.size > 1
|
|
1847
1901
|
op.merge(refs)
|
|
1848
|
-
when :rm, :clean
|
|
1849
|
-
append_pathspec(op.extras, expect: flag
|
|
1902
|
+
when :rm, :clean, :'sparse-checkout'
|
|
1903
|
+
append_pathspec(op.extras, expect: flag != :clean, resolve: flag != :'sparse-checkout')
|
|
1850
1904
|
when :grep
|
|
1851
1905
|
op.each do |val|
|
|
1852
1906
|
if op.include?('--')
|
|
@@ -1863,7 +1917,7 @@ module Squared
|
|
|
1863
1917
|
when :revert, :mv, :rm
|
|
1864
1918
|
source(sync: false, stderr: true)
|
|
1865
1919
|
else
|
|
1866
|
-
source
|
|
1920
|
+
success?(source, flag == :'sparse-checkout' || (flag == :add && !op.arg?('verbose')))
|
|
1867
1921
|
end
|
|
1868
1922
|
end
|
|
1869
1923
|
|
|
@@ -1882,7 +1936,7 @@ module Squared
|
|
|
1882
1936
|
private
|
|
1883
1937
|
|
|
1884
1938
|
def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
|
|
1885
|
-
multiple: false, hint: nil, from: nil, send: :system, **kwargs)
|
|
1939
|
+
multiple: false, hint: nil, from: nil, timeout: nil, send: :system, **kwargs)
|
|
1886
1940
|
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
|
1887
1941
|
if io && banner == false
|
|
1888
1942
|
from = nil
|
|
@@ -1892,16 +1946,20 @@ module Squared
|
|
|
1892
1946
|
banner = nil unless banner? && !multiple
|
|
1893
1947
|
args = true
|
|
1894
1948
|
end
|
|
1895
|
-
if from
|
|
1896
|
-
from = :"git:#{from}"
|
|
1897
|
-
elsif from == false
|
|
1949
|
+
if from == false
|
|
1898
1950
|
from = nil
|
|
1951
|
+
elsif !from && cmd.respond_to?(:drop)
|
|
1952
|
+
from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z-]*\z/) }
|
|
1953
|
+
from &&= symjoin 'git', from
|
|
1899
1954
|
end
|
|
1900
|
-
banner &&= cmd.temp { |val| val.start_with?(/--(
|
|
1955
|
+
banner &&= cmd.temp { |val| val.start_with?(/--(work-tree|git-dir)/) } if cmd.respond_to?(:temp)
|
|
1901
1956
|
end
|
|
1957
|
+
timeout = session_timeout cmd if timeout.nil?
|
|
1902
1958
|
cmd = session_done cmd
|
|
1903
1959
|
log&.info cmd
|
|
1904
|
-
banner =
|
|
1960
|
+
banner = if banner
|
|
1961
|
+
format_banner(banner.is_a?(String) ? banner : cmd, hint: hint, strip: true)
|
|
1962
|
+
end
|
|
1905
1963
|
on :first, from
|
|
1906
1964
|
begin
|
|
1907
1965
|
if io
|
|
@@ -1910,35 +1968,31 @@ module Squared
|
|
|
1910
1968
|
return args ? [IO.popen(cmd), banner || '', from] : IO.popen(cmd)
|
|
1911
1969
|
elsif stdin? ? sync : stdout
|
|
1912
1970
|
print_item banner unless multiple
|
|
1913
|
-
ret =
|
|
1971
|
+
ret = if stdin? && timeout.to_f > 0
|
|
1972
|
+
Timeout.timeout(timeout) { `#{cmd}` }
|
|
1973
|
+
else
|
|
1974
|
+
`#{cmd}`
|
|
1975
|
+
end.chomp
|
|
1914
1976
|
raise(ret.empty? ? $?.to_s : ret) unless $?.success?
|
|
1915
1977
|
|
|
1916
1978
|
if ret.empty?
|
|
1917
|
-
success?(
|
|
1979
|
+
success?(true, !banner.nil?)
|
|
1918
1980
|
else
|
|
1919
1981
|
puts ret
|
|
1920
1982
|
end
|
|
1921
1983
|
elsif !kwargs[:sub] && (sync || (!exception && !stderr))
|
|
1922
1984
|
print_item banner unless multiple
|
|
1923
|
-
ret =
|
|
1985
|
+
ret = shell_t(cmd, name: send, exception: exception, timeout: timeout)
|
|
1986
|
+
elsif timeout.to_f > 0
|
|
1987
|
+
Timeout.timeout(timeout) { run_e(cmd, stderr: stderr, banner: banner, **kwargs) }
|
|
1924
1988
|
else
|
|
1925
|
-
|
|
1926
|
-
if stderr
|
|
1927
|
-
Open3.popen3(cmd) do |_, out, err|
|
|
1928
|
-
n = write_lines(out, banner: banner, pass: true, **kwargs)
|
|
1929
|
-
if n == 0
|
|
1930
|
-
n = write_lines(err, banner: banner)
|
|
1931
|
-
success?(nil, n == 0 && !banner.nil?)
|
|
1932
|
-
else
|
|
1933
|
-
write_lines(err, loglevel: Logger::DEBUG)
|
|
1934
|
-
end
|
|
1935
|
-
end
|
|
1936
|
-
else
|
|
1937
|
-
Open3.popen2e(cmd) { |_, out| write_lines(out, banner: banner, **kwargs) }
|
|
1938
|
-
end
|
|
1989
|
+
run_e(cmd, stderr: stderr, banner: banner, **kwargs)
|
|
1939
1990
|
end
|
|
1940
|
-
rescue
|
|
1941
|
-
|
|
1991
|
+
rescue Timeout::Error => e
|
|
1992
|
+
print_error(Logger::ERROR, cmd, subject: name, hint: e)
|
|
1993
|
+
exit 1 unless exception?(Logger::DEBUG, Logger::INFO)
|
|
1994
|
+
rescue => e
|
|
1995
|
+
on_error(e, pass: true)
|
|
1942
1996
|
nil
|
|
1943
1997
|
else
|
|
1944
1998
|
on :last, from
|
|
@@ -1946,32 +2000,6 @@ module Squared
|
|
|
1946
2000
|
end
|
|
1947
2001
|
end
|
|
1948
2002
|
|
|
1949
|
-
def write_lines(data, grep: [], prefix: nil, sub: nil, banner: nil, loglevel: nil, pass: false, first: false)
|
|
1950
|
-
grep = (matchmap(grep, prefix) unless grep.empty?)
|
|
1951
|
-
sub = (as_a sub unless stdin?)
|
|
1952
|
-
ret = 0
|
|
1953
|
-
out = []
|
|
1954
|
-
data.each do |line|
|
|
1955
|
-
next if grep&.none? { |pat| pat.match?(line) }
|
|
1956
|
-
next if block_given? && !(line = yield(line, ret))
|
|
1957
|
-
|
|
1958
|
-
if loglevel
|
|
1959
|
-
log&.add loglevel, line
|
|
1960
|
-
else
|
|
1961
|
-
sub&.each { |h| sub_style!(line, **h) }
|
|
1962
|
-
if banner
|
|
1963
|
-
out << line
|
|
1964
|
-
else
|
|
1965
|
-
puts line
|
|
1966
|
-
end
|
|
1967
|
-
end
|
|
1968
|
-
ret += 1
|
|
1969
|
-
break if first
|
|
1970
|
-
end
|
|
1971
|
-
print_item banner, out if banner && (ret > 0 || (!pass && !first))
|
|
1972
|
-
ret
|
|
1973
|
-
end
|
|
1974
|
-
|
|
1975
2003
|
def list_result(size, type, action: 'found', grep: [], from: nil)
|
|
1976
2004
|
if size == 0
|
|
1977
2005
|
puts empty_status("No #{type} were #{action}", 'grep', grep.join(', '))
|
|
@@ -2007,7 +2035,7 @@ module Squared
|
|
|
2007
2035
|
ret = choice_index('Choose a commit', git_spawn(cmd, stdout: false), column: /^(\S+)/, force: force, **kwargs)
|
|
2008
2036
|
case ret
|
|
2009
2037
|
when Array
|
|
2010
|
-
ret.map
|
|
2038
|
+
ret.map(&:stripstyle)
|
|
2011
2039
|
when String
|
|
2012
2040
|
ret.stripstyle
|
|
2013
2041
|
else
|
|
@@ -2025,24 +2053,18 @@ module Squared
|
|
|
2025
2053
|
algorithm ||= Digest::SHA256
|
|
2026
2054
|
glob = kwargs.fetch(:include, [])
|
|
2027
2055
|
pass = kwargs.fetch(:exclude, [])
|
|
2028
|
-
|
|
2029
|
-
status_data(*args).each do |file,|
|
|
2056
|
+
status_data(*args).map(&:first).each_with_object({}) do |file, out|
|
|
2030
2057
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
|
2031
2058
|
next if pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
|
2032
2059
|
|
|
2033
|
-
|
|
2060
|
+
out[file] = algorithm.hexdigest(File.read(basepath(file)))
|
|
2034
2061
|
end
|
|
2035
|
-
ret
|
|
2036
2062
|
end
|
|
2037
2063
|
|
|
2038
2064
|
def status_data(*args)
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
next unless line =~ /^(.)(.) (.+)$/
|
|
2042
|
-
|
|
2043
|
-
ret << [$3, $2, $1]
|
|
2065
|
+
git_spawn('status -z -uall', *args).split("\x0").each_with_object([]) do |line, out|
|
|
2066
|
+
out << [$3, $2, $1] if line =~ /^(.)(.) (.+)$/
|
|
2044
2067
|
end
|
|
2045
|
-
ret
|
|
2046
2068
|
end
|
|
2047
2069
|
|
|
2048
2070
|
def append_pull(opts, list, flag:, from:, target: @session, no: nil, remote: nil)
|
|
@@ -2050,9 +2072,8 @@ module Squared
|
|
|
2050
2072
|
append_submodules(target: target, from: from)
|
|
2051
2073
|
return if !remote && opts.empty?
|
|
2052
2074
|
|
|
2053
|
-
refspec = []
|
|
2054
2075
|
op = OptionPartition.new(opts, remote ? list + ['refspec=v'] : list, target, project: self, no: no)
|
|
2055
|
-
op.
|
|
2076
|
+
refspec = op.each_with_object([]) do |opt, out|
|
|
2056
2077
|
if opt =~ op.values
|
|
2057
2078
|
case $1
|
|
2058
2079
|
when 'rebase'
|
|
@@ -2063,7 +2084,7 @@ module Squared
|
|
|
2063
2084
|
when 'recurse-submodules'
|
|
2064
2085
|
op.append?($1, $2, type: :basic)
|
|
2065
2086
|
when 'refspec'
|
|
2066
|
-
|
|
2087
|
+
out << shell_quote($2)
|
|
2067
2088
|
end
|
|
2068
2089
|
elsif op.arg?('multiple')
|
|
2069
2090
|
op.found << opt
|
|
@@ -2075,7 +2096,7 @@ module Squared
|
|
|
2075
2096
|
if remote
|
|
2076
2097
|
op.append(remote, delim: true)
|
|
2077
2098
|
if (val = option('refspec', target: target, strict: true))
|
|
2078
|
-
op.append(
|
|
2099
|
+
op.append(split_escape(val))
|
|
2079
2100
|
else
|
|
2080
2101
|
op.merge(refspec)
|
|
2081
2102
|
end
|
|
@@ -2089,27 +2110,31 @@ module Squared
|
|
|
2089
2110
|
op.clear(errors: true, subject: flag) if flag
|
|
2090
2111
|
end
|
|
2091
2112
|
|
|
2092
|
-
def append_commit(*
|
|
2093
|
-
|
|
2094
|
-
if !
|
|
2095
|
-
|
|
2113
|
+
def append_commit(*refs, target: @session, head: false)
|
|
2114
|
+
refs.compact!
|
|
2115
|
+
if !refs.empty?
|
|
2116
|
+
target.merge(refs.map { |val| commithash(val) || shell_quote(val) })
|
|
2096
2117
|
elsif head
|
|
2097
2118
|
target << (append_head(target: target) || 'HEAD')
|
|
2098
2119
|
end
|
|
2099
2120
|
end
|
|
2100
2121
|
|
|
2101
|
-
def append_pathspec(files = [], target: @session, expect: false,
|
|
2122
|
+
def append_pathspec(files = [], target: @session, expect: false, **kwargs)
|
|
2102
2123
|
if session_arg?('pathspec-from-file', target: target)
|
|
2103
|
-
|
|
2124
|
+
OptionPartition.clear(target, files, styles: theme[:inline])
|
|
2104
2125
|
true
|
|
2105
2126
|
else
|
|
2106
2127
|
option('pathspec', target: target) { |val| files = split_escape(val) } if files.empty?
|
|
2107
|
-
files = projectmap(files,
|
|
2128
|
+
files = projectmap(files, **kwargs)
|
|
2108
2129
|
if !files.empty?
|
|
2109
2130
|
target << '--' << files.join(' ')
|
|
2110
2131
|
true
|
|
2111
2132
|
elsif expect
|
|
2112
|
-
raise_error(
|
|
2133
|
+
raise_error(if expect.is_a?(String)
|
|
2134
|
+
expect
|
|
2135
|
+
else
|
|
2136
|
+
kwargs[:parent] ? 'pathspec not present' : 'pathspec not within worktree'
|
|
2137
|
+
end)
|
|
2113
2138
|
else
|
|
2114
2139
|
false
|
|
2115
2140
|
end
|
|
@@ -2153,11 +2178,15 @@ module Squared
|
|
|
2153
2178
|
end
|
|
2154
2179
|
end
|
|
2155
2180
|
|
|
2156
|
-
def foreachref(path, *args, format: nil)
|
|
2157
|
-
path = Array(path).map
|
|
2181
|
+
def foreachref(path, *args, format: nil, chomp: true)
|
|
2182
|
+
path = Array(path).map { |val| "refs/#{val}" }
|
|
2158
2183
|
format &&= quote_option('format', format)
|
|
2159
2184
|
ret = git_spawn('for-each-ref', format, *args, *path, stdout: workspace.windows?)
|
|
2160
|
-
ret.is_a?(String)
|
|
2185
|
+
if ret.is_a?(String)
|
|
2186
|
+
ret.lines(chomp: chomp)
|
|
2187
|
+
else
|
|
2188
|
+
chomp ? ret.readlines(chomp: chomp) : ret
|
|
2189
|
+
end
|
|
2161
2190
|
end
|
|
2162
2191
|
|
|
2163
2192
|
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
|
@@ -2204,7 +2233,9 @@ module Squared
|
|
|
2204
2233
|
raise_error(ArgumentError, "missing #{origin ? 'branch' : 'remote'} name", hint: origin)
|
|
2205
2234
|
end
|
|
2206
2235
|
branch = "#{branch}:#{origin[i.succ..-1]}" unless origin.end_with?("/#{branch}")
|
|
2207
|
-
[origin[0..i.pred], branch]
|
|
2236
|
+
ret = [origin[0..i.pred], branch]
|
|
2237
|
+
ret.quote! if quote
|
|
2238
|
+
ret
|
|
2208
2239
|
end
|
|
2209
2240
|
|
|
2210
2241
|
def commithash(val)
|
|
@@ -2229,16 +2260,22 @@ module Squared
|
|
|
2229
2260
|
[/\A[^a-z\d-]+/i, %r{\A[^=\\/*]*[\\/*]}, /\A--\z/]
|
|
2230
2261
|
end
|
|
2231
2262
|
|
|
2263
|
+
def matchfile(file, pat)
|
|
2264
|
+
file.read[pat, 0] if file.exist?
|
|
2265
|
+
rescue
|
|
2266
|
+
nil
|
|
2267
|
+
end
|
|
2268
|
+
|
|
2232
2269
|
def messageopt
|
|
2233
2270
|
option('message', 'm', prefix: 'git', ignore: false)
|
|
2234
2271
|
end
|
|
2235
2272
|
|
|
2236
2273
|
def threadargs
|
|
2237
|
-
{ stderr: true, exception: exception || !workspace.series.multiple? }
|
|
2274
|
+
{ stderr: true, exception: exception? || !workspace.series.multiple? }
|
|
2238
2275
|
end
|
|
2239
2276
|
end
|
|
2240
2277
|
|
|
2241
|
-
Application.implement Git
|
|
2278
|
+
Application.implement Git, base: 1
|
|
2242
2279
|
end
|
|
2243
2280
|
end
|
|
2244
2281
|
end
|