squared 0.4.8 → 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 +76 -1
- data/README.ruby.md +44 -31
- data/lib/squared/common/format.rb +10 -17
- data/lib/squared/common/prompt.rb +38 -13
- data/lib/squared/common/shell.rb +21 -14
- data/lib/squared/common/system.rb +2 -2
- data/lib/squared/common/utils.rb +1 -1
- data/lib/squared/config.rb +3 -3
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +11 -15
- data/lib/squared/workspace/project/base.rb +79 -35
- data/lib/squared/workspace/project/docker.rb +22 -24
- data/lib/squared/workspace/project/git.rb +666 -362
- data/lib/squared/workspace/project/node.rb +14 -15
- data/lib/squared/workspace/project/python.rb +35 -41
- data/lib/squared/workspace/project/ruby.rb +133 -105
- data/lib/squared/workspace/project/support/class.rb +29 -13
- data/lib/squared/workspace/repo.rb +4 -4
- data/lib/squared/workspace/series.rb +9 -6
- data/lib/squared/workspace.rb +1 -1
- metadata +3 -3
@@ -27,7 +27,7 @@ module Squared
|
|
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')
|
@@ -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
|
|
@@ -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'
|
@@ -383,65 +412,105 @@ module Squared
|
|
383
412
|
tag flag, args.to_a
|
384
413
|
end
|
385
414
|
when :delete
|
386
|
-
format_desc action, flag, 'name
|
415
|
+
format_desc action, flag, 'name+'
|
387
416
|
task flag do |_, args|
|
388
|
-
|
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
|
390
421
|
end
|
391
|
-
tag(flag, refs: refs)
|
422
|
+
tag(flag, refs: refs, remote: remote)
|
392
423
|
end
|
393
424
|
when :add, :sign
|
394
|
-
format_desc action, flag, 'name,message?,commit?'
|
395
|
-
task flag, [:name, :message, :commit] do |_, args|
|
396
|
-
name =
|
397
|
-
|
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
|
398
438
|
end
|
399
439
|
end
|
400
440
|
when 'stash'
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
end
|
441
|
+
format_desc(action, flag, 'opts*', after: case flag
|
442
|
+
when :push then 'pathspec*'
|
443
|
+
when :list then nil
|
444
|
+
else 'commit?' end)
|
406
445
|
task flag do |_, args|
|
407
446
|
stash flag, args.to_a
|
408
447
|
end
|
409
448
|
when 'log', 'diff'
|
410
449
|
case flag
|
411
450
|
when :view, :between, :contain
|
412
|
-
|
413
|
-
|
451
|
+
view = flag == :view
|
452
|
+
if view && action == 'log'
|
453
|
+
format_desc action, flag, '(^)commit*|:,opts*,ref?,pathspec*'
|
414
454
|
task flag do |_, args|
|
415
|
-
|
416
|
-
args.
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
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
|
423
471
|
end
|
472
|
+
args = args.drop(index.size)
|
424
473
|
end
|
425
|
-
log!(flag, args
|
474
|
+
log!(flag, args, index: index)
|
426
475
|
end
|
427
476
|
else
|
428
477
|
format_desc action, flag, 'commit1,commit2,opts*,pathspec*'
|
429
478
|
task flag, [:commit1, :commit2] do |_, args|
|
430
|
-
commit1 =
|
431
|
-
|
432
|
-
|
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)
|
433
491
|
end
|
434
492
|
end
|
435
493
|
when :head
|
436
|
-
format_desc action, flag, 'commit
|
494
|
+
format_desc action, flag, 'commit*|:,opts*,pathspec*'
|
437
495
|
task flag do |_, args|
|
438
|
-
|
439
|
-
args.
|
440
|
-
|
441
|
-
|
442
|
-
|
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)
|
443
512
|
end
|
444
|
-
diff(flag, args
|
513
|
+
diff(flag, args, index: index)
|
445
514
|
end
|
446
515
|
when :branch
|
447
516
|
format_desc action, flag, 'name,opts*,pathspec*'
|
@@ -460,7 +529,7 @@ module Squared
|
|
460
529
|
when 'checkout'
|
461
530
|
case flag
|
462
531
|
when :branch
|
463
|
-
format_desc action, flag, 'name
|
532
|
+
format_desc action, flag, 'name,create?=[bB],commit?,detach?=d'
|
464
533
|
task flag, [:name, :create, :commit, :detach] do |_, args|
|
465
534
|
if (branch = args.name)
|
466
535
|
branch = param_guard(action, flag, args: args, key: :name)
|
@@ -473,21 +542,21 @@ module Squared
|
|
473
542
|
commit = nil
|
474
543
|
detach = 'd'
|
475
544
|
elsif create && create.size > 1
|
476
|
-
commit = create
|
545
|
+
commit = commithead create
|
477
546
|
create = nil
|
478
547
|
detach = args.commit
|
479
548
|
else
|
480
549
|
detach = args.detach
|
481
|
-
commit = args.commit
|
550
|
+
commit = commithead args.commit
|
482
551
|
end
|
483
552
|
param_guard(action, flag, args: { create: create }, key: :create, pat: /\Ab\z/i) if create
|
484
553
|
else
|
485
|
-
branch = choice_refs 'Choose a branch to switch'
|
554
|
+
branch = choice_refs 'Choose a branch to switch'
|
486
555
|
end
|
487
556
|
checkout(flag, branch: branch, create: create, commit: commit, detach: detach)
|
488
557
|
end
|
489
558
|
when :track
|
490
|
-
format_desc action, flag, 'origin
|
559
|
+
format_desc action, flag, 'origin,(^)name?'
|
491
560
|
task flag, [:origin, :name] do |_, args|
|
492
561
|
if (origin = args.origin)
|
493
562
|
branch = args.name
|
@@ -497,15 +566,26 @@ module Squared
|
|
497
566
|
checkout(flag, branch: branch, origin: origin)
|
498
567
|
end
|
499
568
|
when :commit
|
500
|
-
format_desc action, flag, '
|
569
|
+
format_desc action, flag, 'ref,opts*'
|
501
570
|
task flag, [:commit] do |_, args|
|
502
|
-
commit =
|
503
|
-
|
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)
|
504
579
|
end
|
505
580
|
when :detach
|
506
|
-
format_desc action, flag, '
|
581
|
+
format_desc action, flag, 'ref?'
|
507
582
|
task flag, [:commit] do |_, args|
|
508
|
-
|
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)
|
509
589
|
end
|
510
590
|
when :path
|
511
591
|
format_desc action, flag, 'opts*,pathspec*'
|
@@ -516,33 +596,46 @@ module Squared
|
|
516
596
|
when 'branch'
|
517
597
|
case flag
|
518
598
|
when :create
|
519
|
-
format_desc action, flag, 'name,ref?=HEAD'
|
599
|
+
format_desc action, flag, 'name,ref?=HEAD|:'
|
520
600
|
task flag, [:name, :ref] do |_, args|
|
521
601
|
target = param_guard(action, flag, args: args, key: :name)
|
522
|
-
|
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)
|
523
605
|
end
|
524
|
-
when :
|
525
|
-
format_desc
|
606
|
+
when :track
|
607
|
+
format_desc action, flag, '(^~)upstream?,name?'
|
526
608
|
task flag, [:upstream, :name] do |_, args|
|
527
609
|
if (ref = args.upstream)
|
528
610
|
target = args.name
|
611
|
+
if ref.start_with?('~')
|
612
|
+
ref = ref[1..-1]
|
613
|
+
remote = true
|
614
|
+
end
|
529
615
|
else
|
530
|
-
ref, target = choice_refs('Choose a remote', 'remotes',
|
616
|
+
ref, remote, target = choice_refs('Choose a remote', 'remotes', accept: [['Push?', true]],
|
617
|
+
values: ['Enter branch name'])
|
531
618
|
end
|
532
|
-
branch(flag, target: target, ref: ref)
|
619
|
+
branch(flag, target: target, ref: ref, remote: remote)
|
533
620
|
end
|
534
621
|
when :delete
|
535
|
-
format_desc action, flag, '(^~)name
|
622
|
+
format_desc action, flag, '(^~)name*,:?'
|
536
623
|
task flag do |_, args|
|
537
|
-
|
538
|
-
|
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
|
539
637
|
end
|
540
|
-
branch(flag, refs: refs)
|
541
|
-
end
|
542
|
-
when :edit
|
543
|
-
format_desc action, flag, 'name?'
|
544
|
-
task flag, [:name] do |_, args|
|
545
|
-
branch(flag, target: args.name)
|
638
|
+
branch(flag, refs: refs, remote: remote)
|
546
639
|
end
|
547
640
|
when :list
|
548
641
|
format_desc action, flag, 'opts*,pattern*'
|
@@ -557,17 +650,55 @@ module Squared
|
|
557
650
|
else
|
558
651
|
format_desc action, flag, 'branch,oldbranch?'
|
559
652
|
task flag, [:branch, :oldbranch] do |_, args|
|
560
|
-
branch =
|
561
|
-
|
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)
|
562
683
|
end
|
563
684
|
end
|
564
685
|
when 'reset'
|
565
686
|
case flag
|
566
687
|
when :commit
|
567
|
-
format_desc action, flag, '
|
688
|
+
format_desc action, flag, 'ref|:,opts*'
|
568
689
|
task flag, [:commit] do |_, args|
|
569
|
-
commit =
|
570
|
-
|
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))
|
571
702
|
end
|
572
703
|
when :index
|
573
704
|
format_desc action, flag, 'opts*,pathspec*'
|
@@ -575,15 +706,18 @@ module Squared
|
|
575
706
|
reset flag, args.to_a
|
576
707
|
end
|
577
708
|
when :mode
|
578
|
-
format_desc action, flag, 'mode,ref?=HEAD'
|
709
|
+
format_desc action, flag, 'mode,ref?=HEAD|:'
|
579
710
|
task flag, [:mode, :ref] do |_, args|
|
580
711
|
mode = param_guard(action, flag, args: args, key: :mode)
|
581
|
-
|
712
|
+
ref = commithead args.ref
|
713
|
+
ref = choice_commit(reflog: false) if ref == ':'
|
714
|
+
reset(flag, mode: mode, ref: ref)
|
582
715
|
end
|
583
716
|
when :patch
|
584
|
-
format_desc action, flag, 'ref
|
717
|
+
format_desc action, flag, 'ref?=HEAD|:,pathspec*'
|
585
718
|
task flag, [:ref] do |_, args|
|
586
|
-
ref =
|
719
|
+
ref = commithead args.ref
|
720
|
+
ref = choice_commit(reflog: false) unless ref && ref != ':'
|
587
721
|
reset(flag, refs: args.extras, ref: ref)
|
588
722
|
end
|
589
723
|
end
|
@@ -592,7 +726,7 @@ module Squared
|
|
592
726
|
when :oneline
|
593
727
|
format_desc action, flag, 'opts*,object*'
|
594
728
|
task flag do |_, args|
|
595
|
-
show flag, args.to_a
|
729
|
+
show flag, args.to_a
|
596
730
|
end
|
597
731
|
when :format
|
598
732
|
format_desc action, flag, 'format?,opts*,object*'
|
@@ -609,23 +743,42 @@ module Squared
|
|
609
743
|
when 'rebase', 'merge'
|
610
744
|
case flag
|
611
745
|
when :branch
|
612
|
-
format_desc action, flag, '
|
613
|
-
task flag do |_, args|
|
614
|
-
|
615
|
-
|
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)
|
616
755
|
end
|
617
756
|
when :onto
|
618
|
-
format_desc action, flag, '
|
757
|
+
format_desc action, flag, 'ref,upstream,branch?=HEAD'
|
619
758
|
task flag, [:commit, :upstream, :branch] do |_, args|
|
620
|
-
commit =
|
621
|
-
|
622
|
-
|
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)
|
623
771
|
end
|
624
772
|
when :commit, :'no-commit'
|
625
|
-
format_desc action, flag, '
|
773
|
+
format_desc action, flag, 'refs+,opts*'
|
626
774
|
task flag do |_, args|
|
627
|
-
args =
|
628
|
-
|
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)
|
629
782
|
end
|
630
783
|
when :send
|
631
784
|
format_desc(action, flag, VAL_GIT[action.to_sym][:send], arg: nil)
|
@@ -640,25 +793,20 @@ module Squared
|
|
640
793
|
when :commit
|
641
794
|
format_desc action, flag, 'ref?=HEAD,size?'
|
642
795
|
task flag, [:ref, :size] do |_, args|
|
643
|
-
ref = args.ref
|
796
|
+
ref = commithead args.ref
|
644
797
|
size = args.size
|
645
|
-
if !size && ref.to_i
|
798
|
+
if !size && ref.to_i.between?(1, 40)
|
646
799
|
size = ref
|
647
800
|
ref = nil
|
648
801
|
end
|
649
802
|
rev_parse(flag, ref: ref, size: size)
|
650
803
|
end
|
651
|
-
when :branch
|
652
|
-
format_desc action, flag, 'ref?=HEAD'
|
653
|
-
task flag, [:ref] do |_, args|
|
654
|
-
rev_parse(flag, ref: args.ref)
|
655
|
-
end
|
656
804
|
when :build
|
657
805
|
format_desc action, flag, OPT_GIT[:status]
|
658
806
|
task flag do |_, args|
|
659
807
|
revbuild flag, args.to_a
|
660
808
|
end
|
661
|
-
|
809
|
+
when :output
|
662
810
|
format_desc action, flag, 'opts*,args*'
|
663
811
|
task flag do |_, args|
|
664
812
|
rev_parse flag, args.to_a
|
@@ -666,10 +814,9 @@ module Squared
|
|
666
814
|
end
|
667
815
|
when 'refs', 'files'
|
668
816
|
if flag == :remote
|
669
|
-
format_desc action, flag, 'remote
|
817
|
+
format_desc action, flag, 'remote?,opts*,pattern*'
|
670
818
|
task flag, [:remote] do |_, args|
|
671
|
-
|
672
|
-
ls_remote(flag, args.extras, remote: remote)
|
819
|
+
ls_remote(flag, args.extras, remote: args.remote)
|
673
820
|
end
|
674
821
|
else
|
675
822
|
format_desc action, flag, 'opts*,pattern*'
|
@@ -677,17 +824,57 @@ module Squared
|
|
677
824
|
__send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
|
678
825
|
end
|
679
826
|
end
|
680
|
-
when 'restore'
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
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)
|
689
876
|
task flag do |_, args|
|
690
|
-
|
877
|
+
git flag, args.to_a
|
691
878
|
end
|
692
879
|
end
|
693
880
|
end
|
@@ -744,16 +931,12 @@ module Squared
|
|
744
931
|
cmd, opts = git_session('rebase', opts: opts)
|
745
932
|
case flag
|
746
933
|
when :branch
|
934
|
+
return unless upstream
|
935
|
+
|
747
936
|
op = OptionPartition.new(opts, OPT_GIT[:rebase], cmd, project: self, no: OPT_GIT[:no][:rebase])
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
when 1, 2
|
752
|
-
op.append(delim: true)
|
753
|
-
else
|
754
|
-
op.append(op.pop(2), delim: true)
|
755
|
-
.clear(pass: false)
|
756
|
-
end
|
937
|
+
cmd << shell_escape(upstream)
|
938
|
+
append_head op.shift
|
939
|
+
op.clear(pass: false)
|
757
940
|
when :onto
|
758
941
|
return unless upstream
|
759
942
|
|
@@ -775,8 +958,8 @@ module Squared
|
|
775
958
|
|
776
959
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
777
960
|
cmd, opts = git_session('fetch', opts: opts)
|
778
|
-
append_pull(opts, collect_hash(OPT_GIT[:fetch]),
|
779
|
-
|
961
|
+
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]), remote: remote,
|
962
|
+
flag: flag)
|
780
963
|
cmd << '--all' if !remote && !session_arg?('multiple') && option('all')
|
781
964
|
cmd << '--verbose' if verbose && !session_arg?('quiet')
|
782
965
|
source(sync: sync, **threadargs)
|
@@ -807,8 +990,12 @@ module Squared
|
|
807
990
|
def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
|
808
991
|
if flag
|
809
992
|
cmd, opts = git_session('stash', flag, opts: opts)
|
810
|
-
|
811
|
-
|
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)
|
812
999
|
case flag
|
813
1000
|
when :push
|
814
1001
|
append_pathspec op.extras
|
@@ -823,6 +1010,7 @@ module Squared
|
|
823
1010
|
end
|
824
1011
|
return
|
825
1012
|
when :list
|
1013
|
+
op.clear
|
826
1014
|
out, banner, from = source(io: true)
|
827
1015
|
print_item banner
|
828
1016
|
list_result(write_lines(out), 'objects', from: from)
|
@@ -830,8 +1018,8 @@ module Squared
|
|
830
1018
|
end
|
831
1019
|
else
|
832
1020
|
git_session('stash', 'push', opts: opts)
|
833
|
-
append_option(
|
834
|
-
append_message
|
1021
|
+
append_option(OPT_GIT[:stash][:push].grep_v(/[=|]/), no: true, ignore: false)
|
1022
|
+
append_message
|
835
1023
|
end
|
836
1024
|
source(banner: !quiet?, sync: sync, **threadargs)
|
837
1025
|
end
|
@@ -839,6 +1027,7 @@ module Squared
|
|
839
1027
|
def status(*)
|
840
1028
|
cmd = git_session 'status'
|
841
1029
|
cmd << (option('long') ? '--long' : '--short')
|
1030
|
+
cmd << '--branch' if option('branch')
|
842
1031
|
if (val = option('ignore-submodules', ignore: false))
|
843
1032
|
cmd << basic_option('ignore-submodules', case val
|
844
1033
|
when '0', 'none'
|
@@ -852,18 +1041,22 @@ module Squared
|
|
852
1041
|
end)
|
853
1042
|
end
|
854
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
|
855
1058
|
out, banner, from = source(io: true)
|
856
|
-
ret = write_lines(out, banner: banner, sub:
|
857
|
-
r = color(:red)
|
858
|
-
g = color(:green)
|
859
|
-
[
|
860
|
-
{ pat: /^(.)([A-Z?!])(.+)$/, styles: r, index: 2 },
|
861
|
-
{ pat: /^([A-Z?!])(.+)$/, styles: g },
|
862
|
-
{ pat: /^(\?\?)(.+)$/, styles: r },
|
863
|
-
{ pat: /^(## )(.+)(\.{3})(.+)$/,
|
864
|
-
styles: [nil, g, nil, r], index: -1 }
|
865
|
-
]
|
866
|
-
end)
|
1059
|
+
ret = write_lines(out, banner: banner, sub: sub)
|
867
1060
|
list_result(ret, 'files', from: from, action: 'modified')
|
868
1061
|
end
|
869
1062
|
|
@@ -927,13 +1120,14 @@ module Squared
|
|
927
1120
|
case flag
|
928
1121
|
when :commit, :index
|
929
1122
|
op = OptionPartition.new(opts, OPT_GIT[:reset] + VAL_GIT[:reset], cmd,
|
930
|
-
project: self, no: OPT_GIT[:no][:reset]
|
1123
|
+
project: self, no: OPT_GIT[:no][:reset],
|
1124
|
+
first: flag == :index ? matchpathspec : nil)
|
931
1125
|
if flag == :commit
|
932
|
-
op.append(commit
|
1126
|
+
op.append(commit)
|
933
1127
|
.clear(pass: false)
|
934
1128
|
ref = false
|
935
1129
|
else
|
936
|
-
|
1130
|
+
refs = op.extras
|
937
1131
|
end
|
938
1132
|
when :mode
|
939
1133
|
return unless VAL_GIT[:reset].include?(mode)
|
@@ -945,6 +1139,7 @@ module Squared
|
|
945
1139
|
end
|
946
1140
|
when :patch
|
947
1141
|
cmd << '--patch'
|
1142
|
+
append_pathspec(refs, pass: false)
|
948
1143
|
end
|
949
1144
|
unless ref == false
|
950
1145
|
append_commit(ref, head: true)
|
@@ -953,7 +1148,7 @@ module Squared
|
|
953
1148
|
source
|
954
1149
|
end
|
955
1150
|
|
956
|
-
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)
|
957
1152
|
cmd, opts = git_session('checkout', opts: opts)
|
958
1153
|
append_option 'force', 'merge'
|
959
1154
|
case flag
|
@@ -971,21 +1166,23 @@ module Squared
|
|
971
1166
|
end
|
972
1167
|
cmd << '--track' << shell_quote(origin)
|
973
1168
|
when :detach
|
1169
|
+
cmd << '-m' if merge
|
974
1170
|
cmd << '--detach' << commit
|
975
1171
|
else
|
976
|
-
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)
|
977
1174
|
if flag == :commit
|
978
|
-
op.append(commit
|
1175
|
+
op.append(commit)
|
979
1176
|
.clear(pass: false)
|
980
1177
|
else
|
981
1178
|
append_head
|
982
|
-
append_pathspec
|
1179
|
+
append_pathspec(op.extras, pass: false)
|
983
1180
|
end
|
984
1181
|
end
|
985
1182
|
source
|
986
1183
|
end
|
987
1184
|
|
988
|
-
def tag(flag, opts = [], refs: [], message: nil, commit: nil)
|
1185
|
+
def tag(flag, opts = [], refs: [], message: nil, commit: nil, remote: nil)
|
989
1186
|
cmd, opts = git_session('tag', opts: opts)
|
990
1187
|
case flag
|
991
1188
|
when :add, :sign
|
@@ -997,31 +1194,32 @@ module Squared
|
|
997
1194
|
cmd << '--force' if option('force')
|
998
1195
|
if !commit && message && (sha = commithash(message))
|
999
1196
|
commit = sha
|
1000
|
-
|
1001
|
-
append_message message
|
1197
|
+
message = nil
|
1002
1198
|
end
|
1199
|
+
append_message message
|
1003
1200
|
append_value refs
|
1004
1201
|
append_head commit
|
1005
|
-
when :
|
1202
|
+
when :delete
|
1203
|
+
cmd << '--delete'
|
1204
|
+
append_value refs
|
1205
|
+
else
|
1006
1206
|
op = OptionPartition.new(opts, OPT_GIT[:tag], cmd << '--list', project: self, no: OPT_GIT[:no][:tag])
|
1007
1207
|
out, banner, from = source(io: true)
|
1008
1208
|
print_item banner
|
1009
1209
|
ret = write_lines(out, grep: op.extras)
|
1010
1210
|
list_result(ret, 'tags', from: from, grep: op.extras)
|
1011
1211
|
return
|
1012
|
-
when :delete
|
1013
|
-
cmd << '--delete'
|
1014
|
-
append_value refs
|
1015
|
-
else
|
1016
|
-
cmd << shell_option(flag, commit)
|
1017
1212
|
end
|
1213
|
+
remote ||= option('remote')
|
1018
1214
|
source
|
1215
|
+
git_spawn('push', flag == :delete ? '-d' : nil, remote, *refs.map { |val| shell_quote(val) }) if remote
|
1019
1216
|
end
|
1020
1217
|
|
1021
1218
|
def log!(flag, opts = [], range: [], index: [])
|
1022
1219
|
cmd, opts = git_session('log', opts: opts)
|
1023
1220
|
op = OptionPartition.new(opts, collect_hash(OPT_GIT[:log]), cmd,
|
1024
|
-
project: self, no: collect_hash(OPT_GIT[:no][:log])
|
1221
|
+
project: self, no: collect_hash(OPT_GIT[:no][:log]),
|
1222
|
+
first: matchpathspec)
|
1025
1223
|
case flag
|
1026
1224
|
when :between, :contain
|
1027
1225
|
op << shell_quote(range.join(flag == :between ? '..' : '...'))
|
@@ -1036,7 +1234,8 @@ module Squared
|
|
1036
1234
|
def diff(flag, opts = [], refs: [], branch: nil, range: [], index: [])
|
1037
1235
|
cmd, opts = git_session('diff', opts: opts)
|
1038
1236
|
op = OptionPartition.new(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff], cmd,
|
1039
|
-
project: self, no: OPT_GIT[:no][:log][:diff]
|
1237
|
+
project: self, no: OPT_GIT[:no][:log][:diff],
|
1238
|
+
first: flag == :files ? nil : matchpathspec)
|
1040
1239
|
case flag
|
1041
1240
|
when :files, :view, :between, :contain
|
1042
1241
|
op.delete('--cached')
|
@@ -1049,7 +1248,7 @@ module Squared
|
|
1049
1248
|
case flag
|
1050
1249
|
when :view
|
1051
1250
|
op << '--merge-base' if option('merge-base')
|
1052
|
-
op
|
1251
|
+
op.merge(range)
|
1053
1252
|
when :between, :contain
|
1054
1253
|
op.delete('--merge-base')
|
1055
1254
|
op << shell_quote(range.join(flag == :between ? '..' : '...'))
|
@@ -1072,82 +1271,99 @@ module Squared
|
|
1072
1271
|
source(exception: op.arg?('exit-code'))
|
1073
1272
|
end
|
1074
1273
|
|
1075
|
-
def commit(flag,
|
1076
|
-
|
1077
|
-
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
|
1078
1292
|
if !message && !amend
|
1079
1293
|
return if pass
|
1080
1294
|
|
1081
|
-
|
1295
|
+
message = readline('Enter message', force: true)
|
1082
1296
|
end
|
1083
|
-
pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
|
1084
|
-
'--all'
|
1085
|
-
elsif (refs = projectmap(refs)).empty?
|
1086
|
-
raise_error 'no qualified pathspec'
|
1087
|
-
else
|
1088
|
-
"-- #{refs.join(' ')}"
|
1089
|
-
end
|
1090
|
-
origin = nil
|
1091
1297
|
branch = nil
|
1298
|
+
origin = nil
|
1092
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)'
|
1093
1305
|
git_spawn 'fetch --no-tags --quiet'
|
1094
|
-
|
1095
|
-
next
|
1096
|
-
|
1097
|
-
branch =
|
1098
|
-
if
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
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)
|
1110
1321
|
end
|
1111
1322
|
end
|
1112
|
-
|
1323
|
+
raise_error('missing remote name', hint: origin) unless origin.include?('/')
|
1324
|
+
upstream = true
|
1113
1325
|
end
|
1114
1326
|
break
|
1115
1327
|
end
|
1116
|
-
|
1117
|
-
|
1118
|
-
if amend
|
1119
|
-
cmd << '--amend'
|
1328
|
+
if pathspec
|
1329
|
+
op << pathspec
|
1120
1330
|
else
|
1121
|
-
|
1331
|
+
append_pathspec op.extras
|
1122
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'
|
1339
|
+
end
|
1340
|
+
co << '--amend' if amend
|
1123
1341
|
if message
|
1124
1342
|
append_message message
|
1125
1343
|
elsif flag == :'amend-orig' || option('edit', equals: '0')
|
1126
|
-
|
1127
|
-
end
|
1128
|
-
a = git_output 'add', '--verbose'
|
1129
|
-
b = git_output 'push', upstream && '--set-upstream'
|
1130
|
-
if dryrun?
|
1131
|
-
a << '--dry-run'
|
1132
|
-
b << '--dry-run'
|
1344
|
+
co << '--no-edit'
|
1133
1345
|
end
|
1134
|
-
|
1135
|
-
|
1136
|
-
b << origin << branch
|
1346
|
+
pu << '--force-with-lease' if amend
|
1347
|
+
pu.merge(repotrack(origin, branch))
|
1137
1348
|
puts if pass
|
1138
|
-
source
|
1139
|
-
source
|
1140
|
-
source
|
1349
|
+
source op
|
1350
|
+
source co
|
1351
|
+
source pu
|
1141
1352
|
end
|
1142
1353
|
|
1143
|
-
def merge(flag, opts = [], command: nil)
|
1354
|
+
def merge(flag, opts = [], command: nil, branch: nil)
|
1144
1355
|
cmd, opts = git_session('merge', opts: opts)
|
1145
1356
|
case flag
|
1146
1357
|
when :commit, :'no-commit'
|
1147
1358
|
op = OptionPartition.new(opts, OPT_GIT[:merge], cmd, project: self, no: OPT_GIT[:no][:merge])
|
1148
1359
|
raise_error 'no branch/commit' if op.empty?
|
1149
1360
|
op << "--#{flag}" << '--'
|
1150
|
-
|
1361
|
+
if branch
|
1362
|
+
op << branch
|
1363
|
+
op.clear(pass: false)
|
1364
|
+
else
|
1365
|
+
append_commit(*op.extras)
|
1366
|
+
end
|
1151
1367
|
else
|
1152
1368
|
return unless VAL_GIT[:merge][:send].include?(command)
|
1153
1369
|
|
@@ -1156,7 +1372,7 @@ module Squared
|
|
1156
1372
|
source
|
1157
1373
|
end
|
1158
1374
|
|
1159
|
-
def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil)
|
1375
|
+
def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil, remote: nil)
|
1160
1376
|
cmd, opts = git_session('branch', opts: opts)
|
1161
1377
|
stdout = false
|
1162
1378
|
case flag
|
@@ -1172,43 +1388,46 @@ module Squared
|
|
1172
1388
|
end
|
1173
1389
|
end
|
1174
1390
|
cmd << '--force' if option('force')
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
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?('/')
|
1178
1395
|
if ref.start_with?('^')
|
1179
|
-
cmd << '--unset-upstream' <<
|
1180
|
-
|
1396
|
+
cmd << '--unset-upstream' << shell_quote(ref[1..-1])
|
1397
|
+
remote = false
|
1181
1398
|
stdout = true
|
1182
1399
|
else
|
1183
1400
|
cmd << quote_option('set-upstream-to', ref)
|
1401
|
+
cmd << shell_quote(target) if target
|
1184
1402
|
end
|
1185
|
-
ref = nil
|
1186
1403
|
when :delete
|
1404
|
+
remote&.each do |val|
|
1405
|
+
source git_output('push', '--delete', *val.split('/', 2).map { |s| shell_quote(s) })
|
1406
|
+
end
|
1187
1407
|
force, list = refs.partition { |val| val.match?(/^[~^]/) }
|
1188
1408
|
force.each do |val|
|
1189
|
-
dr = val[0,
|
1409
|
+
dr = val[0, 2]
|
1190
1410
|
d = dr.include?('^') ? '-D' : '-d'
|
1191
1411
|
r = '-r' if dr.include?('~')
|
1192
|
-
source git_output('branch', d, r, shell_quote(val.sub(/^[
|
1412
|
+
source git_output('branch', d, r, shell_quote(val.sub(/^[~^]+/, '')))
|
1193
1413
|
end
|
1194
1414
|
return if list.empty?
|
1195
1415
|
|
1196
1416
|
cmd << '-d'
|
1197
1417
|
append_value list
|
1418
|
+
remote = nil
|
1198
1419
|
when :move, :copy
|
1199
1420
|
flag = "-#{flag.to_s[0]}"
|
1200
1421
|
cmd << (option('force') ? flag.upcase : flag)
|
1201
1422
|
refs.compact.each { |val| cmd << shell_quote(val) }
|
1202
1423
|
stdout = true
|
1203
|
-
when :edit
|
1204
|
-
cmd << '--edit-description'
|
1205
1424
|
when :current
|
1206
1425
|
cmd << '--show-current'
|
1207
1426
|
source(banner: verbosetype > 1, stdout: true)
|
1208
1427
|
return
|
1209
1428
|
when :list
|
1210
1429
|
op = OptionPartition.new(opts, OPT_GIT[:branch], cmd << '--list',
|
1211
|
-
project: self, no: OPT_GIT[:no][:branch], single:
|
1430
|
+
project: self, no: OPT_GIT[:no][:branch], single: /\Av+\z/)
|
1212
1431
|
op.each { |val| op << shell_quote(val) }
|
1213
1432
|
out, banner, from = source(io: true)
|
1214
1433
|
print_item banner
|
@@ -1250,15 +1469,46 @@ module Squared
|
|
1250
1469
|
end
|
1251
1470
|
return
|
1252
1471
|
end
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
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
|
1256
1479
|
end
|
1257
1480
|
|
1258
|
-
def
|
1259
|
-
cmd
|
1260
|
-
|
1261
|
-
|
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)
|
1262
1512
|
source(sync: false, stderr: true)
|
1263
1513
|
end
|
1264
1514
|
|
@@ -1267,14 +1517,13 @@ module Squared
|
|
1267
1517
|
case flag
|
1268
1518
|
when :textconv
|
1269
1519
|
cmd << '--textconv'
|
1270
|
-
append_value(files.
|
1271
|
-
.flatten
|
1520
|
+
append_value(files.flat_map { |val| Dir[val] }
|
1272
1521
|
.select { |val| projectpath?(val) }
|
1273
1522
|
.map! { |val| shell_quote("HEAD:#{val}") })
|
1274
1523
|
source(banner: false)
|
1275
1524
|
return
|
1276
1525
|
when :oneline
|
1277
|
-
format =
|
1526
|
+
format = 'oneline'
|
1278
1527
|
end
|
1279
1528
|
if format
|
1280
1529
|
case (val = format.downcase)
|
@@ -1291,21 +1540,12 @@ module Squared
|
|
1291
1540
|
op = OptionPartition.new(opts, OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff], cmd,
|
1292
1541
|
project: self,
|
1293
1542
|
no: OPT_GIT[:no][:show] + collect_hash(OPT_GIT[:no][:log], pass: [:base]))
|
1294
|
-
unless val == 'oneline' && op.arg?('abbrev-commit')
|
1295
|
-
op << basic_option('abbrev', val) if (val = option('abbrev')) && val.to_i > 0
|
1296
|
-
banner = true
|
1297
|
-
end
|
1298
1543
|
op.append(delim: true)
|
1299
|
-
source(exception: false, banner:
|
1544
|
+
source(exception: false, banner: flag != :oneline)
|
1300
1545
|
end
|
1301
1546
|
|
1302
1547
|
def rev_parse(flag, opts = [], ref: nil, size: nil)
|
1303
1548
|
cmd, opts = git_session('rev-parse', opts: opts)
|
1304
|
-
cmd << if flag == :parseopt
|
1305
|
-
'--parseopt'
|
1306
|
-
elsif opts.delete('sq-quote')
|
1307
|
-
'--sq-quote'
|
1308
|
-
end
|
1309
1549
|
case flag
|
1310
1550
|
when :commit
|
1311
1551
|
cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
|
@@ -1313,9 +1553,14 @@ module Squared
|
|
1313
1553
|
when :branch
|
1314
1554
|
cmd << '--abbrev-ref'
|
1315
1555
|
append_commit(ref, head: true)
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
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)
|
1319
1564
|
end
|
1320
1565
|
source(banner: verbosetype > 1)
|
1321
1566
|
end
|
@@ -1342,18 +1587,10 @@ module Squared
|
|
1342
1587
|
|
1343
1588
|
def git(flag, opts = [])
|
1344
1589
|
cmd, opts = git_session(flag, opts: opts)
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
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)
|
1348
1593
|
case flag
|
1349
|
-
when :clean
|
1350
|
-
refs = projectmap(op.extras)
|
1351
|
-
unless refs.empty?
|
1352
|
-
op << '--'
|
1353
|
-
op.merge(refs)
|
1354
|
-
end
|
1355
|
-
sync = true
|
1356
|
-
stderr = false
|
1357
1594
|
when :revert
|
1358
1595
|
if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
|
1359
1596
|
op.clear
|
@@ -1362,14 +1599,29 @@ module Squared
|
|
1362
1599
|
else
|
1363
1600
|
append_commit(*op.extras)
|
1364
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
|
1365
1617
|
when :mv
|
1366
|
-
refs = projectmap
|
1618
|
+
refs = projectmap op.extras
|
1367
1619
|
raise_error 'no source/destination' unless refs.size > 1
|
1368
1620
|
op.merge(refs)
|
1369
1621
|
when :rm
|
1370
|
-
append_pathspec(op.extras, expect:
|
1622
|
+
append_pathspec(op.extras, expect: !op.arg?('pathspec-from-file'))
|
1371
1623
|
end
|
1372
|
-
source(sync:
|
1624
|
+
source(sync: false, stderr: true)
|
1373
1625
|
end
|
1374
1626
|
|
1375
1627
|
def clone?
|
@@ -1388,16 +1640,17 @@ module Squared
|
|
1388
1640
|
|
1389
1641
|
def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
|
1390
1642
|
multiple: false, sub: nil)
|
1643
|
+
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
1391
1644
|
banner = nil if multiple && banner
|
1392
1645
|
if cmd.respond_to?(:done)
|
1393
1646
|
if io && banner == false
|
1394
1647
|
from = nil
|
1395
|
-
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/) })
|
1396
1649
|
from = :"git:#{from}"
|
1397
1650
|
end
|
1398
1651
|
banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
|
1399
1652
|
end
|
1400
|
-
cmd = session_done
|
1653
|
+
cmd = session_done cmd
|
1401
1654
|
log&.info cmd
|
1402
1655
|
on :first, from
|
1403
1656
|
banner = if banner
|
@@ -1414,20 +1667,20 @@ module Squared
|
|
1414
1667
|
ret = `#{cmd}`
|
1415
1668
|
if !ret.empty?
|
1416
1669
|
puts ret
|
1417
|
-
elsif banner
|
1418
|
-
|
1670
|
+
elsif success?(!banner.nil?)
|
1671
|
+
print_success
|
1419
1672
|
end
|
1420
1673
|
elsif sync || (!exception && !stderr)
|
1421
1674
|
print_item banner unless multiple
|
1422
|
-
shell(cmd, exception: exception)
|
1675
|
+
ret = shell(cmd, exception: exception)
|
1423
1676
|
else
|
1424
1677
|
require 'open3'
|
1425
1678
|
if stderr
|
1426
1679
|
Open3.popen3(cmd) do |_, out, err|
|
1427
|
-
|
1428
|
-
if
|
1429
|
-
|
1430
|
-
|
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?)
|
1431
1684
|
else
|
1432
1685
|
write_lines(err, loglevel: Logger::DEBUG)
|
1433
1686
|
end
|
@@ -1442,8 +1695,10 @@ module Squared
|
|
1442
1695
|
raise if exception && ret != true
|
1443
1696
|
|
1444
1697
|
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1698
|
+
nil
|
1445
1699
|
else
|
1446
1700
|
on :last, from
|
1701
|
+
ret
|
1447
1702
|
end
|
1448
1703
|
end
|
1449
1704
|
|
@@ -1484,7 +1739,7 @@ module Squared
|
|
1484
1739
|
styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
|
1485
1740
|
styles << :bold if styles.size <= 1
|
1486
1741
|
puts print_footer("#{size} #{size == 1 ? type.sub(/(?:(?<!l)e)?s\z/, '') : type}",
|
1487
|
-
sub: { pat: /\A(\d+)(.+)\z
|
1742
|
+
sub: { pat: /\A(\d+)(.+)\z/m, styles: styles })
|
1488
1743
|
else
|
1489
1744
|
puts empty_status("No #{type} were #{action}", 'grep', grep.is_a?(Array) ? case grep.size
|
1490
1745
|
when 0
|
@@ -1497,20 +1752,32 @@ module Squared
|
|
1497
1752
|
on :last, from
|
1498
1753
|
end
|
1499
1754
|
|
1500
|
-
def choice_refs(msg, type, format: nil, sort: '-creatordate', count:
|
1755
|
+
def choice_refs(msg, *type, format: nil, sort: '-creatordate', count: true, short: true, **kwargs)
|
1756
|
+
type << 'heads' if type.empty?
|
1501
1757
|
unless format
|
1502
1758
|
format = +"%(refname#{short ? ':short' : ''})"
|
1503
|
-
|
1504
|
-
when 'heads', 'tags'
|
1759
|
+
if type.include?('heads') || type.include?('tags')
|
1505
1760
|
format += '%(if)%(HEAD)%(then) *%(end)'
|
1506
1761
|
trim = /\s+\*\z/
|
1507
1762
|
end
|
1508
1763
|
end
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
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)
|
1514
1781
|
end
|
1515
1782
|
|
1516
1783
|
def status_digest(*args, algorithm: nil, **kwargs)
|
@@ -1524,15 +1791,11 @@ module Squared
|
|
1524
1791
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1525
1792
|
next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1526
1793
|
|
1527
|
-
ret[file] = algorithm.hexdigest(File.read(
|
1794
|
+
ret[file] = algorithm.hexdigest(File.read(path + file))
|
1528
1795
|
end
|
1529
1796
|
ret
|
1530
1797
|
end
|
1531
1798
|
|
1532
|
-
def git_spawn(*cmd, stdout: true)
|
1533
|
-
source(git_output(*cmd), io: true, banner: false, stdout: stdout)
|
1534
|
-
end
|
1535
|
-
|
1536
1799
|
def append_pull(opts, list, target: @session, flag: nil, no: nil, remote: nil)
|
1537
1800
|
target << '--force' if option('force', target: target)
|
1538
1801
|
append_submodules(target: target)
|
@@ -1589,7 +1852,7 @@ module Squared
|
|
1589
1852
|
option_clear files
|
1590
1853
|
else
|
1591
1854
|
if files.empty? && (val = option('pathspec', target: target))
|
1592
|
-
files = split_escape
|
1855
|
+
files = split_escape val
|
1593
1856
|
end
|
1594
1857
|
files = projectmap(files, parent: parent, pass: pass)
|
1595
1858
|
if !files.empty?
|
@@ -1600,12 +1863,13 @@ module Squared
|
|
1600
1863
|
end
|
1601
1864
|
end
|
1602
1865
|
|
1603
|
-
def append_message(val, target: @session)
|
1604
|
-
|
1866
|
+
def append_message(val = nil, target: @session)
|
1867
|
+
val = messageopt if val.to_s.empty?
|
1868
|
+
target << quote_option('message', val) if val
|
1605
1869
|
end
|
1606
1870
|
|
1607
1871
|
def append_head(val = nil, target: @session)
|
1608
|
-
return target << val if val
|
1872
|
+
return target << shell_quote(val) if val
|
1609
1873
|
|
1610
1874
|
append_first('head', 'tree-ish', 'object', target: target, flag: false, ignore: false)
|
1611
1875
|
end
|
@@ -1614,22 +1878,33 @@ module Squared
|
|
1614
1878
|
return unless (val = option('recurse-submodules', target: target, ignore: false))
|
1615
1879
|
|
1616
1880
|
if from == :clone
|
1617
|
-
|
1618
|
-
|
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
|
1619
1890
|
end
|
1620
|
-
target
|
1621
1891
|
else
|
1622
1892
|
target << case val
|
1623
1893
|
when 'no', '0', 'false'
|
1624
1894
|
'--no-recurse-submodules'
|
1625
1895
|
when 'yes', 'on-demand'
|
1626
|
-
"--recurse-submodules
|
1896
|
+
"--recurse-submodules=#{val}"
|
1627
1897
|
else
|
1628
1898
|
'--recurse-submodules'
|
1629
1899
|
end
|
1630
1900
|
end
|
1631
1901
|
end
|
1632
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
|
+
|
1633
1908
|
def git_session(*cmd, opts: nil, worktree: true, **kwargs)
|
1634
1909
|
dir = worktree ? ["--work-tree=#{shell_quote(path)}", "--git-dir=#{shell_quote(gitpath)}"] : []
|
1635
1910
|
return session('git', *dir, *cmd, **kwargs) unless opts
|
@@ -1643,10 +1918,14 @@ module Squared
|
|
1643
1918
|
git_session(*cmd, main: false, options: false, **kwargs)
|
1644
1919
|
end
|
1645
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
|
+
|
1646
1925
|
def dryrun?(*, target: @session, **)
|
1647
1926
|
return false unless target
|
1648
1927
|
|
1649
|
-
target.include?('--dry-run')
|
1928
|
+
target.include?('--dry-run') || !option('dry-run', target: target).nil?
|
1650
1929
|
end
|
1651
1930
|
|
1652
1931
|
def quiet?(target: @session)
|
@@ -1656,11 +1935,36 @@ module Squared
|
|
1656
1935
|
end
|
1657
1936
|
|
1658
1937
|
def gitpath
|
1659
|
-
|
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
|
1660
1946
|
end
|
1661
1947
|
|
1662
1948
|
def commithash(val)
|
1663
|
-
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)
|
1664
1968
|
end
|
1665
1969
|
|
1666
1970
|
def threadargs
|