squared 0.2.9 → 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].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 recurse-submodules=s server-option=s
81
- shallow-exclude=s 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,21 +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
- if flag == :rebase
444
- cmd << '--rebase'
445
- cmd << '--autostash' if option('autostash')
446
- elsif (val = option('rebase', ignore: false))
569
+ if (val = option('rebase', ignore: false))
447
570
  cmd << case val
448
571
  when '0'
449
572
  '--no-rebase'
450
573
  else
451
- VAL_REBASE.include?(val) ? basic_option('rebase', val) : '--rebase'
574
+ VAL_GIT[:rebase][:value].include?(val) ? basic_option('rebase', val) : '--rebase'
452
575
  end
453
576
  end
454
- append_pull(opts, OPT_PULL + OPT_FETCH - (FOR_FETCH + FNO_FETCH), NO_PULL + NO_FETCH, remote: remote,
455
- 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)
456
579
  source(sync: sync, sub: if verbose
457
580
  [
458
581
  { pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
@@ -461,39 +584,44 @@ module Squared
461
584
  end, **threadargs)
462
585
  end
463
586
 
464
- def rebase(flag = nil, sync: invoked_sync?('rebase', flag), command: nil, commit: nil, upstream: nil,
465
- branch: nil)
587
+ def rebase(flag = nil, opts = [], sync: invoked_sync?('rebase', flag), commit: nil, upstream: nil, branch: nil,
588
+ command: nil)
466
589
  return pull(:rebase, sync: sync) unless flag
467
590
 
468
591
  cmd = git_session 'rebase'
469
- cmd << '--interactive' unless flag == :send || !option('interactive', 'i')
470
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
471
604
  when :onto
472
605
  return unless upstream
473
606
 
474
- cmd << shell_option('onto', commit)
607
+ cmd << '--interactive' if option('interactive', 'i')
608
+ cmd << shell_option('onto', commit) if commit
475
609
  cmd << shell_escape(upstream)
476
610
  append_head branch
477
- when :root
478
- return unless branch
479
-
480
- cmd << shell_option('onto', commit) if commit
481
- cmd << '--root' << shell_escape(branch)
482
- when :send
483
- return unless OPT_REBASE.include?(command)
611
+ else
612
+ return unless VAL_GIT[:rebase][:send].include?(command)
484
613
 
485
614
  cmd << "--#{command}"
486
- else
487
- return
488
615
  end
489
616
  source
490
617
  end
491
618
 
492
- 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)
493
620
  cmd = git_session 'fetch'
494
621
  cmd << '--all' if !remote && !opts.include?('multiple') && option('all')
495
622
  cmd << '--verbose' if verbose && !opts.include?('quiet')
496
- 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)
497
625
  source(sync: sync, **threadargs)
498
626
  end
499
627
 
@@ -514,35 +642,39 @@ module Squared
514
642
  opts[:local] = val != '0' if (val = option('local', strict: true))
515
643
  opts.delete(:'recurse-submodules') || opts.delete(:'no-recurse-submodules') if append_submodules(:clone)
516
644
  append_hash opts
517
- if cmd.include?('--quiet') || cmd.include?('-q')
518
- quiet = true
519
- elsif verbose
520
- quiet = false
521
- else
522
- cmd << '--quiet'
523
- quiet = true
524
- end
525
- append_value([data[0], path], delim: true, escape: false)
526
- 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?)
527
648
  end
528
649
 
529
- def stash(flag = nil, files = [], sync: invoked_sync?('stash', flag), commit: nil)
530
- cmd = git_session 'stash', flag || 'push'
531
- case flag
532
- when :apply, :pop
533
- cmd << '--index' if option('index')
534
- 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
535
668
  else
536
- 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)
537
671
  append_message option('message', 'm', ignore: false)
538
- append_pathspec files
539
672
  end
540
- source(sync: sync, **threadargs)
673
+ source(banner: !quiet?, sync: sync, **threadargs)
541
674
  end
542
675
 
