squared 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -72,23 +72,111 @@ module Squared
72
72
 
73
73
  module Project
74
74
  class Git < Base
75
- FOR_FETCH = %w[atomic multiple negotiate-only prefetch progress prune-tags refetch recurse-submodules=s].freeze
76
- NO_FETCH = %w[all ipv4 ipv6 recurse-submodules show-forced-updates tags].freeze
77
- FNO_FETCH = %w[auto-gc auto-maintenance write-commit-graph write-fetch-head].freeze
78
- OPT_FETCH = (FOR_FETCH + NO_FETCH + FNO_FETCH +
79
- %w[append dry-run force keep prune quiet set-upstream unshallow update-shallow verbose
80
- deepen=i depth=i jobs=i negotiation-tip=s refmap=s server-option=s shallow-exclude=s
81
- shallow-since=d upload-pack=s]).freeze
82
- NO_PULL = %w[allow-unrelated-histories autostash commit edit ff signoff squash stat verify verify-signatures
83
- gpg-sign=? log=? rebase=?].freeze
84
- OPT_PULL = (NO_PULL + %w[ff-only signoff=s strategy=s strategy-option=s]).freeze
85
- OPT_REBASE = %w[continue skip abort quit].freeze
86
- VAL_REBASE = %w[true false merges interactive].freeze
87
- NO_BRANCH = %w[abbrev=i color=? column=? track=?].freeze
88
- OPT_BRANCH = (NO_BRANCH + %w[all create-reflog ignore-case quiet remotes verbose
89
- contains=s format=s merged=s no-contains=s no-merged=s points-at=s sort=s]).freeze
90
- private_constant :FOR_FETCH, :NO_FETCH, :FNO_FETCH, :OPT_FETCH, :NO_PULL, :OPT_PULL, :OPT_REBASE, :VAL_REBASE,
91
- :NO_BRANCH, :OPT_BRANCH
75
+ OPT_GIT = {
76
+ branch: %w[a|all create-reflog i|ignore-case q|quiet r|remotes v|verbose abbrev=i color=b column=b
77
+ contains=e format=q merged=e no-contains=e no-merged=e points-at=e u|set-upstream-to=e sort=q
78
+ t|track=b].freeze,
79
+ checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
80
+ pathspec-file-nul q quiet orphan=e ours theirs conflict=b pathspec-from-file=p
81
+ t|track=b].freeze,
82
+ diff: {
83
+ base: %w[0 1|base 2|ours 3|theirs].freeze,
84
+ show: %w[s exit-code histogram].freeze
85
+ }.freeze,
86
+ fetch: {
87
+ base: %w[multiple progress P|prune-tags refetch stdin u|update-head-ok recurse-submodules=s
88
+ recurse-submodules-default=b].freeze,
89
+ pull: %w[4 6 n t a|append atomic dry-run f|force k|keep n|negotiate-only prefetch p|prune q|quiet
90
+ set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
91
+ refmap=q o|server-option=e shallow-exclude=e shallow-since=s upload-pack=e].freeze
92
+ }.freeze,
93
+ log: {
94
+ base: %w[all all-match alternate-refs author-date-order basic-regexp bisect boundary cherry cherry-mark
95
+ cherry-pick clear-decorations date-order dense do-walk exclude-first-parent-only E|extended-regexp
96
+ first-parent F|fixed-strings follow full-diff full-history ignore-missing invert-grep left-only
97
+ merge log-size no-max-parents no-min-parents not P|perl-regexp reflog i|regexp-ignore-case
98
+ remove-empty reverse right-only simplify-by-decoration simplify-merges single-worktree show-pulls
99
+ source sparse stdin topo-order g|walk-reflogs after=q ancestry-path=e? author=q before=q
100
+ branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q exclude=q
101
+ exclude-hidden=b? glob=q grep=q grep-reflog=q L=q n|max-count=i max-parents=i min-parents=i
102
+ no-walk=b? remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
103
+ format: %w[t children combined-all-paths oneline left-right no-diff-merges parents relative-date
104
+ show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q notes=q pretty=q?
105
+ show-linear-break=q?].freeze,
106
+ diff: %w[p R u z l=i G=q O=q S=q binary check compact-summary cumulative find-copies-harder full-index
107
+ W|function-context w|ignore-all-space ignore-blank-lines ignore-cr-at-eol ignore-space-at-eol
108
+ b|ignore-space-change D|irreversible-delete graph ita-invisible-in-index minimal name-only
109
+ name-status no-color-moved-ws no-prefix no-renames numstat patch-with-raw patch-with-stat patience
110
+ pickaxe-all pickaxe-regex raw shortstat summary a|text abbrev=i? anchored=q B|break-rewrites=e?
111
+ color=b color-moved=b color-moved-ws=b color-words=q? diff-algorithm=b diff-filter=e? X|dirstat=q?
112
+ dirstat-by-file=q? dst-prefix=q C|find-copies=i? find-object=e M|find-renames=i?
113
+ I|ignore-matching-lines=q ignore-submodules=b inter-hunk-context=i line-prefix=q output=p
114
+ output-indicator-context=q output-indicator-new=q output-indicator-old=q relative=p rotate-to=p
115
+ skip-to=p src-prefix=q stat=q? stat-width=i stat-name-width=i stat-count=i submodule=b? U|unified=i
116
+ word-diff=b? word-diff-regex=q ws-error-highligt=q].freeze
117
+ }.freeze,
118
+ ls_files: %w[z debug deduplicate directory eol error-unmatch exclude-standard full-name k|killed
119
+ no-empty-directory recurse-submodules sparse s|stage u|unmerged abbrev=i x|exclude=q
120
+ X|exclude-from=p exclude-per-directory=p format=q with-tree=q].freeze,
121
+ ls_remote: %w[exit-code get-url q|quiet o|server-option=e symref sort=q upload-pack=e].freeze,
122
+ pull: %w[e n allow-unrelated-histories ff-only S|gpg-sign=e log=i rebase=s s|strategy=b
123
+ X|strategy-option=e].freeze,
124
+ rebase: %w[n C=i allow-empty-message apply committer-date-is-author-date edit-todo f|force-rebase ignore-date
125
+ ignore-whitespace i|interactive keep-base m merge no-ff q|quiet quit r|rebase-merges=b?
126
+ reset-author-date root show-current-patch signoff v|verbose empty=b S|gpg-sign=b onto=e
127
+ s|strategy=b X|strategy-option=b whitespace=e].freeze,
128
+ reset: %w[N pathspec-file-nul q|quiet pathspec-from-file=p].freeze,
129
+ restore: %w[ignore-unmerged ignore-skip-worktree-bits m|merge ours p|patch pathspec-file-nul S|staged theirs
130
+ W|worktree conflict=b pathspec-from-file=p s|source=q].freeze,
131
+ rev_parse: {
132
+ output: %w[absolute-git-dir all flags git-common-dir git-dir is-bare-repository is-inside-git-dir
133
+ is-inside-work-tree is-shallow-repository local-env-vars no-flags no-revs not q|quiet sq
134
+ revs-only shared-index-path show-cdup show-prefix show-toplevel show-superproject-working-tree
135
+ sq-quote symbolic symbolic-full-name verify abbrev-ref=b? after=q before=q default=e
136
+ disambiguate=b exclude=q exclude-hidden=b glob=q git-path=p path-format=b? prefix=q branches=q?
137
+ remotes=q? resolve-git-dir=p short=i? show-object-format=b? since=q tags=q? until=q].freeze,
138
+ parseopt: %w[keep-dashdash stop-at-non-option stuck-long].freeze
139
+ }.freeze,
140
+ show: %w[t combined-all-paths no-diff-merges remerge-diff show-signature diff-merges=b encoding=b
141
+ expand-tabs=i notes=q show-notes=q?].freeze,
142
+ stash: {
143
+ common: %w[q|quiet].freeze,
144
+ push: %w[a|all u|include-untracked k|keep-index no-keep-index p|patch S|staged m|message=q
145
+ pathspec-from-file=p].freeze,
146
+ pop: %w[index].freeze,
147
+ apply: %w[index].freeze
148
+ }.freeze,
149
+ tag: %w[create-reflog column=b contains=e? format=q merged=e? n=i no-contains=e? no-merged=e? points-at=q
150
+ sort=q].freeze,
151
+ no: {
152
+ fetch: {
153
+ base: %w[auto-gc auto-maintenance write-commit-graph write-fetch-head].freeze,
154
+ pull: %w[all ipv4 ipv6 recurse-submodules show-forced-updates tags].freeze
155
+ },
156
+ log: {
157
+ base: %w[decorate mailmap merges use-mailmap].freeze,
158
+ show: %w[abbrev-commit expand-tabs notes].freeze,
159
+ diff: %w[color color-moved ext-diff indent-heuristic patch relative rename-empty textconv].freeze
160
+ }.freeze,
161
+ pull: %w[autostash commit edit ff log signoff squash stat verify verify-signatures gpg-sign rebase].freeze,
162
+ tag: %w[column].freeze,
163
+ branch: %w[color-moved column color track].freeze,
164
+ checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
165
+ rebase: %w[autosquash autostash fork-point gpg-sign keep-empty reapply-cherry-picks reschedule-failed-exec
166
+ rerere-autoupdate stat update-refs verify].freeze,
167
+ reset: %w[refresh].freeze,
168
+ restore: %w[overlay progress recurse-submodules].freeze,
169
+ show: %w[standard-notes].freeze
170
+ }.freeze
171
+ }
172
+ VAL_GIT = {
173
+ rebase: {
174
+ send: %w[continue skip abort quit].freeze,
175
+ value: %w[true false merges interactive].freeze
176
+ }.freeze,
177
+ reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze
178
+ }
179
+ private_constant :OPT_GIT, :VAL_GIT
92
180
 
