git 5.0.0.beta.1 → 5.0.0.beta.3
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 +90 -22
- 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/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 +288 -128
- data/lib/git/stash.rb +2 -9
- data/lib/git/stashes.rb +2 -7
- data/lib/git/status.rb +12 -23
- 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 +182 -77
- data/redesign/3_architecture_implementation.md +170 -112
- data/redesign/Phase 4 - Step A.md +366 -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 -6
- data/lib/git/base.rb +0 -1204
- data/lib/git/lib.rb +0 -2855
- data/lib/git/repository/configuring.rb +0 -156
data/lib/git/repository.rb
CHANGED
|
@@ -3,17 +3,21 @@
|
|
|
3
3
|
require 'find'
|
|
4
4
|
require 'pathname'
|
|
5
5
|
|
|
6
|
+
require 'git/configuring'
|
|
7
|
+
require 'git/deprecation'
|
|
6
8
|
require 'git/execution_context/repository'
|
|
7
9
|
require 'git/repository/branching'
|
|
10
|
+
require 'git/repository/context_helpers'
|
|
8
11
|
require 'git/repository/committing'
|
|
9
|
-
require 'git/repository/configuring'
|
|
10
12
|
require 'git/repository/diffing'
|
|
13
|
+
require 'git/repository/factories'
|
|
11
14
|
require 'git/repository/inspecting'
|
|
12
15
|
require 'git/repository/logging'
|
|
16
|
+
require 'git/repository/maintenance'
|
|
13
17
|
require 'git/repository/merging'
|
|
14
18
|
require 'git/repository/object_operations'
|
|
15
|
-
require 'git/repository/path_resolver'
|
|
16
19
|
require 'git/repository/remote_operations'
|
|
20
|
+
require 'git/repository/shared_private'
|
|
17
21
|
require 'git/repository/staging'
|
|
18
22
|
require 'git/repository/stashing'
|
|
19
23
|
require 'git/repository/status_operations'
|
|
@@ -44,13 +48,17 @@ module Git
|
|
|
44
48
|
#
|
|
45
49
|
# @api public
|
|
46
50
|
#
|
|
47
|
-
class Repository
|
|
51
|
+
class Repository # rubocop:disable Metrics/ClassLength
|
|
52
|
+
extend Git::Repository::Factories
|
|
53
|
+
|
|
54
|
+
include Git::Configuring
|
|
48
55
|
include Git::Repository::Branching
|
|
56
|
+
include Git::Repository::ContextHelpers
|
|
49
57
|
include Git::Repository::Committing
|
|
50
|
-
include Git::Repository::Configuring
|
|
51
58
|
include Git::Repository::Diffing
|
|
52
59
|
include Git::Repository::Inspecting
|
|
53
60
|
include Git::Repository::Logging
|
|
61
|
+
include Git::Repository::Maintenance
|
|
54
62
|
include Git::Repository::Merging
|
|
55
63
|
include Git::Repository::ObjectOperations
|
|
56
64
|
include Git::Repository::RemoteOperations
|
|
@@ -59,133 +67,22 @@ module Git
|
|
|
59
67
|
include Git::Repository::StatusOperations
|
|
60
68
|
include Git::Repository::WorktreeOperations
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# The new repository factories are additive scaffolding introduced by the
|
|
65
|
-
# architectural redesign. The top-level {Git.open} entry point still returns a
|
|
66
|
-
# {Git::Base} object; this method exists so future work can route construction
|
|
67
|
-
# through {Git::Repository} without changing the public entry points.
|
|
68
|
-
#
|
|
69
|
-
# Note: this method opens working copies only. To open a bare repository, use
|
|
70
|
-
# {Git::Repository.bare}.
|
|
71
|
-
#
|
|
72
|
-
# @example Open the working copy in the current directory
|
|
73
|
-
# repository = Git::Repository.open('.')
|
|
74
|
-
#
|
|
75
|
-
# @param working_dir [String] the path to the root of the working copy
|
|
76
|
-
#
|
|
77
|
-
# May be any path inside the working tree when `:repository` is not given.
|
|
78
|
-
#
|
|
79
|
-
# @param options [Hash] options that control how the repository is located
|
|
80
|
-
#
|
|
81
|
-
# @option options [String] :repository a non-standard path to the `.git`
|
|
82
|
-
# directory
|
|
83
|
-
#
|
|
84
|
-
# When given, `working_dir` is used as-is (the working tree root is not
|
|
85
|
-
# auto-detected).
|
|
86
|
-
#
|
|
87
|
-
# @option options [String] :index a non-standard path to the index file
|
|
88
|
-
#
|
|
89
|
-
# @option options [Logger] :log a logger forwarded to the command layer
|
|
90
|
-
#
|
|
91
|
-
# @option options [String, nil, :use_global_config] :git_ssh path to a custom SSH executable;
|
|
92
|
-
# pass `:use_global_config` (the default) to use `Git::Base.config.git_ssh`
|
|
93
|
-
#
|
|
94
|
-
# @option options [String, :use_global_config] :binary_path path to the git binary;
|
|
95
|
-
# pass `:use_global_config` (the default) to use `Git::Base.config.binary_path`
|
|
96
|
-
#
|
|
97
|
-
# @return [Git::Repository] a repository bound to the resolved paths
|
|
98
|
-
#
|
|
99
|
-
# @raise [ArgumentError] if `working_dir` is not a directory or is not inside
|
|
100
|
-
# a git working tree
|
|
101
|
-
#
|
|
102
|
-
def self.open(working_dir, options = {})
|
|
103
|
-
raise ArgumentError, "'#{working_dir}' is not a directory" unless Dir.exist?(working_dir)
|
|
104
|
-
|
|
105
|
-
working_dir = resolve_open_working_dir(working_dir, options) unless options[:repository]
|
|
70
|
+
CONFIG_SET_ALLOWED_OPTS = %i[file].freeze
|
|
71
|
+
private_constant :CONFIG_SET_ALLOWED_OPTS
|
|
106
72
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
repository: options[:repository],
|
|
110
|
-
index: options[:index]
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
from_paths(options, paths)
|
|
114
|
-
end
|
|
73
|
+
CONFIG_READ_ALLOWED_OPTS = %i[file].freeze
|
|
74
|
+
private_constant :CONFIG_READ_ALLOWED_OPTS
|
|
115
75
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
# {Git::Base} object; this method exists so future work can route construction
|
|
121
|
-
# through {Git::Repository} without changing the public entry points.
|
|
122
|
-
#
|
|
123
|
-
# @example Open a bare repository
|
|
124
|
-
# repository = Git::Repository.bare('/path/to/repo.git')
|
|
125
|
-
#
|
|
126
|
-
# @param git_dir [String] the path to the bare repository directory
|
|
127
|
-
#
|
|
128
|
-
# @param options [Hash] options forwarded to the constructed repository
|
|
129
|
-
#
|
|
130
|
-
# @option options [Logger] :log a logger forwarded to the command layer
|
|
131
|
-
#
|
|
132
|
-
# @option options [String, nil, :use_global_config] :git_ssh path to a custom SSH executable;
|
|
133
|
-
# pass `:use_global_config` (the default) to use `Git::Base.config.git_ssh`
|
|
134
|
-
#
|
|
135
|
-
# @option options [String, :use_global_config] :binary_path path to the git binary;
|
|
136
|
-
# pass `:use_global_config` (the default) to use `Git::Base.config.binary_path`
|
|
137
|
-
#
|
|
138
|
-
# @return [Git::Repository] a repository bound to the bare repository directory
|
|
139
|
-
#
|
|
140
|
-
def self.bare(git_dir, options = {})
|
|
141
|
-
paths = PathResolver.resolve_paths(repository: git_dir, bare: true)
|
|
142
|
-
|
|
143
|
-
from_paths(options, paths)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Resolve the worktree root to use as the working directory for `.open`
|
|
147
|
-
#
|
|
148
|
-
# Delegates to {PathResolver.root_of_worktree}, forwarding `:binary_path`
|
|
149
|
-
# and `:git_ssh` from `options`.
|
|
150
|
-
#
|
|
151
|
-
# @param working_dir [String] a path inside the working tree
|
|
152
|
-
#
|
|
153
|
-
# @param options [Hash] the caller-supplied options hash from `.open`
|
|
154
|
-
#
|
|
155
|
-
# @return [String] the absolute path to the root of the working tree
|
|
156
|
-
#
|
|
157
|
-
# @raise [ArgumentError] if `working_dir` is not inside a git working tree
|
|
158
|
-
#
|
|
159
|
-
# @api private
|
|
160
|
-
#
|
|
161
|
-
def self.resolve_open_working_dir(working_dir, options)
|
|
162
|
-
PathResolver.root_of_worktree(
|
|
163
|
-
working_dir,
|
|
164
|
-
binary_path: options.fetch(:binary_path, :use_global_config),
|
|
165
|
-
git_ssh: options.fetch(:git_ssh, :use_global_config)
|
|
166
|
-
)
|
|
167
|
-
end
|
|
168
|
-
private_class_method :resolve_open_working_dir
|
|
76
|
+
CONFIG_DEPRECATION_WARNING =
|
|
77
|
+
'Git::Repository#config is deprecated and will be removed in v6.0.0. ' \
|
|
78
|
+
'Use config_get(name), config_set(name, value), or config_list instead.'
|
|
79
|
+
private_constant :CONFIG_DEPRECATION_WARNING
|
|
169
80
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
# @param paths [Hash{Symbol => (String, nil)}] the resolved
|
|
176
|
-
# `:working_directory`, `:repository`, and `:index` paths
|
|
177
|
-
#
|
|
178
|
-
# @return [Git::Repository] the constructed repository
|
|
179
|
-
#
|
|
180
|
-
# @api private
|
|
181
|
-
#
|
|
182
|
-
def self.from_paths(options, paths)
|
|
183
|
-
execution_context = Git::ExecutionContext::Repository.from_hash(
|
|
184
|
-
options.merge(paths), logger: options[:log]
|
|
185
|
-
)
|
|
186
|
-
new(execution_context: execution_context)
|
|
187
|
-
end
|
|
188
|
-
private_class_method :from_paths
|
|
81
|
+
GLOBAL_CONFIG_DEPRECATION_WARNING =
|
|
82
|
+
'Git::Repository#global_config is deprecated and will be removed in v6.0.0. ' \
|
|
83
|
+
'Use config_get(name, global: true), config_set(name, value, global: true), ' \
|
|
84
|
+
'or config_list(global: true) instead.'
|
|
85
|
+
private_constant :GLOBAL_CONFIG_DEPRECATION_WARNING
|
|
189
86
|
|
|
190
87
|
# @return [Git::ExecutionContext::Repository] the execution context used to run
|
|
191
88
|
# git commands for this repository
|
|
@@ -239,6 +136,202 @@ module Git
|
|
|
239
136
|
index_file && Pathname.new(index_file)
|
|
240
137
|
end
|
|
241
138
|
|
|
139
|
+
# Returns `self` after emitting a deprecation warning.
|
|
140
|
+
#
|
|
141
|
+
# Legacy callers that used `git.lib.some_method` can migrate to calling the
|
|
142
|
+
# facade method directly on the repository object. This shim will be removed
|
|
143
|
+
# in v6.0.0.
|
|
144
|
+
#
|
|
145
|
+
# @return [self]
|
|
146
|
+
#
|
|
147
|
+
# @api private
|
|
148
|
+
#
|
|
149
|
+
def lib
|
|
150
|
+
Git::Deprecation.warn(
|
|
151
|
+
'Git::Repository#lib is deprecated and will be removed in v6.0.0. ' \
|
|
152
|
+
'Use the repository object directly.'
|
|
153
|
+
)
|
|
154
|
+
self
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# @return [String, nil] the git directory path
|
|
158
|
+
#
|
|
159
|
+
# @api private
|
|
160
|
+
def git_dir = execution_context.git_dir
|
|
161
|
+
|
|
162
|
+
# @return [String, nil] the working directory path
|
|
163
|
+
#
|
|
164
|
+
# @api private
|
|
165
|
+
def git_work_dir = execution_context.git_work_dir
|
|
166
|
+
|
|
167
|
+
# @return [String, nil] the index file path
|
|
168
|
+
#
|
|
169
|
+
# @api private
|
|
170
|
+
def git_index_file = execution_context.git_index_file
|
|
171
|
+
|
|
172
|
+
# @return [Git::Version] the installed git version
|
|
173
|
+
#
|
|
174
|
+
# @api private
|
|
175
|
+
def git_version(timeout: nil) = execution_context.git_version(timeout: timeout)
|
|
176
|
+
|
|
177
|
+
# @return [String, nil] the SSH wrapper path
|
|
178
|
+
#
|
|
179
|
+
# @api private
|
|
180
|
+
def git_ssh = execution_context.git_ssh
|
|
181
|
+
|
|
182
|
+
# @return [String, :use_global_config] the path to the git binary
|
|
183
|
+
#
|
|
184
|
+
# @api private
|
|
185
|
+
def binary_path = execution_context.binary_path
|
|
186
|
+
|
|
187
|
+
# Read or write a git configuration entry
|
|
188
|
+
#
|
|
189
|
+
# Dispatches to one of three modes depending on the arguments supplied:
|
|
190
|
+
#
|
|
191
|
+
# * **List** — `config()` returns all visible config entries as a `Hash`.
|
|
192
|
+
# * **Get** — `config(name)` returns the value for a single key as a `String`.
|
|
193
|
+
# * **Set** — `config(name, value)` writes a value and returns the raw
|
|
194
|
+
# command result.
|
|
195
|
+
#
|
|
196
|
+
# @overload config(options = {})
|
|
197
|
+
#
|
|
198
|
+
# @example List all config entries
|
|
199
|
+
# repo.config #=> { "user.name" => "Alice", "core.bare" => "false" }
|
|
200
|
+
#
|
|
201
|
+
# @example List all entries from a custom config file
|
|
202
|
+
# repo.config(file: '/path/to/.gitconfig')
|
|
203
|
+
# #=> { "user.name" => "Alice", "core.bare" => "false" }
|
|
204
|
+
#
|
|
205
|
+
# @param options [Hash] options for the list operation
|
|
206
|
+
#
|
|
207
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
208
|
+
# to read from instead of the default resolution chain
|
|
209
|
+
#
|
|
210
|
+
# @return [Hash{String => String}] all visible config entries, keyed by
|
|
211
|
+
# their full dotted key names (e.g. `"user.name"`)
|
|
212
|
+
#
|
|
213
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
214
|
+
#
|
|
215
|
+
# @overload config(name, options = {})
|
|
216
|
+
#
|
|
217
|
+
# @example Read the committer name from config
|
|
218
|
+
# repo.config('user.name') #=> "Alice"
|
|
219
|
+
#
|
|
220
|
+
# @example Read a value from a custom config file
|
|
221
|
+
# repo.config('user.name', file: '/path/to/.gitconfig') #=> "Alice"
|
|
222
|
+
#
|
|
223
|
+
# @param name [String] the dotted config key to look up (e.g.
|
|
224
|
+
# `"user.name"`)
|
|
225
|
+
#
|
|
226
|
+
# @param options [Hash] options for the get operation
|
|
227
|
+
#
|
|
228
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
229
|
+
# to read from instead of the default resolution chain
|
|
230
|
+
#
|
|
231
|
+
# @return [String] the value of the config entry
|
|
232
|
+
#
|
|
233
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
234
|
+
#
|
|
235
|
+
# @overload config(name, value, options = {})
|
|
236
|
+
#
|
|
237
|
+
# @example Set the committer name in local config
|
|
238
|
+
# repo.config('user.name', 'Alice')
|
|
239
|
+
#
|
|
240
|
+
# @example Write a value to a custom config file
|
|
241
|
+
# repo.config('user.name', 'Alice', file: '/path/to/custom/config')
|
|
242
|
+
#
|
|
243
|
+
# @param name [String] the dotted config key to write (e.g.
|
|
244
|
+
# `"user.name"`)
|
|
245
|
+
#
|
|
246
|
+
# @param value [#to_s] the value to assign; must not be `nil` (a `nil`
|
|
247
|
+
# value is treated as "no value" and routes to the get overload).
|
|
248
|
+
# Must not be a `Hash` (a Hash is treated as the `options` argument;
|
|
249
|
+
# call `value.to_s` explicitly before passing if a stringified Hash
|
|
250
|
+
# is genuinely needed). Any other non-nil object is converted to a
|
|
251
|
+
# String via `#to_s` before being passed to git
|
|
252
|
+
#
|
|
253
|
+
# @param options [Hash] options for the set operation
|
|
254
|
+
#
|
|
255
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
256
|
+
# to write to instead of the repository's default `.git/config`
|
|
257
|
+
#
|
|
258
|
+
# @return [Git::CommandLineResult] the raw result of
|
|
259
|
+
# `git config <name> <value>`
|
|
260
|
+
#
|
|
261
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
262
|
+
#
|
|
263
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
264
|
+
#
|
|
265
|
+
def config(name = nil, value = nil, options = {})
|
|
266
|
+
Git::Deprecation.warn(CONFIG_DEPRECATION_WARNING)
|
|
267
|
+
name, value, options = deprecated_normalize_config_args(name, value, options)
|
|
268
|
+
|
|
269
|
+
if !name.nil? && !value.nil?
|
|
270
|
+
deprecated_config_set(name, value, **options)
|
|
271
|
+
elsif name
|
|
272
|
+
deprecated_config_get(name, **options)
|
|
273
|
+
else
|
|
274
|
+
deprecated_config_list(**options)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Read or write a global git configuration entry
|
|
279
|
+
#
|
|
280
|
+
# Dispatches to one of three modes depending on the arguments supplied,
|
|
281
|
+
# targeting the git global config scope (`git config --global`):
|
|
282
|
+
#
|
|
283
|
+
# * **List** — `global_config()` returns all global config entries as a `Hash`.
|
|
284
|
+
# * **Get** — `global_config(name)` returns the value for a single key as a `String`.
|
|
285
|
+
# * **Set** — `global_config(name, value)` writes a value and returns the raw
|
|
286
|
+
# command result.
|
|
287
|
+
#
|
|
288
|
+
# @overload global_config
|
|
289
|
+
#
|
|
290
|
+
# @example List all global config entries
|
|
291
|
+
# repo.global_config #=> { "user.name" => "Alice", "core.autocrlf" => "false" }
|
|
292
|
+
#
|
|
293
|
+
# @return [Hash{String => String}] all global config entries, keyed by their
|
|
294
|
+
# full dotted key names (e.g. `"user.name"`)
|
|
295
|
+
#
|
|
296
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
297
|
+
#
|
|
298
|
+
# @overload global_config(name)
|
|
299
|
+
#
|
|
300
|
+
# @example Read the global committer name
|
|
301
|
+
# repo.global_config('user.name') #=> "Alice"
|
|
302
|
+
#
|
|
303
|
+
# @param name [String] the dotted config key to look up (e.g. `"user.name"`)
|
|
304
|
+
#
|
|
305
|
+
# @return [String] the value of the global config entry
|
|
306
|
+
#
|
|
307
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
308
|
+
#
|
|
309
|
+
# @overload global_config(name, value)
|
|
310
|
+
#
|
|
311
|
+
# @example Set the global committer name
|
|
312
|
+
# repo.global_config('user.name', 'Alice')
|
|
313
|
+
#
|
|
314
|
+
# @param name [String] the dotted config key to write (e.g. `"user.name"`)
|
|
315
|
+
#
|
|
316
|
+
# @param value [#to_s] the value to assign; any object is accepted and
|
|
317
|
+
# converted to a String via `#to_s` before being passed to git
|
|
318
|
+
#
|
|
319
|
+
# @return [Git::CommandLineResult] the raw result of
|
|
320
|
+
# `git config --global <name> <value>`
|
|
321
|
+
#
|
|
322
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
323
|
+
#
|
|
324
|
+
def global_config(name = nil, value = nil)
|
|
325
|
+
Git::Deprecation.warn(GLOBAL_CONFIG_DEPRECATION_WARNING)
|
|
326
|
+
if !name.nil? && !value.nil?
|
|
327
|
+
deprecated_global_config_set(name, value)
|
|
328
|
+
elsif !name.nil?
|
|
329
|
+
deprecated_global_config_get(name)
|
|
330
|
+
else
|
|
331
|
+
deprecated_global_config_list
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
242
335
|
# Returns the size of the repository directory in bytes
|
|
243
336
|
#
|
|
244
337
|
# Sums the sizes of every regular file under the repository (`.git`)
|
|
@@ -265,5 +358,72 @@ module Git
|
|
|
265
358
|
end
|
|
266
359
|
total
|
|
267
360
|
end
|
|
361
|
+
|
|
362
|
+
private
|
|
363
|
+
|
|
364
|
+
def deprecated_normalize_config_args(name, value, options)
|
|
365
|
+
if name.is_a?(Hash)
|
|
366
|
+
raise ArgumentError, 'unexpected positional arguments after options hash' if !value.nil? || !options.empty?
|
|
367
|
+
|
|
368
|
+
[nil, nil, name]
|
|
369
|
+
elsif value.is_a?(Hash)
|
|
370
|
+
raise ArgumentError, 'unexpected third argument when second argument is options hash' unless options.empty?
|
|
371
|
+
|
|
372
|
+
[name, nil, value]
|
|
373
|
+
else
|
|
374
|
+
[name, value, options]
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def deprecated_config_set(name, value, **)
|
|
379
|
+
SharedPrivate.assert_valid_opts!(CONFIG_SET_ALLOWED_OPTS, **)
|
|
380
|
+
Git::Commands::ConfigOptionSyntax::Set.new(@execution_context).call(name, value, **)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def deprecated_config_get(name, **options)
|
|
384
|
+
SharedPrivate.assert_valid_opts!(CONFIG_READ_ALLOWED_OPTS, **options)
|
|
385
|
+
opts = options[:file] ? { file: options[:file] } : {}
|
|
386
|
+
result = Git::Commands::ConfigOptionSyntax::Get.new(@execution_context).call(name, **opts)
|
|
387
|
+
raise Git::FailedError, result if result.status.exitstatus != 0
|
|
388
|
+
|
|
389
|
+
result.stdout
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def deprecated_config_list(**options)
|
|
393
|
+
SharedPrivate.assert_valid_opts!(CONFIG_READ_ALLOWED_OPTS, **options)
|
|
394
|
+
opts = options[:file] ? { file: options[:file] } : {}
|
|
395
|
+
lines = Git::Commands::ConfigOptionSyntax::List.new(@execution_context).call(**opts).stdout.split("\n")
|
|
396
|
+
lines.each_with_object({}) do |line, hsh|
|
|
397
|
+
key, value = line.split('=', 2)
|
|
398
|
+
hsh[key] = value || ''
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def deprecated_global_config_get(name)
|
|
403
|
+
result = Git::Commands::ConfigOptionSyntax::Get.new(@execution_context).call(name, global: true)
|
|
404
|
+
raise Git::FailedError, result if result.status.exitstatus != 0
|
|
405
|
+
|
|
406
|
+
result.stdout
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def deprecated_global_config_list
|
|
410
|
+
lines = Git::Commands::ConfigOptionSyntax::List.new(@execution_context).call(global: true).stdout.split("\n")
|
|
411
|
+
lines.each_with_object({}) do |line, hsh|
|
|
412
|
+
key, value = line.split('=', 2)
|
|
413
|
+
hsh[key] = value || ''
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def deprecated_global_config_set(name, value)
|
|
418
|
+
Git::Commands::ConfigOptionSyntax::Set.new(@execution_context).call(name, value, global: true)
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
# All git config scopes are valid in a repository context
|
|
422
|
+
#
|
|
423
|
+
# @return [void]
|
|
424
|
+
#
|
|
425
|
+
def assert_valid_scope!(**)
|
|
426
|
+
nil
|
|
427
|
+
end
|
|
268
428
|
end
|
|
269
429
|
end
|
data/lib/git/stash.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'git/base'
|
|
4
|
-
|
|
5
3
|
module Git
|
|
6
4
|
# Represents a single stash entry in a Git repository
|
|
7
5
|
#
|
|
@@ -18,7 +16,7 @@ module Git
|
|
|
18
16
|
# When `existing` is `false` (the default), immediately calls {#save} to push
|
|
19
17
|
# the current working-directory state onto the stash stack.
|
|
20
18
|
#
|
|
21
|
-
# @param base [Git::Repository
|
|
19
|
+
# @param base [Git::Repository] the git repository
|
|
22
20
|
#
|
|
23
21
|
# @param message [String] the stash message
|
|
24
22
|
#
|
|
@@ -93,15 +91,10 @@ module Git
|
|
|
93
91
|
|
|
94
92
|
private
|
|
95
93
|
|
|
96
|
-
# Returns the facade interface for stash operations
|
|
97
|
-
#
|
|
98
|
-
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
99
|
-
# The `is_a?` guard will be removed when {Git::Base} is deleted in Phase 4.
|
|
100
|
-
#
|
|
101
94
|
# @return [Git::Repository]
|
|
102
95
|
#
|
|
103
96
|
def stash_repository
|
|
104
|
-
@base
|
|
97
|
+
@base
|
|
105
98
|
end
|
|
106
99
|
end
|
|
107
100
|
end
|
data/lib/git/stashes.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'git/base'
|
|
4
|
-
|
|
5
3
|
module Git
|
|
6
4
|
# Collection of stash entries for a Git repository
|
|
7
5
|
#
|
|
@@ -21,7 +19,7 @@ module Git
|
|
|
21
19
|
#
|
|
22
20
|
# Loads all existing stash entries from the repository at construction time.
|
|
23
21
|
#
|
|
24
|
-
# @param base [Git::Repository
|
|
22
|
+
# @param base [Git::Repository] the git repository
|
|
25
23
|
#
|
|
26
24
|
# @return [void]
|
|
27
25
|
#
|
|
@@ -161,13 +159,10 @@ module Git
|
|
|
161
159
|
|
|
162
160
|
# Returns the facade interface for stash operations
|
|
163
161
|
#
|
|
164
|
-
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
165
|
-
# The `is_a?` guard will be removed when {Git::Base} is deleted in Phase 4.
|
|
166
|
-
#
|
|
167
162
|
# @return [Git::Repository]
|
|
168
163
|
#
|
|
169
164
|
def stash_repository
|
|
170
|
-
@base
|
|
165
|
+
@base
|
|
171
166
|
end
|
|
172
167
|
end
|
|
173
168
|
end
|
data/lib/git/status.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Git
|
|
|
14
14
|
|
|
15
15
|
# Create a new Status for the given repository
|
|
16
16
|
#
|
|
17
|
-
# @param base [Git::
|
|
17
|
+
# @param base [Git::Repository] the git object backing this status
|
|
18
18
|
#
|
|
19
19
|
def initialize(base)
|
|
20
20
|
@base = base
|
|
@@ -172,17 +172,15 @@ module Git
|
|
|
172
172
|
|
|
173
173
|
# Return `true` when git is configured to ignore filename case
|
|
174
174
|
#
|
|
175
|
-
# Reads `core.ignoreCase`
|
|
176
|
-
# the config value is absent
|
|
175
|
+
# Reads `core.ignoreCase` with {Git::Repository#config_get}. Returns `false`
|
|
176
|
+
# when the config value is absent.
|
|
177
177
|
#
|
|
178
178
|
# @return [Boolean] `true` when `core.ignoreCase` is `"true"`
|
|
179
179
|
#
|
|
180
180
|
def ignore_case?
|
|
181
|
-
return @
|
|
181
|
+
return @ignore_case if defined?(@ignore_case)
|
|
182
182
|
|
|
183
|
-
@
|
|
184
|
-
rescue Git::FailedError
|
|
185
|
-
@_ignore_case = false
|
|
183
|
+
@ignore_case = (@base.config_get('core.ignoreCase')&.value == 'true')
|
|
186
184
|
end
|
|
187
185
|
end
|
|
188
186
|
end
|
|
@@ -239,7 +237,7 @@ module Git
|
|
|
239
237
|
|
|
240
238
|
# Initialize a new StatusFile with the given git object and data hash
|
|
241
239
|
#
|
|
242
|
-
# @param base [Git::
|
|
240
|
+
# @param base [Git::Repository] the git object
|
|
243
241
|
#
|
|
244
242
|
# @param hash [Hash] raw status data for this file
|
|
245
243
|
#
|
|
@@ -281,18 +279,10 @@ module Git
|
|
|
281
279
|
class StatusFileFactory
|
|
282
280
|
# Create a new factory backed by the given git object
|
|
283
281
|
#
|
|
284
|
-
#
|
|
285
|
-
# directly), it is used as the data provider. When `base` is a
|
|
286
|
-
# {Git::Base} (the legacy path), `base.lib` is used instead.
|
|
287
|
-
#
|
|
288
|
-
# @param base [Git::Base, Git::Repository] the git object used as the
|
|
289
|
-
# status data provider
|
|
282
|
+
# @param base [Git::Repository] the git object used as the status data provider
|
|
290
283
|
#
|
|
291
284
|
def initialize(base)
|
|
292
285
|
@base = base
|
|
293
|
-
# When base is Git::Repository (which exposes #diff_index directly),
|
|
294
|
-
# use it as the data provider. Otherwise use base.lib (legacy path).
|
|
295
|
-
@provider = base.respond_to?(:diff_index) ? base : base.lib
|
|
296
286
|
end
|
|
297
287
|
|
|
298
288
|
# Gather all status data and build a hash of file paths to StatusFile objects
|
|
@@ -314,7 +304,7 @@ module Git
|
|
|
314
304
|
# @return [Hash{String => Hash}] raw per-file status data keyed by path
|
|
315
305
|
#
|
|
316
306
|
def fetch_all_files_data
|
|
317
|
-
files = @
|
|
307
|
+
files = @base.ls_files # Start with files tracked in the index.
|
|
318
308
|
merge_untracked_files(files)
|
|
319
309
|
merge_modified_files(files)
|
|
320
310
|
merge_head_diffs(files)
|
|
@@ -328,7 +318,7 @@ module Git
|
|
|
328
318
|
# @return [void]
|
|
329
319
|
#
|
|
330
320
|
def merge_untracked_files(files)
|
|
331
|
-
@
|
|
321
|
+
@base.untracked_files.each do |file|
|
|
332
322
|
files[file] = { path: file, untracked: true }
|
|
333
323
|
end
|
|
334
324
|
end
|
|
@@ -341,7 +331,7 @@ module Git
|
|
|
341
331
|
#
|
|
342
332
|
def merge_modified_files(files)
|
|
343
333
|
# Merge changes between the index and the working directory.
|
|
344
|
-
@
|
|
334
|
+
@base.diff_files.each do |path, data|
|
|
345
335
|
(files[path] ||= {}).merge!(data)
|
|
346
336
|
end
|
|
347
337
|
end
|
|
@@ -353,12 +343,11 @@ module Git
|
|
|
353
343
|
# @return [void]
|
|
354
344
|
#
|
|
355
345
|
def merge_head_diffs(files)
|
|
356
|
-
|
|
357
|
-
is_empty = @provider.respond_to?(:no_commits?) ? @provider.no_commits? : @provider.empty?
|
|
346
|
+
is_empty = @base.no_commits?
|
|
358
347
|
return if is_empty
|
|
359
348
|
|
|
360
349
|
# Merge changes between HEAD and the index.
|
|
361
|
-
@
|
|
350
|
+
@base.diff_index('HEAD').each do |path, data|
|
|
362
351
|
(files[path] ||= {}).merge!(data)
|
|
363
352
|
end
|
|
364
353
|
end
|
data/lib/git/version.rb
CHANGED
|
@@ -4,7 +4,7 @@ module Git
|
|
|
4
4
|
# The current gem version
|
|
5
5
|
#
|
|
6
6
|
# @return [String] the current gem version
|
|
7
|
-
VERSION = '5.0.0.beta.
|
|
7
|
+
VERSION = '5.0.0.beta.3'
|
|
8
8
|
|
|
9
9
|
# Represents a git version with major, minor, and patch components
|
|
10
10
|
#
|
|
@@ -100,7 +100,7 @@ module Git
|
|
|
100
100
|
# Return the version as an array of integers
|
|
101
101
|
#
|
|
102
102
|
# Useful when legacy code expects the array shape returned by the
|
|
103
|
-
# deprecated
|
|
103
|
+
# deprecated `Git::Lib#current_command_version` method.
|
|
104
104
|
#
|
|
105
105
|
# @return [Array<Integer>] [major, minor, patch]
|
|
106
106
|
#
|
data/lib/git/worktree.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'git/base'
|
|
4
|
-
|
|
5
3
|
module Git
|
|
6
4
|
# A worktree in a Git repository
|
|
7
5
|
#
|
|
@@ -9,11 +7,6 @@ module Git
|
|
|
9
7
|
# {Git::Repository::WorktreeOperations#worktree} or populated by
|
|
10
8
|
# {Git::Worktrees}.
|
|
11
9
|
#
|
|
12
|
-
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy form)
|
|
13
|
-
# as the `base` argument. The `is_a?(Git::Base)` guard routes git operations
|
|
14
|
-
# through the facade repository and will be removed when {Git::Base} is
|
|
15
|
-
# deleted in Phase 4.
|
|
16
|
-
#
|
|
17
10
|
# @example Add and remove a linked worktree
|
|
18
11
|
# worktree = repo.worktree('/path/to/new-worktree')
|
|
19
12
|
# worktree.add
|
|
@@ -37,7 +30,7 @@ module Git
|
|
|
37
30
|
|
|
38
31
|
# Creates a new Worktree object
|
|
39
32
|
#
|
|
40
|
-
# @param base [Git::
|
|
33
|
+
# @param base [Git::Repository] the repository that owns this
|
|
41
34
|
# worktree
|
|
42
35
|
#
|
|
43
36
|
# @param dir [String] filesystem path of the worktree
|
|
@@ -137,18 +130,12 @@ module Git
|
|
|
137
130
|
|
|
138
131
|
private
|
|
139
132
|
|
|
140
|
-
# Resolves the {Git::Repository} for worktree operations
|
|
141
|
-
#
|
|
142
|
-
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
143
|
-
# The `is_a?(Git::Base)` guard will be removed when {Git::Base} is deleted
|
|
144
|
-
# in Phase 4.
|
|
145
|
-
#
|
|
146
133
|
# @return [Git::Repository] the repository used for worktree operations
|
|
147
134
|
#
|
|
148
135
|
# @api private
|
|
149
136
|
#
|
|
150
137
|
def worktree_repository
|
|
151
|
-
@base
|
|
138
|
+
@base
|
|
152
139
|
end
|
|
153
140
|
end
|
|
154
141
|
end
|