543
676
  def status(*, sync: invoked_sync?('status'), **)
544
- cmd = git_session 'status'
545
- cmd << (option('long') ? '--long' : '--short')
677
+ cmd = git_session 'status', option('long') ? '--long' : '--short'
546
678
  if (val = option('ignore-submodules', ignore: false))
547
679
  cmd << basic_option('ignore-submodules', case val
548
680
  when '0', 'none'
@@ -563,8 +695,8 @@ module Squared
563
695
  end
564
696
  ret = write_lines(out, banner: banner, sub: if verbose
565
697
  [
566
- { pat: /^(.)([A-Z?!])(.+)$/, styles: :red, index: 2 },
567
- { pat: /^([A-Z?!])(.+)$/, styles: :green },
698
+ { pat: /^(.)([A-Z])(.+)$/, styles: :red, index: 2 },
699
+ { pat: /^([A-Z])(.+)$/, styles: :green },
568
700
  { pat: /^(\?\?)(.+)$/, styles: :red },
569
701
  { pat: /^(## )(.+)(\.{3})(.+)$/,
570
702
  styles: [nil, :green, nil, :red], index: -1 }
@@ -573,34 +705,41 @@ module Squared
573
705
  list_result(ret, 'files', from: from, action: 'modified')
574
706
  end
575
707
 
576
- def reset(flag, files = nil, mode: nil, ref: nil)
708
+ def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
577
709
  cmd = git_session 'reset'
578
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
579
720
  when :mode
580
- case mode
581
- when 'mixed'
582
- cmd << '--mixed'
721
+ return unless VAL_GIT[:reset].include?(mode)
722
+
723
+ cmd << "--#{mode}"
724
+ if mode == 'mixed'
583
725
  cmd << '-N' if option('n')
584
726
  cmd << '--no-refresh' if option('refresh', equals: '0')
585
- when 'soft', 'hard', 'merge', 'keep'
586
- cmd << "--#{mode}"
587
- when 'submodules'
588
- cmd << '--recurse-submodules'
589
- when 'no-submodules'
590
- cmd << '--no-recurse-submodules'
591
- else
592
- return
593
727
  end
594
728
  when :patch
595
729
  cmd << '--patch'
730
+ else
731
+ return
732
+ end
733
+ unless ref == false
734
+ append_commit ref
735
+ append_pathspec refs if refs
596
736
  end
597
- append_commit ref
598
- append_pathspec files if files
599
737
  source
600
738
  end
601
739
 
602
- 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)
603
741
  cmd = git_session 'checkout'
742
+ append_option 'force', 'merge'
604
743
  case flag
605
744
  when :branch
606
745
  cmd << '--detach' if detach == 'd' || option('detach')
@@ -623,92 +762,122 @@ module Squared
623
762
  end
624
763
  cmd << '--track' << origin
625
764
  when :detach
626
- cmd << "--#{flag}" << commit
765
+ cmd << '--detach' << commit
627
766
  else
628
- cmd << "--#{flag}"
629
- append_first %w[ours theirs]
630
- append_head
631
- 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
632
775
  end
633
776
  source
634
777
  end
635
778
 
636
- def tag(flag, refs, message: nil, commit: nil)
779
+ def tag(flag, opts = [], refs: [], message: nil, commit: nil)
637
780
  cmd = git_session 'tag'
638
781
  case flag
639
782
  when :add
640
783
  if option('sign')
641
784
  cmd << '--sign'
642
- else
643
- out = cmd.to_s
644
- 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'
645
787
  end
646
788
  if !commit && message && (hash = commithash(message))
647
789
  commit = hash
648
790
  else
649
791
  append_message message
650
792
  end
651
- append_value(refs, escape: false)
793
+ append_value refs
652
794
  append_head commit
653
- 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
654
807
  cmd << shell_option(flag, commit)
655
- append_option(%w[contains sort] + (flag == :list ? ['merged'] : []), equals: true) unless flag == :delete
656
- append_value(refs, escape: false)
657
808
  end
658
809
  source
659
810
  end
660
811
 
661
- 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: [])
662
830
  cmd = git_session 'diff'
663
- sha = []
831
+ files = option_sanitize(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff],
832
+ no: OPT_GIT[:no][:log][:diff]).first
664
833
  case flag
665
- when :files, :between, :contain
834
+ when :files, :view, :between, :contain
666
835
  cmd.delete('--cached')
667
836
  else
668
837
  items = files.dup
838
+ sha = nil
669
839
  files.clear
670
840
  items.each do |val|
671
- if (hash = commithash(val))
672
- sha << hash
841
+ if (s = commithash(val))
842
+ (sha ||= []).push(s)
673
843
  else
674
844
  files << val
675
845
  end
676
846
  end
677
847
  end
678
- if (val = option('unified')).to_i > 0
679
- cmd << basic_option('unified', val)
680
- end
681
848
  append_nocolor
682
- case flag
683
- when :cached
684
- cmd << '--cached'
685
- cmd << '--merge-base' if option('merge-base')
686
- when :branch
687
- cmd << branch
688
- when :files
849
+ if flag == :files
689
850
  cmd << '--no-index'
690
- when :between, :contain
691
- cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
851
+ append_pathspec(refs, parent: true)
692
852
  else
693
- if (val = option('index')) || index > 0
694
- cmd << "HEAD~#{val || index}"
695
- elsif !sha.empty? && option('merge-base')
696
- cmd << '--merge-base'
697
- end
698
- end
699
- unless sha.empty?
700
- if cmd.include?('--cached')
701
- raise_error('diff', sha.join(', '), hint: 'one commit') if sha.size > 1
702
- 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 ? '..' : '...'))
703
860
  else