93
181
  class << self
94
182
  include Rake::DSL
@@ -134,21 +222,22 @@ module Squared
134
222
  end
135
223
 
136
224
  @@tasks[ref] = {
137
- 'checkout' => %i[branch track detach force merge].freeze,
138
- 'commit' => %i[add amend amend-orig all no-all].freeze,
139
- 'diff' => %i[head cached branch files between contain].freeze,
140
- 'pull' => %i[origin remote].freeze,
141
- 'fetch' => %i[origin remote].freeze,
142
- 'stash' => %i[push pop apply list clear].freeze,
143
- 'rebase' => %i[onto root send].freeze,
144
225
  'branch' => %i[create set delete move copy list edit current].freeze,
145
- 'refs' => %i[heads tags].freeze,
146
- 'files' => %i[cached modified deleted others].freeze,
147
- 'reset' => %i[head patch mode].freeze,
226
+ 'checkout' => %i[commit branch track detach path].freeze,
227
+ 'commit' => %i[add all amend amend-orig].freeze,
228
+ 'diff' => %i[head cached branch files view between contain].freeze,
229
+ 'fetch' => %i[origin remote].freeze,
230
+ 'files' => %i[cached modified deleted others ignored].freeze,
231
+ 'log' => %i[view between contain].freeze,
232
+ 'pull' => %i[origin remote].freeze,
233
+ 'rebase' => %i[branch onto send].freeze,
234
+ 'refs' => %i[heads tags remote].freeze,
235
+ 'reset' => %i[commit index patch mode].freeze,
148
236
  'restore' => %i[source worktree staged overlay].freeze,
149
- 'rev' => %i[commit branch].freeze,
237
+ 'rev' => %i[commit branch output parseopt].freeze,
150
238
  'show' => %i[format oneline].freeze,
151
- 'tag' => %i[add delete list merged].freeze
239
+ 'stash' => %i[push pop apply drop list].freeze,
240
+ 'tag' => %i[add delete list].freeze
152
241
  }.freeze
153
242
 
154
243
  def initialize(*, **)
@@ -173,93 +262,96 @@ module Squared
173
262
  case action
174
263
  when 'pull', 'fetch'
175
264
  if flag == :remote
176
- if @@task_desc
177
- format_desc(action, flag, ['refspec=s'] + (action == 'pull' ? OPT_PULL : OPT_FETCH),
178
- before: 'remote')
179
- end
265
+ format_desc(action, flag, 'remote,opts*')
180
266
  task flag, [:remote] do |_, args|
181
267
  remote = param_guard(action, flag, args: args, key: :remote)
182
- __send__(action, flag, remote: remote, opts: args.extras)
268
+ __send__(action, flag, args.extras, remote: remote)
183
269
  end
184
270
  else
185
- format_desc(action, flag, action == 'pull' ? OPT_PULL : OPT_FETCH)
271
+ format_desc action, flag, 'opts*'
186
272
  task flag do |_, args|
187
- __send__(action, flag, opts: args.to_a)
273
+ __send__ action, flag, args.to_a
188
274
  end
189
275
  end
190
- when 'commit', 'restore'
276
+ when 'commit'
191
277
  case flag
192
278
  when :all
193
279
  format_desc action, flag, 'message?'
194
280
  task flag, [:message] do |_, args|
195
281
  commit(flag, message: args.fetch(:message, nil))
196
282
  end
197
- when :source
198
- format_desc action, flag, 'tree,pathspec*'
283
+ else
284
+ format_desc action, flag, 'pathspec+'
285
+ task flag do |_, args|
286
+ refs = param_guard(action, flag, args: args.to_a)
287
+ commit(flag, refs: refs)
288
+ end
289
+ end
290
+ when 'restore'
291
+ if flag == :source
292
+ format_desc action, flag, 'tree,opts*,pathspec*'
199
293
  task flag, [:tree] do |_, args|
200
294
  tree = param_guard(action, flag, args: args, key: :tree)
201
295
  restore(flag, args.extras, tree: tree)
202
296
  end
203
297
  else
204
- format_desc action, flag, 'pathspec+'
298
+ format_desc action, flag, 'opts*,pathspec+'
205
299
  task flag do |_, args|
206
- files = param_guard(action, flag, args: args.to_a)
207
- __send__ action, flag, files
300
+ restore flag, args.to_a
208
301
  end
209
302
  end
210
303
  when 'tag'
211
304
  case flag
212
305
  when :list
213
- format_desc action, flag, 'pattern*'
306
+ format_desc action, flag, 'opts*,pattern*'
214
307
  task flag do |_, args|
215
308
  tag flag, args.to_a
216
309
  end
217
- when :merged
218
- format_desc action, flag, 'commit,pattern*'
219
- task flag, [:commit] do |_, args|
220
- commit = param_guard(action, flag, args: args, key: :commit)
221
- tag(flag, args.extras, commit: commit)
222
- end
223
310
  when :delete
224
311
  format_desc action, flag, 'name+'
225
312
  task flag do |_, args|
