squared 0.6.9 → 0.7.1
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 +89 -2
- data/README.md +245 -203
- data/lib/squared/common/format.rb +7 -10
- data/lib/squared/common/prompt.rb +23 -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 +290 -175
- data/lib/squared/workspace/project/base.rb +566 -446
- data/lib/squared/workspace/project/docker.rb +151 -131
- data/lib/squared/workspace/project/git.rb +205 -151
- data/lib/squared/workspace/project/node.rb +90 -88
- data/lib/squared/workspace/project/python.rb +236 -139
- data/lib/squared/workspace/project/ruby.rb +395 -281
- data/lib/squared/workspace/project/support/class.rb +12 -6
- data/lib/squared/workspace/project/support/optionpartition.rb +58 -41
- 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 +2 -1
|
@@ -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,
|
|
@@ -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'), **)
|
|
@@ -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,16 +1274,28 @@ 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),
|
|
1249
|
-
exclude: relativepath(*Array(kwargs[:exclude]), all: true)
|
|
1281
|
+
exclude: relativepath(*Array(kwargs[:exclude]), all: true),
|
|
1282
|
+
before: kwargs[:before],
|
|
1283
|
+
after: kwargs[:after],
|
|
1284
|
+
pass: kwargs.fetch(:pass, true)
|
|
1250
1285
|
}
|
|
1251
1286
|
end
|
|
1252
1287
|
unless workspace.closed
|
|
1253
1288
|
if @revbuild
|
|
1254
|
-
kw.call.each
|
|
1289
|
+
kw.call.each do |key, val|
|
|
1290
|
+
case @revbuild[key]
|
|
1291
|
+
when Array
|
|
1292
|
+
@revbuild[key].concat(val)
|
|
1293
|
+
when Hash
|
|
1294
|
+
@revbuild[key].update(val)
|
|
1295
|
+
else
|
|
1296
|
+
@revbuild[key] = val
|
|
1297
|
+
end
|
|
1298
|
+
end
|
|
1255
1299
|
else
|
|
1256
1300
|
@revbuild = kw.call
|
|
1257
1301
|
end
|
|
@@ -1260,8 +1304,8 @@ module Squared
|
|
|
1260
1304
|
sha = git_spawn('rev-parse --verify HEAD').chomp
|
|
1261
1305
|
return if sha.empty?
|
|
1262
1306
|
|
|
1263
|
-
sync = invoked_sync?('revbuild', flag)
|
|
1264
|
-
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? kw.call : @revbuild || {}
|
|
1307
|
+
sync = kwargs.fetch(:sync) { invoked_sync?('revbuild', flag) }
|
|
1308
|
+
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? kw.call : @revbuild || { pass: true }
|
|
1265
1309
|
case flag
|
|
1266
1310
|
when :build
|
|
1267
1311
|
op = OptionPartition.new(opts, VAL_GIT[:revbuild].map { |key| "#{key}=b?" }, project: self)
|
|
@@ -1274,6 +1318,7 @@ module Squared
|
|
|
1274
1318
|
.compact
|
|
1275
1319
|
OptionPartition.uniq!(args)
|
|
1276
1320
|
end
|
|
1321
|
+
run_p(*Array(kwargs[:before]), sync: sync, from: :revbuild) if kwargs[:before]
|
|
1277
1322
|
if (cur = workspace.rev_entry(name)) && cur['revision'] == sha && !env('REVBUILD_FORCE')
|
|
1278
1323
|
files = status_digest(*args, **kwargs)
|
|
1279
1324
|
if cur['files'].size == files.size && cur['files'].find { |key, val| files[key] != val }.nil?
|
|
@@ -1283,13 +1328,19 @@ module Squared
|
|
|
1283
1328
|
end
|
|
1284
1329
|
end
|
|
1285
1330
|
start = time_epoch
|
|
1286
|
-
build(*@output, sync: sync, from:
|
|
1287
|
-
rescue
|
|
1331
|
+
ret = build(*@output, sync: sync, from: symjoin('git', 'revbuild'))
|
|
1332
|
+
rescue => e
|
|
1288
1333
|
print_error(e, pass: true)
|
|
1289
1334
|
else
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1335
|
+
if ret == false && !kwargs[:pass]
|
|
1336
|
+
print_status('revbuild', subject: name, start: start, loglevel: Logger::WARN, from: :failed)
|
|
1337
|
+
workspace.rev_timeutc name, 'build'
|
|
1338
|
+
else
|
|
1339
|
+
run_p(*Array(kwargs[:after]), sync: sync, from: :revbuild) if kwargs[:after] && ret != false
|
|
1340
|
+
print_status('revbuild', subject: name, start: start)
|
|
1341
|
+
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
|
|
1342
|
+
sync: sync, utc: 'build')
|
|
1343
|
+
end
|
|
1293
1344
|
end
|
|
1294
1345
|
|
|
1295
1346
|
def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
|
|
@@ -1341,9 +1392,9 @@ module Squared
|
|
|
1341
1392
|
cmd << '-m' if merge
|
|
1342
1393
|
cmd << '--detach' << commit
|
|
1343
1394
|
else
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1395
|
+
op = OptionPartition.new(opts, OPT_GIT[:checkout] + OPT_GIT[:log][:diff_context], cmd,
|
|
1396
|
+
project: self, no: OPT_GIT[:no][:checkout],
|
|
1397
|
+
first: (matchpathspec if flag == :path))
|
|
1347
1398
|
if flag == :path
|
|
1348
1399
|
append_head
|
|
1349
1400
|
append_pathspec(op.extras, pass: false)
|
|
@@ -1383,8 +1434,10 @@ module Squared
|
|
|
1383
1434
|
list_result(ret, 'tags', grep: op.extras, from: from)
|
|
1384
1435
|
return
|
|
1385
1436
|
end
|
|
1386
|
-
remote ||= option('remote')
|
|
1387
|
-
|
|
1437
|
+
if (ret = source) && (remote ||= option('remote'))
|
|
1438
|
+
git_spawn('push', ('-d' if flag == :delete), remote, *refs.quote!)
|
|
1439
|
+
end
|
|
1440
|
+
ret
|
|
1388
1441
|
end
|
|
1389
1442
|
|
|
1390
1443
|
def log!(flag, opts = [], range: [], index: [], grep: [])
|
|
@@ -1488,7 +1541,7 @@ module Squared
|
|
|
1488
1541
|
format = '%(if)%(HEAD)%(then)%(refname:short)...%(upstream:short)...%(upstream:track)%(end)'
|
|
1489
1542
|
git_spawn 'fetch --no-tags --quiet'
|
|
1490
1543
|
foreachref('heads', format: format).each do |line|
|
|
1491
|
-
next if
|
|
1544
|
+
next if line.empty?
|
|
1492
1545
|
|
|
1493
1546
|
branch, origin, hint = line.split('...')
|
|
1494
1547
|
if hint && !hint.match?(/^\[(\D+0,\D+0)\]$/)
|
|
@@ -1533,7 +1586,7 @@ module Squared
|
|
|
1533
1586
|
cached = git_spawn 'diff --cached --name-only --no-color'
|
|
1534
1587
|
if amend || !cached.empty? || dryrun?
|
|
1535
1588
|
if adding.empty? && !cached.empty? && banner?
|
|
1536
|
-
puts(cached.lines(chomp: true).map
|
|
1589
|
+
puts(cached.lines(chomp: true).map { |val| "cached #{shell_quote(val)}" })
|
|
1537
1590
|
end
|
|
1538
1591
|
source co
|
|
1539
1592
|
source pu
|
|
@@ -1605,7 +1658,7 @@ module Squared
|
|
|
1605
1658
|
end
|
|
1606
1659
|
when :delete
|
|
1607
1660
|
remote&.each { |val| source git_output('push --delete', *val.split('/', 2).quote!) }
|
|
1608
|
-
force, list = refs.partition { |val| val.start_with?(
|
|
1661
|
+
force, list = refs.partition { |val| val.start_with?('~', '^') }
|
|
1609
1662
|
force.each do |val|
|
|
1610
1663
|
r = '-r' if val.delete!('~')
|
|
1611
1664
|
source git_output('branch', val.delete!('^') ? '-D' : '-d', r, shell_quote(val))
|
|
@@ -1712,7 +1765,7 @@ module Squared
|
|
|
1712
1765
|
op << '--recursive' if option('r', 'recursive')
|
|
1713
1766
|
op.splice(path: true)
|
|
1714
1767
|
end
|
|
1715
|
-
|
|
1768
|
+
success?(source, flag == :branch)
|
|
1716
1769
|
end
|
|
1717
1770
|
|
|
1718
1771
|
def restore(flag, opts = [], commit: nil, files: nil)
|
|
@@ -1732,7 +1785,7 @@ module Squared
|
|
|
1732
1785
|
cmd << '--textconv'
|
|
1733
1786
|
append_value(files.flat_map { |val| Dir[val] }
|
|
1734
1787
|
.select { |val| projectpath?(val) }
|
|
1735
|
-
.map
|
|
1788
|
+
.map { |val| shell_quote("HEAD:#{val}") })
|
|
1736
1789
|
source(banner: false)
|
|
1737
1790
|
return
|
|
1738
1791
|
when :oneline
|
|
@@ -1747,8 +1800,9 @@ module Squared
|
|
|
1747
1800
|
opts << format if format
|
|
1748
1801
|
end
|
|
1749
1802
|
list = OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff] + OPT_GIT[:log][:diff_context]
|
|
1750
|
-
op = OptionPartition.new(opts, list, cmd,
|
|
1751
|
-
|
|
1803
|
+
op = OptionPartition.new(opts, list, cmd,
|
|
1804
|
+
project: self,
|
|
1805
|
+
no: OPT_GIT[:no][:show] + collect_hash(OPT_GIT[:no][:log], pass: [:base]))
|
|
1752
1806
|
op.append(delim: true)
|
|
1753
1807
|
source(exception: false, banner: flag != :oneline)
|
|
1754
1808
|
end
|
|
@@ -1760,8 +1814,13 @@ module Squared
|
|
|
1760
1814
|
cmd << (size.to_i.zero? ? '--verify' : basic_option('short', [size.to_i, 5].max))
|
|
1761
1815
|
append_commit(ref, head: true)
|
|
1762
1816
|
when :branch
|
|
1763
|
-
cmd << '--abbrev-ref'
|
|
1764
|
-
|
|
1817
|
+
cmd << '--abbrev-ref' << '--symbolic-full-name' << shell_quote(case ref
|
|
1818
|
+
when 'upstream', 'push'
|
|
1819
|
+
"@{#{ref}}"
|
|
1820
|
+
else
|
|
1821
|
+
ref
|
|
1822
|
+
end)
|
|
1823
|
+
return git_spawn(cmd, exception: false).chomp
|
|
1765
1824
|
when :output
|
|
1766
1825
|
if opts.delete('sq-quote')
|
|
1767
1826
|
cmd << '--sq-quote'
|
|
@@ -1773,6 +1832,20 @@ module Squared
|
|
|
1773
1832
|
source(banner: verbose?)
|
|
1774
1833
|
end
|
|
1775
1834
|
|
|
1835
|
+
def sparse_checkout(flag, opts = [])
|
|
1836
|
+
cmd, opts = git_session('sparse-checkout', flag, opts: opts)
|
|
1837
|
+
op = OptionPartition.new(opts, OPT_GIT[:sparse_checkout].fetch(flag, []), cmd,
|
|
1838
|
+
project: self, no: OPT_GIT[:no][:sparse_checkout][flag])
|
|
1839
|
+
case flag
|
|
1840
|
+
when :add
|
|
1841
|
+
append_pathspec(op.detach, expect: true, resolve: false, pass: false)
|
|
1842
|
+
when :clean
|
|
1843
|
+
op << '--dry-run' unless op.arg?('n', 'f', 'force')
|
|
1844
|
+
end
|
|
1845
|
+
op.clear
|
|
1846
|
+
success?(source, flag != :list)
|
|
1847
|
+
end
|
|
1848
|
+
|
|
1776
1849
|
def ls_remote(flag, opts = [], remote: nil)
|
|
1777
1850
|
cmd, opts = git_session('ls-remote --refs', opts: opts)
|
|
1778
1851
|
cmd << "--#{flag}" unless flag == :remote
|
|
@@ -1802,10 +1875,12 @@ module Squared
|
|
|
1802
1875
|
list.concat(OPT_GIT[:log][:diff_context])
|
|
1803
1876
|
when :revert
|
|
1804
1877
|
list.concat(VAL_GIT[:rebase][:send])
|
|
1878
|
+
when :'sparse-checkout'
|
|
1879
|
+
cmd << 'set'
|
|
1805
1880
|
end
|
|
1806
1881
|
op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GIT[:no][flag], single: /\A\d+\z/,
|
|
1807
1882
|
first: case flag
|
|
1808
|
-
when :blame, :revert then nil
|
|
1883
|
+
when :blame, :revert, :'sparse-checkout' then nil
|
|
1809
1884
|
else matchpathspec
|
|
1810
1885
|
end)
|
|
1811
1886
|
case flag
|
|
@@ -1826,12 +1901,12 @@ module Squared
|
|
|
1826
1901
|
grep, pathspec = op.partition { |val| OptionPartition.pattern?(val) }
|
|
1827
1902
|
unless grep.empty? && !pathspec.empty?
|
|
1828
1903
|
grep.map! { |val| Regexp.new(val[1..-2]) }
|
|
1829
|
-
files =
|
|
1830
|
-
status_data.each do |a, b|
|
|
1904
|
+
files = status_data.map do |a, b|
|
|
1831
1905
|
next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
|
|
1832
1906
|
|
|
1833
|
-
|
|
1907
|
+
"#{sub_style(b, color(:red))} #{a}"
|
|
1834
1908
|
end
|
|
1909
|
+
.compact
|
|
1835
1910
|
unless files.empty?
|
|
1836
1911
|
files = choice_index('Select files', files, multiple: true, trim: /^\S+\s/,
|
|
1837
1912
|
accept: [accept_y('Add?')])
|
|
@@ -1840,13 +1915,12 @@ module Squared
|
|
|
1840
1915
|
end
|
|
1841
1916
|
end
|
|
1842
1917
|
return source(git_session('status -s'), banner: false) unless append_pathspec(op.extras)
|
|
1843
|
-
return success?(source) if flag == :add && !op.arg?('verbose')
|
|
1844
1918
|
when :mv
|
|
1845
1919
|
refs = projectmap op.extras
|
|
1846
1920
|
raise_error 'no source/destination' unless refs.size > 1
|
|
1847
1921
|
op.merge(refs)
|
|
1848
|
-
when :rm, :clean
|
|
1849
|
-
append_pathspec(op.extras, expect: flag
|
|
1922
|
+
when :rm, :clean, :'sparse-checkout'
|
|
1923
|
+
append_pathspec(op.extras, expect: flag != :clean, resolve: flag != :'sparse-checkout')
|
|
1850
1924
|
when :grep
|
|
1851
1925
|
op.each do |val|
|
|
1852
1926
|
if op.include?('--')
|
|
@@ -1863,7 +1937,7 @@ module Squared
|
|
|
1863
1937
|
when :revert, :mv, :rm
|
|
1864
1938
|
source(sync: false, stderr: true)
|
|
1865
1939
|
else
|
|
1866
|
-
source
|
|
1940
|
+
success?(source, flag == :'sparse-checkout' || (flag == :add && !op.arg?('verbose')))
|
|
1867
1941
|
end
|
|
1868
1942
|
end
|
|
1869
1943
|
|
|
@@ -1882,7 +1956,7 @@ module Squared
|
|
|
1882
1956
|
private
|
|
1883
1957
|
|
|
1884
1958
|
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)
|
|
1959
|
+
multiple: false, hint: nil, from: nil, timeout: nil, send: :system, **kwargs)
|
|
1886
1960
|
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
|
1887
1961
|
if io && banner == false
|
|
1888
1962
|
from = nil
|
|
@@ -1896,10 +1970,11 @@ module Squared
|
|
|
1896
1970
|
from = nil
|
|
1897
1971
|
elsif !from && cmd.respond_to?(:drop)
|
|
1898
1972
|
from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z-]*\z/) }
|
|
1899
|
-
from &&=
|
|
1973
|
+
from &&= symjoin 'git', from
|
|
1900
1974
|
end
|
|
1901
|
-
banner &&= cmd.temp { |val| val.start_with?(/--(
|
|
1975
|
+
banner &&= cmd.temp { |val| val.start_with?(/--(work-tree|git-dir)/) } if cmd.respond_to?(:temp)
|
|
1902
1976
|
end
|
|
1977
|
+
timeout = session_timeout cmd if timeout.nil?
|
|
1903
1978
|
cmd = session_done cmd
|
|
1904
1979
|
log&.info cmd
|
|
1905
1980
|
banner = if banner
|
|
@@ -1913,7 +1988,11 @@ module Squared
|
|
|
1913
1988
|
return args ? [IO.popen(cmd), banner || '', from] : IO.popen(cmd)
|
|
1914
1989
|
elsif stdin? ? sync : stdout
|
|
1915
1990
|
print_item banner unless multiple
|
|
1916
|
-
ret =
|
|
1991
|
+
ret = if stdin? && timeout.to_f > 0
|
|
1992
|
+
Timeout.timeout(timeout) { `#{cmd}` }
|
|
1993
|
+
else
|
|
1994
|
+
`#{cmd}`
|
|
1995
|
+
end.chomp
|
|
1917
1996
|
raise(ret.empty? ? $?.to_s : ret) unless $?.success?
|
|
1918
1997
|
|
|
1919
1998
|
if ret.empty?
|
|
@@ -1923,25 +2002,17 @@ module Squared
|
|
|
1923
2002
|
end
|
|
1924
2003
|
elsif !kwargs[:sub] && (sync || (!exception && !stderr))
|
|
1925
2004
|
print_item banner unless multiple
|
|
1926
|
-
ret =
|
|
2005
|
+
ret = shell_t(cmd, name: send, exception: exception, timeout: timeout)
|
|
2006
|
+
elsif timeout.to_f > 0
|
|
2007
|
+
Timeout.timeout(timeout) { run_e(cmd, stderr: stderr, banner: banner, **kwargs) }
|
|
1927
2008
|
else
|
|
1928
|
-
|
|
1929
|
-
if stderr
|
|
1930
|
-
Open3.popen3(cmd) do |_, out, err|
|
|
1931
|
-
n = write_lines(out, banner: banner, pass: true, **kwargs)
|
|
1932
|
-
if n == 0
|
|
1933
|
-
n = write_lines(err, banner: banner)
|
|
1934
|
-
success?(n == 0, n == 0 && !banner.nil?)
|
|
1935
|
-
else
|
|
1936
|
-
write_lines(err, loglevel: Logger::DEBUG)
|
|
1937
|
-
end
|
|
1938
|
-
end
|
|
1939
|
-
else
|
|
1940
|
-
Open3.popen2e(cmd) { |_, out| write_lines(out, banner: banner, **kwargs) }
|
|
1941
|
-
end
|
|
2009
|
+
run_e(cmd, stderr: stderr, banner: banner, **kwargs)
|
|
1942
2010
|
end
|
|
1943
|
-
rescue
|
|
1944
|
-
|
|
2011
|
+
rescue Timeout::Error => e
|
|
2012
|
+
print_error(Logger::ERROR, cmd, subject: name, hint: e)
|
|
2013
|
+
exit 1 unless exception?(Logger::DEBUG, Logger::INFO)
|
|
2014
|
+
rescue => e
|
|
2015
|
+
on_error(e, pass: true)
|
|
1945
2016
|
nil
|
|
1946
2017
|
else
|
|
1947
2018
|
on :last, from
|
|
@@ -1949,32 +2020,6 @@ module Squared
|
|
|
1949
2020
|
end
|
|
1950
2021
|
end
|
|
1951
2022
|
|
|
1952
|
-
def write_lines(data, grep: [], prefix: nil, sub: nil, banner: nil, loglevel: nil, pass: false, first: false)
|
|
1953
|
-
grep = (matchmap(grep, prefix) unless grep.empty?)
|
|
1954
|
-
sub = (as_a sub unless stdin?)
|
|
1955
|
-
ret = 0
|
|
1956
|
-
out = []
|
|
1957
|
-
data.each do |line|
|
|
1958
|
-
next if grep&.none? { |pat| pat.match?(line) }
|
|
1959
|
-
next if block_given? && !(line = yield(line, ret))
|
|
1960
|
-
|
|
1961
|
-
if loglevel
|
|
1962
|
-
log&.add loglevel, line
|
|
1963
|
-
else
|
|
1964
|
-
sub&.each { |h| sub_style!(line, **h) }
|
|
1965
|
-
if banner
|
|
1966
|
-
out << line
|
|
1967
|
-
else
|
|
1968
|
-
puts line
|
|
1969
|
-
end
|
|
1970
|
-
end
|
|
1971
|
-
ret += 1
|
|
1972
|
-
break if first
|
|
1973
|
-
end
|
|
1974
|
-
print_item banner, out if banner && (ret > 0 || (!pass && !first))
|
|
1975
|
-
ret
|
|
1976
|
-
end
|
|
1977
|
-
|
|
1978
2023
|
def list_result(size, type, action: 'found', grep: [], from: nil)
|
|
1979
2024
|
if size == 0
|
|
1980
2025
|
puts empty_status("No #{type} were #{action}", 'grep', grep.join(', '))
|
|
@@ -2010,7 +2055,7 @@ module Squared
|
|
|
2010
2055
|
ret = choice_index('Choose a commit', git_spawn(cmd, stdout: false), column: /^(\S+)/, force: force, **kwargs)
|
|
2011
2056
|
case ret
|
|
2012
2057
|
when Array
|
|
2013
|
-
ret.map
|
|
2058
|
+
ret.map(&:stripstyle)
|
|
2014
2059
|
when String
|
|
2015
2060
|
ret.stripstyle
|
|
2016
2061
|
else
|
|
@@ -2028,24 +2073,18 @@ module Squared
|
|
|
2028
2073
|
algorithm ||= Digest::SHA256
|
|
2029
2074
|
glob = kwargs.fetch(:include, [])
|
|
2030
2075
|
pass = kwargs.fetch(:exclude, [])
|
|
2031
|
-
|
|
2032
|
-
status_data(*args).each do |file,|
|
|
2076
|
+
status_data(*args).map(&:first).each_with_object({}) do |file, out|
|
|
2033
2077
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
|
2034
2078
|
next if pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
|
2035
2079
|
|
|
2036
|
-
|
|
2080
|
+
out[file] = algorithm.hexdigest(File.read(basepath(file)))
|
|
2037
2081
|
end
|
|
2038
|
-
ret
|
|
2039
2082
|
end
|
|
2040
2083
|
|
|
2041
2084
|
def status_data(*args)
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
next unless line =~ /^(.)(.) (.+)$/
|
|
2045
|
-
|
|
2046
|
-
ret << [$3, $2, $1]
|
|
2085
|
+
git_spawn('status -z -uall', *args).split("\x0").each_with_object([]) do |line, out|
|
|
2086
|
+
out << [$3, $2, $1] if line =~ /^(.)(.) (.+)$/
|
|
2047
2087
|
end
|
|
2048
|
-
ret
|
|
2049
2088
|
end
|
|
2050
2089
|
|
|
2051
2090
|
def append_pull(opts, list, flag:, from:, target: @session, no: nil, remote: nil)
|
|
@@ -2053,9 +2092,8 @@ module Squared
|
|
|
2053
2092
|
append_submodules(target: target, from: from)
|
|
2054
2093
|
return if !remote && opts.empty?
|
|
2055
2094
|
|
|
2056
|
-
refspec = []
|
|
2057
2095
|
op = OptionPartition.new(opts, remote ? list + ['refspec=v'] : list, target, project: self, no: no)
|
|
2058
|
-
op.
|
|
2096
|
+
refspec = op.each_with_object([]) do |opt, out|
|
|
2059
2097
|
if opt =~ op.values
|
|
2060
2098
|
case $1
|
|
2061
2099
|
when 'rebase'
|
|
@@ -2066,7 +2104,7 @@ module Squared
|
|
|
2066
2104
|
when 'recurse-submodules'
|
|
2067
2105
|
op.append?($1, $2, type: :basic)
|
|
2068
2106
|
when 'refspec'
|
|
2069
|
-
|
|
2107
|
+
out << shell_quote($2)
|
|
2070
2108
|
end
|
|
2071
2109
|
elsif op.arg?('multiple')
|
|
2072
2110
|
op.found << opt
|
|
@@ -2078,7 +2116,7 @@ module Squared
|
|
|
2078
2116
|
if remote
|
|
2079
2117
|
op.append(remote, delim: true)
|
|
2080
2118
|
if (val = option('refspec', target: target, strict: true))
|
|
2081
|
-
op.append(
|
|
2119
|
+
op.append(split_escape(val))
|
|
2082
2120
|
else
|
|
2083
2121
|
op.merge(refspec)
|
|
2084
2122
|
end
|
|
@@ -2092,27 +2130,31 @@ module Squared
|
|
|
2092
2130
|
op.clear(errors: true, subject: flag) if flag
|
|
2093
2131
|
end
|
|
2094
2132
|
|
|
2095
|
-
def append_commit(*
|
|
2096
|
-
|
|
2097
|
-
if !
|
|
2098
|
-
|
|
2133
|
+
def append_commit(*refs, target: @session, head: false)
|
|
2134
|
+
refs.compact!
|
|
2135
|
+
if !refs.empty?
|
|
2136
|
+
target.merge(refs.map { |val| commithash(val) || shell_quote(val) })
|
|
2099
2137
|
elsif head
|
|
2100
2138
|
target << (append_head(target: target) || 'HEAD')
|
|
2101
2139
|
end
|
|
2102
2140
|
end
|
|
2103
2141
|
|
|
2104
|
-
def append_pathspec(files = [], target: @session, expect: false,
|
|
2142
|
+
def append_pathspec(files = [], target: @session, expect: false, **kwargs)
|
|
2105
2143
|
if session_arg?('pathspec-from-file', target: target)
|
|
2106
|
-
|
|
2144
|
+
OptionPartition.clear(target, files, styles: theme[:inline])
|
|
2107
2145
|
true
|
|
2108
2146
|
else
|
|
2109
2147
|
option('pathspec', target: target) { |val| files = split_escape(val) } if files.empty?
|
|
2110
|
-
files = projectmap(files,
|
|
2148
|
+
files = projectmap(files, **kwargs)
|
|
2111
2149
|
if !files.empty?
|
|
2112
2150
|
target << '--' << files.join(' ')
|
|
2113
2151
|
true
|
|
2114
2152
|
elsif expect
|
|
2115
|
-
raise_error(
|
|
2153
|
+
raise_error(if expect.is_a?(String)
|
|
2154
|
+
expect
|
|
2155
|
+
else
|
|
2156
|
+
kwargs[:parent] ? 'pathspec not present' : 'pathspec not within worktree'
|
|
2157
|
+
end)
|
|
2116
2158
|
else
|
|
2117
2159
|
false
|
|
2118
2160
|
end
|
|
@@ -2156,11 +2198,15 @@ module Squared
|
|
|
2156
2198
|
end
|
|
2157
2199
|
end
|
|
2158
2200
|
|
|
2159
|
-
def foreachref(path, *args, format: nil)
|
|
2160
|
-
path = Array(path).map
|
|
2201
|
+
def foreachref(path, *args, format: nil, chomp: true)
|
|
2202
|
+
path = Array(path).map { |val| "refs/#{val}" }
|
|
2161
2203
|
format &&= quote_option('format', format)
|
|
2162
2204
|
ret = git_spawn('for-each-ref', format, *args, *path, stdout: workspace.windows?)
|
|
2163
|
-
ret.is_a?(String)
|
|
2205
|
+
if ret.is_a?(String)
|
|
2206
|
+
ret.lines(chomp: chomp)
|
|
2207
|
+
else
|
|
2208
|
+
chomp ? ret.readlines(chomp: chomp) : ret
|
|
2209
|
+
end
|
|
2164
2210
|
end
|
|
2165
2211
|
|
|
2166
2212
|
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
|
@@ -2207,7 +2253,9 @@ module Squared
|
|
|
2207
2253
|
raise_error(ArgumentError, "missing #{origin ? 'branch' : 'remote'} name", hint: origin)
|
|
2208
2254
|
end
|
|
2209
2255
|
branch = "#{branch}:#{origin[i.succ..-1]}" unless origin.end_with?("/#{branch}")
|
|
2210
|
-
[origin[0..i.pred], branch]
|
|
2256
|
+
ret = [origin[0..i.pred], branch]
|
|
2257
|
+
ret.quote! if quote
|
|
2258
|
+
ret
|
|
2211
2259
|
end
|
|
2212
2260
|
|
|
2213
2261
|
def commithash(val)
|
|
@@ -2232,16 +2280,22 @@ module Squared
|
|
|
2232
2280
|
[/\A[^a-z\d-]+/i, %r{\A[^=\\/*]*[\\/*]}, /\A--\z/]
|
|
2233
2281
|
end
|
|
2234
2282
|
|
|
2283
|
+
def matchfile(file, pat)
|
|
2284
|
+
file.read[pat, 0] if file.exist?
|
|
2285
|
+
rescue
|
|
2286
|
+
nil
|
|
2287
|
+
end
|
|
2288
|
+
|
|
2235
2289
|
def messageopt
|
|
2236
2290
|
option('message', 'm', prefix: 'git', ignore: false)
|
|
2237
2291
|
end
|
|
2238
2292
|
|
|
2239
2293
|
def threadargs
|
|
2240
|
-
{ stderr: true, exception: exception || !workspace.series.multiple? }
|
|
2294
|
+
{ stderr: true, exception: exception? || !workspace.series.multiple? }
|
|
2241
2295
|
end
|
|
2242
2296
|
end
|
|
2243
2297
|
|
|
2244
|
-
Application.implement Git
|
|
2298
|
+
Application.implement Git, base: 1
|
|
2245
2299
|
end
|
|
2246
2300
|
end
|
|
2247
2301
|
end
|