704
- 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
705
874
  end
875
+ append_pathspec files
706
876
  end
707
- append_pathspec(files, parent: flag == :files)
708
- source(exception: cmd.include?('--exit-code'))
877
+ source(exception: session_arg?('exit-code'))
709
878
  end
710
879
 
711
- def commit(flag, files = [], message: nil, pass: false)
880
+ def commit(flag, *, refs: [], message: nil, pass: false)
712
881
  message ||= option('message', 'm', prefix: 'git', ignore: false)
713
882
  amend = flag.to_s.start_with?('amend')
714
883
  if !message && !amend
@@ -716,36 +885,36 @@ module Squared
716
885
 
717
886
  raise_error('commit', 'GIT_MESSAGE="description"', hint: 'missing')
718
887
  end
719
- pathspec = if flag == :all || (amend && files.size == 1 && files.first == '*')
888
+ pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
720
889
  '--all'
890
+ elsif (refs = projectmap(refs)).empty?
891
+ raise_error('commit', 'pathspec', hint: 'missing')
721
892
  else
722
- raise_error('commit', 'pathspec', hint: 'missing') if (files = projectmap(files)).empty?
723
- "-- #{files.join(' ')}"
893
+ "-- #{refs.join(' ')}"
724
894
  end
725
895
  origin = nil
726
896
  branch = nil
727
897
  upstream = nil
728
- source(git_output('fetch --no-tags --quiet'), io: true, banner: false)
729
- 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|
730
900
  next unless (data = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
731
901
 
732
902
  branch = data[1]
733
- sha = data[2]
734
903
  if !data[3]
735
904
  unless (origin = option('repository', prefix: 'git', ignore: false))
736
- out = source(git_output('log -n1 --format=%h%d'), io: true, stdout: true, banner: false).first
737
- if (data = /^#{sha} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/.match(out))
738
- split_escape(data[1]).each do |s|
739
- next unless s.end_with?("/#{branch}")
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|
908
+ next unless val.end_with?("/#{branch}")
740
909
 
741
- origin = s[0..s.size - branch.size - 2]
910
+ origin = val[0, val.size - branch.size - 1]
742
911
  break
743
912
  end
744
913
  end
745
914
  end
746
915
  upstream = true if origin
747
- elsif (data = Regexp.new("^(.+)/#{Regexp.escape(branch)}$").match(data[3]))
748
- origin = data[1]
916
+ elsif data[3] =~ %r{^(.+)/#{Regexp.escape(branch)}$}
917
+ origin = $1
749
918
  end
750
919
  break
751
920
  end
@@ -776,7 +945,7 @@ module Squared
776
945
  source b
777
946
  end
778
947
 
779
- def branch(flag, names = [], target: nil, ref: nil, opts: [])
948
+ def branch(flag, opts = [], refs: [], ref: nil, target: nil)
780
949
  cmd = git_session 'branch'
781
950
  stdout = false
782
951
  case flag
@@ -793,8 +962,10 @@ module Squared
793
962
  end
794
963
  cmd << '--force' if option('force')
795
964
  when :set
796
- if ref.start_with?('!')
797
- cmd << '--unset-upstream' << shell_escape(ref[1..-1])
965
+ return unless ref
966
+
967
+ if ref.start_with?('^')
968
+ cmd << '--unset-upstream' << shell_escape(arg[1..-1])
798
969
  target = nil
799
970
  stdout = true
800
971
  else
@@ -802,9 +973,9 @@ module Squared
802
973
  end
803
974
  ref = nil
804
975
  when :delete
805
- force, list = names.partition { |val| val =~ /^[\^~]/ }
976
+ force, list = refs.partition { |val| val =~ /^[\^~]/ }
806
977
  force.each do |val|
807
- dr = val[0..2]
978
+ dr = val[0, 3]
808
979
  d = dr.include?('^') ? '-D' : '-d'
809
980
  r = dr.include?('~') ? '-r' : nil
810
981
  source git_output('branch', d, r, shell_quote(val.sub(/^[\^~]+/, '')))
@@ -816,27 +987,18 @@ module Squared
816
987
  when :move, :copy
817
988
  flag = "-#{flag.to_s[0]}"
818
989
  cmd << (option('force') ? flag.upcase : flag)
819
- names.compact.each { |val| cmd << shell_quote(val) }
990
+ refs.compact.each { |val| cmd << shell_quote(val) }
820
991
  stdout = true
821
992
  when :edit
822
993
  cmd << '--edit-description'
823
994
  when :current
824
995
  cmd << '--show-current'
825
996
  else
826
- opts, pat = option_partition(opts, OPT_BRANCH, no: NO_BRANCH)
997
+ opts = option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first
827
998
  grep = []
828
999
  opts.each do |opt|
829
1000
  if opt =~ /^(v+)$/
830
1001
  cmd << "-#{$1}"
831
- elsif opt =~ pat
832
- case $1
833
- when 'column', 'format'
834
- cmd << quote_option($1, $2)
835
- when 'abbrev'
836
- cmd << basic_option($1, $2) if $2.to_i > 0
837
- else
838
- cmd << shell_option($1, $2)
839
- end
840
1002
  else
841
1003
  grep << opt
842
1004
  end
@@ -857,16 +1019,24 @@ module Squared
857
1019
  source(stdout: stdout)
858
1020
  end
859
1021
 
860
- def restore(flag, files, tree: nil)
861
- source = flag == :source
862
- cmd = git_session 'restore', source && files.empty? ? '--patch' : nil, shell_option(flag, tree)
863
- append_option %w[staged worktree]
864
- append_first %w[ours theirs]
865
- append_pathspec(files, expect: !cmd.include?('--patch'))
866
- 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)
867
1037
  end
868
1038
 
869
- def show(objs, format: nil, opts: nil)
1039
+ def show(format, opts = [])
870
1040
  cmd = git_session 'show'
871
1041
  if format
872
1042
  case (val = format.downcase)
@@ -876,41 +1046,54 @@ module Squared
876
1046
  if format =~ /^t?format:/ || format.include?('%')
877
1047
  cmd << quote_option('pretty', format)
878
1048
  else
879
- objs << format
1049
+ opts << format
880
1050
  end
881
1051
  end
882
1052
  end
883
- if opts
884
- append_hash opts
885
- banner = format != 'oneline'
886
- 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')
887
1056
  cmd << basic_option('abbrev', val) if (val = option('abbrev')) && val.to_i > 0
888
1057
  banner = true
889
1058
  end
890
- append_value(objs, delim: true)
1059
+ append_value(refs, delim: true)
891
1060
  source(exception: false, banner: banner)
892
1061
  end
893
1062
 
894
- def rev_parse(flag, ref: nil, size: nil)
895
- git_session 'rev-parse', if flag == :branch
896
- '--abbrev-ref'
897
- else
898
- (n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify'
899
- end
900
- append_commit ref
901
- 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)
902
1081
  end
903
1082
 
904
- def ls_remote(flag, grep: nil)
905
- 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
906
1088
  out, banner, from = source(io: true)
907
1089
  print_item banner
908
1090
  ret = write_lines(out, grep: grep)
909
1091
  list_result(ret, flag.to_s, from: from, grep: grep)
910
1092
  end
911
1093
 
912
- def ls_files(flag, grep: nil)
1094
+ def ls_files(flag, opts = [])
913
1095
  git_session 'ls-files', "--#{flag}"
1096
+ grep = option_sanitize(opts, OPT_GIT[:ls_files]).first
914
1097
  out, banner, from = source(io: true)
915
1098
  print_item banner
916
1099
  ret = write_lines(out, grep: grep)
@@ -937,8 +1120,8 @@ module Squared
937
1120
  banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
938
1121
  end
939
1122
  cmd = session_done(cmd)
940
- log&.info cmd
941
- on :first, from if from
1123
+ log.info cmd
1124
+ on :first, from
942
1125
  banner = if banner
943
1126
  format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
944
1127
  end
@@ -973,26 +1156,32 @@ module Squared
973
1156
  end
974
1157
  end
975
1158
  rescue StandardError => e
976
- log&.error e
977
- ret = on(:error, from, e) if from
1159
+ log.error e
1160
+ ret = on(:error, from, e)
978
1161
  raise if exception && ret != true
979
1162
 
980
1163
  warn log_message(Logger::WARN, e) if warning?
981
1164
  else
982
- on :last, from if from
1165
+ on :last, from
983
1166
  end
984
1167
  end
985
1168
 
986
1169
  def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false)
987
- 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
988
1177
  sub = nil if stdin?
989
1178
  ret = 0
990
1179
  out = []
991
1180
  data.each do |line|
992
- next if grep && !line.match?(grep)
1181
+ next if grep&.none? { |pat| pat.match?(line) }
993
1182
 
994
1183
  if loglevel
995
- log&.add loglevel, line
1184
+ log.add loglevel, line
996
1185
  else
997
1186
  sub&.each { |h| line = sub_style(line, **h) }
998
1187
  if banner
@@ -1012,38 +1201,37 @@ module Squared
1012
1201
  if size > 0
1013
1202
  styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
1014
1203
  styles << :bold if styles.size <= 1
1015
- puts print_footer("#{size} #{size == 1 ? type.sub(/(?:(?<!l)e)?s\z/, '') : type}",
1204
+ puts print_footer("#{size} #{size == 1 ? type.sub(/s\z/, '') : type}",
1016
1205
  sub: { pat: /\A(\d+)(.+)\z/, styles: styles })
1017
1206
  else
1018
- 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)
1019
1213
  end
1020
1214
  end
1021
- on :last, from if from
1215
+ on :last, from
1022
1216
  end
1023
1217
 
1024
- def append_pull(opts, list, no = [], target: @session, flag: nil, remote: nil)
1025
- target << '--force' if option('force', target: target)
1026
- modules = append_submodules(target: target)
1218
+ def append_pull(opts, list, target: @session, no: nil, flag: nil, remote: nil)
1219
+ cmd << '--force' if option('force')
1220
+ rsm = append_submodules(target: target)
1027
1221
  out = []
1028
1222
  refspec = []
1029
- 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)
1030
1224
  opts.each do |opt|