226
- name = param_guard(action, flag, args: args.to_a)
227
- tag flag, name
313
+ refs = param_guard(action, flag, args: args.to_a)
314
+ tag(flag, refs: refs)
228
315
  end
229
316
  when :add
230
317
  format_desc action, flag, 'name,message?,commit?'
231
318
  task flag, [:name, :message, :commit] do |_, args|
232
319
  name = param_guard(action, flag, args: args, key: :name)
233
- tag(flag, [name], message: args.message, commit: args.commit)
320
+ tag(flag, refs: [name], message: args.message, commit: args.commit)
234
321
  end
235
322
  end
236
323
  when 'stash'
237
- if flag == :push
238
- format_desc action, flag, 'pathspec*'
239
- task flag do |_, args|
240
- stash flag, args.to_a
241
- end
324
+ if flag == :list
325
+ format_desc action, flag
242
326
  else
243
- format_desc action, flag, 'commit?'
244
- task flag, [:commit] do |_, args|
245
- stash(flag, commit: args.commit)
246
- end
327
+ format_desc(action, flag, '*opts', after: flag == :push ? 'pathspec*' : 'commit?')
328
+ end
329
+ task flag do |_, args|
330
+ stash flag, args.to_a
247
331
  end
248
- when 'diff'
332
+ when 'log', 'diff'
249
333
  case flag
250
- when :head
251
- format_desc action, flag, 'index?=0,pathspec*'
252
- task flag do |_, args|
253
- files = args.to_a
254
- diff(flag, files, index: /\A\d+\z/.match?(files[0]) && !option('index') ? files.shift.to_i : 0)
334
+ when :view, :between, :contain
335
+ if flag == :view && action == 'log'
336
+ format_desc action, flag, '(^)commit*,pathspec*,opts*'
337
+ task flag do |_, args|
338
+ logx flag, args.to_a
339
+ end
340
+ else
341
+ format_desc action, flag, 'commit1,commit2,pathspec*,opts*'
342
+ task flag, [:commit1, :commit2] do |_, args|
343
+ commit1 = param_guard(action, flag, args: args, key: :commit1)
344
+ commit2 = param_guard(action, flag, args: args, key: :commit2)
345
+ __send__(action == 'log' ? :logx : :diff, flag, args.extras, range: [commit1, commit2])
346
+ end
255
347
  end
256
- when :cached
257
- format_desc action, flag, 'pathspec*'
348
+ when :head, :cached
349
+ format_desc action, flag, 'opts*,pathspec*'
258
350
  task flag do |_, args|
259
351
  diff flag, args.to_a
260
352
  end
261
353
  when :branch
262
- format_desc action, flag, 'name,pathspec*'
354
+ format_desc action, flag, 'name,opts*,pathspec*'
263
355
  task flag, [:name] do |_, args|
264
356
  branch = param_guard(action, flag, args: args, key: :name)
265
357
  diff(flag, args.extras, branch: branch)
@@ -269,14 +361,7 @@ module Squared
269
361
  task flag, [:path1, :path2] do |_, args|
270
362
  path1 = param_guard(action, flag, args: args, key: :path1)
271
363
  path2 = param_guard(action, flag, args: args, key: :path2)
272
- diff flag, [path1, path2]
273
- end
274
- else
275
- format_desc action, flag, 'commit1,commit2,pathspec*'
276
- task flag, [:commit1, :commit2] do |_, args|
277
- commit1 = param_guard(action, flag, args: args, key: :commit1)
278
- commit2 = param_guard(action, flag, args: args, key: :commit2)
279
- diff(flag, args.extras, range: [commit1, commit2])
364
+ diff(flag, refs: [path1, path2])
280
365
  end
281
366
  end
282
367
  when 'checkout'
@@ -310,13 +395,19 @@ module Squared
310
395
  origin = param_guard(action, flag, args: args, key: :origin)
311
396
  checkout(flag, branch: args.name, origin: origin)
312
397
  end
398
+ when :commit
399
+ format_desc action, flag, 'branch/commit,opts*'
400
+ task flag, [:commit] do |_, args|
401
+ commit = param_guard(action, flag, args: args, key: :commit)
402
+ checkout(flag, commit: commit)
403
+ end
313
404
  when :detach
314
405
  format_desc action, flag, 'branch/commit?'
315
406
  task flag, [:commit] do |_, args|
316
407
  checkout(flag, commit: args.commit)
317
408
  end
318
- else
319
- format_desc action, flag, 'pathspec*'
409
+ when :path
410
+ format_desc action, flag, 'opts*,pathspec*'
320
411
  task flag do |_, args|
321
412
  checkout flag, args.to_a
322
413
  end
@@ -326,11 +417,11 @@ module Squared
326
417
  when :create
327
418
  format_desc action, flag, 'name,ref?=HEAD'
328
419
  task flag, [:name, :ref] do |_, args|
329
- name = param_guard(action, flag, args: args, key: :name)
330
- branch(flag, target: name, ref: args.ref)
420
+ target = param_guard(action, flag, args: args, key: :name)
421
+ branch(flag, target: target, ref: args.ref)
331
422
  end
332
423
  when :set
333
- format_desc(action, flag, '(!)upstream,name?')
424
+ format_desc(action, flag, '(^)upstream,name?')
334
425
  task flag, [:upstream, :name] do |_, args|
335
426
  upstream = param_guard(action, flag, args: args, key: :upstream)
336
427
  branch(flag, target: args.name, ref: upstream)
@@ -338,8 +429,8 @@ module Squared
338
429
  when :delete
339
430
  format_desc action, flag, '(^~)name+'
340
431
  task flag, [:name] do |_, args|
341
- name = param_guard(action, flag, args: args.to_a)
342
- branch flag, name
432
+ refs = param_guard(action, flag, args: args.to_a)
433
+ branch(flag, refs: refs)
343
434
  end
344
435
  when :edit
345
436
  format_desc action, flag, 'name?'
@@ -347,9 +438,9 @@ module Squared
347
438
  branch(flag, target: args.name)
348
439
  end
349
440
  when :list
350
- format_desc(action, flag, OPT_BRANCH, before: 'pattern*')
441
+ format_desc action, flag, 'opts*,pattern*'
351
442
  task flag do |_, args|
352
- branch(flag, opts: args.to_a)
443
+ branch flag, args.to_a
353
444
  end
354
445
  when :current
355
446
  format_desc action, flag
@@ -357,74 +448,109 @@ module Squared
357
448
  branch flag
358
449
  end
359
450
  else
360
- format_desc action, flag, 'newbranch,oldbranch?'
361
- task flag, [:newbranch, :oldbranch] do |_, args|
362
- newbranch = param_guard(action, flag, args: args, key: :newbranch)
363
- branch flag, [args.oldbranch, newbranch]
451
+ format_desc action, flag, 'branch,oldbranch?'
452
+ task flag, [:branch, :oldbranch] do |_, args|
453
+ branch = param_guard(action, flag, args: args, key: :branch)
454
+ branch(flag, refs: [args.oldbranch, branch])
364
455
  end
365
456
  end
366
457
  when 'reset'
367
458
  case flag
368
- when :mode
369
- if @@task_desc
370
- format_desc(action, flag, %w[soft mixed hard merge keep {no-}submodules], after: 'ref?=HEAD',
371
- arg: false)
459
+ when :commit
460
+ format_desc action, flag, 'branch/commit,opts*'
461
+ task flag, [:commit] do |_, args|
462
+ commit = param_guard(action, flag, args: args, key: :commit)
463
+ reset(flag, args.extras, commit: commit)
372
464
  end
