git 5.7.0 → 6.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +132 -35
- data/CONTRIBUTING.md +44 -31
- data/README.md +138 -100
- data/UPGRADING.md +867 -262
- data/git.gemspec +6 -8
- data/lib/git/author_info.rb +1 -2
- data/lib/git/commands/base.rb +22 -2
- data/lib/git/commands/cat_file/raw.rb +0 -68
- data/lib/git/commands/maintenance/register.rb +0 -4
- data/lib/git/commands/maintenance/run.rb +0 -4
- data/lib/git/commands/maintenance/start.rb +0 -4
- data/lib/git/commands/maintenance/stop.rb +0 -4
- data/lib/git/commands/maintenance/unregister.rb +0 -4
- data/lib/git/commands/maintenance.rb +0 -2
- data/lib/git/commands/show_ref/exclude_existing.rb +1 -1
- data/lib/git/commands/show_ref/exists.rb +0 -5
- data/lib/git/commands/show_ref/list.rb +1 -1
- data/lib/git/commands/show_ref/verify.rb +1 -1
- data/lib/git/commands/show_ref.rb +1 -1
- data/lib/git/commands/worktree/repair.rb +0 -5
- data/lib/git/diff_path_status.rb +1 -1
- data/lib/git/encoding_utils.rb +25 -0
- data/lib/git/errors.rb +24 -18
- data/lib/git/factories.rb +361 -125
- data/lib/git/log.rb +3 -75
- data/lib/git/object.rb +4 -185
- data/lib/git/path_resolver.rb +104 -36
- data/lib/git/repository/branching.rb +21 -189
- data/lib/git/repository/committing.rb +0 -25
- data/lib/git/repository/context_helpers.rb +249 -155
- data/lib/git/repository/diffing.rb +2 -72
- data/lib/git/repository/merging.rb +32 -54
- data/lib/git/repository/object_operations.rb +120 -497
- data/lib/git/repository/remote_operations.rb +7 -219
- data/lib/git/repository/staging.rb +6 -184
- data/lib/git/repository/stashing.rb +126 -130
- data/lib/git/repository/status_operations.rb +1 -54
- data/lib/git/repository/worktree_operations.rb +30 -125
- data/lib/git/repository.rb +20 -299
- data/lib/git/system_call_guard.rb +95 -0
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +47 -364
- metadata +24 -18
- data/lib/git/author.rb +0 -46
- data/lib/git/branch.rb +0 -693
- data/lib/git/branches.rb +0 -194
- data/lib/git/remote.rb +0 -191
- data/lib/git/stash.rb +0 -124
- data/lib/git/stashes.rb +0 -198
- data/lib/git/status.rb +0 -384
- data/lib/git/worktree.rb +0 -180
- data/lib/git/worktrees.rb +0 -152
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'git/commands/config_option_syntax'
|
|
4
3
|
require 'git/commands/fetch'
|
|
5
4
|
require 'git/commands/ls_remote'
|
|
6
5
|
require 'git/commands/pull'
|
|
@@ -8,7 +7,6 @@ require 'git/commands/push'
|
|
|
8
7
|
require 'git/commands/remote'
|
|
9
8
|
require 'git/parsers/ls_remote'
|
|
10
9
|
require 'git/parsers/remote'
|
|
11
|
-
require 'git/remote'
|
|
12
10
|
|
|
13
11
|
require 'git/repository/shared_private'
|
|
14
12
|
|
|
@@ -20,7 +18,7 @@ module Git
|
|
|
20
18
|
#
|
|
21
19
|
# @api private
|
|
22
20
|
#
|
|
23
|
-
module RemoteOperations
|
|
21
|
+
module RemoteOperations
|
|
24
22
|
# Key normalizations for {#fetch} options
|
|
25
23
|
#
|
|
26
24
|
# Maps dash-style option keys (which the 4.x `Git::Lib#fetch` accepted)
|
|
@@ -192,6 +190,12 @@ module Git
|
|
|
192
190
|
#
|
|
193
191
|
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
194
192
|
#
|
|
193
|
+
# @note The fetch completes before the merge starts, so a failure after the
|
|
194
|
+
# fetch leaves `FETCH_HEAD` and any updated remote-tracking branches in
|
|
195
|
+
# place. On a conflict, the merge is left in progress as described at
|
|
196
|
+
# {#merge}, or the rebase when the repository is configured to pull with
|
|
197
|
+
# rebase.
|
|
198
|
+
#
|
|
195
199
|
def pull(remote = nil, branch = nil, opts = {})
|
|
196
200
|
raise ArgumentError, 'You must specify a remote if a branch is specified' if remote.nil? && !branch.nil?
|
|
197
201
|
|
|
@@ -346,41 +350,6 @@ module Git
|
|
|
346
350
|
nil
|
|
347
351
|
end
|
|
348
352
|
|
|
349
|
-
# @param name [String] the name for the new remote
|
|
350
|
-
#
|
|
351
|
-
# @param url [String, Git::Repository] the URL of the remote repository
|
|
352
|
-
#
|
|
353
|
-
# A {Git::Repository} instance is accepted for local references and converted
|
|
354
|
-
# to `url.repo.to_s`.
|
|
355
|
-
#
|
|
356
|
-
# @param opts [Hash] options for adding the remote
|
|
357
|
-
#
|
|
358
|
-
# @option opts [Boolean, nil] :fetch (nil) fetch from the remote immediately
|
|
359
|
-
# after adding it (`-f`)
|
|
360
|
-
#
|
|
361
|
-
# The deprecated alias `:with_fetch` is accepted and normalized
|
|
362
|
-
# automatically.
|
|
363
|
-
#
|
|
364
|
-
# @option opts [String, nil] :track (nil) track only the given branch during
|
|
365
|
-
# fetch (`-t`)
|
|
366
|
-
#
|
|
367
|
-
# @return [Git::Remote] the newly added remote
|
|
368
|
-
#
|
|
369
|
-
# @raise [ArgumentError] when unsupported option keys are provided
|
|
370
|
-
#
|
|
371
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
372
|
-
#
|
|
373
|
-
# @deprecated Use {#remote_add} instead
|
|
374
|
-
#
|
|
375
|
-
def add_remote(name, url, opts = {})
|
|
376
|
-
Git::Deprecation.warn(
|
|
377
|
-
'Git::Repository#add_remote is deprecated and will be removed in v6.0.0. ' \
|
|
378
|
-
'Use Git::Repository#remote_add instead.'
|
|
379
|
-
)
|
|
380
|
-
remote_add(name, url, opts)
|
|
381
|
-
Git::Remote.new(self, name)
|
|
382
|
-
end
|
|
383
|
-
|
|
384
353
|
# Removes a remote from this repository
|
|
385
354
|
#
|
|
386
355
|
# Deletes the remote named `name` along with its associated configuration,
|
|
@@ -399,22 +368,6 @@ module Git
|
|
|
399
368
|
Git::Commands::Remote::Remove.new(@execution_context).call(name)
|
|
400
369
|
end
|
|
401
370
|
|
|
402
|
-
# @param name [String] the name of the remote to remove
|
|
403
|
-
#
|
|
404
|
-
# @return [Git::CommandLine::Result] the result of calling `git remote remove`
|
|
405
|
-
#
|
|
406
|
-
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
407
|
-
#
|
|
408
|
-
# @deprecated Use {#remote_remove} instead
|
|
409
|
-
#
|
|
410
|
-
def remove_remote(name)
|
|
411
|
-
Git::Deprecation.warn(
|
|
412
|
-
'Git::Repository#remove_remote is deprecated and will be removed in v6.0.0. ' \
|
|
413
|
-
'Use Git::Repository#remote_remove instead.'
|
|
414
|
-
)
|
|
415
|
-
remote_remove(name)
|
|
416
|
-
end
|
|
417
|
-
|
|
418
371
|
# Sets the URL for an existing remote
|
|
419
372
|
#
|
|
420
373
|
# Replaces the fetch URL configured for the remote named `name`.
|
|
@@ -444,28 +397,6 @@ module Git
|
|
|
444
397
|
nil
|
|
445
398
|
end
|
|
446
399
|
|
|
447
|
-
# @param name [String] the name of the remote to update
|
|
448
|
-
#
|
|
449
|
-
# @param url [String, Git::Repository] the new URL for the remote
|
|
450
|
-
#
|
|
451
|
-
# A {Git::Repository} instance is accepted for local references and converted
|
|
452
|
-
# to `url.repo.to_s`.
|
|
453
|
-
#
|
|
454
|
-
# @return [Git::Remote] the updated remote
|
|
455
|
-
#
|
|
456
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
457
|
-
#
|
|
458
|
-
# @deprecated Use {#remote_set_url} instead
|
|
459
|
-
#
|
|
460
|
-
def set_remote_url(name, url)
|
|
461
|
-
Git::Deprecation.warn(
|
|
462
|
-
'Git::Repository#set_remote_url is deprecated and will be removed in v6.0.0. ' \
|
|
463
|
-
'Use Git::Repository#remote_set_url instead.'
|
|
464
|
-
)
|
|
465
|
-
remote_set_url(name, url)
|
|
466
|
-
Git::Remote.new(self, name)
|
|
467
|
-
end
|
|
468
|
-
|
|
469
400
|
# Configures which branches are fetched for a remote
|
|
470
401
|
#
|
|
471
402
|
# Uses `git remote set-branches` to set or append fetch refspecs. When the
|
|
@@ -503,65 +434,6 @@ module Git
|
|
|
503
434
|
nil
|
|
504
435
|
end
|
|
505
436
|
|
|
506
|
-
# Return the git configuration entries for a named remote
|
|
507
|
-
#
|
|
508
|
-
# Reads `git config --list` and returns all entries whose keys begin with
|
|
509
|
-
# `remote.<name>.`, with the `remote.<name>.` prefix stripped. This
|
|
510
|
-
# typically yields at least `"url"` and `"fetch"` for a configured remote.
|
|
511
|
-
#
|
|
512
|
-
# @example Retrieve the config for the 'origin' remote
|
|
513
|
-
# repo.config_remote('origin')
|
|
514
|
-
# #=> {
|
|
515
|
-
# # 'url' => 'https://github.com/user/repo.git',
|
|
516
|
-
# # 'fetch' => '+refs/heads/*:refs/remotes/origin/*'
|
|
517
|
-
# # }
|
|
518
|
-
#
|
|
519
|
-
# @param name [String] the name of the remote (e.g. `"origin"`)
|
|
520
|
-
#
|
|
521
|
-
# @return [Hash{String => String}] configuration entries for the remote,
|
|
522
|
-
# keyed without the `remote.<name>.` prefix
|
|
523
|
-
#
|
|
524
|
-
# Returns an empty hash when no entries are found.
|
|
525
|
-
#
|
|
526
|
-
# @raise [Git::FailedError] when git exits with a non-zero status
|
|
527
|
-
#
|
|
528
|
-
# @deprecated Use `remote_list.find { |r| r.name == name }` for the fields
|
|
529
|
-
# {Git::RemoteInfo} models, or filter {Git::Configuring#config_list} on
|
|
530
|
-
# the `remote.<name>.` key prefix to keep every entry
|
|
531
|
-
#
|
|
532
|
-
# {#remote_list} returns a {Git::RemoteInfo} per remote. Its `url` and
|
|
533
|
-
# `fetch` members hold every configured value as `Array<String>`,
|
|
534
|
-
# whereas this method returns a flat hash in which a repeated `url` or
|
|
535
|
-
# `fetch` key overwrites the earlier value.
|
|
536
|
-
#
|
|
537
|
-
# {Git::RemoteInfo} models only the remote variables git defines and
|
|
538
|
-
# drops any other `remote.<name>.*` entry, whereas this method returns
|
|
539
|
-
# every entry. Callers that read custom keys should filter
|
|
540
|
-
# {Git::Configuring#config_list} instead, which returns the same hash
|
|
541
|
-
# (shown here for the `origin` remote):
|
|
542
|
-
#
|
|
543
|
-
# prefix = 'remote.origin.'
|
|
544
|
-
# repo.config_list
|
|
545
|
-
# .select { |entry| entry.key.start_with?(prefix) }
|
|
546
|
-
# .to_h { |entry| [entry.key.delete_prefix(prefix), entry.value] }
|
|
547
|
-
#
|
|
548
|
-
# @see #remote_list
|
|
549
|
-
#
|
|
550
|
-
# @see Git::Configuring#config_list
|
|
551
|
-
#
|
|
552
|
-
def config_remote(name)
|
|
553
|
-
Git::Deprecation.warn(
|
|
554
|
-
'Git::Repository#config_remote is deprecated and will be removed in v6.0.0. ' \
|
|
555
|
-
'Use Git::Repository#remote_list.find { |r| r.name == name } for the fields ' \
|
|
556
|
-
'Git::RemoteInfo models, or filter Git::Repository#config_list on the ' \
|
|
557
|
-
'"remote.<name>." key prefix to keep every entry.'
|
|
558
|
-
)
|
|
559
|
-
prefix = "remote.#{name}."
|
|
560
|
-
Private.config_list(@execution_context).each_with_object({}) do |(key, value), hsh|
|
|
561
|
-
hsh[key.delete_prefix(prefix)] = value if key.start_with?(prefix)
|
|
562
|
-
end
|
|
563
|
-
end
|
|
564
|
-
|
|
565
437
|
# List all configured remotes as {Git::RemoteInfo} objects
|
|
566
438
|
#
|
|
567
439
|
# Reads the repository configuration via {Git::Configuring#config_list} and
|
|
@@ -590,67 +462,6 @@ module Git
|
|
|
590
462
|
Git::Parsers::Remote.parse_list(config_list)
|
|
591
463
|
end
|
|
592
464
|
|
|
593
|
-
# Returns a {Git::Remote} object for the named remote
|
|
594
|
-
#
|
|
595
|
-
# @example Get the default 'origin' remote
|
|
596
|
-
# repo.remote #=> #<Git::Remote 'origin'>
|
|
597
|
-
#
|
|
598
|
-
# @example Get a named remote
|
|
599
|
-
# repo.remote('upstream') #=> #<Git::Remote 'upstream'>
|
|
600
|
-
#
|
|
601
|
-
# @param name [String] the remote name (defaults to `'origin'`)
|
|
602
|
-
#
|
|
603
|
-
# @return [Git::Remote] the remote object
|
|
604
|
-
#
|
|
605
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
606
|
-
#
|
|
607
|
-
# @deprecated Use `remote_list.find { |r| r.name == name }` instead
|
|
608
|
-
#
|
|
609
|
-
# {#remote_list} returns immutable {Git::RemoteInfo} value objects
|
|
610
|
-
# rather than {Git::Remote}. Call the corresponding {Git::Repository}
|
|
611
|
-
# method (e.g. {#fetch}, {#remote_remove}) for operations on a remote.
|
|
612
|
-
#
|
|
613
|
-
# @see #remote_list
|
|
614
|
-
#
|
|
615
|
-
def remote(name = 'origin')
|
|
616
|
-
Git::Deprecation.warn(
|
|
617
|
-
'Git::Repository#remote is deprecated and will be removed in v6.0.0. ' \
|
|
618
|
-
'Use Git::Repository#remote_list.find { |r| r.name == name } instead.'
|
|
619
|
-
)
|
|
620
|
-
Git::Remote.new(self, name)
|
|
621
|
-
end
|
|
622
|
-
|
|
623
|
-
# Returns all configured remotes as {Git::Remote} objects
|
|
624
|
-
#
|
|
625
|
-
# @example List all remotes
|
|
626
|
-
# repo.remotes #=> [#<Git::Remote 'origin'>, #<Git::Remote 'upstream'>]
|
|
627
|
-
#
|
|
628
|
-
# @return [Array<Git::Remote>] one {Git::Remote} for each configured remote
|
|
629
|
-
#
|
|
630
|
-
# Returns an empty array when no remotes are configured.
|
|
631
|
-
#
|
|
632
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
633
|
-
#
|
|
634
|
-
# @deprecated Use {#remote_list} instead
|
|
635
|
-
#
|
|
636
|
-
# {#remote_list} returns `Array<Git::RemoteInfo>` (immutable value
|
|
637
|
-
# objects) rather than `Array<Git::Remote>`. Call the corresponding
|
|
638
|
-
# {Git::Repository} method (e.g. {#fetch}, {#remote_remove}) for
|
|
639
|
-
# operations on a remote. Each {Git::Remote} this method constructs
|
|
640
|
-
# emits its own deprecation warning, so a call produces one warning
|
|
641
|
-
# for this method plus one per remote returned.
|
|
642
|
-
#
|
|
643
|
-
# @see #remote_list
|
|
644
|
-
#
|
|
645
|
-
def remotes
|
|
646
|
-
Git::Deprecation.warn(
|
|
647
|
-
'Git::Repository#remotes is deprecated and will be removed in v6.0.0. ' \
|
|
648
|
-
'Use Git::Repository#remote_list instead.'
|
|
649
|
-
)
|
|
650
|
-
result = Git::Commands::Remote::List.new(@execution_context).call
|
|
651
|
-
result.stdout.split("\n").map { |name| Git::Remote.new(self, name) }
|
|
652
|
-
end
|
|
653
|
-
|
|
654
465
|
# Returns the names of all configured remotes
|
|
655
466
|
#
|
|
656
467
|
# Lists remote names by running `git remote`. This is a lightweight
|
|
@@ -954,29 +765,6 @@ module Git
|
|
|
954
765
|
normalized[:fetch] = normalized.delete(:with_fetch) if normalized.key?(:with_fetch)
|
|
955
766
|
normalized
|
|
956
767
|
end
|
|
957
|
-
|
|
958
|
-
# Retrieve all config entries as a flat hash
|
|
959
|
-
#
|
|
960
|
-
# Runs `git config --list` and parses each `key=value` line into a hash.
|
|
961
|
-
# When no value is present for a key, the value defaults to an empty string.
|
|
962
|
-
#
|
|
963
|
-
# @param execution_context [Git::ExecutionContext::Repository] the
|
|
964
|
-
# execution context for the repository
|
|
965
|
-
#
|
|
966
|
-
# @return [Hash{String => String}] all visible config entries, keyed by
|
|
967
|
-
# their full dotted key names
|
|
968
|
-
#
|
|
969
|
-
# For example, `"remote.origin.url"` is a valid key.
|
|
970
|
-
#
|
|
971
|
-
# @api private
|
|
972
|
-
#
|
|
973
|
-
def config_list(execution_context)
|
|
974
|
-
lines = Git::Commands::ConfigOptionSyntax::List.new(execution_context).call.stdout.split("\n")
|
|
975
|
-
lines.each_with_object({}) do |line, hsh|
|
|
976
|
-
key, value = line.split('=', 2)
|
|
977
|
-
hsh[key] = value || ''
|
|
978
|
-
end
|
|
979
|
-
end
|
|
980
768
|
end
|
|
981
769
|
private_constant :Private
|
|
982
770
|
end
|
|
@@ -92,38 +92,6 @@ module Git
|
|
|
92
92
|
Git::Commands::Reset.new(@execution_context).call(commitish, **opts).stdout
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
-
# Reset the current HEAD to a specified state with `--hard`
|
|
96
|
-
#
|
|
97
|
-
# @example Hard reset to HEAD
|
|
98
|
-
# repo.reset_hard
|
|
99
|
-
#
|
|
100
|
-
# @example Hard reset to a specific commit
|
|
101
|
-
# repo.reset_hard('HEAD~1')
|
|
102
|
-
#
|
|
103
|
-
# @param commitish [String, nil] the commit or tree-ish to reset to;
|
|
104
|
-
# defaults to HEAD when `nil`
|
|
105
|
-
#
|
|
106
|
-
# @param opts [Hash] options passed through to {#reset}
|
|
107
|
-
#
|
|
108
|
-
# @option opts [Boolean, nil] :hard (nil) ignored; this method always forces
|
|
109
|
-
# `hard: true`
|
|
110
|
-
#
|
|
111
|
-
# @return [String] git's stdout from the reset
|
|
112
|
-
#
|
|
113
|
-
# @raise [ArgumentError] when unsupported options are provided
|
|
114
|
-
#
|
|
115
|
-
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
116
|
-
#
|
|
117
|
-
# @deprecated Use {#reset} with `hard: true` instead
|
|
118
|
-
#
|
|
119
|
-
def reset_hard(commitish = nil, opts = {})
|
|
120
|
-
Git::Deprecation.warn(
|
|
121
|
-
'Git::Repository#reset_hard is deprecated and will be removed in v6.0.0. ' \
|
|
122
|
-
'Use Git::Repository#reset(commitish, hard: true) instead.'
|
|
123
|
-
)
|
|
124
|
-
reset(commitish, **opts, hard: true)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
95
|
# Apply a patch file to the working tree
|
|
128
96
|
#
|
|
129
97
|
# Reads the unified diff in `file` and applies it to the working tree via
|
|
@@ -164,6 +132,11 @@ module Git
|
|
|
164
132
|
#
|
|
165
133
|
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
166
134
|
#
|
|
135
|
+
# @note If a patch fails to apply, the `git am` session is left in progress
|
|
136
|
+
# until the caller continues, skips, or aborts it. The patches applied
|
|
137
|
+
# before it are already committed on the current branch; aborting the
|
|
138
|
+
# session removes them again.
|
|
139
|
+
#
|
|
167
140
|
def apply_mail(file)
|
|
168
141
|
return unless File.exist?(file)
|
|
169
142
|
|
|
@@ -325,10 +298,6 @@ module Git
|
|
|
325
298
|
end
|
|
326
299
|
|
|
327
300
|
# Option keys accepted by {#clean}
|
|
328
|
-
#
|
|
329
|
-
# The deprecated `:ff` and `:force_force` keys are handled by
|
|
330
|
-
# {Git::Repository::Staging::Private.migrate_clean_legacy_options} before this
|
|
331
|
-
# whitelist is enforced, so they are intentionally absent here.
|
|
332
301
|
CLEAN_ALLOWED_OPTS = %i[d force f dry_run n quiet q exclude e x X pathspec].freeze
|
|
333
302
|
private_constant :CLEAN_ALLOWED_OPTS
|
|
334
303
|
|
|
@@ -377,13 +346,11 @@ module Git
|
|
|
377
346
|
#
|
|
378
347
|
# @return [String] git's stdout from the clean
|
|
379
348
|
#
|
|
380
|
-
# @raise [ArgumentError] when unsupported options are provided
|
|
381
|
-
# deprecated `:ff`/`:force_force` value is not `true`, `false`, or `nil`
|
|
349
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
382
350
|
#
|
|
383
351
|
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
384
352
|
#
|
|
385
353
|
def clean(opts = {})
|
|
386
|
-
opts = Private.migrate_clean_legacy_options(opts)
|
|
387
354
|
SharedPrivate.assert_valid_opts!(CLEAN_ALLOWED_OPTS, **opts)
|
|
388
355
|
Git::Commands::Clean.new(@execution_context).call(**opts).stdout
|
|
389
356
|
end
|
|
@@ -417,151 +384,6 @@ module Git
|
|
|
417
384
|
module Private
|
|
418
385
|
module_function
|
|
419
386
|
|
|
420
|
-
# Translate deprecated `git clean` option keys into their modern form
|
|
421
|
-
#
|
|
422
|
-
# Maps the legacy `:ff` and `:force_force` boolean options onto the
|
|
423
|
-
# `:force` option, emitting a deprecation warning for each.
|
|
424
|
-
#
|
|
425
|
-
# @param opts [Hash] the caller-provided clean options
|
|
426
|
-
#
|
|
427
|
-
# @option opts [Boolean, nil] :ff (nil) deprecated alias for requesting a
|
|
428
|
-
# double-force clean
|
|
429
|
-
#
|
|
430
|
-
# @option opts [Boolean, nil] :force_force (nil) deprecated alias for
|
|
431
|
-
# requesting a double-force clean
|
|
432
|
-
#
|
|
433
|
-
# @option opts [Boolean, Integer, nil] :force (nil) existing force value
|
|
434
|
-
# merged with deprecated options when present
|
|
435
|
-
#
|
|
436
|
-
# @return [Hash] a new options hash with deprecated keys translated
|
|
437
|
-
#
|
|
438
|
-
# @raise [ArgumentError] when a deprecated value is not `true`, `false`, or `nil`
|
|
439
|
-
#
|
|
440
|
-
def migrate_clean_legacy_options(opts)
|
|
441
|
-
opts = deprecate_clean_option(
|
|
442
|
-
:ff,
|
|
443
|
-
':ff option is deprecated and will be removed in v6.0.0. Use force: 2 instead.',
|
|
444
|
-
opts
|
|
445
|
-
)
|
|
446
|
-
|
|
447
|
-
deprecate_clean_option(
|
|
448
|
-
:force_force,
|
|
449
|
-
':force_force option is deprecated and will be removed in v6.0.0. Use force: 2 instead.',
|
|
450
|
-
opts
|
|
451
|
-
)
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
# Translate a single deprecated clean option key onto `:force`
|
|
455
|
-
#
|
|
456
|
-
# @param key [Symbol] the deprecated option key (`:ff` or `:force_force`)
|
|
457
|
-
#
|
|
458
|
-
# @param message [String] the deprecation message to emit
|
|
459
|
-
#
|
|
460
|
-
# @param opts [Hash] the clean options
|
|
461
|
-
#
|
|
462
|
-
# @option opts [Boolean, nil] :ff (nil) deprecated alias for requesting a
|
|
463
|
-
# double-force clean
|
|
464
|
-
#
|
|
465
|
-
# @option opts [Boolean, nil] :force_force (nil) deprecated alias for
|
|
466
|
-
# requesting a double-force clean
|
|
467
|
-
#
|
|
468
|
-
# @option opts [Boolean, Integer, nil] :force (nil) existing force value
|
|
469
|
-
# updated when the deprecated key is true
|
|
470
|
-
#
|
|
471
|
-
# @return [Hash] a new options hash with the deprecated key removed
|
|
472
|
-
#
|
|
473
|
-
# @raise [ArgumentError] when the deprecated value is not `true`, `false`,
|
|
474
|
-
# or `nil`
|
|
475
|
-
#
|
|
476
|
-
def deprecate_clean_option(key, message, opts)
|
|
477
|
-
return opts unless opts.key?(key)
|
|
478
|
-
|
|
479
|
-
opts = opts.dup
|
|
480
|
-
deprecated_value = opts.delete(key)
|
|
481
|
-
validate_deprecated_clean_option_value!(key, deprecated_value)
|
|
482
|
-
|
|
483
|
-
Git::Deprecation.warn(message)
|
|
484
|
-
return opts unless deprecated_value
|
|
485
|
-
|
|
486
|
-
opts[:force] = merge_clean_force_option(opts[:force], force_specified: force_option_specified?(opts))
|
|
487
|
-
opts
|
|
488
|
-
end
|
|
489
|
-
|
|
490
|
-
# Whether the caller explicitly set a non-nil `:force` value
|
|
491
|
-
#
|
|
492
|
-
# @param opts [Hash] the clean options
|
|
493
|
-
#
|
|
494
|
-
# @option opts [Boolean, Integer, nil] :force (nil) the clean force value
|
|
495
|
-
# to inspect
|
|
496
|
-
#
|
|
497
|
-
# @return [Boolean] true if `:force` was set to a non-nil value, false
|
|
498
|
-
# otherwise
|
|
499
|
-
#
|
|
500
|
-
def force_option_specified?(opts)
|
|
501
|
-
opts.key?(:force) && !opts[:force].nil?
|
|
502
|
-
end
|
|
503
|
-
|
|
504
|
-
# Validate the value passed to a deprecated clean option
|
|
505
|
-
#
|
|
506
|
-
# @param key [Symbol] the deprecated option key
|
|
507
|
-
#
|
|
508
|
-
# @param value [Object] the value provided for the deprecated key
|
|
509
|
-
#
|
|
510
|
-
# @return [void]
|
|
511
|
-
#
|
|
512
|
-
# @raise [ArgumentError] when `value` is not `true`, `false`, or `nil`
|
|
513
|
-
#
|
|
514
|
-
def validate_deprecated_clean_option_value!(key, value)
|
|
515
|
-
return if value.nil? || value == true || value == false
|
|
516
|
-
|
|
517
|
-
raise ArgumentError, "#{key} option only accepts true, false, or nil"
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
# Merge a deprecated force request into the existing `:force` value
|
|
521
|
-
#
|
|
522
|
-
# @param existing_force [Boolean, Integer, nil] the caller's `:force` value
|
|
523
|
-
#
|
|
524
|
-
# @param force_specified [Boolean] whether the caller explicitly set `:force`
|
|
525
|
-
#
|
|
526
|
-
# @return [Integer] the resolved `:force` value
|
|
527
|
-
#
|
|
528
|
-
def merge_clean_force_option(existing_force, force_specified: false)
|
|
529
|
-
return 2 unless force_specified
|
|
530
|
-
|
|
531
|
-
normalized_force = normalize_clean_force_option(existing_force)
|
|
532
|
-
|
|
533
|
-
case normalized_force
|
|
534
|
-
when Integer then merge_integer_clean_force_option(normalized_force)
|
|
535
|
-
when false then 2
|
|
536
|
-
else normalized_force
|
|
537
|
-
end
|
|
538
|
-
end
|
|
539
|
-
|
|
540
|
-
# Merge an integer `:force` value with the deprecated force request
|
|
541
|
-
#
|
|
542
|
-
# @param normalized_force [Integer] the caller's normalized `:force` value
|
|
543
|
-
#
|
|
544
|
-
# @return [Integer] the resolved `:force` value
|
|
545
|
-
#
|
|
546
|
-
def merge_integer_clean_force_option(normalized_force)
|
|
547
|
-
return normalized_force if normalized_force < 1
|
|
548
|
-
|
|
549
|
-
[normalized_force, 2].max
|
|
550
|
-
end
|
|
551
|
-
|
|
552
|
-
# Normalize a `:force` value, coercing `true` to the integer `1`
|
|
553
|
-
#
|
|
554
|
-
# @param value [Boolean, Integer, nil] the `:force` value
|
|
555
|
-
#
|
|
556
|
-
# @return [Integer, Boolean, nil] the normalized value
|
|
557
|
-
#
|
|
558
|
-
def normalize_clean_force_option(value)
|
|
559
|
-
case value
|
|
560
|
-
when true then 1
|
|
561
|
-
else value
|
|
562
|
-
end
|
|
563
|
-
end
|
|
564
|
-
|
|
565
387
|
# Unescape a git-quoted path
|
|
566
388
|
#
|
|
567
389
|
# Git wraps paths containing non-ASCII or special characters in
|