1031
1225
  if opt =~ pat
1032
1226
  case $1
1033
1227
  when 'rebase'
1034
- target << basic_option($1, $2) if VAL_REBASE.include?($2)
1228
+ target << basic_option($1, $2) if VAL_GIT[:rebase][:value].include?($2)
1035
1229
  when 'shallow-since'
1036
1230
  next unless (val = Date.parse($2))
1037
1231
 
1038
1232
  target << quote_option($1, val.strftime('%F %T'))
1039
1233
  when 'recurse-submodules'
1040
- target << basic_option($1, $2) unless modules
1041
- when 'shallow-exclude', 'gpg-sign', 'signoff', 'strategy', 'strategy-option'
1042
- target << shell_option($1, $2)
1043
- when 'refmap', 'negotiation-tip'
1044
- target << quote_option($1, $2)
1045
- when 'depth', 'deepen', 'log', 'jobs'
1046
- target << basic_option($1, $2) if $2.to_i > 0
1234
+ target << basic_option($1, $2) unless rsm
1047
1235
  when 'refspec'
1048
1236
  refspec << shell_escape($2, quote: true)
1049
1237
  end
@@ -1052,9 +1240,9 @@ module Squared
1052
1240
  end
1053
1241
  end
1054
1242
  if remote
1055
- append_value(remote, target: target, delim: true, quote: true)
1056
- if (val = option('refspec', target: target, strict: true))
1057
- append_value(split_escape(val), target: target, escape: false)
1243
+ append_value(remote, target: target, delim: true)
1244
+ if (val = option('refspec', strict: true))
1245
+ append_value(split_escape(val), target: target)
1058
1246
  else