465
+ when :index
466
+ format_desc action, flag, 'opts*,pathspec*'
467
+ task flag do |_, args|
468
+ reset flag, args.to_a
469
+ end
470
+ when :mode
471
+ format_desc action, flag, 'mode,ref?=HEAD'
373
472
  task flag, [:mode, :ref] do |_, args|
374
473
  mode = param_guard(action, flag, args: args, key: :mode)
375
474
  reset(flag, mode: mode, ref: args.ref)
376
475
  end
377
- else
378
- format_desc action, flag, 'ref,pathspec+'
476
+ when :patch
477
+ format_desc action, flag, 'ref,pathspec*'
379
478
  task flag, [:ref] do |_, args|
380
- files = param_guard(action, flag, args: args.extras)
381
- reset(flag, files, ref: args.ref)
479
+ ref = param_guard(action, flag, args: args, key: :ref)
480
+ reset(flag, refs: args.extras, ref: ref)
382
481
  end
383
482
  end
384
483
  when 'show'
385
484
  case flag
386
485
  when :oneline
387
- format_desc action, flag, 'object*'
486
+ format_desc action, flag, 'opts*,object*'
388
487
  task flag do |_, args|
389
- show(args.to_a, format: 'oneline', opts: { 'abbrev-commit': true })
488
+ show 'oneline', args.to_a.push('abbrev-commit')
390
489
  end
391
490
  when :format
392
- format_desc action, flag, 'format?,object*'
491
+ format_desc action, flag, 'format?,opts*,object*'
393
492
  task flag, [:format] do |_, args|
394
- show(args.extras, format: args.format)
493
+ show args.format, args.extras
395
494
  end
396
495
  end
397
496
  when 'rebase'
398
497
  case flag
498
+ when :branch
499
+ format_desc action, flag, 'opts*,upstream?,branch?'
500
+ task flag do |_, args|
501
+ args = param_guard(action, flag, args: args.to_a)
502
+ rebase flag, args
503
+ end
399
504
  when :onto
400
- format_desc action, flag, 'commit,upstream,branch?=HEAD'
505
+ format_desc action, flag, 'branch/commit,upstream,branch?=HEAD'
401
506
  task flag, [:commit, :upstream, :branch] do |_, args|
402
507
  commit = param_guard(action, flag, args: args, key: :commit)
403
508
  upstream = param_guard(action, flag, args: args, key: :upstream)
404
509
  rebase(flag, commit: commit, upstream: upstream, branch: args.branch)
405
510
  end
406
- when :root
407
- format_desc action, flag, 'branch,onto?'
408
- task flag, [:branch, :onto] do |_, args|
409
- branch = param_guard(action, flag, args: args, key: :branch)
410
- rebase(flag, commit: args.onto, branch: branch)
411
- end
412
511
  when :send
413
- format_desc(action, flag, OPT_REBASE, arg: nil)
512
+ format_desc(action, flag, VAL_GIT[:rebase][:send], arg: nil)
414
513
  task flag, [:command] do |_, args|
415
514
  command = param_guard(action, flag, args: args, key: :command)
416
515
  rebase(flag, command: command)
417
516
  end
418
517
  end
419
518
  when 'rev'
420
- format_desc(action, flag, "ref?=HEAD#{flag == :commit ? ',size?' : ''}")
421
- task flag, [:ref, :size] do |_, args|
422
- rev_parse(flag, ref: args.ref, size: args.size)
519
+ case flag
520
+ when :commit
521
+ format_desc action, flag, 'ref?=HEAD,size?'
522
+ task flag, [:ref, :size] do |_, args|
523
+ ref = args.ref
524
+ size = args.size
525
+ if !size && ref.to_i > 0
526
+ size = ref
527
+ ref = nil
528
+ end
529
+ rev_parse(flag, ref: ref, size: size)
530
+ end
531
+ when :branch
532
+ format_desc action, flag, 'ref?=HEAD'
533
+ task flag, [:ref] do |_, args|
534
+ rev_parse(flag, ref: args.ref)
535
+ end
536
+ else
537
+ format_desc action, flag, 'opts*,args*'
538
+ task flag do |_, args|
539
+ rev_parse flag, args.to_a
540
+ end
423
541
  end
424
542
  when 'refs', 'files'
425
- format_desc action, flag, 'grep?=pattern'
426
- task flag, [:grep] do |_, args|
427
- __send__(action == 'refs' ? :ls_remote : :ls_files, flag, grep: args.fetch(:grep, nil))
543
+ if flag == :remote
544
+ format_desc action, flag, 'remote,opts*,pattern*'
545
+ task flag, [:remote] do |_, args|
546
+ remote = param_guard(action, flag, args: args, key: :remote)
547
+ ls_remote(flag, args.to_a.drop(1), remote: remote)
548
+ end
549
+ else
550
+ format_desc action, flag, 'opts*,pattern*'
551
+ task flag do |_, args|
552
+ __send__(action == 'refs' ? :ls_remote : :ls_files, flag, args.to_a)
553
+ end
428
554
  end
429
555
  end
430
556
  end
@@ -438,18 +564,18 @@ module Squared
438
564
  super
439
565
  end
440
566
 
441
- def pull(flag = nil, sync: invoked_sync?('pull', flag), remote: nil, opts: [])
567
+ def pull(flag = nil, opts = [], sync: invoked_sync?('pull', flag), remote: nil)
442
568
  cmd = git_session 'pull'
443
569
  if (val = option('rebase', ignore: false))
444
570
  cmd << case val
445
571
  when '0'
446
572
  '--no-rebase'
447
573
  else
448
- VAL_REBASE.include?(val) ? basic_option('rebase', val) : '--rebase'
574
+ VAL_GIT[:rebase][:value].include?(val) ? basic_option('rebase', val) : '--rebase'
449
575
  end
450
576
  end
