squared 0.2.2 → 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,30 +642,35 @@ 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'), **)
@@ -569,34 +705,41 @@ module Squared
569
705
  list_result(ret, 'files', from: from, action: 'modified')
570
706
  end
571
707
 
572
- def reset(flag, files = nil, mode: nil, ref: nil)
708
+ def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
573
709
  cmd = git_session 'reset'
574
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
575
720
  when :mode
576
- case mode
577
- when 'mixed'
578
- cmd << '--mixed'
721
+ return unless VAL_GIT[:reset].include?(mode)
722
+
723
+ cmd << "--#{mode}"
724
+ if mode == 'mixed'
579
725
  cmd << '-N' if option('n')
580
726
  cmd << '--no-refresh' if option('refresh', equals: '0')
581
- when 'soft', 'hard', 'merge', 'keep'
582
- cmd << "--#{mode}"
583
- when 'submodules'
584
- cmd << '--recurse-submodules'
585
- when 'no-submodules'
586
- cmd << '--no-recurse-submodules'
587
- else
588
- return
589
727
  end
590
728
  when :patch
591
729
  cmd << '--patch'
730
+ else
731
+ return
732
+ end
733
+ unless ref == false
734
+ append_commit ref
735
+ append_pathspec refs if refs
592
736
  end
593
- append_commit ref
594
- append_pathspec files if files
595
737
  source
596
738
  end
597
739
 
598
- 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)
599
741
  cmd = git_session 'checkout'
742
+ append_option 'force', 'merge'
600
743
  case flag
601
744
  when :branch
602
745
  cmd << '--detach' if detach == 'd' || option('detach')
@@ -619,92 +762,122 @@ module Squared
619
762
  end
620
763
  cmd << '--track' << origin
621
764
  when :detach
622
- cmd << "--#{flag}" << commit
765
+ cmd << '--detach' << commit
623
766
  else
624
- cmd << "--#{flag}"
625
- append_first %w[ours theirs]
626
- append_head
627
- 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
628
775
  end
629
776
  source
630
777
  end
631
778
 
632
- def tag(flag, refs, message: nil, commit: nil)
779
+ def tag(flag, opts = [], refs: [], message: nil, commit: nil)
633
780
  cmd = git_session 'tag'
634
781
  case flag
635
782
  when :add
636
783
  if option('sign')
637
784
  cmd << '--sign'
638
- else
639
- out = cmd.to_s
640
- 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'
641
787
  end
642
788
  if !commit && message && (hash = commithash(message))
643
789
  commit = hash
644
790
  else
645
791
  append_message message
646
792
  end
647
- append_value(refs, escape: false)
793
+ append_value refs
648
794
  append_head commit
649
- 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
650
807
  cmd << shell_option(flag, commit)
651
- append_option(%w[contains sort] + (flag == :list ? ['merged'] : []), equals: true) unless flag == :delete
652
- append_value(refs, escape: false)
653
808
  end
654
809
  source
655
810
  end
656
811
 
657
- 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: [])
658
830
  cmd = git_session 'diff'
659
- sha = []
831
+ files = option_sanitize(opts, collect_hash(OPT_GIT[:diff]) + OPT_GIT[:log][:diff],
832
+ no: OPT_GIT[:no][:log][:diff]).first
660
833
  case flag
661
- when :files, :between, :contain
834
+ when :files, :view, :between, :contain
662
835
  cmd.delete('--cached')
663
836
  else
664
837
  items = files.dup
838
+ sha = nil
665
839
  files.clear
666
840
  items.each do |val|
667
- if (hash = commithash(val))
668
- sha << hash
841
+ if (s = commithash(val))
842
+ (sha ||= []).push(s)
669
843
  else
670
844
  files << val
671
845
  end
672
846
  end
673
847
  end
674
- if (val = option('unified')).to_i > 0
675
- cmd << basic_option('unified', val)
676
- end
677
848
  append_nocolor
678
- case flag
679
- when :cached
680
- cmd << '--cached'
681
- cmd << '--merge-base' if option('merge-base')
682
- when :branch
683
- cmd << branch
684
- when :files
849
+ if flag == :files
685
850
  cmd << '--no-index'
686
- when :between, :contain
687
- cmd << shell_quote(range.join(flag == :between ? '..' : '...'))
851
+ append_pathspec(refs, parent: true)
688
852
  else
