git 5.3.0 → 5.4.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 +16 -0
- data/README.md +1 -1
- data/UPGRADING.md +320 -22
- data/lib/git/branch.rb +9 -5
- data/lib/git/object.rb +56 -8
- data/lib/git/parsers/status.rb +251 -0
- data/lib/git/parsers/worktree.rb +185 -0
- data/lib/git/repository/object_operations.rb +257 -20
- data/lib/git/repository/stashing.rb +532 -52
- data/lib/git/repository/status_operations.rb +56 -8
- data/lib/git/repository/worktree_operations.rb +198 -18
- data/lib/git/stash.rb +31 -2
- data/lib/git/stashes.rb +47 -11
- data/lib/git/status.rb +14 -0
- data/lib/git/status_file_info.rb +258 -0
- data/lib/git/status_info.rb +189 -0
- data/lib/git/tag_info.rb +2 -1
- data/lib/git/version.rb +1 -1
- data/lib/git/worktree.rb +39 -0
- data/lib/git/worktree_info.rb +128 -0
- data/lib/git/worktrees.rb +19 -1
- data/lib/git.rb +4 -0
- metadata +8 -3
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require 'git/commands/ls_files'
|
|
4
4
|
require 'git/commands/rev_parse'
|
|
5
|
+
require 'git/commands/status'
|
|
5
6
|
require 'git/escaped_path'
|
|
7
|
+
require 'git/parsers/status'
|
|
6
8
|
require 'git/status'
|
|
9
|
+
require 'git/status_info'
|
|
7
10
|
|
|
8
11
|
module Git
|
|
9
12
|
class Repository
|
|
@@ -87,6 +90,47 @@ module Git
|
|
|
87
90
|
).stdout.split("\n").map { |f| Private.unescape_quoted_path(f) }
|
|
88
91
|
end
|
|
89
92
|
|
|
93
|
+
# Returns a {Git::StatusInfo} describing the index and working tree state
|
|
94
|
+
#
|
|
95
|
+
# Runs `git status` in porcelain v2 format with NUL-separated entries and
|
|
96
|
+
# every untracked file listed individually, then reads `core.ignoreCase`
|
|
97
|
+
# as a boolean so that the path predicates on the result compare paths the
|
|
98
|
+
# way git does in this repository. Every entry type git reports is
|
|
99
|
+
# represented, including renames, copies, and merge conflicts. Clean
|
|
100
|
+
# tracked paths are not reported by `git status`, so they are absent from
|
|
101
|
+
# the result; the deprecated {#status} listed them, and {#ls_files} still
|
|
102
|
+
# does.
|
|
103
|
+
#
|
|
104
|
+
# @example Check which files are modified
|
|
105
|
+
# repo.status_info.changed
|
|
106
|
+
# #=> { "lib/foo.rb" => #<data Git::StatusFileInfo path="lib/foo.rb", ...> }
|
|
107
|
+
#
|
|
108
|
+
# @example Check for untracked files
|
|
109
|
+
# repo.status_info.untracked.keys #=> ["new_file.rb"]
|
|
110
|
+
#
|
|
111
|
+
# @example Check one path
|
|
112
|
+
# repo.status_info.changed?('lib/foo.rb') #=> true
|
|
113
|
+
#
|
|
114
|
+
# @example Iterate over every entry
|
|
115
|
+
# repo.status_info.files.each do |file|
|
|
116
|
+
# puts "#{file.index_status}#{file.worktree_status} #{file.path}"
|
|
117
|
+
# end
|
|
118
|
+
#
|
|
119
|
+
# @return [Git::StatusInfo] the status of the repository
|
|
120
|
+
#
|
|
121
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
122
|
+
#
|
|
123
|
+
# @see https://git-scm.com/docs/git-status git-status
|
|
124
|
+
#
|
|
125
|
+
def status_info
|
|
126
|
+
result = Git::Commands::Status.new(@execution_context).call(
|
|
127
|
+
porcelain: 'v2', z: true, untracked_files: 'all'
|
|
128
|
+
)
|
|
129
|
+
files = Git::Parsers::Status.parse(result.stdout)
|
|
130
|
+
ignore_case = config_get('core.ignoreCase', type: 'bool')&.value == 'true'
|
|
131
|
+
Git::StatusInfo.new(files: files, ignore_case: ignore_case)
|
|
132
|
+
end
|
|
133
|
+
|
|
90
134
|
# Returns a {Git::Status} object describing the working tree and index state
|
|
91
135
|
#
|
|
92
136
|
# Constructs a {Git::Status} for this repository by collecting information from
|
|
@@ -95,22 +139,26 @@ module Git
|
|
|
95
139
|
# result identifies which files have been modified, added, deleted, or are
|
|
96
140
|
# untracked.
|
|
97
141
|
#
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
# @example Check for untracked files
|
|
102
|
-
# repo.status.untracked #=> { "new_file.rb" => <Git::Status::StatusFile ...> }
|
|
142
|
+
# Emits one deprecation warning per call. The {Git::Status} it constructs is
|
|
143
|
+
# built with warnings silenced so the caller does not see a second one.
|
|
103
144
|
#
|
|
104
|
-
# @example
|
|
105
|
-
# repo.status.
|
|
145
|
+
# @example Check which files are modified (deprecated; use status_info)
|
|
146
|
+
# repo.status.changed.keys #=> ["lib/foo.rb"]
|
|
147
|
+
# repo.status_info.changed.keys #=> ["lib/foo.rb"]
|
|
106
148
|
#
|
|
107
149
|
# @return [Git::Status] the status of the repository
|
|
108
150
|
#
|
|
109
151
|
# @raise [Git::FailedError] if any underlying git command exits with a
|
|
110
152
|
# non-zero exit status
|
|
111
153
|
#
|
|
154
|
+
# @deprecated Use {#status_info} instead
|
|
155
|
+
#
|
|
112
156
|
def status
|
|
113
|
-
Git::
|
|
157
|
+
Git::Deprecation.warn(
|
|
158
|
+
'Git::Repository#status is deprecated and will be removed in v6.0.0. ' \
|
|
159
|
+
'Use Git::Repository#status_info instead.'
|
|
160
|
+
)
|
|
161
|
+
Git::Deprecation.silence { Git::Status.new(self) }
|
|
114
162
|
end
|
|
115
163
|
|
|
116
164
|
# List all files tracked in the index
|
|
@@ -1,22 +1,55 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'git/commands/worktree'
|
|
4
|
+
require 'git/parsers/worktree'
|
|
4
5
|
require 'git/worktree'
|
|
6
|
+
require 'git/worktree_info'
|
|
5
7
|
require 'git/worktrees'
|
|
6
8
|
|
|
7
9
|
module Git
|
|
8
10
|
class Repository
|
|
9
|
-
# Facade methods for worktree operations
|
|
11
|
+
# Facade methods for worktree operations: listing, adding, removing, moving,
|
|
12
|
+
# locking, repairing, and pruning worktrees
|
|
10
13
|
#
|
|
11
14
|
# Included by {Git::Repository}.
|
|
12
15
|
#
|
|
13
16
|
# @api private
|
|
14
17
|
#
|
|
15
18
|
module WorktreeOperations
|
|
19
|
+
# Returns every worktree attached to the repository
|
|
20
|
+
#
|
|
21
|
+
# Lists the main worktree first, then each linked worktree, in the order
|
|
22
|
+
# git reports them. The main worktree of a bare repository is included
|
|
23
|
+
# with {Git::WorktreeInfo#bare?} true and no head or branch.
|
|
24
|
+
#
|
|
25
|
+
# @example List all worktrees
|
|
26
|
+
# repo.worktree_list.map(&:path)
|
|
27
|
+
# #=> ["/path/to/main", "/tmp/feature"]
|
|
28
|
+
#
|
|
29
|
+
# @example Find the worktree that has a branch checked out
|
|
30
|
+
# info = repo.worktree_list.find { |w| w.branch == 'refs/heads/feature' }
|
|
31
|
+
# info.path #=> "/tmp/feature"
|
|
32
|
+
# info.head #=> "b8c63202c3c0ebd37b7e45fd0c22e6c20d5bead1"
|
|
33
|
+
# info.locked? #=> false
|
|
34
|
+
#
|
|
35
|
+
# @return [Array<Git::WorktreeInfo>] one entry per worktree
|
|
36
|
+
#
|
|
37
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
38
|
+
#
|
|
39
|
+
# @raise [Git::UnexpectedResultError] if the worktree listing cannot be
|
|
40
|
+
# parsed
|
|
41
|
+
#
|
|
42
|
+
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
43
|
+
#
|
|
44
|
+
def worktree_list
|
|
45
|
+
result = Git::Commands::Worktree::List.new(@execution_context).call(porcelain: true)
|
|
46
|
+
Git::Parsers::Worktree.parse_list(result.stdout)
|
|
47
|
+
end
|
|
48
|
+
|
|
16
49
|
# Returns all worktrees as an array of directory and SHA pairs
|
|
17
50
|
#
|
|
18
|
-
# Lists
|
|
19
|
-
#
|
|
51
|
+
# Lists the main worktree and all linked worktrees. The main worktree of
|
|
52
|
+
# a bare repository has no checked-out commit and is omitted.
|
|
20
53
|
#
|
|
21
54
|
# @example List all worktrees
|
|
22
55
|
# repo.worktrees_all
|
|
@@ -30,20 +63,22 @@ module Git
|
|
|
30
63
|
#
|
|
31
64
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
32
65
|
#
|
|
66
|
+
# @deprecated Use {#worktree_list} instead
|
|
67
|
+
#
|
|
68
|
+
# {#worktree_list} returns one {Git::WorktreeInfo} per worktree, with
|
|
69
|
+
# `path` and `head` in place of the pair, and includes the main worktree
|
|
70
|
+
# of a bare repository.
|
|
71
|
+
#
|
|
72
|
+
# @see #worktree_list
|
|
73
|
+
#
|
|
33
74
|
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
34
75
|
#
|
|
35
76
|
def worktrees_all
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
key, value = line.split(' ', 2)
|
|
42
|
-
current_directory = value if key == 'worktree'
|
|
43
|
-
worktree_entries << [current_directory, value] if key == 'HEAD'
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
worktree_entries
|
|
77
|
+
Git::Deprecation.warn(
|
|
78
|
+
'Git::Repository#worktrees_all is deprecated and will be removed in v6.0.0. ' \
|
|
79
|
+
'Use Git::Repository#worktree_list instead.'
|
|
80
|
+
)
|
|
81
|
+
worktree_list.reject { |worktree| worktree.head.nil? }.map { |worktree| [worktree.path, worktree.head] }
|
|
47
82
|
end
|
|
48
83
|
|
|
49
84
|
# Create a new linked worktree at the given directory
|
|
@@ -75,10 +110,15 @@ module Git
|
|
|
75
110
|
|
|
76
111
|
# Remove a linked worktree
|
|
77
112
|
#
|
|
78
|
-
# @example Remove a worktree
|
|
113
|
+
# @example Remove a worktree by path
|
|
79
114
|
# repo.worktree_remove('/tmp/feature')
|
|
80
115
|
#
|
|
81
|
-
# @
|
|
116
|
+
# @example Remove a worktree from the list
|
|
117
|
+
# info = repo.worktree_list.find { |w| w.branch == 'refs/heads/feature' }
|
|
118
|
+
# repo.worktree_remove(info)
|
|
119
|
+
#
|
|
120
|
+
# @param worktree [String, Git::WorktreeInfo] the path of the worktree to
|
|
121
|
+
# remove, or its entry from {#worktree_list}
|
|
82
122
|
#
|
|
83
123
|
# @return [String] the output from the git worktree remove command
|
|
84
124
|
# (typically empty)
|
|
@@ -87,8 +127,120 @@ module Git
|
|
|
87
127
|
#
|
|
88
128
|
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
89
129
|
#
|
|
90
|
-
def worktree_remove(
|
|
91
|
-
Git::Commands::Worktree::Remove.new(@execution_context).call(
|
|
130
|
+
def worktree_remove(worktree)
|
|
131
|
+
Git::Commands::Worktree::Remove.new(@execution_context).call(worktree.to_s).stdout
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Move a linked worktree to a new location
|
|
135
|
+
#
|
|
136
|
+
# @example Move a worktree
|
|
137
|
+
# repo.worktree_move('/tmp/feature', '/tmp/feature-moved')
|
|
138
|
+
#
|
|
139
|
+
# @example Move a locked worktree
|
|
140
|
+
# repo.worktree_move('/tmp/feature', '/tmp/feature-moved', force: 2)
|
|
141
|
+
#
|
|
142
|
+
# @param worktree [String, Git::WorktreeInfo] the path of the worktree to
|
|
143
|
+
# move, or its entry from {#worktree_list}
|
|
144
|
+
#
|
|
145
|
+
# @param new_path [String] the destination path
|
|
146
|
+
#
|
|
147
|
+
# @param opts [Hash] options for the move
|
|
148
|
+
#
|
|
149
|
+
# @option opts [Boolean, Integer, nil] :force (nil) override git's
|
|
150
|
+
# safeguards; git refuses to move a locked worktree unless the flag is
|
|
151
|
+
# given twice, so pass `2` for that
|
|
152
|
+
#
|
|
153
|
+
# @return [String] the output from the git worktree move command
|
|
154
|
+
# (typically empty)
|
|
155
|
+
#
|
|
156
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
157
|
+
#
|
|
158
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
159
|
+
#
|
|
160
|
+
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
161
|
+
#
|
|
162
|
+
def worktree_move(worktree, new_path, opts = {})
|
|
163
|
+
Git::Commands::Worktree::Move.new(@execution_context).call(worktree.to_s, new_path, **opts).stdout
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Lock a linked worktree so that `git worktree prune` leaves it alone
|
|
167
|
+
#
|
|
168
|
+
# Lock a worktree whose directory is on removable media or a network
|
|
169
|
+
# share that is not always mounted.
|
|
170
|
+
#
|
|
171
|
+
# @example Lock a worktree
|
|
172
|
+
# repo.worktree_lock('/tmp/feature')
|
|
173
|
+
#
|
|
174
|
+
# @example Lock a worktree with a reason
|
|
175
|
+
# repo.worktree_lock('/tmp/feature', reason: 'on an external drive')
|
|
176
|
+
#
|
|
177
|
+
# @param worktree [String, Git::WorktreeInfo] the path of the worktree to
|
|
178
|
+
# lock, or its entry from {#worktree_list}
|
|
179
|
+
#
|
|
180
|
+
# @param opts [Hash] options for the lock
|
|
181
|
+
#
|
|
182
|
+
# @option opts [String, nil] :reason (nil) an explanation stored with the
|
|
183
|
+
# lock and reported as {Git::WorktreeInfo#lock_reason}
|
|
184
|
+
#
|
|
185
|
+
# @return [String] the output from the git worktree lock command
|
|
186
|
+
# (typically empty)
|
|
187
|
+
#
|
|
188
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
189
|
+
#
|
|
190
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
191
|
+
#
|
|
192
|
+
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
193
|
+
#
|
|
194
|
+
def worktree_lock(worktree, opts = {})
|
|
195
|
+
Git::Commands::Worktree::Lock.new(@execution_context).call(worktree.to_s, **opts).stdout
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Unlock a linked worktree
|
|
199
|
+
#
|
|
200
|
+
# @example Unlock a worktree
|
|
201
|
+
# repo.worktree_unlock('/tmp/feature')
|
|
202
|
+
#
|
|
203
|
+
# @param worktree [String, Git::WorktreeInfo] the path of the worktree to
|
|
204
|
+
# unlock, or its entry from {#worktree_list}
|
|
205
|
+
#
|
|
206
|
+
# @return [String] the output from the git worktree unlock command
|
|
207
|
+
# (typically empty)
|
|
208
|
+
#
|
|
209
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
210
|
+
#
|
|
211
|
+
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
212
|
+
#
|
|
213
|
+
def worktree_unlock(worktree)
|
|
214
|
+
Git::Commands::Worktree::Unlock.new(@execution_context).call(worktree.to_s).stdout
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Repair the links between the repository and its linked worktrees
|
|
218
|
+
#
|
|
219
|
+
# With no paths, repairs the link from each linked worktree back to the
|
|
220
|
+
# repository, which is needed after the repository directory was moved.
|
|
221
|
+
# Given the current paths of linked worktrees that were moved without
|
|
222
|
+
# {#worktree_move}, also repairs the repository's links to them.
|
|
223
|
+
#
|
|
224
|
+
# @example Repair after the repository directory was moved
|
|
225
|
+
# repo.worktree_repair
|
|
226
|
+
#
|
|
227
|
+
# @example Repair after a linked worktree was moved by hand
|
|
228
|
+
# repo.worktree_repair('/new/path/to/feature')
|
|
229
|
+
#
|
|
230
|
+
# @param paths [Array<String, Git::WorktreeInfo>] the current paths of the
|
|
231
|
+
# worktrees to repair, or their entries from {#worktree_list}
|
|
232
|
+
#
|
|
233
|
+
# @return [String] the output from the git worktree repair command, which
|
|
234
|
+
# reports each repair made
|
|
235
|
+
#
|
|
236
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
237
|
+
#
|
|
238
|
+
# @raise [Git::VersionError] if the installed git is older than 2.29.0
|
|
239
|
+
#
|
|
240
|
+
# @see https://git-scm.com/docs/git-worktree git-worktree documentation
|
|
241
|
+
#
|
|
242
|
+
def worktree_repair(*paths)
|
|
243
|
+
Git::Commands::Worktree::Repair.new(@execution_context).call(*paths.map(&:to_s)).stdout
|
|
92
244
|
end
|
|
93
245
|
|
|
94
246
|
# Prune stale worktree administrative files
|
|
@@ -128,7 +280,22 @@ module Git
|
|
|
128
280
|
#
|
|
129
281
|
# @return [Git::Worktree] a worktree domain object for the given path
|
|
130
282
|
#
|
|
283
|
+
# @deprecated Use {#worktree_add} and {#worktree_remove} instead
|
|
284
|
+
#
|
|
285
|
+
# `repo.worktree(dir, commitish).add` becomes
|
|
286
|
+
# `repo.worktree_add(dir, commitish)` and `repo.worktree(dir).remove`
|
|
287
|
+
# becomes `repo.worktree_remove(dir)`. Read a worktree's checked-out
|
|
288
|
+
# commit from {Git::WorktreeInfo#head} via {#worktree_list}.
|
|
289
|
+
#
|
|
290
|
+
# @see #worktree_add
|
|
291
|
+
#
|
|
292
|
+
# @see #worktree_remove
|
|
293
|
+
#
|
|
131
294
|
def worktree(dir, commitish = nil)
|
|
295
|
+
Git::Deprecation.warn(
|
|
296
|
+
'Git::Repository#worktree is deprecated and will be removed in v6.0.0. ' \
|
|
297
|
+
'Use Git::Repository#worktree_add and Git::Repository#worktree_remove instead.'
|
|
298
|
+
)
|
|
132
299
|
Git::Worktree.new(self, dir, commitish)
|
|
133
300
|
end
|
|
134
301
|
|
|
@@ -151,7 +318,20 @@ module Git
|
|
|
151
318
|
#
|
|
152
319
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
153
320
|
#
|
|
321
|
+
# @deprecated Use {#worktree_list} instead
|
|
322
|
+
#
|
|
323
|
+
# {#worktree_list} returns `Array<Git::WorktreeInfo>`. Look a worktree up
|
|
324
|
+
# by path with `worktree_list.find { |w| w.path == path }` in place of
|
|
325
|
+
# `worktrees[path]`, and call {#worktree_prune} in place of
|
|
326
|
+
# `worktrees.prune`. Calling this method emits one deprecation warning.
|
|
327
|
+
#
|
|
328
|
+
# @see #worktree_list
|
|
329
|
+
#
|
|
154
330
|
def worktrees
|
|
331
|
+
Git::Deprecation.warn(
|
|
332
|
+
'Git::Repository#worktrees is deprecated and will be removed in v6.0.0. ' \
|
|
333
|
+
'Use Git::Repository#worktree_list instead.'
|
|
334
|
+
)
|
|
155
335
|
Git::Worktrees.new(self)
|
|
156
336
|
end
|
|
157
337
|
end
|
data/lib/git/stash.rb
CHANGED
|
@@ -3,11 +3,25 @@
|
|
|
3
3
|
module Git
|
|
4
4
|
# Represents a single stash entry in a Git repository
|
|
5
5
|
#
|
|
6
|
-
#
|
|
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)
|
|
7
12
|
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
8
13
|
# stash.message #=> "WIP: feature work"
|
|
9
14
|
# stash.saved? #=> true
|
|
10
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
|
+
#
|
|
11
25
|
# @api public
|
|
12
26
|
#
|
|
13
27
|
class Stash
|
|
@@ -16,6 +30,8 @@ module Git
|
|
|
16
30
|
# When `existing` is `false` (the default), immediately calls {#save} to push
|
|
17
31
|
# the current working-directory state onto the stash stack.
|
|
18
32
|
#
|
|
33
|
+
# Emits one deprecation warning per object.
|
|
34
|
+
#
|
|
19
35
|
# @example Create a new stash entry
|
|
20
36
|
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
21
37
|
# stash.saved? #=> true
|
|
@@ -32,7 +48,15 @@ module Git
|
|
|
32
48
|
# without pushing any changes
|
|
33
49
|
#
|
|
34
50
|
# @return [void]
|
|
51
|
+
#
|
|
52
|
+
# @deprecated Use {Git::Repository#stash_push} and {Git::StashInfo} instead
|
|
53
|
+
#
|
|
35
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
|
+
)
|
|
36
60
|
@base = base
|
|
37
61
|
@message = message
|
|
38
62
|
save unless existing
|
|
@@ -48,8 +72,10 @@ module Git
|
|
|
48
72
|
# local changes to save
|
|
49
73
|
#
|
|
50
74
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
75
|
+
#
|
|
51
76
|
def save
|
|
52
|
-
|
|
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) }
|
|
53
79
|
end
|
|
54
80
|
|
|
55
81
|
# Returns whether the stash was saved successfully
|
|
@@ -60,6 +86,7 @@ module Git
|
|
|
60
86
|
#
|
|
61
87
|
# @return [Boolean, nil] `true` if changes were stashed, `false` if there were no
|
|
62
88
|
# local changes, `nil` if {#save} has not been called (e.g. `existing: true`)
|
|
89
|
+
#
|
|
63
90
|
def saved?
|
|
64
91
|
@saved
|
|
65
92
|
end
|
|
@@ -71,6 +98,7 @@ module Git
|
|
|
71
98
|
# stash.message #=> "WIP: feature work"
|
|
72
99
|
#
|
|
73
100
|
# @return [String] the stash message
|
|
101
|
+
#
|
|
74
102
|
attr_reader :message
|
|
75
103
|
|
|
76
104
|
# Returns the stash description as a string
|
|
@@ -80,6 +108,7 @@ module Git
|
|
|
80
108
|
# stash.to_s #=> "WIP: feature work"
|
|
81
109
|
#
|
|
82
110
|
# @return [String] the stash message
|
|
111
|
+
#
|
|
83
112
|
def to_s
|
|
84
113
|
message
|
|
85
114
|
end
|
data/lib/git/stashes.rb
CHANGED
|
@@ -3,12 +3,23 @@
|
|
|
3
3
|
module Git
|
|
4
4
|
# Collection of stash entries for a Git repository
|
|
5
5
|
#
|
|
6
|
-
#
|
|
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)
|
|
7
13
|
# git.stashes.each { |s| puts s.message }
|
|
8
14
|
#
|
|
9
|
-
# @example
|
|
10
|
-
#
|
|
11
|
-
#
|
|
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
|
|
12
23
|
#
|
|
13
24
|
# @api public
|
|
14
25
|
#
|
|
@@ -18,6 +29,7 @@ module Git
|
|
|
18
29
|
# Initialize the stashes collection
|
|
19
30
|
#
|
|
20
31
|
# Loads all existing stash entries from the repository at construction time.
|
|
32
|
+
# Emits one deprecation warning per object.
|
|
21
33
|
#
|
|
22
34
|
# @example Load stashes for a repository
|
|
23
35
|
# stashes = Git::Stashes.new(repo)
|
|
@@ -28,14 +40,20 @@ module Git
|
|
|
28
40
|
# @return [void]
|
|
29
41
|
#
|
|
30
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
|
+
#
|
|
31
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
|
+
)
|
|
32
52
|
@stashes = []
|
|
33
53
|
@base = base
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@stashes.unshift(Git::Stash.new(@base, message, existing: true))
|
|
38
|
-
end
|
|
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 }
|
|
39
57
|
end
|
|
40
58
|
|
|
41
59
|
# Returns all stash entries as an array of index and message pairs
|
|
@@ -51,7 +69,8 @@ module Git
|
|
|
51
69
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
52
70
|
#
|
|
53
71
|
def all
|
|
54
|
-
|
|
72
|
+
# stashes_all is deprecated too; silence it so this call emits no second warning
|
|
73
|
+
Git::Deprecation.silence { stash_repository.stashes_all }
|
|
55
74
|
end
|
|
56
75
|
|
|
57
76
|
# Saves the current working-directory state to a new stash entry
|
|
@@ -65,8 +84,10 @@ module Git
|
|
|
65
84
|
# @return [void]
|
|
66
85
|
#
|
|
67
86
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
87
|
+
#
|
|
68
88
|
def save(message)
|
|
69
|
-
|
|
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) }
|
|
70
91
|
@stashes.unshift(s) if s.saved?
|
|
71
92
|
end
|
|
72
93
|
|
|
@@ -83,6 +104,7 @@ module Git
|
|
|
83
104
|
# @return [String] the output from the git stash apply command
|
|
84
105
|
#
|
|
85
106
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
107
|
+
#
|
|
86
108
|
def apply(index = nil)
|
|
87
109
|
stash_repository.stash_apply(index)
|
|
88
110
|
end
|
|
@@ -96,6 +118,7 @@ module Git
|
|
|
96
118
|
# @return [void]
|
|
97
119
|
#
|
|
98
120
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
121
|
+
#
|
|
99
122
|
def clear
|
|
100
123
|
stash_repository.stash_clear
|
|
101
124
|
@stashes = []
|
|
@@ -108,6 +131,7 @@ module Git
|
|
|
108
131
|
# git.stashes.size #=> 2
|
|
109
132
|
#
|
|
110
133
|
# @return [Integer] the number of stashes
|
|
134
|
+
#
|
|
111
135
|
def size
|
|
112
136
|
@stashes.size
|
|
113
137
|
end
|
|
@@ -145,12 +169,24 @@ module Git
|
|
|
145
169
|
# @param index [Integer, #to_i] the stash index (0 = most recent)
|
|
146
170
|
#
|
|
147
171
|
# @return [Git::Stash, nil] the stash entry, or `nil` if the index is out of bounds
|
|
172
|
+
#
|
|
148
173
|
def [](index)
|
|
149
174
|
@stashes[index.to_i]
|
|
150
175
|
end
|
|
151
176
|
|
|
152
177
|
private
|
|
153
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
|
+
|
|
154
190
|
# Returns the facade interface for stash operations
|
|
155
191
|
#
|
|
156
192
|
# @return [Git::Repository]
|
data/lib/git/status.rb
CHANGED
|
@@ -13,6 +13,9 @@ module Git
|
|
|
13
13
|
# status.deleted.each { |path, _file| puts "Deleted: #{path}" }
|
|
14
14
|
# status.untracked.each { |path, _file| puts "Untracked: #{path}" }
|
|
15
15
|
#
|
|
16
|
+
# @deprecated Use {Git::StatusInfo}, returned by {Git::Repository#status_info},
|
|
17
|
+
# instead; this class will be removed in v6.0.0
|
|
18
|
+
#
|
|
16
19
|
# @api public
|
|
17
20
|
#
|
|
18
21
|
class Status
|
|
@@ -22,7 +25,15 @@ module Git
|
|
|
22
25
|
#
|
|
23
26
|
# @param base [Git::Repository] the git object backing this status
|
|
24
27
|
#
|
|
28
|
+
# @deprecated Use {Git::Repository#status_info} instead
|
|
29
|
+
#
|
|
25
30
|
def initialize(base)
|
|
31
|
+
if defined?(Git::Deprecation)
|
|
32
|
+
Git::Deprecation.warn(
|
|
33
|
+
'Git::Status is deprecated and will be removed in v6.0.0. ' \
|
|
34
|
+
'Use Git::Repository#status_info instead.'
|
|
35
|
+
)
|
|
36
|
+
end
|
|
26
37
|
@base = base
|
|
27
38
|
# The factory returns a hash of file paths to StatusFile objects.
|
|
28
39
|
@files = StatusFileFactory.new(base).construct_files
|
|
@@ -204,6 +215,9 @@ module Git
|
|
|
204
215
|
# Represents a single file's status in the git repository. Each instance
|
|
205
216
|
# holds information about a file's state in the index and working tree.
|
|
206
217
|
#
|
|
218
|
+
# @deprecated Use {Git::StatusFileInfo}, held by {Git::StatusInfo#files},
|
|
219
|
+
# instead; this class will be removed in v6.0.0
|
|
220
|
+
#
|
|
207
221
|
# @api public
|
|
208
222
|
#
|
|
209
223
|
class StatusFile
|