1059
1247
  target.merge(refspec)
1060
1248
  end
@@ -1072,29 +1260,33 @@ module Squared
1072
1260
  end
1073
1261
 
1074
1262
  def append_pathspec(files = [], target: @session, expect: false, parent: false)
1075
- if files.empty? && (val = option('pathspec', target: target))
1076
- files = split_escape(val)
1077
- end
1078
- files = projectmap(files, parent: parent)
1079
- if !files.empty?
1080
- target << "-- #{files.join(' ')}"
1081
- elsif expect
1082
- 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
1083
1275
  end
1084
1276
  end
1085
1277
 
1086
1278
  def append_message(val, target: @session)
1087
- target << "--message=\"#{double_quote(val)}\"" unless val.to_s.empty?
1279
+ target << quote_option('message', val) unless val.to_s.empty?
1088
1280
  end
1089
1281
 
1090
1282
  def append_head(val = nil, target: @session)
1091
1283
  return target << val if val
1092
1284
 
1093
- 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)
1094
1286
  end
1095
1287
 
1096
1288
  def append_submodules(from = nil, target: @session)
1097
- return unless (val = option('recurse-submodules', target: target, ignore: false))
1289
+ return unless (val = option('recurse-submodules', ignore: false))
1098
1290
 
1099
1291
  if from == :clone
1100
1292
  projectmap(split_escape(val)).each do |path|
@@ -1122,8 +1314,14 @@ module Squared
1122
1314
  git_session(*cmd, main: false, options: false, **kwargs)
1123
1315
  end
1124
1316
 
1125
- def dryrun?(*)
1126
- !!@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')
1127
1325
  end
1128
1326
 
1129
1327
  def gitpath
@@ -1131,7 +1329,7 @@ module Squared
1131
1329
  end
1132
1330
 
1133
1331
  def commithash(val)
1134
- (data = /\A#\{(\h{5,40})\}\z/.match(val)) ? data[1] : nil
1332
+ val =~ /\A#\{(\h{5,40})\}\z/ ? $1 : nil
1135
1333
  end
1136
1334
 
1137
1335
  def threadargs