squared 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +106 -1
- data/README.ruby.md +57 -28
- data/lib/squared/common/base.rb +1 -0
- data/lib/squared/common/class.rb +19 -1
- data/lib/squared/common/format.rb +35 -38
- data/lib/squared/common/prompt.rb +66 -3
- data/lib/squared/common/shell.rb +30 -19
- data/lib/squared/common/system.rb +3 -3
- data/lib/squared/common/utils.rb +11 -10
- data/lib/squared/config.rb +4 -5
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +46 -34
- data/lib/squared/workspace/project/base.rb +191 -70
- data/lib/squared/workspace/project/docker.rb +79 -40
- data/lib/squared/workspace/project/git.rb +742 -392
- data/lib/squared/workspace/project/node.rb +35 -51
- data/lib/squared/workspace/project/python.rb +42 -48
- data/lib/squared/workspace/project/ruby.rb +316 -100
- data/lib/squared/workspace/project/support/class.rb +37 -19
- data/lib/squared/workspace/repo.rb +10 -12
- data/lib/squared/workspace/series.rb +11 -7
- data/lib/squared/workspace.rb +2 -9
- metadata +3 -3
@@ -14,20 +14,20 @@ module Squared
|
|
14
14
|
check = ->(proj) { proj.is_a?(Project::Git) && !proj.exclude?(Project::Git.ref) && git_clone?(proj.path) }
|
15
15
|
if uri.is_a?(Array)
|
16
16
|
base = name
|
17
|
-
uri.each { |val| repo << proj if (proj = @project[val.to_s]) && check.(proj) }
|
17
|
+
uri.each { |val| repo << proj if (proj = @project[val.to_s]) && check.call(proj) }
|
18
18
|
elsif uri
|
19
19
|
data[name.to_s] = uri
|
20
20
|
elsif name.is_a?(Enumerable)
|
21
21
|
data = name.to_h
|
22
22
|
elsif name.is_a?(String) && name.match?(GIT_PROTO)
|
23
23
|
base = name
|
24
|
-
@project.each_value { |proj| repo << proj if !proj.parent && check.(proj) }
|
24
|
+
@project.each_value { |proj| repo << proj if !proj.parent && check.call(proj) }
|
25
25
|
else
|
26
26
|
warn log_message(Logger::WARN, name, subject: 'git', hint: 'invalid', pass: true) if warning
|
27
27
|
return self
|
28
28
|
end
|
29
29
|
if base
|
30
|
-
base = base.match?(GIT_PROTO) ? "#{base.chomp('/')}/" : @root
|
30
|
+
base = base.match?(GIT_PROTO) ? "#{base.chomp('/')}/" : @root + base
|
31
31
|
repo.each do |target|
|
32
32
|
if target.is_a?(Project::Git)
|
33
33
|
data[target.localname] = target.project
|
@@ -46,14 +46,14 @@ module Squared
|
|
46
46
|
end
|
47
47
|
unless uri.match?(GIT_PROTO) || Pathname.new(uri).absolute?
|
48
48
|
if uri.start_with?('.')
|
49
|
-
uri = @root
|
49
|
+
uri = @root + uri
|
50
50
|
elsif base
|
51
|
-
uri = base
|
51
|
+
uri = base + uri
|
52
52
|
else
|
53
53
|
next
|
54
54
|
end
|
55
55
|
end
|
56
|
-
key = task_name
|
56
|
+
key = task_name key
|
57
57
|
(GIT_REPO[main] ||= {})[key] = [uri.to_s, opts]
|
58
58
|
(@kind[key] ||= []) << Project::Git
|
59
59
|
end
|
@@ -145,115 +145,117 @@ module Squared
|
|
145
145
|
module Project
|
146
146
|
class Git < Base
|
147
147
|
OPT_GIT = {
|
148
|
-
common: %w[bare
|
149
|
-
no-replace-objects noglob-pathspecs
|
150
|
-
|
151
|
-
|
148
|
+
common: %w[c=q bare glob-pathspecs icase-pathspecs literal-pathspecs no-optional-locks no-pager
|
149
|
+
no-replace-objects noglob-pathspecs paginate config-env=q exec-path=p namespace=p].freeze,
|
150
|
+
add: %w[A|all e|edit f|force ignore-errors ignore-missing ignore-removal i|interactive no-all
|
151
|
+
no-ignore-removal n|dry-run p|patch pathspec-file-nul renormalize sparse u|update v|verbose
|
152
|
+
chmod=b pathspec-from-file=p].freeze,
|
153
|
+
branch: %w[a|all create-reflog i|ignore-case q|quiet r|remotes v|verbose vv abbrev=i color=b column=b
|
154
|
+
contains=b format=q merged=b no-contains=b no-merged=b points-at=b u|set-upstream-to=b sort=q
|
152
155
|
t|track=b].freeze,
|
153
156
|
checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
|
154
|
-
pathspec-file-nul q|quiet
|
155
|
-
t|track=b].freeze,
|
156
|
-
clean: %w[d x X f|force i|interactive n|dry-run q|quiet e|exlcude=q].freeze,
|
157
|
+
pathspec-file-nul q|quiet ours theirs conflict=b orphan=b pathspec-from-file=p t|track=b].freeze,
|
157
158
|
diff: {
|
158
159
|
base: %w[0 1|base 2|ours 3|theirs].freeze,
|
159
160
|
show: %w[s exit-code histogram].freeze
|
160
161
|
}.freeze,
|
161
162
|
fetch: {
|
162
|
-
base: %w[multiple progress P|prune-tags refetch stdin u|update-head-ok
|
163
|
-
|
164
|
-
pull: %w[4 6 n t a|append atomic dry-run f|force k|keep n|negotiate-only prefetch p|prune q|quiet
|
163
|
+
base: %w[multiple progress P|prune-tags refetch stdin u|update-head-ok recurse-submodules-default=b].freeze,
|
164
|
+
pull: %w[4 6 n t a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet
|
165
165
|
set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
|
166
|
-
recurse-submodules=v refmap=q o|server-option=q shallow-exclude=
|
166
|
+
recurse-submodules=v refmap=q o|server-option=q shallow-exclude=b shallow-since=v
|
167
167
|
upload-pack=q].freeze
|
168
168
|
}.freeze,
|
169
|
+
git: {
|
170
|
+
add: %w[N|intent-to-add refresh].freeze,
|
171
|
+
clean: %w[d x X f|force n|dry-run i|interactive q|quiet e|exclude=q].freeze,
|
172
|
+
mv: %w[k f|force n|dry-run v|verbose].freeze,
|
173
|
+
revert: %w[e S=bm? abort continue n|no-commit quit reference skip cleanup=b gpg-sign=b? m|mainline=i
|
174
|
+
s|signoff strategy=b X|strategy-option=b].freeze,
|
175
|
+
rm: %w[r cached f|force n|dry-run ignore-unmatch pathspec-file-nul q|quiet sparse v|verbose
|
176
|
+
pathspec-from-file=p].freeze
|
177
|
+
}.freeze,
|
169
178
|
log: {
|
170
|
-
base: %w[all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
|
179
|
+
base: %w[L=qm all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
|
171
180
|
cherry-pick clear-decorations date-order dense do-walk exclude-first-parent-only E|extended-regexp
|
172
181
|
first-parent F|fixed-strings follow full-diff full-history ignore-missing invert-grep left-only
|
173
|
-
|
182
|
+
log-size merge no-max-parents no-min-parents not P|perl-regexp reflog i|regexp-ignore-case
|
174
183
|
remove-empty reverse right-only simplify-by-decoration simplify-merges single-worktree show-pulls
|
175
184
|
source sparse stdin topo-order g|walk-reflogs after=q ancestry-path=b? author=q before=q
|
176
185
|
branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
|
177
|
-
exclude-hidden=b
|
178
|
-
|
186
|
+
exclude-hidden=b glob=q grep=q grep-reflog=q n|max-count=i max-parents=i min-parents=i no-walk=b?
|
187
|
+
remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
|
179
188
|
format: %w[t children combined-all-paths oneline left-right no-diff-merges parents relative-date
|
180
|
-
show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=
|
189
|
+
show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=b pretty=q?
|
181
190
|
show-linear-break=q?].freeze,
|
182
|
-
diff: %w[p R u z l=
|
183
|
-
W|function-context w|ignore-all-space ignore-blank-lines
|
184
|
-
b|ignore-space-change D|irreversible-delete graph
|
185
|
-
name-status no-color-moved-ws no-prefix no-renames numstat
|
186
|
-
pickaxe-all pickaxe-regex raw shortstat summary a|text
|
187
|
-
color=b color-moved=b color-moved-ws=b color-words=q?
|
188
|
-
dirstat-by-file=
|
189
|
-
|
190
|
-
output-indicator-context=q output-indicator-new=q output-indicator-old=q
|
191
|
-
skip-to=p src-prefix=q stat=
|
192
|
-
word-diff=b? word-diff-regex=q ws-error-
|
191
|
+
diff: %w[p R u z B=bm? C=bm? l=im G=qm I=qm M=bm? O=qm S=qm U=im binary check compact-summary cumulative
|
192
|
+
find-copies-harder full-index W|function-context w|ignore-all-space ignore-blank-lines
|
193
|
+
ignore-cr-at-eol ignore-space-at-eol b|ignore-space-change D|irreversible-delete graph
|
194
|
+
ita-invisible-in-index minimal name-only name-status no-color-moved-ws no-prefix no-renames numstat
|
195
|
+
patch-with-raw patch-with-stat patience pickaxe-all pickaxe-regex raw shortstat summary a|text
|
196
|
+
abbrev=i? anchored=q break-rewrites=b? color=b color-moved=b color-moved-ws=b color-words=q?
|
197
|
+
diff-algorithm=b diff-filter=e? X|dirstat=b? dirstat-by-file=b? dst-prefix=q find-copies=i?
|
198
|
+
find-object=b find-renames=b? ignore-matching-lines=q ignore-submodules=b? inter-hunk-context=i
|
199
|
+
line-prefix=q output=p output-indicator-context=q output-indicator-new=q output-indicator-old=q
|
200
|
+
relative=p rotate-to=p skip-to=p src-prefix=q stat=b? stat-count=i stat-width=i stat-name-width=i
|
201
|
+
submodule=b? unified=i word-diff=b? word-diff-regex=q ws-error-highlight=b].freeze
|
193
202
|
}.freeze,
|
194
|
-
ls_files: %w[z debug deduplicate directory eol error-unmatch exclude-standard full-name
|
195
|
-
no-empty-directory recurse-submodules sparse s|stage u|unmerged abbrev=i x|exclude=q
|
203
|
+
ls_files: %w[f t v z debug deduplicate directory eol error-unmatch exclude-standard full-name i|ignored
|
204
|
+
k|killed no-empty-directory recurse-submodules sparse s|stage u|unmerged abbrev=i x|exclude=q
|
196
205
|
X|exclude-from=p exclude-per-directory=p format=q with-tree=q].freeze,
|
197
|
-
ls_remote: %w[exit-code get-url q|quiet o|server-option=q
|
198
|
-
|
199
|
-
|
206
|
+
ls_remote: %w[exit-code get-url q|quiet symref o|server-option=q sort=q upload-pack=q].freeze,
|
207
|
+
merge: %w[e n S=bm? allow-unrelated-histories ff-only m=q q|quiet v|verbose cleanup=b F|file=p gpg-sign=b?
|
208
|
+
into-name=b log=i s|strategy=b X|strategy-option=b].freeze,
|
209
|
+
pull: %w[e n S=bm? allow-unrelated-histories ff-only cleanup=b gpg-sign=b? log=i r|rebase=v? s|strategy=b
|
200
210
|
X|strategy-option=b].freeze,
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
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,
|
211
|
+
rebase: %w[n C=im S=bm? allow-empty-message apply committer-date-is-author-date edit-todo empty=b
|
212
|
+
f|force-rebase ignore-date ignore-whitespace i|interactive keep-base m|merge no-ff q|quiet quit
|
213
|
+
reset-author-date root show-current-patch signoff v|verbose empty=b x|exec=q gpg-sign=b? onto=b
|
214
|
+
r|rebase-merges=b s|strategy=b X|strategy-option=b whitespace=b].freeze,
|
207
215
|
reset: %w[N pathspec-file-nul q|quiet pathspec-from-file=p].freeze,
|
208
|
-
restore: %w[ignore-
|
209
|
-
W|worktree conflict=b pathspec-from-file=p s|source=
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
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,
|
219
|
-
parseopt: %w[keep-dashdash stop-at-non-option stuck-long].freeze
|
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,
|
216
|
+
restore: %w[ignore-skip-worktree-bits ignore-unmerged m|merge ours p|patch pathspec-file-nul q|quiet S|staged
|
217
|
+
theirs W|worktree conflict=b pathspec-from-file=p s|source=b].freeze,
|
218
|
+
rev_parse: %w[absolute-git-dir all git-common-dir git-dir is-bare-repository is-inside-git-dir
|
219
|
+
is-inside-work-tree is-shallow-repository local-env-vars no-revs not q|quiet revs-only
|
220
|
+
shared-index-path show-cdup show-prefix show-superproject-working-tree show-toplevel sq sq-quote
|
221
|
+
symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q branches=q? default=q
|
222
|
+
disambiguate=b exclude=q exclude-hidden=b git-path=p glob=q path-format=b? prefix=q remotes=q?
|
223
|
+
resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
|
223
224
|
show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
|
224
225
|
expand-tabs=i notes=q show-notes=q?].freeze,
|
225
226
|
stash: {
|
226
227
|
common: %w[q|quiet].freeze,
|
227
|
-
push: %w[a|all u|include-untracked k|keep-index no-keep-index
|
228
|
-
pathspec-from-file=p].freeze,
|
228
|
+
push: %w[a|all u|include-untracked k|keep-index no-keep-index no-include-untracked pathspec-file-nul
|
229
|
+
p|patch S|staged m|message=q pathspec-from-file=p].freeze,
|
229
230
|
pop: %w[index].freeze,
|
230
231
|
apply: %w[index].freeze
|
231
232
|
}.freeze,
|
232
|
-
status: %w[
|
233
|
-
tag: %w[create-reflog column=b contains=b? format=q merged=b?
|
234
|
-
sort=q].freeze,
|
233
|
+
status: %w[u|ignore-submodules=bm? ignored=b? untracked-files=b?],
|
234
|
+
tag: %w[n=im cleanup=b create-reflog i|ignore-case color=b? column=b contains=b? format=q merged=b?
|
235
|
+
no-contains=b? no-merged=b? points-at=q sort=q].freeze,
|
235
236
|
no: {
|
237
|
+
branch: %w[color color-moved column track].freeze,
|
238
|
+
checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
|
236
239
|
fetch: {
|
237
240
|
base: %w[auto-gc auto-maintenance write-commit-graph write-fetch-head].freeze,
|
238
241
|
pull: %w[all ipv4 ipv6 recurse-submodules show-forced-updates tags].freeze
|
239
242
|
},
|
240
243
|
log: {
|
241
244
|
base: %w[decorate mailmap merges use-mailmap].freeze,
|
242
|
-
|
243
|
-
|
245
|
+
diff: %w[color color-moved ext-diff indent-heuristic patch relative rename-empty textconv].freeze,
|
246
|
+
show: %w[abbrev-commit expand-tabs notes].freeze
|
244
247
|
}.freeze,
|
245
|
-
|
246
|
-
tag: %w[column].freeze,
|
247
|
-
branch: %w[color-moved column color track].freeze,
|
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
|
248
|
+
merge: %w[autostash edit ff gpg-sign log overwrite-ignore progress rerere-autoupdate signoff squash stat
|
250
249
|
verify verify-signatures].freeze,
|
251
|
-
|
252
|
-
|
250
|
+
pull: %w[autostash commit edit gpg-sign ff log rebase signoff squash stat verify verify-signatures].freeze,
|
251
|
+
rebase: %w[autosquash autostash fork-point gpg-sign keep-empty reapply-cherry-picks rebase-merges
|
252
|
+
rerere-autoupdate reschedule-failed-exec stat update-refs verify].freeze,
|
253
253
|
reset: %w[refresh].freeze,
|
254
254
|
restore: %w[overlay progress recurse-submodules].freeze,
|
255
|
+
rev_parse: %w[flags].freeze,
|
255
256
|
revert: %w[edit gpg-sign rerere-autoupdate].freeze,
|
256
|
-
show: %w[standard-notes].freeze
|
257
|
+
show: %w[standard-notes].freeze,
|
258
|
+
tag: %w[column].freeze
|
257
259
|
}.freeze
|
258
260
|
}.freeze
|
259
261
|
VAL_GIT = {
|
@@ -272,7 +274,7 @@ module Squared
|
|
272
274
|
include Rake::DSL
|
273
275
|
|
274
276
|
def populate(ws, **)
|
275
|
-
return if ws.series
|
277
|
+
return if ws.series.exclude?(:pull, true)
|
276
278
|
|
277
279
|
namespace(name = ws.task_name('git')) do
|
278
280
|
all = ws.task_join(name, 'all')
|
@@ -297,7 +299,7 @@ module Squared
|
|
297
299
|
end
|
298
300
|
|
299
301
|
def tasks
|
300
|
-
%i[pull rebase fetch clone stash status branch revbuild].freeze
|
302
|
+
%i[pull rebase autostash fetch clone stash status branch revbuild].freeze
|
301
303
|
end
|
302
304
|
|
303
305
|
def config?(val)
|
@@ -308,23 +310,24 @@ module Squared
|
|
308
310
|
end
|
309
311
|
|
310
312
|
subtasks({
|
311
|
-
'branch' => %i[create
|
313
|
+
'branch' => %i[create track delete move copy list current].freeze,
|
312
314
|
'checkout' => %i[commit branch track detach path].freeze,
|
313
|
-
'commit' => %i[add all amend amend-orig].freeze,
|
315
|
+
'commit' => %i[add all amend amend-orig fixup].freeze,
|
314
316
|
'diff' => %i[head branch files view between contain].freeze,
|
315
317
|
'fetch' => %i[origin remote].freeze,
|
316
|
-
'files' => %i[cached modified deleted others
|
317
|
-
'git' => %i[clean mv revert rm].freeze,
|
318
|
+
'files' => %i[cached modified deleted others].freeze,
|
319
|
+
'git' => %i[add clean mv revert rm].freeze,
|
318
320
|
'log' => %i[view between contain].freeze,
|
319
321
|
'merge' => %i[commit no-commit send].freeze,
|
320
322
|
'pull' => %i[origin remote].freeze,
|
321
323
|
'rebase' => %i[branch onto send].freeze,
|
322
324
|
'refs' => %i[heads tags remote].freeze,
|
323
325
|
'reset' => %i[commit index patch mode].freeze,
|
324
|
-
'restore' => %i[staged worktree].freeze,
|
325
|
-
'rev' => %i[commit
|
326
|
+
'restore' => %i[source staged worktree].freeze,
|
327
|
+
'rev' => %i[commit build output].freeze,
|
326
328
|
'show' => %i[format oneline textconv].freeze,
|
327
329
|
'stash' => %i[push pop apply drop clear list].freeze,
|
330
|
+
'switch' => %i[create detach merge].freeze,
|
328
331
|
'tag' => %i[add sign delete list].freeze
|
329
332
|
})
|
330
333
|
|
@@ -342,7 +345,7 @@ module Squared
|
|
342
345
|
return unless ref?(Git.ref)
|
343
346
|
|
344
347
|
namespace name do
|
345
|
-
|
348
|
+
Git.subtasks do |action, flags|
|
346
349
|
next if @pass.include?(action)
|
347
350
|
|
348
351
|
namespace action do
|
@@ -350,7 +353,7 @@ module Squared
|
|
350
353
|
case action
|
351
354
|
when 'pull', 'fetch'
|
352
355
|
if flag == :remote
|
353
|
-
format_desc
|
356
|
+
format_desc action, flag, 'remote,opts*'
|
354
357
|
task flag, [:remote] do |_, args|
|
355
358
|
remote = param_guard(action, flag, args: args, key: :remote)
|
356
359
|
__send__(action, flag, args.extras, remote: remote)
|
@@ -366,13 +369,39 @@ module Squared
|
|
366
369
|
when :all
|
367
370
|
format_desc action, flag, 'message?'
|
368
371
|
task flag, [:message] do |_, args|
|
369
|
-
commit(flag, message: args.
|
372
|
+
commit(flag, message: args.message)
|
370
373
|
end
|
371
374
|
else
|
372
|
-
format_desc
|
375
|
+
format_desc(action, flag, 'pathspec+', before: flag == :add ? 'opts*' : nil)
|
373
376
|
task flag do |_, args|
|
374
|
-
|
375
|
-
|
377
|
+
if flag == :fixup
|
378
|
+
ref, squash, pick = choice_commit(accept: [['Auto squash?', true]], reflog: false,
|
379
|
+
values: ['Pick [amend|reword]'])
|
380
|
+
pick = case pick&.downcase
|
381
|
+
when 'a', 'amend'
|
382
|
+
'amend'
|
383
|
+
when 'r', 'reword'
|
384
|
+
'reword'
|
385
|
+
end
|
386
|
+
if squash
|
387
|
+
found = false
|
388
|
+
git_spawn(git_output('log --format=%h'), stdout: false).each do |val|
|
389
|
+
if found
|
390
|
+
squash = val.chomp
|
391
|
+
break
|
392
|
+
end
|
393
|
+
found = val.chomp == ref
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
refs = pick == 'reword' ? [] : param_guard(action, flag, args: args.to_a)
|
398
|
+
if flag == :add
|
399
|
+
opts = refs
|
400
|
+
refs = []
|
401
|
+
else
|
402
|
+
opts = []
|
403
|
+
end
|
404
|
+
commit(flag, opts, refs: refs, ref: ref, squash: squash, pick: pick)
|
376
405
|
end
|
377
406
|
end
|
378
407
|
when 'tag'
|
@@ -385,61 +414,103 @@ module Squared
|
|
385
414
|
when :delete
|
386
415
|
format_desc action, flag, 'name+'
|
387
416
|
task flag do |_, args|
|
388
|
-
refs =
|
389
|
-
|
417
|
+
refs = args.to_a
|
418
|
+
if refs.empty?
|
419
|
+
refs = choice_refs('Choose a tag', 'tags', multiple: true, accept: 'Delete?', series: true)
|
420
|
+
remote = choice_remote
|
421
|
+
end
|
422
|
+
tag(flag, refs: refs, remote: remote)
|
390
423
|
end
|
391
424
|
when :add, :sign
|
392
|
-
format_desc action, flag, 'name,message?,commit?'
|
393
|
-
task flag, [:name, :message, :commit] do |_, args|
|
394
|
-
name =
|
395
|
-
|
425
|
+
format_desc action, flag, 'name,message?,commit?,remote?'
|
426
|
+
task flag, [:name, :message, :commit, :remote] do |_, args|
|
427
|
+
if (name = args.name)
|
428
|
+
message = args.message
|
429
|
+
commit = commithead args.commit
|
430
|
+
remote = args.remote
|
431
|
+
else
|
432
|
+
commit, name, message = choice_commit(values: [['Enter tag name', true], 'Enter message'],
|
433
|
+
series: true, reflog: false)
|
434
|
+
remote = choice_remote
|
435
|
+
end
|
436
|
+
ret = tag(flag, refs: [name], message: message, commit: commit, remote: remote)
|
437
|
+
print_success if success?(ret) && !remote
|
396
438
|
end
|
397
439
|
end
|
398
440
|
when 'stash'
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
end
|
441
|
+
format_desc(action, flag, 'opts*', after: case flag
|
442
|
+
when :push then 'pathspec*'
|
443
|
+
when :list then nil
|
444
|
+
else 'commit?' end)
|
404
445
|
task flag do |_, args|
|
405
446
|
stash flag, args.to_a
|
406
447
|
end
|
407
448
|
when 'log', 'diff'
|
408
449
|
case flag
|
409
450
|
when :view, :between, :contain
|
410
|
-
|
411
|
-
|
451
|
+
view = flag == :view
|
452
|
+
if view && action == 'log'
|
453
|
+
format_desc action, flag, '(^)commit*|:,opts*,ref?,pathspec*'
|
412
454
|
task flag do |_, args|
|
413
|
-
|
414
|
-
args.
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
455
|
+
args = args.to_a
|
456
|
+
if args.first == ':'
|
457
|
+
args.shift
|
458
|
+
index = choice_commit(multiple: true)
|
459
|
+
else
|
460
|
+
index = []
|
461
|
+
args.each do |val|
|
462
|
+
if matchhead(val)
|
463
|
+
index << commithead(val)
|
464
|
+
elsif (sha = commithash(val))
|
465
|
+
index << sha
|
466
|
+
elsif val.start_with?('^')
|
467
|
+
index << shell_quote(val)
|
468
|
+
else
|
469
|
+
break
|
470
|
+
end
|
421
471
|
end
|
472
|
+
args = args.drop(index.size)
|
422
473
|
end
|
423
|
-
|
474
|
+
log!(flag, args, index: index)
|
424
475
|
end
|
425
476
|
else
|
426
|
-
format_desc action, flag, 'commit1,commit2,pathspec
|
477
|
+
format_desc action, flag, 'commit1,commit2,opts*,pathspec*'
|
427
478
|
task flag, [:commit1, :commit2] do |_, args|
|
428
|
-
commit1 =
|
429
|
-
|
430
|
-
|
479
|
+
commit1 = commithead args.commit1
|
480
|
+
if commit1
|
481
|
+
commit2 = commithead param_guard(action, flag, args: args, key: :commit2)
|
482
|
+
args = args.extras.to_a
|
483
|
+
range = [commit1, commit2]
|
484
|
+
else
|
485
|
+
range, opts, refs = choice_commit(multiple: view ? true : 2, values: %w[Options Pathspec])
|
486
|
+
range = range.reverse
|
487
|
+
args = OptionPartition.strip(opts)
|
488
|
+
args.concat(refs.shellsplit) if refs
|
489
|
+
end
|
490
|
+
__send__(action == 'log' ? :log! : :diff, flag, args, range: range)
|
431
491
|
end
|
432
492
|
end
|
433
493
|
when :head
|
434
|
-
format_desc action, flag, 'commit
|
494
|
+
format_desc action, flag, 'commit*|:,opts*,pathspec*'
|
435
495
|
task flag do |_, args|
|
436
|
-
|
437
|
-
args.
|
438
|
-
|
439
|
-
|
440
|
-
|
496
|
+
args = args.to_a
|
497
|
+
if args.first == ':'
|
498
|
+
args.shift
|
499
|
+
index = choice_commit(multiple: true)
|
500
|
+
else
|
501
|
+
index = []
|
502
|
+
args.each do |val|
|
503
|
+
if matchhead(val)
|
504
|
+
index << commithead(val)
|
505
|
+
elsif (sha = commithash(val))
|
506
|
+
index << sha
|
507
|
+
else
|
508
|
+
break
|
509
|
+
end
|
510
|
+
end
|
511
|
+
args = args.drop(index.size)
|
441
512
|
end
|
442
|
-
diff(flag, args
|
513
|
+
diff(flag, args, index: index)
|
443
514
|
end
|
444
515
|
when :branch
|
445
516
|
format_desc action, flag, 'name,opts*,pathspec*'
|
@@ -460,42 +531,61 @@ module Squared
|
|
460
531
|
when :branch
|
461
532
|
format_desc action, flag, 'name,create?=[bB],commit?,detach?=d'
|
462
533
|
task flag, [:name, :create, :commit, :detach] do |_, args|
|
463
|
-
branch =
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
create
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
534
|
+
if (branch = args.name)
|
535
|
+
branch = param_guard(action, flag, args: args, key: :name)
|
536
|
+
create = args.create
|
537
|
+
if args.commit == 'd'
|
538
|
+
detach = 'd'
|
539
|
+
commit = nil
|
540
|
+
elsif create == 'd'
|
541
|
+
create = nil
|
542
|
+
commit = nil
|
543
|
+
detach = 'd'
|
544
|
+
elsif create && create.size > 1
|
545
|
+
commit = commithead create
|
546
|
+
create = nil
|
547
|
+
detach = args.commit
|
548
|
+
else
|
549
|
+
detach = args.detach
|
550
|
+
commit = commithead args.commit
|
551
|
+
end
|
552
|
+
param_guard(action, flag, args: { create: create }, key: :create, pat: /\Ab\z/i) if create
|
476
553
|
else
|
477
|
-
|
478
|
-
commit = args.commit
|
554
|
+
branch = choice_refs 'Choose a branch to switch'
|
479
555
|
end
|
480
|
-
param_guard(action, flag, args: { create: create }, key: :create, pat: /\Ab\z/i) if create
|
481
556
|
checkout(flag, branch: branch, create: create, commit: commit, detach: detach)
|
482
557
|
end
|
483
558
|
when :track
|
484
559
|
format_desc action, flag, 'origin,(^)name?'
|
485
560
|
task flag, [:origin, :name] do |_, args|
|
486
|
-
origin =
|
487
|
-
|
561
|
+
if (origin = args.origin)
|
562
|
+
branch = args.name
|
563
|
+
else
|
564
|
+
origin, branch = choice_refs('Choose a remote', 'remotes', values: ['Enter branch name'])
|
565
|
+
end
|
566
|
+
checkout(flag, branch: branch, origin: origin)
|
488
567
|
end
|
489
568
|
when :commit
|
490
|
-
format_desc action, flag, '
|
569
|
+
format_desc action, flag, 'ref,opts*'
|
491
570
|
task flag, [:commit] do |_, args|
|
492
|
-
commit =
|
493
|
-
|
571
|
+
commit = commithead args.commit
|
572
|
+
if commit
|
573
|
+
args = args.extras
|
574
|
+
else
|
575
|
+
commit, opts = choice_commit(values: ['Options'])
|
576
|
+
args = OptionPartition.strip(opts)
|
577
|
+
end
|
578
|
+
checkout(flag, args, commit: commit)
|
494
579
|
end
|
495
580
|
when :detach
|
496
|
-
format_desc action, flag, '
|
581
|
+
format_desc action, flag, 'ref?'
|
497
582
|
task flag, [:commit] do |_, args|
|
498
|
-
|
583
|
+
commit = commithead args.commit
|
584
|
+
unless commit
|
585
|
+
commit, merge = choice_commit(values: ['Merge? [y|N]'])
|
586
|
+
merge = merge&.upcase == 'Y'
|
587
|
+
end
|
588
|
+
checkout(flag, commit: commit, merge: merge)
|
499
589
|
end
|
500
590
|
when :path
|
501
591
|
format_desc action, flag, 'opts*,pathspec*'
|
@@ -506,27 +596,46 @@ module Squared
|
|
506
596
|
when 'branch'
|
507
597
|
case flag
|
508
598
|
when :create
|
509
|
-
format_desc action, flag, 'name,ref?=HEAD'
|
599
|
+
format_desc action, flag, 'name,ref?=HEAD|:'
|
510
600
|
task flag, [:name, :ref] do |_, args|
|
511
601
|
target = param_guard(action, flag, args: args, key: :name)
|
512
|
-
|
602
|
+
ref = commithead args.ref
|
603
|
+
ref, remote = choice_refs('Choose a remote', 'remotes', accept: [['Push?', true]]) if ref == ':'
|
604
|
+
branch(flag, target: target, ref: ref, remote: remote)
|
513
605
|
end
|
514
|
-
when :
|
515
|
-
format_desc
|
606
|
+
when :track
|
607
|
+
format_desc action, flag, '(^~)upstream?,name?'
|
516
608
|
task flag, [:upstream, :name] do |_, args|
|
517
|
-
|
518
|
-
|
609
|
+
if (ref = args.upstream)
|
610
|
+
target = args.name
|
611
|
+
if ref.start_with?('~')
|
612
|
+
ref = ref[1..-1]
|
613
|
+
remote = true
|
614
|
+
end
|
615
|
+
else
|
616
|
+
ref, remote, target = choice_refs('Choose a remote', 'remotes', accept: [['Push?', true]],
|
617
|
+
values: ['Enter branch name'])
|
618
|
+
end
|
619
|
+
branch(flag, target: target, ref: ref, remote: remote)
|
519
620
|
end
|
520
621
|
when :delete
|
521
|
-
format_desc action, flag, '(^~)name
|
622
|
+
format_desc action, flag, '(^~)name*,:?'
|
522
623
|
task flag do |_, args|
|
523
|
-
refs =
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
624
|
+
refs = args.to_a
|
625
|
+
if refs.empty? || (r = refs.last == ':')
|
626
|
+
accept = ['Delete?']
|
627
|
+
accept << ['Force?', true] unless r
|
628
|
+
remote = choice_refs('Choose a branch', r ? 'remotes' : 'heads', multiple: true,
|
629
|
+
accept: accept)
|
630
|
+
if r
|
631
|
+
refs.pop
|
632
|
+
else
|
633
|
+
refs = remote.first
|
634
|
+
refs.map! { |val| "^#{val}" } if remote[1]
|
635
|
+
remote = nil
|
636
|
+
end
|
637
|
+
end
|
638
|
+
branch(flag, refs: refs, remote: remote)
|
530
639
|
end
|
531
640
|
when :list
|
532
641
|
format_desc action, flag, 'opts*,pattern*'
|
@@ -541,17 +650,55 @@ module Squared
|
|
541
650
|
else
|
542
651
|
format_desc action, flag, 'branch,oldbranch?'
|
543
652
|
task flag, [:branch, :oldbranch] do |_, args|
|
544
|
-
branch =
|
545
|
-
|
653
|
+
if (branch = args.branch)
|
654
|
+
oldbranch = args.oldbranch
|
655
|
+
else
|
656
|
+
oldbranch, branch = choice_refs("Choose a branch to #{flag}",
|
657
|
+
values: [['Enter new branch name', true]])
|
658
|
+
end
|
659
|
+
branch(flag, refs: [oldbranch, branch])
|
660
|
+
end
|
661
|
+
end
|
662
|
+
when 'switch'
|
663
|
+
case flag
|
664
|
+
when :create
|
665
|
+
format_desc action, flag, '(^)name,ref?=HEAD|:'
|
666
|
+
task flag, [:name, :commit] do |_, args|
|
667
|
+
target = param_guard(action, flag, args: args, key: :name)
|
668
|
+
commit = commithead args.commit
|
669
|
+
commit, track = choice_commit(values: ['Track? [Y|n]'], force: false) if commit == ':'
|
670
|
+
switch(flag, target: target, commit: commit, track: track)
|
671
|
+
end
|
672
|
+
when :detach
|
673
|
+
format_desc action, flag, 'ref?=HEAD'
|
674
|
+
task flag, [:commit] do |_, args|
|
675
|
+
commit = commithead(args.commit) || choice_commit(force: false)
|
676
|
+
switch(flag, commit: commit)
|
677
|
+
end
|
678
|
+
when :merge
|
679
|
+
format_desc action, flag, 'branch?'
|
680
|
+
task flag, [:branch] do |_, args|
|
681
|
+
commit = args.branch || choice_refs('Choose a branch')
|
682
|
+
switch(flag, commit: commit)
|
546
683
|
end
|
547
684
|
end
|
548
685
|
when 'reset'
|
549
686
|
case flag
|
550
687
|
when :commit
|
551
|
-
format_desc action, flag, '
|
688
|
+
format_desc action, flag, 'ref|:,opts*'
|
552
689
|
task flag, [:commit] do |_, args|
|
553
|
-
commit =
|
554
|
-
|
690
|
+
commit = commithead args.commit
|
691
|
+
if commit && commit != ':'
|
692
|
+
args = args.extras
|
693
|
+
else
|
694
|
+
commit, mode = choice_commit(values: ['Mode [mixed|soft|hard|N]'])
|
695
|
+
args = args.extras.to_a.concat(case mode&.downcase
|
696
|
+
when 'h', 'hard' then ['hard']
|
697
|
+
when 's', 'soft' then ['soft']
|
698
|
+
when 'n', 'N' then ['mixed', 'N']
|
699
|
+
else ['mixed'] end)
|
700
|
+
end
|
701
|
+
print_success if success?(reset(flag, args, commit: commit))
|
555
702
|
end
|
556
703
|
when :index
|
557
704
|
format_desc action, flag, 'opts*,pathspec*'
|
@@ -559,15 +706,18 @@ module Squared
|
|
559
706
|
reset flag, args.to_a
|
560
707
|
end
|
561
708
|
when :mode
|
562
|
-
format_desc action, flag, 'mode,ref?=HEAD'
|
709
|
+
format_desc action, flag, 'mode,ref?=HEAD|:'
|
563
710
|
task flag, [:mode, :ref] do |_, args|
|
564
711
|
mode = param_guard(action, flag, args: args, key: :mode)
|
565
|
-
|
712
|
+
ref = commithead args.ref
|
713
|
+
ref = choice_commit(reflog: false) if ref == ':'
|
714
|
+
reset(flag, mode: mode, ref: ref)
|
566
715
|
end
|
567
716
|
when :patch
|
568
|
-
format_desc action, flag, 'ref
|
717
|
+
format_desc action, flag, 'ref?=HEAD|:,pathspec*'
|
569
718
|
task flag, [:ref] do |_, args|
|
570
|
-
ref =
|
719
|
+
ref = commithead args.ref
|
720
|
+
ref = choice_commit(reflog: false) unless ref && ref != ':'
|
571
721
|
reset(flag, refs: args.extras, ref: ref)
|
572
722
|
end
|
573
723
|
end
|
@@ -576,7 +726,7 @@ module Squared
|
|
576
726
|
when :oneline
|
577
727
|
format_desc action, flag, 'opts*,object*'
|
578
728
|
task flag do |_, args|
|
579
|
-
show flag, args.to_a
|
729
|
+
show flag, args.to_a
|
580
730
|
end
|
581
731
|
when :format
|
582
732
|
format_desc action, flag, 'format?,opts*,object*'
|
@@ -593,23 +743,42 @@ module Squared
|
|
593
743
|
when 'rebase', 'merge'
|
594
744
|
case flag
|
595
745
|
when :branch
|
596
|
-
format_desc action, flag, '
|
597
|
-
task flag do |_, args|
|
598
|
-
|
599
|
-
|
746
|
+
format_desc action, flag, 'upstream,branch?=HEAD,opts*'
|
747
|
+
task flag, [:upstream] do |_, args|
|
748
|
+
if (upstream = args.upstream)
|
749
|
+
args = args.extras
|
750
|
+
else
|
751
|
+
upstream, opts = choice_refs('Choose upstream branch', values: ['Options'])
|
752
|
+
args = OptionPartition.strip(opts)
|
753
|
+
end
|
754
|
+
rebase(flag, args, upstream: upstream)
|
600
755
|
end
|
601
756
|
when :onto
|
602
|
-
format_desc action, flag, '
|
757
|
+
format_desc action, flag, 'ref,upstream,branch?=HEAD'
|
603
758
|
task flag, [:commit, :upstream, :branch] do |_, args|
|
604
|
-
commit =
|
605
|
-
|
606
|
-
|
759
|
+
commit = commithead args.commit
|
760
|
+
if commit
|
761
|
+
upstream = param_guard(action, flag, args: args, key: :upstream)
|
762
|
+
branch = args.branch
|
763
|
+
args = []
|
764
|
+
else
|
765
|
+
commit = choice_refs 'Choose "onto" branch'
|
766
|
+
target, opts = choice_commit(multiple: 2, values: ['Options'], reflog: false)
|
767
|
+
branch, upstream = target
|
768
|
+
args = OptionPartition.strip(opts)
|
769
|
+
end
|
770
|
+
rebase(flag, args, commit: commit, upstream: upstream, branch: branch)
|
607
771
|
end
|
608
772
|
when :commit, :'no-commit'
|
609
|
-
format_desc action, flag, '
|
773
|
+
format_desc action, flag, 'refs+,opts*'
|
610
774
|
task flag do |_, args|
|
611
|
-
args =
|
612
|
-
|
775
|
+
args = args.to_a
|
776
|
+
if args.empty?
|
777
|
+
accept = "Merge with #{`#{git_output('branch --show-current')}`.chomp}?"
|
778
|
+
branch, opts = choice_refs('Choose a branch', values: ['Options'], accept: accept)
|
779
|
+
args = OptionPartition.strip(opts)
|
780
|
+
end
|
781
|
+
merge(flag, args, branch: branch)
|
613
782
|
end
|
614
783
|
when :send
|
615
784
|
format_desc(action, flag, VAL_GIT[action.to_sym][:send], arg: nil)
|
@@ -624,25 +793,20 @@ module Squared
|
|
624
793
|
when :commit
|
625
794
|
format_desc action, flag, 'ref?=HEAD,size?'
|
626
795
|
task flag, [:ref, :size] do |_, args|
|
627
|
-
ref = args.ref
|
796
|
+
ref = commithead args.ref
|
628
797
|
size = args.size
|
629
|
-
if !size && ref.to_i
|
798
|
+
if !size && ref.to_i.between?(1, 40)
|
630
799
|
size = ref
|
631
800
|
ref = nil
|
632
801
|
end
|
633
802
|
rev_parse(flag, ref: ref, size: size)
|
634
803
|
end
|
635
|
-
when :branch
|
636
|
-
format_desc action, flag, 'ref?=HEAD'
|
637
|
-
task flag, [:ref] do |_, args|
|
638
|
-
rev_parse(flag, ref: args.ref)
|
639
|
-
end
|
640
804
|
when :build
|
641
805
|
format_desc action, flag, OPT_GIT[:status]
|
642
806
|
task flag do |_, args|
|
643
807
|
revbuild flag, args.to_a
|
644
808
|
end
|
645
|
-
|
809
|
+
when :output
|
646
810
|
format_desc action, flag, 'opts*,args*'
|
647
811
|
task flag do |_, args|
|
648
812
|
rev_parse flag, args.to_a
|
@@ -650,10 +814,9 @@ module Squared
|
|
650
814
|
end
|
651
815
|
when 'refs', 'files'
|
652
816
|
if flag == :remote
|
653
|
-
format_desc action, flag, 'remote
|
817
|
+
format_desc action, flag, 'remote?,opts*,pattern*'
|
654
818
|
task flag, [:remote] do |_, args|
|
655
|
-
|
656
|
-
ls_remote(flag, args.extras, remote: remote)
|
819
|
+
ls_remote(flag, args.extras, remote: args.remote)
|
657
820
|
end
|
658
821
|
else
|
659
822
|
format_desc action, flag, 'opts*,pattern*'
|
@@ -661,17 +824,57 @@ module Squared
|
|
661
824
|
__send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
|
662
825
|
end
|
663
826
|
end
|
664
|
-
when 'restore'
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
827
|
+
when 'restore'
|
828
|
+
case flag
|
829
|
+
when :source
|
830
|
+
format_desc action, flag, 'ref,opts*,pathspec*'
|
831
|
+
task flag, [:commit] do |_, args|
|
832
|
+
commit = commithead args.commit
|
833
|
+
if commit
|
834
|
+
args = args.extras
|
835
|
+
else
|
836
|
+
commit, opts, files = choice_commit(values: ['Options', ['Pathspec', true]])
|
837
|
+
args = OptionPartition.strip(opts)
|
838
|
+
files = files&.shellsplit
|
839
|
+
end
|
840
|
+
restore(flag, args, commit: commit, files: files)
|
841
|
+
end
|
842
|
+
when :staged, :worktree
|
843
|
+
format_desc action, flag, 'opts*,pathspec*,:?'
|
844
|
+
task flag do |_, args|
|
845
|
+
args = args.to_a
|
846
|
+
if args.empty? || args.last == ':'
|
847
|
+
files = []
|
848
|
+
git_spawn('status -s --porcelain', stdout: false).each do |line|
|
849
|
+
next unless line =~ /^(.)(.)\s+(.+)$/
|
850
|
+
|
851
|
+
case (flag == :staged ? $1 : $2)
|
852
|
+
when 'A', 'M'
|
853
|
+
files << $3
|
854
|
+
end
|
855
|
+
end
|
856
|
+
unless files.empty?
|
857
|
+
files = choice_index('Select a file', files, multiple: true, force: false,
|
858
|
+
accept: 'Restore?')
|
859
|
+
end
|
860
|
+
args.pop
|
861
|
+
args, glob = args.partition { |val| val.match?(/^(?:[a-z-]+=|[^*]+$)/) }
|
862
|
+
(files ||= []).concat(glob)
|
863
|
+
next if args.empty? && files.empty?
|
864
|
+
end
|
865
|
+
restore(flag, args, files: files)
|
866
|
+
end
|
867
|
+
end
|
868
|
+
when 'git'
|
869
|
+
before = case flag
|
870
|
+
when :rm then 'source+,destination'
|
871
|
+
when :revert then 'commit+' end
|
872
|
+
format_desc(action, flag, 'opts*', before: before, after: case flag
|
873
|
+
when :add, :clean, :mv
|
874
|
+
'pathspec*'
|
875
|
+
end)
|
673
876
|
task flag do |_, args|
|
674
|
-
|
877
|
+
git flag, args.to_a
|
675
878
|
end
|
676
879
|
end
|
677
880
|
end
|
@@ -699,15 +902,18 @@ module Squared
|
|
699
902
|
cmd, opts = git_session('pull', opts: opts)
|
700
903
|
if flag == :rebase
|
701
904
|
cmd << '--rebase'
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
905
|
+
cmd << '--autostash' if option('autostash')
|
906
|
+
else
|
907
|
+
cmd << '--autostash' if flag == :autostash
|
908
|
+
if (val = option('rebase', ignore: false))
|
909
|
+
cmd << case val
|
910
|
+
when '0', 'false'
|
911
|
+
'--no-rebase'
|
912
|
+
else
|
913
|
+
VAL_GIT[:rebase][:value].include?(val) ? basic_option('rebase', val) : '--rebase'
|
914
|
+
end
|
915
|
+
end
|
709
916
|
end
|
710
|
-
cmd << '--autostash' if option('autostash')
|
711
917
|
append_pull(opts, OPT_GIT[:pull] + OPT_GIT[:fetch][:pull],
|
712
918
|
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag)
|
713
919
|
source(sync: sync, sub: if verbose
|
@@ -725,16 +931,12 @@ module Squared
|
|
725
931
|
cmd, opts = git_session('rebase', opts: opts)
|
726
932
|
case flag
|
727
933
|
when :branch
|
934
|
+
return unless upstream
|
935
|
+
|
728
936
|
op = OptionPartition.new(opts, OPT_GIT[:rebase], cmd, project: self, no: OPT_GIT[:no][:rebase])
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
when 1, 2
|
733
|
-
op.append(delim: true)
|
734
|
-
else
|
735
|
-
op.append(op.pop(2), delim: true)
|
736
|
-
.clear(pass: false)
|
737
|
-
end
|
937
|
+
cmd << shell_escape(upstream)
|
938
|
+
append_head op.shift
|
939
|
+
op.clear(pass: false)
|
738
940
|
when :onto
|
739
941
|
return unless upstream
|
740
942
|
|
@@ -750,6 +952,10 @@ module Squared
|
|
750
952
|
source
|
751
953
|
end
|
752
954
|
|
955
|
+
def autostash(*, sync: invoked_sync?('autostash'), **)
|
956
|
+
pull(:autostash, sync: sync)
|
957
|
+
end
|
958
|
+
|
753
959
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
754
960
|
cmd, opts = git_session('fetch', opts: opts)
|
755
961
|
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]), remote: remote,
|
@@ -784,8 +990,12 @@ module Squared
|
|
784
990
|
def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
|
785
991
|
if flag
|
786
992
|
cmd, opts = git_session('stash', flag, opts: opts)
|
787
|
-
|
788
|
-
|
993
|
+
list = OPT_GIT[:stash][:common] + OPT_GIT[:stash].fetch(flag, [])
|
994
|
+
if flag == :list
|
995
|
+
list += collect_hash(OPT_GIT[:log])
|
996
|
+
no = collect_hash(OPT_GIT[:no][:log])
|
997
|
+
end
|
998
|
+
op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: flag == :push ? matchpathspec : nil)
|
789
999
|
case flag
|
790
1000
|
when :push
|
791
1001
|
append_pathspec op.extras
|
@@ -800,6 +1010,7 @@ module Squared
|
|
800
1010
|
end
|
801
1011
|
return
|
802
1012
|
when :list
|
1013
|
+
op.clear
|
803
1014
|
out, banner, from = source(io: true)
|
804
1015
|
print_item banner
|
805
1016
|
list_result(write_lines(out), 'objects', from: from)
|
@@ -807,8 +1018,8 @@ module Squared
|
|
807
1018
|
end
|
808
1019
|
else
|
809
1020
|
git_session('stash', 'push', opts: opts)
|
810
|
-
append_option(
|
811
|
-
append_message
|
1021
|
+
append_option(OPT_GIT[:stash][:push].grep_v(/[=|]/), no: true, ignore: false)
|
1022
|
+
append_message
|
812
1023
|
end
|
813
1024
|
source(banner: !quiet?, sync: sync, **threadargs)
|
814
1025
|
end
|
@@ -816,6 +1027,7 @@ module Squared
|
|
816
1027
|
def status(*)
|
817
1028
|
cmd = git_session 'status'
|
818
1029
|
cmd << (option('long') ? '--long' : '--short')
|
1030
|
+
cmd << '--branch' if option('branch')
|
819
1031
|
if (val = option('ignore-submodules', ignore: false))
|
820
1032
|
cmd << basic_option('ignore-submodules', case val
|
821
1033
|
when '0', 'none'
|
@@ -829,18 +1041,22 @@ module Squared
|
|
829
1041
|
end)
|
830
1042
|
end
|
831
1043
|
append_pathspec
|
1044
|
+
if verbose
|
1045
|
+
r = color(:red)
|
1046
|
+
g = color(:green)
|
1047
|
+
sub = if session_arg?('short')
|
1048
|
+
[
|
1049
|
+
{ pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
|
1050
|
+
{ pat: /^([A-Z?!])(.+)$/, styles: g },
|
1051
|
+
{ pat: /^(\?\?)(.+)$/, styles: r },
|
1052
|
+
{ pat: /^(## )(.+?)(\.{3})(.+)$/, styles: [nil, g, nil, r], index: -1 }
|
1053
|
+
]
|
1054
|
+
else
|
1055
|
+
[{ pat: /^(\t+)([a-z]+: +.+)$/, styles: r, index: 2 }]
|
1056
|
+
end
|
1057
|
+
end
|
832
1058
|
out, banner, from = source(io: true)
|
833
|
-
ret = write_lines(out, banner: banner, sub:
|
834
|
-
r = color(:red)
|
835
|
-
g = color(:green)
|
836
|
-
[
|
837
|
-
{ pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
|
838
|
-
{ pat: /^([A-Z?!])(.+)$/, styles: g },
|
839
|
-
{ pat: /^(\?\?)(.+)$/, styles: r },
|
840
|
-
{ pat: /^(## )(.+)(\.{3})(.+)$/,
|
841
|
-
styles: [nil, g, nil, r], index: -1 }
|
842
|
-
]
|
843
|
-
end)
|
1059
|
+
ret = write_lines(out, banner: banner, sub: sub)
|
844
1060
|
list_result(ret, 'files', from: from, action: 'modified')
|
845
1061
|
end
|
846
1062
|
|
@@ -853,16 +1069,16 @@ module Squared
|
|
853
1069
|
end
|
854
1070
|
unless workspace.closed
|
855
1071
|
if @revbuild
|
856
|
-
statusargs.
|
1072
|
+
statusargs.call.each { |key, val| @revbuild[key] += val }
|
857
1073
|
else
|
858
|
-
@revbuild = statusargs.
|
1074
|
+
@revbuild = statusargs.call
|
859
1075
|
end
|
860
1076
|
return
|
861
1077
|
end
|
862
|
-
sha = git_spawn('rev-parse --verify HEAD').
|
1078
|
+
sha = git_spawn('rev-parse --verify HEAD').chomp
|
863
1079
|
return if sha.empty?
|
864
1080
|
|
865
|
-
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.
|
1081
|
+
kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.call : @revbuild || {}
|
866
1082
|
case flag
|
867
1083
|
when :build
|
868
1084
|
op = OptionPartition.new(opts, OPT_GIT[:status], project: self)
|
@@ -904,13 +1120,14 @@ module Squared
|
|
904
1120
|
case flag
|
905
1121
|
when :commit, :index
|
906
1122
|
op = OptionPartition.new(opts, OPT_GIT[:reset] + VAL_GIT[:reset], cmd,
|
907
|
-
project: self, no: OPT_GIT[:no][:reset]
|
1123
|
+
project: self, no: OPT_GIT[:no][:reset],
|
1124
|
+
first: flag == :index ? matchpathspec : nil)
|
908
1125
|
if flag == :commit
|
909
|
-
op.append(commit
|
1126
|
+
op.append(commit)
|
910
1127
|
.clear(pass: false)
|
911
1128
|
ref = false
|
912
1129
|
else
|
913
|
-
|
1130
|
+
refs = op.extras
|
914
1131
|
end
|
915
1132
|
when :mode
|
916
1133
|
return unless VAL_GIT[:reset].include?(mode)
|
@@ -922,6 +1139,7 @@ module Squared
|
|
922
1139
|
end
|
923
1140
|
when :patch
|
924
1141
|
cmd << '--patch'
|
1142
|
+
append_pathspec(refs, pass: false)
|
925
1143
|
end
|
926
1144
|
unless ref == false
|
927
1145
|
append_commit(ref, head: true)
|
@@ -930,39 +1148,41 @@ module Squared
|
|
930
1148
|
source
|
931
1149
|
end
|
932
1150
|
|
933
|
-
def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil)
|
1151
|
+
def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil, merge: false)
|
934
1152
|
cmd, opts = git_session('checkout', opts: opts)
|
935
1153
|
append_option 'force', 'merge'
|
936
1154
|
case flag
|
937
1155
|
when :branch
|
938
1156
|
cmd << '--detach' if detach == 'd' || option('detach')
|
939
1157
|
append_option('track', equals: true)
|
940
|
-
cmd << (create ?
|
1158
|
+
cmd << (create ? quote_option(create, branch) : branch) << commit
|
941
1159
|
when :track
|
942
1160
|
if branch
|
943
1161
|
if branch.start_with?('^')
|
944
1162
|
opt = 'B'
|
945
1163
|
branch = branch[1..-1]
|
946
1164
|
end
|
947
|
-
cmd <<
|
1165
|
+
cmd << quote_option(opt || 'b', branch)
|
948
1166
|
end
|
949
|
-
cmd << '--track' << origin
|
1167
|
+
cmd << '--track' << shell_quote(origin)
|
950
1168
|
when :detach
|
1169
|
+
cmd << '-m' if merge
|
951
1170
|
cmd << '--detach' << commit
|
952
1171
|
else
|
953
|
-
op = OptionPartition.new(opts, OPT_GIT[:checkout], cmd, project: self, no: OPT_GIT[:no][:checkout]
|
1172
|
+
op = OptionPartition.new(opts, OPT_GIT[:checkout], cmd, project: self, no: OPT_GIT[:no][:checkout],
|
1173
|
+
first: flag == :path ? matchpathspec : nil)
|
954
1174
|
if flag == :commit
|
955
|
-
op.append(commit
|
1175
|
+
op.append(commit)
|
956
1176
|
.clear(pass: false)
|
957
1177
|
else
|
958
1178
|
append_head
|
959
|
-
append_pathspec
|
1179
|
+
append_pathspec(op.extras, pass: false)
|
960
1180
|
end
|
961
1181
|
end
|
962
1182
|
source
|
963
1183
|
end
|
964
1184
|
|
965
|
-
def tag(flag, opts = [], refs: [], message: nil, commit: nil)
|
1185
|
+
def tag(flag, opts = [], refs: [], message: nil, commit: nil, remote: nil)
|
966
1186
|
cmd, opts = git_session('tag', opts: opts)
|
967
1187
|
case flag
|
968
1188
|
when :add, :sign
|
@@ -974,31 +1194,32 @@ module Squared
|
|
974
1194
|
cmd << '--force' if option('force')
|
975
1195
|
if !commit && message && (sha = commithash(message))
|
976
1196
|
commit = sha
|
977
|
-
|
978
|
-
append_message message
|
1197
|
+
message = nil
|
979
1198
|
end
|
1199
|
+
append_message message
|
980
1200
|
append_value refs
|
981
1201
|
append_head commit
|
982
|
-
when :
|
1202
|
+
when :delete
|
1203
|
+
cmd << '--delete'
|
1204
|
+
append_value refs
|
1205
|
+
else
|
983
1206
|
op = OptionPartition.new(opts, OPT_GIT[:tag], cmd << '--list', project: self, no: OPT_GIT[:no][:tag])
|
984
1207
|
out, banner, from = source(io: true)
|
985
1208
|
print_item banner
|
986
1209
|
ret = write_lines(out, grep: op.extras)
|
987
1210
|
list_result(ret, 'tags', from: from, grep: op.extras)
|
988
1211
|
return
|
989
|
-
when :delete
|
990
|
-
cmd << '--delete'
|
991
|
-
append_value refs
|
992
|
-
else
|
993
|
-
cmd << shell_option(flag, commit)
|
994
1212
|
end
|
1213
|
+
remote ||= option('remote')
|
995
1214
|
source
|
1215
|
+
git_spawn('push', flag == :delete ? '-d' : nil, remote, *refs.map { |val| shell_quote(val) }) if remote
|
996
1216
|
end
|
997
1217
|
|
998
|
-
def
|
1218
|
+
def log!(flag, opts = [], range: [], index: [])
|
999
1219
|
cmd, opts = git_session('log', opts: opts)
|
1000
1220
|
op = OptionPartition.new(opts, collect_hash(OPT_GIT[:log]), cmd,
|
1001
|
-
project: self, no: collect_hash(OPT_GIT[:no][:log])
|
1221
|
+
project: self, no: collect_hash(OPT_GIT[:no][:log]),
|
1222
|
+
first: matchpathspec)
|
1002
1223
|
case flag
|
1003
1224
|
when :between, :contain
|
1004
1225
|
op << shell_quote(range.join(flag == :between ? '..' : '...'))
|
@@ -1013,7 +1234,8 @@ module Squared
|
|
1013
1234
|
def diff(flag, opts = [], refs: [], branch: nil, range: [], index: [])
|
1014
1235
|
cmd, opts = git_session('diff', opts: opts)
|
1015
1236
|
op = OptionPartition.new(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff], cmd,
|
1016
|
-
project: self, no: OPT_GIT[:no][:log][:diff]
|
1237
|
+
project: self, no: OPT_GIT[:no][:log][:diff],
|
1238
|
+
first: flag == :files ? nil : matchpathspec)
|
1017
1239
|
case flag
|
1018
1240
|
when :files, :view, :between, :contain
|
1019
1241
|
op.delete('--cached')
|
@@ -1026,7 +1248,7 @@ module Squared
|
|
1026
1248
|
case flag
|
1027
1249
|
when :view
|
1028
1250
|
op << '--merge-base' if option('merge-base')
|
1029
|
-
op
|
1251
|
+
op.merge(range)
|
1030
1252
|
when :between, :contain
|
1031
1253
|
op.delete('--merge-base')
|
1032
1254
|
op << shell_quote(range.join(flag == :between ? '..' : '...'))
|
@@ -1049,82 +1271,99 @@ module Squared
|
|
1049
1271
|
source(exception: op.arg?('exit-code'))
|
1050
1272
|
end
|
1051
1273
|
|
1052
|
-
def commit(flag,
|
1053
|
-
|
1054
|
-
amend = flag.to_s.start_with?('amend')
|
1274
|
+
def commit(flag, opts = [], refs: [], ref: nil, squash: nil, pick: nil, message: nil, pass: false)
|
1275
|
+
fixup = flag == :fixup
|
1276
|
+
amend = !fixup && flag.to_s.start_with?('amend')
|
1277
|
+
unless flag == :add || pick == 'reword'
|
1278
|
+
pathspec = if flag == :all || ((fixup || amend) && refs.size == 1 && refs.first == '*')
|
1279
|
+
'--all'
|
1280
|
+
elsif (refs = projectmap(refs)).empty?
|
1281
|
+
raise_error 'no qualified pathspec'
|
1282
|
+
else
|
1283
|
+
"-- #{refs.join(' ')}"
|
1284
|
+
end
|
1285
|
+
end
|
1286
|
+
if fixup
|
1287
|
+
source git_session('commit', basic_option('fixup', "#{pick ? "#{pick}:" : ''}#{ref}"), pathspec)
|
1288
|
+
source git_output('rebase --autosquash', squash) if squash.is_a?(String)
|
1289
|
+
return
|
1290
|
+
end
|
1291
|
+
message ||= messageopt
|
1055
1292
|
if !message && !amend
|
1056
1293
|
return if pass
|
1057
1294
|
|
1058
|
-
|
1295
|
+
message = readline('Enter message', force: true)
|
1059
1296
|
end
|
1060
|
-
pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
|
1061
|
-
'--all'
|
1062
|
-
elsif (refs = projectmap(refs)).empty?
|
1063
|
-
raise_error 'no qualified pathspec'
|
1064
|
-
else
|
1065
|
-
"-- #{refs.join(' ')}"
|
1066
|
-
end
|
1067
|
-
origin = nil
|
1068
1297
|
branch = nil
|
1298
|
+
origin = nil
|
1069
1299
|
upstream = nil
|
1300
|
+
cmd, opts = git_session('add', opts: opts)
|
1301
|
+
op = OptionPartition.new(opts, OPT_GIT[:add], cmd, project: self, first: matchpathspec)
|
1302
|
+
op << '--verbose' if verbose
|
1303
|
+
dryrun = dryrun?
|
1304
|
+
format = '%(if)%(HEAD)%(then)%(refname:short)...%(upstream:short)...%(upstream:track)%(end)'
|
1070
1305
|
git_spawn 'fetch --no-tags --quiet'
|
1071
|
-
|
1072
|
-
next
|
1073
|
-
|
1074
|
-
branch =
|
1075
|
-
if
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
end
|
1306
|
+
foreachref('heads', format: format).each do |line|
|
1307
|
+
next if (line = line.chomp).empty?
|
1308
|
+
|
1309
|
+
branch, origin, hint = line.split('...')
|
1310
|
+
if hint && !hint.match?(/^\[(\D+0,\D+0)\]$/)
|
1311
|
+
raise_error('work tree is not usable', hint: hint[1..-2])
|
1312
|
+
elsif origin.empty?
|
1313
|
+
return nil if pass
|
1314
|
+
break if dryrun
|
1315
|
+
|
1316
|
+
unless (origin = option('upstream', prefix: 'git', ignore: false))
|
1317
|
+
if (origin = choice_refs('Choose an upstream', 'remotes', attempts: 1, force: false))
|
1318
|
+
git_spawn 'branch', quote_option('set-upstream-to', origin)
|
1319
|
+
else
|
1320
|
+
origin = readline('Enter an upstream', force: true)
|
1087
1321
|
end
|
1088
1322
|
end
|
1089
|
-
|
1323
|
+
raise_error('missing remote name', hint: origin) unless origin.include?('/')
|
1324
|
+
upstream = true
|
1090
1325
|
end
|
1091
1326
|
break
|
1092
1327
|
end
|
1093
|
-
|
1094
|
-
|
1095
|
-
if amend
|
1096
|
-
cmd << '--amend'
|
1328
|
+
if pathspec
|
1329
|
+
op << pathspec
|
1097
1330
|
else
|
1098
|
-
|
1331
|
+
append_pathspec op.extras
|
1332
|
+
end
|
1333
|
+
co = git_session('commit', options: false)
|
1334
|
+
pu = git_output 'push', upstream && '--set-upstream'
|
1335
|
+
if dryrun
|
1336
|
+
op.delete('--dry-run')
|
1337
|
+
co << '--dry-run'
|
1338
|
+
pu << '--dry-run'
|
1099
1339
|
end
|
1340
|
+
co << '--amend' if amend
|
1100
1341
|
if message
|
1101
1342
|
append_message message
|
1102
1343
|
elsif flag == :'amend-orig' || option('edit', equals: '0')
|
1103
|
-
|
1104
|
-
end
|
1105
|
-
a = git_output 'add', '--verbose'
|
1106
|
-
b = git_output 'push', upstream && '--set-upstream'
|
1107
|
-
if dryrun?
|
1108
|
-
a << '--dry-run'
|
1109
|
-
b << '--dry-run'
|
1344
|
+
co << '--no-edit'
|
1110
1345
|
end
|
1111
|
-
|
1112
|
-
|
1113
|
-
b << origin << branch
|
1346
|
+
pu << '--force-with-lease' if amend
|
1347
|
+
pu.merge(repotrack(origin, branch))
|
1114
1348
|
puts if pass
|
1115
|
-
source
|
1116
|
-
source
|
1117
|
-
source
|
1349
|
+
source op
|
1350
|
+
source co
|
1351
|
+
source pu
|
1118
1352
|
end
|
1119
1353
|
|
1120
|
-
def merge(flag, opts = [], command: nil)
|
1354
|
+
def merge(flag, opts = [], command: nil, branch: nil)
|
1121
1355
|
cmd, opts = git_session('merge', opts: opts)
|
1122
1356
|
case flag
|
1123
1357
|
when :commit, :'no-commit'
|
1124
1358
|
op = OptionPartition.new(opts, OPT_GIT[:merge], cmd, project: self, no: OPT_GIT[:no][:merge])
|
1125
1359
|
raise_error 'no branch/commit' if op.empty?
|
1126
1360
|
op << "--#{flag}" << '--'
|
1127
|
-
|
1361
|
+
if branch
|
1362
|
+
op << branch
|
1363
|
+
op.clear(pass: false)
|
1364
|
+
else
|
1365
|
+
append_commit(*op.extras)
|
1366
|
+
end
|
1128
1367
|
else
|
1129
1368
|
return unless VAL_GIT[:merge][:send].include?(command)
|
1130
1369
|
|
@@ -1133,7 +1372,7 @@ module Squared
|
|
1133
1372
|
source
|
1134
1373
|
end
|
1135
1374
|
|
1136
|
-
def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil)
|
1375
|
+
def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil, remote: nil)
|
1137
1376
|
cmd, opts = git_session('branch', opts: opts)
|
1138
1377
|
stdout = false
|
1139
1378
|
case flag
|
@@ -1149,43 +1388,46 @@ module Squared
|
|
1149
1388
|
end
|
1150
1389
|
end
|
1151
1390
|
cmd << '--force' if option('force')
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1391
|
+
cmd << shell_quote(target)
|
1392
|
+
cmd << shell_quote(ref) if ref
|
1393
|
+
when :track
|
1394
|
+
raise_error('invalid upstream', hint: ref) unless ref.include?('/')
|
1155
1395
|
if ref.start_with?('^')
|
1156
|
-
cmd << '--unset-upstream' <<
|
1157
|
-
|
1396
|
+
cmd << '--unset-upstream' << shell_quote(ref[1..-1])
|
1397
|
+
remote = false
|
1158
1398
|
stdout = true
|
1159
1399
|
else
|
1160
1400
|
cmd << quote_option('set-upstream-to', ref)
|
1401
|
+
cmd << shell_quote(target) if target
|
1161
1402
|
end
|
1162
|
-
ref = nil
|
1163
1403
|
when :delete
|
1164
|
-
|
1404
|
+
remote&.each do |val|
|
1405
|
+
source git_output('push', '--delete', *val.split('/', 2).map { |s| shell_quote(s) })
|
1406
|
+
end
|
1407
|
+
force, list = refs.partition { |val| val.match?(/^[~^]/) }
|
1165
1408
|
force.each do |val|
|
1166
|
-
dr = val[0,
|
1409
|
+
dr = val[0, 2]
|
1167
1410
|
d = dr.include?('^') ? '-D' : '-d'
|
1168
|
-
r = dr.include?('~')
|
1169
|
-
source git_output('branch', d, r, shell_quote(val.sub(/^[
|
1411
|
+
r = '-r' if dr.include?('~')
|
1412
|
+
source git_output('branch', d, r, shell_quote(val.sub(/^[~^]+/, '')))
|
1170
1413
|
end
|
1171
1414
|
return if list.empty?
|
1172
1415
|
|
1173
1416
|
cmd << '-d'
|
1174
|
-
list
|
1417
|
+
append_value list
|
1418
|
+
remote = nil
|
1175
1419
|
when :move, :copy
|
1176
1420
|
flag = "-#{flag.to_s[0]}"
|
1177
1421
|
cmd << (option('force') ? flag.upcase : flag)
|
1178
1422
|
refs.compact.each { |val| cmd << shell_quote(val) }
|
1179
1423
|
stdout = true
|
1180
|
-
when :edit
|
1181
|
-
cmd << '--edit-description'
|
1182
1424
|
when :current
|
1183
1425
|
cmd << '--show-current'
|
1184
1426
|
source(banner: verbosetype > 1, stdout: true)
|
1185
1427
|
return
|
1186
1428
|
when :list
|
1187
1429
|
op = OptionPartition.new(opts, OPT_GIT[:branch], cmd << '--list',
|
1188
|
-
project: self, no: OPT_GIT[:no][:branch], single:
|
1430
|
+
project: self, no: OPT_GIT[:no][:branch], single: /\Av+\z/)
|
1189
1431
|
op.each { |val| op << shell_quote(val) }
|
1190
1432
|
out, banner, from = source(io: true)
|
1191
1433
|
print_item banner
|
@@ -1196,7 +1438,7 @@ module Squared
|
|
1196
1438
|
list_result(ret, 'branches', from: from)
|
1197
1439
|
return
|
1198
1440
|
else
|
1199
|
-
head = git_spawn('rev-parse --abbrev-ref HEAD').
|
1441
|
+
head = git_spawn('rev-parse --abbrev-ref HEAD').chomp
|
1200
1442
|
if head.empty?
|
1201
1443
|
ret = 0
|
1202
1444
|
else
|
@@ -1212,8 +1454,8 @@ module Squared
|
|
1212
1454
|
if (r1 = r[1]) && r1 =~ /^(.+):(?: ([a-z]+) (\d+),)? ([a-z]+) (\d+)$/
|
1213
1455
|
write = ->(s1, s2) { "#{s1.capitalize.rjust(7)}: #{sub_style(s2, styles: theme[:warn])}" }
|
1214
1456
|
r1 = $1
|
1215
|
-
r2 = $2 && write.($2, $3)
|
1216
|
-
r3 = write.($4, $5)
|
1457
|
+
r2 = $2 && write.call($2, $3)
|
1458
|
+
r3 = write.call($4, $5)
|
1217
1459
|
end
|
1218
1460
|
r1 = nil if r1 == "origin/#{data[0]}"
|
1219
1461
|
[" Branch: #{a + (r1 ? " (#{r1})" : '')}", r2, r3, " Commit: #{b}", "Message: #{r[2]}"]
|
@@ -1227,15 +1469,46 @@ module Squared
|
|
1227
1469
|
end
|
1228
1470
|
return
|
1229
1471
|
end
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1472
|
+
return unless success?(source(stdout: stdout))
|
1473
|
+
|
1474
|
+
if !ref
|
1475
|
+
print_success if flag == :create
|
1476
|
+
elsif remote && target
|
1477
|
+
source git_output('push', '-u', shell_quote(ref.split('/', 2).first), shell_quote(target))
|
1478
|
+
end
|
1233
1479
|
end
|
1234
1480
|
|
1235
|
-
def
|
1236
|
-
cmd
|
1237
|
-
|
1238
|
-
|
1481
|
+
def switch(flag, opts = [], target: nil, commit: nil, track: nil)
|
1482
|
+
cmd = git_session('switch', opts: opts).first
|
1483
|
+
case flag
|
1484
|
+
when :create
|
1485
|
+
c = 'c'
|
1486
|
+
if target.start_with?('^')
|
1487
|
+
target = target[1..-1]
|
1488
|
+
c = c.upcase
|
1489
|
+
end
|
1490
|
+
cmd << quote_option(c, target)
|
1491
|
+
cmd << case (track ||= option('track', ignore: false))
|
1492
|
+
when 'n', 'N', '0', 'false'
|
1493
|
+
'--no-track'
|
1494
|
+
when 'y', 'Y', '1', 'true'
|
1495
|
+
'--track'
|
1496
|
+
when 'direct', 'inherit'
|
1497
|
+
basic_option('track', track)
|
1498
|
+
end
|
1499
|
+
when :detach, :merge
|
1500
|
+
cmd << "--#{flag}"
|
1501
|
+
end
|
1502
|
+
cmd << '--force' if option('force')
|
1503
|
+
append_head commit
|
1504
|
+
source
|
1505
|
+
end
|
1506
|
+
|
1507
|
+
def restore(flag, opts = [], commit: nil, files: nil)
|
1508
|
+
cmd, opts = git_session('restore', shell_option(flag, commit, escape: false, force: false), opts: opts)
|
1509
|
+
op = OptionPartition.new(opts, OPT_GIT[:restore], cmd, project: self, no: OPT_GIT[:no][:restore],
|
1510
|
+
first: matchpathspec)
|
1511
|
+
append_pathspec(op.extras + (files || []), pass: false)
|
1239
1512
|
source(sync: false, stderr: true)
|
1240
1513
|
end
|
1241
1514
|
|
@@ -1244,14 +1517,13 @@ module Squared
|
|
1244
1517
|
case flag
|
1245
1518
|
when :textconv
|
1246
1519
|
cmd << '--textconv'
|
1247
|
-
append_value(files.
|
1248
|
-
.flatten
|
1520
|
+
append_value(files.flat_map { |val| Dir[val] }
|
1249
1521
|
.select { |val| projectpath?(val) }
|
1250
1522
|
.map! { |val| shell_quote("HEAD:#{val}") })
|
1251
1523
|
source(banner: false)
|
1252
1524
|
return
|
1253
1525
|
when :oneline
|
1254
|
-
format =
|
1526
|
+
format = 'oneline'
|
1255
1527
|
end
|
1256
1528
|
if format
|
1257
1529
|
case (val = format.downcase)
|
@@ -1268,21 +1540,12 @@ module Squared
|
|
1268
1540
|
op = OptionPartition.new(opts, OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff], cmd,
|
1269
1541
|
project: self,
|
1270
1542
|
no: OPT_GIT[:no][:show] + collect_hash(OPT_GIT[:no][:log], pass: [:base]))
|
1271
|
-
unless val == 'oneline' && op.arg?('abbrev-commit')
|
1272
|
-
op << basic_option('abbrev', val) if (val = option('abbrev')) && val.to_i > 0
|
1273
|
-
banner = true
|
1274
|
-
end
|
1275
1543
|
op.append(delim: true)
|
1276
|
-
source(exception: false, banner:
|
1544
|
+
source(exception: false, banner: flag != :oneline)
|
1277
1545
|
end
|
1278
1546
|
|
1279
1547
|
def rev_parse(flag, opts = [], ref: nil, size: nil)
|
1280
1548
|
cmd, opts = git_session('rev-parse', opts: opts)
|
1281
|
-
cmd << if flag == :parseopt
|
1282
|
-
'--parseopt'
|
1283
|
-
elsif opts.delete('sq-quote')
|
1284
|
-
'--sq-quote'
|
1285
|
-
end
|
1286
1549
|
case flag
|
1287
1550
|
when :commit
|
1288
1551
|
cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
|
@@ -1290,9 +1553,14 @@ module Squared
|
|
1290
1553
|
when :branch
|
1291
1554
|
cmd << '--abbrev-ref'
|
1292
1555
|
append_commit(ref, head: true)
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1556
|
+
when :output
|
1557
|
+
if opts.delete('sq-quote')
|
1558
|
+
cmd << '--sq-quote'
|
1559
|
+
args = true
|
1560
|
+
end
|
1561
|
+
op = OptionPartition.new(opts, OPT_GIT[:rev_parse], cmd, project: self, no: OPT_GIT[:no][:rev_parse],
|
1562
|
+
args: args)
|
1563
|
+
op.append(escape: args)
|
1296
1564
|
end
|
1297
1565
|
source(banner: verbosetype > 1)
|
1298
1566
|
end
|
@@ -1319,18 +1587,10 @@ module Squared
|
|
1319
1587
|
|
1320
1588
|
def git(flag, opts = [])
|
1321
1589
|
cmd, opts = git_session(flag, opts: opts)
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1590
|
+
list = OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, [])
|
1591
|
+
op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GIT[:no][flag],
|
1592
|
+
first: flag == :revert ? nil : matchpathspec)
|
1325
1593
|
case flag
|
1326
|
-
when :clean
|
1327
|
-
refs = projectmap(op.extras)
|
1328
|
-
unless refs.empty?
|
1329
|
-
op << '--'
|
1330
|
-
op.merge(refs)
|
1331
|
-
end
|
1332
|
-
sync = true
|
1333
|
-
stderr = false
|
1334
1594
|
when :revert
|
1335
1595
|
if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
|
1336
1596
|
op.clear
|
@@ -1339,14 +1599,29 @@ module Squared
|
|
1339
1599
|
else
|
1340
1600
|
append_commit(*op.extras)
|
1341
1601
|
end
|
1602
|
+
when :add, :clean
|
1603
|
+
if flag == :add && op.empty? && !op.arg?('pathspec-from-file')
|
1604
|
+
files = []
|
1605
|
+
red = color(:red)
|
1606
|
+
git_spawn('status -s --porcelain -uall', stdout: false).each do |line|
|
1607
|
+
next unless line =~ /^.(.) (.+)$/
|
1608
|
+
|
1609
|
+
files << "#{sub_style($1, styles: red)} #{$2}"
|
1610
|
+
end
|
1611
|
+
files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/, accept: 'Add?')
|
1612
|
+
end
|
1613
|
+
append_pathspec(files || op.extras)
|
1614
|
+
verbose = flag == :add && !op.arg?('verbose')
|
1615
|
+
print_success if success?(source) && verbose
|
1616
|
+
return
|
1342
1617
|
when :mv
|
1343
|
-
refs = projectmap
|
1618
|
+
refs = projectmap op.extras
|
1344
1619
|
raise_error 'no source/destination' unless refs.size > 1
|
1345
1620
|
op.merge(refs)
|
1346
1621
|
when :rm
|
1347
|
-
append_pathspec(op.extras, expect:
|
1622
|
+
append_pathspec(op.extras, expect: !op.arg?('pathspec-from-file'))
|
1348
1623
|
end
|
1349
|
-
source(sync:
|
1624
|
+
source(sync: false, stderr: true)
|
1350
1625
|
end
|
1351
1626
|
|
1352
1627
|
def clone?
|
@@ -1365,43 +1640,47 @@ module Squared
|
|
1365
1640
|
|
1366
1641
|
def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
|
1367
1642
|
multiple: false, sub: nil)
|
1643
|
+
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
1368
1644
|
banner = nil if multiple && banner
|
1369
1645
|
if cmd.respond_to?(:done)
|
1370
1646
|
if io && banner == false
|
1371
1647
|
from = nil
|
1372
|
-
elsif !from && (from = cmd.drop(1).find { |val| val.match?(
|
1648
|
+
elsif !from && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z][a-z\-]{2,}\z/) })
|
1373
1649
|
from = :"git:#{from}"
|
1374
1650
|
end
|
1375
1651
|
banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
|
1376
1652
|
end
|
1377
|
-
cmd = session_done
|
1653
|
+
cmd = session_done cmd
|
1378
1654
|
log&.info cmd
|
1379
1655
|
on :first, from
|
1380
1656
|
banner = if banner
|
1381
1657
|
format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
|
1382
1658
|
end
|
1383
1659
|
begin
|
1384
|
-
|
1660
|
+
if io
|
1661
|
+
return `#{cmd}` if stdout
|
1385
1662
|
|
1663
|
+
return banner ? [IO.popen(cmd), banner, from] : IO.popen(cmd)
|
1664
|
+
end
|
1386
1665
|
if stdin? ? sync : stdout
|
1387
1666
|
print_item banner unless multiple
|
1388
1667
|
ret = `#{cmd}`
|
1389
1668
|
if !ret.empty?
|
1390
1669
|
puts ret
|
1391
|
-
elsif banner
|
1392
|
-
|
1670
|
+
elsif success?(!banner.nil?)
|
1671
|
+
print_success
|
1393
1672
|
end
|
1394
1673
|
elsif sync || (!exception && !stderr)
|
1395
1674
|
print_item banner unless multiple
|
1396
|
-
shell(cmd, exception: exception)
|
1675
|
+
ret = shell(cmd, exception: exception)
|
1397
1676
|
else
|
1398
1677
|
require 'open3'
|
1399
1678
|
if stderr
|
1400
1679
|
Open3.popen3(cmd) do |_, out, err|
|
1401
|
-
|
1402
|
-
if
|
1403
|
-
|
1404
|
-
|
1680
|
+
n = write_lines(out, banner: banner, sub: sub, pass: true)
|
1681
|
+
if n == 0
|
1682
|
+
n = write_lines(err, banner: banner)
|
1683
|
+
print_success if success?(n == 0 && !banner.nil?)
|
1405
1684
|
else
|
1406
1685
|
write_lines(err, loglevel: Logger::DEBUG)
|
1407
1686
|
end
|
@@ -1416,8 +1695,10 @@ module Squared
|
|
1416
1695
|
raise if exception && ret != true
|
1417
1696
|
|
1418
1697
|
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1698
|
+
nil
|
1419
1699
|
else
|
1420
1700
|
on :last, from
|
1701
|
+
ret
|
1421
1702
|
end
|
1422
1703
|
end
|
1423
1704
|
|
@@ -1458,7 +1739,7 @@ module Squared
|
|
1458
1739
|
styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
|
1459
1740
|
styles << :bold if styles.size <= 1
|
1460
1741
|
puts print_footer("#{size} #{size == 1 ? type.sub(/(?:(?<!l)e)?s\z/, '') : type}",
|
1461
|
-
sub: { pat: /\A(\d+)(.+)\z
|
1742
|
+
sub: { pat: /\A(\d+)(.+)\z/m, styles: styles })
|
1462
1743
|
else
|
1463
1744
|
puts empty_status("No #{type} were #{action}", 'grep', grep.is_a?(Array) ? case grep.size
|
1464
1745
|
when 0
|
@@ -1471,27 +1752,55 @@ module Squared
|
|
1471
1752
|
on :last, from
|
1472
1753
|
end
|
1473
1754
|
|
1474
|
-
def
|
1755
|
+
def choice_refs(msg, *type, format: nil, sort: '-creatordate', count: true, short: true, **kwargs)
|
1756
|
+
type << 'heads' if type.empty?
|
1757
|
+
unless format
|
1758
|
+
format = +"%(refname#{short ? ':short' : ''})"
|
1759
|
+
if type.include?('heads') || type.include?('tags')
|
1760
|
+
format += '%(if)%(HEAD)%(then) *%(end)'
|
1761
|
+
trim = /\s+\*\z/
|
1762
|
+
end
|
1763
|
+
end
|
1764
|
+
args = []
|
1765
|
+
args << quote_option('sort', sort) if sort
|
1766
|
+
args << shell_option('count', env('GIT_COUNT', ARG[:CHOICE])) if count
|
1767
|
+
choice_index(msg, foreachref(type, *args, format: format), trim: trim, **kwargs)
|
1768
|
+
end
|
1769
|
+
|
1770
|
+
def choice_commit(count: true, reflog: true, force: true, **kwargs)
|
1771
|
+
kwargs[:attempts] ||= 1 unless force
|
1772
|
+
cmd = git_output(reflog && env('GIT_REFLOG') ? 'reflog' : 'log')
|
1773
|
+
cmd << quote_option('format', '(%h) %s')
|
1774
|
+
cmd << basic_option('max-count', env('GIT_COUNT', ARG[:CHOICE])) if count
|
1775
|
+
choice_index('Choose a commit', git_spawn(cmd, stdout: false), column: /\((\w+)\)/, force: force, **kwargs)
|
1776
|
+
end
|
1777
|
+
|
1778
|
+
def choice_remote(force: false, **kwargs)
|
1779
|
+
kwargs[:attempts] ||= 1 unless force
|
1780
|
+
choice_index('Select a remote', git_spawn('remote', stdout: false), force: force, **kwargs)
|
1781
|
+
end
|
1782
|
+
|
1783
|
+
def status_digest(*args, algorithm: nil, **kwargs)
|
1784
|
+
require 'digest'
|
1785
|
+
algorithm ||= Digest::SHA256
|
1475
1786
|
glob = kwargs.fetch(:include, [])
|
1476
1787
|
pass = kwargs.fetch(:exclude, [])
|
1477
1788
|
ret = {}
|
1478
|
-
git_spawn('status -s --porcelain', *args, stdout: false).
|
1789
|
+
git_spawn('status -s --porcelain', *args, stdout: false).each do |line|
|
1479
1790
|
next unless (file = line[/^[A-Z ?!]{3}"?(.+?)"?$/, 1])
|
1480
1791
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1481
1792
|
next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1482
1793
|
|
1483
|
-
ret[file] = algorithm.hexdigest(File.read(
|
1794
|
+
ret[file] = algorithm.hexdigest(File.read(path + file))
|
1484
1795
|
end
|
1485
1796
|
ret
|
1486
1797
|
end
|
1487
1798
|
|
1488
|
-
def git_spawn(*cmd, stdout: true)
|
1489
|
-
source(git_output(*cmd), io: true, banner: false, stdout: stdout)
|
1490
|
-
end
|
1491
|
-
|
1492
1799
|
def append_pull(opts, list, target: @session, flag: nil, no: nil, remote: nil)
|
1493
1800
|
target << '--force' if option('force', target: target)
|
1494
1801
|
append_submodules(target: target)
|
1802
|
+
return if !remote && opts.empty?
|
1803
|
+
|
1495
1804
|
refspec = []
|
1496
1805
|
op = OptionPartition.new(opts, remote ? list + ['refspec=v'] : list, target, project: self, no: no)
|
1497
1806
|
op.each do |opt|
|
@@ -1543,7 +1852,7 @@ module Squared
|
|
1543
1852
|
option_clear files
|
1544
1853
|
else
|
1545
1854
|
if files.empty? && (val = option('pathspec', target: target))
|
1546
|
-
files = split_escape
|
1855
|
+
files = split_escape val
|
1547
1856
|
end
|
1548
1857
|
files = projectmap(files, parent: parent, pass: pass)
|
1549
1858
|
if !files.empty?
|
@@ -1554,12 +1863,13 @@ module Squared
|
|
1554
1863
|
end
|
1555
1864
|
end
|
1556
1865
|
|
1557
|
-
def append_message(val, target: @session)
|
1558
|
-
|
1866
|
+
def append_message(val = nil, target: @session)
|
1867
|
+
val = messageopt if val.to_s.empty?
|
1868
|
+
target << quote_option('message', val) if val
|
1559
1869
|
end
|
1560
1870
|
|
1561
1871
|
def append_head(val = nil, target: @session)
|
1562
|
-
return target << val if val
|
1872
|
+
return target << shell_quote(val) if val
|
1563
1873
|
|
1564
1874
|
append_first('head', 'tree-ish', 'object', target: target, flag: false, ignore: false)
|
1565
1875
|
end
|
@@ -1568,22 +1878,33 @@ module Squared
|
|
1568
1878
|
return unless (val = option('recurse-submodules', target: target, ignore: false))
|
1569
1879
|
|
1570
1880
|
if from == :clone
|
1571
|
-
|
1572
|
-
|
1881
|
+
case val
|
1882
|
+
when '0', 'false'
|
1883
|
+
target << '--no-recurse-submodules'
|
1884
|
+
when '1', 'true'
|
1885
|
+
target << '--recurse-submodules'
|
1886
|
+
else
|
1887
|
+
projectmap(split_escape(val)).each do |path|
|
1888
|
+
target << basic_option('recurse-submodules', path)
|
1889
|
+
end
|
1573
1890
|
end
|
1574
|
-
target
|
1575
1891
|
else
|
1576
1892
|
target << case val
|
1577
1893
|
when 'no', '0', 'false'
|
1578
1894
|
'--no-recurse-submodules'
|
1579
1895
|
when 'yes', 'on-demand'
|
1580
|
-
"--recurse-submodules
|
1896
|
+
"--recurse-submodules=#{val}"
|
1581
1897
|
else
|
1582
1898
|
'--recurse-submodules'
|
1583
1899
|
end
|
1584
1900
|
end
|
1585
1901
|
end
|
1586
1902
|
|
1903
|
+
def foreachref(path, *args, format: nil)
|
1904
|
+
path = as_a(path).map! { |val| "refs/#{val}" }
|
1905
|
+
git_spawn('for-each-ref', format && quote_option('format', format), *args, *path, stdout: false)
|
1906
|
+
end
|
1907
|
+
|
1587
1908
|
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
1588
1909
|
dir = worktree ? ["--work-tree=#{shell_quote(path)}", "--git-dir=#{shell_quote(gitpath)}"] : []
|
1589
1910
|
return session('git', *dir, *cmd, **kwargs) unless opts
|
@@ -1597,10 +1918,14 @@ module Squared
|
|
1597
1918
|
git_session(*cmd, main: false, options: false, **kwargs)
|
1598
1919
|
end
|
1599
1920
|
|
1921
|
+
def git_spawn(*cmd, stdout: true)
|
1922
|
+
source(cmd.first.is_a?(Set) ? cmd.first : git_output(*cmd), io: true, banner: false, stdout: stdout)
|
1923
|
+
end
|
1924
|
+
|
1600
1925
|
def dryrun?(*, target: @session, **)
|
1601
1926
|
return false unless target
|
1602
1927
|
|
1603
|
-
target.include?('--dry-run')
|
1928
|
+
target.include?('--dry-run') || !option('dry-run', target: target).nil?
|
1604
1929
|
end
|
1605
1930
|
|
1606
1931
|
def quiet?(target: @session)
|
@@ -1610,11 +1935,36 @@ module Squared
|
|
1610
1935
|
end
|
1611
1936
|
|
1612
1937
|
def gitpath
|
1613
|
-
|
1938
|
+
path + '.git'
|
1939
|
+
end
|
1940
|
+
|
1941
|
+
def repotrack(origin, branch, quote: true)
|
1942
|
+
i = origin.index('/')
|
1943
|
+
branch = "#{branch}:#{origin[i + 1..-1]}" unless origin.end_with?("/#{branch}")
|
1944
|
+
ret = [origin[0..i - 1], branch]
|
1945
|
+
quote ? ret.map! { |val| shell_quote(val) } : ret
|
1614
1946
|
end
|
1615
1947
|
|
1616
1948
|
def commithash(val)
|
1617
|
-
val[
|
1949
|
+
val[/:(\h{5,40})\z/, 1] || val[/\A#\{(\h{5,40})\}\z/, 1]
|
1950
|
+
end
|
1951
|
+
|
1952
|
+
def commithead(val)
|
1953
|
+
return val unless (s = matchhead(val))
|
1954
|
+
|
1955
|
+
s.match?(/^\d/) ? "@~#{s}" : "@#{s}"
|
1956
|
+
end
|
1957
|
+
|
1958
|
+
def matchhead(val)
|
1959
|
+
val && val =~ /^(?:(?:HEAD|@)([~^]\d*)?|H(\d+))$/ ? $2 || $1 || '' : nil
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
def matchpathspec
|
1963
|
+
[/\A[^a-z\d-]+/i, %r{\A[^=\\/*]*[\\/*]}]
|
1964
|
+
end
|
1965
|
+
|
1966
|
+
def messageopt
|
1967
|
+
option('message', 'm', prefix: 'git', ignore: false)
|
1618
1968
|
end
|
1619
1969
|
|
1620
1970
|
def threadargs
|