git 5.7.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 -35
- data/CONTRIBUTING.md +44 -31
- data/README.md +138 -100
- data/UPGRADING.md +867 -262
- 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 +1 -1
- data/lib/git/encoding_utils.rb +25 -0
- data/lib/git/errors.rb +24 -18
- 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 -72
- data/lib/git/repository/merging.rb +32 -54
- data/lib/git/repository/object_operations.rb +120 -497
- 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 +30 -125
- 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 +24 -18
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'git/commands/rev_parse'
|
|
3
4
|
require 'git/commands/stash'
|
|
4
5
|
require 'git/parsers/stash'
|
|
5
6
|
require 'git/repository/shared_private'
|
|
@@ -9,7 +10,7 @@ module Git
|
|
|
9
10
|
# Facade methods for stash operations
|
|
10
11
|
#
|
|
11
12
|
# Each method maps onto a `git stash` subcommand. Methods that identify or
|
|
12
|
-
# create a stash entry ({#
|
|
13
|
+
# create a stash entry ({#stash_list}, {#stash_push}, {#stash_store}) return
|
|
13
14
|
# {Git::StashInfo} values; methods that only change or display the stash
|
|
14
15
|
# return git's stdout. Every method that takes a stash ({#stash_apply},
|
|
15
16
|
# {#stash_pop}, {#stash_drop}, {#stash_show}, {#stash_branch}) accepts a
|
|
@@ -19,9 +20,6 @@ module Git
|
|
|
19
20
|
# `repo.stash_apply(index: true)` and `repo.stash_apply(nil, opts)` with a
|
|
20
21
|
# stored `opts` Hash both work.
|
|
21
22
|
#
|
|
22
|
-
# {#stashes_all}, {#stash_save}, and {#stash_list} are the legacy surface.
|
|
23
|
-
# They are deprecated and will be removed in v6.0.0.
|
|
24
|
-
#
|
|
25
23
|
# Included by {Git::Repository}.
|
|
26
24
|
#
|
|
27
25
|
# @api private
|
|
@@ -33,10 +31,10 @@ module Git
|
|
|
33
31
|
# `stash@{0}`, the most recent entry.
|
|
34
32
|
#
|
|
35
33
|
# @example List stash entries (newest first)
|
|
36
|
-
# repo.
|
|
34
|
+
# repo.stash_list.map(&:name) #=> ["stash@{0}", "stash@{1}"]
|
|
37
35
|
#
|
|
38
36
|
# @example Apply the oldest entry
|
|
39
|
-
# repo.stash_apply(repo.
|
|
37
|
+
# repo.stash_apply(repo.stash_list.last)
|
|
40
38
|
#
|
|
41
39
|
# @return [Array<Git::StashInfo>] the stash entries, newest first; empty
|
|
42
40
|
# when there are none
|
|
@@ -45,11 +43,16 @@ module Git
|
|
|
45
43
|
#
|
|
46
44
|
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
47
45
|
#
|
|
48
|
-
def
|
|
46
|
+
def stash_list
|
|
49
47
|
result = Git::Commands::Stash::List.new(@execution_context).call
|
|
50
48
|
Git::Parsers::Stash.parse_list(result.stdout)
|
|
51
49
|
end
|
|
52
50
|
|
|
51
|
+
# Alias for {#stash_list}
|
|
52
|
+
#
|
|
53
|
+
# @see #stash_list
|
|
54
|
+
alias stash_infos stash_list
|
|
55
|
+
|
|
53
56
|
# Option keys accepted by {#stash_push}
|
|
54
57
|
STASH_PUSH_ALLOWED_OPTS = %i[
|
|
55
58
|
patch p staged S keep_index k no_keep_index quiet q include_untracked u all a
|
|
@@ -88,10 +91,9 @@ module Git
|
|
|
88
91
|
# @option options [Boolean, nil] :p (nil) alias for `:patch`
|
|
89
92
|
#
|
|
90
93
|
# @option options [Boolean, nil] :staged (nil) stash only the staged changes
|
|
91
|
-
# (alias: `:S
|
|
94
|
+
# (alias: `:S`)
|
|
92
95
|
#
|
|
93
|
-
# @option options [Boolean, nil] :S (nil) alias for `:staged`
|
|
94
|
-
# 2.35+)
|
|
96
|
+
# @option options [Boolean, nil] :S (nil) alias for `:staged`
|
|
95
97
|
#
|
|
96
98
|
# @option options [Boolean, nil] :keep_index (nil) keep the staged changes
|
|
97
99
|
# in the index (alias: `:k`)
|
|
@@ -138,9 +140,9 @@ module Git
|
|
|
138
140
|
def stash_push(*pathspec)
|
|
139
141
|
pathspec, opts = Private.split_pathspec_and_opts(pathspec)
|
|
140
142
|
SharedPrivate.assert_valid_opts!(STASH_PUSH_ALLOWED_OPTS, **opts)
|
|
141
|
-
previous_count =
|
|
143
|
+
previous_count = stash_list.size
|
|
142
144
|
Git::Commands::Stash::Push.new(@execution_context).call(*pathspec, **opts)
|
|
143
|
-
entries =
|
|
145
|
+
entries = stash_list
|
|
144
146
|
entries.first if entries.size > previous_count
|
|
145
147
|
end
|
|
146
148
|
|
|
@@ -153,8 +155,8 @@ module Git
|
|
|
153
155
|
# @example Apply the most recent entry
|
|
154
156
|
# repo.stash_apply #=> "On branch main\nChanges not staged for commit:..."
|
|
155
157
|
#
|
|
156
|
-
# @example Apply an entry from {#
|
|
157
|
-
# repo.stash_apply(repo.
|
|
158
|
+
# @example Apply an entry from {#stash_list}
|
|
159
|
+
# repo.stash_apply(repo.stash_list.last)
|
|
158
160
|
#
|
|
159
161
|
# @example Apply an entry by name and restore the index too
|
|
160
162
|
# repo.stash_apply('stash@{1}', index: true)
|
|
@@ -179,6 +181,11 @@ module Git
|
|
|
179
181
|
#
|
|
180
182
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
181
183
|
#
|
|
184
|
+
# @note If git exits non-zero, nothing is unwound: whatever git applied stays
|
|
185
|
+
# in the working tree and index, including untracked files restored from
|
|
186
|
+
# the entry even when git refused to touch the tracked files, and on a
|
|
187
|
+
# conflict the conflicted paths are left for the caller to resolve.
|
|
188
|
+
#
|
|
182
189
|
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
183
190
|
#
|
|
184
191
|
def stash_apply(stash = nil, opts = {})
|
|
@@ -196,8 +203,8 @@ module Git
|
|
|
196
203
|
# @example Pop the most recent entry
|
|
197
204
|
# repo.stash_pop #=> "On branch main\n...Dropped refs/stash@{0} (abc1234...)"
|
|
198
205
|
#
|
|
199
|
-
# @example Pop an entry from {#
|
|
200
|
-
# repo.stash_pop(repo.
|
|
206
|
+
# @example Pop an entry from {#stash_list}
|
|
207
|
+
# repo.stash_pop(repo.stash_list.last)
|
|
201
208
|
#
|
|
202
209
|
# @param stash [Git::StashInfo, String, Integer, nil] the entry to pop: a
|
|
203
210
|
# {Git::StashInfo}, a `stash@{N}` name, an Integer `N` (`0` is the most
|
|
@@ -219,6 +226,10 @@ module Git
|
|
|
219
226
|
#
|
|
220
227
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
221
228
|
#
|
|
229
|
+
# @note If git exits non-zero, nothing is unwound, as described at
|
|
230
|
+
# {#stash_apply}, and the entry is kept in the stash list rather than
|
|
231
|
+
# dropped.
|
|
232
|
+
#
|
|
222
233
|
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
223
234
|
#
|
|
224
235
|
def stash_pop(stash = nil, opts = {})
|
|
@@ -236,8 +247,8 @@ module Git
|
|
|
236
247
|
# @example Drop the most recent entry
|
|
237
248
|
# repo.stash_drop #=> "Dropped refs/stash@{0} (abc1234...)"
|
|
238
249
|
#
|
|
239
|
-
# @example Drop an entry from {#
|
|
240
|
-
# repo.stash_drop(repo.
|
|
250
|
+
# @example Drop an entry from {#stash_list}
|
|
251
|
+
# repo.stash_drop(repo.stash_list.last)
|
|
241
252
|
#
|
|
242
253
|
# @param stash [Git::StashInfo, String, Integer, nil] the entry to drop: a
|
|
243
254
|
# {Git::StashInfo}, a `stash@{N}` name, an Integer `N` (`0` is the most
|
|
@@ -279,8 +290,8 @@ module Git
|
|
|
279
290
|
# @example Show the diffstat of the most recent entry
|
|
280
291
|
# repo.stash_show #=> " file.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)"
|
|
281
292
|
#
|
|
282
|
-
# @example Show the full patch of an entry from {#
|
|
283
|
-
# repo.stash_show(repo.
|
|
293
|
+
# @example Show the full patch of an entry from {#stash_list}
|
|
294
|
+
# repo.stash_show(repo.stash_list.last, patch: true)
|
|
284
295
|
#
|
|
285
296
|
# @param stash [Git::StashInfo, String, Integer, nil] the entry to show: a
|
|
286
297
|
# {Git::StashInfo}, a `stash@{N}` name, an Integer `N` (`0` is the most
|
|
@@ -304,16 +315,15 @@ module Git
|
|
|
304
315
|
# @option opts [Integer, String] :U (nil) alias for `:unified`
|
|
305
316
|
#
|
|
306
317
|
# @option opts [Boolean, nil] :include_untracked (nil) include the
|
|
307
|
-
# untracked files recorded in the entry (alias: `:u
|
|
318
|
+
# untracked files recorded in the entry (alias: `:u`)
|
|
308
319
|
#
|
|
309
320
|
# @option opts [Boolean, nil] :u (nil) alias for `:include_untracked`
|
|
310
|
-
# (requires git 2.30+)
|
|
311
321
|
#
|
|
312
322
|
# @option opts [Boolean, nil] :no_include_untracked (nil) exclude the
|
|
313
|
-
# untracked files recorded in the entry
|
|
323
|
+
# untracked files recorded in the entry
|
|
314
324
|
#
|
|
315
325
|
# @option opts [Boolean, nil] :only_untracked (nil) show only the
|
|
316
|
-
# untracked files recorded in the entry
|
|
326
|
+
# untracked files recorded in the entry
|
|
317
327
|
#
|
|
318
328
|
# @option opts [Boolean, Integer, nil] :find_renames (nil) detect
|
|
319
329
|
# renames, optionally with a similarity threshold (alias: `:M`)
|
|
@@ -356,8 +366,8 @@ module Git
|
|
|
356
366
|
# @example Branch from the most recent entry
|
|
357
367
|
# repo.stash_branch('feature') #=> "Switched to a new branch 'feature'\n..."
|
|
358
368
|
#
|
|
359
|
-
# @example Branch from an entry from {#
|
|
360
|
-
# repo.stash_branch('feature', repo.
|
|
369
|
+
# @example Branch from an entry from {#stash_list}
|
|
370
|
+
# repo.stash_branch('feature', repo.stash_list.last)
|
|
361
371
|
#
|
|
362
372
|
# @param branch_name [String] the name of the branch to create
|
|
363
373
|
#
|
|
@@ -369,6 +379,10 @@ module Git
|
|
|
369
379
|
#
|
|
370
380
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
371
381
|
#
|
|
382
|
+
# @note If applying the entry fails, `branch_name` has already been created
|
|
383
|
+
# and checked out, so the repository is left on it with whatever git could
|
|
384
|
+
# apply in the working tree, and the entry stays in the stash list.
|
|
385
|
+
#
|
|
372
386
|
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
373
387
|
#
|
|
374
388
|
def stash_branch(branch_name, stash = nil)
|
|
@@ -407,7 +421,13 @@ module Git
|
|
|
407
421
|
|
|
408
422
|
# Add a stash commit created by {#stash_create} to the stash list
|
|
409
423
|
#
|
|
410
|
-
#
|
|
424
|
+
# `commit` is resolved to the full object id of the commit with
|
|
425
|
+
# `git rev-parse` and that id is what is stored, so an annotated tag stores
|
|
426
|
+
# the tagged commit rather than the tag object (which `git stash store`
|
|
427
|
+
# accepts but `git stash list` cannot show). Because the id is what git
|
|
428
|
+
# sees, a failure from `git stash store` names the resolved id rather than
|
|
429
|
+
# the revision as it was given. The stash list is read after the store and
|
|
430
|
+
# the entry whose object id equals that id is returned.
|
|
411
431
|
#
|
|
412
432
|
# @example Store a stash commit
|
|
413
433
|
# oid = repo.stash_create
|
|
@@ -415,7 +435,17 @@ module Git
|
|
|
415
435
|
# info.name #=> "stash@{0}"
|
|
416
436
|
# info.message #=> "saved for later"
|
|
417
437
|
#
|
|
418
|
-
# @
|
|
438
|
+
# @example Store a stash commit named by a ref
|
|
439
|
+
# repo.stash_store('refs/tmp/wip').oid #=> "9b9b31e704c0b85ffdd8d2af2ded85170a5af87d"
|
|
440
|
+
#
|
|
441
|
+
# @param commit [String, #to_s] the stash commit to store, as any revision
|
|
442
|
+
# that resolves to it
|
|
443
|
+
#
|
|
444
|
+
# Full or abbreviated object ids, branch, tag, and other ref names,
|
|
445
|
+
# `stash@{N}`, and `:/<text>` searches all resolve with `git rev-parse`,
|
|
446
|
+
# and a {Git::StashInfo} resolves through its `#to_s`. A `:/<text>` search
|
|
447
|
+
# finds only commits reachable from a ref, so it cannot name a commit from
|
|
448
|
+
# {#stash_create} until that commit is stored or a ref points at it.
|
|
419
449
|
#
|
|
420
450
|
# @param opts [Hash] options for the store
|
|
421
451
|
#
|
|
@@ -429,18 +459,34 @@ module Git
|
|
|
429
459
|
#
|
|
430
460
|
# @option opts [Boolean, nil] :q (nil) alias for `:quiet`
|
|
431
461
|
#
|
|
432
|
-
# @return [Git::StashInfo] the stored entry
|
|
462
|
+
# @return [Git::StashInfo] the stored entry
|
|
433
463
|
#
|
|
434
464
|
# @raise [ArgumentError] if unsupported options are provided
|
|
435
465
|
#
|
|
466
|
+
# @raise [ArgumentError] if `commit` is `nil` or starts with a hyphen or a
|
|
467
|
+
# caret
|
|
468
|
+
#
|
|
436
469
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
437
470
|
#
|
|
471
|
+
# @raise [Git::UnexpectedResultError] if the stash listing cannot be parsed
|
|
472
|
+
# or does not contain the stored commit
|
|
473
|
+
#
|
|
474
|
+
# The entry is missing when another process dropped or cleared it between
|
|
475
|
+
# the store and the lookup.
|
|
476
|
+
#
|
|
477
|
+
# @note Storing the commit that is already at the top of the stash list
|
|
478
|
+
# adds no entry: `git stash store` writes nothing to the `refs/stash`
|
|
479
|
+
# reflog, any `:message` given is discarded, and the existing top entry
|
|
480
|
+
# is returned.
|
|
481
|
+
#
|
|
438
482
|
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
439
483
|
#
|
|
440
484
|
def stash_store(commit, opts = {})
|
|
441
485
|
SharedPrivate.assert_valid_opts!(STASH_STORE_ALLOWED_OPTS, **opts)
|
|
442
|
-
|
|
443
|
-
|
|
486
|
+
oid = Private.resolve_commit_oid(@execution_context, commit)
|
|
487
|
+
Git::Commands::Stash::Store.new(@execution_context).call(oid, **opts)
|
|
488
|
+
stash_list.find { |entry| entry.oid == oid } ||
|
|
489
|
+
raise(Git::UnexpectedResultError, "stash was stored but not found in the stash list: #{oid}")
|
|
444
490
|
end
|
|
445
491
|
|
|
446
492
|
# Remove all stash entries
|
|
@@ -462,105 +508,6 @@ module Git
|
|
|
462
508
|
Git::Commands::Stash::Clear.new(@execution_context).call.stdout
|
|
463
509
|
end
|
|
464
510
|
|
|
465
|
-
# Returns all stash entries as an array of index and message pairs
|
|
466
|
-
#
|
|
467
|
-
# Lists all stash entries in the repository ordered from oldest to newest.
|
|
468
|
-
# The index is a sequential number starting from 0 for the oldest stash. The
|
|
469
|
-
# message is the stash description with the leading branch prefix (e.g.
|
|
470
|
-
# `"On main:"` or `"WIP on main:"`) stripped.
|
|
471
|
-
#
|
|
472
|
-
# @example List all stashes (oldest first)
|
|
473
|
-
# repo.stashes_all #=> [[0, "Fix bug"], [1, "Add feature"]]
|
|
474
|
-
#
|
|
475
|
-
# @return [Array<Array(Integer, String)>] array of `[index, message]` pairs
|
|
476
|
-
# where index is the sequential position (0 is oldest) and message is the
|
|
477
|
-
# stash description with the branch prefix stripped
|
|
478
|
-
#
|
|
479
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
480
|
-
#
|
|
481
|
-
# @note The sequential index returned here is **not** the same as git's
|
|
482
|
-
# `stash@{N}` reference used by {#stash_apply}. In git, `stash@{0}` is the
|
|
483
|
-
# **most recent** stash, while index `0` here is the **oldest**. To apply a
|
|
484
|
-
# specific stash from this list, convert the entry's position to a git
|
|
485
|
-
# reference: `'stash@{%d}' % (total - 1 - index)`, or pass the string
|
|
486
|
-
# reference directly to {#stash_apply}.
|
|
487
|
-
#
|
|
488
|
-
# @deprecated Use {#stash_infos} instead. It returns {Git::StashInfo} entries
|
|
489
|
-
# newest first with git's own `stash@{N}` indices and the full message.
|
|
490
|
-
# This method will be removed in v6.0.0.
|
|
491
|
-
#
|
|
492
|
-
# @see #stash_infos
|
|
493
|
-
#
|
|
494
|
-
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
495
|
-
#
|
|
496
|
-
def stashes_all
|
|
497
|
-
Git::Deprecation.warn(
|
|
498
|
-
'Git::Repository#stashes_all is deprecated and will be removed in v6.0.0. ' \
|
|
499
|
-
'Use Git::Repository#stash_infos instead.'
|
|
500
|
-
)
|
|
501
|
-
stash_infos.reverse.each_with_index.map do |info, i|
|
|
502
|
-
message = info.message.sub(/^(?:WIP on|On)\s+[^:]+:\s*/, '')
|
|
503
|
-
[i, message]
|
|
504
|
-
end
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
# Returns stash entries as a formatted string matching `git stash list` output
|
|
508
|
-
#
|
|
509
|
-
# @example List stashes as a formatted string
|
|
510
|
-
# repo.stash_list #=> "stash@{0}: On main: WIP\nstash@{1}: On feature: Fix bug"
|
|
511
|
-
#
|
|
512
|
-
# @return [String] newline-joined `"stash@{n}: <full message>"` entries, or an
|
|
513
|
-
# empty string when there are no stashes; the format matches `git stash list`
|
|
514
|
-
# output
|
|
515
|
-
#
|
|
516
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
517
|
-
#
|
|
518
|
-
# @deprecated Use {#stash_infos} instead and format the entries yourself:
|
|
519
|
-
# `repo.stash_infos.map { |s| "#{s.name}: #{s.message}" }.join("\n")`.
|
|
520
|
-
# This method will be removed in v6.0.0, and a later release will reuse
|
|
521
|
-
# the name for a method returning `Array<Git::StashInfo>`.
|
|
522
|
-
#
|
|
523
|
-
# @see #stash_infos
|
|
524
|
-
#
|
|
525
|
-
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
526
|
-
#
|
|
527
|
-
def stash_list
|
|
528
|
-
Git::Deprecation.warn(
|
|
529
|
-
'Git::Repository#stash_list is deprecated and will be removed in v6.0.0. ' \
|
|
530
|
-
'Use Git::Repository#stash_infos instead.'
|
|
531
|
-
)
|
|
532
|
-
stash_infos.map { |info| "#{info.name}: #{info.message}" }.join("\n")
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
# Save the current working directory and index state to a new stash
|
|
536
|
-
#
|
|
537
|
-
# @example Save current changes
|
|
538
|
-
# repo.stash_save('WIP: feature work') #=> true
|
|
539
|
-
#
|
|
540
|
-
# @param message [String] the stash message
|
|
541
|
-
#
|
|
542
|
-
# @return [Boolean] true if changes were stashed, false if there were no
|
|
543
|
-
# local changes to save
|
|
544
|
-
#
|
|
545
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
546
|
-
#
|
|
547
|
-
# @deprecated Use {#stash_push} with the `:message` option instead. It
|
|
548
|
-
# returns the new {Git::StashInfo}, or `nil` when there were no local
|
|
549
|
-
# changes to save. This method will be removed in v6.0.0.
|
|
550
|
-
#
|
|
551
|
-
# @see #stash_push
|
|
552
|
-
#
|
|
553
|
-
# @see https://git-scm.com/docs/git-stash git-stash documentation
|
|
554
|
-
#
|
|
555
|
-
def stash_save(message) # rubocop:disable Naming/PredicateMethod
|
|
556
|
-
Git::Deprecation.warn(
|
|
557
|
-
'Git::Repository#stash_save is deprecated and will be removed in v6.0.0. ' \
|
|
558
|
-
'Use Git::Repository#stash_push(message: ...) instead.'
|
|
559
|
-
)
|
|
560
|
-
result = Git::Commands::Stash::Push.new(@execution_context).call(message: message)
|
|
561
|
-
!result.stdout.include?('No local changes to save')
|
|
562
|
-
end
|
|
563
|
-
|
|
564
511
|
# Private helpers local to {Git::Repository::Stashing}
|
|
565
512
|
#
|
|
566
513
|
# @api private
|
|
@@ -568,6 +515,55 @@ module Git
|
|
|
568
515
|
module Private
|
|
569
516
|
module_function
|
|
570
517
|
|
|
518
|
+
# Resolve a commit-ish to the full object id of the commit it names
|
|
519
|
+
#
|
|
520
|
+
# The revision is peeled with `git rev-parse --verify <commit>^{commit}`,
|
|
521
|
+
# so an annotated tag yields the tagged commit, an abbreviated or uppercase
|
|
522
|
+
# id yields the full lowercase id, and an id that names no object fails
|
|
523
|
+
# (a bare `--verify <id>` echoes a well-formed id back without looking it
|
|
524
|
+
# up). A `:/<text>` search consumes the rest of the revision string, so it
|
|
525
|
+
# is passed without the suffix; such a search only ever names a commit.
|
|
526
|
+
# {Git::Repository::ObjectOperations#rev_parse} is not used because it
|
|
527
|
+
# runs `--revs-only`, which prints both ends of a range and exits zero
|
|
528
|
+
# instead of failing.
|
|
529
|
+
#
|
|
530
|
+
# {Git::Commands::RevParse} places its operand after `--end-of-options`,
|
|
531
|
+
# so the arguments DSL does not reject a `nil` or option-like operand, and
|
|
532
|
+
# `--verify` accepts a negated revision such as `^HEAD` and prints the id
|
|
533
|
+
# back with its caret. This method raises `ArgumentError` for all three
|
|
534
|
+
# before running git.
|
|
535
|
+
#
|
|
536
|
+
# @example With an annotated tag
|
|
537
|
+
# Private.resolve_commit_oid(execution_context, 'v1.0.0')
|
|
538
|
+
# #=> "9b9b31e704c0b85ffdd8d2af2ded85170a5af87d"
|
|
539
|
+
#
|
|
540
|
+
# @example With a range
|
|
541
|
+
# Private.resolve_commit_oid(execution_context, 'main..topic')
|
|
542
|
+
# #=> raises Git::FailedError
|
|
543
|
+
#
|
|
544
|
+
# @param execution_context [Git::ExecutionContext] the context to run git in
|
|
545
|
+
#
|
|
546
|
+
# @param commit [String, #to_s] a revision that resolves to a commit or
|
|
547
|
+
# peels to one
|
|
548
|
+
#
|
|
549
|
+
# @return [String] the full object id of the commit
|
|
550
|
+
#
|
|
551
|
+
# @raise [ArgumentError] if `commit` is `nil` or starts with a hyphen or a
|
|
552
|
+
# caret
|
|
553
|
+
#
|
|
554
|
+
# @raise [Git::FailedError] when `commit` does not resolve to a single
|
|
555
|
+
# revision or does not peel to a commit
|
|
556
|
+
#
|
|
557
|
+
def resolve_commit_oid(execution_context, commit)
|
|
558
|
+
raise ArgumentError, 'commit is required' if commit.nil?
|
|
559
|
+
|
|
560
|
+
commit = commit.to_s
|
|
561
|
+
raise ArgumentError, "Invalid commit: '#{commit}'" if commit.start_with?('-', '^')
|
|
562
|
+
|
|
563
|
+
revision = commit.start_with?(':/') ? commit : "#{commit}^{commit}"
|
|
564
|
+
Git::Commands::RevParse.new(execution_context).call(revision, verify: true).stdout.strip
|
|
565
|
+
end
|
|
566
|
+
|
|
571
567
|
# Separate the stash operand from a positional options Hash
|
|
572
568
|
#
|
|
573
569
|
# The stash-taking facade methods are declared `(stash = nil, opts = {})`.
|
|
@@ -5,7 +5,6 @@ require 'git/commands/rev_parse'
|
|
|
5
5
|
require 'git/commands/status'
|
|
6
6
|
require 'git/escaped_path'
|
|
7
7
|
require 'git/parsers/status'
|
|
8
|
-
require 'git/status'
|
|
9
8
|
require 'git/status_info'
|
|
10
9
|
|
|
11
10
|
module Git
|
|
@@ -46,27 +45,6 @@ module Git
|
|
|
46
45
|
true
|
|
47
46
|
end
|
|
48
47
|
|
|
49
|
-
# Returns `true` if the repository has no commits yet
|
|
50
|
-
#
|
|
51
|
-
# @example Check whether a repository is empty
|
|
52
|
-
# repo.empty? #=> true # freshly initialized, no commits yet
|
|
53
|
-
# repo.empty? #=> false # at least one commit exists
|
|
54
|
-
#
|
|
55
|
-
# @return [Boolean] `true` when the repository has no commits, `false` otherwise
|
|
56
|
-
#
|
|
57
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status other
|
|
58
|
-
# than when the repository has no commits
|
|
59
|
-
#
|
|
60
|
-
# @deprecated Use {#no_commits?} instead
|
|
61
|
-
#
|
|
62
|
-
def empty?
|
|
63
|
-
Git::Deprecation.warn(
|
|
64
|
-
'Git::Repository#empty? is deprecated and will be removed in v6.0.0. ' \
|
|
65
|
-
'Use Git::Repository#no_commits? instead.'
|
|
66
|
-
)
|
|
67
|
-
no_commits?
|
|
68
|
-
end
|
|
69
|
-
|
|
70
48
|
# List all files in the working tree that are not tracked by git
|
|
71
49
|
#
|
|
72
50
|
# Runs `git ls-files --others --exclude-standard` from the working tree
|
|
@@ -98,8 +76,7 @@ module Git
|
|
|
98
76
|
# way git does in this repository. Every entry type git reports is
|
|
99
77
|
# represented, including renames, copies, and merge conflicts. Clean
|
|
100
78
|
# tracked paths are not reported by `git status`, so they are absent from
|
|
101
|
-
# the result;
|
|
102
|
-
# does.
|
|
79
|
+
# the result; {#ls_files} lists them.
|
|
103
80
|
#
|
|
104
81
|
# @example Check which files are modified
|
|
105
82
|
# repo.status_info.changed
|
|
@@ -131,36 +108,6 @@ module Git
|
|
|
131
108
|
Git::StatusInfo.new(files: files, ignore_case: ignore_case)
|
|
132
109
|
end
|
|
133
110
|
|
|
134
|
-
# Returns a {Git::Status} object describing the working tree and index state
|
|
135
|
-
#
|
|
136
|
-
# Constructs a {Git::Status} for this repository by collecting information from
|
|
137
|
-
# `git ls-files --stage`, `git ls-files --others`, `git diff-files`, and
|
|
138
|
-
# `git diff-index HEAD` (the last only when at least one commit exists). The
|
|
139
|
-
# result identifies which files have been modified, added, deleted, or are
|
|
140
|
-
# untracked.
|
|
141
|
-
#
|
|
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.
|
|
144
|
-
#
|
|
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"]
|
|
148
|
-
#
|
|
149
|
-
# @return [Git::Status] the status of the repository
|
|
150
|
-
#
|
|
151
|
-
# @raise [Git::FailedError] if any underlying git command exits with a
|
|
152
|
-
# non-zero exit status
|
|
153
|
-
#
|
|
154
|
-
# @deprecated Use {#status_info} instead
|
|
155
|
-
#
|
|
156
|
-
def status
|
|
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) }
|
|
162
|
-
end
|
|
163
|
-
|
|
164
111
|
# List all files tracked in the index
|
|
165
112
|
#
|
|
166
113
|
# Runs `git ls-files --stage` under the given `location` and returns a
|