689
- if (val = option('index')) || index > 0
690
- cmd << "HEAD~#{val || index}"
691
- elsif !sha.empty? && option('merge-base')
692
- cmd << '--merge-base'
693
- end
694
- end
695
- unless sha.empty?
696
- if cmd.include?('--cached')
697
- raise_error('diff', sha.join(', '), hint: 'one commit') if sha.size > 1
698
- 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 ? '..' : '...'))
699
860
  else
700
- 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
701
874
  end
875
+ append_pathspec files
702
876
  end
703
- append_pathspec(files, parent: flag == :files)
704
- source(exception: cmd.include?('--exit-code'))
877
+ source(exception: session_arg?('exit-code'))
705
878
  end
706
879
 
707
- def commit(flag, files = [], message: nil, pass: false)
880
+ def commit(flag, *, refs: [], message: nil, pass: false)
708
881
  message ||= option('message', 'm', prefix: 'git', ignore: false)
709
882
  amend = flag.to_s.start_with?('amend')
710
883
  if !message && !amend
@@ -712,11 +885,12 @@ module Squared
712
885
 
713
886
  raise_error('commit', 'GIT_MESSAGE="description"', hint: 'missing')
714
887
  end
715
- pathspec = if flag == :all || (amend && files.size == 1 && files.first == '*')
888
+ pathspec = if flag == :all || (amend && refs.size == 1 && refs.first == '*')
716
889
  '--all'
890
+ elsif (refs = projectmap(refs)).empty?
891
+ raise_error('commit', 'pathspec', hint: 'missing')
717
892
  else
718
- raise_error('commit', 'pathspec', hint: 'missing') if (files = projectmap(files)).empty?
719
- "-- #{files.join(' ')}"
893
+ "-- #{refs.join(' ')}"
720
894
  end
721
895
  origin = nil
722
896
  branch = nil
@@ -726,22 +900,21 @@ module Squared
726
900
  next unless (data = /^\*\s(\S+)\s+(\h+)(?:\s\[(.+?)(?=\]\s)\])?\s/.match(val))
727
901
 
728
902
  branch = data[1]
729
- sha = data[2]
730
903
  if !data[3]
731
904
  unless (origin = option('repository', prefix: 'git', ignore: false))
732
905
  out = source(git_output('log', '-n1', '--format=%h%d'), io: true, stdout: true, banner: false).first
733
- if (data = /^#{sha} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/.match(out))
734
- split_escape(data[1]).each do |val|
906
+ if out =~ /^#{data[2]} \(HEAD -> #{Regexp.escape(branch)}, (.+?)\)$/
907
+ split_escape($1).each do |val|
735
908
  next unless val.end_with?("/#{branch}")
736
909
 
737
- origin = val[0..val.size - branch.size - 2]
910
+ origin = val[0, val.size - branch.size - 1]
738
911
  break
739
912
  end
740
913
  end
741
914
  end
742
915
  upstream = true if origin
743
- elsif (data = Regexp.new("^(.+)/#{Regexp.escape(branch)}$").match(data[3]))
744
- origin = data[1]
916
+ elsif data[3] =~ %r{^(.+)/#{Regexp.escape(branch)}$}
917
+ origin = $1
745
918
  end
746
919
  break
747
920
  end
@@ -772,7 +945,7 @@ module Squared
772
945
  source b
773
946
  end
774
947
 
775
- def branch(flag, names = [], target: nil, ref: nil, opts: [])
948
+ def branch(flag, opts = [], refs: [], ref: nil, target: nil)
776
949
  cmd = git_session 'branch'
777
950
  stdout = false
778
951
  case flag
@@ -789,7 +962,9 @@ module Squared
789
962
  end
790
963
  cmd << '--force' if option('force')
791
964
  when :set
792
- if ref.start_with?('!')
965
+ return unless ref
966
+
967
+ if ref.start_with?('^')
793
968
  cmd << '--unset-upstream' << shell_escape(arg[1..-1])
794
969
  target = nil
795
970
  stdout = true
@@ -798,9 +973,9 @@ module Squared
798
973
  end
799
974
  ref = nil
800
975
  when :delete
801
- force, list = names.partition { |val| val =~ /^[\^~]/ }
976
+ force, list = refs.partition { |val| val =~ /^[\^~]/ }
802
977
  force.each do |val|
803
- dr = val[0..2]
978
+ dr = val[0, 3]
804
979
  d = dr.include?('^') ? '-D' : '-d'
805
980
  r = dr.include?('~') ? '-r' : nil
806
981
  source git_output('branch', d, r, shell_quote(val.sub(/^[\^~]+/, '')))
@@ -812,27 +987,18 @@ module Squared
812
987
  when :move, :copy
813
988
  flag = "-#{flag.to_s[0]}"
814
989
  cmd << (option('force') ? flag.upcase : flag)
815
- names.compact.each { |val| cmd << shell_quote(val) }
990
+ refs.compact.each { |val| cmd << shell_quote(val) }
816
991
  stdout = true
817
992
  when :edit
818
993
  cmd << '--edit-description'
819
994
  when :current
820
995
  cmd << '--show-current'
821
996
  else
822
- opts, pat = option_partition(opts, OPT_BRANCH, no: NO_BRANCH)
997
+ opts = option_sanitize(opts, OPT_GIT[:branch], no: OPT_GIT[:no][:branch]).first
823
998
  grep = []
824
999
  opts.each do |opt|
825
1000
  if opt =~ /^(v+)$/
826
1001
  cmd << "-#{$1}"
827
- elsif opt =~ pat
828
- case $1
829
- when 'column', 'format'
830
- cmd << quote_option($1, $2)
831
- when 'abbrev'
832
- cmd << basic_option($1, $2) if $2.to_i > 0
833
- else
834
- cmd << shell_option($1, $2)
835
- end
836
1002
  else
837
1003
  grep << opt
838
1004
  end
@@ -853,16 +1019,24 @@ module Squared
853
1019
  source(stdout: stdout)
854
1020
  end
855
1021
 
856
- def restore(flag, files, tree: nil)
857
- source = flag == :source
858
- cmd = git_session 'restore', source && files.empty? ? '--patch' : nil, shell_option(flag, tree)
859
- append_option %w[staged worktree]
860
- append_first %w[ours theirs]
861
- append_pathspec(files, expect: !cmd.include?('--patch'))
862
- 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)
863
1037
  end
864
1038
 
865
- def show(objs, format: nil, opts: nil)
1039
+ def show(format, opts = [])
866
1040
  cmd = git_session 'show'
867
1041
  if format
868
1042
  case (val = format.downcase)
@@ -872,41 +1046,54 @@ module Squared
872
1046
  if format =~ /^t?format:/ || format.include?('%')
873
1047
  cmd << quote_option('pretty', format)
874
1048
  else
875
- objs << format
1049
+ opts << format
876
1050
  end
877
1051
  end
878
1052
  end
879
- if opts
880
- append_hash opts
881
- banner = format != 'oneline'
882
- 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')
883
1056
  cmd << basic_option('abbrev', val) if (val = option('abbrev')) && val.to_i > 0
884
1057
  banner = true
885
1058
  end
886
- append_value(objs, delim: true)
1059
+ append_value(refs, delim: true)
887
1060
  source(exception: false, banner: banner)
888
1061
  end
889
1062
 
890
- def rev_parse(flag, ref: nil, size: nil)
891
- git_session 'rev-parse', if flag == :branch
892
- '--abbrev-ref'
893
- else
894
- (n = size.to_i) > 0 ? basic_option('short', [n, 5].max) : '--verify'
895
- end
896
- append_commit ref
897
- 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)
898
1081
  end
899
1082
 
900
- def ls_remote(flag, grep: nil)
901
- 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
902
1088
  out, banner, from = source(io: true)
903
1089
  print_item banner
904
1090
  ret = write_lines(out, grep: grep)
905
1091
  list_result(ret, flag.to_s, from: from, grep: grep)
906
1092
  end
907
1093
 
908
- def ls_files(flag, grep: nil)
1094
+ def ls_files(flag, opts = [])
909
1095
  git_session 'ls-files', "--#{flag}"
1096
+ grep = option_sanitize(opts, OPT_GIT[:ls_files]).first
910
1097
  out, banner, from = source(io: true)
911
1098
  print_item banner
912
1099
  ret = write_lines(out, grep: grep)
@@ -934,7 +1121,7 @@ module Squared
934
1121
  end
935
1122
  cmd = session_done(cmd)
936
1123
  log.info cmd
937
- on :first, from if from
1124
+ on :first, from
938
1125
  banner = if banner
939
1126
  format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
940
1127
  end
@@ -970,22 +1157,28 @@ module Squared
970
1157
  end
971
1158
  rescue StandardError => e
972
1159
  log.error e
973
- ret = on(:error, from, e) if from
1160
+ ret = on(:error, from, e)
974
1161
  raise if exception && ret != true
975
1162
 
976
1163
  warn log_message(Logger::WARN, e) if warning?
977
1164
  else
978
- on :last, from if from
1165
+ on :last, from
979
1166
  end
980
1167
  end
981
1168
 
982
1169
  def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false)
