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
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'pathname'
|
|
4
|
-
require 'git/branch'
|
|
5
4
|
require 'git/branch_info'
|
|
6
|
-
require 'git/branches'
|
|
7
5
|
require 'git/commands/branch/create'
|
|
8
6
|
require 'git/commands/branch/delete'
|
|
9
7
|
require 'git/commands/branch/list'
|
|
@@ -175,6 +173,10 @@ module Git
|
|
|
175
173
|
#
|
|
176
174
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
177
175
|
#
|
|
176
|
+
# @note A refused checkout leaves HEAD, the index, and the working tree as
|
|
177
|
+
# they were, and the branch `:new_branch` or `:orphan` names is not
|
|
178
|
+
# created.
|
|
179
|
+
#
|
|
178
180
|
def checkout(branch = nil, opts = {})
|
|
179
181
|
if branch.is_a?(Hash) && opts.empty?
|
|
180
182
|
opts = branch
|
|
@@ -197,18 +199,13 @@ module Git
|
|
|
197
199
|
# checked out again. The hard reset discards changes to tracked files only;
|
|
198
200
|
# untracked files created by the block are left in place.
|
|
199
201
|
#
|
|
200
|
-
#
|
|
201
|
-
# branch
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
# any checkout happens.
|
|
208
|
-
#
|
|
209
|
-
# **Note:** the restore checkout is not wrapped in `ensure`. If the block,
|
|
210
|
-
# the commit, or the reset raises an exception, the repository is left
|
|
211
|
-
# checked out on `branch` rather than restored to the original branch.
|
|
202
|
+
# This method does not create `branch`: it must be an existing local
|
|
203
|
+
# branch. Unlike {#checkout}, a commit SHA, tag, or remote-tracking branch
|
|
204
|
+
# is rejected before any checkout happens: those detach HEAD, and a commit
|
|
205
|
+
# made there would be left dangling once the original branch is restored.
|
|
206
|
+
# HEAD must be on a branch with at least one commit, or detached: an unborn
|
|
207
|
+
# branch (no commits yet) cannot be checked out again by name, so it is
|
|
208
|
+
# rejected before any checkout happens.
|
|
212
209
|
#
|
|
213
210
|
# @example Commit a new file on a feature branch
|
|
214
211
|
# repo.in_branch('feature', 'Add README') do
|
|
@@ -242,6 +239,11 @@ module Git
|
|
|
242
239
|
# @yieldreturn [Object] a truthy value to commit all changes, a falsy value to
|
|
243
240
|
# hard-reset
|
|
244
241
|
#
|
|
242
|
+
# @note If the block, the commit, the reset, or the restore checkout raises
|
|
243
|
+
# an exception, the repository is left checked out on `branch` rather than
|
|
244
|
+
# restored to the original branch. When the restore checkout is the step
|
|
245
|
+
# that fails, the commit or reset has already run.
|
|
246
|
+
#
|
|
245
247
|
def in_branch(branch, message = 'in branch work')
|
|
246
248
|
SharedPrivate.assert_local_branch!(self, branch)
|
|
247
249
|
restore_point = SharedPrivate.head_restore_point(self)
|
|
@@ -251,6 +253,7 @@ module Git
|
|
|
251
253
|
else
|
|
252
254
|
reset(nil, hard: true)
|
|
253
255
|
end
|
|
256
|
+
# Runs only on success. See ADR-0009.
|
|
254
257
|
checkout(restore_point)
|
|
255
258
|
end
|
|
256
259
|
|
|
@@ -283,6 +286,10 @@ module Git
|
|
|
283
286
|
#
|
|
284
287
|
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
285
288
|
#
|
|
289
|
+
# @note git does not stop at the first path it cannot write, so a failure
|
|
290
|
+
# leaves the files it did write in place, under `:prefix` when one is
|
|
291
|
+
# given.
|
|
292
|
+
#
|
|
286
293
|
def checkout_index(options = {})
|
|
287
294
|
SharedPrivate.assert_valid_opts!(CHECKOUT_INDEX_ALLOWED_OPTS, **options)
|
|
288
295
|
|
|
@@ -344,71 +351,6 @@ module Git
|
|
|
344
351
|
local_branch?(branch) || remote_branch?(branch)
|
|
345
352
|
end
|
|
346
353
|
|
|
347
|
-
# Checks whether the named branch exists locally
|
|
348
|
-
#
|
|
349
|
-
# @example Check whether main exists locally
|
|
350
|
-
# repo.is_local_branch?('main') # => true
|
|
351
|
-
#
|
|
352
|
-
# @param branch [String] the local branch name to look up
|
|
353
|
-
#
|
|
354
|
-
# @return [Boolean] `true` if the branch exists locally, `false` otherwise
|
|
355
|
-
#
|
|
356
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
357
|
-
#
|
|
358
|
-
# @deprecated use {#local_branch?} instead
|
|
359
|
-
#
|
|
360
|
-
def is_local_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
361
|
-
Git::Deprecation.warn(
|
|
362
|
-
'Git::Repository#is_local_branch? is deprecated and will be removed in v6.0.0. ' \
|
|
363
|
-
'Use Git::Repository#local_branch? instead.'
|
|
364
|
-
)
|
|
365
|
-
local_branch?(branch)
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
# Checks whether the named branch exists as a remote-tracking branch
|
|
369
|
-
#
|
|
370
|
-
# @example Check whether master exists on any remote
|
|
371
|
-
# repo.is_remote_branch?('master') # => true
|
|
372
|
-
#
|
|
373
|
-
# @param branch [String] the short branch name to look up across all remotes
|
|
374
|
-
#
|
|
375
|
-
# @return [Boolean] `true` if a remote-tracking branch with that short name
|
|
376
|
-
# exists, `false` otherwise
|
|
377
|
-
#
|
|
378
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
379
|
-
#
|
|
380
|
-
# @deprecated use {#remote_branch?} instead
|
|
381
|
-
#
|
|
382
|
-
def is_remote_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
383
|
-
Git::Deprecation.warn(
|
|
384
|
-
'Git::Repository#is_remote_branch? is deprecated and will be removed in v6.0.0. ' \
|
|
385
|
-
'Use Git::Repository#remote_branch? instead.'
|
|
386
|
-
)
|
|
387
|
-
remote_branch?(branch)
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
# Checks whether the named branch exists locally or as a remote-tracking branch
|
|
391
|
-
#
|
|
392
|
-
# @example Check whether main exists anywhere
|
|
393
|
-
# repo.is_branch?('main') # => true
|
|
394
|
-
#
|
|
395
|
-
# @param branch [String] the branch name to look up
|
|
396
|
-
#
|
|
397
|
-
# @return [Boolean] `true` if the branch exists locally or remotely,
|
|
398
|
-
# `false` otherwise
|
|
399
|
-
#
|
|
400
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
401
|
-
#
|
|
402
|
-
# @deprecated use {#branch?} instead
|
|
403
|
-
#
|
|
404
|
-
def is_branch?(branch) # rubocop:disable Naming/PredicatePrefix
|
|
405
|
-
Git::Deprecation.warn(
|
|
406
|
-
'Git::Repository#is_branch? is deprecated and will be removed in v6.0.0. ' \
|
|
407
|
-
'Use Git::Repository#branch? instead.'
|
|
408
|
-
)
|
|
409
|
-
branch?(branch)
|
|
410
|
-
end
|
|
411
|
-
|
|
412
354
|
# Option keys accepted by {#branch_new}
|
|
413
355
|
#
|
|
414
356
|
BRANCH_NEW_ALLOWED_OPTS = %i[].freeze
|
|
@@ -624,30 +566,6 @@ module Git
|
|
|
624
566
|
Git::Parsers::Branch.parse_list(result.stdout, remote_names:)
|
|
625
567
|
end
|
|
626
568
|
|
|
627
|
-
# Returns all local and remote-tracking branches in the 4.x-compatible format
|
|
628
|
-
#
|
|
629
|
-
# Each entry is a 4-element array: `[refname, current, worktree, symref]`.
|
|
630
|
-
# The `refname` uses the short form (`main`, `remotes/origin/main`) to
|
|
631
|
-
# match the output of the legacy `Git::Lib#branches_all` method.
|
|
632
|
-
#
|
|
633
|
-
# @return [Array<Array>] array of `[refname, current, worktree, symref]` tuples
|
|
634
|
-
#
|
|
635
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
636
|
-
#
|
|
637
|
-
# @deprecated Use {#branch_list} instead, which returns richer
|
|
638
|
-
# {Git::BranchInfo} objects.
|
|
639
|
-
#
|
|
640
|
-
def branches_all
|
|
641
|
-
Git::Deprecation.warn(
|
|
642
|
-
'Git::Repository#branches_all is deprecated and will be removed in v6.0.0. ' \
|
|
643
|
-
'Use Git::Repository#branch_list instead.'
|
|
644
|
-
)
|
|
645
|
-
branch_list.map do |info|
|
|
646
|
-
refname = info.remote? ? "remotes/#{info.remote_name}/#{info.short_name}" : info.short_name
|
|
647
|
-
[refname, info.current, info.other_worktree?, info.symref]
|
|
648
|
-
end
|
|
649
|
-
end
|
|
650
|
-
|
|
651
569
|
# Update a branch ref to point to a new commit
|
|
652
570
|
#
|
|
653
571
|
# Derives the full ref from the `branch` argument:
|
|
@@ -683,89 +601,6 @@ module Git
|
|
|
683
601
|
Git::Commands::UpdateRef::Update.new(@execution_context).call(ref, commit)
|
|
684
602
|
end
|
|
685
603
|
|
|
686
|
-
# Returns a {Git::Branch} object for the given branch name
|
|
687
|
-
#
|
|
688
|
-
# @example Get a branch object for 'main'
|
|
689
|
-
# repo.branch('main') #=> #<Git::Branch 'main'>
|
|
690
|
-
#
|
|
691
|
-
# @example Get a branch object for the current branch
|
|
692
|
-
# repo.branch #=> #<Git::Branch 'main'>
|
|
693
|
-
#
|
|
694
|
-
# @param branch_name [String] the branch name (defaults to the current branch)
|
|
695
|
-
#
|
|
696
|
-
# @return [Git::Branch] the branch object
|
|
697
|
-
#
|
|
698
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
699
|
-
#
|
|
700
|
-
# @deprecated Use `branch_list(name).first` and the name-based branch
|
|
701
|
-
# operations instead
|
|
702
|
-
#
|
|
703
|
-
# {#branch_list} returns immutable {Git::BranchInfo} value objects
|
|
704
|
-
# rather than {Git::Branch}. It takes `git branch --list` patterns, so
|
|
705
|
-
# pass the short name of a local branch or `"#{remote}/#{name}"` for a
|
|
706
|
-
# remote-tracking branch; the `remotes/` and `refs/` prefixes this
|
|
707
|
-
# method accepts match nothing. A `"#{remote}/#{name}"` pattern also
|
|
708
|
-
# matches a local branch of that name, so take `find(&:remote?)` rather
|
|
709
|
-
# than `first` for a remote-tracking branch. With no argument this
|
|
710
|
-
# method wraps {#current_branch}, which is `'HEAD'` when HEAD is
|
|
711
|
-
# detached; {#branch_list} has no entry for a detached or unborn HEAD,
|
|
712
|
-
# so use {#current_branch_state} in those states. Call the
|
|
713
|
-
# corresponding {Git::Repository} method (e.g. {#checkout},
|
|
714
|
-
# {#branch_new}, {#branch_delete}) for operations on a branch.
|
|
715
|
-
#
|
|
716
|
-
# @see #branch_list
|
|
717
|
-
#
|
|
718
|
-
def branch(branch_name = current_branch)
|
|
719
|
-
Git::Deprecation.warn(
|
|
720
|
-
'Git::Repository#branch is deprecated and will be removed in v6.0.0. ' \
|
|
721
|
-
'Use Git::Repository#branch_list(name).first for a local branch, ' \
|
|
722
|
-
'Git::Repository#branch_list("remote/name").find(&:remote?) for a remote-tracking branch, ' \
|
|
723
|
-
'and the name-based branch operations instead.'
|
|
724
|
-
)
|
|
725
|
-
Git::Branch.new(self, branch_name)
|
|
726
|
-
end
|
|
727
|
-
|
|
728
|
-
# Returns a {Git::Branches} collection of all branches in the repository
|
|
729
|
-
#
|
|
730
|
-
# @example List all branches
|
|
731
|
-
# repo.branches
|
|
732
|
-
# # => #<Git::Branches ...>
|
|
733
|
-
#
|
|
734
|
-
# @example Iterate over all branches
|
|
735
|
-
# repo.branches.each { |b| puts b.name }
|
|
736
|
-
#
|
|
737
|
-
# @example Access local branches only
|
|
738
|
-
# repo.branches.local
|
|
739
|
-
#
|
|
740
|
-
# @example Access remote-tracking branches only
|
|
741
|
-
# repo.branches.remote
|
|
742
|
-
#
|
|
743
|
-
# @example Look up a branch by name
|
|
744
|
-
# repo.branches['main'] # => #<Git::Branch 'main'>
|
|
745
|
-
#
|
|
746
|
-
# @return [Git::Branches] a collection wrapping all local and
|
|
747
|
-
# remote-tracking branches in the repository
|
|
748
|
-
#
|
|
749
|
-
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
750
|
-
#
|
|
751
|
-
# @deprecated Use {#branch_list} instead
|
|
752
|
-
#
|
|
753
|
-
# {#branch_list} returns `Array<Git::BranchInfo>` (immutable value
|
|
754
|
-
# objects) rather than a {Git::Branches} collection. Filter it with
|
|
755
|
-
# `select(&:remote?)` or `reject(&:remote?)` in place of
|
|
756
|
-
# `branches.remote` and `branches.local`, and look a branch up by name
|
|
757
|
-
# with `branch_list(name).first` in place of `branches[name]`.
|
|
758
|
-
#
|
|
759
|
-
# @see #branch_list
|
|
760
|
-
#
|
|
761
|
-
def branches
|
|
762
|
-
Git::Deprecation.warn(
|
|
763
|
-
'Git::Repository#branches is deprecated and will be removed in v6.0.0. ' \
|
|
764
|
-
'Use Git::Repository#branch_list instead.'
|
|
765
|
-
)
|
|
766
|
-
Git::Branches.new(self)
|
|
767
|
-
end
|
|
768
|
-
|
|
769
604
|
# Private helpers local to {Git::Repository::Branching}
|
|
770
605
|
#
|
|
771
606
|
# @api private
|
|
@@ -939,9 +774,6 @@ module Git
|
|
|
939
774
|
|
|
940
775
|
# Builds the full git ref string from a branch name argument
|
|
941
776
|
#
|
|
942
|
-
# Mirrors the routing logic of `Git::Branch#update_ref` for backward
|
|
943
|
-
# compatibility:
|
|
944
|
-
#
|
|
945
777
|
# - `remotes/<remote>/<name>` or `refs/remotes/<remote>/<name>` →
|
|
946
778
|
# `refs/remotes/<remote>/<name>`
|
|
947
779
|
# - Any other value → `refs/heads/<branch>`
|
|
@@ -73,7 +73,6 @@ 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 = normalize_commit_options(opts)
|
|
77
76
|
SharedPrivate.assert_valid_opts!(COMMIT_ALLOWED_OPTS, **opts)
|
|
78
77
|
|
|
79
78
|
call_opts = { no_edit: true }
|
|
@@ -217,30 +216,6 @@ module Git
|
|
|
217
216
|
def write_and_commit_tree(opts = {})
|
|
218
217
|
commit_tree(write_tree, opts)
|
|
219
218
|
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
|
|
244
219
|
end
|
|
245
220
|
end
|
|
246
221
|
end
|