git 5.0.0.beta.5 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +520 -0
- data/README.md +53 -475
- data/UPGRADING.md +26 -0
- data/lib/git/branch.rb +5 -1
- data/lib/git/branch_info.rb +135 -76
- data/lib/git/branches.rb +1 -1
- data/lib/git/log.rb +12 -6
- data/lib/git/object.rb +5 -2
- data/lib/git/parsers/branch.rb +62 -64
- data/lib/git/parsers/remote.rb +162 -0
- data/lib/git/remote.rb +1 -22
- data/lib/git/remote_info.rb +146 -0
- data/lib/git/repository/branching.rb +57 -22
- data/lib/git/repository/committing.rb +25 -6
- data/lib/git/repository/context_helpers.rb +1 -1
- data/lib/git/repository/diffing.rb +2 -1
- data/lib/git/repository/factories.rb +10 -3
- data/lib/git/repository/merging.rb +5 -5
- data/lib/git/repository/remote_operations.rb +64 -8
- data/lib/git/repository/staging.rb +13 -4
- data/lib/git/repository/stashing.rb +1 -1
- data/lib/git/repository/status_operations.rb +1 -1
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +8 -5
- data/redesign/branch_parse_refactor_plan.md +163 -0
- data/redesign/info_object_migration_plan.md +126 -0
- data/redesign/integration_test_analysis.md +521 -0
- data/redesign/remote_refactor_plan.md +164 -0
- metadata +10 -4
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/config_entry_info'
|
|
4
|
+
require 'git/remote_info'
|
|
5
|
+
|
|
6
|
+
module Git
|
|
7
|
+
module Parsers
|
|
8
|
+
# Parser that builds {Git::RemoteInfo} objects from git config entries
|
|
9
|
+
#
|
|
10
|
+
# Accepts `Array<Git::ConfigEntryInfo>` as returned by
|
|
11
|
+
# {Git::Configuring#config_list} and groups entries by remote name,
|
|
12
|
+
# collecting multi-value fields and coercing boolean values.
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
module Remote
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
# Parse an array of config entries into an array of RemoteInfo objects
|
|
20
|
+
#
|
|
21
|
+
# Groups entries whose key matches `remote.<name>.<variable>` by remote
|
|
22
|
+
# name and builds one {Git::RemoteInfo} per unique remote name.
|
|
23
|
+
#
|
|
24
|
+
# Non-remote config entries (keys that do not start with `remote.`) are
|
|
25
|
+
# silently ignored.
|
|
26
|
+
#
|
|
27
|
+
# @param config_entries [Array<Git::ConfigEntryInfo>] all config entries
|
|
28
|
+
# to inspect; may contain non-remote entries
|
|
29
|
+
#
|
|
30
|
+
# @return [Array<Git::RemoteInfo>] one entry per unique remote name, in
|
|
31
|
+
# the order the first entry for each name appeared in `config_entries`
|
|
32
|
+
#
|
|
33
|
+
# @raise [ArgumentError] if a boolean config field carries an unrecognized
|
|
34
|
+
# value (mirrors git's own fatal-error behavior)
|
|
35
|
+
#
|
|
36
|
+
def parse_list(config_entries)
|
|
37
|
+
group_by_remote(config_entries).map { |name, pairs| build_remote_info(name, pairs) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Group config entries by remote name, collecting variable/value pairs
|
|
41
|
+
#
|
|
42
|
+
# @param config_entries [Array<Git::ConfigEntryInfo>]
|
|
43
|
+
#
|
|
44
|
+
# @return [Hash{String => Array}] remote name to variable/value pairs
|
|
45
|
+
#
|
|
46
|
+
# @api private
|
|
47
|
+
#
|
|
48
|
+
def group_by_remote(config_entries)
|
|
49
|
+
config_entries.each_with_object({}) do |entry, groups|
|
|
50
|
+
next unless entry.section == 'remote' && !entry.subsection.empty?
|
|
51
|
+
|
|
52
|
+
remote_name = entry.subsection
|
|
53
|
+
variable = entry.variable.downcase
|
|
54
|
+
groups[remote_name] ||= []
|
|
55
|
+
groups[remote_name] << [variable, entry.value]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Config variable names that hold arrays of strings
|
|
60
|
+
ARRAY_VARIABLES = %w[url pushurl fetch push].freeze
|
|
61
|
+
private_constant :ARRAY_VARIABLES
|
|
62
|
+
|
|
63
|
+
# Config variable names that hold boolean values
|
|
64
|
+
BOOLEAN_VARIABLES = %w[mirror skipdefaultupdate prune prunetags promisor].freeze
|
|
65
|
+
private_constant :BOOLEAN_VARIABLES
|
|
66
|
+
|
|
67
|
+
# Map from git config variable name to RemoteInfo field name (symbol)
|
|
68
|
+
#
|
|
69
|
+
# All keys are lowercase because `git config --list` unconditionally
|
|
70
|
+
# lowercases section names and variable names (subsection names are
|
|
71
|
+
# case-preserved, but are never used as lookup keys here).
|
|
72
|
+
VARIABLE_TO_FIELD = {
|
|
73
|
+
'url' => :url,
|
|
74
|
+
'pushurl' => :push_url,
|
|
75
|
+
'fetch' => :fetch,
|
|
76
|
+
'push' => :push,
|
|
77
|
+
'mirror' => :mirror,
|
|
78
|
+
'skipdefaultupdate' => :skip_default_update,
|
|
79
|
+
'tagopt' => :tag_opt,
|
|
80
|
+
'prune' => :prune,
|
|
81
|
+
'prunetags' => :prune_tags,
|
|
82
|
+
'receivepack' => :receivepack,
|
|
83
|
+
'uploadpack' => :uploadpack,
|
|
84
|
+
'promisor' => :promisor,
|
|
85
|
+
'partialclonefilter' => :partial_clone_filter,
|
|
86
|
+
'vcs' => :vcs
|
|
87
|
+
}.freeze
|
|
88
|
+
private_constant :VARIABLE_TO_FIELD
|
|
89
|
+
|
|
90
|
+
# True string values per git's boolean rules
|
|
91
|
+
BOOL_TRUE_VALUES = %w[true yes on 1].freeze
|
|
92
|
+
private_constant :BOOL_TRUE_VALUES
|
|
93
|
+
|
|
94
|
+
# False string values per git's boolean rules
|
|
95
|
+
BOOL_FALSE_VALUES = %w[false no off 0].freeze
|
|
96
|
+
private_constant :BOOL_FALSE_VALUES
|
|
97
|
+
|
|
98
|
+
# Build a RemoteInfo from grouped variable/value pairs
|
|
99
|
+
#
|
|
100
|
+
# @param remote_name [String]
|
|
101
|
+
#
|
|
102
|
+
# @param pairs [Array] variable/value pairs collected from config entries
|
|
103
|
+
#
|
|
104
|
+
# @return [Git::RemoteInfo]
|
|
105
|
+
#
|
|
106
|
+
# @api private
|
|
107
|
+
#
|
|
108
|
+
def build_remote_info(remote_name, pairs)
|
|
109
|
+
attrs = { name: remote_name }
|
|
110
|
+
pairs.each { |variable, value| apply_pair(attrs, variable, value) }
|
|
111
|
+
Git::RemoteInfo.new(**attrs)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Apply a single variable/value pair to an attrs hash
|
|
115
|
+
#
|
|
116
|
+
# @param attrs [Hash] accumulator of RemoteInfo keyword arguments
|
|
117
|
+
#
|
|
118
|
+
# @param variable [String] git config variable name (e.g. 'url', 'tagopt')
|
|
119
|
+
#
|
|
120
|
+
# @param value [String] raw config value
|
|
121
|
+
#
|
|
122
|
+
# @return [void]
|
|
123
|
+
#
|
|
124
|
+
# @api private
|
|
125
|
+
#
|
|
126
|
+
def apply_pair(attrs, variable, value)
|
|
127
|
+
field = VARIABLE_TO_FIELD[variable]
|
|
128
|
+
return unless field # ignore unknown variables
|
|
129
|
+
|
|
130
|
+
if ARRAY_VARIABLES.include?(variable)
|
|
131
|
+
attrs[field] ||= []
|
|
132
|
+
attrs[field] << value
|
|
133
|
+
elsif BOOLEAN_VARIABLES.include?(variable)
|
|
134
|
+
attrs[field] = coerce_boolean(variable, value)
|
|
135
|
+
else
|
|
136
|
+
attrs[field] = value
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Coerce a git config boolean string to a Ruby boolean
|
|
141
|
+
#
|
|
142
|
+
# @param variable [String] the config variable name (for error messages)
|
|
143
|
+
#
|
|
144
|
+
# @param value [String] the raw string value from git config
|
|
145
|
+
#
|
|
146
|
+
# @return [Boolean] `true` or `false`
|
|
147
|
+
#
|
|
148
|
+
# @raise [ArgumentError] if the value is not a recognized boolean
|
|
149
|
+
#
|
|
150
|
+
# @api private
|
|
151
|
+
#
|
|
152
|
+
def coerce_boolean(variable, value)
|
|
153
|
+
normalized = value.downcase
|
|
154
|
+
return true if BOOL_TRUE_VALUES.include?(normalized) || normalized == ''
|
|
155
|
+
return false if BOOL_FALSE_VALUES.include?(normalized)
|
|
156
|
+
|
|
157
|
+
raise ArgumentError,
|
|
158
|
+
"unrecognized boolean value #{value.inspect} for config variable #{variable.inspect}"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
data/lib/git/remote.rb
CHANGED
|
@@ -121,9 +121,7 @@ module Git
|
|
|
121
121
|
#
|
|
122
122
|
def branch(branch = nil)
|
|
123
123
|
branch ||= remote_repository.current_branch
|
|
124
|
-
|
|
125
|
-
branch_info = build_branch_info(remote_tracking_branch)
|
|
126
|
-
Git::Branch.new(@base, branch_info)
|
|
124
|
+
Git::Branch.new(@base, "#{@name}/#{branch}")
|
|
127
125
|
end
|
|
128
126
|
|
|
129
127
|
# Removes this remote from the repository
|
|
@@ -159,24 +157,5 @@ module Git
|
|
|
159
157
|
def remote_repository
|
|
160
158
|
@base
|
|
161
159
|
end
|
|
162
|
-
|
|
163
|
-
# Builds branch metadata for a remote-tracking branch
|
|
164
|
-
#
|
|
165
|
-
# @param refname [String] remote-tracking branch name (for example,
|
|
166
|
-
# `'origin/main'`)
|
|
167
|
-
#
|
|
168
|
-
# @return [Git::BranchInfo] minimal branch metadata for constructing
|
|
169
|
-
# {Git::Branch}
|
|
170
|
-
#
|
|
171
|
-
def build_branch_info(refname)
|
|
172
|
-
Git::BranchInfo.new(
|
|
173
|
-
refname: refname,
|
|
174
|
-
target_oid: nil,
|
|
175
|
-
current: false,
|
|
176
|
-
worktree: false,
|
|
177
|
-
symref: nil,
|
|
178
|
-
upstream: nil
|
|
179
|
-
)
|
|
180
|
-
end
|
|
181
160
|
end
|
|
182
161
|
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Value object representing a configured git remote
|
|
5
|
+
#
|
|
6
|
+
# Each instance holds the parsed configuration for a single remote as read
|
|
7
|
+
# from the repository's git config. Multi-value fields (`:url`, `:push_url`,
|
|
8
|
+
# `:fetch`, `:push`) are always `Array<String>` (never `nil`; may be empty).
|
|
9
|
+
# All other fields are nilable except `:name`.
|
|
10
|
+
#
|
|
11
|
+
# @example Minimal remote (fetch-only, one URL)
|
|
12
|
+
# info = Git::RemoteInfo.new(
|
|
13
|
+
# name: 'origin',
|
|
14
|
+
# url: ['https://github.com/ruby-git/ruby-git.git'],
|
|
15
|
+
# push_url: [],
|
|
16
|
+
# fetch: ['+refs/heads/*:refs/remotes/origin/*'],
|
|
17
|
+
# push: []
|
|
18
|
+
# )
|
|
19
|
+
# info.name # => "origin"
|
|
20
|
+
# info.url # => ["https://github.com/ruby-git/ruby-git.git"]
|
|
21
|
+
# info.prune # => nil
|
|
22
|
+
#
|
|
23
|
+
# @api public
|
|
24
|
+
#
|
|
25
|
+
# @!attribute [r] name
|
|
26
|
+
# @return [String] the name of the remote (e.g. `'origin'`)
|
|
27
|
+
#
|
|
28
|
+
# @!attribute [r] url
|
|
29
|
+
# @return [Array<String>] the fetch URL(s) for this remote (`remote.<name>.url`)
|
|
30
|
+
#
|
|
31
|
+
# @!attribute [r] push_url
|
|
32
|
+
# @return [Array<String>] the push URL(s) for this remote (`remote.<name>.pushurl`)
|
|
33
|
+
#
|
|
34
|
+
# @!attribute [r] fetch
|
|
35
|
+
# @return [Array<String>] the fetch refspec(s) for this remote (`remote.<name>.fetch`)
|
|
36
|
+
#
|
|
37
|
+
# @!attribute [r] push
|
|
38
|
+
# @return [Array<String>] the push refspec(s) for this remote (`remote.<name>.push`)
|
|
39
|
+
#
|
|
40
|
+
# @!attribute [r] mirror
|
|
41
|
+
# @return [Boolean, nil] `true`/`false` per `remote.<name>.mirror`, or `nil` when not set
|
|
42
|
+
#
|
|
43
|
+
# @!attribute [r] skip_default_update
|
|
44
|
+
# @return [Boolean, nil] `true`/`false` per `remote.<name>.skipDefaultUpdate`, or `nil` when not set
|
|
45
|
+
#
|
|
46
|
+
# @!attribute [r] tag_opt
|
|
47
|
+
# @return [String, nil] the tag-fetching option (`remote.<name>.tagOpt`), or `nil` when not set
|
|
48
|
+
#
|
|
49
|
+
# @!attribute [r] prune
|
|
50
|
+
# @return [Boolean, nil] `true`/`false` per `remote.<name>.prune`; `nil` inherits `fetch.prune`
|
|
51
|
+
#
|
|
52
|
+
# @!attribute [r] prune_tags
|
|
53
|
+
# @return [Boolean, nil] `true`/`false` per `remote.<name>.pruneTags`; `nil` inherits `fetch.pruneTags`
|
|
54
|
+
#
|
|
55
|
+
# @!attribute [r] receivepack
|
|
56
|
+
# @return [String, nil] the `git-receive-pack` path on the remote (`remote.<name>.receivepack`)
|
|
57
|
+
#
|
|
58
|
+
# @!attribute [r] uploadpack
|
|
59
|
+
# @return [String, nil] the `git-upload-pack` path on the remote (`remote.<name>.uploadpack`)
|
|
60
|
+
#
|
|
61
|
+
# @!attribute [r] promisor
|
|
62
|
+
# @return [Boolean, nil] `true`/`false` per `remote.<name>.promisor`, or `nil` when not set
|
|
63
|
+
#
|
|
64
|
+
# @!attribute [r] partial_clone_filter
|
|
65
|
+
# @return [String, nil] the partial-clone object filter (`remote.<name>.partialclonefilter`)
|
|
66
|
+
#
|
|
67
|
+
# @!attribute [r] vcs
|
|
68
|
+
# @return [String, nil] the VCS type for git-remote helpers (`remote.<name>.vcs`)
|
|
69
|
+
#
|
|
70
|
+
RemoteInfo = Data.define(
|
|
71
|
+
:name,
|
|
72
|
+
:url,
|
|
73
|
+
:push_url,
|
|
74
|
+
:fetch,
|
|
75
|
+
:push,
|
|
76
|
+
:mirror,
|
|
77
|
+
:skip_default_update,
|
|
78
|
+
:tag_opt,
|
|
79
|
+
:prune,
|
|
80
|
+
:prune_tags,
|
|
81
|
+
:receivepack,
|
|
82
|
+
:uploadpack,
|
|
83
|
+
:promisor,
|
|
84
|
+
:partial_clone_filter,
|
|
85
|
+
:vcs
|
|
86
|
+
) do
|
|
87
|
+
# Create a new RemoteInfo
|
|
88
|
+
#
|
|
89
|
+
# @param name [String] the name of the remote (required)
|
|
90
|
+
#
|
|
91
|
+
# @param url [Array<String>] fetch URLs (default `[]`)
|
|
92
|
+
#
|
|
93
|
+
# @param push_url [Array<String>] push URLs (default `[]`)
|
|
94
|
+
#
|
|
95
|
+
# @param fetch [Array<String>] fetch refspecs (default `[]`)
|
|
96
|
+
#
|
|
97
|
+
# @param push [Array<String>] push refspecs (default `[]`)
|
|
98
|
+
#
|
|
99
|
+
# @param mirror [Boolean, nil] mirror flag (default `nil`)
|
|
100
|
+
#
|
|
101
|
+
# @param skip_default_update [Boolean, nil] skip-default-update flag (default `nil`)
|
|
102
|
+
#
|
|
103
|
+
# @param tag_opt [String, nil] tag-fetching option (default `nil`)
|
|
104
|
+
#
|
|
105
|
+
# @param prune [Boolean, nil] prune flag (default `nil`)
|
|
106
|
+
#
|
|
107
|
+
# @param prune_tags [Boolean, nil] prune-tags flag (default `nil`)
|
|
108
|
+
#
|
|
109
|
+
# @param receivepack [String, nil] receive-pack path (default `nil`)
|
|
110
|
+
#
|
|
111
|
+
# @param uploadpack [String, nil] upload-pack path (default `nil`)
|
|
112
|
+
#
|
|
113
|
+
# @param promisor [Boolean, nil] promisor flag (default `nil`)
|
|
114
|
+
#
|
|
115
|
+
# @param partial_clone_filter [String, nil] partial-clone filter (default `nil`)
|
|
116
|
+
#
|
|
117
|
+
# @param vcs [String, nil] VCS type (default `nil`)
|
|
118
|
+
#
|
|
119
|
+
# @return [Git::RemoteInfo]
|
|
120
|
+
#
|
|
121
|
+
def initialize(
|
|
122
|
+
name:,
|
|
123
|
+
url: [],
|
|
124
|
+
push_url: [],
|
|
125
|
+
fetch: [],
|
|
126
|
+
push: [],
|
|
127
|
+
mirror: nil,
|
|
128
|
+
skip_default_update: nil,
|
|
129
|
+
tag_opt: nil,
|
|
130
|
+
prune: nil,
|
|
131
|
+
prune_tags: nil,
|
|
132
|
+
receivepack: nil,
|
|
133
|
+
uploadpack: nil,
|
|
134
|
+
promisor: nil,
|
|
135
|
+
partial_clone_filter: nil,
|
|
136
|
+
vcs: nil
|
|
137
|
+
)
|
|
138
|
+
super(
|
|
139
|
+
name:, url: Array(url), push_url: Array(push_url), fetch: Array(fetch),
|
|
140
|
+
push: Array(push), mirror:, skip_default_update:, tag_opt:, prune:,
|
|
141
|
+
prune_tags:, receivepack:, uploadpack:, promisor:, partial_clone_filter:,
|
|
142
|
+
vcs:
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -277,7 +277,7 @@ module Git
|
|
|
277
277
|
#
|
|
278
278
|
def is_local_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
279
279
|
Git::Deprecation.warn(
|
|
280
|
-
'Git::Repository#is_local_branch? is deprecated and will be removed in
|
|
280
|
+
'Git::Repository#is_local_branch? is deprecated and will be removed in v6.0.0. ' \
|
|
281
281
|
'Use Git::Repository#local_branch? instead.'
|
|
282
282
|
)
|
|
283
283
|
local_branch?(branch)
|
|
@@ -299,7 +299,7 @@ module Git
|
|
|
299
299
|
#
|
|
300
300
|
def is_remote_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
301
301
|
Git::Deprecation.warn(
|
|
302
|
-
'Git::Repository#is_remote_branch? is deprecated and will be removed in
|
|
302
|
+
'Git::Repository#is_remote_branch? is deprecated and will be removed in v6.0.0. ' \
|
|
303
303
|
'Use Git::Repository#remote_branch? instead.'
|
|
304
304
|
)
|
|
305
305
|
remote_branch?(branch)
|
|
@@ -321,7 +321,7 @@ module Git
|
|
|
321
321
|
#
|
|
322
322
|
def is_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
323
323
|
Git::Deprecation.warn(
|
|
324
|
-
'Git::Repository#is_branch? is deprecated and will be removed in
|
|
324
|
+
'Git::Repository#is_branch? is deprecated and will be removed in v6.0.0. ' \
|
|
325
325
|
'Use Git::Repository#branch? instead.'
|
|
326
326
|
)
|
|
327
327
|
branch?(branch)
|
|
@@ -499,28 +499,71 @@ module Git
|
|
|
499
499
|
# Returns all local and remote-tracking branches as structured objects
|
|
500
500
|
#
|
|
501
501
|
# @example List all branches
|
|
502
|
-
# repo.
|
|
503
|
-
# # => [#<data Git::BranchInfo refname="main", current=true, ...>,
|
|
504
|
-
# # #<data Git::BranchInfo refname="remotes/origin/main", current=false, ...>]
|
|
502
|
+
# repo.branch_list
|
|
503
|
+
# # => [#<data Git::BranchInfo refname="refs/heads/main", current=true, ...>,
|
|
504
|
+
# # #<data Git::BranchInfo refname="refs/remotes/origin/main", current=false, ...>]
|
|
505
505
|
#
|
|
506
506
|
# @example Find the currently checked-out branch
|
|
507
|
-
# repo.
|
|
507
|
+
# repo.branch_list.find(&:current)
|
|
508
508
|
#
|
|
509
509
|
# @example List only local branches
|
|
510
|
-
# repo.
|
|
510
|
+
# repo.branch_list.reject(&:remote?)
|
|
511
|
+
#
|
|
512
|
+
# @example Filter to an exact branch name
|
|
513
|
+
# repo.branch_list('feature/auth')
|
|
514
|
+
#
|
|
515
|
+
# @example Filter using glob patterns
|
|
516
|
+
# repo.branch_list('feature/*', 'hotfix/*')
|
|
517
|
+
#
|
|
518
|
+
# @param patterns [Array<String>] optional shell wildcard patterns passed
|
|
519
|
+
# directly to `git branch --list`; when empty (the default) all branches
|
|
520
|
+
# are returned. Pattern matching follows git's own rules; behavior may
|
|
521
|
+
# differ between local and remote-tracking branches.
|
|
522
|
+
#
|
|
523
|
+
# @param remote_names [Array<String>, nil] configured remote names used to
|
|
524
|
+
# resolve remote-tracking refs
|
|
525
|
+
#
|
|
526
|
+
# Especially useful for remotes whose remote names contain slashes. When
|
|
527
|
+
# omitted, the repository's configured remote names are fetched automatically.
|
|
511
528
|
#
|
|
512
529
|
# @return [Array<Git::BranchInfo>] parsed branch information for every
|
|
513
|
-
# local and remote-tracking branch
|
|
530
|
+
# local and remote-tracking branch matching the pattern
|
|
514
531
|
#
|
|
515
|
-
# Returns an empty array when the repository has no branches
|
|
532
|
+
# Returns an empty array when the repository has no branches or no branches
|
|
533
|
+
# match the given pattern.
|
|
516
534
|
#
|
|
517
535
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
518
536
|
#
|
|
519
|
-
def
|
|
537
|
+
def branch_list(*patterns, remote_names: nil)
|
|
538
|
+
remote_names ||= self.remote_names
|
|
520
539
|
result = Git::Commands::Branch::List.new(@execution_context).call(
|
|
521
|
-
all: true, format: Git::Parsers::Branch::FORMAT_STRING
|
|
540
|
+
*patterns, all: true, format: Git::Parsers::Branch::FORMAT_STRING
|
|
522
541
|
)
|
|
523
|
-
Git::Parsers::Branch.parse_list(result.stdout)
|
|
542
|
+
Git::Parsers::Branch.parse_list(result.stdout, remote_names:)
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
# Returns all local and remote-tracking branches in the 4.x-compatible format
|
|
546
|
+
#
|
|
547
|
+
# Each entry is a 4-element array: `[refname, current, worktree, symref]`.
|
|
548
|
+
# The `refname` uses the short form (`main`, `remotes/origin/main`) to
|
|
549
|
+
# match the output of the legacy `Git::Lib#branches_all` method.
|
|
550
|
+
#
|
|
551
|
+
# @return [Array<Array>] array of `[refname, current, worktree, symref]` tuples
|
|
552
|
+
#
|
|
553
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
554
|
+
#
|
|
555
|
+
# @deprecated Use {#branch_list} instead, which returns richer
|
|
556
|
+
# {Git::BranchInfo} objects.
|
|
557
|
+
#
|
|
558
|
+
def branches_all
|
|
559
|
+
Git::Deprecation.warn(
|
|
560
|
+
'Git::Repository#branches_all is deprecated and will be removed in v6.0.0. ' \
|
|
561
|
+
'Use Git::Repository#branch_list instead.'
|
|
562
|
+
)
|
|
563
|
+
branch_list.map do |info|
|
|
564
|
+
refname = info.remote? ? "remotes/#{info.remote_name}/#{info.short_name}" : info.short_name
|
|
565
|
+
[refname, info.current, info.other_worktree?, info.symref]
|
|
566
|
+
end
|
|
524
567
|
end
|
|
525
568
|
|
|
526
569
|
# Update a branch ref to point to a new commit
|
|
@@ -573,15 +616,7 @@ module Git
|
|
|
573
616
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
574
617
|
#
|
|
575
618
|
def branch(branch_name = current_branch)
|
|
576
|
-
|
|
577
|
-
refname: branch_name,
|
|
578
|
-
target_oid: nil,
|
|
579
|
-
current: false,
|
|
580
|
-
worktree: false,
|
|
581
|
-
symref: nil,
|
|
582
|
-
upstream: nil
|
|
583
|
-
)
|
|
584
|
-
Git::Branch.new(self, branch_info)
|
|
619
|
+
Git::Branch.new(self, branch_name)
|
|
585
620
|
end
|
|
586
621
|
|
|
587
622
|
# Returns a {Git::Branches} collection of all branches in the repository
|
|
@@ -73,12 +73,7 @@ module Git
|
|
|
73
73
|
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
74
74
|
#
|
|
75
75
|
def commit(message, opts = {})
|
|
76
|
-
opts = opts
|
|
77
|
-
if opts.key?(:add_all)
|
|
78
|
-
Git::Deprecation.warn('The :add_all option for #commit is deprecated, use :all instead')
|
|
79
|
-
opts[:all] = opts.delete(:add_all)
|
|
80
|
-
end
|
|
81
|
-
|
|
76
|
+
opts = normalize_commit_options(opts)
|
|
82
77
|
SharedPrivate.assert_valid_opts!(COMMIT_ALLOWED_OPTS, **opts)
|
|
83
78
|
|
|
84
79
|
call_opts = { no_edit: true }
|
|
@@ -222,6 +217,30 @@ module Git
|
|
|
222
217
|
def write_and_commit_tree(opts = {})
|
|
223
218
|
commit_tree(write_tree, opts)
|
|
224
219
|
end
|
|
220
|
+
|
|
221
|
+
private
|
|
222
|
+
|
|
223
|
+
# Normalizes deprecated commit options into their supported form
|
|
224
|
+
#
|
|
225
|
+
# @param opts [Hash] caller-provided commit options
|
|
226
|
+
#
|
|
227
|
+
# @option opts [Boolean, nil] :add_all (nil) deprecated alias for `:all`
|
|
228
|
+
#
|
|
229
|
+
# @return [Hash] options with deprecated aliases translated
|
|
230
|
+
#
|
|
231
|
+
# @api private
|
|
232
|
+
#
|
|
233
|
+
def normalize_commit_options(opts)
|
|
234
|
+
opts = opts.dup
|
|
235
|
+
return opts unless opts.key?(:add_all)
|
|
236
|
+
|
|
237
|
+
Git::Deprecation.warn(
|
|
238
|
+
'The :add_all option for #commit is deprecated and will be removed in v6.0.0. ' \
|
|
239
|
+
'Use :all instead.'
|
|
240
|
+
)
|
|
241
|
+
opts[:all] = opts.delete(:add_all)
|
|
242
|
+
opts
|
|
243
|
+
end
|
|
225
244
|
end
|
|
226
245
|
end
|
|
227
246
|
end
|
|
@@ -242,7 +242,7 @@ module Git
|
|
|
242
242
|
def context_helpers_deprecate_check_argument(check, must_exist)
|
|
243
243
|
if !check.nil? && defined?(Git::Deprecation)
|
|
244
244
|
Git::Deprecation.warn(
|
|
245
|
-
'The "check" argument is deprecated and will be removed in
|
|
245
|
+
'The "check" argument is deprecated and will be removed in v6.0.0. ' \
|
|
246
246
|
'Use "must_exist:" instead.'
|
|
247
247
|
)
|
|
248
248
|
end
|
|
@@ -517,7 +517,8 @@ module Git
|
|
|
517
517
|
opts[:path_limiter]
|
|
518
518
|
elsif opts.key?(:path)
|
|
519
519
|
Git::Deprecation.warn(
|
|
520
|
-
'Git::Repository#diff_path_status :path option is deprecated
|
|
520
|
+
'Git::Repository#diff_path_status :path option is deprecated and will be removed in v6.0.0. ' \
|
|
521
|
+
'Use :path_limiter instead.'
|
|
521
522
|
)
|
|
522
523
|
opts[:path]
|
|
523
524
|
end
|
|
@@ -750,7 +750,10 @@ module Git
|
|
|
750
750
|
return unless opts.key?(:path)
|
|
751
751
|
|
|
752
752
|
if defined?(Git::Deprecation)
|
|
753
|
-
Git::Deprecation.warn(
|
|
753
|
+
Git::Deprecation.warn(
|
|
754
|
+
'The :path option for Git.clone is deprecated and will be removed in v6.0.0. ' \
|
|
755
|
+
'Use :chdir instead.'
|
|
756
|
+
)
|
|
754
757
|
end
|
|
755
758
|
path = opts.delete(:path)
|
|
756
759
|
opts[:chdir] ||= path
|
|
@@ -775,7 +778,8 @@ module Git
|
|
|
775
778
|
|
|
776
779
|
if defined?(Git::Deprecation)
|
|
777
780
|
Git::Deprecation.warn(
|
|
778
|
-
'The :recursive option for Git.clone is deprecated
|
|
781
|
+
'The :recursive option for Git.clone is deprecated and will be removed in v6.0.0. ' \
|
|
782
|
+
'Use :recurse_submodules instead.'
|
|
779
783
|
)
|
|
780
784
|
end
|
|
781
785
|
opts[:recurse_submodules] = opts.delete(:recursive)
|
|
@@ -798,7 +802,10 @@ module Git
|
|
|
798
802
|
return unless opts.key?(:remote)
|
|
799
803
|
|
|
800
804
|
if defined?(Git::Deprecation)
|
|
801
|
-
Git::Deprecation.warn(
|
|
805
|
+
Git::Deprecation.warn(
|
|
806
|
+
'The :remote option for Git.clone is deprecated and will be removed in v6.0.0. ' \
|
|
807
|
+
'Use :origin instead.'
|
|
808
|
+
)
|
|
802
809
|
end
|
|
803
810
|
opts[:origin] = opts.delete(:remote)
|
|
804
811
|
end
|
|
@@ -48,11 +48,11 @@ module Git
|
|
|
48
48
|
# @example Merge without committing
|
|
49
49
|
# repo.merge('feature', nil, no_commit: true)
|
|
50
50
|
#
|
|
51
|
-
# @param branch [
|
|
52
|
-
#
|
|
51
|
+
# @param branch [#to_s, Array<#to_s>] the branch or branches to merge into the
|
|
52
|
+
# current branch
|
|
53
53
|
#
|
|
54
|
-
# When an Array is given, an octopus merge is performed;
|
|
55
|
-
# object is coerced to a String via `#to_s`.
|
|
54
|
+
# When an Array is given, an octopus merge is performed; each branch-ish
|
|
55
|
+
# object (e.g., {Git::BranchInfo}) is coerced to a String via `#to_s`.
|
|
56
56
|
#
|
|
57
57
|
# @param message [String, nil] optional commit message for the merge commit
|
|
58
58
|
#
|
|
@@ -245,7 +245,7 @@ module Git
|
|
|
245
245
|
#
|
|
246
246
|
def conflicts(&)
|
|
247
247
|
Git::Deprecation.warn(
|
|
248
|
-
'Git::Repository#conflicts is deprecated and will be removed in
|
|
248
|
+
'Git::Repository#conflicts is deprecated and will be removed in v6.0.0. ' \
|
|
249
249
|
'Use Git::Repository#each_conflict instead.'
|
|
250
250
|
)
|
|
251
251
|
each_conflict(&)
|