983
- 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
984
1177
  sub = nil if stdin?
985
1178
  ret = 0
986
1179
  out = []
987
1180
  data.each do |line|
988
- next if grep && !line.match?(grep)
1181
+ next if grep&.none? { |pat| pat.match?(line) }
989
1182
 
990
1183
  if loglevel
991
1184
  log.add loglevel, line
@@ -1011,35 +1204,34 @@ module Squared
1011
1204
  puts print_footer("#{size} #{size == 1 ? type.sub(/s\z/, '') : type}",
1012
1205
  sub: { pat: /\A(\d+)(.+)\z/, styles: styles })
1013
1206
  else
1014
- 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)
1015
1213
  end
1016
1214
  end
1017
- on :last, from if from
1215
+ on :last, from
1018
1216
  end
1019
1217
 
1020
- 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)
1021
1219
  cmd << '--force' if option('force')
1022
- modules = append_submodules(target: target)
1220
+ rsm = append_submodules(target: target)
1023
1221
  out = []
1024
1222
  refspec = []
1025
- 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)
1026
1224
  opts.each do |opt|
1027
1225
  if opt =~ pat
1028
1226
  case $1
1029
1227
  when 'rebase'
1030
- target << basic_option($1, $2) if VAL_REBASE.include?($2)
1228
+ target << basic_option($1, $2) if VAL_GIT[:rebase][:value].include?($2)
1031
1229
  when 'shallow-since'
1032
1230
  next unless (val = Date.parse($2))
1033
1231
 
1034
1232
  target << quote_option($1, val.strftime('%F %T'))
1035
1233
  when 'recurse-submodules'
1036
- target << basic_option($1, $2) unless modules
1037
- when 'shallow-exclude', 'gpg-sign', 'signoff', 'strategy', 'strategy-option'
1038
- target << shell_option($1, $2)
1039
- when 'refmap', 'negotiation-tip'
1040
- target << quote_option($1, $2)
1041
- when 'depth', 'deepen', 'log', 'jobs'
1042
- target << basic_option($1, $2) if $2.to_i > 0
1234
+ target << basic_option($1, $2) unless rsm
1043
1235
  when 'refspec'
1044
1236
  refspec << shell_escape($2, quote: true)
1045
1237
  end
@@ -1048,9 +1240,9 @@ module Squared
1048
1240
  end
1049
1241
  end
1050
1242
  if remote
1051
- append_value(remote, target: target, delim: true, quote: true)
1243
+ append_value(remote, target: target, delim: true)
1052
1244
  if (val = option('refspec', strict: true))
1053
- append_value(split_escape(val), target: target, escape: false)
1245
+ append_value(split_escape(val), target: target)
1054
1246
  else
1055
1247
  target.merge(refspec)
1056
1248
  end
@@ -1068,25 +1260,29 @@ module Squared
1068
1260
  end
1069
1261
 
1070
1262
  def append_pathspec(files = [], target: @session, expect: false, parent: false)
1071
- if files.empty? && (val = option('pathspec'))
1072
- files = split_escape(val)
1073
- end
1074
- files = projectmap(files, parent: parent)
1075
- if !files.empty?
1076
- target << "-- #{files.join(' ')}"
1077
- elsif expect
1078
- 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
1079
1275
  end
1080
1276
  end
1081
1277
 
1082
1278
  def append_message(val, target: @session)
1083
- target << "--message=\"#{double_quote(val)}\"" unless val.to_s.empty?
1279
+ target << quote_option('message', val) unless val.to_s.empty?
1084
1280
  end
1085
1281
 
1086
1282
  def append_head(val = nil, target: @session)
1087
1283
  return target << val if val
1088
1284
 
1089
- 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)
1090
1286
  end
1091
1287
 
1092
1288
  def append_submodules(from = nil, target: @session)
@@ -1118,8 +1314,14 @@ module Squared
1118
1314
  git_session(*cmd, main: false, options: false, **kwargs)
1119
1315
  end
1120
1316
 
1121
- def dryrun?(*)
1122
- !!@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')
1123
1325
  end
1124
1326
 
1125
1327
  def gitpath
@@ -1127,7 +1329,7 @@ module Squared
1127
1329
  end
1128
1330
 
1129
1331
  def commithash(val)
1130
- (data = /\A#\{(\h{5,40})\}\z/.match(val)) ? data[1] : nil
1332
+ val =~ /\A#\{(\h{5,40})\}\z/ ? $1 : nil
1131
1333
  end
1132
1334
 
1133
1335
  def threadargs