git 5.0.0.beta.1 → 5.0.0.beta.2
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/.github/copilot-instructions.md +6 -0
- data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +188 -0
- data/.github/skills/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +22 -0
- data/.github/skills/extract-facade-from-base-lib/SKILL.md +28 -14
- data/.github/skills/facade-implementation/SKILL.md +14 -0
- data/.github/skills/facade-test-conventions/SKILL.md +14 -0
- data/.rubocop.yml +5 -0
- data/README.md +51 -11
- data/UPGRADING.md +141 -0
- data/git.gemspec +5 -0
- data/lib/git/branch.rb +7 -18
- data/lib/git/branches.rb +2 -10
- data/lib/git/command_line/base.rb +10 -0
- data/lib/git/command_line/capturing.rb +5 -3
- data/lib/git/command_line/streaming.rb +5 -3
- data/lib/git/command_line.rb +3 -3
- data/lib/git/commands/base.rb +7 -6
- data/lib/git/commands/cat_file/batch.rb +6 -1
- data/lib/git/commands/cat_file/raw.rb +7 -1
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +5 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +1 -1
- data/lib/git/commands/update_ref/batch.rb +1 -1
- data/lib/git/commands/version.rb +5 -0
- data/lib/git/commands.rb +5 -7
- data/lib/git/config.rb +17 -0
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +665 -0
- data/lib/git/deprecation.rb +9 -0
- data/lib/git/diff.rb +4 -8
- data/lib/git/diff_path_status.rb +2 -13
- data/lib/git/diff_stats.rb +1 -9
- data/lib/git/execution_context/global.rb +3 -28
- data/lib/git/execution_context/repository.rb +30 -41
- data/lib/git/execution_context.rb +43 -24
- data/lib/git/log.rb +3 -9
- data/lib/git/object.rb +14 -21
- data/lib/git/parsers/config_entry.rb +110 -0
- data/lib/git/parsers/ls_remote.rb +79 -0
- data/lib/git/remote.rb +7 -20
- data/lib/git/repository/branching.rb +183 -12
- data/lib/git/repository/committing.rb +64 -68
- data/lib/git/repository/configuring.rb +208 -13
- data/lib/git/repository/context_helpers.rb +264 -0
- data/lib/git/repository/factories.rb +682 -0
- data/lib/git/repository/inspecting.rb +99 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +63 -1
- data/lib/git/repository/object_operations.rb +133 -35
- data/lib/git/repository/path_resolver.rb +1 -1
- data/lib/git/repository/remote_operations.rb +166 -21
- data/lib/git/repository/staging.rb +187 -23
- data/lib/git/repository/stashing.rb +39 -3
- data/lib/git/repository/status_operations.rb +21 -0
- data/lib/git/repository.rb +68 -129
- data/lib/git/stash.rb +2 -9
- data/lib/git/stashes.rb +2 -7
- data/lib/git/status.rb +8 -17
- data/lib/git/version.rb +2 -2
- data/lib/git/worktree.rb +2 -15
- data/lib/git/worktrees.rb +2 -15
- data/lib/git.rb +180 -77
- data/redesign/3_architecture_implementation.md +148 -111
- data/redesign/Phase 4 - Step A.md +360 -0
- data/redesign/beta_release.md +107 -0
- data/redesign/c1c2_audit.md +566 -0
- data/redesign/c1c2_bucket6_lib_orphans.md +626 -0
- data/redesign/config_design.rb +501 -0
- metadata +19 -5
- data/lib/git/base.rb +0 -1204
- data/lib/git/lib.rb +0 -2855
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This is a forward looking document (in Ruby format) on the evolution of `git
|
|
4
|
+
# config` methods in Ruby Git. Here is how `git config` methods will change in
|
|
5
|
+
# v5.x and v6.x.
|
|
6
|
+
#
|
|
7
|
+
# In v5.x, `Git.config` and `Git.global_config` will continue to work as they do in
|
|
8
|
+
# v4.x but will be deprecated. New methods in the Git::Configuring module will be
|
|
9
|
+
# introduced in Git and Git::Repository to provide structured access to configuration
|
|
10
|
+
# entries. These will not be strict drop-in replacements for the existing deprecated
|
|
11
|
+
# methods.
|
|
12
|
+
#
|
|
13
|
+
# In v6.x, the deprecated methods will be removed.
|
|
14
|
+
|
|
15
|
+
# Top level Git module
|
|
16
|
+
module Git
|
|
17
|
+
# Represents a single Git configuration entry
|
|
18
|
+
#
|
|
19
|
+
# @example
|
|
20
|
+
# scope = 'local'
|
|
21
|
+
# origin = 'path/to/config'
|
|
22
|
+
# key = 'remote.origin.url'
|
|
23
|
+
# value = 'https://github.com/ruby-git/ruby-git'
|
|
24
|
+
# entry = Git::ConfigEntryInfo.new(scope:, origin:, key: , value:)
|
|
25
|
+
#
|
|
26
|
+
# @!attribute [r] scope
|
|
27
|
+
#
|
|
28
|
+
# The scope of the configuration entry
|
|
29
|
+
#
|
|
30
|
+
# May be one of "system", "global", "local", "worktree", "file", or "blob".
|
|
31
|
+
#
|
|
32
|
+
# @return [String]
|
|
33
|
+
#
|
|
34
|
+
# @!attribute [r] origin
|
|
35
|
+
#
|
|
36
|
+
# Where the configuration entry originates
|
|
37
|
+
#
|
|
38
|
+
# The origin is in the format: `<origin-type>:<actual-origin>`. It is never
|
|
39
|
+
# blank.
|
|
40
|
+
#
|
|
41
|
+
# ### `origin-type`
|
|
42
|
+
#
|
|
43
|
+
# This prefix explains the context of the configuration source. The four possible
|
|
44
|
+
# types are `file:`, `blob:`, `command line:`, and `standard input:`.
|
|
45
|
+
#
|
|
46
|
+
# ### `actual-origin`
|
|
47
|
+
#
|
|
48
|
+
# This provides the specific location for the configuration source. Only the
|
|
49
|
+
# `file:` and `blob:` origin types have an actual origin. For `command line:` and
|
|
50
|
+
# `standard input:`, Git drops this portion entirely and places the tab character
|
|
51
|
+
# immediately after the colon.
|
|
52
|
+
#
|
|
53
|
+
# #### Path Resolution
|
|
54
|
+
#
|
|
55
|
+
# When the origin type is a file, the actual origin can be formatted as either an
|
|
56
|
+
# absolute or relative path depending on how Git resolves it.
|
|
57
|
+
#
|
|
58
|
+
# - **Absolute Paths**: Git outputs the full system path for system-level configurations,
|
|
59
|
+
# global configurations, explicitly provided absolute paths, or absolute
|
|
60
|
+
# paths used in [include] directives.
|
|
61
|
+
# - **Relative Paths**: Git outputs a relative path for local repository configurations,
|
|
62
|
+
# explicitly provided relative paths, or relative paths used in [include]
|
|
63
|
+
# directives.
|
|
64
|
+
# - **Relative Anchors**: Local repository paths are relative to the repository
|
|
65
|
+
# root. Command-line relative paths are relative to your current working
|
|
66
|
+
# directory. Relative paths from an [include] directive are anchored to
|
|
67
|
+
# the parent configuration file that included them.
|
|
68
|
+
#
|
|
69
|
+
# @return [String]
|
|
70
|
+
#
|
|
71
|
+
# @!attribute [r] key
|
|
72
|
+
#
|
|
73
|
+
# The full key name of the configuration entry (e.g., remote.origin.url)
|
|
74
|
+
#
|
|
75
|
+
# @return [String]
|
|
76
|
+
#
|
|
77
|
+
# @!attribute [r] value
|
|
78
|
+
#
|
|
79
|
+
# The value of the configuration entry
|
|
80
|
+
#
|
|
81
|
+
# @return [String]
|
|
82
|
+
#
|
|
83
|
+
# @api public
|
|
84
|
+
#
|
|
85
|
+
ConfigEntryInfo = Data.define(:scope, :origin, :key, :value) do
|
|
86
|
+
# Everything up to the first dot in the {key}
|
|
87
|
+
#
|
|
88
|
+
# Returns an empty string if {key} contains no dot.
|
|
89
|
+
#
|
|
90
|
+
# @example
|
|
91
|
+
# entry.section # => 'remote'
|
|
92
|
+
#
|
|
93
|
+
# @return [String]
|
|
94
|
+
#
|
|
95
|
+
def section = first_dot ? key[0...first_dot] : ''
|
|
96
|
+
|
|
97
|
+
# Everything between the first and last dot in the {key}
|
|
98
|
+
#
|
|
99
|
+
# Returns an empty string if {key} has no subsection (zero or one dot).
|
|
100
|
+
#
|
|
101
|
+
# @example
|
|
102
|
+
# entry.subsection # => 'origin'
|
|
103
|
+
#
|
|
104
|
+
# @return [String]
|
|
105
|
+
#
|
|
106
|
+
def subsection = first_dot && first_dot != last_dot ? key[(first_dot + 1)...last_dot] : ''
|
|
107
|
+
|
|
108
|
+
# Everything after the last dot in the {key}
|
|
109
|
+
#
|
|
110
|
+
# Returns the full {key} if {key} contains no dot.
|
|
111
|
+
#
|
|
112
|
+
# @example
|
|
113
|
+
# entry.variable # => 'url'
|
|
114
|
+
#
|
|
115
|
+
# @return [String]
|
|
116
|
+
#
|
|
117
|
+
def variable = last_dot ? key[(last_dot + 1)..] : key
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def first_dot = key.index('.')
|
|
122
|
+
|
|
123
|
+
def last_dot = key.rindex('.')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
module Parsers
|
|
127
|
+
# Parser for `git config --get` and `git config --list` output
|
|
128
|
+
# when called with `--show-scope --show-origin --null`.
|
|
129
|
+
#
|
|
130
|
+
# @api private
|
|
131
|
+
#
|
|
132
|
+
module ConfigEntry
|
|
133
|
+
module_function
|
|
134
|
+
|
|
135
|
+
# Parse `git config --get --show-scope --show-origin --null` output.
|
|
136
|
+
#
|
|
137
|
+
# Output format (per entry): `scope\0origin\0value\0`
|
|
138
|
+
# The key name is not present in --get output; it must be supplied.
|
|
139
|
+
#
|
|
140
|
+
# @param key [String] the config key name that was queried
|
|
141
|
+
# @param output [String] raw stdout from the command
|
|
142
|
+
# @return [Git::ConfigEntryInfo, nil] the parsed entry, or nil if not found
|
|
143
|
+
#
|
|
144
|
+
def parse_get(key, output)
|
|
145
|
+
return nil if output.empty?
|
|
146
|
+
|
|
147
|
+
scope, origin, value = output.split("\0", -1)
|
|
148
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: origin, key: key, value: value)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Parse `git config --get-all --show-scope --show-origin --null` output.
|
|
152
|
+
#
|
|
153
|
+
# Output format (per entry): `scope\0origin\0value\0`
|
|
154
|
+
# The key name is not present in --get-all output; it must be supplied.
|
|
155
|
+
# Entries repeat back-to-back in the same string.
|
|
156
|
+
#
|
|
157
|
+
# @param key [String] the config key name that was queried
|
|
158
|
+
# @param output [String] raw stdout from the command
|
|
159
|
+
# @return [Array<Git::ConfigEntryInfo>] the parsed entries
|
|
160
|
+
#
|
|
161
|
+
def parse_get_all(key, output)
|
|
162
|
+
return [] if output.empty?
|
|
163
|
+
|
|
164
|
+
tokens = output.split("\0", -1)
|
|
165
|
+
tokens.pop if tokens.last && tokens.last.empty?
|
|
166
|
+
tokens.each_slice(3).map do |scope, origin, value|
|
|
167
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: origin, key: key, value: value)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Parse `git config --list --show-scope --show-origin --null` output.
|
|
172
|
+
#
|
|
173
|
+
# Also used for `--get-regexp` and `--get-urlmatch` output, which share
|
|
174
|
+
# the same format.
|
|
175
|
+
#
|
|
176
|
+
# Output format (per entry): `scope\0origin\0key\nvalue\0`
|
|
177
|
+
# Entries repeat back-to-back in the same string.
|
|
178
|
+
#
|
|
179
|
+
# @param output [String] raw stdout from the command
|
|
180
|
+
# @return [Array<Git::ConfigEntryInfo>] the parsed entries
|
|
181
|
+
#
|
|
182
|
+
def parse_list(output)
|
|
183
|
+
return [] if output.empty?
|
|
184
|
+
|
|
185
|
+
tokens = output.split("\0", -1)
|
|
186
|
+
tokens.pop if tokens.last && tokens.last.empty?
|
|
187
|
+
tokens.each_slice(3).map do |scope, origin, key_value|
|
|
188
|
+
key, value = key_value.split("\n", 2)
|
|
189
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: origin, key: key, value: value || '')
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Designed to be included in the Git module and the Git::Repository module
|
|
196
|
+
#
|
|
197
|
+
# The including/extending class must implement {#execution_context} and
|
|
198
|
+
# {#assert_valid_scope!}.
|
|
199
|
+
#
|
|
200
|
+
module Configuring # rubocop:disable Metrics/ModuleLength
|
|
201
|
+
# @!group Read Operations
|
|
202
|
+
|
|
203
|
+
CONFIG_GET_ALLOWED_OPTS = %i[global system local worktree file f blob includes no_includes type default].freeze
|
|
204
|
+
private_constant :CONFIG_GET_ALLOWED_OPTS
|
|
205
|
+
|
|
206
|
+
# @return [Git::ConfigEntryInfo, nil] nil if the key is not found
|
|
207
|
+
def config_get(name, value_regex = nil, **options)
|
|
208
|
+
Private.assert_valid_opts!(CONFIG_GET_ALLOWED_OPTS, **options)
|
|
209
|
+
assert_valid_scope!(**options)
|
|
210
|
+
options = options.merge(show_scope: true, show_origin: true, null: true)
|
|
211
|
+
cmd = Git::Commands::ConfigOptionSyntax::Get.new(execution_context)
|
|
212
|
+
output = cmd.call(name, value_regex, **options).stdout
|
|
213
|
+
Git::Parsers::ConfigEntry.parse_get(name, output)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
CONFIG_GET_ALL_ALLOWED_OPTS = %i[global system local worktree file f blob includes no_includes type].freeze
|
|
217
|
+
private_constant :CONFIG_GET_ALL_ALLOWED_OPTS
|
|
218
|
+
|
|
219
|
+
# @return [Array<Git::ConfigEntryInfo>]
|
|
220
|
+
def config_get_all(name, value_regex = nil, **options)
|
|
221
|
+
Private.assert_valid_opts!(CONFIG_GET_ALL_ALLOWED_OPTS, **options)
|
|
222
|
+
assert_valid_scope!(**options)
|
|
223
|
+
options = options.merge(show_scope: true, show_origin: true, null: true)
|
|
224
|
+
cmd = Git::Commands::ConfigOptionSyntax::GetAll.new(execution_context)
|
|
225
|
+
output = cmd.call(name, value_regex, **options).stdout
|
|
226
|
+
Git::Parsers::ConfigEntry.parse_get_all(name, output)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# `git config --get --type=color [--default=<default>]` is preferred over
|
|
230
|
+
# --get-color
|
|
231
|
+
#
|
|
232
|
+
# def config_get_color(name, default = nil, **)
|
|
233
|
+
# ...
|
|
234
|
+
# end
|
|
235
|
+
|
|
236
|
+
CONFIG_GET_COLORBOOL_ALLOWED_OPTS = %i[global system local worktree file f blob includes no_includes].freeze
|
|
237
|
+
private_constant :CONFIG_GET_COLORBOOL_ALLOWED_OPTS
|
|
238
|
+
|
|
239
|
+
# @return [String] always 'true' or 'false'
|
|
240
|
+
def config_get_colorbool(name, stdout_is_tty = nil, **)
|
|
241
|
+
Private.assert_valid_opts!(CONFIG_GET_COLORBOOL_ALLOWED_OPTS, **)
|
|
242
|
+
assert_valid_scope!(**)
|
|
243
|
+
cmd = Git::Commands::ConfigOptionSyntax::GetColorBool.new(execution_context)
|
|
244
|
+
cmd.call(name, stdout_is_tty, **).stdout.chomp
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
CONFIG_GET_REGEXP_ALLOWED_OPTS = %i[global system local worktree file f blob includes no_includes type].freeze
|
|
248
|
+
private_constant :CONFIG_GET_REGEXP_ALLOWED_OPTS
|
|
249
|
+
|
|
250
|
+
# @return [Array<Git::ConfigEntryInfo>]
|
|
251
|
+
def config_get_regexp(name_regex, value_regex = nil, **options)
|
|
252
|
+
Private.assert_valid_opts!(CONFIG_GET_REGEXP_ALLOWED_OPTS, **options)
|
|
253
|
+
assert_valid_scope!(**options)
|
|
254
|
+
options = options.merge(show_scope: true, show_origin: true, null: true)
|
|
255
|
+
cmd = Git::Commands::ConfigOptionSyntax::GetRegexp.new(execution_context)
|
|
256
|
+
output = cmd.call(name_regex, value_regex, **options).stdout
|
|
257
|
+
Git::Parsers::ConfigEntry.parse_list(output)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
CONFIG_GET_URLMATCH_ALLOWED_OPTS = %i[global system local worktree file f blob includes no_includes type].freeze
|
|
261
|
+
private_constant :CONFIG_GET_URLMATCH_ALLOWED_OPTS
|
|
262
|
+
|
|
263
|
+
# @return [Array<Git::ConfigEntryInfo>]
|
|
264
|
+
def config_get_urlmatch(name, url, **options)
|
|
265
|
+
Private.assert_valid_opts!(CONFIG_GET_URLMATCH_ALLOWED_OPTS, **options)
|
|
266
|
+
assert_valid_scope!(**options)
|
|
267
|
+
options = options.merge(show_scope: true, show_origin: true, null: true)
|
|
268
|
+
cmd = Git::Commands::ConfigOptionSyntax::GetUrlmatch.new(execution_context)
|
|
269
|
+
output = cmd.call(name, url, **options).stdout
|
|
270
|
+
Git::Parsers::ConfigEntry.parse_list(output)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
CONFIG_LIST_ALLOWED_OPTS = %i[global system local worktree file f blob includes no_includes type].freeze
|
|
274
|
+
private_constant :CONFIG_LIST_ALLOWED_OPTS
|
|
275
|
+
|
|
276
|
+
# @return [Array<Git::ConfigEntryInfo>]
|
|
277
|
+
def config_list(**options)
|
|
278
|
+
Private.assert_valid_opts!(CONFIG_LIST_ALLOWED_OPTS, **options)
|
|
279
|
+
assert_valid_scope!(**options)
|
|
280
|
+
options = options.merge(show_scope: true, show_origin: true, null: true)
|
|
281
|
+
cmd = Git::Commands::ConfigOptionSyntax::List.new(execution_context)
|
|
282
|
+
output = cmd.call(**options).stdout
|
|
283
|
+
Git::Parsers::ConfigEntry.parse_list(output)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# @!endgroup
|
|
287
|
+
|
|
288
|
+
# @!group Write Operations
|
|
289
|
+
|
|
290
|
+
CONFIG_ADD_ALLOWED_OPTS = %i[global system local worktree file f blob type].freeze
|
|
291
|
+
private_constant :CONFIG_ADD_ALLOWED_OPTS
|
|
292
|
+
|
|
293
|
+
# @return [void]
|
|
294
|
+
#
|
|
295
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
296
|
+
#
|
|
297
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
298
|
+
def config_add(name, value, **)
|
|
299
|
+
Private.assert_valid_opts!(CONFIG_ADD_ALLOWED_OPTS, **)
|
|
300
|
+
assert_valid_scope!(**)
|
|
301
|
+
cmd = Git::Commands::ConfigOptionSyntax::Add.new(execution_context)
|
|
302
|
+
cmd.call(name, value, **)
|
|
303
|
+
nil
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
CONFIG_REMOVE_SECTION_ALLOWED_OPTS = %i[global system local worktree file f blob].freeze
|
|
307
|
+
private_constant :CONFIG_REMOVE_SECTION_ALLOWED_OPTS
|
|
308
|
+
|
|
309
|
+
# @return [void]
|
|
310
|
+
#
|
|
311
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
312
|
+
#
|
|
313
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
314
|
+
def config_remove_section(name, **)
|
|
315
|
+
Private.assert_valid_opts!(CONFIG_REMOVE_SECTION_ALLOWED_OPTS, **)
|
|
316
|
+
assert_valid_scope!(**)
|
|
317
|
+
cmd = Git::Commands::ConfigOptionSyntax::RemoveSection.new(execution_context)
|
|
318
|
+
cmd.call(name, **)
|
|
319
|
+
nil
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
CONFIG_RENAME_SECTION_ALLOWED_OPTS = %i[global system local worktree file f blob].freeze
|
|
323
|
+
private_constant :CONFIG_RENAME_SECTION_ALLOWED_OPTS
|
|
324
|
+
|
|
325
|
+
# @return [void]
|
|
326
|
+
#
|
|
327
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
328
|
+
#
|
|
329
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
330
|
+
def config_rename_section(old_name, new_name, **)
|
|
331
|
+
Private.assert_valid_opts!(CONFIG_RENAME_SECTION_ALLOWED_OPTS, **)
|
|
332
|
+
assert_valid_scope!(**)
|
|
333
|
+
cmd = Git::Commands::ConfigOptionSyntax::RenameSection.new(execution_context)
|
|
334
|
+
cmd.call(old_name, new_name, **)
|
|
335
|
+
nil
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
CONFIG_REPLACE_ALL_ALLOWED_OPTS = %i[global system local worktree file f blob type].freeze
|
|
339
|
+
private_constant :CONFIG_REPLACE_ALL_ALLOWED_OPTS
|
|
340
|
+
|
|
341
|
+
# @return [void]
|
|
342
|
+
#
|
|
343
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
344
|
+
#
|
|
345
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
346
|
+
def config_replace_all(name, value, value_regex = nil, **)
|
|
347
|
+
Private.assert_valid_opts!(CONFIG_REPLACE_ALL_ALLOWED_OPTS, **)
|
|
348
|
+
assert_valid_scope!(**)
|
|
349
|
+
cmd = Git::Commands::ConfigOptionSyntax::ReplaceAll.new(execution_context)
|
|
350
|
+
cmd.call(name, value, value_regex, **)
|
|
351
|
+
nil
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
CONFIG_SET_ALLOWED_OPTS = %i[global system local worktree file f blob type].freeze
|
|
355
|
+
private_constant :CONFIG_SET_ALLOWED_OPTS
|
|
356
|
+
|
|
357
|
+
# @return [void]
|
|
358
|
+
#
|
|
359
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
360
|
+
#
|
|
361
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
362
|
+
def config_set(name, value, **)
|
|
363
|
+
Private.assert_valid_opts!(CONFIG_SET_ALLOWED_OPTS, **)
|
|
364
|
+
assert_valid_scope!(**)
|
|
365
|
+
cmd = Git::Commands::ConfigOptionSyntax::Set.new(execution_context)
|
|
366
|
+
cmd.call(name, value, **)
|
|
367
|
+
nil
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
CONFIG_UNSET_ALLOWED_OPTS = %i[global system local worktree file f blob].freeze
|
|
371
|
+
private_constant :CONFIG_UNSET_ALLOWED_OPTS
|
|
372
|
+
|
|
373
|
+
# @return [void]
|
|
374
|
+
#
|
|
375
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
376
|
+
#
|
|
377
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
378
|
+
def config_unset(name, value_regex = nil, **)
|
|
379
|
+
Private.assert_valid_opts!(CONFIG_UNSET_ALLOWED_OPTS, **)
|
|
380
|
+
assert_valid_scope!(**)
|
|
381
|
+
cmd = Git::Commands::ConfigOptionSyntax::Unset.new(execution_context)
|
|
382
|
+
cmd.call(name, value_regex, **)
|
|
383
|
+
nil
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
CONFIG_UNSET_ALL_ALLOWED_OPTS = %i[global system local worktree file f blob].freeze
|
|
387
|
+
private_constant :CONFIG_UNSET_ALL_ALLOWED_OPTS
|
|
388
|
+
|
|
389
|
+
# @return [void]
|
|
390
|
+
#
|
|
391
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
392
|
+
#
|
|
393
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
394
|
+
def config_unset_all(name, value_regex = nil, **)
|
|
395
|
+
Private.assert_valid_opts!(CONFIG_UNSET_ALL_ALLOWED_OPTS, **)
|
|
396
|
+
assert_valid_scope!(**)
|
|
397
|
+
cmd = Git::Commands::ConfigOptionSyntax::UnsetAll.new(execution_context)
|
|
398
|
+
cmd.call(name, value_regex, **)
|
|
399
|
+
nil
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# @!endgroup
|
|
403
|
+
|
|
404
|
+
private
|
|
405
|
+
|
|
406
|
+
# @abstract Including/extending class must implement execution_context
|
|
407
|
+
#
|
|
408
|
+
# @return [Git::ExecutionContext]
|
|
409
|
+
#
|
|
410
|
+
def execution_context
|
|
411
|
+
raise NotImplementedError
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# @abstract Including/extending class must implement assert_valid_scope!
|
|
415
|
+
#
|
|
416
|
+
# Called before every config operation to validate that the requested scope
|
|
417
|
+
# is appropriate for the context (e.g., repository-specific scopes such as
|
|
418
|
+
# `local` are not valid when called without a repository).
|
|
419
|
+
#
|
|
420
|
+
# @raise [ArgumentError] if the scope is not permitted in this context
|
|
421
|
+
#
|
|
422
|
+
# @return [void]
|
|
423
|
+
#
|
|
424
|
+
def assert_valid_scope!(**)
|
|
425
|
+
raise NotImplementedError
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# Internal helpers local to {Git::Configuring}
|
|
429
|
+
#
|
|
430
|
+
# @api private
|
|
431
|
+
#
|
|
432
|
+
module Private
|
|
433
|
+
module_function
|
|
434
|
+
|
|
435
|
+
# Validate that `options` contains only keys listed in `allowed`
|
|
436
|
+
#
|
|
437
|
+
# @example Reject an undocumented option
|
|
438
|
+
# Private.assert_valid_opts!(%i[all force], bogus: true)
|
|
439
|
+
# #=> raises ArgumentError: Unknown options: bogus
|
|
440
|
+
#
|
|
441
|
+
# @param allowed [Array<Symbol>] the keys permitted by the facade method
|
|
442
|
+
#
|
|
443
|
+
# @param options [Hash] the options hash provided by the caller
|
|
444
|
+
#
|
|
445
|
+
# @return [void]
|
|
446
|
+
#
|
|
447
|
+
# @raise [ArgumentError] when `options` contains any key not in `allowed`
|
|
448
|
+
#
|
|
449
|
+
def assert_valid_opts!(allowed, **options)
|
|
450
|
+
unknown = options.keys - allowed
|
|
451
|
+
return if unknown.empty?
|
|
452
|
+
|
|
453
|
+
raise ArgumentError, "Unknown options: #{unknown.join(', ')}"
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
private_constant :Private
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
REPOSITORY_SPECIFIC_SCOPES = %i[local worktree blob].freeze
|
|
460
|
+
private_constant :REPOSITORY_SPECIFIC_SCOPES
|
|
461
|
+
|
|
462
|
+
# Reopens Git::Repository to mix in config read/write operations.
|
|
463
|
+
#
|
|
464
|
+
# In the real implementation this `include` lives in
|
|
465
|
+
# `lib/git/repository/configuring.rb` and is picked up by the
|
|
466
|
+
# `Git::Repository` class definition in `lib/git/repository.rb`.
|
|
467
|
+
class Repository
|
|
468
|
+
# Mixes in config_get, config_list, config_set, etc.
|
|
469
|
+
include Git::Configuring
|
|
470
|
+
|
|
471
|
+
private
|
|
472
|
+
|
|
473
|
+
# @return [Git::ExecutionContext::Repository]
|
|
474
|
+
attr_reader :execution_context
|
|
475
|
+
|
|
476
|
+
# All scopes are permitted when called with a repository context.
|
|
477
|
+
def assert_valid_scope!(**)
|
|
478
|
+
# All scopes allowed
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# Enables calling Git.config_get('user.name')
|
|
483
|
+
extend Git::Configuring
|
|
484
|
+
|
|
485
|
+
# Returns a global execution context for non-repository config operations.
|
|
486
|
+
#
|
|
487
|
+
# Overrides the abstract {Git::Configuring#execution_context} for the
|
|
488
|
+
# module-level case.
|
|
489
|
+
#
|
|
490
|
+
# @return [Git::ExecutionContext::Global]
|
|
491
|
+
def self.execution_context
|
|
492
|
+
Git::ExecutionContext::Global.new
|
|
493
|
+
end
|
|
494
|
+
private_class_method :execution_context
|
|
495
|
+
|
|
496
|
+
def self.assert_valid_scope!(**options)
|
|
497
|
+
repo_scopes = options.keys.select { |k| options[k] && REPOSITORY_SPECIFIC_SCOPES.include?(k) }
|
|
498
|
+
raise ArgumentError, "scope #{repo_scopes.first} requires a repository" if repo_scopes.any?
|
|
499
|
+
end
|
|
500
|
+
private_class_method :assert_valid_scope!
|
|
501
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: git
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.0.0.beta.
|
|
4
|
+
version: 5.0.0.beta.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Chacon and others
|
|
@@ -343,6 +343,7 @@ files:
|
|
|
343
343
|
- ".commitlintrc.yml"
|
|
344
344
|
- ".github/copilot-instructions.md"
|
|
345
345
|
- ".github/issue_template.md"
|
|
346
|
+
- ".github/prompts/iteratively-address-copilot-reviews.prompt.md"
|
|
346
347
|
- ".github/pull_request_template.md"
|
|
347
348
|
- ".github/skills/breaking-change-analysis/SKILL.md"
|
|
348
349
|
- ".github/skills/ci-cd-troubleshooting/SKILL.md"
|
|
@@ -353,6 +354,7 @@ files:
|
|
|
353
354
|
- ".github/skills/dependency-management/SKILL.md"
|
|
354
355
|
- ".github/skills/development-workflow/SKILL.md"
|
|
355
356
|
- ".github/skills/extract-command-from-lib/SKILL.md"
|
|
357
|
+
- ".github/skills/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md"
|
|
356
358
|
- ".github/skills/extract-facade-from-base-lib/SKILL.md"
|
|
357
359
|
- ".github/skills/facade-implementation/REFERENCE.md"
|
|
358
360
|
- ".github/skills/facade-implementation/SKILL.md"
|
|
@@ -396,12 +398,12 @@ files:
|
|
|
396
398
|
- MAINTAINERS.md
|
|
397
399
|
- README.md
|
|
398
400
|
- Rakefile
|
|
401
|
+
- UPGRADING.md
|
|
399
402
|
- commitlint.test
|
|
400
403
|
- git.gemspec
|
|
401
404
|
- lib/git.rb
|
|
402
405
|
- lib/git/args_builder.rb
|
|
403
406
|
- lib/git/author.rb
|
|
404
|
-
- lib/git/base.rb
|
|
405
407
|
- lib/git/branch.rb
|
|
406
408
|
- lib/git/branch_delete_failure.rb
|
|
407
409
|
- lib/git/branch_delete_result.rb
|
|
@@ -562,6 +564,9 @@ files:
|
|
|
562
564
|
- lib/git/commands/worktree/unlock.rb
|
|
563
565
|
- lib/git/commands/write_tree.rb
|
|
564
566
|
- lib/git/config.rb
|
|
567
|
+
- lib/git/config_entry_info.rb
|
|
568
|
+
- lib/git/configuring.rb
|
|
569
|
+
- lib/git/deprecation.rb
|
|
565
570
|
- lib/git/detached_head_info.rb
|
|
566
571
|
- lib/git/diff.rb
|
|
567
572
|
- lib/git/diff_file_numstat_info.rb
|
|
@@ -581,14 +586,15 @@ files:
|
|
|
581
586
|
- lib/git/file_ref.rb
|
|
582
587
|
- lib/git/fsck_object.rb
|
|
583
588
|
- lib/git/fsck_result.rb
|
|
584
|
-
- lib/git/lib.rb
|
|
585
589
|
- lib/git/log.rb
|
|
586
590
|
- lib/git/object.rb
|
|
587
591
|
- lib/git/parsers/branch.rb
|
|
588
592
|
- lib/git/parsers/cat_file.rb
|
|
593
|
+
- lib/git/parsers/config_entry.rb
|
|
589
594
|
- lib/git/parsers/diff.rb
|
|
590
595
|
- lib/git/parsers/fsck.rb
|
|
591
596
|
- lib/git/parsers/grep.rb
|
|
597
|
+
- lib/git/parsers/ls_remote.rb
|
|
592
598
|
- lib/git/parsers/ls_tree.rb
|
|
593
599
|
- lib/git/parsers/stash.rb
|
|
594
600
|
- lib/git/parsers/tag.rb
|
|
@@ -597,9 +603,12 @@ files:
|
|
|
597
603
|
- lib/git/repository/branching.rb
|
|
598
604
|
- lib/git/repository/committing.rb
|
|
599
605
|
- lib/git/repository/configuring.rb
|
|
606
|
+
- lib/git/repository/context_helpers.rb
|
|
600
607
|
- lib/git/repository/diffing.rb
|
|
608
|
+
- lib/git/repository/factories.rb
|
|
601
609
|
- lib/git/repository/inspecting.rb
|
|
602
610
|
- lib/git/repository/logging.rb
|
|
611
|
+
- lib/git/repository/maintenance.rb
|
|
603
612
|
- lib/git/repository/merging.rb
|
|
604
613
|
- lib/git/repository/object_operations.rb
|
|
605
614
|
- lib/git/repository/path_resolver.rb
|
|
@@ -625,6 +634,11 @@ files:
|
|
|
625
634
|
- redesign/1_architecture_existing.md
|
|
626
635
|
- redesign/2_architecture_redesign.md
|
|
627
636
|
- redesign/3_architecture_implementation.md
|
|
637
|
+
- redesign/Phase 4 - Step A.md
|
|
638
|
+
- redesign/beta_release.md
|
|
639
|
+
- redesign/c1c2_audit.md
|
|
640
|
+
- redesign/c1c2_bucket6_lib_orphans.md
|
|
641
|
+
- redesign/config_design.rb
|
|
628
642
|
- redesign/index.md
|
|
629
643
|
- tasks/gem_tasks.rake
|
|
630
644
|
- tasks/npm_tasks.rake
|
|
@@ -639,8 +653,8 @@ licenses:
|
|
|
639
653
|
metadata:
|
|
640
654
|
homepage_uri: http://github.com/ruby-git/ruby-git
|
|
641
655
|
source_code_uri: http://github.com/ruby-git/ruby-git
|
|
642
|
-
changelog_uri: https://rubydoc.info/gems/git/5.0.0.beta.
|
|
643
|
-
documentation_uri: https://rubydoc.info/gems/git/5.0.0.beta.
|
|
656
|
+
changelog_uri: https://rubydoc.info/gems/git/5.0.0.beta.2/file/CHANGELOG.md
|
|
657
|
+
documentation_uri: https://rubydoc.info/gems/git/5.0.0.beta.2
|
|
644
658
|
rubygems_mfa_required: 'true'
|
|
645
659
|
rdoc_options: []
|
|
646
660
|
require_paths:
|