git 5.0.0.beta.3 → 5.0.0.beta.5
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/.dockerignore +27 -0
- data/.github/copilot-instructions.md +3 -8
- data/.github/hooks/bin-setup-on-worktree.json +11 -0
- data/.github/hooks/run-bin-setup-once.sh +14 -0
- data/.github/skills/breaking-change-analysis/SKILL.md +6 -9
- data/.github/skills/ci-cd-troubleshooting/SKILL.md +2 -2
- data/.github/skills/command-implementation/REFERENCE.md +34 -33
- data/.github/skills/command-implementation/SKILL.md +5 -4
- data/.github/skills/command-test-conventions/SKILL.md +13 -9
- data/.github/skills/command-yard-documentation/SKILL.md +14 -6
- data/.github/skills/development-workflow/SKILL.md +20 -14
- data/.github/skills/facade-implementation/REFERENCE.md +19 -22
- data/.github/skills/facade-implementation/SKILL.md +0 -5
- data/.github/skills/facade-test-conventions/SKILL.md +4 -7
- data/.github/skills/facade-yard-documentation/SKILL.md +8 -2
- data/.github/skills/make-skill-template/SKILL.md +53 -3
- data/.github/skills/pr-readiness-review/SKILL.md +22 -2
- data/.github/skills/project-context/SKILL.md +16 -23
- data/.github/skills/pull-request-review/SKILL.md +2 -2
- data/.github/skills/rebase/SKILL.md +148 -0
- data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +1 -1
- data/.github/skills/resolve-feedback/SKILL.md +288 -0
- data/.github/skills/review-arguments-dsl/CHECKLIST.md +3 -3
- data/.github/skills/reviewing-skills/SKILL.md +28 -3
- data/.github/skills/test-debugging/SKILL.md +20 -19
- data/.github/skills/yard-documentation/SKILL.md +671 -483
- data/.github/skills/yard-documentation/element-rules.md +162 -0
- data/.github/skills-deprecated/README.md +21 -0
- data/.github/{skills → skills-deprecated}/extract-command-from-lib/SKILL.md +9 -9
- data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/SKILL.md +12 -12
- data/.github/workflows/continuous_integration.yml +3 -2
- data/.rubocop.yml +7 -39
- data/.yard-lint.yml +75 -0
- data/CONTRIBUTING.md +186 -174
- data/Gemfile +17 -0
- data/README.md +79 -12
- data/Rakefile +3 -21
- data/UPGRADING.md +268 -70
- data/docker/test/Dockerfile +32 -0
- data/docker/test/docker-compose.yml +0 -0
- data/git.gemspec +3 -4
- data/lib/git/author.rb +20 -1
- data/lib/git/branch.rb +26 -6
- data/lib/git/branch_delete_failure.rb +3 -0
- data/lib/git/branch_delete_result.rb +6 -3
- data/lib/git/branch_info.rb +6 -6
- data/lib/git/command_line/base.rb +6 -13
- data/lib/git/command_line/capturing.rb +67 -10
- data/lib/git/command_line/result.rb +0 -8
- data/lib/git/command_line/streaming.rb +45 -5
- data/lib/git/command_line.rb +4 -3
- data/lib/git/commands/add.rb +61 -53
- data/lib/git/commands/am/abort.rb +2 -2
- data/lib/git/commands/am/apply.rb +109 -98
- data/lib/git/commands/am/continue.rb +2 -2
- data/lib/git/commands/am/quit.rb +2 -2
- data/lib/git/commands/am/retry.rb +4 -2
- data/lib/git/commands/am/show_current_patch.rb +1 -1
- data/lib/git/commands/am/skip.rb +2 -2
- data/lib/git/commands/am.rb +2 -2
- data/lib/git/commands/apply.rb +7 -2
- data/lib/git/commands/archive/list_formats.rb +3 -3
- data/lib/git/commands/archive.rb +7 -2
- data/lib/git/commands/arguments.rb +1370 -359
- data/lib/git/commands/base.rb +111 -13
- data/lib/git/commands/branch/copy.rb +29 -21
- data/lib/git/commands/branch/create.rb +72 -68
- data/lib/git/commands/branch/delete.rb +25 -17
- data/lib/git/commands/branch/list.rb +76 -60
- data/lib/git/commands/branch/move.rb +29 -21
- data/lib/git/commands/branch/set_upstream.rb +8 -8
- data/lib/git/commands/branch/show_current.rb +3 -3
- data/lib/git/commands/branch/unset_upstream.rb +4 -8
- data/lib/git/commands/branch.rb +2 -2
- data/lib/git/commands/cat_file/batch.rb +36 -20
- data/lib/git/commands/cat_file/filtered.rb +12 -12
- data/lib/git/commands/cat_file/raw.rb +13 -13
- data/lib/git/commands/cat_file.rb +4 -4
- data/lib/git/commands/checkout/branch.rb +7 -5
- data/lib/git/commands/checkout/files.rb +5 -4
- data/lib/git/commands/checkout.rb +4 -4
- data/lib/git/commands/checkout_index.rb +5 -4
- data/lib/git/commands/clean.rb +6 -4
- data/lib/git/commands/clone.rb +5 -4
- data/lib/git/commands/commit.rb +5 -4
- data/lib/git/commands/commit_tree.rb +5 -4
- data/lib/git/commands/config_option_syntax/add.rb +7 -4
- data/lib/git/commands/config_option_syntax/get.rb +9 -5
- data/lib/git/commands/config_option_syntax/get_all.rb +7 -4
- data/lib/git/commands/config_option_syntax/get_color.rb +8 -4
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +7 -4
- data/lib/git/commands/config_option_syntax/get_regexp.rb +8 -4
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +8 -4
- data/lib/git/commands/config_option_syntax/list.rb +8 -4
- data/lib/git/commands/config_option_syntax/remove_section.rb +7 -2
- data/lib/git/commands/config_option_syntax/rename_section.rb +7 -2
- data/lib/git/commands/config_option_syntax/replace_all.rb +7 -2
- data/lib/git/commands/config_option_syntax/set.rb +7 -2
- data/lib/git/commands/config_option_syntax/unset.rb +7 -4
- data/lib/git/commands/config_option_syntax/unset_all.rb +7 -2
- data/lib/git/commands/describe.rb +5 -4
- data/lib/git/commands/diff.rb +13 -12
- data/lib/git/commands/diff_files.rb +7 -6
- data/lib/git/commands/diff_index.rb +10 -7
- data/lib/git/commands/fetch.rb +6 -4
- data/lib/git/commands/fsck.rb +6 -4
- data/lib/git/commands/gc.rb +6 -4
- data/lib/git/commands/grep.rb +6 -5
- data/lib/git/commands/init.rb +6 -4
- data/lib/git/commands/log.rb +287 -285
- data/lib/git/commands/ls_files.rb +69 -65
- data/lib/git/commands/ls_remote.rb +62 -56
- data/lib/git/commands/ls_tree.rb +50 -46
- data/lib/git/commands/maintenance/register.rb +25 -23
- data/lib/git/commands/maintenance/run.rb +7 -2
- data/lib/git/commands/maintenance/start.rb +7 -2
- data/lib/git/commands/maintenance/stop.rb +7 -2
- data/lib/git/commands/maintenance/unregister.rb +7 -2
- data/lib/git/commands/merge/abort.rb +2 -2
- data/lib/git/commands/merge/continue.rb +2 -2
- data/lib/git/commands/merge/quit.rb +2 -2
- data/lib/git/commands/merge/start.rb +7 -2
- data/lib/git/commands/merge.rb +2 -2
- data/lib/git/commands/merge_base.rb +7 -2
- data/lib/git/commands/mv.rb +7 -2
- data/lib/git/commands/name_rev.rb +7 -2
- data/lib/git/commands/pull.rb +7 -2
- data/lib/git/commands/push.rb +7 -2
- data/lib/git/commands/read_tree.rb +7 -2
- data/lib/git/commands/remote/add.rb +7 -2
- data/lib/git/commands/remote/get_url.rb +4 -2
- data/lib/git/commands/remote/list.rb +4 -2
- data/lib/git/commands/remote/prune.rb +4 -2
- data/lib/git/commands/remote/remove.rb +4 -2
- data/lib/git/commands/remote/rename.rb +4 -2
- data/lib/git/commands/remote/set_branches.rb +9 -2
- data/lib/git/commands/remote/set_head.rb +12 -5
- data/lib/git/commands/remote/set_url.rb +9 -2
- data/lib/git/commands/remote/set_url_add.rb +11 -2
- data/lib/git/commands/remote/set_url_delete.rb +9 -2
- data/lib/git/commands/remote/show.rb +18 -12
- data/lib/git/commands/remote/update.rb +19 -12
- data/lib/git/commands/remote.rb +2 -2
- data/lib/git/commands/repack.rb +67 -63
- data/lib/git/commands/reset.rb +51 -44
- data/lib/git/commands/rev_parse.rb +135 -128
- data/lib/git/commands/revert/abort.rb +2 -2
- data/lib/git/commands/revert/continue.rb +7 -2
- data/lib/git/commands/revert/quit.rb +2 -2
- data/lib/git/commands/revert/skip.rb +2 -2
- data/lib/git/commands/revert/start.rb +7 -2
- data/lib/git/commands/revert.rb +2 -2
- data/lib/git/commands/rm.rb +35 -36
- data/lib/git/commands/show.rb +1 -1
- data/lib/git/commands/show_ref/exclude_existing.rb +3 -4
- data/lib/git/commands/show_ref/exists.rb +15 -13
- data/lib/git/commands/show_ref/list.rb +39 -35
- data/lib/git/commands/show_ref/verify.rb +29 -27
- data/lib/git/commands/show_ref.rb +4 -4
- data/lib/git/commands/stash/apply.rb +31 -25
- data/lib/git/commands/stash/branch.rb +10 -8
- data/lib/git/commands/stash/clear.rb +7 -5
- data/lib/git/commands/stash/create.rb +10 -8
- data/lib/git/commands/stash/drop.rb +15 -9
- data/lib/git/commands/stash/list.rb +9 -5
- data/lib/git/commands/stash/pop.rb +21 -12
- data/lib/git/commands/stash/push.rb +20 -11
- data/lib/git/commands/stash/show.rb +21 -12
- data/lib/git/commands/stash/store.rb +19 -10
- data/lib/git/commands/stash.rb +2 -2
- data/lib/git/commands/status.rb +7 -2
- data/lib/git/commands/symbolic_ref/delete.rb +18 -14
- data/lib/git/commands/symbolic_ref/read.rb +24 -20
- data/lib/git/commands/symbolic_ref/update.rb +20 -17
- data/lib/git/commands/symbolic_ref.rb +4 -4
- data/lib/git/commands/tag/create.rb +45 -42
- data/lib/git/commands/tag/delete.rb +5 -3
- data/lib/git/commands/tag/list.rb +47 -44
- data/lib/git/commands/tag/verify.rb +12 -12
- data/lib/git/commands/tag.rb +2 -2
- data/lib/git/commands/update_ref/batch.rb +6 -1
- data/lib/git/commands/update_ref/delete.rb +19 -21
- data/lib/git/commands/update_ref/update.rb +22 -25
- data/lib/git/commands/update_ref.rb +4 -4
- data/lib/git/commands/version.rb +14 -11
- data/lib/git/commands/worktree/add.rb +50 -51
- data/lib/git/commands/worktree/list.rb +17 -17
- data/lib/git/commands/worktree/lock.rb +12 -12
- data/lib/git/commands/worktree/move.rb +16 -16
- data/lib/git/commands/worktree/prune.rb +2 -2
- data/lib/git/commands/worktree/remove.rb +2 -2
- data/lib/git/commands/worktree/repair.rb +2 -2
- data/lib/git/commands/worktree/unlock.rb +2 -2
- data/lib/git/commands/write_tree.rb +2 -2
- data/lib/git/commands.rb +4 -3
- data/lib/git/config.rb +47 -1
- data/lib/git/configuring.rb +89 -15
- data/lib/git/detached_head_info.rb +4 -1
- data/lib/git/diff.rb +2 -5
- data/lib/git/diff_file_numstat_info.rb +3 -1
- data/lib/git/diff_file_patch_info.rb +3 -1
- data/lib/git/diff_file_raw_info.rb +3 -1
- data/lib/git/diff_info.rb +8 -15
- data/lib/git/diff_path_status.rb +16 -3
- data/lib/git/diff_result.rb +3 -1
- data/lib/git/diff_stats.rb +15 -0
- data/lib/git/dirstat_info.rb +24 -8
- data/lib/git/encoding_utils.rb +32 -1
- data/lib/git/errors.rb +19 -9
- data/lib/git/escaped_path.rb +55 -3
- data/lib/git/execution_context/repository.rb +15 -0
- data/lib/git/execution_context.rb +76 -74
- data/lib/git/file_ref.rb +6 -3
- data/lib/git/fsck_object.rb +8 -0
- data/lib/git/fsck_result.rb +26 -15
- data/lib/git/log.rb +152 -5
- data/lib/git/object.rb +284 -8
- data/lib/git/parsers/branch.rb +18 -0
- data/lib/git/parsers/cat_file.rb +2 -2
- data/lib/git/parsers/diff.rb +213 -5
- data/lib/git/parsers/fsck.rb +11 -0
- data/lib/git/parsers/ls_remote.rb +1 -1
- data/lib/git/parsers/stash.rb +51 -0
- data/lib/git/parsers/tag.rb +38 -0
- data/lib/git/remote.rb +34 -2
- data/lib/git/repository/branching.rb +23 -21
- data/lib/git/repository/committing.rb +46 -6
- data/lib/git/repository/context_helpers.rb +45 -16
- data/lib/git/repository/diffing.rb +32 -23
- data/lib/git/repository/factories.rb +153 -28
- data/lib/git/repository/inspecting.rb +1 -1
- data/lib/git/repository/logging.rb +169 -30
- data/lib/git/repository/maintenance.rb +1 -1
- data/lib/git/repository/merging.rb +3 -3
- data/lib/git/repository/object_operations.rb +108 -14
- data/lib/git/repository/remote_operations.rb +150 -171
- data/lib/git/repository/shared_private.rb +7 -5
- data/lib/git/repository/staging.rb +36 -12
- data/lib/git/repository/stashing.rb +16 -16
- data/lib/git/repository/status_operations.rb +1 -1
- data/lib/git/repository/worktree_operations.rb +1 -1
- data/lib/git/repository.rb +123 -63
- data/lib/git/stash.rb +16 -21
- data/lib/git/stash_info.rb +4 -4
- data/lib/git/stashes.rb +20 -26
- data/lib/git/status.rb +21 -7
- data/lib/git/tag_delete_failure.rb +3 -0
- data/lib/git/tag_delete_result.rb +6 -3
- data/lib/git/tag_info.rb +1 -0
- data/lib/git/url.rb +12 -5
- data/lib/git/version.rb +6 -4
- data/lib/git/version_constraint.rb +4 -0
- data/lib/git.rb +434 -313
- data/redesign/3_architecture_implementation.md +59 -29
- data/redesign/Phase 4 - Step B.md +921 -0
- data/redesign/Phase 4 - Step C.md +833 -0
- data/redesign/c1a-public-api-scope.tsv +256 -0
- data/redesign/phase-4-step-b-test-audit.tsv +485 -0
- data/redesign/reverse_dependencies.sql +44 -0
- data/tasks/yard.rake +24 -17
- metadata +25 -57
- data/commitlint.test +0 -4
- data/lib/git/args_builder.rb +0 -103
- data/lib/git/command_line_result.rb +0 -8
- data/lib/git/deprecation.rb +0 -9
- data/tasks/test.rake +0 -25
- /data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -0
- /data/.github/{skills → skills-deprecated}/review-backward-compatibility/SKILL.md +0 -0
data/lib/git.rb
CHANGED
|
@@ -1,29 +1,54 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'active_support'
|
|
4
3
|
require 'active_support/deprecation'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
# Define Git::Deprecation before requiring the rest of the library to ensure that
|
|
6
|
+
# any deprecation warnings emitted during the loading of the library are properly
|
|
7
|
+
# configured according to the GIT_DEPRECATION_BEHAVIOR environment variable.
|
|
8
|
+
#
|
|
9
9
|
module Git
|
|
10
|
-
#
|
|
10
|
+
# The deprecation instance used to emit deprecation warnings for the Git gem
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
|
|
12
|
+
# @api public
|
|
13
|
+
Deprecation = ActiveSupport::Deprecation.new('6.0.0', 'Git')
|
|
14
|
+
|
|
15
|
+
# Configure a deprecation instance from a GIT_DEPRECATION_BEHAVIOR value
|
|
14
16
|
#
|
|
15
|
-
# @
|
|
17
|
+
# @param deprecation [ActiveSupport::Deprecation] the deprecation instance to configure
|
|
16
18
|
#
|
|
17
|
-
# @
|
|
19
|
+
# @param behavior [String, nil] the desired behavior name (e.g. `'silence'`); when
|
|
20
|
+
# `nil` the deprecation instance is left unchanged
|
|
18
21
|
#
|
|
19
|
-
|
|
22
|
+
# @return [void]
|
|
23
|
+
#
|
|
24
|
+
# @raise [ArgumentError] if `behavior` is not one of the keys of
|
|
25
|
+
# `ActiveSupport::Deprecation::DEFAULT_BEHAVIORS`
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
def self.configure_deprecation_behavior(deprecation, behavior)
|
|
30
|
+
return if behavior.nil?
|
|
31
|
+
|
|
32
|
+
behavior = behavior.strip
|
|
33
|
+
allowed_behaviors = ActiveSupport::Deprecation::DEFAULT_BEHAVIORS.keys.map(&:to_s)
|
|
34
|
+
|
|
35
|
+
unless allowed_behaviors.include?(behavior)
|
|
36
|
+
raise ArgumentError,
|
|
37
|
+
"Invalid GIT_DEPRECATION_BEHAVIOR=#{behavior.inspect}; " \
|
|
38
|
+
"expected one of: #{allowed_behaviors.join(', ')}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
deprecation.behavior = behavior.to_sym
|
|
42
|
+
end
|
|
43
|
+
private_class_method :configure_deprecation_behavior
|
|
44
|
+
|
|
45
|
+
configure_deprecation_behavior(Deprecation, ENV.fetch('GIT_DEPRECATION_BEHAVIOR', nil))
|
|
20
46
|
end
|
|
21
47
|
|
|
22
48
|
require 'git/author'
|
|
23
49
|
require 'git/branch'
|
|
24
50
|
require 'git/branch_info'
|
|
25
51
|
require 'git/branches'
|
|
26
|
-
require 'git/command_line_result'
|
|
27
52
|
require 'git/command_line'
|
|
28
53
|
require 'process_executer'
|
|
29
54
|
require 'git/config'
|
|
@@ -61,6 +86,7 @@ require 'git/tag_delete_failure'
|
|
|
61
86
|
require 'git/tag_delete_result'
|
|
62
87
|
require 'git/tag_info'
|
|
63
88
|
require 'git/url'
|
|
89
|
+
require 'git/version'
|
|
64
90
|
require 'git/worktree'
|
|
65
91
|
require 'git/worktrees'
|
|
66
92
|
|
|
@@ -69,216 +95,178 @@ require 'git/worktrees'
|
|
|
69
95
|
# open a bare repository, initialize a new repo or clone an
|
|
70
96
|
# existing remote repository.
|
|
71
97
|
#
|
|
72
|
-
# @author Scott Chacon (mailto:schacon@gmail.com)
|
|
73
|
-
#
|
|
74
98
|
module Git
|
|
75
99
|
extend Git::Configuring
|
|
100
|
+
extend Git::Repository::Factories
|
|
76
101
|
|
|
77
|
-
#
|
|
78
|
-
# Use `Git.config_get(name)`, `Git.config_set(name, value)`, or `Git.config_list` instead.
|
|
79
|
-
def config(name = nil, value = nil)
|
|
80
|
-
Git::Deprecation.warn(
|
|
81
|
-
'Git#config is deprecated and will be removed in v6.0.0. ' \
|
|
82
|
-
'Use Git.config_get(name), Git.config_set(name, value), or Git.config_list instead.'
|
|
83
|
-
)
|
|
84
|
-
Git.__send__(:run_config_utility, name, value, global: false)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Configures the gem by yielding {Git::Config.instance} to the block
|
|
88
|
-
#
|
|
89
|
-
# @example Set the global git binary path
|
|
90
|
-
# Git.configure { |c| c.binary_path = '/usr/local/bin/git' }
|
|
91
|
-
#
|
|
92
|
-
# @yield [config] yields the singleton config object
|
|
102
|
+
# Minimum git version required by this gem
|
|
93
103
|
#
|
|
94
|
-
#
|
|
104
|
+
# Commands and features may require newer versions, but this is the absolute
|
|
105
|
+
# minimum supported version for the gem as a whole.
|
|
95
106
|
#
|
|
96
|
-
# @
|
|
107
|
+
# @return [Git::Version]
|
|
97
108
|
#
|
|
98
|
-
# @
|
|
109
|
+
# @api public
|
|
99
110
|
#
|
|
100
|
-
|
|
101
|
-
yield Git::Config.instance
|
|
102
|
-
nil
|
|
103
|
-
end
|
|
111
|
+
MINIMUM_GIT_VERSION = Version.parse('2.28.0')
|
|
104
112
|
|
|
105
|
-
#
|
|
113
|
+
# Compatibility shim for code that monkeypatches the `Git::Base` class from
|
|
114
|
+
# versions prior to 5.0.0.
|
|
106
115
|
#
|
|
107
|
-
#
|
|
108
|
-
#
|
|
116
|
+
# `Git::Base` is a module included in {Git::Repository}, so any instance
|
|
117
|
+
# methods added to `Git::Base` are automatically available on
|
|
118
|
+
# {Git::Repository} instances. A deprecation warning is emitted for each
|
|
119
|
+
# method added, encouraging migration to {Git::Repository}.
|
|
109
120
|
#
|
|
110
|
-
# @
|
|
121
|
+
# @example Monkeypatching Git::Base (deprecated)
|
|
122
|
+
# module Git::Base
|
|
123
|
+
# def my_helper = "hello"
|
|
124
|
+
# end
|
|
125
|
+
# Git.open('.').my_helper # => "hello"
|
|
111
126
|
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
127
|
+
# @deprecated Define instance methods on {Git::Repository} instead.
|
|
128
|
+
#
|
|
129
|
+
# @api public
|
|
130
|
+
Base = Module.new do
|
|
131
|
+
# Emit a deprecation warning each time a method is defined in Git::Base so
|
|
132
|
+
# that authors of monkeypatches are nudged toward Git::Repository.
|
|
133
|
+
def self.method_added(method_name)
|
|
134
|
+
Git::Deprecation.warn(
|
|
135
|
+
'Monkeypatching Git::Base is deprecated and will be removed in v6.0.0. ' \
|
|
136
|
+
"Define #{method_name} in Git::Repository instead."
|
|
137
|
+
)
|
|
138
|
+
super
|
|
139
|
+
end
|
|
115
140
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
'Git#global_config is deprecated and will be removed in v6.0.0. ' \
|
|
122
|
-
'Use Git.config_get(name, global: true), Git.config_set(name, value, global: true), ' \
|
|
123
|
-
'or Git.config_list(global: true) instead.'
|
|
124
|
-
)
|
|
125
|
-
Git.global_config(name, value)
|
|
141
|
+
# Raise a clear error when legacy code calls Git::Base.new directly.
|
|
142
|
+
def self.new(...)
|
|
143
|
+
raise NoMethodError,
|
|
144
|
+
'Git::Base.new is not supported. Use Git.open, Git.clone, or Git.init instead.'
|
|
145
|
+
end
|
|
126
146
|
end
|
|
127
147
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
#
|
|
131
|
-
# Since there is no working copy, you can not checkout or commit
|
|
132
|
-
# but you can do most read operations.
|
|
133
|
-
#
|
|
134
|
-
# @see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository
|
|
135
|
-
# What is a bare repository?
|
|
136
|
-
#
|
|
137
|
-
# @example Open a bare repository and retrieve the first commit SHA
|
|
138
|
-
# repository = Git.bare('ruby-git.git')
|
|
139
|
-
# puts repository.log[0].sha #=> "64c6fa011d3287bab9158049c85f3e85718854a0"
|
|
140
|
-
#
|
|
141
|
-
# @param [Pathname] git_dir The path to the bare repository directory
|
|
142
|
-
# containing an initialized Git repository. If a relative path is given, it
|
|
143
|
-
# is converted to an absolute path using
|
|
144
|
-
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
|
|
145
|
-
#
|
|
146
|
-
# @param [Hash] options The options for this command (see list of valid
|
|
147
|
-
# options below)
|
|
148
|
-
#
|
|
149
|
-
# @option options [String, nil] :git_ssh An optional custom SSH command
|
|
148
|
+
Repository.include(Base)
|
|
149
|
+
|
|
150
|
+
# Intercept the first lookup of the deprecated `Git::CommandLineResult` constant
|
|
150
151
|
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
#
|
|
152
|
+
# When `name` is `:CommandLineResult`, caches and returns {Git::CommandLine::Result}
|
|
153
|
+
# after emitting a deprecation warning. Calls `super` for any other unknown constant,
|
|
154
|
+
# preserving normal Ruby `NameError` behavior.
|
|
154
155
|
#
|
|
155
|
-
# @
|
|
156
|
-
# are logged at the `:info` level. Additional logging is done at the `:debug`
|
|
157
|
-
# level.
|
|
156
|
+
# @param name [Symbol] the name of the missing constant
|
|
158
157
|
#
|
|
159
|
-
# @return [
|
|
160
|
-
# of the bare repository.
|
|
158
|
+
# @return [Class] the resolved constant value
|
|
161
159
|
#
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
# @api private
|
|
161
|
+
def self.const_missing(name)
|
|
162
|
+
return super unless name == :CommandLineResult
|
|
163
|
+
|
|
164
|
+
# Cache the constant first so subsequent accesses are zero-cost even if
|
|
165
|
+
# the deprecation behavior raises (e.g. in the test suite).
|
|
166
|
+
const_set(:CommandLineResult, Git::CommandLine::Result)
|
|
167
|
+
Git::Deprecation.warn(
|
|
168
|
+
'Git::CommandLineResult is deprecated and will be removed in v6.0.0. ' \
|
|
169
|
+
'Use Git::CommandLine::Result instead.'
|
|
170
|
+
)
|
|
171
|
+
Git::CommandLine::Result
|
|
164
172
|
end
|
|
165
173
|
|
|
166
|
-
#
|
|
174
|
+
# Gets or sets local git configuration options
|
|
167
175
|
#
|
|
168
|
-
# @
|
|
169
|
-
#
|
|
176
|
+
# @overload config(name, value)
|
|
177
|
+
# Set the value for the git named configuration option
|
|
170
178
|
#
|
|
171
|
-
#
|
|
172
|
-
# from. See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a)
|
|
173
|
-
# for more information.
|
|
174
|
-
#
|
|
175
|
-
# @param directory [Pathname, nil] The directory to clone into
|
|
179
|
+
# @param name [String] the name of the git configuration option
|
|
176
180
|
#
|
|
177
|
-
#
|
|
178
|
-
# given. If `:chdir` is not given, `directory` is relative to the current
|
|
179
|
-
# working directory.
|
|
181
|
+
# @param value [String, Boolean] the value to set for the git configuration option
|
|
180
182
|
#
|
|
181
|
-
#
|
|
182
|
-
# the path from the `repository_url`. For example, for the URL:
|
|
183
|
-
# `https://github.com/org/repo.git`, `directory` will be set to `repo`.
|
|
183
|
+
# @return [Git::CommandLine::Result] the result of the git configuration command
|
|
184
184
|
#
|
|
185
|
-
#
|
|
186
|
-
# the
|
|
187
|
-
# will be set to `foo`.
|
|
188
|
-
#
|
|
189
|
-
# @param [Hash] options The options for this command (see list of valid
|
|
190
|
-
# options below)
|
|
185
|
+
# @overload config(name)
|
|
186
|
+
# Get the value for the git named configuration option
|
|
191
187
|
#
|
|
192
|
-
#
|
|
193
|
-
# [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository).
|
|
188
|
+
# @param name [String] the name of the git configuration option
|
|
194
189
|
#
|
|
195
|
-
#
|
|
196
|
-
# instead of the default branch.
|
|
190
|
+
# @return [String] the value of the git configuration option
|
|
197
191
|
#
|
|
198
|
-
# @
|
|
199
|
-
#
|
|
192
|
+
# @overload config()
|
|
193
|
+
# List all git configuration options
|
|
200
194
|
#
|
|
201
|
-
#
|
|
202
|
-
# truncated to the specified number of commits.
|
|
195
|
+
# @return [Hash{String => String}] a hash of all git configuration options
|
|
203
196
|
#
|
|
204
|
-
# @
|
|
205
|
-
#
|
|
197
|
+
# @deprecated Mixing in the `Git` module is deprecated and will be removed in v6.0.0.
|
|
198
|
+
# Use `Git.config_get(name)`, `Git.config_set(name, value)`, or `Git.config_list` instead.
|
|
206
199
|
#
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
200
|
+
def config(name = nil, value = nil)
|
|
201
|
+
Git::Deprecation.warn(
|
|
202
|
+
'Git#config is deprecated and will be removed in v6.0.0. ' \
|
|
203
|
+
'Use Git.config_get(name), Git.config_set(name, value), or Git.config_list instead.'
|
|
204
|
+
)
|
|
205
|
+
Git.__send__(:legacy_config_set_get_list, name, value, global: false)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Configures the gem by yielding {Git::Config.instance} to the block
|
|
214
209
|
#
|
|
215
|
-
# @
|
|
210
|
+
# @example Set the global git binary path
|
|
211
|
+
# Git.configure { |c| c.binary_path = '/usr/local/bin/git' }
|
|
216
212
|
#
|
|
217
|
-
#
|
|
218
|
-
# - If nil, disables SSH for this instance.
|
|
219
|
-
# - If a non-empty string, uses that value for this instance.
|
|
213
|
+
# @return [void]
|
|
220
214
|
#
|
|
221
|
-
# @
|
|
222
|
-
# commands are logged at the `:info` level. Additional logging is done
|
|
223
|
-
# at the `:debug` level.
|
|
215
|
+
# @yield [config] yields the singleton config object
|
|
224
216
|
#
|
|
225
|
-
# @
|
|
217
|
+
# @yieldparam config [Git::Config] the singleton config object
|
|
226
218
|
#
|
|
227
|
-
# @
|
|
228
|
-
# the upstream repository.
|
|
219
|
+
# @yieldreturn [void]
|
|
229
220
|
#
|
|
230
|
-
|
|
221
|
+
def self.configure
|
|
222
|
+
yield Git::Config.instance
|
|
223
|
+
nil
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Returns the process-wide {Git::Config} singleton
|
|
231
227
|
#
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
# running `git clone`. The returned path is the join of `:chdir` and the
|
|
235
|
-
# cloned directory path.
|
|
228
|
+
# @example Read the configured binary path
|
|
229
|
+
# Git.config.binary_path #=> "git"
|
|
236
230
|
#
|
|
237
|
-
# @
|
|
231
|
+
# @return [Git::Config] the singleton config object
|
|
238
232
|
#
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
def self.config
|
|
234
|
+
Git::Config.instance
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Gets or sets global git configuration options
|
|
241
238
|
#
|
|
242
|
-
# @
|
|
243
|
-
# git
|
|
239
|
+
# @overload global_config(name, value)
|
|
240
|
+
# Set the value for the git named configuration option
|
|
244
241
|
#
|
|
245
|
-
#
|
|
246
|
-
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', branch: 'development')
|
|
242
|
+
# @param name [String] the name of the git configuration option
|
|
247
243
|
#
|
|
248
|
-
#
|
|
249
|
-
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', 'my-ruby-git')
|
|
244
|
+
# @param value [String, Boolean] the value to set for the git configuration option
|
|
250
245
|
#
|
|
251
|
-
#
|
|
252
|
-
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', chdir: '/path/to/projects')
|
|
253
|
-
# # clones into /path/to/projects/ruby-git
|
|
246
|
+
# @return [Git::CommandLine::Result] the result of the git configuration command
|
|
254
247
|
#
|
|
255
|
-
# @
|
|
256
|
-
#
|
|
248
|
+
# @overload global_config(name)
|
|
249
|
+
# Get the value for the git named configuration option
|
|
257
250
|
#
|
|
258
|
-
#
|
|
259
|
-
# git = Git.clone(
|
|
260
|
-
# 'https://github.com/ruby-git/ruby-git.git',
|
|
261
|
-
# config: 'submodule.recurse=true'
|
|
262
|
-
# )
|
|
251
|
+
# @param name [String] the name of the git configuration option
|
|
263
252
|
#
|
|
264
|
-
#
|
|
265
|
-
# git = Git.clone(
|
|
266
|
-
# 'https://github.com/ruby-git/ruby-git.git',
|
|
267
|
-
# config: ['user.name=John Doe', 'user.email=john@doe.com']
|
|
268
|
-
# )
|
|
253
|
+
# @return [String] the value of the git configuration option
|
|
269
254
|
#
|
|
270
|
-
# @
|
|
271
|
-
# git
|
|
272
|
-
# 'git@github.com:ruby-git/ruby-git.git',
|
|
273
|
-
# 'local-dir',
|
|
274
|
-
# git_ssh: 'ssh -i /path/to/private_key'
|
|
275
|
-
# )
|
|
255
|
+
# @overload global_config()
|
|
256
|
+
# List all git configuration options
|
|
276
257
|
#
|
|
277
|
-
#
|
|
278
|
-
# of the cloned local working copy or cloned repository.
|
|
258
|
+
# @return [Hash{String => String}] a hash of all git configuration options
|
|
279
259
|
#
|
|
280
|
-
|
|
281
|
-
|
|
260
|
+
# @deprecated Mixing in the `Git` module is deprecated and will be removed in v6.0.0.
|
|
261
|
+
# Use `Git.config_get(name, global: true)`, `Git.config_set(name, value, global: true)`, or
|
|
262
|
+
# `Git.config_list(global: true)` instead.
|
|
263
|
+
def global_config(name = nil, value = nil)
|
|
264
|
+
Git::Deprecation.warn(
|
|
265
|
+
'Git#global_config is deprecated and will be removed in v6.0.0. ' \
|
|
266
|
+
'Use Git.config_get(name, global: true), Git.config_set(name, value, global: true), ' \
|
|
267
|
+
'or Git.config_list(global: true) instead.'
|
|
268
|
+
)
|
|
269
|
+
Git.__send__(:legacy_config_set_get_list, name, value, global: true)
|
|
282
270
|
end
|
|
283
271
|
|
|
284
272
|
# Returns the name of the default branch of the given repository
|
|
@@ -301,15 +289,16 @@ module Git
|
|
|
301
289
|
# @example with the logging option
|
|
302
290
|
# logger = Logger.new(STDOUT, level: Logger::INFO)
|
|
303
291
|
# Git.default_branch('.', log: logger) # => 'master'
|
|
304
|
-
#
|
|
305
|
-
#
|
|
292
|
+
# # Logs the executed git command to STDOUT, for example:
|
|
293
|
+
# # I, [2022-04-13T16:01:33.221596 #18415] INFO -- : git '-c' 'core.quotePath=true'
|
|
294
|
+
# # '-c' 'color.ui=false' ls-remote '--symref' '--' '.' 'HEAD' 2>&1
|
|
306
295
|
#
|
|
307
296
|
# @param repository [URI, Pathname, String] The (possibly remote) repository to get the default branch name for
|
|
308
297
|
#
|
|
309
298
|
# See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a)
|
|
310
299
|
# for more information.
|
|
311
300
|
#
|
|
312
|
-
# @param [Hash]
|
|
301
|
+
# @param options [Hash] The options for this command (see list of valid
|
|
313
302
|
# options below)
|
|
314
303
|
#
|
|
315
304
|
# @option options [Logger] :log A logger to use for Git operations. Git
|
|
@@ -324,94 +313,64 @@ module Git
|
|
|
324
313
|
Git::Parsers::LsRemote.parse_default_branch(output)
|
|
325
314
|
end
|
|
326
315
|
|
|
327
|
-
#
|
|
328
|
-
# is specified) into the +name+ directory, then remove all traces of git from the
|
|
329
|
-
# directory.
|
|
316
|
+
# Clone a repository into `directory` then remove its `.git` directory
|
|
330
317
|
#
|
|
331
|
-
#
|
|
332
|
-
#
|
|
333
|
-
# remote, 'origin.'
|
|
334
|
-
def self.export(repository, name, options = {})
|
|
335
|
-
options.delete(:remote)
|
|
336
|
-
repo = clone(repository, name, { depth: 1 }.merge(options))
|
|
337
|
-
repo.checkout("origin/#{options[:branch]}") if options[:branch]
|
|
338
|
-
FileUtils.rm_r File.join(repo.dir.to_s, '.git')
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
# Same as g.config, but forces it to be at the global level
|
|
342
|
-
#
|
|
343
|
-
# g.config('user.name', 'Scott Chacon') # sets value
|
|
344
|
-
# g.config('user.email', 'email@email.com') # sets value
|
|
345
|
-
# g.config('user.name') # returns 'Scott Chacon'
|
|
346
|
-
# g.config # returns whole config hash
|
|
347
|
-
def self.global_config(name = nil, value = nil)
|
|
348
|
-
run_config_utility(name, value, global: true)
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
# Create an empty Git repository or reinitialize an existing Git repository
|
|
318
|
+
# Exports the current HEAD (or the specific branch given in <tt>options[:branch]</tt>)
|
|
319
|
+
# into the given `directory`. It then removes all traces of git from the directory.
|
|
352
320
|
#
|
|
353
|
-
#
|
|
354
|
-
#
|
|
355
|
-
# Otherwise, the repository is created in `"#{directory}"`.
|
|
321
|
+
# Takes the same options as {Git.clone} except that `:remote` is silently ignored
|
|
322
|
+
# and `:depth` defaults to 1.
|
|
356
323
|
#
|
|
357
|
-
#
|
|
324
|
+
# @param repository_url [String, URI, Pathname] the repository to export from
|
|
358
325
|
#
|
|
359
|
-
#
|
|
360
|
-
#
|
|
361
|
-
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
|
|
362
|
-
#
|
|
363
|
-
# @param [Hash] options The options for this command (see list of valid
|
|
364
|
-
# options below)
|
|
326
|
+
# @param directory [String, Pathname, nil] the directory to export into; defaults to the
|
|
327
|
+
# repository basename
|
|
365
328
|
#
|
|
366
|
-
# @
|
|
367
|
-
# `
|
|
368
|
-
# See [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository).
|
|
329
|
+
# @param options [Hash] options forwarded to {Git.clone} (`:remote` is ignored;
|
|
330
|
+
# `:depth` defaults to 1)
|
|
369
331
|
#
|
|
370
|
-
# @option options [String] :
|
|
371
|
-
# initial branch in the newly created repository.
|
|
332
|
+
# @option options [String] :branch the branch or tag to export instead of HEAD
|
|
372
333
|
#
|
|
373
|
-
# @
|
|
374
|
-
# Git repository. The default for non-bare repository is `"#{directory}/.git"`.
|
|
375
|
-
#
|
|
376
|
-
# A relative path is referenced from the current working directory of the process
|
|
377
|
-
# and converted to an absolute path using
|
|
378
|
-
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
|
|
379
|
-
#
|
|
380
|
-
# @option options [Pathname] :separate_git_dir Alias for `:repository`.
|
|
381
|
-
#
|
|
382
|
-
# @option options [String, nil] :git_ssh An optional custom SSH command
|
|
334
|
+
# @return [void]
|
|
383
335
|
#
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
336
|
+
def self.export(repository_url, directory = nil, options = {})
|
|
337
|
+
options.delete(:remote)
|
|
338
|
+
repo = clone(repository_url, directory, { depth: 1 }.merge(options))
|
|
339
|
+
repo.checkout("origin/#{options[:branch]}") if options[:branch]
|
|
340
|
+
FileUtils.rm_r File.join(repo.dir.to_s, '.git')
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# Get or set a git global configuration value
|
|
387
344
|
#
|
|
388
|
-
# @
|
|
389
|
-
#
|
|
390
|
-
# Raises `ArgumentError` if set to `nil`.
|
|
345
|
+
# @example Set a value
|
|
346
|
+
# Git.global_config('user.name', 'Scott Chacon')
|
|
391
347
|
#
|
|
392
|
-
# @
|
|
393
|
-
#
|
|
394
|
-
# at the `:debug` level.
|
|
348
|
+
# @example Get a value
|
|
349
|
+
# Git.global_config('user.name') # => 'Scott Chacon'
|
|
395
350
|
#
|
|
396
|
-
# @
|
|
397
|
-
#
|
|
351
|
+
# @example List all global config entries
|
|
352
|
+
# Git.global_config # => { 'user.name' => 'Scott Chacon', ... }
|
|
398
353
|
#
|
|
399
|
-
# @
|
|
400
|
-
# git = Git.init
|
|
354
|
+
# @param name [String, nil] the config key to get or set; omit to list all
|
|
401
355
|
#
|
|
402
|
-
# @
|
|
403
|
-
# git = Git.init '~/code/ruby-git'
|
|
356
|
+
# @param value [Object, nil] the value to set; omit to get or list
|
|
404
357
|
#
|
|
405
|
-
# @
|
|
406
|
-
#
|
|
358
|
+
# @return [String, Hash, Git::CommandLine::Result] the config value, all entries,
|
|
359
|
+
# or the result of the set command
|
|
407
360
|
#
|
|
408
|
-
# @
|
|
409
|
-
# git = Git.init '~/code/ruby-git', repository: '~/code/ruby-git.git'
|
|
361
|
+
# @deprecated Use {Git.config_get}, {Git.config_set}, or {Git.config_list} instead.
|
|
410
362
|
#
|
|
411
|
-
#
|
|
363
|
+
# - `Git.global_config('user.name')` → `Git.config_get('user.name', global: true)`
|
|
364
|
+
# - `Git.global_config('user.name', 'Bob')` → `Git.config_set('user.name', 'Bob', global: true)`
|
|
365
|
+
# - `Git.global_config` → `Git.config_list(global: true)`
|
|
412
366
|
#
|
|
413
|
-
def self.
|
|
414
|
-
Git::
|
|
367
|
+
def self.global_config(name = nil, value = nil)
|
|
368
|
+
Git::Deprecation.warn(
|
|
369
|
+
'Git.global_config is deprecated and will be removed in v6.0.0. ' \
|
|
370
|
+
'Use Git.config_get(name, global: true), Git.config_set(name, value, global: true), ' \
|
|
371
|
+
'or Git.config_list(global: true) instead.'
|
|
372
|
+
)
|
|
373
|
+
legacy_config_set_get_list(name, value, global: true)
|
|
415
374
|
end
|
|
416
375
|
|
|
417
376
|
# Option keys accepted by {.ls_remote}
|
|
@@ -429,84 +388,129 @@ module Git
|
|
|
429
388
|
].freeze
|
|
430
389
|
private_constant :LS_REMOTE_ALLOWED_OPTS
|
|
431
390
|
|
|
432
|
-
#
|
|
433
|
-
# of the target repository
|
|
391
|
+
# Displays references available in a remote repository along with the associated commit IDs
|
|
434
392
|
#
|
|
435
|
-
#
|
|
436
|
-
#
|
|
393
|
+
# @example From a remote repository given its URL
|
|
394
|
+
# references = Git.ls_remote('https://github.com/user/repo.git')
|
|
437
395
|
#
|
|
438
|
-
# @
|
|
439
|
-
#
|
|
440
|
-
def self.ls_remote(location = nil, options = {})
|
|
441
|
-
options = options.dup
|
|
442
|
-
log = options.delete(:log)
|
|
443
|
-
unknown = options.keys - LS_REMOTE_ALLOWED_OPTS
|
|
444
|
-
raise ArgumentError, "Unknown options: #{unknown.join(', ')}" unless unknown.empty?
|
|
445
|
-
|
|
446
|
-
context = Git::ExecutionContext::Global.new(logger: log)
|
|
447
|
-
repository = location || '.'
|
|
448
|
-
output_lines = Git::Commands::LsRemote.new(context).call(repository, **options).stdout.split("\n")
|
|
449
|
-
Git::Parsers::LsRemote.parse_output(output_lines)
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
# Open a an existing Git working directory
|
|
396
|
+
# @example From the default remote of the current repository
|
|
397
|
+
# references = Git.ls_remote
|
|
453
398
|
#
|
|
454
|
-
#
|
|
455
|
-
#
|
|
399
|
+
# @example From a specific remote of the current repository
|
|
400
|
+
# references = Git.ls_remote('origin')
|
|
456
401
|
#
|
|
457
|
-
#
|
|
458
|
-
# the repository and index are in the default places (`.git/`, `.git/index`).
|
|
402
|
+
# @param repository [String, nil] the target repository location or the name of a remote
|
|
459
403
|
#
|
|
460
|
-
#
|
|
461
|
-
#
|
|
404
|
+
# Defaults to `'.'` (the current directory). Passing `nil` explicitly is
|
|
405
|
+
# deprecated and will be removed in v6.0.0; pass `'.'` or omit the argument.
|
|
462
406
|
#
|
|
463
|
-
# @
|
|
464
|
-
# git = Git.open('~/Projects/ruby-git')
|
|
407
|
+
# @param options [Hash] the options to pass to the git command
|
|
465
408
|
#
|
|
466
|
-
# @
|
|
467
|
-
# logger = Logger.new(STDOUT)
|
|
468
|
-
# git = Git.open('~/Projects/ruby-git', log: logger)
|
|
409
|
+
# @option options [Boolean, nil] :branches (nil) limit output to refs under `refs/heads/`
|
|
469
410
|
#
|
|
470
|
-
#
|
|
471
|
-
# git = Git.open('~/Projects/ruby-git', repository: '~/Project/ruby-git.git')
|
|
411
|
+
# Alias: `:b`
|
|
472
412
|
#
|
|
473
|
-
# @
|
|
474
|
-
# for git commands.
|
|
413
|
+
# @option options [Boolean, nil] :heads (nil) limit output to refs under `refs/heads/`
|
|
475
414
|
#
|
|
476
|
-
#
|
|
477
|
-
#
|
|
478
|
-
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
|
|
415
|
+
# Deprecated: use `:branches` instead. Kept for backward compatibility with
|
|
416
|
+
# older git versions where `--heads` is the only supported flag.
|
|
479
417
|
#
|
|
480
|
-
#
|
|
481
|
-
# options below)
|
|
418
|
+
# Alias: `:h`
|
|
482
419
|
#
|
|
483
|
-
# @option options [
|
|
484
|
-
# the repository directory. The default is `"#{working_dir}/.git"`.
|
|
420
|
+
# @option options [Boolean, nil] :tags (nil) limit output to refs under `refs/tags/`
|
|
485
421
|
#
|
|
486
|
-
#
|
|
487
|
-
# index file. The default is `"#{working_dir}/.git/index"`
|
|
422
|
+
# Alias: `:t`
|
|
488
423
|
#
|
|
489
|
-
# @option options [
|
|
424
|
+
# @option options [Boolean, nil] :refs (nil) exclude peeled tags and pseudorefs
|
|
425
|
+
# like `HEAD` from the output
|
|
490
426
|
#
|
|
491
|
-
#
|
|
492
|
-
#
|
|
493
|
-
# - If a non-empty string, uses that value for this instance.
|
|
427
|
+
# @option options [String] :upload_pack (nil) full path to `git-upload-pack` on the
|
|
428
|
+
# remote host
|
|
494
429
|
#
|
|
495
|
-
#
|
|
496
|
-
#
|
|
497
|
-
#
|
|
430
|
+
# Useful when accessing repositories via SSH where the daemon does not use the
|
|
431
|
+
# PATH configured by the user.
|
|
432
|
+
#
|
|
433
|
+
# @option options [Boolean, nil] :quiet (nil) do not print the remote URL to stderr
|
|
434
|
+
#
|
|
435
|
+
# Alias: `:q`
|
|
436
|
+
#
|
|
437
|
+
# @option options [Boolean, nil] :exit_code (nil) exit with status `2` when no
|
|
438
|
+
# matching refs are found in the remote repository
|
|
439
|
+
#
|
|
440
|
+
# Without this option, the command exits `0` whenever it successfully
|
|
441
|
+
# communicates with the remote, even if no refs match.
|
|
498
442
|
#
|
|
499
|
-
# @
|
|
500
|
-
# of the opened working copy
|
|
443
|
+
# @option options [String] :sort (nil) sort output by the given key
|
|
501
444
|
#
|
|
502
|
-
|
|
503
|
-
|
|
445
|
+
# Prefix `-` for descending order. Supports `"version:refname"` or `"v:refname"`.
|
|
446
|
+
# See `git for-each-ref` for sort key documentation.
|
|
447
|
+
#
|
|
448
|
+
# @option options [String, Array<String>] :server_option (nil) transmit a string to
|
|
449
|
+
# the server when communicating using protocol version 2
|
|
450
|
+
#
|
|
451
|
+
# The string must not contain NUL or LF characters. Repeatable by passing an
|
|
452
|
+
# Array. Alias: `:o`
|
|
453
|
+
#
|
|
454
|
+
# @option options [Numeric] :timeout (nil) execution timeout in seconds
|
|
455
|
+
#
|
|
456
|
+
# @option options [Logger] :log (nil) a logger to use for Git operations
|
|
457
|
+
#
|
|
458
|
+
# Git commands are logged at the `:info` level. Additional logging is done at
|
|
459
|
+
# the `:debug` level.
|
|
460
|
+
#
|
|
461
|
+
# @return [Hash{String => Hash}] the available references of the target repo
|
|
462
|
+
#
|
|
463
|
+
def self.ls_remote(repository = '.', options = {})
|
|
464
|
+
repository = normalize_ls_remote_repository(repository)
|
|
465
|
+
options = options.dup
|
|
466
|
+
log = options.delete(:log)
|
|
467
|
+
unknown = options.keys - LS_REMOTE_ALLOWED_OPTS
|
|
468
|
+
raise ArgumentError, "Unknown options: #{unknown.join(', ')}" unless unknown.empty?
|
|
469
|
+
|
|
470
|
+
context = Git::ExecutionContext::Global.new(logger: log)
|
|
471
|
+
output_lines = Git::Commands::LsRemote.new(context).call(repository, **options).stdout.split("\n")
|
|
472
|
+
Git::Parsers::LsRemote.parse_output(output_lines)
|
|
504
473
|
end
|
|
505
474
|
|
|
475
|
+
# Normalize the repository argument for {.ls_remote}
|
|
476
|
+
#
|
|
477
|
+
# Returns the repository unchanged unless it is nil, in which case a
|
|
478
|
+
# deprecation warning is emitted and `'.'` is returned.
|
|
479
|
+
#
|
|
480
|
+
# @param repository [String, nil] the repository argument passed by the caller
|
|
481
|
+
#
|
|
482
|
+
# @return [String] the normalized repository value (`'.'` when nil was given)
|
|
483
|
+
#
|
|
484
|
+
# @api private
|
|
485
|
+
#
|
|
486
|
+
def self.normalize_ls_remote_repository(repository)
|
|
487
|
+
return repository unless repository.nil?
|
|
488
|
+
|
|
489
|
+
Git::Deprecation.warn(
|
|
490
|
+
'Passing nil as the repository to Git.ls_remote is deprecated and will ' \
|
|
491
|
+
"be removed in v6.0.0. Pass '.' explicitly or omit the argument instead."
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
'.'
|
|
495
|
+
end
|
|
496
|
+
private_class_method :normalize_ls_remote_repository
|
|
497
|
+
|
|
506
498
|
# Thread-safe cache for git versions, keyed by binary path.
|
|
507
499
|
@git_version_cache_mutex = Mutex.new
|
|
508
500
|
@git_version_cache = {}
|
|
509
501
|
|
|
502
|
+
# Return the cached git version for the given binary path
|
|
503
|
+
#
|
|
504
|
+
# If it isn't already known, compute it using the given block.
|
|
505
|
+
#
|
|
506
|
+
# @param binary_path [String] the path to the git binary
|
|
507
|
+
#
|
|
508
|
+
# @return [Git::Version] the git version
|
|
509
|
+
#
|
|
510
|
+
# @yield [] compute the git version if it is not cached
|
|
511
|
+
#
|
|
512
|
+
# @yieldreturn [Git::Version] the computed git version
|
|
513
|
+
#
|
|
510
514
|
# @api private
|
|
511
515
|
def self.cached_git_version(binary_path, &block)
|
|
512
516
|
@git_version_cache_mutex.synchronize do
|
|
@@ -514,6 +518,10 @@ module Git
|
|
|
514
518
|
end
|
|
515
519
|
end
|
|
516
520
|
|
|
521
|
+
# Clear the cached git version for all binary paths
|
|
522
|
+
#
|
|
523
|
+
# @return [void]
|
|
524
|
+
#
|
|
517
525
|
# @api private
|
|
518
526
|
def self.clear_git_version_cache
|
|
519
527
|
@git_version_cache_mutex.synchronize do
|
|
@@ -545,35 +553,135 @@ module Git
|
|
|
545
553
|
cached_git_version(path) { run_git_version(path) }
|
|
546
554
|
end
|
|
547
555
|
|
|
556
|
+
# Return the version of the git binary
|
|
557
|
+
#
|
|
558
|
+
# @param path [String] the path to the git binary
|
|
559
|
+
#
|
|
560
|
+
# @return [Git::Version] the parsed git version
|
|
561
|
+
#
|
|
562
|
+
# @raise [Git::UnexpectedResultError] if the version output cannot be parsed
|
|
563
|
+
#
|
|
564
|
+
# @raise [Git::FailedError] if the git binary exits with a non-zero status
|
|
565
|
+
#
|
|
566
|
+
# @raise [Git::Error] if the binary is not found or fails to launch
|
|
567
|
+
#
|
|
548
568
|
# @api private
|
|
569
|
+
#
|
|
549
570
|
def self.run_git_version(path)
|
|
550
571
|
output = Git::Commands::Version.new(Git::ExecutionContext::Global.new(binary_path: path)).call.stdout
|
|
551
572
|
Git::Version.parse(output)
|
|
552
573
|
end
|
|
553
574
|
private_class_method :run_git_version
|
|
554
575
|
|
|
576
|
+
# Get or set a git config value
|
|
577
|
+
#
|
|
578
|
+
# @overload legacy_config_set_get_list(name, value, global:)
|
|
579
|
+
#
|
|
580
|
+
# Set the value of a git configuration option
|
|
581
|
+
#
|
|
582
|
+
# @param name [String] the name of the git configuration value to set
|
|
583
|
+
#
|
|
584
|
+
# @param value [String, Boolean] the value to set
|
|
585
|
+
#
|
|
586
|
+
# @param global [Boolean] true to use the global git configuration, false for the
|
|
587
|
+
# local repo config
|
|
588
|
+
#
|
|
589
|
+
# @return [Git::CommandLine::Result] the result of the git config command
|
|
590
|
+
#
|
|
591
|
+
# @overload legacy_config_set_get_list(name, global:)
|
|
592
|
+
#
|
|
593
|
+
# Get the value of a git configuration option
|
|
594
|
+
#
|
|
595
|
+
# @param name [String] the name of the git configuration value to get
|
|
596
|
+
#
|
|
597
|
+
# @param global [Boolean] true to use the global git configuration, false for the
|
|
598
|
+
# local repo config
|
|
599
|
+
#
|
|
600
|
+
# @return [String] the value of the git configuration option
|
|
601
|
+
#
|
|
602
|
+
# @overload legacy_config_set_get_list(global:)
|
|
603
|
+
#
|
|
604
|
+
# Get all git configuration options
|
|
605
|
+
#
|
|
606
|
+
# @param global [Boolean] true to use the global git configuration, false for the
|
|
607
|
+
# local repo config
|
|
608
|
+
#
|
|
609
|
+
# @return [Hash{String => String}] all git configuration options
|
|
610
|
+
#
|
|
611
|
+
# @raise [Git::FailedError] if the git config command fails
|
|
612
|
+
#
|
|
555
613
|
# @api private
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
614
|
+
#
|
|
615
|
+
def self.legacy_config_set_get_list(name, value, global:)
|
|
616
|
+
if !name.nil? && !value.nil?
|
|
617
|
+
legacy_config_set(name, value, global:)
|
|
618
|
+
elsif !name.nil?
|
|
619
|
+
legacy_config_get(name, global:)
|
|
620
|
+
else
|
|
621
|
+
legacy_config_list(global:)
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
private_class_method :legacy_config_set_get_list
|
|
562
625
|
|
|
563
|
-
|
|
564
|
-
|
|
626
|
+
# Set the value of a git configuration option
|
|
627
|
+
#
|
|
628
|
+
# @param name [String] the name of the git configuration value to set
|
|
629
|
+
#
|
|
630
|
+
# @param value [String, Boolean] the value to set
|
|
631
|
+
#
|
|
632
|
+
# @param global [Boolean] whether to use the global git configuration
|
|
633
|
+
#
|
|
634
|
+
# @api private
|
|
635
|
+
#
|
|
636
|
+
def self.legacy_config_set(name, value, global:)
|
|
637
|
+
options = global ? { global: true } : {}
|
|
638
|
+
Git::Commands::ConfigOptionSyntax::Set.new(execution_context).call(name, value, **options)
|
|
565
639
|
end
|
|
566
|
-
private_class_method :
|
|
640
|
+
private_class_method :legacy_config_set
|
|
567
641
|
|
|
568
|
-
|
|
569
|
-
|
|
642
|
+
# Get the value of a git configuration option
|
|
643
|
+
#
|
|
644
|
+
# @param name [String] the name of the git configuration option
|
|
645
|
+
#
|
|
646
|
+
# @param global [Boolean] whether to use the global git configuration
|
|
647
|
+
#
|
|
648
|
+
# @return [String] the value of the git configuration option
|
|
649
|
+
#
|
|
650
|
+
# @api private
|
|
651
|
+
#
|
|
652
|
+
def self.legacy_config_get(name, global:)
|
|
653
|
+
options = global ? { global: true } : {}
|
|
654
|
+
result = Git::Commands::ConfigOptionSyntax::Get.new(execution_context).call(name, **options)
|
|
570
655
|
raise Git::FailedError, result if result.status.exitstatus != 0
|
|
571
656
|
|
|
572
657
|
result.stdout
|
|
573
658
|
end
|
|
574
|
-
private_class_method :
|
|
659
|
+
private_class_method :legacy_config_get
|
|
660
|
+
|
|
661
|
+
# Get a list of all git configuration options
|
|
662
|
+
#
|
|
663
|
+
# @param global [Boolean] true to use the global git configuration, false for the
|
|
664
|
+
# local repo config
|
|
665
|
+
#
|
|
666
|
+
# @return [Hash{String => String}] all git configuration options
|
|
667
|
+
#
|
|
668
|
+
# @api private
|
|
669
|
+
#
|
|
670
|
+
def self.legacy_config_list(global:)
|
|
671
|
+
options = global ? { global: true } : {}
|
|
672
|
+
output = Git::Commands::ConfigOptionSyntax::List.new(execution_context).call(**options).stdout
|
|
673
|
+
parse_config_list(output.split("\n"))
|
|
674
|
+
end
|
|
675
|
+
private_class_method :legacy_config_list
|
|
575
676
|
|
|
677
|
+
# Parse the output of `git config --list` into a hash
|
|
678
|
+
#
|
|
679
|
+
# @param lines [Array<String>] the lines of output from `git config --list`
|
|
680
|
+
#
|
|
681
|
+
# @return [Hash{String => String}] the parsed git configuration options
|
|
682
|
+
#
|
|
576
683
|
# @api private
|
|
684
|
+
#
|
|
577
685
|
def self.parse_config_list(lines)
|
|
578
686
|
lines.each_with_object({}) do |line, hsh|
|
|
579
687
|
key, value = line.split('=', 2)
|
|
@@ -600,10 +708,23 @@ module Git
|
|
|
600
708
|
# The +:local+, +:worktree+, and +:blob+ scopes require an active git
|
|
601
709
|
# repository and are therefore not valid at the Git module level.
|
|
602
710
|
#
|
|
711
|
+
# @param options_to_check [Hash{Symbol => Object}] the scope options to check
|
|
712
|
+
#
|
|
713
|
+
# If any of the options listed in +REPOSITORY_SPECIFIC_SCOPES+ are present and
|
|
714
|
+
# truthy, an +ArgumentError+ will be raised.
|
|
715
|
+
#
|
|
716
|
+
# @option options_to_check [Object] :local truthy value requests local scope
|
|
717
|
+
#
|
|
718
|
+
# @option options_to_check [Object] :worktree truthy value requests worktree scope
|
|
719
|
+
#
|
|
720
|
+
# @option options_to_check [Object] :blob truthy value requests blob scope
|
|
721
|
+
#
|
|
722
|
+
# @raise [ArgumentError] if a repository-specific scope is requested
|
|
723
|
+
#
|
|
603
724
|
# @api private
|
|
604
725
|
#
|
|
605
|
-
def self.assert_valid_scope!(**
|
|
606
|
-
invalid = REPOSITORY_SPECIFIC_SCOPES.select { |s|
|
|
726
|
+
def self.assert_valid_scope!(**options_to_check)
|
|
727
|
+
invalid = REPOSITORY_SPECIFIC_SCOPES.select { |s| options_to_check[s] }
|
|
607
728
|
return if invalid.empty?
|
|
608
729
|
|
|
609
730
|
raise ArgumentError, "#{invalid.join(', ')} scope requires a repository"
|