squared 0.3.14 → 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 +63 -230
- data/README.md +1285 -387
- data/README.ruby.md +546 -0
- data/lib/squared/app.rb +1 -0
- data/lib/squared/common/base.rb +9 -7
- data/lib/squared/common/class.rb +1 -1
- data/lib/squared/common/format.rb +34 -24
- data/lib/squared/common/prompt.rb +3 -3
- data/lib/squared/common/shell.rb +53 -41
- data/lib/squared/common/system.rb +14 -21
- data/lib/squared/common/utils.rb +55 -2
- data/lib/squared/config.rb +1 -3
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +34 -43
- data/lib/squared/workspace/project/base.rb +476 -215
- data/lib/squared/workspace/project/docker.rb +572 -0
- data/lib/squared/workspace/project/git.rb +489 -256
- data/lib/squared/workspace/project/node.rb +86 -92
- data/lib/squared/workspace/project/python.rb +130 -41
- data/lib/squared/workspace/project/ruby.rb +52 -68
- data/lib/squared/workspace/project.rb +7 -1
- data/lib/squared/workspace/repo.rb +12 -5
- data/lib/squared/workspace/series.rb +1 -1
- data/squared.gemspec +4 -4
- metadata +8 -6
@@ -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,29 +11,27 @@ 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)
|
14
20
|
base = name
|
15
|
-
uri.each
|
16
|
-
if (proj = @project[val.to_s]) && check.(proj)
|
17
|
-
repo << proj
|
18
|
-
end
|
19
|
-
end
|
21
|
+
uri.each { |val| repo << proj if (proj = @project[val.to_s]) && check.(proj) }
|
20
22
|
elsif uri
|
21
23
|
data[name.to_s] = uri
|
22
24
|
elsif name.is_a?(Enumerable)
|
23
25
|
data = name.to_h
|
24
|
-
elsif name.is_a?(String) && name
|
26
|
+
elsif name.is_a?(String) && name.match?(GIT_PROTO)
|
25
27
|
base = name
|
26
28
|
@project.each_value { |proj| repo << proj if !proj.parent && check.(proj) }
|
27
29
|
else
|
28
|
-
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
|
29
31
|
return self
|
30
32
|
end
|
31
33
|
if base
|
32
|
-
base = base
|
34
|
+
base = base.match?(GIT_PROTO) ? "#{base.chomp('/')}/" : @root.join(base)
|
33
35
|
repo.each do |target|
|
34
36
|
if target.is_a?(Project::Git)
|
35
37
|
data[target.localname] = target.project
|
@@ -59,6 +61,23 @@ module Squared
|
|
59
61
|
(GIT_REPO[main] ||= {})[key] = [uri.to_s, opts]
|
60
62
|
(@kind[key] ||= []) << Project::Git
|
61
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)
|
62
81
|
self
|
63
82
|
end
|
64
83
|
|
@@ -66,36 +85,86 @@ module Squared
|
|
66
85
|
(ret = GIT_REPO[main]) && ret[name]
|
67
86
|
end
|
68
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
|
+
|
69
132
|
def git_clone?(path, name = nil)
|
70
133
|
return false if name && !git_repo(name)
|
71
134
|
|
72
135
|
!path.exist? || path.empty?
|
73
136
|
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def rev_timenow
|
141
|
+
DateTime.now.strftime('%Q').to_i + time_offset
|
142
|
+
end
|
74
143
|
end
|
75
144
|
Application.include Git
|
76
145
|
|
77
146
|
module Project
|
78
147
|
class Git < Base
|
79
|
-
include Prompt
|
80
|
-
|
81
148
|
OPT_GIT = {
|
82
|
-
|
83
|
-
|
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,
|
151
|
+
branch: %w[a|all create-reflog i|ignore-case q|quiet r|remotes v|verbose abbrev=i color=b column=b
|
152
|
+
contains=b format=q merged=b no-contains=b no-merged=b points-at=e u|set-upstream-to=e sort=q
|
84
153
|
t|track=b].freeze,
|
85
154
|
checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
|
86
|
-
pathspec-file-nul q
|
155
|
+
pathspec-file-nul q quiet orphan=e ours theirs conflict=b pathspec-from-file=p
|
87
156
|
t|track=b].freeze,
|
157
|
+
clean: %w[d x X f|force i|interactive n|dry-run q|quiet e|exlcude=q].freeze,
|
88
158
|
diff: {
|
89
159
|
base: %w[0 1|base 2|ours 3|theirs].freeze,
|
90
160
|
show: %w[s exit-code histogram].freeze
|
91
161
|
}.freeze,
|
92
162
|
fetch: {
|
93
|
-
base: %w[multiple progress P|prune-tags refetch stdin u|update-head-ok
|
163
|
+
base: %w[multiple progress P|prune-tags refetch stdin u|update-head-ok recurse-submodules=b
|
94
164
|
recurse-submodules-default=b].freeze,
|
95
|
-
pull: %w[4 6 n t a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet
|
165
|
+
pull: %w[4 6 n t a|append atomic dry-run f|force k|keep n|negotiate-only prefetch p|prune q|quiet
|
96
166
|
set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
|
97
|
-
|
98
|
-
upload-pack=e].freeze
|
167
|
+
refmap=q o|server-option=q shallow-exclude=e shallow-since=b upload-pack=q].freeze
|
99
168
|
}.freeze,
|
100
169
|
log: {
|
101
170
|
base: %w[all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
|
@@ -103,47 +172,54 @@ module Squared
|
|
103
172
|
first-parent F|fixed-strings follow full-diff full-history ignore-missing invert-grep left-only
|
104
173
|
merge log-size no-max-parents no-min-parents not P|perl-regexp reflog i|regexp-ignore-case
|
105
174
|
remove-empty reverse right-only simplify-by-decoration simplify-merges single-worktree show-pulls
|
106
|
-
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
|
107
176
|
branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
|
108
177
|
exclude-hidden=b? glob=q grep=q grep-reflog=q L=q n|max-count=i max-parents=i min-parents=i
|
109
178
|
no-walk=b? remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
|
110
179
|
format: %w[t children combined-all-paths oneline left-right no-diff-merges parents relative-date
|
111
|
-
show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=
|
180
|
+
show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=q pretty=q?
|
112
181
|
show-linear-break=q?].freeze,
|
113
182
|
diff: %w[p R u z l=i G=q O=q S=q binary check compact-summary cumulative find-copies-harder full-index
|
114
183
|
W|function-context w|ignore-all-space ignore-blank-lines ignore-cr-at-eol ignore-space-at-eol
|
115
184
|
b|ignore-space-change D|irreversible-delete graph ita-invisible-in-index minimal name-only
|
116
185
|
name-status no-color-moved-ws no-prefix no-renames numstat patch-with-raw patch-with-stat patience
|
117
|
-
pickaxe-all pickaxe-regex raw shortstat summary a|text abbrev=i? anchored=q B|break-rewrites=
|
118
|
-
color=b color-moved=b color-moved-ws=b color-words=q? diff-algorithm=b diff-filter=e? X|dirstat=
|
119
|
-
dirstat-by-file=q? dst-prefix=q C|find-copies=
|
186
|
+
pickaxe-all pickaxe-regex raw shortstat summary a|text abbrev=i? anchored=q B|break-rewrites=b?
|
187
|
+
color=b color-moved=b color-moved-ws=b color-words=q? diff-algorithm=b diff-filter=e? X|dirstat=q?
|
188
|
+
dirstat-by-file=q? dst-prefix=q C|find-copies=i? find-object=b M|find-renames=i?
|
120
189
|
I|ignore-matching-lines=q ignore-submodules=b inter-hunk-context=i line-prefix=q output=p
|
121
190
|
output-indicator-context=q output-indicator-new=q output-indicator-old=q relative=p rotate-to=p
|
122
191
|
skip-to=p src-prefix=q stat=q? stat-width=i stat-name-width=i stat-count=i submodule=b? U|unified=i
|
123
|
-
word-diff=b? word-diff-regex=q ws-error-
|
192
|
+
word-diff=b? word-diff-regex=q ws-error-highligt=q].freeze
|
124
193
|
}.freeze,
|
125
|
-
ls_files: %w[
|
126
|
-
|
194
|
+
ls_files: %w[z debug deduplicate directory eol error-unmatch exclude-standard full-name k|killed
|
195
|
+
no-empty-directory recurse-submodules sparse s|stage u|unmerged abbrev=i x|exclude=q
|
127
196
|
X|exclude-from=p exclude-per-directory=p format=q with-tree=q].freeze,
|
128
|
-
ls_remote: %w[exit-code get-url q|quiet o|server-option=
|
129
|
-
|
130
|
-
|
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,
|
131
203
|
rebase: %w[n C=i allow-empty-message apply committer-date-is-author-date edit-todo f|force-rebase ignore-date
|
132
|
-
ignore-whitespace i|interactive keep-base m
|
133
|
-
reset-author-date root show-current-patch signoff v|verbose empty=b S|gpg-sign=
|
134
|
-
s|strategy=b X|strategy-option=b whitespace=
|
204
|
+
ignore-whitespace i|interactive keep-base m merge no-ff q|quiet quit r|rebase-merges=b?
|
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,
|
135
207
|
reset: %w[N pathspec-file-nul q|quiet pathspec-from-file=p].freeze,
|
136
208
|
restore: %w[ignore-unmerged ignore-skip-worktree-bits m|merge ours p|patch pathspec-file-nul S|staged theirs
|
137
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,
|
138
212
|
rev_parse: {
|
139
213
|
output: %w[absolute-git-dir all flags git-common-dir git-dir is-bare-repository is-inside-git-dir
|
140
|
-
is-inside-work-tree is-shallow-repository local-env-vars no-flags no-revs not q|quiet
|
141
|
-
shared-index-path show-cdup show-prefix show-toplevel show-superproject-working-tree
|
142
|
-
symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q default=
|
143
|
-
exclude=q exclude-hidden=b glob=q git-path=p path-format=b? prefix=q branches=q?
|
144
|
-
resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
|
214
|
+
is-inside-work-tree is-shallow-repository local-env-vars no-flags no-revs not q|quiet sq
|
215
|
+
revs-only shared-index-path show-cdup show-prefix show-toplevel show-superproject-working-tree
|
216
|
+
sq-quote symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q default=q
|
217
|
+
disambiguate=b exclude=q exclude-hidden=b glob=q git-path=p path-format=b? prefix=q branches=q?
|
218
|
+
remotes=q? resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
|
145
219
|
parseopt: %w[keep-dashdash stop-at-non-option stuck-long].freeze
|
146
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,
|
147
223
|
show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
|
148
224
|
expand-tabs=i notes=q show-notes=q?].freeze,
|
149
225
|
stash: {
|
@@ -153,7 +229,8 @@ module Squared
|
|
153
229
|
pop: %w[index].freeze,
|
154
230
|
apply: %w[index].freeze
|
155
231
|
}.freeze,
|
156
|
-
|
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
|
157
234
|
sort=q].freeze,
|
158
235
|
no: {
|
159
236
|
fetch: {
|
@@ -169,20 +246,26 @@ module Squared
|
|
169
246
|
tag: %w[column].freeze,
|
170
247
|
branch: %w[color-moved column color track].freeze,
|
171
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,
|
172
251
|
rebase: %w[autosquash autostash fork-point gpg-sign keep-empty reapply-cherry-picks reschedule-failed-exec
|
173
252
|
rerere-autoupdate stat update-refs verify].freeze,
|
174
253
|
reset: %w[refresh].freeze,
|
175
254
|
restore: %w[overlay progress recurse-submodules].freeze,
|
255
|
+
revert: %w[edit gpg-sign rerere-autoupdate].freeze,
|
176
256
|
show: %w[standard-notes].freeze
|
177
257
|
}.freeze
|
178
|
-
}
|
258
|
+
}.freeze
|
179
259
|
VAL_GIT = {
|
260
|
+
merge: {
|
261
|
+
send: %w[continue abort quit].freeze
|
262
|
+
}.freeze,
|
180
263
|
rebase: {
|
181
264
|
send: %w[continue skip abort quit].freeze,
|
182
265
|
value: %w[true false merges interactive].freeze
|
183
266
|
}.freeze,
|
184
267
|
reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze
|
185
|
-
}
|
268
|
+
}.freeze
|
186
269
|
private_constant :OPT_GIT, :VAL_GIT
|
187
270
|
|
188
271
|
class << self
|
@@ -214,7 +297,7 @@ module Squared
|
|
214
297
|
end
|
215
298
|
|
216
299
|
def tasks
|
217
|
-
%i[pull rebase fetch clone stash status].freeze
|
300
|
+
%i[pull rebase fetch clone stash status branch revbuild].freeze
|
218
301
|
end
|
219
302
|
|
220
303
|
def batchargs
|
@@ -232,24 +315,25 @@ module Squared
|
|
232
315
|
'branch' => %i[create set delete move copy list edit current].freeze,
|
233
316
|
'checkout' => %i[commit branch track detach path].freeze,
|
234
317
|
'commit' => %i[add all amend amend-orig].freeze,
|
235
|
-
'diff' => %i[head
|
318
|
+
'diff' => %i[head branch files view between contain].freeze,
|
236
319
|
'fetch' => %i[origin remote].freeze,
|
237
|
-
'files' => %i[cached modified deleted others].freeze,
|
320
|
+
'files' => %i[cached modified deleted others ignored].freeze,
|
321
|
+
'git' => %i[clean mv restore revert rm].freeze,
|
238
322
|
'log' => %i[view between contain].freeze,
|
323
|
+
'merge' => %i[commit no-commit send].freeze,
|
239
324
|
'pull' => %i[origin remote].freeze,
|
240
325
|
'rebase' => %i[branch onto send].freeze,
|
241
326
|
'refs' => %i[heads tags remote].freeze,
|
242
327
|
'reset' => %i[commit index patch mode].freeze,
|
243
|
-
'
|
244
|
-
'rev' => %i[commit branch output parseopt].freeze,
|
328
|
+
'rev' => %i[commit branch output parseopt build].freeze,
|
245
329
|
'show' => %i[format oneline].freeze,
|
246
|
-
'stash' => %i[push pop apply drop
|
330
|
+
'stash' => %i[push pop apply drop list].freeze,
|
247
331
|
'tag' => %i[add delete list].freeze
|
248
332
|
}.freeze
|
249
333
|
|
250
334
|
def initialize(*, **)
|
251
335
|
super
|
252
|
-
initialize_ref
|
336
|
+
initialize_ref Git.ref if gitpath.exist?
|
253
337
|
end
|
254
338
|
|
255
339
|
def ref
|
@@ -294,19 +378,6 @@ module Squared
|
|
294
378
|
commit(flag, refs: refs)
|
295
379
|
end
|
296
380
|
end
|
297
|
-
when 'restore'
|
298
|
-
if flag == :source
|
299
|
-
format_desc action, flag, 'tree,opts*,pathspec*'
|
300
|
-
task flag, [:tree] do |_, args|
|
301
|
-
tree = param_guard(action, flag, args: args, key: :tree)
|
302
|
-
restore(flag, args.extras, tree: tree)
|
303
|
-
end
|
304
|
-
else
|
305
|
-
format_desc action, flag, 'opts*,pathspec+'
|
306
|
-
task flag do |_, args|
|
307
|
-
restore flag, args.to_a
|
308
|
-
end
|
309
|
-
end
|
310
381
|
when 'tag'
|
311
382
|
case flag
|
312
383
|
when :list
|
@@ -340,9 +411,19 @@ module Squared
|
|
340
411
|
case flag
|
341
412
|
when :view, :between, :contain
|
342
413
|
if flag == :view && action == 'log'
|
343
|
-
format_desc action, flag, '(^)commit*,pathspec*,opts*'
|
414
|
+
format_desc action, flag, '(^)commit/H0*,pathspec*,opts*'
|
344
415
|
task flag do |_, args|
|
345
|
-
|
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)
|
346
427
|
end
|
347
428
|
else
|
348
429
|
format_desc action, flag, 'commit1,commit2,pathspec*,opts*'
|
@@ -352,10 +433,16 @@ module Squared
|
|
352
433
|
__send__(action == 'log' ? :logx : :diff, flag, args.extras, range: [commit1, commit2])
|
353
434
|
end
|
354
435
|
end
|
355
|
-
when :head
|
356
|
-
format_desc action, flag, 'opts*,pathspec*'
|
436
|
+
when :head
|
437
|
+
format_desc action, flag, 'commit/H0*,opts*,pathspec*'
|
357
438
|
task flag do |_, args|
|
358
|
-
|
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)
|
359
446
|
end
|
360
447
|
when :branch
|
361
448
|
format_desc action, flag, 'name,opts*,pathspec*'
|
@@ -406,7 +493,7 @@ module Squared
|
|
406
493
|
format_desc action, flag, 'branch/commit,opts*'
|
407
494
|
task flag, [:commit] do |_, args|
|
408
495
|
commit = param_guard(action, flag, args: args, key: :commit)
|
409
|
-
checkout(flag,
|
496
|
+
checkout(flag, commit: commit)
|
410
497
|
end
|
411
498
|
when :detach
|
412
499
|
format_desc action, flag, 'branch/commit?'
|
@@ -500,7 +587,7 @@ module Squared
|
|
500
587
|
show args.format, args.extras
|
501
588
|
end
|
502
589
|
end
|
503
|
-
when 'rebase'
|
590
|
+
when 'rebase', 'merge'
|
504
591
|
case flag
|
505
592
|
when :branch
|
506
593
|
format_desc action, flag, 'opts*,upstream?,branch?'
|
@@ -515,11 +602,18 @@ module Squared
|
|
515
602
|
upstream = param_guard(action, flag, args: args, key: :upstream)
|
516
603
|
rebase(flag, commit: commit, upstream: upstream, branch: args.branch)
|
517
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
|
518
611
|
when :send
|
519
|
-
format_desc(action, flag, VAL_GIT[
|
612
|
+
format_desc(action, flag, VAL_GIT[action.to_sym][:send], arg: nil)
|
520
613
|
task flag, [:command] do |_, args|
|
521
|
-
command = param_guard(action, flag, args: args, key: :command
|
522
|
-
|
614
|
+
command = param_guard(action, flag, args: args, key: :command,
|
615
|
+
values: VAL_GIT[action.to_sym][:send])
|
616
|
+
__send__(action, flag, command: command)
|
523
617
|
end
|
524
618
|
end
|
525
619
|
when 'rev'
|
@@ -540,6 +634,11 @@ module Squared
|
|
540
634
|
task flag, [:ref] do |_, args|
|
541
635
|
rev_parse(flag, ref: args.ref)
|
542
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
|
543
642
|
else
|
544
643
|
format_desc action, flag, 'opts*,args*'
|
545
644
|
task flag do |_, args|
|
@@ -551,7 +650,7 @@ module Squared
|
|
551
650
|
format_desc action, flag, 'remote,opts*,pattern*'
|
552
651
|
task flag, [:remote] do |_, args|
|
553
652
|
remote = param_guard(action, flag, args: args, key: :remote)
|
554
|
-
ls_remote(flag, args.
|
653
|
+
ls_remote(flag, args.to_a.drop(1), remote: remote)
|
555
654
|
end
|
556
655
|
else
|
557
656
|
format_desc action, flag, 'opts*,pattern*'
|
@@ -559,6 +658,18 @@ module Squared
|
|
559
658
|
__send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
|
560
659
|
end
|
561
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
|
562
673
|
end
|
563
674
|
end
|
564
675
|
end
|
@@ -571,12 +682,19 @@ module Squared
|
|
571
682
|
super
|
572
683
|
end
|
573
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
|
+
|
574
695
|
def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil)
|
575
|
-
cmd = git_session
|
576
|
-
if
|
577
|
-
cmd << '--rebase'
|
578
|
-
cmd << '--autostash' if option('autostash')
|
579
|
-
elsif (val = option('rebase', ignore: false))
|
696
|
+
cmd, opts = git_session('pull', flag && "--#{flag}", opts: opts)
|
697
|
+
if (val = option('rebase', ignore: false))
|
580
698
|
cmd << case val
|
581
699
|
when '0'
|
582
700
|
'--no-rebase'
|
@@ -588,8 +706,8 @@ module Squared
|
|
588
706
|
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag)
|
589
707
|
source(sync: sync, sub: if verbose
|
590
708
|
[
|
591
|
-
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
|
592
|
-
{ 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 }
|
593
711
|
]
|
594
712
|
end, **threadargs)
|
595
713
|
end
|
@@ -598,7 +716,7 @@ module Squared
|
|
598
716
|
command: nil)
|
599
717
|
return pull(:rebase, sync: sync) unless flag
|
600
718
|
|
601
|
-
cmd = git_session
|
719
|
+
cmd, opts = git_session('rebase', opts: opts)
|
602
720
|
case flag
|
603
721
|
when :branch
|
604
722
|
branch = option_sanitize(opts, OPT_GIT[:rebase], no: OPT_GIT[:no][:rebase]).first
|
@@ -627,7 +745,7 @@ module Squared
|
|
627
745
|
end
|
628
746
|
|
629
747
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
630
|
-
cmd = git_session
|
748
|
+
cmd, opts = git_session('fetch', opts: opts)
|
631
749
|
cmd << '--all' if !remote && !opts.include?('multiple') && option('all')
|
632
750
|
cmd << '--verbose' if verbose && !opts.include?('quiet')
|
633
751
|
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
|
@@ -659,22 +777,14 @@ module Squared
|
|
659
777
|
|
660
778
|
def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
|
661
779
|
if flag
|
662
|
-
cmd = git_session
|
663
|
-
|
664
|
-
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
|
665
782
|
case flag
|
666
783
|
when :push
|
667
784
|
append_pathspec refs
|
668
785
|
when :pop, :apply, :drop
|
669
|
-
|
670
|
-
|
671
|
-
option_clear refs
|
672
|
-
end
|
673
|
-
when :clear
|
674
|
-
if confirm("Remove #{sub_style('all', styles: theme[:active])} the stash entries? [y/N] ", 'N')
|
675
|
-
source(stdout: true)
|
676
|
-
end
|
677
|
-
return
|
786
|
+
cmd << shell_quote(refs.pop)
|
787
|
+
option_clear refs
|
678
788
|
when :list
|
679
789
|
out, banner, from = source(io: true)
|
680
790
|
print_item banner
|
@@ -683,17 +793,16 @@ module Squared
|
|
683
793
|
return
|
684
794
|
end
|
685
795
|
else
|
686
|
-
git_session
|
796
|
+
git_session('stash', 'push', opts: opts)
|
687
797
|
append_option(%w[all keep-index include-untracked staged].freeze, no: true, ignore: false)
|
688
798
|
append_message option('message', 'm', ignore: false)
|
689
799
|
end
|
690
800
|
source(banner: !quiet?, sync: sync, **threadargs)
|
691
801
|
end
|
692
802
|
|
693
|
-
def status(
|
803
|
+
def status(*)
|
694
804
|
cmd = git_session 'status'
|
695
805
|
cmd << (option('long') ? '--long' : '--short')
|
696
|
-
cmd << '--branch' if option('branch')
|
697
806
|
if (val = option('ignore-submodules', ignore: false))
|
698
807
|
cmd << basic_option('ignore-submodules', case val
|
699
808
|
when '0', 'none'
|
@@ -708,31 +817,85 @@ module Squared
|
|
708
817
|
end
|
709
818
|
append_pathspec
|
710
819
|
out, banner, from = source(io: true)
|
711
|
-
if sync
|
712
|
-
print_item banner
|
713
|
-
banner = nil
|
714
|
-
end
|
715
820
|
ret = write_lines(out, banner: banner, sub: if verbose
|
821
|
+
r = color(:red)
|
822
|
+
g = color(:green)
|
716
823
|
[
|
717
|
-
{ pat: /^(.)([A-Z?!])(.+)$/, styles:
|
718
|
-
{ pat: /^([A-Z?!])(.+)$/, styles:
|
719
|
-
{ pat: /^(\?\?)(.+)$/, styles:
|
824
|
+
{ pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
|
825
|
+
{ pat: /^([A-Z?!])(.+)$/, styles: g },
|
826
|
+
{ pat: /^(\?\?)(.+)$/, styles: r },
|
720
827
|
{ pat: /^(## )(.+)(\.{3})(.+)$/,
|
721
|
-
styles: [nil,
|
828
|
+
styles: [nil, g, nil, r], index: -1 }
|
722
829
|
]
|
723
830
|
end)
|
724
831
|
list_result(ret, 'files', from: from, action: 'modified')
|
725
832
|
end
|
726
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
|
+
|
727
888
|
def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
|
728
|
-
cmd = git_session
|
889
|
+
cmd, opts = git_session('reset', opts: opts)
|
729
890
|
case flag
|
730
891
|
when :commit, :index
|
731
|
-
|
892
|
+
out = option_sanitize(opts, OPT_GIT[:reset] + VAL_GIT[:reset], no: OPT_GIT[:no][:reset]).first
|
732
893
|
if flag == :commit
|
733
|
-
append_value
|
734
|
-
option_clear
|
894
|
+
append_value(commit, delim: true)
|
895
|
+
option_clear out
|
735
896
|
ref = false
|
897
|
+
else
|
898
|
+
(refs ||= []).concat(out)
|
736
899
|
end
|
737
900
|
when :mode
|
738
901
|
return unless VAL_GIT[:reset].include?(mode)
|
@@ -748,21 +911,19 @@ module Squared
|
|
748
911
|
return
|
749
912
|
end
|
750
913
|
unless ref == false
|
751
|
-
append_commit
|
914
|
+
append_commit(ref, head: true)
|
752
915
|
append_pathspec refs if refs
|
753
916
|
end
|
754
917
|
source
|
755
918
|
end
|
756
919
|
|
757
920
|
def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil)
|
758
|
-
cmd = git_session
|
921
|
+
cmd, opts = git_session('checkout', opts: opts)
|
759
922
|
append_option 'force', 'merge'
|
760
923
|
case flag
|
761
924
|
when :branch
|
762
925
|
cmd << '--detach' if detach == 'd' || option('detach')
|
763
|
-
|
764
|
-
cmd << shell_option('track', val)
|
765
|
-
end
|
926
|
+
append_option('track', equals: true)
|
766
927
|
cmd << if create
|
767
928
|
shell_option(create, branch)
|
768
929
|
else
|
@@ -783,7 +944,7 @@ module Squared
|
|
783
944
|
else
|
784
945
|
out = option_sanitize(opts, OPT_GIT[:checkout], no: OPT_GIT[:no][:checkout]).first
|
785
946
|
if flag == :commit
|
786
|
-
append_value
|
947
|
+
append_value(commit, delim: true)
|
787
948
|
option_clear out
|
788
949
|
else
|
789
950
|
append_head
|
@@ -794,7 +955,7 @@ module Squared
|
|
794
955
|
end
|
795
956
|
|
796
957
|
def tag(flag, opts = [], refs: [], message: nil, commit: nil)
|
797
|
-
cmd = git_session
|
958
|
+
cmd, opts = git_session('tag', opts: opts)
|
798
959
|
case flag
|
799
960
|
when :add
|
800
961
|
if option('sign')
|
@@ -802,8 +963,8 @@ module Squared
|
|
802
963
|
elsif !session_arg?('s', 'sign', 'u', 'local-user')
|
803
964
|
cmd << '--annotate'
|
804
965
|
end
|
805
|
-
if !commit && message && (
|
806
|
-
commit =
|
966
|
+
if !commit && message && (sha = commithash(message))
|
967
|
+
commit = sha
|
807
968
|
else
|
808
969
|
append_message message
|
809
970
|
end
|
@@ -826,41 +987,27 @@ module Squared
|
|
826
987
|
source
|
827
988
|
end
|
828
989
|
|
829
|
-
def logx(flag, opts = [], range: [])
|
830
|
-
cmd = git_session
|
831
|
-
|
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
|
832
993
|
case flag
|
833
994
|
when :between, :contain
|
834
995
|
cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
|
835
996
|
else
|
836
|
-
|
837
|
-
val.start_with?('^') || (!%r{^.(?:[\\/]|$)}.match?(val) && !%r{[\\/]$}.match?(val)) || commithash(val)
|
838
|
-
end
|
839
|
-
cmd.merge(commit.map { |val| commithash(val) || shell_quote(val) }) unless commit.empty?
|
997
|
+
cmd.merge(index)
|
840
998
|
end
|
841
999
|
append_nocolor
|
842
|
-
append_pathspec
|
1000
|
+
append_pathspec refs
|
843
1001
|
source(exception: false)
|
844
1002
|
end
|
845
1003
|
|
846
|
-
def diff(flag, opts = [], refs: [], branch: nil, range: [])
|
847
|
-
cmd = git_session
|
1004
|
+
def diff(flag, opts = [], refs: [], branch: nil, range: [], index: [])
|
1005
|
+
cmd, opts = git_session('diff', opts: opts)
|
848
1006
|
files = option_sanitize(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff],
|
849
1007
|
no: OPT_GIT[:no][:log][:diff]).first
|
850
1008
|
case flag
|
851
1009
|
when :files, :view, :between, :contain
|
852
1010
|
cmd.delete('--cached')
|
853
|
-
else
|
854
|
-
items = files.dup
|
855
|
-
sha = nil
|
856
|
-
files.clear
|
857
|
-
items.each do |val|
|
858
|
-
if (s = commithash(val))
|
859
|
-
(sha ||= []).push(s)
|
860
|
-
else
|
861
|
-
files << val
|
862
|
-
end
|
863
|
-
end
|
864
1011
|
end
|
865
1012
|
append_nocolor
|
866
1013
|
if flag == :files
|
@@ -875,15 +1022,14 @@ module Squared
|
|
875
1022
|
cmd.delete('--merge-base')
|
876
1023
|
cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
|
877
1024
|
else
|
878
|
-
cmd << '--cached' if flag == :cached
|
879
1025
|
cmd << '--merge-base' if option('merge-base')
|
880
1026
|
cmd << shell_quote(branch) if branch
|
881
|
-
if
|
1027
|
+
if !index.empty?
|
882
1028
|
if session_arg?('cached')
|
883
|
-
raise_error(
|
884
|
-
cmd <<
|
1029
|
+
raise_error("one commit only: #{index.join(', ')}", hint: '--cached') if index.size > 1
|
1030
|
+
cmd << index.first
|
885
1031
|
else
|
886
|
-
cmd.merge(
|
1032
|
+
cmd.merge(index)
|
887
1033
|
end
|
888
1034
|
elsif (n = option('index'))
|
889
1035
|
cmd << "HEAD~#{n}"
|
@@ -900,49 +1046,61 @@ module Squared
|
|
900
1046
|
if !message && !amend
|
901
1047
|
return if pass
|
902
1048
|
|
903
|
-
raise_error('
|
1049
|
+
raise_error('missing message', hint: 'GIT_MESSAGE="description"')
|
904
1050
|
end
|
905
1051
|
pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
|
906
1052
|
'--all'
|
907
1053
|
elsif (refs = projectmap(refs)).empty?
|
908
|
-
raise_error
|
1054
|
+
raise_error 'no qualified pathspec'
|
909
1055
|
else
|
910
1056
|
"-- #{refs.join(' ')}"
|
911
1057
|
end
|
912
|
-
format = '%(if)%(HEAD)%(then)%(refname:short)...%(upstream:short)...%(upstream:track)%(end)'
|
913
|
-
branch = nil
|
914
1058
|
origin = nil
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
(
|
919
|
-
next
|
920
|
-
|
921
|
-
branch
|
922
|
-
if
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
1059
|
+
branch = nil
|
1060
|
+
upstream = nil
|
1061
|
+
source(git_output('fetch --no-tags --quiet'), io: true, banner: false)
|
1062
|
+
source(git_output('branch -vv --list'), io: true, banner: false).first.each do |val|
|
1063
|
+
next unless (r = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
|
1064
|
+
|
1065
|
+
branch = r[1]
|
1066
|
+
if r[3]
|
1067
|
+
origin = r[3][%r{^(.+)/#{Regexp.escape(branch)}$}, 1]
|
1068
|
+
else
|
1069
|
+
unless (origin = option('repository', prefix: 'git', ignore: false))
|
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)}, (.+?)\)$/
|
1072
|
+
split_escape($1).each do |val|
|
1073
|
+
next unless val.end_with?("/#{branch}")
|
1074
|
+
|
1075
|
+
origin = val[0, val.size - branch.size - 1]
|
1076
|
+
break
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
end
|
1080
|
+
upstream = true if origin
|
928
1081
|
end
|
929
1082
|
break
|
930
1083
|
end
|
931
|
-
|
932
|
-
branch = "#{branch}:#{origin[(i + 1)..-1]}" unless origin.end_with?("/#{branch}")
|
933
|
-
origin = origin[0..(i - 1)]
|
1084
|
+
raise_error 'work tree is not usable' unless origin && branch
|
934
1085
|
cmd = git_session('commit', option('dry-run') && '--dry-run', options: false)
|
935
|
-
|
1086
|
+
if amend
|
1087
|
+
cmd << '--amend'
|
1088
|
+
else
|
1089
|
+
cmd.delete('--amend')
|
1090
|
+
end
|
936
1091
|
if message
|
937
1092
|
append_message message
|
938
1093
|
elsif flag == :'amend-orig' || option('no-edit')
|
939
1094
|
cmd << '--no-edit'
|
940
1095
|
end
|
941
1096
|
a = git_output 'add', '--verbose'
|
942
|
-
b = git_output 'push'
|
943
|
-
|
1097
|
+
b = git_output 'push', upstream && '--set-upstream'
|
1098
|
+
if dryrun?
|
1099
|
+
a << '--dry-run'
|
1100
|
+
b << '--dry-run'
|
1101
|
+
end
|
944
1102
|
a << pathspec
|
945
|
-
b << '--force
|
1103
|
+
b << '--force' if amend
|
946
1104
|
b << origin << branch
|
947
1105
|
puts if pass
|
948
1106
|
source a
|
@@ -950,8 +1108,24 @@ module Squared
|
|
950
1108
|
source b
|
951
1109
|
end
|
952
1110
|
|
953
|
-
def
|
954
|
-
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)
|
955
1129
|
stdout = false
|
956
1130
|
case flag
|
957
1131
|
when :create
|
@@ -970,7 +1144,7 @@ module Squared
|
|
970
1144
|
return unless ref
|
971
1145
|
|
972
1146
|
if ref.start_with?('^')
|
973
|
-
cmd << '--unset-upstream' << shell_escape(
|
1147
|
+
cmd << '--unset-upstream' << shell_escape(arg[1..-1])
|
974
1148
|
target = nil
|
975
1149
|
stdout = true
|
976
1150
|
else
|
@@ -978,7 +1152,7 @@ module Squared
|
|
978
1152
|
end
|
979
1153
|
ref = nil
|
980
1154
|
when :delete
|
981
|
-
force, list = refs.partition { |val| val
|
1155
|
+
force, list = refs.partition { |val| val.match?(/^[\^~]/) }
|
982
1156
|
force.each do |val|
|
983
1157
|
dr = val[0, 3]
|
984
1158
|
d = dr.include?('^') ? '-D' : '-d'
|
@@ -998,10 +1172,9 @@ module Squared
|
|
998
1172
|
cmd << '--edit-description'
|
999
1173
|
when :current
|
1000
1174
|
cmd << '--show-current'
|
1001
|
-
|
1002
|
-
opts = option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first
|
1175
|
+
when :list
|
1003
1176
|
grep = []
|
1004
|
-
opts.each do |opt|
|
1177
|
+
option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first.each do |opt|
|
1005
1178
|
if opt =~ /^(v+)$/
|
1006
1179
|
cmd << "-#{$1}"
|
1007
1180
|
else
|
@@ -1013,42 +1186,46 @@ module Squared
|
|
1013
1186
|
out, banner, from = source(io: true)
|
1014
1187
|
print_item banner
|
1015
1188
|
ret = write_lines(out, sub: [
|
1016
|
-
{ pat: /^(\*\s+)(\S+)(\s*)$/, styles: :green, index: 2 },
|
1017
|
-
{ 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 }
|
1018
1191
|
])
|
1019
1192
|
list_result(ret, 'branches', from: from)
|
1020
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
|
1021
1215
|
end
|
1022
1216
|
cmd << shell_escape(target) if target
|
1023
1217
|
cmd << shell_escape(ref) if ref
|
1024
1218
|
source(stdout: stdout)
|
1025
1219
|
end
|
1026
1220
|
|
1027
|
-
def restore(flag, opts = [], tree: nil)
|
1028
|
-
cmd = git_session 'restore'
|
1029
|
-
refs = option_sanitize(opts, OPT_GIT[:restore], no: OPT_GIT[:no][:restore]).first
|
1030
|
-
if flag == :source
|
1031
|
-
cmd << '--patch' if refs.empty?
|
1032
|
-
cmd << shell_option('source', tree)
|
1033
|
-
else
|
1034
|
-
cmd << "--#{flag}"
|
1035
|
-
end
|
1036
|
-
if session_arg?('p', 'patch')
|
1037
|
-
option_clear refs
|
1038
|
-
else
|
1039
|
-
append_pathspec(refs, expect: true)
|
1040
|
-
end
|
1041
|
-
source(sync: false, stderr: true)
|
1042
|
-
end
|
1043
|
-
|
1044
1221
|
def show(format, opts = [])
|
1045
|
-
cmd = git_session
|
1222
|
+
cmd, opts = git_session('show', opts: opts)
|
1046
1223
|
if format
|
1047
1224
|
case (val = format.downcase)
|
1048
1225
|
when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
|
1049
1226
|
cmd << basic_option('format', val)
|
1050
1227
|
else
|
1051
|
-
if format
|
1228
|
+
if format.match?(/^t?format:/) || format.include?('%')
|
1052
1229
|
cmd << quote_option('pretty', format)
|
1053
1230
|
else
|
1054
1231
|
opts << format
|
@@ -1066,18 +1243,19 @@ module Squared
|
|
1066
1243
|
end
|
1067
1244
|
|
1068
1245
|
def rev_parse(flag, opts = [], ref: nil, size: nil)
|
1069
|
-
cmd = git_session
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
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
|
1074
1252
|
case flag
|
1075
1253
|
when :commit
|
1076
1254
|
cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
|
1077
|
-
append_commit
|
1255
|
+
append_commit(ref, head: true)
|
1078
1256
|
when :branch
|
1079
1257
|
cmd << '--abbrev-ref'
|
1080
|
-
append_commit
|
1258
|
+
append_commit(ref, head: true)
|
1081
1259
|
else
|
1082
1260
|
args = option_sanitize(opts, OPT_GIT[:rev_parse][flag]).first
|
1083
1261
|
append_value(args, escape: session_arg?('sq-quote'))
|
@@ -1086,7 +1264,7 @@ module Squared
|
|
1086
1264
|
end
|
1087
1265
|
|
1088
1266
|
def ls_remote(flag, opts = [], remote: nil)
|
1089
|
-
cmd = git_session
|
1267
|
+
cmd, opts = git_session('ls-remote', '--refs', opts: opts)
|
1090
1268
|
cmd << "--#{flag}" unless flag == :remote
|
1091
1269
|
grep = option_sanitize(opts, OPT_GIT[:ls_remote]).first
|
1092
1270
|
cmd << shell_quote(remote) if remote
|
@@ -1097,7 +1275,7 @@ module Squared
|
|
1097
1275
|
end
|
1098
1276
|
|
1099
1277
|
def ls_files(flag, opts = [])
|
1100
|
-
git_session
|
1278
|
+
opts = git_session('ls-files', "--#{flag}", opts: opts).last
|
1101
1279
|
grep = option_sanitize(opts, OPT_GIT[:ls_files]).first
|
1102
1280
|
out, banner, from = source(io: true)
|
1103
1281
|
print_item banner
|
@@ -1105,10 +1283,51 @@ module Squared
|
|
1105
1283
|
list_result(ret, 'files', from: from, grep: grep)
|
1106
1284
|
end
|
1107
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
|
+
|
1108
1323
|
def clone?
|
1109
1324
|
ref?(workspace.baseref) && workspace.git_clone?(path, name) ? 1 : false
|
1110
1325
|
end
|
1111
1326
|
|
1327
|
+
def revbuild?
|
1328
|
+
build? && !!workspace.revfile
|
1329
|
+
end
|
1330
|
+
|
1112
1331
|
def enabled?(*, **kwargs)
|
1113
1332
|
super || (kwargs[:base] == false && !!clone?)
|
1114
1333
|
end
|
@@ -1121,7 +1340,7 @@ module Squared
|
|
1121
1340
|
if cmd.respond_to?(:done)
|
1122
1341
|
if io && banner == false
|
1123
1342
|
from = nil
|
1124
|
-
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,}$/) })
|
1125
1344
|
from = :"git:#{from}"
|
1126
1345
|
end
|
1127
1346
|
banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
|
@@ -1133,14 +1352,9 @@ module Squared
|
|
1133
1352
|
format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
|
1134
1353
|
end
|
1135
1354
|
begin
|
1136
|
-
if io
|
1137
|
-
|
1138
|
-
|
1139
|
-
else
|
1140
|
-
[IO.popen(cmd), banner, from]
|
1141
|
-
end
|
1142
|
-
return ret
|
1143
|
-
elsif stdin? ? sync : stdout
|
1355
|
+
return [stdout ? `#{cmd}` : IO.popen(cmd), banner, from] if io
|
1356
|
+
|
1357
|
+
if stdin? ? sync : stdout
|
1144
1358
|
print_item banner unless multiple
|
1145
1359
|
ret = `#{cmd}`
|
1146
1360
|
if !ret.empty?
|
@@ -1148,7 +1362,7 @@ module Squared
|
|
1148
1362
|
elsif banner && stdout && !stdin?
|
1149
1363
|
puts 'Success'
|
1150
1364
|
end
|
1151
|
-
elsif
|
1365
|
+
elsif sync || (!exception && !stderr)
|
1152
1366
|
print_item banner unless multiple
|
1153
1367
|
shell(cmd, exception: exception)
|
1154
1368
|
else
|
@@ -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,34 +1417,52 @@ 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
|
|
1210
1426
|
def list_result(size, type, from: nil, action: 'found', grep: nil)
|
1211
|
-
if
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1427
|
+
if verbose
|
1428
|
+
if size > 0
|
1429
|
+
styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
|
1430
|
+
styles << :bold if styles.size <= 1
|
1431
|
+
puts print_footer("#{size} #{size == 1 ? type.sub(/e?s\z/, '') : type}",
|
1432
|
+
sub: { pat: /\A(\d+)(.+)\z/, styles: styles })
|
1433
|
+
else
|
1434
|
+
puts empty_status("No #{type} were #{action}", 'grep', grep.is_a?(Array) ? case grep.size
|
1435
|
+
when 0
|
1436
|
+
nil
|
1437
|
+
else
|
1438
|
+
grep.join(', ')
|
1439
|
+
end : grep.to_s)
|
1440
|
+
end
|
1223
1441
|
end
|
1224
1442
|
on :last, from
|
1225
1443
|
end
|
1226
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
|
+
|
1227
1460
|
def append_pull(opts, list, target: @session, no: nil, flag: nil, remote: nil)
|
1228
|
-
|
1461
|
+
cmd << '--force' if option('force')
|
1229
1462
|
rsm = append_submodules(target: target)
|
1230
1463
|
out = []
|
1231
1464
|
refspec = []
|
1232
|
-
opts, pat = option_sanitize(opts, remote ? list + ['refspec=
|
1465
|
+
opts, pat = option_sanitize(opts, remote ? list + ['refspec=b'] : list, target: target, no: no)
|
1233
1466
|
opts.each do |opt|
|
1234
1467
|
if opt =~ pat
|
1235
1468
|
case $1
|
@@ -1250,7 +1483,7 @@ module Squared
|
|
1250
1483
|
end
|
1251
1484
|
if remote
|
1252
1485
|
append_value(remote, target: target, delim: true)
|
1253
|
-
if (val = option('refspec',
|
1486
|
+
if (val = option('refspec', strict: true))
|
1254
1487
|
append_value(split_escape(val), target: target)
|
1255
1488
|
else
|
1256
1489
|
target.merge(refspec)
|
@@ -1263,23 +1496,27 @@ module Squared
|
|
1263
1496
|
option_clear(out, target: target, subject: flag.to_s) if flag
|
1264
1497
|
end
|
1265
1498
|
|
1266
|
-
def append_commit(val, target: @session)
|
1267
|
-
val
|
1268
|
-
|
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
|
1269
1506
|
end
|
1270
1507
|
|
1271
1508
|
def append_pathspec(files = [], target: @session, expect: false, parent: false)
|
1272
|
-
if session_arg?('pathspec-from-file'
|
1509
|
+
if session_arg?('pathspec-from-file')
|
1273
1510
|
option_clear files
|
1274
1511
|
else
|
1275
|
-
if files.empty? && (val = option('pathspec'
|
1512
|
+
if files.empty? && (val = option('pathspec'))
|
1276
1513
|
files = split_escape(val)
|
1277
1514
|
end
|
1278
1515
|
files = projectmap(files, parent: parent)
|
1279
1516
|
if !files.empty?
|
1280
|
-
target <<
|
1517
|
+
target << '--' << files.join(' ')
|
1281
1518
|
elsif expect
|
1282
|
-
raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree'
|
1519
|
+
raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree')
|
1283
1520
|
end
|
1284
1521
|
end
|
1285
1522
|
end
|
@@ -1295,34 +1532,32 @@ module Squared
|
|
1295
1532
|
end
|
1296
1533
|
|
1297
1534
|
def append_submodules(from = nil, target: @session)
|
1298
|
-
return unless (val = option('recurse-submodules',
|
1535
|
+
return unless (val = option('recurse-submodules', ignore: false))
|
1299
1536
|
|
1300
1537
|
if from == :clone
|
1301
|
-
|
1302
|
-
|
1303
|
-
target << '--no-recurse-submodules'
|
1304
|
-
when '1', 'true'
|
1305
|
-
target << '--recurse-submodules'
|
1306
|
-
else
|
1307
|
-
projectmap(split_escape(val)).each do |path|
|
1308
|
-
target << basic_option('recurse-submodules', path)
|
1309
|
-
end
|
1538
|
+
projectmap(split_escape(val)).each do |path|
|
1539
|
+
target << basic_option('recurse-submodules', path)
|
1310
1540
|
end
|
1541
|
+
target
|
1311
1542
|
else
|
1312
1543
|
target << case val
|
1313
1544
|
when 'no', '0'
|
1314
1545
|
'--no-recurse-submodules'
|
1315
1546
|
when 'yes', 'on-demand'
|
1316
|
-
"--recurse-submodules=#{val}"
|
1547
|
+
"--recurse-submodules#{from == :reset ? '' : "=#{val}"}"
|
1317
1548
|
else
|
1318
1549
|
'--recurse-submodules'
|
1319
1550
|
end
|
1320
1551
|
end
|
1321
1552
|
end
|
1322
1553
|
|
1323
|
-
def git_session(*cmd, worktree: true, **kwargs)
|
1554
|
+
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
1324
1555
|
dir = worktree ? ["--work-tree=#{shell_quote(path)}", "--git-dir=#{shell_quote(gitpath)}"] : []
|
1325
|
-
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]
|
1326
1561
|
end
|
1327
1562
|
|
1328
1563
|
def git_output(*cmd, **kwargs)
|
@@ -1330,9 +1565,7 @@ module Squared
|
|
1330
1565
|
end
|
1331
1566
|
|
1332
1567
|
def dryrun?(*, target: @session, **)
|
1333
|
-
|
1334
|
-
|
1335
|
-
target.include?('--dry-run')
|
1568
|
+
!!target&.include?('--dry-run')
|
1336
1569
|
end
|
1337
1570
|
|
1338
1571
|
def quiet?(target: @session)
|
@@ -1342,11 +1575,11 @@ module Squared
|
|
1342
1575
|
end
|
1343
1576
|
|
1344
1577
|
def gitpath
|
1345
|
-
basepath
|
1578
|
+
basepath '.git'
|
1346
1579
|
end
|
1347
1580
|
|
1348
1581
|
def commithash(val)
|
1349
|
-
val
|
1582
|
+
val[/^#\{(\h{5,40})\}$/, 1]
|
1350
1583
|
end
|
1351
1584
|
|
1352
1585
|
def threadargs
|