git 5.6.0 → 6.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/CHANGELOG.md +132 -16
- data/CONTRIBUTING.md +44 -31
- data/README.md +135 -67
- data/UPGRADING.md +915 -268
- data/git.gemspec +6 -8
- data/lib/git/author_info.rb +1 -2
- data/lib/git/commands/base.rb +22 -2
- data/lib/git/commands/cat_file/raw.rb +0 -68
- data/lib/git/commands/maintenance/register.rb +0 -4
- data/lib/git/commands/maintenance/run.rb +0 -4
- data/lib/git/commands/maintenance/start.rb +0 -4
- data/lib/git/commands/maintenance/stop.rb +0 -4
- data/lib/git/commands/maintenance/unregister.rb +0 -4
- data/lib/git/commands/maintenance.rb +0 -2
- data/lib/git/commands/show_ref/exclude_existing.rb +1 -1
- data/lib/git/commands/show_ref/exists.rb +0 -5
- data/lib/git/commands/show_ref/list.rb +1 -1
- data/lib/git/commands/show_ref/verify.rb +1 -1
- data/lib/git/commands/show_ref.rb +1 -1
- data/lib/git/commands/worktree/repair.rb +0 -5
- data/lib/git/diff_path_status.rb +2 -2
- data/lib/git/encoding_utils.rb +25 -0
- data/lib/git/errors.rb +23 -5
- data/lib/git/factories.rb +361 -125
- data/lib/git/log.rb +3 -75
- data/lib/git/object.rb +4 -185
- data/lib/git/path_resolver.rb +104 -36
- data/lib/git/repository/branching.rb +21 -189
- data/lib/git/repository/committing.rb +0 -25
- data/lib/git/repository/context_helpers.rb +249 -155
- data/lib/git/repository/diffing.rb +2 -44
- data/lib/git/repository/merging.rb +32 -54
- data/lib/git/repository/object_operations.rb +121 -338
- data/lib/git/repository/remote_operations.rb +7 -219
- data/lib/git/repository/staging.rb +6 -184
- data/lib/git/repository/stashing.rb +126 -130
- data/lib/git/repository/status_operations.rb +1 -54
- data/lib/git/repository/worktree_operations.rb +31 -118
- data/lib/git/repository.rb +20 -299
- data/lib/git/system_call_guard.rb +95 -0
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +47 -364
- metadata +25 -19
- data/lib/git/author.rb +0 -46
- data/lib/git/branch.rb +0 -693
- data/lib/git/branches.rb +0 -194
- data/lib/git/remote.rb +0 -191
- data/lib/git/stash.rb +0 -124
- data/lib/git/stashes.rb +0 -198
- data/lib/git/status.rb +0 -384
- data/lib/git/worktree.rb +0 -180
- data/lib/git/worktrees.rb +0 -152
data/lib/git/branches.rb
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Git
|
|
4
|
-
# Collection of all Git branches in a repository
|
|
5
|
-
#
|
|
6
|
-
# Wraps both local and remote-tracking branches and provides filtering,
|
|
7
|
-
# enumeration, and name-based lookup.
|
|
8
|
-
#
|
|
9
|
-
# @example Enumerate all branches
|
|
10
|
-
# branches = repo.branches
|
|
11
|
-
# branches.each { |b| puts b.name }
|
|
12
|
-
#
|
|
13
|
-
# @deprecated Use {Git::Repository::Branching#branch_list} instead
|
|
14
|
-
#
|
|
15
|
-
# {Git::Repository::Branching#branch_list} returns `Array<Git::BranchInfo>`
|
|
16
|
-
# (immutable value objects). Filter it with `select(&:remote?)` or
|
|
17
|
-
# `reject(&:remote?)` in place of {#remote} and {#local}, and look a
|
|
18
|
-
# branch up by name with `branch_list(name).first` in place of {#[]}.
|
|
19
|
-
# Constructing a `Git::Branches` emits a deprecation warning.
|
|
20
|
-
#
|
|
21
|
-
# @api public
|
|
22
|
-
#
|
|
23
|
-
class Branches
|
|
24
|
-
include Enumerable
|
|
25
|
-
|
|
26
|
-
# Creates a new Branches collection populated from the given repository
|
|
27
|
-
#
|
|
28
|
-
# @param base [Git::Repository] the repository to enumerate
|
|
29
|
-
# branches from
|
|
30
|
-
#
|
|
31
|
-
# @return [void]
|
|
32
|
-
#
|
|
33
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
34
|
-
#
|
|
35
|
-
# @deprecated Use {Git::Repository::Branching#branch_list} instead
|
|
36
|
-
#
|
|
37
|
-
# @see Git::Repository::Branching#branch_list
|
|
38
|
-
#
|
|
39
|
-
def initialize(base)
|
|
40
|
-
Git::Deprecation.warn(
|
|
41
|
-
'Git::Branches is deprecated and will be removed in v6.0.0. ' \
|
|
42
|
-
'Use Git::Repository#branch_list instead.'
|
|
43
|
-
)
|
|
44
|
-
@branches = {}
|
|
45
|
-
@lookup = {}
|
|
46
|
-
|
|
47
|
-
@base = base
|
|
48
|
-
|
|
49
|
-
load_branches
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Returns all local (non-remote-tracking) branches
|
|
53
|
-
#
|
|
54
|
-
# @example List local branch names
|
|
55
|
-
# repo.branches.local.map(&:name)
|
|
56
|
-
#
|
|
57
|
-
# @return [Array<Git::Branch>] the local branches
|
|
58
|
-
#
|
|
59
|
-
def local
|
|
60
|
-
reject(&:remote)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Returns all remote-tracking branches
|
|
64
|
-
#
|
|
65
|
-
# @example List remote branch names
|
|
66
|
-
# repo.branches.remote.map(&:name)
|
|
67
|
-
#
|
|
68
|
-
# @return [Array<Git::Branch>] the remote-tracking branches
|
|
69
|
-
#
|
|
70
|
-
def remote
|
|
71
|
-
self.select(&:remote)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Returns the number of branches in the collection
|
|
75
|
-
#
|
|
76
|
-
# @example Count all branches
|
|
77
|
-
# repo.branches.size # => 3
|
|
78
|
-
#
|
|
79
|
-
# @return [Integer] the total number of branches
|
|
80
|
-
#
|
|
81
|
-
def size
|
|
82
|
-
@branches.size
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Iterates over every branch in the collection
|
|
86
|
-
#
|
|
87
|
-
# @overload each
|
|
88
|
-
#
|
|
89
|
-
# @example Get an enumerator over all branches
|
|
90
|
-
# enum = repo.branches.each
|
|
91
|
-
#
|
|
92
|
-
# @return [Enumerator<Git::Branch>] an enumerator over all branches
|
|
93
|
-
#
|
|
94
|
-
# @overload each(&block)
|
|
95
|
-
#
|
|
96
|
-
# @example Print every branch name
|
|
97
|
-
# repo.branches.each { |b| puts b.name }
|
|
98
|
-
#
|
|
99
|
-
# @return [Array<Git::Branch>] the full list of branches
|
|
100
|
-
#
|
|
101
|
-
# @yield [branch] passes each branch to the block
|
|
102
|
-
#
|
|
103
|
-
# @yieldparam branch [Git::Branch] a branch in the repository
|
|
104
|
-
#
|
|
105
|
-
# @yieldreturn [void]
|
|
106
|
-
#
|
|
107
|
-
def each(&)
|
|
108
|
-
@branches.values.each(&)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# Returns the branch with the given name
|
|
112
|
-
#
|
|
113
|
-
# Supports short names (`'main'`), remote-qualified names
|
|
114
|
-
# (`'working/master'`), and full refspec names
|
|
115
|
-
# (`'remotes/working/master'`).
|
|
116
|
-
#
|
|
117
|
-
# @example Look up a branch by short name
|
|
118
|
-
# repo.branches['main']
|
|
119
|
-
#
|
|
120
|
-
# @example Look up a remote-tracking branch
|
|
121
|
-
# repo.branches['working/master']
|
|
122
|
-
#
|
|
123
|
-
# @param branch_name [#to_s] the name of the branch to retrieve
|
|
124
|
-
#
|
|
125
|
-
# @return [Git::Branch, nil] the matching branch, or `nil` if not found
|
|
126
|
-
#
|
|
127
|
-
def [](branch_name)
|
|
128
|
-
@lookup[branch_name.to_s]
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
# Returns a string listing all branches, prefixed with `*` for the current branch
|
|
132
|
-
#
|
|
133
|
-
# @example Display all branches
|
|
134
|
-
# puts repo.branches.to_s
|
|
135
|
-
#
|
|
136
|
-
# @return [String] a formatted branch listing
|
|
137
|
-
#
|
|
138
|
-
def to_s
|
|
139
|
-
out = +''
|
|
140
|
-
@branches.each_value do |b|
|
|
141
|
-
# Git::Branch#current is deprecated too; silence it so one to_s call emits one warning
|
|
142
|
-
current = Git::Deprecation.silence { b.current }
|
|
143
|
-
out << (current ? '* ' : ' ') << b.to_s << "\n"
|
|
144
|
-
end
|
|
145
|
-
out
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
private
|
|
149
|
-
|
|
150
|
-
# Builds a Git::Branch for every branch in the repository and indexes it
|
|
151
|
-
#
|
|
152
|
-
# @return [void]
|
|
153
|
-
#
|
|
154
|
-
# @api private
|
|
155
|
-
#
|
|
156
|
-
def load_branches
|
|
157
|
-
branch_repository.branch_list.each do |branch_info|
|
|
158
|
-
branch = Git::Branch.new(@base, branch_info)
|
|
159
|
-
|
|
160
|
-
@branches[branch_info.refname] = branch
|
|
161
|
-
index_branch_lookup(branch, refname: branch_info.refname)
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# @return [Git::Repository] the repository used to enumerate branches
|
|
166
|
-
#
|
|
167
|
-
# @api private
|
|
168
|
-
#
|
|
169
|
-
def branch_repository
|
|
170
|
-
@base
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
# Indexes all supported lookup keys for a branch without mutating
|
|
174
|
-
# the canonical `@branches` collection used by enumeration
|
|
175
|
-
#
|
|
176
|
-
# @param branch [Git::Branch] the branch to index
|
|
177
|
-
#
|
|
178
|
-
# @param refname [String] the full refname key to use for primary lookup
|
|
179
|
-
#
|
|
180
|
-
# @return [void]
|
|
181
|
-
#
|
|
182
|
-
# @api private
|
|
183
|
-
#
|
|
184
|
-
def index_branch_lookup(branch, refname:)
|
|
185
|
-
@lookup[refname] ||= branch
|
|
186
|
-
@lookup[branch.full] ||= branch
|
|
187
|
-
|
|
188
|
-
return unless branch.full.start_with?('remotes/')
|
|
189
|
-
|
|
190
|
-
# Mirror git compatibility: allow omitting a leading "remotes/".
|
|
191
|
-
@lookup[branch.full.delete_prefix('remotes/')] ||= branch
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
end
|
data/lib/git/remote.rb
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'git/branch'
|
|
4
|
-
require 'git/branch_info'
|
|
5
|
-
|
|
6
|
-
module Git
|
|
7
|
-
# A remote in a Git repository
|
|
8
|
-
#
|
|
9
|
-
# Remote objects provide access to remote metadata and operations like fetch,
|
|
10
|
-
# merge, and remove. This class and `Git::Repository#remote`, which returns
|
|
11
|
-
# it, are both deprecated: read remote configuration through
|
|
12
|
-
# {Git::Repository::RemoteOperations#remote_list} and call the
|
|
13
|
-
# repository-level operations with the remote name instead.
|
|
14
|
-
#
|
|
15
|
-
# @example Reading a remote and fetching from it without Git::Remote
|
|
16
|
-
# git = Git.open('.')
|
|
17
|
-
# origin = git.remote_list.find { |r| r.name == 'origin' } #=> Git::RemoteInfo
|
|
18
|
-
# origin.url.first
|
|
19
|
-
# git.fetch(origin.name)
|
|
20
|
-
#
|
|
21
|
-
# @deprecated Use {Git::Repository::RemoteOperations#remote_list} and the
|
|
22
|
-
# repository-level remote operations instead
|
|
23
|
-
#
|
|
24
|
-
# {Git::Repository::RemoteOperations#remote_list} returns immutable
|
|
25
|
-
# {Git::RemoteInfo} value objects. Operations that lived on this class are
|
|
26
|
-
# called on the repository with the remote name instead (for example
|
|
27
|
-
# {Git::Repository::RemoteOperations#fetch} and
|
|
28
|
-
# {Git::Repository::RemoteOperations#remote_remove}). Constructing a
|
|
29
|
-
# `Git::Remote` emits a deprecation warning.
|
|
30
|
-
#
|
|
31
|
-
# @api public
|
|
32
|
-
#
|
|
33
|
-
class Remote
|
|
34
|
-
# The name of this remote (e.g. `'origin'`)
|
|
35
|
-
#
|
|
36
|
-
# @return [String] the remote name
|
|
37
|
-
#
|
|
38
|
-
attr_accessor :name
|
|
39
|
-
|
|
40
|
-
# The URL of this remote
|
|
41
|
-
#
|
|
42
|
-
# @return [String, nil] the remote URL
|
|
43
|
-
#
|
|
44
|
-
attr_accessor :url
|
|
45
|
-
|
|
46
|
-
# The fetch refspec for this remote
|
|
47
|
-
#
|
|
48
|
-
# @return [String, nil] the fetch options string
|
|
49
|
-
#
|
|
50
|
-
attr_accessor :fetch_opts
|
|
51
|
-
|
|
52
|
-
# Initialize a new Remote object
|
|
53
|
-
#
|
|
54
|
-
# @param base [Git::Repository] the git repository
|
|
55
|
-
#
|
|
56
|
-
# @param name [String] the remote name (e.g. `'origin'`)
|
|
57
|
-
#
|
|
58
|
-
# @note Do not construct directly. `Git::Repository#remote` is deprecated as
|
|
59
|
-
# well; use {Git::Repository::RemoteOperations#remote_list} and the
|
|
60
|
-
# repository-level remote operations instead.
|
|
61
|
-
#
|
|
62
|
-
# @api private
|
|
63
|
-
#
|
|
64
|
-
def initialize(base, name)
|
|
65
|
-
Git::Deprecation.warn(
|
|
66
|
-
'Git::Remote is deprecated and will be removed in v6.0.0. ' \
|
|
67
|
-
'Use Git::Repository#remote_list and the repository-level remote operations instead.'
|
|
68
|
-
)
|
|
69
|
-
@base = base
|
|
70
|
-
# config_remote is deprecated too; silence it so one Git::Remote.new emits one warning
|
|
71
|
-
config = Git::Deprecation.silence { remote_repository.config_remote(name) }
|
|
72
|
-
@name = name
|
|
73
|
-
@url = config['url']
|
|
74
|
-
@fetch_opts = config['fetch']
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Fetches from this remote
|
|
78
|
-
#
|
|
79
|
-
# @example Fetch from origin
|
|
80
|
-
# git.remote('origin').fetch
|
|
81
|
-
#
|
|
82
|
-
# @param opts [Hash] options for the fetch command
|
|
83
|
-
#
|
|
84
|
-
# @option opts [Boolean, nil] :tags (nil) fetch all tags from the remote
|
|
85
|
-
# (`--tags`)
|
|
86
|
-
#
|
|
87
|
-
# @option opts [Boolean, nil] :prune (nil) remove remote-tracking references
|
|
88
|
-
# that no longer exist on the remote (`--prune`)
|
|
89
|
-
#
|
|
90
|
-
# @option opts [Boolean, nil] :prune_tags (nil) remove local tags that no
|
|
91
|
-
# longer exist on the remote (`--prune-tags`)
|
|
92
|
-
#
|
|
93
|
-
# @option opts [Boolean, nil] :force (nil) override the fast-forward check
|
|
94
|
-
# when using explicit refspecs (`--force`)
|
|
95
|
-
#
|
|
96
|
-
# @option opts [Boolean, nil] :update_head_ok (nil) allow `git fetch` to
|
|
97
|
-
# update the branch pointed to by `HEAD` (`--update-head-ok`)
|
|
98
|
-
#
|
|
99
|
-
# @option opts [Boolean, nil] :unshallow (nil) convert a shallow clone into a
|
|
100
|
-
# full repository (`--unshallow`)
|
|
101
|
-
#
|
|
102
|
-
# @option opts [String, Integer, nil] :depth (nil) limit history to N commits
|
|
103
|
-
# from each branch tip (`--depth=N`)
|
|
104
|
-
#
|
|
105
|
-
# @option opts [String, Array<String>, nil] :ref (nil) one or more refspecs to
|
|
106
|
-
# fetch as positional arguments after the remote name
|
|
107
|
-
#
|
|
108
|
-
# @return [String] git's stdout from the fetch
|
|
109
|
-
#
|
|
110
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
111
|
-
#
|
|
112
|
-
def fetch(opts = {})
|
|
113
|
-
remote_repository.fetch(@name, opts)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# Merges this remote into the given (or current) local branch
|
|
117
|
-
#
|
|
118
|
-
# @example Merge origin/main into the current branch
|
|
119
|
-
# git.remote('origin').merge('main')
|
|
120
|
-
#
|
|
121
|
-
# @param branch [String] the local branch to merge into (defaults to current branch)
|
|
122
|
-
#
|
|
123
|
-
# @return [String] git's stdout from the merge
|
|
124
|
-
#
|
|
125
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
126
|
-
#
|
|
127
|
-
def merge(branch = nil)
|
|
128
|
-
branch ||= remote_repository.current_branch
|
|
129
|
-
remote_tracking_branch = "#{@name}/#{branch}"
|
|
130
|
-
remote_repository.merge(remote_tracking_branch)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Returns a {Git::Branch} object for the given branch on this remote
|
|
134
|
-
#
|
|
135
|
-
# @example Get the remote-tracking branch object
|
|
136
|
-
# git.remote('origin').branch('main') #=> #<Git::Branch 'origin/main'>
|
|
137
|
-
#
|
|
138
|
-
# @param branch [String] the branch name on this remote (defaults to current branch)
|
|
139
|
-
#
|
|
140
|
-
# @return [Git::Branch] a branch object representing `<remote>/<branch>`
|
|
141
|
-
#
|
|
142
|
-
# @deprecated Use
|
|
143
|
-
# `Git::Repository#branch_list("#{name}/#{branch || current_branch}").first`
|
|
144
|
-
# instead
|
|
145
|
-
#
|
|
146
|
-
# With no argument this method falls back to the current branch, so the
|
|
147
|
-
# replacement has to supply `Git::Repository#current_branch` itself. The
|
|
148
|
-
# replacement returns a {Git::BranchInfo} value object rather than a
|
|
149
|
-
# {Git::Branch}, and returns `nil` when the remote-tracking branch does
|
|
150
|
-
# not exist.
|
|
151
|
-
#
|
|
152
|
-
def branch(branch = nil)
|
|
153
|
-
branch ||= remote_repository.current_branch
|
|
154
|
-
Git::Branch.new(@base, "#{@name}/#{branch}")
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Removes this remote from the repository
|
|
158
|
-
#
|
|
159
|
-
# @example Remove the upstream remote
|
|
160
|
-
# git.remote('upstream').remove
|
|
161
|
-
#
|
|
162
|
-
# @return [Git::CommandLine::Result] the result of `git remote remove`
|
|
163
|
-
#
|
|
164
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
165
|
-
#
|
|
166
|
-
def remove
|
|
167
|
-
remote_repository.remote_remove(@name)
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Returns the name of this remote as a string
|
|
171
|
-
#
|
|
172
|
-
# @example Get the remote name as a string
|
|
173
|
-
# git.remote('origin').to_s #=> 'origin'
|
|
174
|
-
#
|
|
175
|
-
# @return [String] the remote name
|
|
176
|
-
#
|
|
177
|
-
def to_s
|
|
178
|
-
@name
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
private
|
|
182
|
-
|
|
183
|
-
# @return [Git::Repository]
|
|
184
|
-
#
|
|
185
|
-
# @api private
|
|
186
|
-
#
|
|
187
|
-
def remote_repository
|
|
188
|
-
@base
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
end
|
data/lib/git/stash.rb
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Git
|
|
4
|
-
# Represents a single stash entry in a Git repository
|
|
5
|
-
#
|
|
6
|
-
# This class is deprecated and will be removed in v6.0.0. Use the
|
|
7
|
-
# {Git::Repository} stash methods and {Git::StashInfo} instead:
|
|
8
|
-
# {Git::Repository#stash_push} replaces `Git::Stash.new(repo, message)` and
|
|
9
|
-
# returns a {Git::StashInfo}, or `nil` when there was nothing to stash.
|
|
10
|
-
#
|
|
11
|
-
# @example Create a stash and inspect the result (deprecated)
|
|
12
|
-
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
13
|
-
# stash.message #=> "WIP: feature work"
|
|
14
|
-
# stash.saved? #=> true
|
|
15
|
-
#
|
|
16
|
-
# @example The replacement
|
|
17
|
-
# info = repo.stash_push(message: 'WIP: feature work')
|
|
18
|
-
# info.message #=> "On main: WIP: feature work"
|
|
19
|
-
# info.nil? #=> false
|
|
20
|
-
#
|
|
21
|
-
# @deprecated Use {Git::Repository#stash_push} and {Git::StashInfo} instead
|
|
22
|
-
#
|
|
23
|
-
# @see Git::Repository#stash_push
|
|
24
|
-
#
|
|
25
|
-
# @api public
|
|
26
|
-
#
|
|
27
|
-
class Stash
|
|
28
|
-
# Initialize a Stash object
|
|
29
|
-
#
|
|
30
|
-
# When `existing` is `false` (the default), immediately calls {#save} to push
|
|
31
|
-
# the current working-directory state onto the stash stack.
|
|
32
|
-
#
|
|
33
|
-
# Emits one deprecation warning per object.
|
|
34
|
-
#
|
|
35
|
-
# @example Create a new stash entry
|
|
36
|
-
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
37
|
-
# stash.saved? #=> true
|
|
38
|
-
#
|
|
39
|
-
# @example Reference an existing stash without pushing
|
|
40
|
-
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
41
|
-
# stash.saved? #=> nil
|
|
42
|
-
#
|
|
43
|
-
# @param base [Git::Repository] the git repository
|
|
44
|
-
#
|
|
45
|
-
# @param message [String] the stash message
|
|
46
|
-
#
|
|
47
|
-
# @param existing [Boolean] (false) when `true`, wraps an existing stash entry
|
|
48
|
-
# without pushing any changes
|
|
49
|
-
#
|
|
50
|
-
# @return [void]
|
|
51
|
-
#
|
|
52
|
-
# @deprecated Use {Git::Repository#stash_push} and {Git::StashInfo} instead
|
|
53
|
-
#
|
|
54
|
-
def initialize(base, message, existing: false)
|
|
55
|
-
Git::Deprecation.warn(
|
|
56
|
-
'Git::Stash is deprecated and will be removed in v6.0.0. ' \
|
|
57
|
-
'Use the Git::Repository stash methods (stash_push, stash_infos, stash_apply) ' \
|
|
58
|
-
'and Git::StashInfo instead.'
|
|
59
|
-
)
|
|
60
|
-
@base = base
|
|
61
|
-
@message = message
|
|
62
|
-
save unless existing
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Saves the current working-directory state to the stash stack
|
|
66
|
-
#
|
|
67
|
-
# @example Save changes to the stash stack
|
|
68
|
-
# stash = Git::Stash.new(repo, 'WIP', existing: true)
|
|
69
|
-
# stash.save #=> true
|
|
70
|
-
#
|
|
71
|
-
# @return [Boolean] `true` if changes were stashed, `false` if there were no
|
|
72
|
-
# local changes to save
|
|
73
|
-
#
|
|
74
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
75
|
-
#
|
|
76
|
-
def save
|
|
77
|
-
# stash_save is deprecated too; silence it so one Git::Stash call emits one warning
|
|
78
|
-
@saved = Git::Deprecation.silence { stash_repository.stash_save(@message) }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Returns whether the stash was saved successfully
|
|
82
|
-
#
|
|
83
|
-
# @example Check if changes were stashed
|
|
84
|
-
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
85
|
-
# stash.saved? #=> true
|
|
86
|
-
#
|
|
87
|
-
# @return [Boolean, nil] `true` if changes were stashed, `false` if there were no
|
|
88
|
-
# local changes, `nil` if {#save} has not been called (e.g. `existing: true`)
|
|
89
|
-
#
|
|
90
|
-
def saved?
|
|
91
|
-
@saved
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Returns the stash description
|
|
95
|
-
#
|
|
96
|
-
# @example Read the stash message
|
|
97
|
-
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
98
|
-
# stash.message #=> "WIP: feature work"
|
|
99
|
-
#
|
|
100
|
-
# @return [String] the stash message
|
|
101
|
-
#
|
|
102
|
-
attr_reader :message
|
|
103
|
-
|
|
104
|
-
# Returns the stash description as a string
|
|
105
|
-
#
|
|
106
|
-
# @example Convert stash to string
|
|
107
|
-
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
108
|
-
# stash.to_s #=> "WIP: feature work"
|
|
109
|
-
#
|
|
110
|
-
# @return [String] the stash message
|
|
111
|
-
#
|
|
112
|
-
def to_s
|
|
113
|
-
message
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
private
|
|
117
|
-
|
|
118
|
-
# @return [Git::Repository]
|
|
119
|
-
#
|
|
120
|
-
def stash_repository
|
|
121
|
-
@base
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
data/lib/git/stashes.rb
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Git
|
|
4
|
-
# Collection of stash entries for a Git repository
|
|
5
|
-
#
|
|
6
|
-
# This class is deprecated and will be removed in v6.0.0. Use the
|
|
7
|
-
# {Git::Repository} stash methods and {Git::StashInfo} instead:
|
|
8
|
-
# {Git::Repository#stash_infos} replaces the collection, and
|
|
9
|
-
# {Git::Repository#stash_push}, {Git::Repository#stash_apply}, and
|
|
10
|
-
# {Git::Repository#stash_clear} replace {#save}, {#apply}, and {#clear}.
|
|
11
|
-
#
|
|
12
|
-
# @example Iterate over stash entries (deprecated)
|
|
13
|
-
# git.stashes.each { |s| puts s.message }
|
|
14
|
-
#
|
|
15
|
-
# @example The replacement
|
|
16
|
-
# repo.stash_infos.each { |info| puts info.message }
|
|
17
|
-
# repo.stash_infos.size #=> 2
|
|
18
|
-
# repo.stash_apply
|
|
19
|
-
#
|
|
20
|
-
# @deprecated Use {Git::Repository#stash_infos} and {Git::StashInfo} instead
|
|
21
|
-
#
|
|
22
|
-
# @see Git::Repository#stash_infos
|
|
23
|
-
#
|
|
24
|
-
# @api public
|
|
25
|
-
#
|
|
26
|
-
class Stashes
|
|
27
|
-
include Enumerable
|
|
28
|
-
|
|
29
|
-
# Initialize the stashes collection
|
|
30
|
-
#
|
|
31
|
-
# Loads all existing stash entries from the repository at construction time.
|
|
32
|
-
# Emits one deprecation warning per object.
|
|
33
|
-
#
|
|
34
|
-
# @example Load stashes for a repository
|
|
35
|
-
# stashes = Git::Stashes.new(repo)
|
|
36
|
-
# stashes.size #=> 2
|
|
37
|
-
#
|
|
38
|
-
# @param base [Git::Repository] the git repository
|
|
39
|
-
#
|
|
40
|
-
# @return [void]
|
|
41
|
-
#
|
|
42
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
43
|
-
#
|
|
44
|
-
# @deprecated Use {Git::Repository#stash_infos} and {Git::StashInfo} instead
|
|
45
|
-
#
|
|
46
|
-
def initialize(base)
|
|
47
|
-
Git::Deprecation.warn(
|
|
48
|
-
'Git::Stashes is deprecated and will be removed in v6.0.0. ' \
|
|
49
|
-
'Use the Git::Repository stash methods (stash_infos, stash_push, stash_apply, stash_clear) ' \
|
|
50
|
-
'and Git::StashInfo instead.'
|
|
51
|
-
)
|
|
52
|
-
@stashes = []
|
|
53
|
-
@base = base
|
|
54
|
-
# stashes_all and Git::Stash are deprecated too; silence them so one
|
|
55
|
-
# Git::Stashes.new emits one warning
|
|
56
|
-
Git::Deprecation.silence { load_stashes }
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Returns all stash entries as an array of index and message pairs
|
|
60
|
-
#
|
|
61
|
-
# Entries are listed in oldest-first order matching {Git::Repository#stashes_all}.
|
|
62
|
-
#
|
|
63
|
-
# @example List all stash entries
|
|
64
|
-
# git.stashes.all #=> [[0, "testing-stash-all"], [1, "another-stash"]]
|
|
65
|
-
#
|
|
66
|
-
# @return [Array<Array(Integer, String)>] array of `[index, message]` pairs where
|
|
67
|
-
# index 0 is the oldest stash
|
|
68
|
-
#
|
|
69
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
70
|
-
#
|
|
71
|
-
def all
|
|
72
|
-
# stashes_all is deprecated too; silence it so this call emits no second warning
|
|
73
|
-
Git::Deprecation.silence { stash_repository.stashes_all }
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Saves the current working-directory state to a new stash entry
|
|
77
|
-
#
|
|
78
|
-
# @example Save current changes to the stash
|
|
79
|
-
# git.stashes.save('WIP: feature work')
|
|
80
|
-
# git.stashes.size #=> 1
|
|
81
|
-
#
|
|
82
|
-
# @param message [String] the stash message
|
|
83
|
-
#
|
|
84
|
-
# @return [void]
|
|
85
|
-
#
|
|
86
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
87
|
-
#
|
|
88
|
-
def save(message)
|
|
89
|
-
# Git::Stash is deprecated too; silence it so this call emits no second warning
|
|
90
|
-
s = Git::Deprecation.silence { Git::Stash.new(@base, message) }
|
|
91
|
-
@stashes.unshift(s) if s.saved?
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Applies a stash entry to the working directory
|
|
95
|
-
#
|
|
96
|
-
# @example Apply the most recent stash
|
|
97
|
-
# git.stashes.apply
|
|
98
|
-
#
|
|
99
|
-
# @example Apply a specific stash by index
|
|
100
|
-
# git.stashes.apply(1)
|
|
101
|
-
#
|
|
102
|
-
# @param index [Integer, nil] the stash index to apply (default: latest)
|
|
103
|
-
#
|
|
104
|
-
# @return [String] the output from the git stash apply command
|
|
105
|
-
#
|
|
106
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
107
|
-
#
|
|
108
|
-
def apply(index = nil)
|
|
109
|
-
stash_repository.stash_apply(index)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Removes all stash entries
|
|
113
|
-
#
|
|
114
|
-
# @example Clear all stashes
|
|
115
|
-
# git.stashes.clear
|
|
116
|
-
# git.stashes.size #=> 0
|
|
117
|
-
#
|
|
118
|
-
# @return [void]
|
|
119
|
-
#
|
|
120
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
121
|
-
#
|
|
122
|
-
def clear
|
|
123
|
-
stash_repository.stash_clear
|
|
124
|
-
@stashes = []
|
|
125
|
-
nil
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Returns the number of stash entries
|
|
129
|
-
#
|
|
130
|
-
# @example Check how many stashes exist
|
|
131
|
-
# git.stashes.size #=> 2
|
|
132
|
-
#
|
|
133
|
-
# @return [Integer] the number of stashes
|
|
134
|
-
#
|
|
135
|
-
def size
|
|
136
|
-
@stashes.size
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
# Iterates over each stash entry in newest-first order
|
|
140
|
-
#
|
|
141
|
-
# @example Iterate over stashes
|
|
142
|
-
# git.stashes.each { |s| puts s.message }
|
|
143
|
-
#
|
|
144
|
-
# @overload each
|
|
145
|
-
#
|
|
146
|
-
# @return [Enumerator<Git::Stash>] an enumerator over stash entries
|
|
147
|
-
#
|
|
148
|
-
# @overload each(&block)
|
|
149
|
-
#
|
|
150
|
-
# @yield [stash] each stash entry
|
|
151
|
-
#
|
|
152
|
-
# @yieldparam stash [Git::Stash] the current stash entry
|
|
153
|
-
#
|
|
154
|
-
# @yieldreturn [void]
|
|
155
|
-
#
|
|
156
|
-
# @return [Array<Git::Stash>] the stash entries
|
|
157
|
-
#
|
|
158
|
-
def each(&)
|
|
159
|
-
@stashes.each(&)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
# Returns the stash entry at the given index
|
|
163
|
-
#
|
|
164
|
-
# Stashes are stored in newest-first order; index 0 is the most recent stash.
|
|
165
|
-
#
|
|
166
|
-
# @example Access the most recent stash
|
|
167
|
-
# git.stashes[0].message #=> "WIP: feature work"
|
|
168
|
-
#
|
|
169
|
-
# @param index [Integer, #to_i] the stash index (0 = most recent)
|
|
170
|
-
#
|
|
171
|
-
# @return [Git::Stash, nil] the stash entry, or `nil` if the index is out of bounds
|
|
172
|
-
#
|
|
173
|
-
def [](index)
|
|
174
|
-
@stashes[index.to_i]
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
private
|
|
178
|
-
|
|
179
|
-
# Wraps every entry from the repository in a Git::Stash, newest first
|
|
180
|
-
#
|
|
181
|
-
# @return [void]
|
|
182
|
-
#
|
|
183
|
-
def load_stashes
|
|
184
|
-
stash_repository.stashes_all.each do |stash|
|
|
185
|
-
message = stash[1]
|
|
186
|
-
@stashes.unshift(Git::Stash.new(@base, message, existing: true))
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# Returns the facade interface for stash operations
|
|
191
|
-
#
|
|
192
|
-
# @return [Git::Repository]
|
|
193
|
-
#
|
|
194
|
-
def stash_repository
|
|
195
|
-
@base
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|