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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/copilot-instructions.md +6 -0
  3. data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +188 -0
  4. data/.github/skills/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +22 -0
  5. data/.github/skills/extract-facade-from-base-lib/SKILL.md +28 -14
  6. data/.github/skills/facade-implementation/SKILL.md +14 -0
  7. data/.github/skills/facade-test-conventions/SKILL.md +14 -0
  8. data/.rubocop.yml +5 -0
  9. data/README.md +51 -11
  10. data/UPGRADING.md +141 -0
  11. data/git.gemspec +5 -0
  12. data/lib/git/branch.rb +7 -18
  13. data/lib/git/branches.rb +2 -10
  14. data/lib/git/command_line/base.rb +10 -0
  15. data/lib/git/command_line/capturing.rb +5 -3
  16. data/lib/git/command_line/streaming.rb +5 -3
  17. data/lib/git/command_line.rb +3 -3
  18. data/lib/git/commands/base.rb +7 -6
  19. data/lib/git/commands/cat_file/batch.rb +6 -1
  20. data/lib/git/commands/cat_file/raw.rb +7 -1
  21. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +5 -0
  22. data/lib/git/commands/show_ref/exclude_existing.rb +1 -1
  23. data/lib/git/commands/update_ref/batch.rb +1 -1
  24. data/lib/git/commands/version.rb +5 -0
  25. data/lib/git/commands.rb +5 -7
  26. data/lib/git/config.rb +17 -0
  27. data/lib/git/config_entry_info.rb +106 -0
  28. data/lib/git/configuring.rb +665 -0
  29. data/lib/git/deprecation.rb +9 -0
  30. data/lib/git/diff.rb +4 -8
  31. data/lib/git/diff_path_status.rb +2 -13
  32. data/lib/git/diff_stats.rb +1 -9
  33. data/lib/git/execution_context/global.rb +3 -28
  34. data/lib/git/execution_context/repository.rb +30 -41
  35. data/lib/git/execution_context.rb +43 -24
  36. data/lib/git/log.rb +3 -9
  37. data/lib/git/object.rb +14 -21
  38. data/lib/git/parsers/config_entry.rb +110 -0
  39. data/lib/git/parsers/ls_remote.rb +79 -0
  40. data/lib/git/remote.rb +7 -20
  41. data/lib/git/repository/branching.rb +183 -12
  42. data/lib/git/repository/committing.rb +64 -68
  43. data/lib/git/repository/configuring.rb +208 -13
  44. data/lib/git/repository/context_helpers.rb +264 -0
  45. data/lib/git/repository/factories.rb +682 -0
  46. data/lib/git/repository/inspecting.rb +99 -0
  47. data/lib/git/repository/maintenance.rb +65 -0
  48. data/lib/git/repository/merging.rb +63 -1
  49. data/lib/git/repository/object_operations.rb +133 -35
  50. data/lib/git/repository/path_resolver.rb +1 -1
  51. data/lib/git/repository/remote_operations.rb +166 -21
  52. data/lib/git/repository/staging.rb +187 -23
  53. data/lib/git/repository/stashing.rb +39 -3
  54. data/lib/git/repository/status_operations.rb +21 -0
  55. data/lib/git/repository.rb +68 -129
  56. data/lib/git/stash.rb +2 -9
  57. data/lib/git/stashes.rb +2 -7
  58. data/lib/git/status.rb +8 -17
  59. data/lib/git/version.rb +2 -2
  60. data/lib/git/worktree.rb +2 -15
  61. data/lib/git/worktrees.rb +2 -15
  62. data/lib/git.rb +180 -77
  63. data/redesign/3_architecture_implementation.md +148 -111
  64. data/redesign/Phase 4 - Step A.md +360 -0
  65. data/redesign/beta_release.md +107 -0
  66. data/redesign/c1c2_audit.md +566 -0
  67. data/redesign/c1c2_bucket6_lib_orphans.md +626 -0
  68. data/redesign/config_design.rb +501 -0
  69. metadata +19 -5
  70. data/lib/git/base.rb +0 -1204
  71. 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.1
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.1/file/CHANGELOG.md
643
- documentation_uri: https://rubydoc.info/gems/git/5.0.0.beta.1
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: