squared 0.3.6 → 0.4.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 +70 -2
- data/README.md +13 -2
- data/README.ruby.md +171 -88
- data/lib/squared/app.rb +1 -0
- data/lib/squared/common/base.rb +6 -1
- data/lib/squared/common/class.rb +1 -1
- data/lib/squared/common/format.rb +32 -15
- data/lib/squared/common/prompt.rb +2 -2
- data/lib/squared/common/shell.rb +52 -39
- data/lib/squared/common/utils.rb +68 -2
- data/lib/squared/config.rb +1 -1
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +16 -13
- data/lib/squared/workspace/project/base.rb +429 -123
- data/lib/squared/workspace/project/docker.rb +622 -0
- data/lib/squared/workspace/project/git.rb +427 -164
- data/lib/squared/workspace/project/node.rb +48 -50
- data/lib/squared/workspace/project/python.rb +115 -25
- data/lib/squared/workspace/project/ruby.rb +33 -35
- data/lib/squared/workspace/project.rb +7 -1
- data/lib/squared/workspace/repo.rb +9 -4
- data/lib/squared/workspace/series.rb +1 -1
- metadata +3 -2
@@ -1,5 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'date'
|
4
|
+
require 'time'
|
5
|
+
require 'digest'
|
6
|
+
|
3
7
|
module Squared
|
4
8
|
module Workspace
|
5
9
|
module Git
|
@@ -7,7 +11,9 @@ module Squared
|
|
7
11
|
GIT_PROTO = %r{^(?:https?|ssh|git|file)://}i.freeze
|
8
12
|
private_constant :GIT_REPO, :GIT_PROTO
|
9
13
|
|
10
|
-
|
14
|
+
attr_reader :revfile
|
15
|
+
|
16
|
+
def git(name, uri = nil, base: nil, repo: [], options: {}, cache: nil)
|
11
17
|
data = {}
|
12
18
|
check = ->(proj) { proj.is_a?(Project::Git) && !proj.exclude?(Project::Git.ref) && git_clone?(proj.path) }
|
13
19
|
if uri.is_a?(Array)
|
@@ -17,15 +23,15 @@ module Squared
|
|
17
23
|
data[name.to_s] = uri
|
18
24
|
elsif name.is_a?(Enumerable)
|
19
25
|
data = name.to_h
|
20
|
-
elsif name.is_a?(String) && name
|
26
|
+
elsif name.is_a?(String) && name.match?(GIT_PROTO)
|
21
27
|
base = name
|
22
28
|
@project.each_value { |proj| repo << proj if !proj.parent && check.(proj) }
|
23
29
|
else
|
24
|
-
warn log_message(Logger::WARN, name, subject: 'git', hint: 'invalid') if warning
|
30
|
+
warn log_message(Logger::WARN, name, subject: 'git', hint: 'invalid', pass: true) if warning
|
25
31
|
return self
|
26
32
|
end
|
27
33
|
if base
|
28
|
-
base = base
|
34
|
+
base = base.match?(GIT_PROTO) ? "#{base.chomp('/')}/" : @root.join(base)
|
29
35
|
repo.each do |target|
|
30
36
|
if target.is_a?(Project::Git)
|
31
37
|
data[target.localname] = target.project
|
@@ -55,6 +61,23 @@ module Squared
|
|
55
61
|
(GIT_REPO[main] ||= {})[key] = [uri.to_s, opts]
|
56
62
|
(@kind[key] ||= []) << Project::Git
|
57
63
|
end
|
64
|
+
if cache == true
|
65
|
+
revbuild
|
66
|
+
elsif cache
|
67
|
+
revbuild(file: cache)
|
68
|
+
end
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def revbuild(file: nil)
|
73
|
+
@revfile = @home.join(file || "#{@main}.revb")
|
74
|
+
@revdoc = JSON.parse(@revfile.read) if @revfile.exist?
|
75
|
+
rescue StandardError => e
|
76
|
+
@revfile = nil
|
77
|
+
warn log_message(Logger::WARN, e, pass: true) if @warning
|
78
|
+
self
|
79
|
+
else
|
80
|
+
@revdoc = {} unless @revdoc.is_a?(Hash)
|
58
81
|
self
|
59
82
|
end
|
60
83
|
|
@@ -62,11 +85,61 @@ module Squared
|
|
62
85
|
(ret = GIT_REPO[main]) && ret[name]
|
63
86
|
end
|
64
87
|
|
88
|
+
def rev_entry(*keys, val: nil, create: true)
|
89
|
+
return unless @revdoc
|
90
|
+
return @revdoc.dig(*keys) unless val
|
91
|
+
|
92
|
+
data = @revdoc
|
93
|
+
last = keys.pop
|
94
|
+
for key in keys
|
95
|
+
if data[key].is_a?(Hash)
|
96
|
+
data = data[key]
|
97
|
+
elsif create
|
98
|
+
data = data[key] = {}
|
99
|
+
else
|
100
|
+
return
|
101
|
+
end
|
102
|
+
end
|
103
|
+
data[last] = val
|
104
|
+
end
|
105
|
+
|
106
|
+
def rev_timeutc(*keys)
|
107
|
+
rev_entry(*keys, val: rev_timenow)
|
108
|
+
end
|
109
|
+
|
110
|
+
def rev_timesince(*keys, clock: false)
|
111
|
+
epoch = rev_timenow - rev_entry(*keys).to_i
|
112
|
+
rescue StandardError
|
113
|
+
nil
|
114
|
+
else
|
115
|
+
time_format(epoch, clock: clock)
|
116
|
+
end
|
117
|
+
|
118
|
+
def rev_clear(name)
|
119
|
+
rev_write if rev_entry(name, 'revision', val: '', create: false)
|
120
|
+
end
|
121
|
+
|
122
|
+
def rev_write(name = nil, data = nil, utc: nil)
|
123
|
+
return unless @revfile
|
124
|
+
|
125
|
+
if name
|
126
|
+
data&.each { |key, val| rev_entry(name, key, val: val) }
|
127
|
+
rev_timeutc(name, utc) if utc
|
128
|
+
end
|
129
|
+
File.write(@revfile, JSON.pretty_generate(@revdoc))
|
130
|
+
end
|
131
|
+
|
65
132
|
def git_clone?(path, name = nil)
|
66
133
|
return false if name && !git_repo(name)
|
67
134
|
|
68
135
|
!path.exist? || path.empty?
|
69
136
|
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def rev_timenow
|
141
|
+
DateTime.now.strftime('%Q').to_i + time_offset
|
142
|
+
end
|
70
143
|
end
|
71
144
|
Application.include Git
|
72
145
|
|
@@ -75,12 +148,15 @@ module Squared
|
|
75
148
|
include Prompt
|
76
149
|
|
77
150
|
OPT_GIT = {
|
151
|
+
common: %w[bare p|paginate P|no-pager glob-pathspecs icase-pathspecs literal-pathspecs no-optional-locks
|
152
|
+
no-replace-objects noglob-pathspecs c=q config-env=q exec-path=p namespace=p].freeze,
|
78
153
|
branch: %w[a|all create-reflog i|ignore-case q|quiet r|remotes v|verbose abbrev=i color=b column=b
|
79
|
-
contains=
|
154
|
+
contains=b format=q merged=b no-contains=b no-merged=b points-at=e u|set-upstream-to=e sort=q
|
80
155
|
t|track=b].freeze,
|
81
156
|
checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
|
82
157
|
pathspec-file-nul q quiet orphan=e ours theirs conflict=b pathspec-from-file=p
|
83
158
|
t|track=b].freeze,
|
159
|
+
clean: %w[d x X f|force i|interactive n|dry-run q|quiet e|exlcude=q].freeze,
|
84
160
|
diff: {
|
85
161
|
base: %w[0 1|base 2|ours 3|theirs].freeze,
|
86
162
|
show: %w[s exit-code histogram].freeze
|
@@ -90,7 +166,7 @@ module Squared
|
|
90
166
|
recurse-submodules-default=b].freeze,
|
91
167
|
pull: %w[4 6 n t a|append atomic dry-run f|force k|keep n|negotiate-only prefetch p|prune q|quiet
|
92
168
|
set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
|
93
|
-
refmap=q o|server-option=
|
169
|
+
refmap=q o|server-option=q shallow-exclude=e shallow-since=b upload-pack=q].freeze
|
94
170
|
}.freeze,
|
95
171
|
log: {
|
96
172
|
base: %w[all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
|
@@ -98,7 +174,7 @@ module Squared
|
|
98
174
|
first-parent F|fixed-strings follow full-diff full-history ignore-missing invert-grep left-only
|
99
175
|
merge log-size no-max-parents no-min-parents not P|perl-regexp reflog i|regexp-ignore-case
|
100
176
|
remove-empty reverse right-only simplify-by-decoration simplify-merges single-worktree show-pulls
|
101
|
-
source sparse stdin topo-order g|walk-reflogs after=q ancestry-path=
|
177
|
+
source sparse stdin topo-order g|walk-reflogs after=q ancestry-path=b? author=q before=q
|
102
178
|
branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
|
103
179
|
exclude-hidden=b? glob=q grep=q grep-reflog=q L=q n|max-count=i max-parents=i min-parents=i
|
104
180
|
no-walk=b? remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
|
@@ -109,9 +185,9 @@ module Squared
|
|
109
185
|
W|function-context w|ignore-all-space ignore-blank-lines ignore-cr-at-eol ignore-space-at-eol
|
110
186
|
b|ignore-space-change D|irreversible-delete graph ita-invisible-in-index minimal name-only
|
111
187
|
name-status no-color-moved-ws no-prefix no-renames numstat patch-with-raw patch-with-stat patience
|
112
|
-
pickaxe-all pickaxe-regex raw shortstat summary a|text abbrev=i? anchored=q B|break-rewrites=
|
188
|
+
pickaxe-all pickaxe-regex raw shortstat summary a|text abbrev=i? anchored=q B|break-rewrites=b?
|
113
189
|
color=b color-moved=b color-moved-ws=b color-words=q? diff-algorithm=b diff-filter=e? X|dirstat=q?
|
114
|
-
dirstat-by-file=q? dst-prefix=q C|find-copies=i? find-object=
|
190
|
+
dirstat-by-file=q? dst-prefix=q C|find-copies=i? find-object=b M|find-renames=i?
|
115
191
|
I|ignore-matching-lines=q ignore-submodules=b inter-hunk-context=i line-prefix=q output=p
|
116
192
|
output-indicator-context=q output-indicator-new=q output-indicator-old=q relative=p rotate-to=p
|
117
193
|
skip-to=p src-prefix=q stat=q? stat-width=i stat-name-width=i stat-count=i submodule=b? U|unified=i
|
@@ -120,25 +196,32 @@ module Squared
|
|
120
196
|
ls_files: %w[z debug deduplicate directory eol error-unmatch exclude-standard full-name k|killed
|
121
197
|
no-empty-directory recurse-submodules sparse s|stage u|unmerged abbrev=i x|exclude=q
|
122
198
|
X|exclude-from=p exclude-per-directory=p format=q with-tree=q].freeze,
|
123
|
-
ls_remote: %w[exit-code get-url q|quiet o|server-option=
|
124
|
-
|
125
|
-
|
199
|
+
ls_remote: %w[exit-code get-url q|quiet o|server-option=q symref sort=q upload-pack=q].freeze,
|
200
|
+
mv: %w[k f|force n|dry-run v|verbose].freeze,
|
201
|
+
pull: %w[e n allow-unrelated-histories ff-only S|gpg-sign=qq log=i r|rebase=b? s|strategy=b
|
202
|
+
X|strategy-option=b].freeze,
|
203
|
+
merge: %w[e n allow-unrelated-histories ff-only m=q q|quiet v|verbose cleanup=b F|file=p S|gpg-sign=qq
|
204
|
+
into-name=e log=i s|strategy=b X|strategy-option=b].freeze,
|
126
205
|
rebase: %w[n C=i allow-empty-message apply committer-date-is-author-date edit-todo f|force-rebase ignore-date
|
127
206
|
ignore-whitespace i|interactive keep-base m merge no-ff q|quiet quit r|rebase-merges=b?
|
128
|
-
reset-author-date root show-current-patch signoff v|verbose empty=b S|gpg-sign=
|
129
|
-
s|strategy=b X|strategy-option=b whitespace=
|
207
|
+
reset-author-date root show-current-patch signoff v|verbose empty=b S|gpg-sign=qq onto=e
|
208
|
+
s|strategy=b X|strategy-option=b whitespace=b].freeze,
|
130
209
|
reset: %w[N pathspec-file-nul q|quiet pathspec-from-file=p].freeze,
|
131
210
|
restore: %w[ignore-unmerged ignore-skip-worktree-bits m|merge ours p|patch pathspec-file-nul S|staged theirs
|
132
211
|
W|worktree conflict=b pathspec-from-file=p s|source=q].freeze,
|
212
|
+
revert: %w[e abort continue no-commit quit reference skip cleanup=b S|gpg-sign=qq m|mainline=i s|signoff
|
213
|
+
strategy=b X|strategy-option=b].freeze,
|
133
214
|
rev_parse: {
|
134
215
|
output: %w[absolute-git-dir all flags git-common-dir git-dir is-bare-repository is-inside-git-dir
|
135
216
|
is-inside-work-tree is-shallow-repository local-env-vars no-flags no-revs not q|quiet sq
|
136
217
|
revs-only shared-index-path show-cdup show-prefix show-toplevel show-superproject-working-tree
|
137
|
-
sq-quote symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q default=
|
218
|
+
sq-quote symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q default=q
|
138
219
|
disambiguate=b exclude=q exclude-hidden=b glob=q git-path=p path-format=b? prefix=q branches=q?
|
139
220
|
remotes=q? resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
|
140
221
|
parseopt: %w[keep-dashdash stop-at-non-option stuck-long].freeze
|
141
222
|
}.freeze,
|
223
|
+
rm: %w[r cached f|force n|dry-run ignore-unmatch pathspec-file-nul q|quiet sparse v|verbose
|
224
|
+
pathspec-from-file=p].freeze,
|
142
225
|
show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
|
143
226
|
expand-tabs=i notes=q show-notes=q?].freeze,
|
144
227
|
stash: {
|
@@ -148,7 +231,8 @@ module Squared
|
|
148
231
|
pop: %w[index].freeze,
|
149
232
|
apply: %w[index].freeze
|
150
233
|
}.freeze,
|
151
|
-
|
234
|
+
status: %w[untracked-files=b? u|ignore-submodules=m? ignored=b?],
|
235
|
+
tag: %w[create-reflog column=b contains=b? format=q merged=b? n=i no-contains=b? no-merged=b? points-at=q
|
152
236
|
sort=q].freeze,
|
153
237
|
no: {
|
154
238
|
fetch: {
|
@@ -164,20 +248,26 @@ module Squared
|
|
164
248
|
tag: %w[column].freeze,
|
165
249
|
branch: %w[color-moved column color track].freeze,
|
166
250
|
checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
|
251
|
+
merge: %w[autostash edit ff gpg-sign log progress overwrite-ignore rerere-autoupdate signoff squash stat
|
252
|
+
verify verify-signatures].freeze,
|
167
253
|
rebase: %w[autosquash autostash fork-point gpg-sign keep-empty reapply-cherry-picks reschedule-failed-exec
|
168
254
|
rerere-autoupdate stat update-refs verify].freeze,
|
169
255
|
reset: %w[refresh].freeze,
|
170
256
|
restore: %w[overlay progress recurse-submodules].freeze,
|
257
|
+
revert: %w[edit gpg-sign rerere-autoupdate].freeze,
|
171
258
|
show: %w[standard-notes].freeze
|
172
259
|
}.freeze
|
173
|
-
}
|
260
|
+
}.freeze
|
174
261
|
VAL_GIT = {
|
262
|
+
merge: {
|
263
|
+
send: %w[continue abort quit].freeze
|
264
|
+
}.freeze,
|
175
265
|
rebase: {
|
176
266
|
send: %w[continue skip abort quit].freeze,
|
177
267
|
value: %w[true false merges interactive].freeze
|
178
268
|
}.freeze,
|
179
269
|
reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze
|
180
|
-
}
|
270
|
+
}.freeze
|
181
271
|
private_constant :OPT_GIT, :VAL_GIT
|
182
272
|
|
183
273
|
class << self
|
@@ -209,11 +299,7 @@ module Squared
|
|
209
299
|
end
|
210
300
|
|
211
301
|
def tasks
|
212
|
-
%i[pull rebase fetch clone stash status].freeze
|
213
|
-
end
|
214
|
-
|
215
|
-
def batchargs
|
216
|
-
[ref, { 'pull+s': %i[stash pull], 'rebase+s': %i[stash rebase] }]
|
302
|
+
%i[pull rebase fetch clone stash status branch revbuild].freeze
|
217
303
|
end
|
218
304
|
|
219
305
|
def config?(val)
|
@@ -227,24 +313,25 @@ module Squared
|
|
227
313
|
'branch' => %i[create set delete move copy list edit current].freeze,
|
228
314
|
'checkout' => %i[commit branch track detach path].freeze,
|
229
315
|
'commit' => %i[add all amend amend-orig].freeze,
|
230
|
-
'diff' => %i[head
|
316
|
+
'diff' => %i[head branch files view between contain].freeze,
|
231
317
|
'fetch' => %i[origin remote].freeze,
|
232
318
|
'files' => %i[cached modified deleted others ignored].freeze,
|
319
|
+
'git' => %i[clean mv restore revert rm].freeze,
|
233
320
|
'log' => %i[view between contain].freeze,
|
321
|
+
'merge' => %i[commit no-commit send].freeze,
|
234
322
|
'pull' => %i[origin remote].freeze,
|
235
323
|
'rebase' => %i[branch onto send].freeze,
|
236
324
|
'refs' => %i[heads tags remote].freeze,
|
237
325
|
'reset' => %i[commit index patch mode].freeze,
|
238
|
-
'
|
239
|
-
'
|
240
|
-
'show' => %i[format oneline].freeze,
|
326
|
+
'rev' => %i[commit branch output parseopt build].freeze,
|
327
|
+
'show' => %i[format oneline textconv].freeze,
|
241
328
|
'stash' => %i[push pop apply drop clear list].freeze,
|
242
329
|
'tag' => %i[add delete list].freeze
|
243
330
|
}.freeze
|
244
331
|
|
245
332
|
def initialize(*, **)
|
246
333
|
super
|
247
|
-
initialize_ref
|
334
|
+
initialize_ref Git.ref if gitpath.exist?
|
248
335
|
end
|
249
336
|
|
250
337
|
def ref
|
@@ -289,19 +376,6 @@ module Squared
|
|
289
376
|
commit(flag, refs: refs)
|
290
377
|
end
|
291
378
|
end
|
292
|
-
when 'restore'
|
293
|
-
if flag == :source
|
294
|
-
format_desc action, flag, 'tree,opts*,pathspec*'
|
295
|
-
task flag, [:tree] do |_, args|
|
296
|
-
tree = param_guard(action, flag, args: args, key: :tree)
|
297
|
-
restore(flag, args.extras, tree: tree)
|
298
|
-
end
|
299
|
-
else
|
300
|
-
format_desc action, flag, 'opts*,pathspec+'
|
301
|
-
task flag do |_, args|
|
302
|
-
restore flag, args.to_a
|
303
|
-
end
|
304
|
-
end
|
305
379
|
when 'tag'
|
306
380
|
case flag
|
307
381
|
when :list
|
@@ -335,9 +409,19 @@ module Squared
|
|
335
409
|
case flag
|
336
410
|
when :view, :between, :contain
|
337
411
|
if flag == :view && action == 'log'
|
338
|
-
format_desc action, flag, '(^)commit*,pathspec*,opts*'
|
412
|
+
format_desc action, flag, '(^)commit/H0*,pathspec*,opts*'
|
339
413
|
task flag do |_, args|
|
340
|
-
|
414
|
+
index = []
|
415
|
+
args.to_a.each do |val|
|
416
|
+
if val =~ /^H(\d+)$/
|
417
|
+
index << "HEAD~#{$1}"
|
418
|
+
elsif (sha = commithash(val))
|
419
|
+
index << sha
|
420
|
+
elsif val.start_with?('^') || (!%r{^[.\\/]}.match?(val) && !%r{[\\/]$}.match?(val))
|
421
|
+
index << shell_quote(val)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
logx(flag, args.to_a.drop(index.size), index: index)
|
341
425
|
end
|
342
426
|
else
|
343
427
|
format_desc action, flag, 'commit1,commit2,pathspec*,opts*'
|
@@ -347,10 +431,16 @@ module Squared
|
|
347
431
|
__send__(action == 'log' ? :logx : :diff, flag, args.extras, range: [commit1, commit2])
|
348
432
|
end
|
349
433
|
end
|
350
|
-
when :head
|
351
|
-
format_desc action, flag, 'opts*,pathspec*'
|
434
|
+
when :head
|
435
|
+
format_desc action, flag, 'commit/H0*,opts*,pathspec*'
|
352
436
|
task flag do |_, args|
|
353
|
-
|
437
|
+
index = []
|
438
|
+
args.to_a.each do |val|
|
439
|
+
break unless val =~ /^H(\d+)$/ || (sha = commithash(val))
|
440
|
+
|
441
|
+
index << ($1 ? "HEAD~#{$1}" : sha)
|
442
|
+
end
|
443
|
+
diff(flag, args.to_a.drop(index.size), index: index)
|
354
444
|
end
|
355
445
|
when :branch
|
356
446
|
format_desc action, flag, 'name,opts*,pathspec*'
|
@@ -487,15 +577,21 @@ module Squared
|
|
487
577
|
when :oneline
|
488
578
|
format_desc action, flag, 'opts*,object*'
|
489
579
|
task flag do |_, args|
|
490
|
-
show
|
580
|
+
show flag, args.to_a.push('abbrev-commit')
|
491
581
|
end
|
492
582
|
when :format
|
493
583
|
format_desc action, flag, 'format?,opts*,object*'
|
494
584
|
task flag, [:format] do |_, args|
|
495
|
-
show args.
|
585
|
+
show(flag, args.extras, format: args.format)
|
586
|
+
end
|
587
|
+
when :textconv
|
588
|
+
format_desc action, flag, 'files+'
|
589
|
+
task flag do |_, args|
|
590
|
+
files = param_guard(action, flag, args: args.to_a)
|
591
|
+
show(flag, files: files)
|
496
592
|
end
|
497
593
|
end
|
498
|
-
when 'rebase'
|
594
|
+
when 'rebase', 'merge'
|
499
595
|
case flag
|
500
596
|
when :branch
|
501
597
|
format_desc action, flag, 'opts*,upstream?,branch?'
|
@@ -510,11 +606,18 @@ module Squared
|
|
510
606
|
upstream = param_guard(action, flag, args: args, key: :upstream)
|
511
607
|
rebase(flag, commit: commit, upstream: upstream, branch: args.branch)
|
512
608
|
end
|
609
|
+
when :commit, :'no-commit'
|
610
|
+
format_desc action, flag, 'branch/commit+,opts*'
|
611
|
+
task flag do |_, args|
|
612
|
+
args = param_guard(action, flag, args: args.to_a)
|
613
|
+
merge flag, args
|
614
|
+
end
|
513
615
|
when :send
|
514
|
-
format_desc(action, flag, VAL_GIT[
|
616
|
+
format_desc(action, flag, VAL_GIT[action.to_sym][:send], arg: nil)
|
515
617
|
task flag, [:command] do |_, args|
|
516
|
-
command = param_guard(action, flag, args: args, key: :command
|
517
|
-
|
618
|
+
command = param_guard(action, flag, args: args, key: :command,
|
619
|
+
values: VAL_GIT[action.to_sym][:send])
|
620
|
+
__send__(action, flag, command: command)
|
518
621
|
end
|
519
622
|
end
|
520
623
|
when 'rev'
|
@@ -535,6 +638,11 @@ module Squared
|
|
535
638
|
task flag, [:ref] do |_, args|
|
536
639
|
rev_parse(flag, ref: args.ref)
|
537
640
|
end
|
641
|
+
when :build
|
642
|
+
format_desc action, flag, OPT_GIT[:status]
|
643
|
+
task flag do |_, args|
|
644
|
+
revbuild flag, args.to_a
|
645
|
+
end
|
538
646
|
else
|
539
647
|
format_desc action, flag, 'opts*,args*'
|
540
648
|
task flag do |_, args|
|
@@ -554,6 +662,18 @@ module Squared
|
|
554
662
|
__send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
|
555
663
|
end
|
556
664
|
end
|
665
|
+
when 'git'
|
666
|
+
format_desc(action, flag, 'opts*', before: case flag
|
667
|
+
when :rm
|
668
|
+
'source+,destination'
|
669
|
+
when :revert
|
670
|
+
'commit+'
|
671
|
+
else
|
672
|
+
'pathspec*'
|
673
|
+
end)
|
674
|
+
task flag do |_, args|
|
675
|
+
git(flag, args.to_a)
|
676
|
+
end
|
557
677
|
end
|
558
678
|
end
|
559
679
|
end
|
@@ -566,8 +686,18 @@ module Squared
|
|
566
686
|
super
|
567
687
|
end
|
568
688
|
|
689
|
+
def depend(*, **)
|
690
|
+
workspace.rev_clear name
|
691
|
+
super
|
692
|
+
end
|
693
|
+
|
694
|
+
def clean(*, **)
|
695
|
+
workspace.rev_clear name
|
696
|
+
super
|
697
|
+
end
|
698
|
+
|
569
699
|
def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil)
|
570
|
-
cmd = git_session
|
700
|
+
cmd, opts = git_session('pull', flag && "--#{flag}", opts: opts)
|
571
701
|
if (val = option('rebase', ignore: false))
|
572
702
|
cmd << case val
|
573
703
|
when '0'
|
@@ -580,8 +710,8 @@ module Squared
|
|
580
710
|
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag)
|
581
711
|
source(sync: sync, sub: if verbose
|
582
712
|
[
|
583
|
-
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
|
584
|
-
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: :green, index: 3 }
|
713
|
+
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: color(:red), index: 4 },
|
714
|
+
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: color(:green), index: 3 }
|
585
715
|
]
|
586
716
|
end, **threadargs)
|
587
717
|
end
|
@@ -590,7 +720,7 @@ module Squared
|
|
590
720
|
command: nil)
|
591
721
|
return pull(:rebase, sync: sync) unless flag
|
592
722
|
|
593
|
-
cmd = git_session
|
723
|
+
cmd, opts = git_session('rebase', opts: opts)
|
594
724
|
case flag
|
595
725
|
when :branch
|
596
726
|
branch = option_sanitize(opts, OPT_GIT[:rebase], no: OPT_GIT[:no][:rebase]).first
|
@@ -619,7 +749,7 @@ module Squared
|
|
619
749
|
end
|
620
750
|
|
621
751
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
622
|
-
cmd = git_session
|
752
|
+
cmd, opts = git_session('fetch', opts: opts)
|
623
753
|
cmd << '--all' if !remote && !opts.include?('multiple') && option('all')
|
624
754
|
cmd << '--verbose' if verbose && !opts.include?('quiet')
|
625
755
|
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
|
@@ -651,9 +781,8 @@ module Squared
|
|
651
781
|
|
652
782
|
def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
|
653
783
|
if flag
|
654
|
-
cmd = git_session
|
655
|
-
|
656
|
-
refs = option_sanitize(opts, list).first
|
784
|
+
cmd, opts = git_session('stash', flag, opts: opts)
|
785
|
+
refs = option_sanitize(opts, OPT_GIT[:stash][:common] + OPT_GIT[:stash].fetch(flag, [])).first
|
657
786
|
case flag
|
658
787
|
when :push
|
659
788
|
append_pathspec refs
|
@@ -675,14 +804,14 @@ module Squared
|
|
675
804
|
return
|
676
805
|
end
|
677
806
|
else
|
678
|
-
git_session
|
807
|
+
git_session('stash', 'push', opts: opts)
|
679
808
|
append_option(%w[all keep-index include-untracked staged].freeze, no: true, ignore: false)
|
680
809
|
append_message option('message', 'm', ignore: false)
|
681
810
|
end
|
682
811
|
source(banner: !quiet?, sync: sync, **threadargs)
|
683
812
|
end
|
684
813
|
|
685
|
-
def status(
|
814
|
+
def status(*)
|
686
815
|
cmd = git_session 'status'
|
687
816
|
cmd << (option('long') ? '--long' : '--short')
|
688
817
|
if (val = option('ignore-submodules', ignore: false))
|
@@ -699,24 +828,76 @@ module Squared
|
|
699
828
|
end
|
700
829
|
append_pathspec
|
701
830
|
out, banner, from = source(io: true)
|
702
|
-
if sync
|
703
|
-
print_item banner
|
704
|
-
banner = nil
|
705
|
-
end
|
706
831
|
ret = write_lines(out, banner: banner, sub: if verbose
|
832
|
+
r = color(:red)
|
833
|
+
g = color(:green)
|
707
834
|
[
|
708
|
-
{ pat: /^(.)([A-Z?!])(.+)$/, styles:
|
709
|
-
{ pat: /^([A-Z?!])(.+)$/, styles:
|
710
|
-
{ pat: /^(\?\?)(.+)$/, styles:
|
835
|
+
{ pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
|
836
|
+
{ pat: /^([A-Z?!])(.+)$/, styles: g },
|
837
|
+
{ pat: /^(\?\?)(.+)$/, styles: r },
|
711
838
|
{ pat: /^(## )(.+)(\.{3})(.+)$/,
|
712
|
-
styles: [nil,
|
839
|
+
styles: [nil, g, nil, r], index: -1 }
|
713
840
|
]
|
714
841
|
end)
|
715
842
|
list_result(ret, 'files', from: from, action: 'modified')
|
716
843
|
end
|
717
844
|
|
845
|
+
def revbuild(flag = nil, opts = [], sync: invoked_sync?('revbuild', flag), **kwargs)
|
846
|
+
statusargs = lambda do
|
847
|
+
{
|
848
|
+
include: relativepath(as_a(kwargs[:include]), all: true),
|
849
|
+
exclude: relativepath(as_a(kwargs[:exclude]), all: true)
|
850
|
+
}
|
851
|
+
end
|
852
|
+
unless workspace.closed
|
853
|
+
if @revbuild
|
854
|
+
statusargs.().each { |key, val| @revbuild[key] += val }
|
855
|
+
else
|
856
|
+
@revbuild = statusargs.()
|
857
|
+
end
|
858
|
+
return
|
859
|
+
end
|
860
|
+
sha = source(git_output('rev-parse --verify HEAD'), io: true, banner: false, stdout: true).first.to_s.chomp
|
861
|
+
return if sha.empty?
|
862
|
+
|
863
|
+
args = []
|
864
|
+
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.() : @revbuild || {}
|
865
|
+
case flag
|
866
|
+
when :build
|
867
|
+
opts = option_sanitize(opts, OPT_GIT[:status], target: args).first
|
868
|
+
option_clear opts
|
869
|
+
else
|
870
|
+
args << basic_option('untracked-files', flag) if (flag = option('untracked-files', prefix: 'git'))
|
871
|
+
args << basic_option('ignore-submodules', flag) if (flag = option('ignore-submodules', prefix: 'git'))
|
872
|
+
args << basic_option('ignored', flag) if (flag = option('ignored', prefix: 'git'))
|
873
|
+
end
|
874
|
+
if (cur = workspace.rev_entry(name)) && cur['revision'] == sha
|
875
|
+
files = status_digest(*args, **kwargs)
|
876
|
+
if cur['files'].size == files.size && cur['files'].find { |key, val| files[key] != val }.nil?
|
877
|
+
if verbose
|
878
|
+
if (since = workspace.rev_timesince(name, 'build'))
|
879
|
+
puts log_message(Logger::INFO, name, 'no changes', subject: 'revbuild', hint: "#{since} ago")
|
880
|
+
else
|
881
|
+
workspace.rev_timeutc(name, 'build')
|
882
|
+
end
|
883
|
+
end
|
884
|
+
return
|
885
|
+
end
|
886
|
+
end
|
887
|
+
start = epochtime
|
888
|
+
build(@output, sync: sync, from: :'git:revbuild')
|
889
|
+
rescue StandardError => e
|
890
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
891
|
+
else
|
892
|
+
if verbose
|
893
|
+
msg = sub_style('completed', styles: theme[:active])
|
894
|
+
puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
|
895
|
+
end
|
896
|
+
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) }, utc: 'build')
|
897
|
+
end
|
898
|
+
|
718
899
|
def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
|
719
|
-
cmd = git_session
|
900
|
+
cmd, opts = git_session('reset', opts: opts)
|
720
901
|
case flag
|
721
902
|
when :commit, :index
|
722
903
|
out = option_sanitize(opts, OPT_GIT[:reset] + VAL_GIT[:reset], no: OPT_GIT[:no][:reset]).first
|
@@ -741,21 +922,19 @@ module Squared
|
|
741
922
|
return
|
742
923
|
end
|
743
924
|
unless ref == false
|
744
|
-
append_commit
|
925
|
+
append_commit(ref, head: true)
|
745
926
|
append_pathspec refs if refs
|
746
927
|
end
|
747
928
|
source
|
748
929
|
end
|
749
930
|
|
750
931
|
def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil)
|
751
|
-
cmd = git_session
|
932
|
+
cmd, opts = git_session('checkout', opts: opts)
|
752
933
|
append_option 'force', 'merge'
|
753
934
|
case flag
|
754
935
|
when :branch
|
755
936
|
cmd << '--detach' if detach == 'd' || option('detach')
|
756
|
-
|
757
|
-
cmd << shell_option('track', val)
|
758
|
-
end
|
937
|
+
append_option('track', equals: true)
|
759
938
|
cmd << if create
|
760
939
|
shell_option(create, branch)
|
761
940
|
else
|
@@ -787,7 +966,7 @@ module Squared
|
|
787
966
|
end
|
788
967
|
|
789
968
|
def tag(flag, opts = [], refs: [], message: nil, commit: nil)
|
790
|
-
cmd = git_session
|
969
|
+
cmd, opts = git_session('tag', opts: opts)
|
791
970
|
case flag
|
792
971
|
when :add
|
793
972
|
if option('sign')
|
@@ -795,8 +974,8 @@ module Squared
|
|
795
974
|
elsif !session_arg?('s', 'sign', 'u', 'local-user')
|
796
975
|
cmd << '--annotate'
|
797
976
|
end
|
798
|
-
if !commit && message && (
|
799
|
-
commit =
|
977
|
+
if !commit && message && (sha = commithash(message))
|
978
|
+
commit = sha
|
800
979
|
else
|
801
980
|
append_message message
|
802
981
|
end
|
@@ -819,41 +998,27 @@ module Squared
|
|
819
998
|
source
|
820
999
|
end
|
821
1000
|
|
822
|
-
def logx(flag, opts = [], range: [])
|
823
|
-
cmd = git_session
|
824
|
-
|
1001
|
+
def logx(flag, opts = [], range: [], index: [])
|
1002
|
+
cmd, opts = git_session('log', opts: opts)
|
1003
|
+
refs = option_sanitize(opts, collect_hash(OPT_GIT[:log]), no: collect_hash(OPT_GIT[:no][:log])).first
|
825
1004
|
case flag
|
826
1005
|
when :between, :contain
|
827
1006
|
cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
|
828
1007
|
else
|
829
|
-
|
830
|
-
val.start_with?('^') || (!%r{^[.\\/]}.match?(val) && !%r{[\\/]$}.match?(val)) || commithash(val)
|
831
|
-
end
|
832
|
-
cmd.merge(commit.map { |val| commithash(val) || shell_quote(val) }) unless commit.empty?
|
1008
|
+
cmd.merge(index)
|
833
1009
|
end
|
834
1010
|
append_nocolor
|
835
|
-
append_pathspec
|
1011
|
+
append_pathspec refs
|
836
1012
|
source(exception: false)
|
837
1013
|
end
|
838
1014
|
|
839
|
-
def diff(flag, opts = [], refs: [], branch: nil, range: [])
|
840
|
-
cmd = git_session
|
1015
|
+
def diff(flag, opts = [], refs: [], branch: nil, range: [], index: [])
|
1016
|
+
cmd, opts = git_session('diff', opts: opts)
|
841
1017
|
files = option_sanitize(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff],
|
842
1018
|
no: OPT_GIT[:no][:log][:diff]).first
|
843
1019
|
case flag
|
844
1020
|
when :files, :view, :between, :contain
|
845
1021
|
cmd.delete('--cached')
|
846
|
-
else
|
847
|
-
items = files.dup
|
848
|
-
sha = nil
|
849
|
-
files.clear
|
850
|
-
items.each do |val|
|
851
|
-
if (s = commithash(val))
|
852
|
-
(sha ||= []).push(s)
|
853
|
-
else
|
854
|
-
files << val
|
855
|
-
end
|
856
|
-
end
|
857
1022
|
end
|
858
1023
|
append_nocolor
|
859
1024
|
if flag == :files
|
@@ -868,15 +1033,14 @@ module Squared
|
|
868
1033
|
cmd.delete('--merge-base')
|
869
1034
|
cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
|
870
1035
|
else
|
871
|
-
cmd << '--cached' if flag == :cached
|
872
1036
|
cmd << '--merge-base' if option('merge-base')
|
873
1037
|
cmd << shell_quote(branch) if branch
|
874
|
-
if
|
1038
|
+
if !index.empty?
|
875
1039
|
if session_arg?('cached')
|
876
|
-
raise_error(
|
877
|
-
cmd <<
|
1040
|
+
raise_error("one commit only: #{index.join(', ')}", hint: '--cached') if index.size > 1
|
1041
|
+
cmd << index.first
|
878
1042
|
else
|
879
|
-
cmd.merge(
|
1043
|
+
cmd.merge(index)
|
880
1044
|
end
|
881
1045
|
elsif (n = option('index'))
|
882
1046
|
cmd << "HEAD~#{n}"
|
@@ -893,12 +1057,12 @@ module Squared
|
|
893
1057
|
if !message && !amend
|
894
1058
|
return if pass
|
895
1059
|
|
896
|
-
raise_error('
|
1060
|
+
raise_error('missing message', hint: 'GIT_MESSAGE="description"')
|
897
1061
|
end
|
898
1062
|
pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
|
899
1063
|
'--all'
|
900
1064
|
elsif (refs = projectmap(refs)).empty?
|
901
|
-
raise_error
|
1065
|
+
raise_error 'no qualified pathspec'
|
902
1066
|
else
|
903
1067
|
"-- #{refs.join(' ')}"
|
904
1068
|
end
|
@@ -907,13 +1071,15 @@ module Squared
|
|
907
1071
|
upstream = nil
|
908
1072
|
source(git_output('fetch --no-tags --quiet'), io: true, banner: false)
|
909
1073
|
source(git_output('branch -vv --list'), io: true, banner: false).first.each do |val|
|
910
|
-
next unless (
|
1074
|
+
next unless (r = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
|
911
1075
|
|
912
|
-
branch =
|
913
|
-
if
|
1076
|
+
branch = r[1]
|
1077
|
+
if r[3]
|
1078
|
+
origin = r[3][%r{^(.+)/#{Regexp.escape(branch)}$}, 1]
|
1079
|
+
else
|
914
1080
|
unless (origin = option('repository', prefix: 'git', ignore: false))
|
915
|
-
out = source(git_output('log -n1 --format=%h%d'), io: true,
|
916
|
-
if out =~ /^#{
|
1081
|
+
out = source(git_output('log -n1 --format=%h%d'), io: true, banner: false, stdout: true).first
|
1082
|
+
if out =~ /^#{r[2]} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/
|
917
1083
|
split_escape($1).each do |val|
|
918
1084
|
next unless val.end_with?("/#{branch}")
|
919
1085
|
|
@@ -923,12 +1089,10 @@ module Squared
|
|
923
1089
|
end
|
924
1090
|
end
|
925
1091
|
upstream = true if origin
|
926
|
-
elsif data[3] =~ %r{^(.+)/#{Regexp.escape(branch)}$}
|
927
|
-
origin = $1
|
928
1092
|
end
|
929
1093
|
break
|
930
1094
|
end
|
931
|
-
raise_error
|
1095
|
+
raise_error 'work tree is not usable' unless origin && branch
|
932
1096
|
cmd = git_session('commit', option('dry-run') && '--dry-run', options: false)
|
933
1097
|
if amend
|
934
1098
|
cmd << '--amend'
|
@@ -955,8 +1119,24 @@ module Squared
|
|
955
1119
|
source b
|
956
1120
|
end
|
957
1121
|
|
958
|
-
def
|
959
|
-
cmd = git_session
|
1122
|
+
def merge(flag, opts = [], command: nil)
|
1123
|
+
cmd, opts = git_session('merge', opts: opts)
|
1124
|
+
case flag
|
1125
|
+
when :commit, :'no-commit'
|
1126
|
+
refs = option_sanitize(opts, OPT_GIT[:merge], no: OPT_GIT[:no][:merge]).first
|
1127
|
+
raise_error 'no branch/commit' if refs.empty?
|
1128
|
+
cmd << "--#{flag}" << '--'
|
1129
|
+
append_commit(*refs)
|
1130
|
+
else
|
1131
|
+
return unless VAL_GIT[:merge][:send].include?(command)
|
1132
|
+
|
1133
|
+
cmd << "--#{command}"
|
1134
|
+
end
|
1135
|
+
source
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil)
|
1139
|
+
cmd, opts = git_session('branch', opts: opts)
|
960
1140
|
stdout = false
|
961
1141
|
case flag
|
962
1142
|
when :create
|
@@ -983,7 +1163,7 @@ module Squared
|
|
983
1163
|
end
|
984
1164
|
ref = nil
|
985
1165
|
when :delete
|
986
|
-
force, list = refs.partition { |val| val
|
1166
|
+
force, list = refs.partition { |val| val.match?(/^[\^~]/) }
|
987
1167
|
force.each do |val|
|
988
1168
|
dr = val[0, 3]
|
989
1169
|
d = dr.include?('^') ? '-D' : '-d'
|
@@ -1003,10 +1183,9 @@ module Squared
|
|
1003
1183
|
cmd << '--edit-description'
|
1004
1184
|
when :current
|
1005
1185
|
cmd << '--show-current'
|
1006
|
-
|
1007
|
-
opts = option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first
|
1186
|
+
when :list
|
1008
1187
|
grep = []
|
1009
|
-
opts.each do |opt|
|
1188
|
+
option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first.each do |opt|
|
1010
1189
|
if opt =~ /^(v+)$/
|
1011
1190
|
cmd << "-#{$1}"
|
1012
1191
|
else
|
@@ -1018,42 +1197,59 @@ module Squared
|
|
1018
1197
|
out, banner, from = source(io: true)
|
1019
1198
|
print_item banner
|
1020
1199
|
ret = write_lines(out, sub: [
|
1021
|
-
{ pat: /^(\*\s+)(\S+)(\s*)$/, styles: :green, index: 2 },
|
1022
|
-
{ pat: %r{^(\s*)(remotes/\S+)(.*)$}, styles: :red, index: 2 }
|
1200
|
+
{ pat: /^(\*\s+)(\S+)(\s*)$/, styles: color(:green), index: 2 },
|
1201
|
+
{ pat: %r{^(\s*)(remotes/\S+)(.*)$}, styles: color(:red), index: 2 }
|
1023
1202
|
])
|
1024
1203
|
list_result(ret, 'branches', from: from)
|
1025
1204
|
return
|
1205
|
+
else
|
1206
|
+
head = source(git_output('rev-parse --abbrev-ref HEAD'), io: true, banner: false, stdout: true).first.chomp
|
1207
|
+
if head.empty?
|
1208
|
+
ret = 0
|
1209
|
+
else
|
1210
|
+
out, banner, from = source(cmd << '-vv --no-abbrev --list', io: true)
|
1211
|
+
ret = write_lines(out, grep: /^\*\s+#{Regexp.escape(head)}\s/, banner: banner, first: true) do |line|
|
1212
|
+
next line if stdin?
|
1213
|
+
|
1214
|
+
data = line.sub(/^\*\s+/, '').split(/\s+/)
|
1215
|
+
a = sub_style(data[0], styles: theme[:inline])
|
1216
|
+
b = sub_style(data[1], styles: theme[:extra])
|
1217
|
+
r = /\A(?:\[(.+?)(?=\]\s)\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
|
1218
|
+
[" Branch: #{a + (r[1] ? " (#{r[1]})" : '')}", " Commit: #{b}", "Message: #{r[2]}"].compact.join("\n")
|
1219
|
+
end
|
1220
|
+
on :last, from
|
1221
|
+
end
|
1222
|
+
if ret == 0
|
1223
|
+
warn log_message(Logger::WARN, name, 'no ref found', subject: 'branch', hint: 'head', pass: true)
|
1224
|
+
end
|
1225
|
+
return
|
1026
1226
|
end
|
1027
1227
|
cmd << shell_escape(target) if target
|
1028
1228
|
cmd << shell_escape(ref) if ref
|
1029
1229
|
source(stdout: stdout)
|
1030
1230
|
end
|
1031
1231
|
|
1032
|
-
def
|
1033
|
-
cmd = git_session
|
1034
|
-
|
1035
|
-
|
1036
|
-
cmd << '--
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1232
|
+
def show(flag, opts = [], format: nil, files: [])
|
1233
|
+
cmd, opts = git_session('show', opts: opts)
|
1234
|
+
case flag
|
1235
|
+
when :textconv
|
1236
|
+
cmd << '--textconv'
|
1237
|
+
files = files.map { |val| Dir[val] }
|
1238
|
+
.flatten
|
1239
|
+
.select { |val| projectpath?(val) }
|
1240
|
+
.map { |val| shell_quote("HEAD:#{val}") }
|
1241
|
+
append_value files
|
1242
|
+
source(banner: false)
|
1243
|
+
return
|
1244
|
+
when :oneline
|
1245
|
+
format = flag.to_s
|
1045
1246
|
end
|
1046
|
-
source(sync: false, stderr: true)
|
1047
|
-
end
|
1048
|
-
|
1049
|
-
def show(format, opts = [])
|
1050
|
-
cmd = git_session 'show'
|
1051
1247
|
if format
|
1052
1248
|
case (val = format.downcase)
|
1053
1249
|
when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
|
1054
1250
|
cmd << basic_option('format', val)
|
1055
1251
|
else
|
1056
|
-
if format
|
1252
|
+
if format.match?(/^t?format:/) || format.include?('%')
|
1057
1253
|
cmd << quote_option('pretty', format)
|
1058
1254
|
else
|
1059
1255
|
opts << format
|
@@ -1071,18 +1267,19 @@ module Squared
|
|
1071
1267
|
end
|
1072
1268
|
|
1073
1269
|
def rev_parse(flag, opts = [], ref: nil, size: nil)
|
1074
|
-
cmd = git_session
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1270
|
+
cmd, opts = git_session('rev-parse', opts: opts)
|
1271
|
+
cmd << if flag == :parseopt
|
1272
|
+
'--parseopt'
|
1273
|
+
elsif opts.delete('sq-quote')
|
1274
|
+
'--sq-quote'
|
1275
|
+
end
|
1079
1276
|
case flag
|
1080
1277
|
when :commit
|
1081
1278
|
cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
|
1082
|
-
append_commit
|
1279
|
+
append_commit(ref, head: true)
|
1083
1280
|
when :branch
|
1084
1281
|
cmd << '--abbrev-ref'
|
1085
|
-
append_commit
|
1282
|
+
append_commit(ref, head: true)
|
1086
1283
|
else
|
1087
1284
|
args = option_sanitize(opts, OPT_GIT[:rev_parse][flag]).first
|
1088
1285
|
append_value(args, escape: session_arg?('sq-quote'))
|
@@ -1091,7 +1288,7 @@ module Squared
|
|
1091
1288
|
end
|
1092
1289
|
|
1093
1290
|
def ls_remote(flag, opts = [], remote: nil)
|
1094
|
-
cmd = git_session
|
1291
|
+
cmd, opts = git_session('ls-remote', '--refs', opts: opts)
|
1095
1292
|
cmd << "--#{flag}" unless flag == :remote
|
1096
1293
|
grep = option_sanitize(opts, OPT_GIT[:ls_remote]).first
|
1097
1294
|
cmd << shell_quote(remote) if remote
|
@@ -1102,7 +1299,7 @@ module Squared
|
|
1102
1299
|
end
|
1103
1300
|
|
1104
1301
|
def ls_files(flag, opts = [])
|
1105
|
-
git_session
|
1302
|
+
opts = git_session('ls-files', "--#{flag}", opts: opts).last
|
1106
1303
|
grep = option_sanitize(opts, OPT_GIT[:ls_files]).first
|
1107
1304
|
out, banner, from = source(io: true)
|
1108
1305
|
print_item banner
|
@@ -1110,10 +1307,51 @@ module Squared
|
|
1110
1307
|
list_result(ret, 'files', from: from, grep: grep)
|
1111
1308
|
end
|
1112
1309
|
|
1310
|
+
def git(flag, opts = [])
|
1311
|
+
cmd, opts = git_session(flag, opts: opts)
|
1312
|
+
refs = option_sanitize(opts, OPT_GIT[flag], no: OPT_GIT[:no][flag]).first
|
1313
|
+
refs = projectmap(refs) unless flag == :revert
|
1314
|
+
sync = false
|
1315
|
+
stderr = true
|
1316
|
+
case flag
|
1317
|
+
when :clean
|
1318
|
+
unless refs.empty?
|
1319
|
+
cmd << '--'
|
1320
|
+
cmd.merge(refs)
|
1321
|
+
end
|
1322
|
+
sync = true
|
1323
|
+
stderr = false
|
1324
|
+
when :restore
|
1325
|
+
if session_arg?('p', 'patch')
|
1326
|
+
option_clear refs
|
1327
|
+
else
|
1328
|
+
append_pathspec(refs, expect: true)
|
1329
|
+
end
|
1330
|
+
when :revert
|
1331
|
+
if VAL_GIT[:rebase][:send].any? { |val| session_arg?(val) }
|
1332
|
+
option_clear refs
|
1333
|
+
elsif refs.empty?
|
1334
|
+
raise_error 'no commit given'
|
1335
|
+
else
|
1336
|
+
append_commit(*refs)
|
1337
|
+
end
|
1338
|
+
when :mv
|
1339
|
+
raise_error 'no source/destination' unless refs.size > 1
|
1340
|
+
cmd.merge(refs)
|
1341
|
+
when :rm
|
1342
|
+
append_pathspec(refs, expect: true)
|
1343
|
+
end
|
1344
|
+
source(sync: sync, stderr: stderr)
|
1345
|
+
end
|
1346
|
+
|
1113
1347
|
def clone?
|
1114
1348
|
ref?(workspace.baseref) && workspace.git_clone?(path, name) ? 1 : false
|
1115
1349
|
end
|
1116
1350
|
|
1351
|
+
def revbuild?
|
1352
|
+
build? && !!workspace.revfile
|
1353
|
+
end
|
1354
|
+
|
1117
1355
|
def enabled?(*, **kwargs)
|
1118
1356
|
super || (kwargs[:base] == false && !!clone?)
|
1119
1357
|
end
|
@@ -1126,7 +1364,7 @@ module Squared
|
|
1126
1364
|
if cmd.respond_to?(:done)
|
1127
1365
|
if io && banner == false
|
1128
1366
|
from = nil
|
1129
|
-
elsif !from && (from = cmd.drop(1).find { |val| val
|
1367
|
+
elsif !from && (from = cmd.drop(1).find { |val| val.match?(/^[a-z][a-z\-]{2,}$/) })
|
1130
1368
|
from = :"git:#{from}"
|
1131
1369
|
end
|
1132
1370
|
banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
|
@@ -1172,13 +1410,13 @@ module Squared
|
|
1172
1410
|
ret = on(:error, from, e)
|
1173
1411
|
raise if exception && ret != true
|
1174
1412
|
|
1175
|
-
warn log_message(Logger::WARN, e) if warning?
|
1413
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1176
1414
|
else
|
1177
1415
|
on :last, from
|
1178
1416
|
end
|
1179
1417
|
end
|
1180
1418
|
|
1181
|
-
def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false)
|
1419
|
+
def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false, first: false)
|
1182
1420
|
grep = as_a(grep).map do |val|
|
1183
1421
|
next val if val.is_a?(Regexp)
|
1184
1422
|
|
@@ -1191,6 +1429,7 @@ module Squared
|
|
1191
1429
|
data.each do |line|
|
1192
1430
|
next if grep&.none? { |pat| pat.match?(line) }
|
1193
1431
|
|
1432
|
+
line = yield line if block_given?
|
1194
1433
|
if loglevel
|
1195
1434
|
log&.add loglevel, line
|
1196
1435
|
else
|
@@ -1202,8 +1441,9 @@ module Squared
|
|
1202
1441
|
end
|
1203
1442
|
end
|
1204
1443
|
ret += 1
|
1444
|
+
break if first
|
1205
1445
|
end
|
1206
|
-
print_item banner, out if banner && (ret > 0 || !pass)
|
1446
|
+
print_item banner, out if banner && (ret > 0 || (!pass && !first))
|
1207
1447
|
ret
|
1208
1448
|
end
|
1209
1449
|
|
@@ -1226,6 +1466,21 @@ module Squared
|
|
1226
1466
|
on :last, from
|
1227
1467
|
end
|
1228
1468
|
|
1469
|
+
def status_digest(*args, algorithm: Digest::SHA256, **kwargs)
|
1470
|
+
glob = kwargs.fetch(:include, [])
|
1471
|
+
pass = kwargs.fetch(:exclude, [])
|
1472
|
+
ret = {}
|
1473
|
+
out = source(git_output('status -s --porcelain', *args), io: true, banner: false).first
|
1474
|
+
out.each do |line|
|
1475
|
+
next unless (file = line[/^[A-Z ?!]{3}"?(.+?)"?$/, 1])
|
1476
|
+
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1477
|
+
next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1478
|
+
|
1479
|
+
ret[file] = algorithm.hexdigest(File.read(basepath(file)))
|
1480
|
+
end
|
1481
|
+
ret
|
1482
|
+
end
|
1483
|
+
|
1229
1484
|
def append_pull(opts, list, target: @session, no: nil, flag: nil, remote: nil)
|
1230
1485
|
cmd << '--force' if option('force')
|
1231
1486
|
rsm = append_submodules(target: target)
|
@@ -1265,9 +1520,13 @@ module Squared
|
|
1265
1520
|
option_clear(out, target: target, subject: flag.to_s) if flag
|
1266
1521
|
end
|
1267
1522
|
|
1268
|
-
def append_commit(val, target: @session)
|
1269
|
-
val
|
1270
|
-
|
1523
|
+
def append_commit(*val, target: @session, head: false)
|
1524
|
+
val.compact!
|
1525
|
+
if !val.empty?
|
1526
|
+
val.each { |ref| target << (commithash(ref) || shell_quote(ref)) }
|
1527
|
+
elsif head
|
1528
|
+
target << (append_head(target: target) || 'HEAD')
|
1529
|
+
end
|
1271
1530
|
end
|
1272
1531
|
|
1273
1532
|
def append_pathspec(files = [], target: @session, expect: false, parent: false)
|
@@ -1279,9 +1538,9 @@ module Squared
|
|
1279
1538
|
end
|
1280
1539
|
files = projectmap(files, parent: parent)
|
1281
1540
|
if !files.empty?
|
1282
|
-
target <<
|
1541
|
+
target << '--' << files.join(' ')
|
1283
1542
|
elsif expect
|
1284
|
-
raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree'
|
1543
|
+
raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree')
|
1285
1544
|
end
|
1286
1545
|
end
|
1287
1546
|
end
|
@@ -1316,9 +1575,13 @@ module Squared
|
|
1316
1575
|
end
|
1317
1576
|
end
|
1318
1577
|
|
1319
|
-
def git_session(*cmd, worktree: true, **kwargs)
|
1578
|
+
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
1320
1579
|
dir = worktree ? ["--work-tree=#{shell_quote(path)}", "--git-dir=#{shell_quote(gitpath)}"] : []
|
1321
|
-
session('git', *dir,
|
1580
|
+
ret = session('git', *dir, **kwargs)
|
1581
|
+
return ret.merge(cmd) unless opts
|
1582
|
+
|
1583
|
+
opts = option_sanitize(opts, OPT_GIT[:common]).first
|
1584
|
+
[ret.merge(cmd), opts]
|
1322
1585
|
end
|
1323
1586
|
|
1324
1587
|
def git_output(*cmd, **kwargs)
|
@@ -1336,11 +1599,11 @@ module Squared
|
|
1336
1599
|
end
|
1337
1600
|
|
1338
1601
|
def gitpath
|
1339
|
-
basepath
|
1602
|
+
basepath '.git'
|
1340
1603
|
end
|
1341
1604
|
|
1342
1605
|
def commithash(val)
|
1343
|
-
val
|
1606
|
+
val[/^#\{(\h{5,40})\}$/, 1]
|
1344
1607
|
end
|
1345
1608
|
|
1346
1609
|
def threadargs
|