squared 0.3.6 → 0.4.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 +46 -8
- data/README.md +13 -2
- data/README.ruby.md +168 -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 +24 -12
- data/lib/squared/common/prompt.rb +2 -2
- data/lib/squared/common/shell.rb +52 -39
- data/lib/squared/common/utils.rb +54 -1
- 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 +431 -131
- data/lib/squared/workspace/project/docker.rb +572 -0
- data/lib/squared/workspace/project/git.rb +408 -169
- data/lib/squared/workspace/project/node.rb +50 -50
- data/lib/squared/workspace/project/python.rb +115 -24
- data/lib/squared/workspace/project/ruby.rb +35 -36
- 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,25 +85,76 @@ 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
|
|
73
146
|
module Project
|
74
147
|
class Git < Base
|
75
|
-
include Prompt
|
76
|
-
|
77
148
|
OPT_GIT = {
|
149
|
+
common: %w[bare p|paginate P|no-pager glob-pathspecs icase-pathspecs literal-pathspecs no-optional-locks
|
150
|
+
no-replace-objects noglob-pathspecs c=q config-env=q exec-path=p namespace=p].freeze,
|
78
151
|
branch: %w[a|all create-reflog i|ignore-case q|quiet r|remotes v|verbose abbrev=i color=b column=b
|
79
|
-
contains=
|
152
|
+
contains=b format=q merged=b no-contains=b no-merged=b points-at=e u|set-upstream-to=e sort=q
|
80
153
|
t|track=b].freeze,
|
81
154
|
checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
|
82
155
|
pathspec-file-nul q quiet orphan=e ours theirs conflict=b pathspec-from-file=p
|
83
156
|
t|track=b].freeze,
|
157
|
+
clean: %w[d x X f|force i|interactive n|dry-run q|quiet e|exlcude=q].freeze,
|
84
158
|
diff: {
|
85
159
|
base: %w[0 1|base 2|ours 3|theirs].freeze,
|
86
160
|
show: %w[s exit-code histogram].freeze
|
@@ -90,7 +164,7 @@ module Squared
|
|
90
164
|
recurse-submodules-default=b].freeze,
|
91
165
|
pull: %w[4 6 n t a|append atomic dry-run f|force k|keep n|negotiate-only prefetch p|prune q|quiet
|
92
166
|
set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
|
93
|
-
refmap=q o|server-option=
|
167
|
+
refmap=q o|server-option=q shallow-exclude=e shallow-since=b upload-pack=q].freeze
|
94
168
|
}.freeze,
|
95
169
|
log: {
|
96
170
|
base: %w[all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
|
@@ -98,7 +172,7 @@ module Squared
|
|
98
172
|
first-parent F|fixed-strings follow full-diff full-history ignore-missing invert-grep left-only
|
99
173
|
merge log-size no-max-parents no-min-parents not P|perl-regexp reflog i|regexp-ignore-case
|
100
174
|
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=
|
175
|
+
source sparse stdin topo-order g|walk-reflogs after=q ancestry-path=b? author=q before=q
|
102
176
|
branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
|
103
177
|
exclude-hidden=b? glob=q grep=q grep-reflog=q L=q n|max-count=i max-parents=i min-parents=i
|
104
178
|
no-walk=b? remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
|
@@ -109,9 +183,9 @@ module Squared
|
|
109
183
|
W|function-context w|ignore-all-space ignore-blank-lines ignore-cr-at-eol ignore-space-at-eol
|
110
184
|
b|ignore-space-change D|irreversible-delete graph ita-invisible-in-index minimal name-only
|
111
185
|
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=
|
186
|
+
pickaxe-all pickaxe-regex raw shortstat summary a|text abbrev=i? anchored=q B|break-rewrites=b?
|
113
187
|
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=
|
188
|
+
dirstat-by-file=q? dst-prefix=q C|find-copies=i? find-object=b M|find-renames=i?
|
115
189
|
I|ignore-matching-lines=q ignore-submodules=b inter-hunk-context=i line-prefix=q output=p
|
116
190
|
output-indicator-context=q output-indicator-new=q output-indicator-old=q relative=p rotate-to=p
|
117
191
|
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 +194,32 @@ module Squared
|
|
120
194
|
ls_files: %w[z debug deduplicate directory eol error-unmatch exclude-standard full-name k|killed
|
121
195
|
no-empty-directory recurse-submodules sparse s|stage u|unmerged abbrev=i x|exclude=q
|
122
196
|
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
|
-
|
197
|
+
ls_remote: %w[exit-code get-url q|quiet o|server-option=q symref sort=q upload-pack=q].freeze,
|
198
|
+
mv: %w[k f|force n|dry-run v|verbose].freeze,
|
199
|
+
pull: %w[e n allow-unrelated-histories ff-only S|gpg-sign=qq log=i r|rebase=b? s|strategy=b
|
200
|
+
X|strategy-option=b].freeze,
|
201
|
+
merge: %w[e n allow-unrelated-histories ff-only m=q q|quiet v|verbose cleanup=b F|file=p S|gpg-sign=qq
|
202
|
+
into-name=e log=i s|strategy=b X|strategy-option=b].freeze,
|
126
203
|
rebase: %w[n C=i allow-empty-message apply committer-date-is-author-date edit-todo f|force-rebase ignore-date
|
127
204
|
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=
|
205
|
+
reset-author-date root show-current-patch signoff v|verbose empty=b S|gpg-sign=qq onto=e
|
206
|
+
s|strategy=b X|strategy-option=b whitespace=b].freeze,
|
130
207
|
reset: %w[N pathspec-file-nul q|quiet pathspec-from-file=p].freeze,
|
131
208
|
restore: %w[ignore-unmerged ignore-skip-worktree-bits m|merge ours p|patch pathspec-file-nul S|staged theirs
|
132
209
|
W|worktree conflict=b pathspec-from-file=p s|source=q].freeze,
|
210
|
+
revert: %w[e abort continue no-commit quit reference skip cleanup=b S|gpg-sign=qq m|mainline=i s|signoff
|
211
|
+
strategy=b X|strategy-option=b].freeze,
|
133
212
|
rev_parse: {
|
134
213
|
output: %w[absolute-git-dir all flags git-common-dir git-dir is-bare-repository is-inside-git-dir
|
135
214
|
is-inside-work-tree is-shallow-repository local-env-vars no-flags no-revs not q|quiet sq
|
136
215
|
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=
|
216
|
+
sq-quote symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q default=q
|
138
217
|
disambiguate=b exclude=q exclude-hidden=b glob=q git-path=p path-format=b? prefix=q branches=q?
|
139
218
|
remotes=q? resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
|
140
219
|
parseopt: %w[keep-dashdash stop-at-non-option stuck-long].freeze
|
141
220
|
}.freeze,
|
221
|
+
rm: %w[r cached f|force n|dry-run ignore-unmatch pathspec-file-nul q|quiet sparse v|verbose
|
222
|
+
pathspec-from-file=p].freeze,
|
142
223
|
show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
|
143
224
|
expand-tabs=i notes=q show-notes=q?].freeze,
|
144
225
|
stash: {
|
@@ -148,7 +229,8 @@ module Squared
|
|
148
229
|
pop: %w[index].freeze,
|
149
230
|
apply: %w[index].freeze
|
150
231
|
}.freeze,
|
151
|
-
|
232
|
+
status: %w[untracked-files=b? u|ignore-submodules=m? ignored=b?],
|
233
|
+
tag: %w[create-reflog column=b contains=b? format=q merged=b? n=i no-contains=b? no-merged=b? points-at=q
|
152
234
|
sort=q].freeze,
|
153
235
|
no: {
|
154
236
|
fetch: {
|
@@ -164,20 +246,26 @@ module Squared
|
|
164
246
|
tag: %w[column].freeze,
|
165
247
|
branch: %w[color-moved column color track].freeze,
|
166
248
|
checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
|
249
|
+
merge: %w[autostash edit ff gpg-sign log progress overwrite-ignore rerere-autoupdate signoff squash stat
|
250
|
+
verify verify-signatures].freeze,
|
167
251
|
rebase: %w[autosquash autostash fork-point gpg-sign keep-empty reapply-cherry-picks reschedule-failed-exec
|
168
252
|
rerere-autoupdate stat update-refs verify].freeze,
|
169
253
|
reset: %w[refresh].freeze,
|
170
254
|
restore: %w[overlay progress recurse-submodules].freeze,
|
255
|
+
revert: %w[edit gpg-sign rerere-autoupdate].freeze,
|
171
256
|
show: %w[standard-notes].freeze
|
172
257
|
}.freeze
|
173
|
-
}
|
258
|
+
}.freeze
|
174
259
|
VAL_GIT = {
|
260
|
+
merge: {
|
261
|
+
send: %w[continue abort quit].freeze
|
262
|
+
}.freeze,
|
175
263
|
rebase: {
|
176
264
|
send: %w[continue skip abort quit].freeze,
|
177
265
|
value: %w[true false merges interactive].freeze
|
178
266
|
}.freeze,
|
179
267
|
reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze
|
180
|
-
}
|
268
|
+
}.freeze
|
181
269
|
private_constant :OPT_GIT, :VAL_GIT
|
182
270
|
|
183
271
|
class << self
|
@@ -209,7 +297,7 @@ module Squared
|
|
209
297
|
end
|
210
298
|
|
211
299
|
def tasks
|
212
|
-
%i[pull rebase fetch clone stash status].freeze
|
300
|
+
%i[pull rebase fetch clone stash status branch revbuild].freeze
|
213
301
|
end
|
214
302
|
|
215
303
|
def batchargs
|
@@ -227,24 +315,25 @@ module Squared
|
|
227
315
|
'branch' => %i[create set delete move copy list edit current].freeze,
|
228
316
|
'checkout' => %i[commit branch track detach path].freeze,
|
229
317
|
'commit' => %i[add all amend amend-orig].freeze,
|
230
|
-
'diff' => %i[head
|
318
|
+
'diff' => %i[head branch files view between contain].freeze,
|
231
319
|
'fetch' => %i[origin remote].freeze,
|
232
320
|
'files' => %i[cached modified deleted others ignored].freeze,
|
321
|
+
'git' => %i[clean mv restore revert rm].freeze,
|
233
322
|
'log' => %i[view between contain].freeze,
|
323
|
+
'merge' => %i[commit no-commit send].freeze,
|
234
324
|
'pull' => %i[origin remote].freeze,
|
235
325
|
'rebase' => %i[branch onto send].freeze,
|
236
326
|
'refs' => %i[heads tags remote].freeze,
|
237
327
|
'reset' => %i[commit index patch mode].freeze,
|
238
|
-
'
|
239
|
-
'rev' => %i[commit branch output parseopt].freeze,
|
328
|
+
'rev' => %i[commit branch output parseopt build].freeze,
|
240
329
|
'show' => %i[format oneline].freeze,
|
241
|
-
'stash' => %i[push pop apply drop
|
330
|
+
'stash' => %i[push pop apply drop list].freeze,
|
242
331
|
'tag' => %i[add delete list].freeze
|
243
332
|
}.freeze
|
244
333
|
|
245
334
|
def initialize(*, **)
|
246
335
|
super
|
247
|
-
initialize_ref
|
336
|
+
initialize_ref Git.ref if gitpath.exist?
|
248
337
|
end
|
249
338
|
|
250
339
|
def ref
|
@@ -289,19 +378,6 @@ module Squared
|
|
289
378
|
commit(flag, refs: refs)
|
290
379
|
end
|
291
380
|
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
381
|
when 'tag'
|
306
382
|
case flag
|
307
383
|
when :list
|
@@ -335,9 +411,19 @@ module Squared
|
|
335
411
|
case flag
|
336
412
|
when :view, :between, :contain
|
337
413
|
if flag == :view && action == 'log'
|
338
|
-
format_desc action, flag, '(^)commit*,pathspec*,opts*'
|
414
|
+
format_desc action, flag, '(^)commit/H0*,pathspec*,opts*'
|
339
415
|
task flag do |_, args|
|
340
|
-
|
416
|
+
index = []
|
417
|
+
args.to_a.each do |val|
|
418
|
+
if val =~ /^H(\d+)$/
|
419
|
+
index << "HEAD~#{$1}"
|
420
|
+
elsif (sha = commithash(val))
|
421
|
+
index << sha
|
422
|
+
elsif val.start_with?('^') || (!%r{^[.\\/]}.match?(val) && !%r{[\\/]$}.match?(val))
|
423
|
+
index << shell_quote(val)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
logx(flag, args.to_a.drop(index.size), index: index)
|
341
427
|
end
|
342
428
|
else
|
343
429
|
format_desc action, flag, 'commit1,commit2,pathspec*,opts*'
|
@@ -347,10 +433,16 @@ module Squared
|
|
347
433
|
__send__(action == 'log' ? :logx : :diff, flag, args.extras, range: [commit1, commit2])
|
348
434
|
end
|
349
435
|
end
|
350
|
-
when :head
|
351
|
-
format_desc action, flag, 'opts*,pathspec*'
|
436
|
+
when :head
|
437
|
+
format_desc action, flag, 'commit/H0*,opts*,pathspec*'
|
352
438
|
task flag do |_, args|
|
353
|
-
|
439
|
+
index = []
|
440
|
+
args.to_a.each do |val|
|
441
|
+
break unless val =~ /^H(\d+)$/ || (sha = commithash(val))
|
442
|
+
|
443
|
+
index << ($1 ? "HEAD~#{$1}" : sha)
|
444
|
+
end
|
445
|
+
diff(flag, args.to_a.drop(index.size), index: index)
|
354
446
|
end
|
355
447
|
when :branch
|
356
448
|
format_desc action, flag, 'name,opts*,pathspec*'
|
@@ -495,7 +587,7 @@ module Squared
|
|
495
587
|
show args.format, args.extras
|
496
588
|
end
|
497
589
|
end
|
498
|
-
when 'rebase'
|
590
|
+
when 'rebase', 'merge'
|
499
591
|
case flag
|
500
592
|
when :branch
|
501
593
|
format_desc action, flag, 'opts*,upstream?,branch?'
|
@@ -510,11 +602,18 @@ module Squared
|
|
510
602
|
upstream = param_guard(action, flag, args: args, key: :upstream)
|
511
603
|
rebase(flag, commit: commit, upstream: upstream, branch: args.branch)
|
512
604
|
end
|
605
|
+
when :commit, :'no-commit'
|
606
|
+
format_desc action, flag, 'branch/commit+,opts*'
|
607
|
+
task flag do |_, args|
|
608
|
+
args = param_guard(action, flag, args: args.to_a)
|
609
|
+
merge flag, args
|
610
|
+
end
|
513
611
|
when :send
|
514
|
-
format_desc(action, flag, VAL_GIT[
|
612
|
+
format_desc(action, flag, VAL_GIT[action.to_sym][:send], arg: nil)
|
515
613
|
task flag, [:command] do |_, args|
|
516
|
-
command = param_guard(action, flag, args: args, key: :command
|
517
|
-
|
614
|
+
command = param_guard(action, flag, args: args, key: :command,
|
615
|
+
values: VAL_GIT[action.to_sym][:send])
|
616
|
+
__send__(action, flag, command: command)
|
518
617
|
end
|
519
618
|
end
|
520
619
|
when 'rev'
|
@@ -535,6 +634,11 @@ module Squared
|
|
535
634
|
task flag, [:ref] do |_, args|
|
536
635
|
rev_parse(flag, ref: args.ref)
|
537
636
|
end
|
637
|
+
when :build
|
638
|
+
format_desc action, flag, OPT_GIT[:status]
|
639
|
+
task flag do |_, args|
|
640
|
+
revbuild flag, args.to_a
|
641
|
+
end
|
538
642
|
else
|
539
643
|
format_desc action, flag, 'opts*,args*'
|
540
644
|
task flag do |_, args|
|
@@ -554,6 +658,18 @@ module Squared
|
|
554
658
|
__send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
|
555
659
|
end
|
556
660
|
end
|
661
|
+
when 'git'
|
662
|
+
format_desc(action, flag, 'opts*', before: case flag
|
663
|
+
when :rm
|
664
|
+
'source+,destination'
|
665
|
+
when :revert
|
666
|
+
'commit+'
|
667
|
+
else
|
668
|
+
'pathspec*'
|
669
|
+
end)
|
670
|
+
task flag do |_, args|
|
671
|
+
git(flag, args.to_a)
|
672
|
+
end
|
557
673
|
end
|
558
674
|
end
|
559
675
|
end
|
@@ -566,8 +682,18 @@ module Squared
|
|
566
682
|
super
|
567
683
|
end
|
568
684
|
|
685
|
+
def depend(*, **)
|
686
|
+
workspace.rev_clear name
|
687
|
+
super
|
688
|
+
end
|
689
|
+
|
690
|
+
def clean(*, **)
|
691
|
+
workspace.rev_clear name
|
692
|
+
super
|
693
|
+
end
|
694
|
+
|
569
695
|
def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil)
|
570
|
-
cmd = git_session
|
696
|
+
cmd, opts = git_session('pull', flag && "--#{flag}", opts: opts)
|
571
697
|
if (val = option('rebase', ignore: false))
|
572
698
|
cmd << case val
|
573
699
|
when '0'
|
@@ -580,8 +706,8 @@ module Squared
|
|
580
706
|
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag)
|
581
707
|
source(sync: sync, sub: if verbose
|
582
708
|
[
|
583
|
-
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
|
584
|
-
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: :green, index: 3 }
|
709
|
+
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: color(:red), index: 4 },
|
710
|
+
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: color(:green), index: 3 }
|
585
711
|
]
|
586
712
|
end, **threadargs)
|
587
713
|
end
|
@@ -590,7 +716,7 @@ module Squared
|
|
590
716
|
command: nil)
|
591
717
|
return pull(:rebase, sync: sync) unless flag
|
592
718
|
|
593
|
-
cmd = git_session
|
719
|
+
cmd, opts = git_session('rebase', opts: opts)
|
594
720
|
case flag
|
595
721
|
when :branch
|
596
722
|
branch = option_sanitize(opts, OPT_GIT[:rebase], no: OPT_GIT[:no][:rebase]).first
|
@@ -619,7 +745,7 @@ module Squared
|
|
619
745
|
end
|
620
746
|
|
621
747
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
622
|
-
cmd = git_session
|
748
|
+
cmd, opts = git_session('fetch', opts: opts)
|
623
749
|
cmd << '--all' if !remote && !opts.include?('multiple') && option('all')
|
624
750
|
cmd << '--verbose' if verbose && !opts.include?('quiet')
|
625
751
|
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
|
@@ -651,22 +777,14 @@ module Squared
|
|
651
777
|
|
652
778
|
def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
|
653
779
|
if flag
|
654
|
-
cmd = git_session
|
655
|
-
|
656
|
-
refs = option_sanitize(opts, list).first
|
780
|
+
cmd, opts = git_session('stash', flag, opts: opts)
|
781
|
+
refs = option_sanitize(opts, OPT_GIT[:stash][:common] + OPT_GIT[:stash].fetch(flag, [])).first
|
657
782
|
case flag
|
658
783
|
when :push
|
659
784
|
append_pathspec refs
|
660
785
|
when :pop, :apply, :drop
|
661
|
-
|
662
|
-
|
663
|
-
option_clear refs
|
664
|
-
end
|
665
|
-
when :clear
|
666
|
-
if confirm("Remove #{sub_style('all', styles: theme[:active])} the stash entries? [y/N] ", 'N')
|
667
|
-
source(stdout: true)
|
668
|
-
end
|
669
|
-
return
|
786
|
+
cmd << shell_quote(refs.pop)
|
787
|
+
option_clear refs
|
670
788
|
when :list
|
671
789
|
out, banner, from = source(io: true)
|
672
790
|
print_item banner
|
@@ -675,14 +793,14 @@ module Squared
|
|
675
793
|
return
|
676
794
|
end
|
677
795
|
else
|
678
|
-
git_session
|
796
|
+
git_session('stash', 'push', opts: opts)
|
679
797
|
append_option(%w[all keep-index include-untracked staged].freeze, no: true, ignore: false)
|
680
798
|
append_message option('message', 'm', ignore: false)
|
681
799
|
end
|
682
800
|
source(banner: !quiet?, sync: sync, **threadargs)
|
683
801
|
end
|
684
802
|
|
685
|
-
def status(
|
803
|
+
def status(*)
|
686
804
|
cmd = git_session 'status'
|
687
805
|
cmd << (option('long') ? '--long' : '--short')
|
688
806
|
if (val = option('ignore-submodules', ignore: false))
|
@@ -699,24 +817,76 @@ module Squared
|
|
699
817
|
end
|
700
818
|
append_pathspec
|
701
819
|
out, banner, from = source(io: true)
|
702
|
-
if sync
|
703
|
-
print_item banner
|
704
|
-
banner = nil
|
705
|
-
end
|
706
820
|
ret = write_lines(out, banner: banner, sub: if verbose
|
821
|
+
r = color(:red)
|
822
|
+
g = color(:green)
|
707
823
|
[
|
708
|
-
{ pat: /^(.)([A-Z?!])(.+)$/, styles:
|
709
|
-
{ pat: /^([A-Z?!])(.+)$/, styles:
|
710
|
-
{ pat: /^(\?\?)(.+)$/, styles:
|
824
|
+
{ pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
|
825
|
+
{ pat: /^([A-Z?!])(.+)$/, styles: g },
|
826
|
+
{ pat: /^(\?\?)(.+)$/, styles: r },
|
711
827
|
{ pat: /^(## )(.+)(\.{3})(.+)$/,
|
712
|
-
styles: [nil,
|
828
|
+
styles: [nil, g, nil, r], index: -1 }
|
713
829
|
]
|
714
830
|
end)
|
715
831
|
list_result(ret, 'files', from: from, action: 'modified')
|
716
832
|
end
|
717
833
|
|
834
|
+
def revbuild(flag = nil, opts = [], sync: invoked_sync?('revbuild', flag), **kwargs)
|
835
|
+
statusargs = lambda do
|
836
|
+
{
|
837
|
+
include: relativepath(as_a(kwargs[:include]), all: true),
|
838
|
+
exclude: relativepath(as_a(kwargs[:exclude]), all: true)
|
839
|
+
}
|
840
|
+
end
|
841
|
+
unless workspace.closed
|
842
|
+
if @revbuild
|
843
|
+
statusargs.().each { |key, val| @revbuild[key] += val }
|
844
|
+
else
|
845
|
+
@revbuild = statusargs.()
|
846
|
+
end
|
847
|
+
return
|
848
|
+
end
|
849
|
+
sha = source(git_output('rev-parse --verify HEAD'), io: true, banner: false, stdout: true).first.to_s.chomp
|
850
|
+
return if sha.empty?
|
851
|
+
|
852
|
+
args = []
|
853
|
+
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.() : @revbuild || {}
|
854
|
+
case flag
|
855
|
+
when :build
|
856
|
+
opts = option_sanitize(opts, OPT_GIT[:status], target: args).first
|
857
|
+
option_clear opts
|
858
|
+
else
|
859
|
+
args << basic_option('untracked-files', flag) if (flag = option('untracked-files', prefix: 'git'))
|
860
|
+
args << basic_option('ignore-submodules', flag) if (flag = option('ignore-submodules', prefix: 'git'))
|
861
|
+
args << basic_option('ignored', flag) if (flag = option('ignored', prefix: 'git'))
|
862
|
+
end
|
863
|
+
if (cur = workspace.rev_entry(name)) && cur['revision'] == sha
|
864
|
+
files = status_digest(*args, **kwargs)
|
865
|
+
if cur['files'].size == files.size && cur['files'].find { |key, val| files[key] != val }.nil?
|
866
|
+
if verbose
|
867
|
+
if (since = workspace.rev_timesince(name, 'build'))
|
868
|
+
puts log_message(Logger::INFO, name, 'no changes', subject: 'revbuild', hint: "#{since} ago")
|
869
|
+
else
|
870
|
+
workspace.rev_timeutc(name, 'build')
|
871
|
+
end
|
872
|
+
end
|
873
|
+
return
|
874
|
+
end
|
875
|
+
end
|
876
|
+
start = epochtime
|
877
|
+
build(@output, sync: sync, from: :'git:revbuild')
|
878
|
+
rescue StandardError => e
|
879
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
880
|
+
else
|
881
|
+
if verbose
|
882
|
+
msg = sub_style('completed', styles: theme[:active])
|
883
|
+
puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
|
884
|
+
end
|
885
|
+
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) }, utc: 'build')
|
886
|
+
end
|
887
|
+
|
718
888
|
def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
|
719
|
-
cmd = git_session
|
889
|
+
cmd, opts = git_session('reset', opts: opts)
|
720
890
|
case flag
|
721
891
|
when :commit, :index
|
722
892
|
out = option_sanitize(opts, OPT_GIT[:reset] + VAL_GIT[:reset], no: OPT_GIT[:no][:reset]).first
|
@@ -741,21 +911,19 @@ module Squared
|
|
741
911
|
return
|
742
912
|
end
|
743
913
|
unless ref == false
|
744
|
-
append_commit
|
914
|
+
append_commit(ref, head: true)
|
745
915
|
append_pathspec refs if refs
|
746
916
|
end
|
747
917
|
source
|
748
918
|
end
|
749
919
|
|
750
920
|
def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil)
|
751
|
-
cmd = git_session
|
921
|
+
cmd, opts = git_session('checkout', opts: opts)
|
752
922
|
append_option 'force', 'merge'
|
753
923
|
case flag
|
754
924
|
when :branch
|
755
925
|
cmd << '--detach' if detach == 'd' || option('detach')
|
756
|
-
|
757
|
-
cmd << shell_option('track', val)
|
758
|
-
end
|
926
|
+
append_option('track', equals: true)
|
759
927
|
cmd << if create
|
760
928
|
shell_option(create, branch)
|
761
929
|
else
|
@@ -787,7 +955,7 @@ module Squared
|
|
787
955
|
end
|
788
956
|
|
789
957
|
def tag(flag, opts = [], refs: [], message: nil, commit: nil)
|
790
|
-
cmd = git_session
|
958
|
+
cmd, opts = git_session('tag', opts: opts)
|
791
959
|
case flag
|
792
960
|
when :add
|
793
961
|
if option('sign')
|
@@ -795,8 +963,8 @@ module Squared
|
|
795
963
|
elsif !session_arg?('s', 'sign', 'u', 'local-user')
|
796
964
|
cmd << '--annotate'
|
797
965
|
end
|
798
|
-
if !commit && message && (
|
799
|
-
commit =
|
966
|
+
if !commit && message && (sha = commithash(message))
|
967
|
+
commit = sha
|
800
968
|
else
|
801
969
|
append_message message
|
802
970
|
end
|
@@ -819,41 +987,27 @@ module Squared
|
|
819
987
|
source
|
820
988
|
end
|
821
989
|
|
822
|
-
def logx(flag, opts = [], range: [])
|
823
|
-
cmd = git_session
|
824
|
-
|
990
|
+
def logx(flag, opts = [], range: [], index: [])
|
991
|
+
cmd, opts = git_session('log', opts: opts)
|
992
|
+
refs = option_sanitize(opts, collect_hash(OPT_GIT[:log]), no: collect_hash(OPT_GIT[:no][:log])).first
|
825
993
|
case flag
|
826
994
|
when :between, :contain
|
827
995
|
cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
|
828
996
|
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?
|
997
|
+
cmd.merge(index)
|
833
998
|
end
|
834
999
|
append_nocolor
|
835
|
-
append_pathspec
|
1000
|
+
append_pathspec refs
|
836
1001
|
source(exception: false)
|
837
1002
|
end
|
838
1003
|
|
839
|
-
def diff(flag, opts = [], refs: [], branch: nil, range: [])
|
840
|
-
cmd = git_session
|
1004
|
+
def diff(flag, opts = [], refs: [], branch: nil, range: [], index: [])
|
1005
|
+
cmd, opts = git_session('diff', opts: opts)
|
841
1006
|
files = option_sanitize(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff],
|
842
1007
|
no: OPT_GIT[:no][:log][:diff]).first
|
843
1008
|
case flag
|
844
1009
|
when :files, :view, :between, :contain
|
845
1010
|
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
1011
|
end
|
858
1012
|
append_nocolor
|
859
1013
|
if flag == :files
|
@@ -868,15 +1022,14 @@ module Squared
|
|
868
1022
|
cmd.delete('--merge-base')
|
869
1023
|
cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
|
870
1024
|
else
|
871
|
-
cmd << '--cached' if flag == :cached
|
872
1025
|
cmd << '--merge-base' if option('merge-base')
|
873
1026
|
cmd << shell_quote(branch) if branch
|
874
|
-
if
|
1027
|
+
if !index.empty?
|
875
1028
|
if session_arg?('cached')
|
876
|
-
raise_error(
|
877
|
-
cmd <<
|
1029
|
+
raise_error("one commit only: #{index.join(', ')}", hint: '--cached') if index.size > 1
|
1030
|
+
cmd << index.first
|
878
1031
|
else
|
879
|
-
cmd.merge(
|
1032
|
+
cmd.merge(index)
|
880
1033
|
end
|
881
1034
|
elsif (n = option('index'))
|
882
1035
|
cmd << "HEAD~#{n}"
|
@@ -893,12 +1046,12 @@ module Squared
|
|
893
1046
|
if !message && !amend
|
894
1047
|
return if pass
|
895
1048
|
|
896
|
-
raise_error('
|
1049
|
+
raise_error('missing message', hint: 'GIT_MESSAGE="description"')
|
897
1050
|
end
|
898
1051
|
pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
|
899
1052
|
'--all'
|
900
1053
|
elsif (refs = projectmap(refs)).empty?
|
901
|
-
raise_error
|
1054
|
+
raise_error 'no qualified pathspec'
|
902
1055
|
else
|
903
1056
|
"-- #{refs.join(' ')}"
|
904
1057
|
end
|
@@ -907,13 +1060,15 @@ module Squared
|
|
907
1060
|
upstream = nil
|
908
1061
|
source(git_output('fetch --no-tags --quiet'), io: true, banner: false)
|
909
1062
|
source(git_output('branch -vv --list'), io: true, banner: false).first.each do |val|
|
910
|
-
next unless (
|
1063
|
+
next unless (r = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
|
911
1064
|
|
912
|
-
branch =
|
913
|
-
if
|
1065
|
+
branch = r[1]
|
1066
|
+
if r[3]
|
1067
|
+
origin = r[3][%r{^(.+)/#{Regexp.escape(branch)}$}, 1]
|
1068
|
+
else
|
914
1069
|
unless (origin = option('repository', prefix: 'git', ignore: false))
|
915
|
-
out = source(git_output('log -n1 --format=%h%d'), io: true,
|
916
|
-
if out =~ /^#{
|
1070
|
+
out = source(git_output('log -n1 --format=%h%d'), io: true, banner: false, stdout: true).first
|
1071
|
+
if out =~ /^#{r[2]} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/
|
917
1072
|
split_escape($1).each do |val|
|
918
1073
|
next unless val.end_with?("/#{branch}")
|
919
1074
|
|
@@ -923,12 +1078,10 @@ module Squared
|
|
923
1078
|
end
|
924
1079
|
end
|
925
1080
|
upstream = true if origin
|
926
|
-
elsif data[3] =~ %r{^(.+)/#{Regexp.escape(branch)}$}
|
927
|
-
origin = $1
|
928
1081
|
end
|
929
1082
|
break
|
930
1083
|
end
|
931
|
-
raise_error
|
1084
|
+
raise_error 'work tree is not usable' unless origin && branch
|
932
1085
|
cmd = git_session('commit', option('dry-run') && '--dry-run', options: false)
|
933
1086
|
if amend
|
934
1087
|
cmd << '--amend'
|
@@ -955,8 +1108,24 @@ module Squared
|
|
955
1108
|
source b
|
956
1109
|
end
|
957
1110
|
|
958
|
-
def
|
959
|
-
cmd = git_session
|
1111
|
+
def merge(flag, opts = [], command: nil)
|
1112
|
+
cmd, opts = git_session('merge', opts: opts)
|
1113
|
+
case flag
|
1114
|
+
when :commit, :'no-commit'
|
1115
|
+
refs = option_sanitize(opts, OPT_GIT[:merge], no: OPT_GIT[:no][:merge]).first
|
1116
|
+
raise_error 'no branch/commit' if refs.empty?
|
1117
|
+
cmd << "--#{flag}" << '--'
|
1118
|
+
append_commit(*refs)
|
1119
|
+
else
|
1120
|
+
return unless VAL_GIT[:merge][:send].include?(command)
|
1121
|
+
|
1122
|
+
cmd << "--#{command}"
|
1123
|
+
end
|
1124
|
+
source
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil)
|
1128
|
+
cmd, opts = git_session('branch', opts: opts)
|
960
1129
|
stdout = false
|
961
1130
|
case flag
|
962
1131
|
when :create
|
@@ -983,7 +1152,7 @@ module Squared
|
|
983
1152
|
end
|
984
1153
|
ref = nil
|
985
1154
|
when :delete
|
986
|
-
force, list = refs.partition { |val| val
|
1155
|
+
force, list = refs.partition { |val| val.match?(/^[\^~]/) }
|
987
1156
|
force.each do |val|
|
988
1157
|
dr = val[0, 3]
|
989
1158
|
d = dr.include?('^') ? '-D' : '-d'
|
@@ -1003,10 +1172,9 @@ module Squared
|
|
1003
1172
|
cmd << '--edit-description'
|
1004
1173
|
when :current
|
1005
1174
|
cmd << '--show-current'
|
1006
|
-
|
1007
|
-
opts = option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first
|
1175
|
+
when :list
|
1008
1176
|
grep = []
|
1009
|
-
opts.each do |opt|
|
1177
|
+
option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first.each do |opt|
|
1010
1178
|
if opt =~ /^(v+)$/
|
1011
1179
|
cmd << "-#{$1}"
|
1012
1180
|
else
|
@@ -1018,42 +1186,46 @@ module Squared
|
|
1018
1186
|
out, banner, from = source(io: true)
|
1019
1187
|
print_item banner
|
1020
1188
|
ret = write_lines(out, sub: [
|
1021
|
-
{ pat: /^(\*\s+)(\S+)(\s*)$/, styles: :green, index: 2 },
|
1022
|
-
{ pat: %r{^(\s*)(remotes/\S+)(.*)$}, styles: :red, index: 2 }
|
1189
|
+
{ pat: /^(\*\s+)(\S+)(\s*)$/, styles: color(:green), index: 2 },
|
1190
|
+
{ pat: %r{^(\s*)(remotes/\S+)(.*)$}, styles: color(:red), index: 2 }
|
1023
1191
|
])
|
1024
1192
|
list_result(ret, 'branches', from: from)
|
1025
1193
|
return
|
1194
|
+
else
|
1195
|
+
head = source(git_output('rev-parse --abbrev-ref HEAD'), io: true, banner: false, stdout: true).first.chomp
|
1196
|
+
if head.empty?
|
1197
|
+
ret = 0
|
1198
|
+
else
|
1199
|
+
out, banner, from = source(cmd << '-vv --no-abbrev --list', io: true)
|
1200
|
+
ret = write_lines(out, grep: /^\*\s+#{Regexp.escape(head)}\s/, banner: banner, first: true) do |line|
|
1201
|
+
next line if stdin?
|
1202
|
+
|
1203
|
+
data = line.sub(/^\*\s+/, '').split(/\s+/)
|
1204
|
+
a = sub_style(data[0], styles: theme[:inline])
|
1205
|
+
b = sub_style(data[1], styles: theme[:extra])
|
1206
|
+
r = /\A(?:\[(.+?)(?=\]\s)\]\s)?(.+)\z/m.match(data[2..-1].join(' '))
|
1207
|
+
[" Branch: #{a + (r[1] ? " (#{r[1]})" : '')}", " Commit: #{b}", "Message: #{r[2]}"].compact.join("\n")
|
1208
|
+
end
|
1209
|
+
on :last, from
|
1210
|
+
end
|
1211
|
+
if ret == 0
|
1212
|
+
warn log_message(Logger::WARN, name, 'no ref found', subject: 'branch', hint: 'head', pass: true)
|
1213
|
+
end
|
1214
|
+
return
|
1026
1215
|
end
|
1027
1216
|
cmd << shell_escape(target) if target
|
1028
1217
|
cmd << shell_escape(ref) if ref
|
1029
1218
|
source(stdout: stdout)
|
1030
1219
|
end
|
1031
1220
|
|
1032
|
-
def restore(flag, opts = [], tree: nil)
|
1033
|
-
cmd = git_session 'restore'
|
1034
|
-
refs = option_sanitize(opts, OPT_GIT[:restore], no: OPT_GIT[:no][:restore]).first
|
1035
|
-
if flag == :source
|
1036
|
-
cmd << '--patch' if refs.empty?
|
1037
|
-
cmd << shell_option('source', tree)
|
1038
|
-
else
|
1039
|
-
cmd << "--#{flag}"
|
1040
|
-
end
|
1041
|
-
if session_arg?('p', 'patch')
|
1042
|
-
option_clear refs
|
1043
|
-
else
|
1044
|
-
append_pathspec(refs, expect: true)
|
1045
|
-
end
|
1046
|
-
source(sync: false, stderr: true)
|
1047
|
-
end
|
1048
|
-
|
1049
1221
|
def show(format, opts = [])
|
1050
|
-
cmd = git_session
|
1222
|
+
cmd, opts = git_session('show', opts: opts)
|
1051
1223
|
if format
|
1052
1224
|
case (val = format.downcase)
|
1053
1225
|
when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
|
1054
1226
|
cmd << basic_option('format', val)
|
1055
1227
|
else
|
1056
|
-
if format
|
1228
|
+
if format.match?(/^t?format:/) || format.include?('%')
|
1057
1229
|
cmd << quote_option('pretty', format)
|
1058
1230
|
else
|
1059
1231
|
opts << format
|
@@ -1071,18 +1243,19 @@ module Squared
|
|
1071
1243
|
end
|
1072
1244
|
|
1073
1245
|
def rev_parse(flag, opts = [], ref: nil, size: nil)
|
1074
|
-
cmd = git_session
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1246
|
+
cmd, opts = git_session('rev-parse', opts: opts)
|
1247
|
+
cmd << if flag == :parseopt
|
1248
|
+
'--parseopt'
|
1249
|
+
elsif opts.delete('sq-quote')
|
1250
|
+
'--sq-quote'
|
1251
|
+
end
|
1079
1252
|
case flag
|
1080
1253
|
when :commit
|
1081
1254
|
cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
|
1082
|
-
append_commit
|
1255
|
+
append_commit(ref, head: true)
|
1083
1256
|
when :branch
|
1084
1257
|
cmd << '--abbrev-ref'
|
1085
|
-
append_commit
|
1258
|
+
append_commit(ref, head: true)
|
1086
1259
|
else
|
1087
1260
|
args = option_sanitize(opts, OPT_GIT[:rev_parse][flag]).first
|
1088
1261
|
append_value(args, escape: session_arg?('sq-quote'))
|
@@ -1091,7 +1264,7 @@ module Squared
|
|
1091
1264
|
end
|
1092
1265
|
|
1093
1266
|
def ls_remote(flag, opts = [], remote: nil)
|
1094
|
-
cmd = git_session
|
1267
|
+
cmd, opts = git_session('ls-remote', '--refs', opts: opts)
|
1095
1268
|
cmd << "--#{flag}" unless flag == :remote
|
1096
1269
|
grep = option_sanitize(opts, OPT_GIT[:ls_remote]).first
|
1097
1270
|
cmd << shell_quote(remote) if remote
|
@@ -1102,7 +1275,7 @@ module Squared
|
|
1102
1275
|
end
|
1103
1276
|
|
1104
1277
|
def ls_files(flag, opts = [])
|
1105
|
-
git_session
|
1278
|
+
opts = git_session('ls-files', "--#{flag}", opts: opts).last
|
1106
1279
|
grep = option_sanitize(opts, OPT_GIT[:ls_files]).first
|
1107
1280
|
out, banner, from = source(io: true)
|
1108
1281
|
print_item banner
|
@@ -1110,10 +1283,51 @@ module Squared
|
|
1110
1283
|
list_result(ret, 'files', from: from, grep: grep)
|
1111
1284
|
end
|
1112
1285
|
|
1286
|
+
def git(flag, opts = [])
|
1287
|
+
cmd, opts = git_session(flag, opts: opts)
|
1288
|
+
refs = option_sanitize(opts, OPT_GIT[flag], no: OPT_GIT[:no][flag]).first
|
1289
|
+
refs = projectmap(refs) unless flag == :revert
|
1290
|
+
sync = false
|
1291
|
+
stderr = true
|
1292
|
+
case flag
|
1293
|
+
when :clean
|
1294
|
+
unless refs.empty?
|
1295
|
+
cmd << '--'
|
1296
|
+
cmd.merge(refs)
|
1297
|
+
end
|
1298
|
+
sync = true
|
1299
|
+
stderr = false
|
1300
|
+
when :restore
|
1301
|
+
if session_arg?('p', 'patch')
|
1302
|
+
option_clear refs
|
1303
|
+
else
|
1304
|
+
append_pathspec(refs, expect: true)
|
1305
|
+
end
|
1306
|
+
when :revert
|
1307
|
+
if VAL_GIT[:rebase][:send].any? { |val| session_arg?(val) }
|
1308
|
+
option_clear refs
|
1309
|
+
elsif refs.empty?
|
1310
|
+
raise_error 'no commit given'
|
1311
|
+
else
|
1312
|
+
append_commit(*refs)
|
1313
|
+
end
|
1314
|
+
when :mv
|
1315
|
+
raise_error 'no source/destination' unless refs.size > 1
|
1316
|
+
cmd.merge(refs)
|
1317
|
+
when :rm
|
1318
|
+
append_pathspec(refs, expect: true)
|
1319
|
+
end
|
1320
|
+
source(sync: sync, stderr: stderr)
|
1321
|
+
end
|
1322
|
+
|
1113
1323
|
def clone?
|
1114
1324
|
ref?(workspace.baseref) && workspace.git_clone?(path, name) ? 1 : false
|
1115
1325
|
end
|
1116
1326
|
|
1327
|
+
def revbuild?
|
1328
|
+
build? && !!workspace.revfile
|
1329
|
+
end
|
1330
|
+
|
1117
1331
|
def enabled?(*, **kwargs)
|
1118
1332
|
super || (kwargs[:base] == false && !!clone?)
|
1119
1333
|
end
|
@@ -1126,7 +1340,7 @@ module Squared
|
|
1126
1340
|
if cmd.respond_to?(:done)
|
1127
1341
|
if io && banner == false
|
1128
1342
|
from = nil
|
1129
|
-
elsif !from && (from = cmd.drop(1).find { |val| val
|
1343
|
+
elsif !from && (from = cmd.drop(1).find { |val| val.match?(/^[a-z][a-z\-]{2,}$/) })
|
1130
1344
|
from = :"git:#{from}"
|
1131
1345
|
end
|
1132
1346
|
banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
|
@@ -1172,13 +1386,13 @@ module Squared
|
|
1172
1386
|
ret = on(:error, from, e)
|
1173
1387
|
raise if exception && ret != true
|
1174
1388
|
|
1175
|
-
warn log_message(Logger::WARN, e) if warning?
|
1389
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1176
1390
|
else
|
1177
1391
|
on :last, from
|
1178
1392
|
end
|
1179
1393
|
end
|
1180
1394
|
|
1181
|
-
def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false)
|
1395
|
+
def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false, first: false)
|
1182
1396
|
grep = as_a(grep).map do |val|
|
1183
1397
|
next val if val.is_a?(Regexp)
|
1184
1398
|
|
@@ -1191,6 +1405,7 @@ module Squared
|
|
1191
1405
|
data.each do |line|
|
1192
1406
|
next if grep&.none? { |pat| pat.match?(line) }
|
1193
1407
|
|
1408
|
+
line = yield line if block_given?
|
1194
1409
|
if loglevel
|
1195
1410
|
log&.add loglevel, line
|
1196
1411
|
else
|
@@ -1202,8 +1417,9 @@ module Squared
|
|
1202
1417
|
end
|
1203
1418
|
end
|
1204
1419
|
ret += 1
|
1420
|
+
break if first
|
1205
1421
|
end
|
1206
|
-
print_item banner, out if banner && (ret > 0 || !pass)
|
1422
|
+
print_item banner, out if banner && (ret > 0 || (!pass && !first))
|
1207
1423
|
ret
|
1208
1424
|
end
|
1209
1425
|
|
@@ -1226,6 +1442,21 @@ module Squared
|
|
1226
1442
|
on :last, from
|
1227
1443
|
end
|
1228
1444
|
|
1445
|
+
def status_digest(*args, algorithm: Digest::SHA256, **kwargs)
|
1446
|
+
glob = kwargs.fetch(:include, [])
|
1447
|
+
pass = kwargs.fetch(:exclude, [])
|
1448
|
+
ret = {}
|
1449
|
+
out = source(git_output('status -s --porcelain', *args), io: true, banner: false).first
|
1450
|
+
out.each do |line|
|
1451
|
+
next unless (file = line[/^[A-Z ?!]{3}"?(.+?)"?$/, 1])
|
1452
|
+
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1453
|
+
next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1454
|
+
|
1455
|
+
ret[file] = algorithm.hexdigest(File.read(basepath(file)))
|
1456
|
+
end
|
1457
|
+
ret
|
1458
|
+
end
|
1459
|
+
|
1229
1460
|
def append_pull(opts, list, target: @session, no: nil, flag: nil, remote: nil)
|
1230
1461
|
cmd << '--force' if option('force')
|
1231
1462
|
rsm = append_submodules(target: target)
|
@@ -1265,9 +1496,13 @@ module Squared
|
|
1265
1496
|
option_clear(out, target: target, subject: flag.to_s) if flag
|
1266
1497
|
end
|
1267
1498
|
|
1268
|
-
def append_commit(val, target: @session)
|
1269
|
-
val
|
1270
|
-
|
1499
|
+
def append_commit(*val, target: @session, head: false)
|
1500
|
+
val.compact!
|
1501
|
+
if !val.empty?
|
1502
|
+
val.each { |ref| target << (commithash(ref) || shell_quote(ref)) }
|
1503
|
+
elsif head
|
1504
|
+
target << (append_head(target: target) || 'HEAD')
|
1505
|
+
end
|
1271
1506
|
end
|
1272
1507
|
|
1273
1508
|
def append_pathspec(files = [], target: @session, expect: false, parent: false)
|
@@ -1279,9 +1514,9 @@ module Squared
|
|
1279
1514
|
end
|
1280
1515
|
files = projectmap(files, parent: parent)
|
1281
1516
|
if !files.empty?
|
1282
|
-
target <<
|
1517
|
+
target << '--' << files.join(' ')
|
1283
1518
|
elsif expect
|
1284
|
-
raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree'
|
1519
|
+
raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree')
|
1285
1520
|
end
|
1286
1521
|
end
|
1287
1522
|
end
|
@@ -1316,9 +1551,13 @@ module Squared
|
|
1316
1551
|
end
|
1317
1552
|
end
|
1318
1553
|
|
1319
|
-
def git_session(*cmd, worktree: true, **kwargs)
|
1554
|
+
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
1320
1555
|
dir = worktree ? ["--work-tree=#{shell_quote(path)}", "--git-dir=#{shell_quote(gitpath)}"] : []
|
1321
|
-
session('git', *dir,
|
1556
|
+
ret = session('git', *dir, **kwargs)
|
1557
|
+
return ret.merge(cmd) unless opts
|
1558
|
+
|
1559
|
+
opts = option_sanitize(opts, OPT_GIT[:common]).first
|
1560
|
+
[ret.merge(cmd), opts]
|
1322
1561
|
end
|
1323
1562
|
|
1324
1563
|
def git_output(*cmd, **kwargs)
|
@@ -1336,11 +1575,11 @@ module Squared
|
|
1336
1575
|
end
|
1337
1576
|
|
1338
1577
|
def gitpath
|
1339
|
-
basepath
|
1578
|
+
basepath '.git'
|
1340
1579
|
end
|
1341
1580
|
|
1342
1581
|
def commithash(val)
|
1343
|
-
val
|
1582
|
+
val[/^#\{(\h{5,40})\}$/, 1]
|
1344
1583
|
end
|
1345
1584
|
|
1346
1585
|
def threadargs
|