451
- append_pull(opts, OPT_PULL + OPT_FETCH - (FOR_FETCH + FNO_FETCH), NO_PULL + NO_FETCH, remote: remote,
452
- flag: flag)
577
+ append_pull(opts, OPT_GIT[:pull] + OPT_GIT[:fetch][:pull],
578
+ no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag)
453
579
  source(sync: sync, sub: if verbose
454
580
  [
455
581
  { pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
@@ -458,39 +584,44 @@ module Squared
458
584
  end, **threadargs)
459
585
  end
460
586
 
461
- def rebase(flag = nil, sync: invoked_sync?('rebase', flag), command: nil, commit: nil, upstream: nil,
462
- branch: nil)
587
+ def rebase(flag = nil, opts = [], sync: invoked_sync?('rebase', flag), commit: nil, upstream: nil, branch: nil,
588
+ command: nil)
463
589
  return pull(:rebase, sync: sync) unless flag
464
590
 
465
591
  cmd = git_session 'rebase'
466
- cmd << '--interactive' unless flag == :send || !option('interactive', 'i')
467
592
  case flag
593
+ when :branch
594
+ branch = option_sanitize(opts, OPT_GIT[:rebase], no: OPT_GIT[:no][:rebase]).first
595
+ case branch.size
596
+ when 0
597
+ append_head
598
+ when 1, 2
599
+ append_value(branch, delim: true)
600
+ else
601
+ append_value([branch.pop, branch.pop].reverse, delim: true)
602
+ option_clear branch
603
+ end
468
604
  when :onto
469
605
  return unless upstream
470
606
 
471
- cmd << shell_option('onto', commit)
607
+ cmd << '--interactive' if option('interactive', 'i')
608
+ cmd << shell_option('onto', commit) if commit
472
609
  cmd << shell_escape(upstream)
473
610
  append_head branch
474
- when :root
475
- return unless branch
476
-
477
- cmd << shell_option('onto', commit) if commit
478
- cmd << '--root' << shell_escape(branch)
479
- when :send
480
- return unless OPT_REBASE.include?(command)
611
+ else
612
+ return unless VAL_GIT[:rebase][:send].include?(command)
481
613
 
482
614
  cmd << "--#{command}"
483
- else
484
- return
485
615
  end
486
616
  source
487
617
  end
488
618
 
489
- def fetch(flag = nil, sync: invoked_sync?('fetch', flag), remote: nil, opts: [])
619
+ def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
490
620
  cmd = git_session 'fetch'
491
621
  cmd << '--all' if !remote && !opts.include?('multiple') && option('all')
492
622
  cmd << '--verbose' if verbose && !opts.include?('quiet')
493
- append_pull(opts, OPT_FETCH, NO_FETCH + FNO_FETCH, remote: remote, flag: flag)
623
+ append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
624
+ remote: remote, flag: flag)
494
625
  source(sync: sync, **threadargs)
495
626
  end
496
627
 
@@ -511,35 +642,39 @@ module Squared
511
642
  opts[:local] = val != '0' if (val = option('local', strict: true))
512
643
  opts.delete(:'recurse-submodules') || opts.delete(:'no-recurse-submodules') if append_submodules(:clone)
513
644
  append_hash opts
514
- if cmd.include?('--quiet') || cmd.include?('-q')
515
- quiet = true
516
- elsif verbose
517
- quiet = false
518
- else
519
- cmd << '--quiet'
520
- quiet = true
521
- end
522
- append_value([data[0], path], delim: true, escape: false)
523
- source(banner: sync && !quiet, multiple: !sync || quiet)
645
+ cmd << '--quiet' unless verbose
646
+ append_value(data[0], path, delim: true)
647
+ source(banner: sync && !quiet?, multiple: !sync || quiet?)
524
648
  end
525
649
 
526
- def stash(flag = nil, files = [], sync: invoked_sync?('stash', flag), commit: nil)
527
- cmd = git_session 'stash', flag || 'push'
528
- case flag
529
- when :apply, :pop
530
- cmd << '--index' if option('index')
531
- cmd << commit
650
+ def stash(flag = nil, opts = [], sync: invoked_sync?('stash', flag))
651
+ if flag
652
+ cmd = git_session 'stash', flag
653
+ list = OPT_GIT[:stash][:common] + OPT_GIT[:stash].fetch(flag, [])
654
+ refs = option_sanitize(opts, list).first
655
+ case flag
656
+ when :push
657
+ append_pathspec refs
658
+ when :pop, :apply, :drop
659
+ cmd << shell_quote(refs.pop)
660
+ option_clear refs
661
+ when :list
662
+ out, banner, from = source(io: true)
663
+ print_item banner
664
+ ret = write_lines(out)
665
+ list_result(ret, 'objects', from: from)
666
+ return
667
+ end
532
668
  else
533
- append_option %w[all staged include-untracked].freeze
669
+ git_session 'stash', 'push'
670
+ append_option(%w[all keep-index include-untracked staged].freeze, no: true, ignore: false)
534
671
  append_message option('message', 'm', ignore: false)
535
- append_pathspec files
536
672
  end
537
- source(sync: sync, **threadargs)
673
+ source(banner: !quiet?, sync: sync, **threadargs)
538
674
  end
539
675
 
540
676
  def status(*, sync: invoked_sync?('status'), **)
541
- cmd = git_session 'status'
542
- cmd << (option('long') ? '--long' : '--short')
677
+ cmd = git_session 'status', option('long') ? '--long' : '--short'
543
678
  if (val = option('ignore-submodules', ignore: false))
544
679
  cmd << basic_option('ignore-submodules', case val
545
680
  when '0', 'none'
@@ -560,8 +695,8 @@ module Squared
560
695
  end
561
696
  ret = write_lines(out, banner: banner, sub: if verbose
562
697
  [
563
- { pat: /^(.)([A-Z?!])(.+)$/, styles: :red, index: 2 },
564
- { pat: /^([A-Z?!])(.+)$/, styles: :green },
698
+ { pat: /^(.)([A-Z])(.+)$/, styles: :red, index: 2 },
699
+ { pat: /^([A-Z])(.+)$/, styles: :green },
565
700
  { pat: /^(\?\?)(.+)$/, styles: :red },
566
701
  { pat: /^(## )(.+)(\.{3})(.+)$/,
567
702
  styles: [nil, :green, nil, :red], index: -1 }
@@ -570,34 +705,41 @@ module Squared
570
705
  list_result(ret, 'files', from: from, action: 'modified')
571
706
  end
572
707
 
573
- def reset(flag, files = nil, mode: nil, ref: nil)
708
+ def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
574
709
  cmd = git_session 'reset'
575
710
  case flag
711
+ when :commit, :index
712
+ out = option_sanitize(opts, OPT_GIT[:reset] + VAL_GIT[:reset], no: OPT_GIT[:no][:reset]).first
713
+ if flag == :commit
714
+ append_value(commit, delim: true)
715
+ option_clear out
716
+ ref = false
717
+ else
718
+ (refs ||= []).concat(out)
719
+ end
576
720
  when :mode
577
- case mode
578
- when 'mixed'
579
- cmd << '--mixed'
721
+ return unless VAL_GIT[:reset].include?(mode)
722
+
723
+ cmd << "--#{mode}"
724
+ if mode == 'mixed'
580
725
  cmd << '-N' if option('n')
581
726
  cmd << '--no-refresh' if option('refresh', equals: '0')
582
- when 'soft', 'hard', 'merge', 'keep'
583
- cmd << "--#{mode}"
584
- when 'submodules'
585
- cmd << '--recurse-submodules'
586
- when 'no-submodules'
587
- cmd << '--no-recurse-submodules'
588
- else
589
- return
590
727
  end
591
728
  when :patch
592
729
  cmd << '--patch'
730
+ else
731
+ return
732
+ end
733
+ unless ref == false
734
+ append_commit ref
735
+ append_pathspec refs if refs
593
736
  end
594
- append_commit ref
595
- append_pathspec files if files
596
737
  source
597
738
  end
598
739
 
599
- def checkout(flag, files = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil)
740
+ def checkout(flag, opts = [], branch: nil, origin: nil, create: nil, commit: nil, detach: nil)
600
741
  cmd = git_session 'checkout'
742
+ append_option 'force', 'merge'
601
743
  case flag
602
744
  when :branch
603
745
  cmd << '--detach' if detach == 'd' || option('detach')
@@ -620,92 +762,122 @@ module Squared
620
762
  end
621
763
  cmd << '--track' << origin
622
764
  when :detach
623
- cmd << "--#{flag}" << commit
765
+ cmd << '--detach' << commit
624
766
  else
625
- cmd << "--#{flag}"
626
- append_first %w[ours theirs]
627
- append_head
628
- append_pathspec files
767
+ out = option_sanitize(opts, OPT_GIT[:checkout], no: OPT_GIT[:no][:checkout]).first
768
+ if flag == :commit
769
+ append_value(commit, delim: true)
770
+ option_clear out
771
+ else
772
+ append_head
773
+ append_pathspec out
774
+ end
629
775
  end
630
776
  source
631
777
  end
632
778
 
633
- def tag(flag, refs, message: nil, commit: nil)
779
+ def tag(flag, opts = [], refs: [], message: nil, commit: nil)
634
780
  cmd = git_session 'tag'
635
781
  case flag
636
782
  when :add
637
783
  if option('sign')
638
784
  cmd << '--sign'
639
- else
640
- out = cmd.to_s
641
- cmd << '--annotate' if %w[-s --sign -u --local-user].none? { |val| out.include?(" #{val}") }
785
+ elsif !session_arg?('s', 'sign', 'u', 'local-user')
786
+ cmd << '--annotate'
642
787
  end
643
788
  if !commit && message && (hash = commithash(message))
644
789
  commit = hash
645
790
  else
646
791
  append_message message
647
792
  end
648
- append_value(refs, escape: false)
793
+ append_value refs
649
794
  append_head commit
650
- when :delete, :list, :merged
795
+ when :list
796
+ cmd << '--list'
797
+ grep = option_sanitize(opts, OPT_GIT[:tag], no: OPT_GIT[:no][:tag]).first
798
+ out, banner, from = source(io: true)
799
+ print_item banner
800
+ ret = write_lines(out, grep: grep)
801
+ list_result(ret, 'tags', from: from, grep: grep)
802
+ return
803
+ when :delete
804
+ cmd << '--delete'
805
+ append_value refs
806
+ else
651
807
  cmd << shell_option(flag, commit)
652
- append_option(%w[contains sort] + (flag == :list ? ['merged'] : []), equals: true) unless flag == :delete
653
- append_value(refs, escape: false)
654
808
  end
655
809
  source
656
810
  end
657
811
 
658
- def diff(flag, files = [], branch: nil, index: 0, range: [])
812
+ def logx(flag, opts = [], range: [])
813
+ cmd = git_session 'log'
814
+ files = option_sanitize(opts, collect_hash(OPT_GIT[:log]), no: collect_hash(OPT_GIT[:no][:log])).first
815
+ case flag
816
+ when :between, :contain
817
+ cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
818
+ else
819
+ commit, files = files.partition do |val|
820
+ val.start_with?('^') || (!%r{^[.\\/]}.match?(val) && !%r{[\\/]$}.match?(val)) || commithash(val)
821
+ end
822
+ cmd.merge(commit.map { |val| commithash(val) || shell_quote(val) }) unless commit.empty?
823
+ end
824
+ append_nocolor
825
+ append_pathspec files
826
+ source(exception: false)
827
+ end
828
+
829
+ def diff(flag, opts = [], refs: [], branch: nil, range: [])
659
830
  cmd = git_session 'diff'
660
- sha = []
831
+ files = option_sanitize(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff],
832
+ no: OPT_GIT[:no][:log][:diff]).first
661
833
  case flag
662
- when :files, :between, :contain
834
+ when :files, :view, :between, :contain
663
835
  cmd.delete('--cached')
664
836
  else
665
837
  items = files.dup
838
+ sha = nil
666
839
  files.clear
667
840
  items.each do |val|
668
- if (hash = commithash(val))
669
- sha << hash
841
+ if (s = commithash(val))
842
+ (sha ||= []).push(s)
670
843
  else
671
844
  files << val
672
845
  end
673
846
  end
674
847
  end
675
- if (val = option('unified')).to_i > 0
676
- cmd << basic_option('unified', val)
677
- end
678
848
  append_nocolor
679
- case flag
680
- when :cached
681
- cmd << '--cached'
682
- cmd << '--merge-base' if option('merge-base')
683
- when :branch
684
- cmd << branch
685
- when :files
849
+ if flag == :files
686
850
  cmd << '--no-index'
687
- when :between, :contain
688
- cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
851
+ append_pathspec(refs, parent: true)
689
852
  else
690
- if (val = option('index')) || index > 0
691
- cmd << "HEAD~#{val || index}"
692
- elsif !sha.empty? && option('merge-base')
693
- cmd << '--merge-base'
694
- end
695
- end
696
- unless sha.empty?
697
- if cmd.include?('--cached')
698
- raise_error('diff', sha.join(', '), hint: 'one commit') if sha.size > 1
699
- cmd << sha.first
853
+ case flag
854
+ when :view
855
+ cmd << '--merge-base' if option('merge-base')
856
+ cmd << shell_quote(range.first, quote: true) << shell_quote(range.last, quote: true)
857
+ when :between, :contain
858
+ cmd.delete('--merge-base')
859
+ cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
700
860
  else
701
- cmd.merge(sha)
861
+ cmd << '--cached' if flag == :cached
862
+ cmd << '--merge-base' if option('merge-base')
863
+ cmd << shell_quote(branch) if branch
864
+ if sha
865
+ if session_arg?('cached')
866
+ raise_error('diff', sha.join(', '), hint: 'one commit') if sha.size > 1
867
+ cmd << sha.first
868
+ else
869
+ cmd.merge(sha)
870
+ end
871
+ elsif (n = option('index'))
872
+ cmd << "HEAD~#{n}"
873
+ end
702
874
  end
875
+ append_pathspec files
703
876
  end
704
- append_pathspec(files, parent: flag == :files)
705
- source(exception: cmd.include?('--exit-code'))
877
+ source(exception: session_arg?('exit-code'))
706
878
  end
707
879
 
708
- def commit(flag, files = [], message: nil, pass: false)
880
+ def commit(flag, *, refs: [], message: nil, pass: false)
709
881
  message ||= option('message', 'm', prefix: 'git', ignore: false)
710
882
  amend = flag.to_s.start_with?('amend')
711
883
  if !message && !amend
@@ -713,36 +885,36 @@ module Squared
713
885
 
714
886
  raise_error('commit', 'GIT_MESSAGE="description"', hint: 'missing')
715
887
  end
716
- pathspec = if flag == :all || (amend && files.size == 1 && files.first == '*')
888
+ pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
717
889
  '--all'
890
+ elsif (refs = projectmap(refs)).empty?
891
+ raise_error('commit', 'pathspec', hint: 'missing')
718
892
  else
719
- raise_error('commit', 'pathspec', hint: 'missing') if (files = projectmap(files)).empty?
720
- "-- #{files.join(' ')}"
893
+ "-- #{refs.join(' ')}"
721
894
  end
722
895
  origin = nil
723
896
  branch = nil
724
897
  upstream = nil
725
- source(git_output('fetch --no-tags --quiet'), io: true, banner: false)
726
- source(git_output('branch -vv --list'), io: true, banner: false).first.each do |val|
898
+ source(git_output('fetch', '--no-tags', '--quiet'), io: true, banner: false)
899
+ source(git_output('branch', '-vv', '--list'), io: true, banner: false).first.each do |val|
727
900
  next unless (data = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
728
901
 
729
902
  branch = data[1]
730
- sha = data[2]
731
903
  if !data[3]
732
904
  unless (origin = option('repository', prefix: 'git', ignore: false))
733
- out = source(git_output('log -n1 --format=%h%d'), io: true, stdout: true, banner: false).first
734
- if (data = /^#{sha} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/.match(out))
735
- split_escape(data[1]).each do |val|
905
+ out = source(git_output('log', '-n1', '--format=%h%d'), io: true, stdout: true, banner: false).first
906
+ if out =~ /^#{data[2]} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/
907
+ split_escape($1).each do |val|
736
908
  next unless val.end_with?("/#{branch}")
737
909
 
738
- origin = val[0..val.size - branch.size - 2]
910
+ origin = val[0, val.size - branch.size - 1]
739
911
  break
740
912
  end
741
913
  end
742
914
  end
743
915
  upstream = true if origin
744
- elsif (data = Regexp.new("^(.+)/#{Regexp.escape(branch)}$").match(data[3]))
745
- origin = data[1]
916
+ elsif data[3] =~ %r{^(.+)/#{Regexp.escape(branch)}$}
917
+ origin = $1
746
918
  end
747
919
  break
748
920
  end
@@ -773,7 +945,7 @@ module Squared
773
945
  source b
774
946
  end
775
947
 
776
- def branch(flag, names = [], target: nil, ref: nil, opts: [])
948
+ def branch(flag, opts = [], refs: [], ref: nil, target: nil)
777
949
  cmd = git_session 'branch'
778
950
  stdout = false
779
951
  case flag
@@ -790,7 +962,9 @@ module Squared
790
962
  end
791
963
  cmd << '--force' if option('force')
792
964
  when :set
793
- if ref.start_with?('!')
965
+ return unless ref
966
+
967
+ if ref.start_with?('^')
794
968
  cmd << '--unset-upstream' << shell_escape(arg[1..-1])
795
969
  target = nil
796
970
  stdout = true
@@ -799,9 +973,9 @@ module Squared
799
973
  end
800
974
  ref = nil
801
975
  when :delete
802
- force, list = names.partition { |val| val =~ /^[\^~]/ }
976
+ force, list = refs.partition { |val| val =~ /^[\^~]/ }
803
977
  force.each do |val|
804
- dr = val[0..2]
978
+ dr = val[0, 3]
805
979
  d = dr.include?('^') ? '-D' : '-d'
806
980
  r = dr.include?('~') ? '-r' : nil
807
981
  source git_output('branch', d, r, shell_quote(val.sub(/^[\^~]+/, '')))
@@ -813,27 +987,18 @@ module Squared
813
987
  when :move, :copy
814
988
  flag = "-#{flag.to_s[0]}"
815
989
  cmd << (option('force') ? flag.upcase : flag)
816
- names.compact.each { |val| cmd << shell_quote(val) }
990
+ refs.compact.each { |val| cmd << shell_quote(val) }
817
991
  stdout = true
818
992
  when :edit
819
993
  cmd << '--edit-description'
820
994
  when :current
821
995
  cmd << '--show-current'
822
996
  else
823
- opts, pat = option_partition(opts, OPT_BRANCH, no: NO_BRANCH)
997
+ opts = option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first
824
998
  grep = []
825
999
  opts.each do |opt|
826
1000
  if opt =~ /^(v+)$/
827
1001
  cmd << "-#{$1}"
828
- elsif opt =~ pat
829
- case $1
830
- when 'column', 'format'
831
- cmd << quote_option($1, $2)
832
- when 'abbrev'
833
- cmd << basic_option($1, $2) if $2.to_i > 0
834
- else
835
- cmd << shell_option($1, $2)
836
- end
837
1002
  else
838
1003
  grep << opt
839
1004
  end
@@ -854,16 +1019,24 @@ module Squared
854
1019
  source(stdout: stdout)
855
1020
  end
856
1021
 
857
- def restore(flag, files, tree: nil)
858
- source = flag == :source
859
- cmd = git_session 'restore', source && files.empty? ? '--patch' : nil, shell_option(flag, tree)
860
- append_option %w[staged worktree]
861
- append_first %w[ours theirs]
862
- append_pathspec(files, expect: !cmd.include?('--patch'))
863
- source(stdout: !source)
1022
+ def restore(flag, opts = [], tree: nil)
1023
+ cmd = git_session 'restore'
1024
+ refs = option_sanitize(opts, OPT_GIT[:restore], no: OPT_GIT[:no][:restore]).first
1025
+ if flag == :source
1026
+ cmd << '--patch' if refs.empty?
1027
+ cmd << shell_option('source', tree)
1028
+ else
1029
+ cmd << "--#{flag}"
1030
+ end
1031
+ if session_arg?('p', 'patch')
1032
+ option_clear refs
1033
+ else
1034
+ append_pathspec(refs, expect: true)
1035
+ end
1036
+ source(sync: false, stderr: true)
864
1037
  end
865
1038
 
866
- def show(objs, format: nil, opts: nil)
1039
+ def show(format, opts = [])
867
1040
  cmd = git_session 'show'
868
1041
  if format
869
1042
  case (val = format.downcase)
@@ -873,41 +1046,54 @@ module Squared
873
1046
  if format =~ /^t?format:/ || format.include?('%')
874
1047
  cmd << quote_option('pretty', format)
875
1048
  else
876
- objs << format
1049
+ opts << format
877
1050
  end
878
1051
  end
879
1052
  end
880
- if opts
881
- append_hash opts
882
- banner = format != 'oneline'
883
- else
1053
+ refs = option_sanitize(opts, OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff],
1054
+ no: OPT_GIT[:no][:show] + collect_hash(OPT_GIT[:no][:log], pass: [:base])).first
1055
+ unless val == 'oneline' && session_arg?('abbrev-commit')
884
1056
  cmd << basic_option('abbrev', val) if (val = option('abbrev')) && val.to_i > 0
885
1057
  banner = true
886
1058
  end
887
- append_value(objs, delim: true)
1059
+ append_value(refs, delim: true)
888
1060
  source(exception: false, banner: banner)
889
1061
  end
890
1062
 
891
- def rev_parse(flag, ref: nil, size: nil)
892
- git_session 'rev-parse', if flag == :branch
893
- '--abbrev-ref'
894
- else
895
- (n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify'
896
- end
897
- append_commit ref
898
- source
1063
+ def rev_parse(flag, opts = [], ref: nil, size: nil)
1064
+ cmd = git_session 'rev-parse', if flag == :parseopt
1065
+ '--parseopt'
1066
+ elsif opts.delete('sq-quote')
1067
+ '--sq-quote'
1068
+ end
1069
+ case flag
1070
+ when :commit
1071
+ cmd << ((n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify')
1072
+ append_commit ref
1073
+ when :branch
1074
+ cmd << '--abbrev-ref'
1075
+ append_commit ref
1076
+ else
1077
+ args = option_sanitize(opts, OPT_GIT[:rev_parse][flag]).first
1078
+ append_value(args, escape: session_arg?('sq-quote'))
1079
+ end
1080
+ source(banner: verbose == 1)
899
1081
  end
900
1082
 
901
- def ls_remote(flag, grep: nil)
902
- git_session 'ls-remote', "--#{flag}", '--refs'
1083
+ def ls_remote(flag, opts = [], remote: nil)
1084
+ cmd = git_session 'ls-remote', '--refs'
1085
+ cmd << "--#{flag}" unless flag == :remote
1086
+ grep = option_sanitize(opts, OPT_GIT[:ls_remote]).first
1087
+ cmd << shell_quote(remote) if remote
903
1088
  out, banner, from = source(io: true)
904
1089
  print_item banner
905
1090
  ret = write_lines(out, grep: grep)
906
1091
  list_result(ret, flag.to_s, from: from, grep: grep)
907
1092
  end
908
1093
 
909
- def ls_files(flag, grep: nil)
1094
+ def ls_files(flag, opts = [])
910
1095
  git_session 'ls-files', "--#{flag}"
1096
+ grep = option_sanitize(opts, OPT_GIT[:ls_files]).first
911
1097
  out, banner, from = source(io: true)
912
1098
  print_item banner
913
1099
  ret = write_lines(out, grep: grep)
@@ -935,7 +1121,7 @@ module Squared
935
1121
  end
936
1122
  cmd = session_done(cmd)
937
1123
  log.info cmd
938
- on :first, from if from
1124
+ on :first, from
939
1125
  banner = if banner
940
1126
  format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
941
1127
  end
@@ -971,22 +1157,28 @@ module Squared
971
1157
  end
972
1158
  rescue StandardError => e
973
1159
  log.error e
974
- ret = on(:error, from, e) if from
1160
+ ret = on(:error, from, e)
975
1161
  raise if exception && ret != true
976
1162
 
977
1163
  warn log_message(Logger::WARN, e) if warning?
978
1164
  else
979
- on :last, from if from
1165
+ on :last, from
980
1166
  end
981
1167
  end
982
1168
 
983
1169
  def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false)
984
- grep = Regexp.new(grep == '*' ? '.+' : grep) if grep.is_a?(String)
1170
+ grep = if grep && !grep.empty?
1171
+ as_a(grep).map do |val|
1172
+ next val if val.is_a?(Regexp)
1173
+
1174
+ Regexp.new(val == '*' ? '.+' : val.to_s)
1175
+ end
1176
+ end
985
1177
  sub = nil if stdin?
986
1178
  ret = 0
987
1179
  out = []
988
1180
  data.each do |line|
989
- next if grep && !line.match?(grep)
1181
+ next if grep&.none? { |pat| pat.match?(line) }
990
1182
 
991
1183
  if loglevel
992
1184
  log.add loglevel, line
@@ -1012,35 +1204,34 @@ module Squared
1012
1204
  puts print_footer("#{size} #{size == 1 ? type.sub(/s\z/, '') : type}",
1013
1205
  sub: { pat: /\A(\d+)(.+)\z/, styles: styles })
1014
1206
  else
1015
- puts empty_status("No #{type} were #{action}", 'grep', grep)
1207
+ puts empty_status("No #{type} were #{action}", 'grep', grep.is_a?(Array) ? case grep.size
1208
+ when 0
1209
+ nil
1210
+ else
1211
+ grep.join(', ')
1212
+ end : grep.to_s)
1016
1213
  end
1017
1214
  end
1018
- on :last, from if from
1215
+ on :last, from
1019
1216
  end
1020
1217
 
1021
- def append_pull(opts, list, no = [], target: @session, flag: nil, remote: nil)
1218
+ def append_pull(opts, list, target: @session, no: nil, flag: nil, remote: nil)
1022
1219
  cmd << '--force' if option('force')
1023
- modules = append_submodules(target: target)
1220
+ rsm = append_submodules(target: target)
1024
1221
  out = []
1025
1222
  refspec = []
1026
- opts, pat = option_partition(opts, remote ? list + ['refspec=s'] : list, target: target, no: no)
1223
+ opts, pat = option_sanitize(opts, remote ? list + ['refspec=s'] : list, target: target, no: no)
1027
1224
  opts.each do |opt|
1028
1225
  if opt =~ pat
1029
1226
  case $1
1030
1227
  when 'rebase'
1031
- target << basic_option($1, $2) if VAL_REBASE.include?($2)
1228
+ target << basic_option($1, $2) if VAL_GIT[:rebase][:value].include?($2)
1032
1229
  when 'shallow-since'
1033
1230
  next unless (val = Date.parse($2))
1034
1231
 
1035
1232
  target << quote_option($1, val.strftime('%F %T'))
1036
1233
  when 'recurse-submodules'
1037
- target << basic_option($1, $2) unless modules
1038
- when 'shallow-exclude', 'gpg-sign', 'signoff', 'strategy', 'strategy-option'
1039
- target << shell_option($1, $2)
1040
- when 'refmap', 'negotiation-tip'
1041
- target << quote_option($1, $2)
1042
- when 'depth', 'deepen', 'log', 'jobs'
1043
- target << basic_option($1, $2) if $2.to_i > 0
1234
+ target << basic_option($1, $2) unless rsm
1044
1235
  when 'refspec'
1045
1236
  refspec << shell_escape($2, quote: true)
1046
1237
  end
@@ -1049,9 +1240,9 @@ module Squared
1049
1240
  end
1050
1241
  end
1051
1242
  if remote
1052
- append_value(remote, target: target, delim: true, quote: true)
1243
+ append_value(remote, target: target, delim: true)
1053
1244
  if (val = option('refspec', strict: true))
1054
- append_value(split_escape(val), target: target, escape: false)
1245
+ append_value(split_escape(val), target: target)
1055
1246
  else
1056
1247
  target.merge(refspec)
1057
1248
  end
@@ -1069,25 +1260,29 @@ module Squared
1069
1260
  end
1070
1261
 
1071
1262
  def append_pathspec(files = [], target: @session, expect: false, parent: false)
1072
- if files.empty? && (val = option('pathspec'))
1073
- files = split_escape(val)
1074
- end
1075
- files = projectmap(files, parent: parent)
1076
- if !files.empty?
1077
- target << "-- #{files.join(' ')}"
1078
- elsif expect
1079
- raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree', hint: 'invalid')
1263
+ if session_arg?('pathspec-from-file')
1264
+ option_clear files
1265
+ else
1266
+ if files.empty? && (val = option('pathspec'))
1267
+ files = split_escape(val)
1268
+ end
1269
+ files = projectmap(files, parent: parent)
1270
+ if !files.empty?
1271
+ target << "-- #{files.join(' ')}"
1272
+ elsif expect
1273
+ raise_error(parent ? 'pathspec not present' : 'pathspec not within worktree', hint: 'invalid')
1274
+ end
1080
1275
  end
1081
1276
  end
1082
1277
 
1083
1278
  def append_message(val, target: @session)
1084
- target << "--message=\"#{double_quote(val)}\"" unless val.to_s.empty?
1279
+ target << quote_option('message', val) unless val.to_s.empty?
1085
1280
  end
1086
1281
 
1087
1282
  def append_head(val = nil, target: @session)
1088
1283
  return target << val if val
1089
1284
 
1090
- append_first(%w[head tree-ish object], target: target, flag: false, ignore: false)
1285
+ append_first('head', 'tree-ish', 'object', target: target, flag: false, ignore: false)
1091
1286
  end
1092
1287
 
1093
1288
  def append_submodules(from = nil, target: @session)
@@ -1119,8 +1314,14 @@ module Squared
1119
1314
  git_session(*cmd, main: false, options: false, **kwargs)
1120
1315
  end
1121
1316
 
1122
- def dryrun?(*)
1123
- !!@session&.include?('--dry-run')
1317
+ def dryrun?(*, target: @session, **)
1318
+ !!target&.include?('--dry-run')
1319
+ end
1320
+
1321
+ def quiet?(target: @session)
1322
+ return false unless target
1323
+
1324
+ target.include?('--quiet') || (target.include?('-q') && target.first == 'git')
1124
1325
  end
1125
1326
 
1126
1327
  def gitpath
@@ -1128,7 +1329,7 @@ module Squared
1128
1329
  end
1129
1330
 
1130
1331
  def commithash(val)
1131
- (data = /\A#\{(\h{5,40})\}\z/.match(val)) ? data[1] : nil
1332
+ val =~ /\A#\{(\h{5,40})\}\z/ ? $1 : nil
1132
1333
  end
1133
1334
 
1134
1335
  def threadargs