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
data/lib/git/diff.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Git
|
|
|
25
25
|
# @example
|
|
26
26
|
# diff = Git::Diff.new(base, 'HEAD~1', 'HEAD')
|
|
27
27
|
#
|
|
28
|
-
# @param base [Git::
|
|
28
|
+
# @param base [Git::Repository] the git repository
|
|
29
29
|
#
|
|
30
30
|
# @param from [String, nil] the starting commit ref, or `nil` to compare
|
|
31
31
|
# from the index
|
|
@@ -102,11 +102,7 @@ module Git
|
|
|
102
102
|
# @return [String] the raw output of `git diff`
|
|
103
103
|
#
|
|
104
104
|
def patch
|
|
105
|
-
|
|
106
|
-
@base.diff_full(@from, @to, path_limiter: @path)
|
|
107
|
-
else
|
|
108
|
-
@base.lib.diff_full(@from, @to, { path_limiter: @path })
|
|
109
|
-
end
|
|
105
|
+
@base.diff_full(@from, @to, path_limiter: @path)
|
|
110
106
|
end
|
|
111
107
|
alias to_s patch
|
|
112
108
|
|
|
@@ -287,7 +283,7 @@ module Git
|
|
|
287
283
|
# mode: '100644', src: 'abc123', dst: 'def456',
|
|
288
284
|
# type: 'modified', binary: false)
|
|
289
285
|
#
|
|
290
|
-
# @param base [Git::
|
|
286
|
+
# @param base [Git::Repository] the git repository
|
|
291
287
|
#
|
|
292
288
|
# @param hash [Hash] the parsed diff attributes
|
|
293
289
|
#
|
|
@@ -402,7 +398,7 @@ module Git
|
|
|
402
398
|
class FullDiffParser
|
|
403
399
|
# Creates a new FullDiffParser
|
|
404
400
|
#
|
|
405
|
-
# @param base [Git::
|
|
401
|
+
# @param base [Git::Repository] the git repository
|
|
406
402
|
#
|
|
407
403
|
# @param patch_text [String] the raw `git diff` output to parse
|
|
408
404
|
#
|
data/lib/git/diff_path_status.rb
CHANGED
|
@@ -61,26 +61,15 @@ module Git
|
|
|
61
61
|
|
|
62
62
|
# Lazily fetches and caches the path status from the git lib
|
|
63
63
|
#
|
|
64
|
-
# When constructed with a pre-fetched hash, returns it directly.
|
|
65
|
-
# When `@base` responds to `#diff_name_status` (e.g. {Git::Repository} or
|
|
66
|
-
# {Git::Base}, which defines it as an alias for `#diff_path_status`),
|
|
67
|
-
# delegates directly to that method. Otherwise falls back to the legacy
|
|
68
|
-
# `@base.lib.diff_path_status` call for duck-typed base objects that only
|
|
69
|
-
# expose path-status via their lib.
|
|
70
|
-
#
|
|
71
64
|
# @return [Hash{String => String}] a mapping of file paths to status codes
|
|
72
65
|
#
|
|
73
66
|
def fetch_path_status
|
|
74
|
-
@fetch_path_status ||=
|
|
75
|
-
@base.diff_name_status(@from, @to, path_limiter: @path_limiter).to_h
|
|
76
|
-
else
|
|
77
|
-
@base.lib.diff_path_status(@from, @to, { path_limiter: @path_limiter })
|
|
78
|
-
end
|
|
67
|
+
@fetch_path_status ||= @base.diff_name_status(@from, @to, path_limiter: @path_limiter).to_h
|
|
79
68
|
end
|
|
80
69
|
|
|
81
70
|
# Sets up legacy (base, from, to, path_limiter) instance state
|
|
82
71
|
#
|
|
83
|
-
# @param base [Git::
|
|
72
|
+
# @param base [Git::Repository] the git object
|
|
84
73
|
#
|
|
85
74
|
# @param from [String] the first commit or object to compare
|
|
86
75
|
#
|
data/lib/git/diff_stats.rb
CHANGED
|
@@ -88,17 +88,9 @@ module Git
|
|
|
88
88
|
|
|
89
89
|
# Lazily fetches and caches the stats from the git lib
|
|
90
90
|
#
|
|
91
|
-
# When `@base` implements `#diff_numstat`, delegates directly to that
|
|
92
|
-
# method. Otherwise falls back to the legacy `@base.lib.diff_stats` call
|
|
93
|
-
# so that existing `Git::Base`-backed callers continue to work unchanged.
|
|
94
|
-
#
|
|
95
91
|
# @return [Hash] the fetched stats hash
|
|
96
92
|
def fetch_stats
|
|
97
|
-
@fetch_stats ||=
|
|
98
|
-
@base.diff_numstat(@from, @to, path_limiter: @path_limiter)
|
|
99
|
-
else
|
|
100
|
-
@base.lib.diff_stats(@from, @to, { path_limiter: @path_limiter })
|
|
101
|
-
end
|
|
93
|
+
@fetch_stats ||= @base.diff_numstat(@from, @to, path_limiter: @path_limiter)
|
|
102
94
|
end
|
|
103
95
|
end
|
|
104
96
|
end
|
|
@@ -20,37 +20,12 @@ module Git
|
|
|
20
20
|
# @example Create a context targeting a specific binary
|
|
21
21
|
# context = Git::ExecutionContext::Global.new(binary_path: '/usr/local/bin/git2')
|
|
22
22
|
#
|
|
23
|
+
# @see Git::ExecutionContext#initialize for constructor parameters and
|
|
24
|
+
# their semantics
|
|
25
|
+
#
|
|
23
26
|
# @api private
|
|
24
27
|
#
|
|
25
28
|
class Global < ExecutionContext
|
|
26
|
-
# Creates a new global execution context
|
|
27
|
-
#
|
|
28
|
-
# @example Create with default settings
|
|
29
|
-
# Git::ExecutionContext::Global.new
|
|
30
|
-
#
|
|
31
|
-
# @example Create with an explicit binary path
|
|
32
|
-
# Git::ExecutionContext::Global.new(binary_path: '/usr/local/bin/git2')
|
|
33
|
-
#
|
|
34
|
-
# @param binary_path [String, :use_global_config] path to the git binary
|
|
35
|
-
#
|
|
36
|
-
# Give `:use_global_config` (the default) to use `Git::Base.config.binary_path`.
|
|
37
|
-
#
|
|
38
|
-
# Passing `nil` raises `ArgumentError` — there is no "unset the
|
|
39
|
-
# binary" semantic.
|
|
40
|
-
#
|
|
41
|
-
# @param git_ssh [String, nil, :use_global_config] the SSH wrapper path
|
|
42
|
-
#
|
|
43
|
-
# Give `nil` to unset `GIT_SSH`, or `:use_global_config` (default) to use `Git::Base.config.git_ssh`.
|
|
44
|
-
#
|
|
45
|
-
# @param logger [Logger, nil] the logger to use in the CommandLine layer
|
|
46
|
-
#
|
|
47
|
-
# Give `nil` to use a null logger (`Logger.new(nil)`).
|
|
48
|
-
#
|
|
49
|
-
# @raise [ArgumentError] if `binary_path` is `nil`
|
|
50
|
-
#
|
|
51
|
-
def initialize(binary_path: :use_global_config, git_ssh: :use_global_config, logger: nil)
|
|
52
|
-
super
|
|
53
|
-
end
|
|
54
29
|
end
|
|
55
30
|
end
|
|
56
31
|
end
|
|
@@ -13,15 +13,10 @@ module Git
|
|
|
13
13
|
#
|
|
14
14
|
# ### Construction
|
|
15
15
|
#
|
|
16
|
-
#
|
|
17
|
-
# {Git::Base} object or a hash:
|
|
16
|
+
# Use {.from_hash} to build from a configuration hash:
|
|
18
17
|
#
|
|
19
|
-
# context = Git::ExecutionContext::Repository.from_base(base)
|
|
20
18
|
# context = Git::ExecutionContext::Repository.from_hash(repository: '/repo/.git', ...)
|
|
21
19
|
#
|
|
22
|
-
# @example Build from a Git::Base object
|
|
23
|
-
# context = Git::ExecutionContext::Repository.from_base(git)
|
|
24
|
-
#
|
|
25
20
|
# @example Build from a configuration hash
|
|
26
21
|
# context = Git::ExecutionContext::Repository.from_hash(
|
|
27
22
|
# repository: '/path/to/.git',
|
|
@@ -31,31 +26,6 @@ module Git
|
|
|
31
26
|
# @api private
|
|
32
27
|
#
|
|
33
28
|
class Repository < ExecutionContext
|
|
34
|
-
# Creates a Repository context from a {Git::Base} instance
|
|
35
|
-
#
|
|
36
|
-
# @example Build from a base object
|
|
37
|
-
# git = Git.open('/path/to/repo')
|
|
38
|
-
# context = Git::ExecutionContext::Repository.from_base(git)
|
|
39
|
-
#
|
|
40
|
-
# @param base_object [Git::Base] the base Git object to derive context from
|
|
41
|
-
#
|
|
42
|
-
# @param logger [Logger, nil] logger forwarded to the CommandLine layer;
|
|
43
|
-
# `nil` uses a null logger (see {Git::ExecutionContext#initialize})
|
|
44
|
-
#
|
|
45
|
-
# @return [Git::ExecutionContext::Repository] the new repository context
|
|
46
|
-
#
|
|
47
|
-
def self.from_base(base_object, logger: nil)
|
|
48
|
-
new(
|
|
49
|
-
git_dir: base_object.repo.to_s,
|
|
50
|
-
git_index_file: base_object.index&.to_s,
|
|
51
|
-
git_work_dir: base_object.dir&.to_s,
|
|
52
|
-
base_object: base_object,
|
|
53
|
-
git_ssh: base_object.git_ssh,
|
|
54
|
-
binary_path: base_object.binary_path,
|
|
55
|
-
logger: logger
|
|
56
|
-
)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
29
|
# Creates a Repository context from a Hash
|
|
60
30
|
#
|
|
61
31
|
# Expected keys: `:repository`, `:working_directory`, `:index`, `:git_ssh`,
|
|
@@ -79,8 +49,8 @@ module Git
|
|
|
79
49
|
git_dir: base_hash[:repository],
|
|
80
50
|
git_index_file: base_hash[:index],
|
|
81
51
|
git_work_dir: base_hash[:working_directory],
|
|
82
|
-
git_ssh: base_hash.
|
|
83
|
-
binary_path: base_hash.
|
|
52
|
+
git_ssh: base_hash.fetch(:git_ssh, :use_global_config),
|
|
53
|
+
binary_path: base_hash.fetch(:binary_path, :use_global_config),
|
|
84
54
|
logger: logger
|
|
85
55
|
)
|
|
86
56
|
end
|
|
@@ -96,18 +66,18 @@ module Git
|
|
|
96
66
|
#
|
|
97
67
|
# @param git_index_file [String, nil] path to the index file
|
|
98
68
|
#
|
|
99
|
-
# @param base_object [Git::Base, nil] originating base object
|
|
100
|
-
#
|
|
101
69
|
# @param binary_path [String, :use_global_config] path to the git binary
|
|
102
70
|
#
|
|
103
|
-
# Give `:use_global_config` (the default) to use
|
|
71
|
+
# Give `:use_global_config` (the default) to use
|
|
72
|
+
# `Git::Config.instance.binary_path`.
|
|
104
73
|
#
|
|
105
74
|
# Passing `nil` raises `ArgumentError` — there is no "unset the
|
|
106
75
|
# binary" semantic.
|
|
107
76
|
#
|
|
108
77
|
# @param git_ssh [String, nil, :use_global_config] the SSH wrapper path
|
|
109
78
|
#
|
|
110
|
-
# Give `nil` to unset `GIT_SSH`, or `:use_global_config` (default)
|
|
79
|
+
# Give `nil` to unset `GIT_SSH`, or `:use_global_config` (default)
|
|
80
|
+
# to use `Git::Config.instance.git_ssh`.
|
|
111
81
|
#
|
|
112
82
|
# @param logger [Logger, nil] the logger to use in the CommandLine layer
|
|
113
83
|
#
|
|
@@ -119,7 +89,6 @@ module Git
|
|
|
119
89
|
git_dir:,
|
|
120
90
|
git_work_dir: nil,
|
|
121
91
|
git_index_file: nil,
|
|
122
|
-
base_object: nil,
|
|
123
92
|
binary_path: :use_global_config,
|
|
124
93
|
git_ssh: :use_global_config,
|
|
125
94
|
logger: nil
|
|
@@ -128,7 +97,6 @@ module Git
|
|
|
128
97
|
@git_dir = git_dir
|
|
129
98
|
@git_work_dir = git_work_dir
|
|
130
99
|
@git_index_file = git_index_file
|
|
131
|
-
@base_object = base_object
|
|
132
100
|
end
|
|
133
101
|
|
|
134
102
|
# @return [String, nil] path to the `.git` directory
|
|
@@ -140,8 +108,29 @@ module Git
|
|
|
140
108
|
# @return [String, nil] path to the index file
|
|
141
109
|
attr_reader :git_index_file
|
|
142
110
|
|
|
143
|
-
#
|
|
144
|
-
|
|
111
|
+
# Returns a new instance with the same configuration, applying `overrides`
|
|
112
|
+
#
|
|
113
|
+
# Uses raw stored values for `binary_path`, `git_ssh`, and `logger` so
|
|
114
|
+
# that `:use_global_config` sentinels are preserved across rebuilds and
|
|
115
|
+
# future changes to `Git.configure` continue to take effect.
|
|
116
|
+
#
|
|
117
|
+
# @param overrides [Hash] keyword arguments to override in the new instance
|
|
118
|
+
#
|
|
119
|
+
# @return [Git::ExecutionContext::Repository] the new context
|
|
120
|
+
#
|
|
121
|
+
# @api private
|
|
122
|
+
#
|
|
123
|
+
def dup_with(**overrides)
|
|
124
|
+
self.class.new(
|
|
125
|
+
git_dir: @git_dir,
|
|
126
|
+
git_work_dir: @git_work_dir,
|
|
127
|
+
git_index_file: @git_index_file,
|
|
128
|
+
binary_path: @binary_path,
|
|
129
|
+
git_ssh: @git_ssh,
|
|
130
|
+
logger: @logger,
|
|
131
|
+
**overrides
|
|
132
|
+
)
|
|
133
|
+
end
|
|
145
134
|
end
|
|
146
135
|
end
|
|
147
136
|
end
|
|
@@ -88,20 +88,22 @@ module Git
|
|
|
88
88
|
#
|
|
89
89
|
# @param binary_path [String, :use_global_config] path to the git binary
|
|
90
90
|
#
|
|
91
|
-
# Give `:use_global_config` (the default) to use `Git::
|
|
91
|
+
# Give `:use_global_config` (the default) to use `Git::Config.instance.binary_path`.
|
|
92
92
|
#
|
|
93
93
|
# Passing `nil` raises `ArgumentError` — there is no "unset the
|
|
94
94
|
# binary" semantic.
|
|
95
95
|
#
|
|
96
96
|
# @param git_ssh [String, nil, :use_global_config] the SSH wrapper path
|
|
97
97
|
#
|
|
98
|
-
# Give `nil` to unset `GIT_SSH`, or `:use_global_config` (default)
|
|
98
|
+
# Give `nil` to unset `GIT_SSH`, or `:use_global_config` (default)
|
|
99
|
+
# to use `Git::Config.instance.git_ssh`.
|
|
99
100
|
#
|
|
100
101
|
# @param logger [Logger, nil] the logger to use in the CommandLine layer
|
|
101
102
|
#
|
|
102
103
|
# Give `nil` to use a null logger (`Logger.new(nil)`).
|
|
103
104
|
#
|
|
104
|
-
# @raise [NotImplementedError] if called directly on {Git::ExecutionContext}
|
|
105
|
+
# @raise [NotImplementedError] if called directly on {Git::ExecutionContext}
|
|
106
|
+
# rather than a subclass
|
|
105
107
|
#
|
|
106
108
|
# @raise [ArgumentError] if `binary_path` is `nil`
|
|
107
109
|
#
|
|
@@ -156,11 +158,12 @@ module Git
|
|
|
156
158
|
|
|
157
159
|
# Returns the resolved git binary path for this context
|
|
158
160
|
#
|
|
159
|
-
# `:use_global_config` is resolved to `Git::
|
|
160
|
-
# command method is called, so runtime changes to
|
|
161
|
+
# `:use_global_config` is resolved to `Git::Config.instance.binary_path` each time a
|
|
162
|
+
# command method is called, so runtime changes to
|
|
163
|
+
# `Git.configure { |c| c.binary_path = ... }`
|
|
161
164
|
# are reflected per command invocation.
|
|
162
165
|
#
|
|
163
|
-
# @example With the default sentinel (resolves from Git::
|
|
166
|
+
# @example With the default sentinel (resolves from Git::Config.instance at call-time)
|
|
164
167
|
# context = Git::ExecutionContext::Global.new
|
|
165
168
|
# context.binary_path #=> "git"
|
|
166
169
|
#
|
|
@@ -171,19 +174,20 @@ module Git
|
|
|
171
174
|
# @return [String] the resolved git binary path
|
|
172
175
|
#
|
|
173
176
|
def binary_path
|
|
174
|
-
return Git::
|
|
177
|
+
return Git::Config.instance.binary_path if @binary_path == :use_global_config
|
|
175
178
|
|
|
176
179
|
@binary_path
|
|
177
180
|
end
|
|
178
181
|
|
|
179
182
|
# Returns the resolved `GIT_SSH` wrapper path for this context
|
|
180
183
|
#
|
|
181
|
-
# `:use_global_config` is resolved to `Git::
|
|
182
|
-
# command method is called, so runtime changes to
|
|
184
|
+
# `:use_global_config` is resolved to `Git::Config.instance.git_ssh` each time a
|
|
185
|
+
# command method is called, so runtime changes to
|
|
186
|
+
# `Git.configure { |c| c.git_ssh = ... }`
|
|
183
187
|
# are reflected per command invocation. `nil` means the variable will be
|
|
184
188
|
# explicitly unset.
|
|
185
189
|
#
|
|
186
|
-
# @example With the default sentinel (resolves from Git::
|
|
190
|
+
# @example With the default sentinel (resolves from Git::Config.instance at call-time)
|
|
187
191
|
# context = Git::ExecutionContext::Global.new
|
|
188
192
|
# context.git_ssh #=> nil
|
|
189
193
|
#
|
|
@@ -194,11 +198,23 @@ module Git
|
|
|
194
198
|
# @return [String, nil] the resolved `GIT_SSH` wrapper path, or `nil` to unset
|
|
195
199
|
#
|
|
196
200
|
def git_ssh
|
|
197
|
-
return Git::
|
|
201
|
+
return Git::Config.instance.git_ssh if @git_ssh == :use_global_config
|
|
198
202
|
|
|
199
203
|
@git_ssh
|
|
200
204
|
end
|
|
201
205
|
|
|
206
|
+
# Returns the logger used by this context
|
|
207
|
+
#
|
|
208
|
+
# @example
|
|
209
|
+
# context = Git::ExecutionContext::Repository.new(git_dir: '/repo/.git', logger: my_logger)
|
|
210
|
+
# context.logger #=> my_logger
|
|
211
|
+
#
|
|
212
|
+
# @return [Logger] the logger instance; never `nil`
|
|
213
|
+
#
|
|
214
|
+
# @api private
|
|
215
|
+
#
|
|
216
|
+
attr_reader :logger
|
|
217
|
+
|
|
202
218
|
# Runs a git command and returns the result
|
|
203
219
|
#
|
|
204
220
|
# By default, raises {Git::FailedError} if the command exits with a non-zero
|
|
@@ -393,25 +409,24 @@ module Git
|
|
|
393
409
|
|
|
394
410
|
# Returns the installed git version
|
|
395
411
|
#
|
|
396
|
-
# The result is memoized per instance.
|
|
412
|
+
# The result is memoized per instance. Accepts an optional timeout used
|
|
413
|
+
# only when the version has not yet been fetched for this context.
|
|
397
414
|
#
|
|
398
|
-
# @
|
|
399
|
-
#
|
|
400
|
-
#
|
|
415
|
+
# @param timeout [Numeric, nil] seconds to wait for `git version`; `nil`
|
|
416
|
+
# falls back to the global {Git::Config} timeout; `0` disables the timeout
|
|
417
|
+
# entirely (the command runs until it completes or the process is killed)
|
|
401
418
|
#
|
|
402
419
|
# @return [Git::Version] the installed git version
|
|
403
420
|
#
|
|
404
421
|
# @raise [Git::UnexpectedResultError] if the version string cannot be parsed
|
|
405
422
|
#
|
|
406
|
-
def git_version
|
|
423
|
+
def git_version(timeout: nil)
|
|
407
424
|
@git_version ||= begin
|
|
408
|
-
|
|
409
|
-
Git::Version.parse(
|
|
425
|
+
call_opts = timeout.nil? ? {} : { timeout: timeout }
|
|
426
|
+
Git::Version.parse(Git::Commands::Version.new(self).call(**call_opts).stdout)
|
|
410
427
|
end
|
|
411
428
|
end
|
|
412
429
|
|
|
413
|
-
private
|
|
414
|
-
|
|
415
430
|
# Returns a Hash of environment variable overrides for this context
|
|
416
431
|
#
|
|
417
432
|
# Builds the standard git environment from the public accessor methods
|
|
@@ -424,6 +439,8 @@ module Git
|
|
|
424
439
|
#
|
|
425
440
|
# @return [Hash<String, String|nil>] the merged environment variable overrides
|
|
426
441
|
#
|
|
442
|
+
# @api private
|
|
443
|
+
#
|
|
427
444
|
def env_overrides(**additional_overrides)
|
|
428
445
|
{
|
|
429
446
|
'GIT_DIR' => git_dir,
|
|
@@ -435,6 +452,8 @@ module Git
|
|
|
435
452
|
}.merge(additional_overrides)
|
|
436
453
|
end
|
|
437
454
|
|
|
455
|
+
private
|
|
456
|
+
|
|
438
457
|
# Returns the Array of git global option strings for this context
|
|
439
458
|
#
|
|
440
459
|
# Prepends `--git-dir` and `--work-tree` when the corresponding attributes
|
|
@@ -453,9 +472,9 @@ module Git
|
|
|
453
472
|
# Creates a {Git::CommandLine::Capturing} instance for the current invocation.
|
|
454
473
|
#
|
|
455
474
|
# A new instance is created per call so that {#binary_path} — resolved from
|
|
456
|
-
# `Git::
|
|
475
|
+
# `Git::Config.instance` when set to `:use_global_config` — and {#env_overrides}
|
|
457
476
|
# — including {#git_ssh} resolution for `:use_global_config` — reflect the
|
|
458
|
-
# state of
|
|
477
|
+
# state of {Git::Config.instance} at the time of each command invocation.
|
|
459
478
|
#
|
|
460
479
|
# @return [Git::CommandLine::Capturing] the capturing command line instance
|
|
461
480
|
#
|
|
@@ -466,9 +485,9 @@ module Git
|
|
|
466
485
|
# Creates a {Git::CommandLine::Streaming} instance for the current invocation.
|
|
467
486
|
#
|
|
468
487
|
# A new instance is created per call so that {#binary_path} — resolved from
|
|
469
|
-
# `Git::
|
|
488
|
+
# `Git::Config.instance` when set to `:use_global_config` — and {#env_overrides}
|
|
470
489
|
# — including {#git_ssh} resolution for `:use_global_config` — reflect the
|
|
471
|
-
# state of
|
|
490
|
+
# state of {Git::Config.instance} at the time of each command invocation.
|
|
472
491
|
#
|
|
473
492
|
# @return [Git::CommandLine::Streaming] the streaming command line instance
|
|
474
493
|
#
|
data/lib/git/log.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
|
# Builds and executes a `git log` query
|
|
7
5
|
#
|
|
@@ -44,7 +42,8 @@ module Git
|
|
|
44
42
|
# git = Git.open('.')
|
|
45
43
|
# Git::Log.new(git)
|
|
46
44
|
#
|
|
47
|
-
# @param base [Git::Repository
|
|
45
|
+
# @param base [Git::Repository] the git repository object
|
|
46
|
+
#
|
|
48
47
|
# @param max_count [Integer, Symbol, nil] the number of commits to return, or
|
|
49
48
|
# `:all` or `nil` to return all
|
|
50
49
|
#
|
|
@@ -159,15 +158,10 @@ module Git
|
|
|
159
158
|
self
|
|
160
159
|
end
|
|
161
160
|
|
|
162
|
-
# Returns the facade interface for log operations.
|
|
163
|
-
#
|
|
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
161
|
# @return [Git::Repository]
|
|
168
162
|
#
|
|
169
163
|
def log_repository
|
|
170
|
-
@base
|
|
164
|
+
@base
|
|
171
165
|
end
|
|
172
166
|
|
|
173
167
|
def run_log_if_dirty
|
data/lib/git/object.rb
CHANGED
|
@@ -4,7 +4,6 @@ require 'git/author'
|
|
|
4
4
|
require 'git/diff'
|
|
5
5
|
require 'git/errors'
|
|
6
6
|
require 'git/log'
|
|
7
|
-
require 'git/base'
|
|
8
7
|
|
|
9
8
|
module Git
|
|
10
9
|
# represents a git object
|
|
@@ -103,7 +102,7 @@ module Git
|
|
|
103
102
|
#
|
|
104
103
|
# @param file [String, nil] destination file path; a temp file is created if `nil`
|
|
105
104
|
#
|
|
106
|
-
# @param opts [Hash] archive options (see {Git::
|
|
105
|
+
# @param opts [Hash] archive options (see {Git::Repository#archive})
|
|
107
106
|
#
|
|
108
107
|
# @return [String] the path to the written archive file
|
|
109
108
|
#
|
|
@@ -126,15 +125,10 @@ module Git
|
|
|
126
125
|
|
|
127
126
|
private
|
|
128
127
|
|
|
129
|
-
# Returns the facade interface for git object queries.
|
|
130
|
-
#
|
|
131
|
-
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
132
|
-
# The `is_a?` guard will be removed when {Git::Base} is deleted in Phase 4.
|
|
133
|
-
#
|
|
134
128
|
# @return [Git::Repository]
|
|
135
129
|
#
|
|
136
130
|
def object_repository
|
|
137
|
-
@base
|
|
131
|
+
@base
|
|
138
132
|
end
|
|
139
133
|
end
|
|
140
134
|
|
|
@@ -315,19 +309,23 @@ module Git
|
|
|
315
309
|
attr_accessor :name
|
|
316
310
|
|
|
317
311
|
# @overload initialize(base, name)
|
|
318
|
-
#
|
|
319
|
-
# @param
|
|
312
|
+
#
|
|
313
|
+
# @param base [Git::Repository] the git repository
|
|
314
|
+
#
|
|
315
|
+
# @param name [String] the name of the tag
|
|
320
316
|
#
|
|
321
317
|
# @overload initialize(base, sha, name)
|
|
322
|
-
#
|
|
323
|
-
# @param
|
|
324
|
-
#
|
|
318
|
+
#
|
|
319
|
+
# @param base [Git::Repository] the git repository
|
|
320
|
+
#
|
|
321
|
+
# @param sha [String] the SHA of the tag object
|
|
322
|
+
#
|
|
323
|
+
# @param name [String] the name of the tag
|
|
325
324
|
#
|
|
326
325
|
def initialize(base, sha, name = nil)
|
|
327
326
|
if name.nil?
|
|
328
327
|
name = sha
|
|
329
|
-
|
|
330
|
-
sha = repo.tag_sha(name)
|
|
328
|
+
sha = base.tag_sha(name)
|
|
331
329
|
raise Git::UnexpectedResultError, "Tag '#{name}' does not exist." if sha == ''
|
|
332
330
|
end
|
|
333
331
|
|
|
@@ -394,15 +392,10 @@ module Git
|
|
|
394
392
|
Git::Object::Tag.new(base, objectish)
|
|
395
393
|
end
|
|
396
394
|
|
|
397
|
-
# Returns the facade interface for git object queries.
|
|
398
|
-
#
|
|
399
|
-
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
400
|
-
# The `is_a?` guard will be removed when {Git::Base} is deleted in Phase 4.
|
|
401
|
-
#
|
|
402
395
|
# @return [Git::Repository]
|
|
403
396
|
#
|
|
404
397
|
private_class_method def self.object_repository_for(base)
|
|
405
|
-
base
|
|
398
|
+
base
|
|
406
399
|
end
|
|
407
400
|
end
|
|
408
401
|
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/config_entry_info'
|
|
4
|
+
|
|
5
|
+
module Git
|
|
6
|
+
module Parsers
|
|
7
|
+
# Parser for `git config` output
|
|
8
|
+
#
|
|
9
|
+
# Each public method corresponds to a different `git config` sub-command
|
|
10
|
+
# variant and handles the specific output format that variant produces.
|
|
11
|
+
# Most variants are called with `--show-scope --show-origin --null`;
|
|
12
|
+
# `parse_urlmatch` handles the `--get-urlmatch` format where `--show-origin`
|
|
13
|
+
# is unsupported and therefore absent.
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
module ConfigEntry
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
# Parse `git config --get --show-scope --show-origin --null` output
|
|
21
|
+
#
|
|
22
|
+
# Output format (per entry): `scope\0origin\0value\0`
|
|
23
|
+
#
|
|
24
|
+
# The key name is absent from `--get` output and must be supplied by the
|
|
25
|
+
# caller.
|
|
26
|
+
#
|
|
27
|
+
# @param key [String] the config key name that was queried
|
|
28
|
+
#
|
|
29
|
+
# @param output [String] raw stdout from the command
|
|
30
|
+
#
|
|
31
|
+
# @return [Git::ConfigEntryInfo, nil] the parsed entry, or `nil` when not found
|
|
32
|
+
#
|
|
33
|
+
def parse_get(key, output)
|
|
34
|
+
return nil if output.empty?
|
|
35
|
+
|
|
36
|
+
scope, origin, value = output.split("\0", -1)
|
|
37
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: origin, key: key, value: value)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Parse `git config --get-all --show-scope --show-origin --null` output
|
|
41
|
+
#
|
|
42
|
+
# Output format (per entry): `scope\0origin\0value\0`
|
|
43
|
+
#
|
|
44
|
+
# The key name is absent from `--get-all` output and must be supplied by
|
|
45
|
+
# the caller. Multiple entries appear back-to-back in the same string.
|
|
46
|
+
#
|
|
47
|
+
# @param key [String] the config key name that was queried
|
|
48
|
+
#
|
|
49
|
+
# @param output [String] raw stdout from the command
|
|
50
|
+
#
|
|
51
|
+
# @return [Array<Git::ConfigEntryInfo>] the parsed entries
|
|
52
|
+
#
|
|
53
|
+
def parse_get_all(key, output)
|
|
54
|
+
return [] if output.empty?
|
|
55
|
+
|
|
56
|
+
tokens = output.split("\0", -1)
|
|
57
|
+
tokens.pop if tokens.last == ''
|
|
58
|
+
tokens.each_slice(3).map do |scope, origin, value|
|
|
59
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: origin, key: key, value: value)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Parse `git config --list --show-scope --show-origin --null` output
|
|
64
|
+
#
|
|
65
|
+
# Also handles `--get-regexp` output, which shares the same format.
|
|
66
|
+
#
|
|
67
|
+
# Output format (per entry): `scope\0origin\0key\nvalue\0`
|
|
68
|
+
#
|
|
69
|
+
# Multiple entries appear back-to-back in the same string.
|
|
70
|
+
#
|
|
71
|
+
# @param output [String] raw stdout from the command
|
|
72
|
+
#
|
|
73
|
+
# @return [Array<Git::ConfigEntryInfo>] the parsed entries
|
|
74
|
+
#
|
|
75
|
+
def parse_list(output)
|
|
76
|
+
return [] if output.empty?
|
|
77
|
+
|
|
78
|
+
tokens = output.split("\0", -1)
|
|
79
|
+
tokens.pop if tokens.last == ''
|
|
80
|
+
tokens.each_slice(3).map do |scope, origin, key_value|
|
|
81
|
+
key, value = key_value.split("\n", 2)
|
|
82
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: origin, key: key, value: value || '')
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Parse `git config --get-urlmatch --show-scope --null` output
|
|
87
|
+
#
|
|
88
|
+
# Handles the two-field-per-entry format produced by `--get-urlmatch` when
|
|
89
|
+
# `--show-scope` is used but `--show-origin` is not (git does not support
|
|
90
|
+
# `--show-origin` with `--get-urlmatch`).
|
|
91
|
+
#
|
|
92
|
+
# Output format (per entry): `scope\0key\nvalue\0`
|
|
93
|
+
#
|
|
94
|
+
# @param output [String] raw stdout from the command
|
|
95
|
+
#
|
|
96
|
+
# @return [Array<Git::ConfigEntryInfo>] the parsed entries; `origin` is `nil` for each
|
|
97
|
+
#
|
|
98
|
+
def parse_urlmatch(output)
|
|
99
|
+
return [] if output.empty?
|
|
100
|
+
|
|
101
|
+
tokens = output.split("\0", -1)
|
|
102
|
+
tokens.pop if tokens.last == ''
|
|
103
|
+
tokens.each_slice(2).map do |scope, key_value|
|
|
104
|
+
key, value = key_value.split("\n", 2)
|
|
105
|
+
Git::ConfigEntryInfo.new(scope: scope, origin: nil, key: key, value: value || '')
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|