git 1.19.1 → 5.5.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/.yardopts +5 -1
- data/AI_POLICY.md +24 -0
- data/CHANGELOG.md +689 -0
- data/CODE_OF_CONDUCT.md +25 -0
- data/CONTRIBUTING.md +1175 -97
- data/GOVERNANCE.md +106 -0
- data/LICENSE +1 -1
- data/MAINTAINERS.md +17 -4
- data/README.md +476 -320
- data/UPGRADING.md +1138 -0
- data/git.gemspec +124 -36
- data/lib/git/author.rb +39 -7
- data/lib/git/author_info.rb +66 -0
- data/lib/git/branch.rb +615 -65
- data/lib/git/branch_delete_failure.rb +34 -0
- data/lib/git/branch_delete_result.rb +66 -0
- data/lib/git/branch_info.rb +237 -0
- data/lib/git/branches.rb +167 -44
- data/lib/git/command_line/base.rb +247 -0
- data/lib/git/command_line/capturing.rb +308 -0
- data/lib/git/command_line/result.rb +88 -0
- data/lib/git/command_line/streaming.rb +236 -0
- data/lib/git/command_line.rb +52 -0
- data/lib/git/commands/add.rb +139 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +263 -0
- data/lib/git/commands/am/continue.rb +43 -0
- data/lib/git/commands/am/quit.rb +43 -0
- data/lib/git/commands/am/retry.rb +49 -0
- data/lib/git/commands/am/show_current_patch.rb +64 -0
- data/lib/git/commands/am/skip.rb +42 -0
- data/lib/git/commands/am.rb +33 -0
- data/lib/git/commands/apply.rb +242 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +145 -0
- data/lib/git/commands/arguments.rb +4521 -0
- data/lib/git/commands/base.rb +502 -0
- data/lib/git/commands/branch/copy.rb +102 -0
- data/lib/git/commands/branch/create.rb +177 -0
- data/lib/git/commands/branch/delete.rb +88 -0
- data/lib/git/commands/branch/list.rb +178 -0
- data/lib/git/commands/branch/move.rb +102 -0
- data/lib/git/commands/branch/set_upstream.rb +86 -0
- data/lib/git/commands/branch/show_current.rb +49 -0
- data/lib/git/commands/branch/unset_upstream.rb +53 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +385 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +271 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +153 -0
- data/lib/git/commands/checkout/files.rb +116 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +106 -0
- data/lib/git/commands/clean.rb +102 -0
- data/lib/git/commands/clone.rb +241 -0
- data/lib/git/commands/commit.rb +273 -0
- data/lib/git/commands/commit_tree.rb +101 -0
- data/lib/git/commands/config_option_syntax/add.rb +86 -0
- data/lib/git/commands/config_option_syntax/get.rb +121 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
- data/lib/git/commands/config_option_syntax/list.rb +111 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
- data/lib/git/commands/config_option_syntax/set.rb +119 -0
- data/lib/git/commands/config_option_syntax/unset.rb +92 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +156 -0
- data/lib/git/commands/diff.rb +657 -0
- data/lib/git/commands/diff_files.rb +519 -0
- data/lib/git/commands/diff_index.rb +499 -0
- data/lib/git/commands/fetch.rb +354 -0
- data/lib/git/commands/fsck.rb +138 -0
- data/lib/git/commands/gc.rb +134 -0
- data/lib/git/commands/grep.rb +339 -0
- data/lib/git/commands/init.rb +101 -0
- data/lib/git/commands/log.rb +634 -0
- data/lib/git/commands/ls_files.rb +195 -0
- data/lib/git/commands/ls_remote.rb +161 -0
- data/lib/git/commands/ls_tree.rb +135 -0
- data/lib/git/commands/maintenance/register.rb +77 -0
- data/lib/git/commands/maintenance/run.rb +109 -0
- data/lib/git/commands/maintenance/start.rb +71 -0
- data/lib/git/commands/maintenance/stop.rb +60 -0
- data/lib/git/commands/maintenance/unregister.rb +84 -0
- data/lib/git/commands/maintenance.rb +31 -0
- data/lib/git/commands/merge/abort.rb +44 -0
- data/lib/git/commands/merge/continue.rb +44 -0
- data/lib/git/commands/merge/quit.rb +46 -0
- data/lib/git/commands/merge/start.rb +250 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +91 -0
- data/lib/git/commands/mv.rb +82 -0
- data/lib/git/commands/name_rev.rb +119 -0
- data/lib/git/commands/pull.rb +382 -0
- data/lib/git/commands/push.rb +251 -0
- data/lib/git/commands/read_tree.rb +154 -0
- data/lib/git/commands/remote/add.rb +96 -0
- data/lib/git/commands/remote/get_url.rb +68 -0
- data/lib/git/commands/remote/list.rb +56 -0
- data/lib/git/commands/remote/prune.rb +63 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +76 -0
- data/lib/git/commands/remote/set_branches.rb +70 -0
- data/lib/git/commands/remote/set_head.rb +89 -0
- data/lib/git/commands/remote/set_url.rb +78 -0
- data/lib/git/commands/remote/set_url_add.rb +70 -0
- data/lib/git/commands/remote/set_url_delete.rb +71 -0
- data/lib/git/commands/remote/show.rb +77 -0
- data/lib/git/commands/remote/update.rb +79 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +281 -0
- data/lib/git/commands/reset.rb +154 -0
- data/lib/git/commands/rev_parse.rb +304 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +62 -0
- data/lib/git/commands/revert/quit.rb +47 -0
- data/lib/git/commands/revert/skip.rb +44 -0
- data/lib/git/commands/revert/start.rb +158 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +113 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
- data/lib/git/commands/show_ref/exists.rb +80 -0
- data/lib/git/commands/show_ref/list.rb +149 -0
- data/lib/git/commands/show_ref/verify.rb +122 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +81 -0
- data/lib/git/commands/stash/branch.rb +67 -0
- data/lib/git/commands/stash/clear.rb +43 -0
- data/lib/git/commands/stash/create.rb +60 -0
- data/lib/git/commands/stash/drop.rb +73 -0
- data/lib/git/commands/stash/list.rb +43 -0
- data/lib/git/commands/stash/pop.rb +87 -0
- data/lib/git/commands/stash/push.rb +112 -0
- data/lib/git/commands/stash/show.rb +158 -0
- data/lib/git/commands/stash/store.rb +72 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +174 -0
- data/lib/git/commands/symbolic_ref/delete.rb +72 -0
- data/lib/git/commands/symbolic_ref/read.rb +99 -0
- data/lib/git/commands/symbolic_ref/update.rb +79 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +142 -0
- data/lib/git/commands/tag/delete.rb +57 -0
- data/lib/git/commands/tag/list.rb +146 -0
- data/lib/git/commands/tag/verify.rb +71 -0
- data/lib/git/commands/tag.rb +26 -0
- data/lib/git/commands/update_ref/batch.rb +145 -0
- data/lib/git/commands/update_ref/delete.rb +90 -0
- data/lib/git/commands/update_ref/update.rb +103 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +60 -0
- data/lib/git/commands/worktree/add.rb +139 -0
- data/lib/git/commands/worktree/list.rb +64 -0
- data/lib/git/commands/worktree/lock.rb +58 -0
- data/lib/git/commands/worktree/management_base.rb +51 -0
- data/lib/git/commands/worktree/move.rb +66 -0
- data/lib/git/commands/worktree/prune.rb +67 -0
- data/lib/git/commands/worktree/remove.rb +63 -0
- data/lib/git/commands/worktree/repair.rb +76 -0
- data/lib/git/commands/worktree/unlock.rb +47 -0
- data/lib/git/commands/worktree.rb +43 -0
- data/lib/git/commands/write_tree.rb +68 -0
- data/lib/git/commands.rb +88 -0
- data/lib/git/config.rb +72 -5
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +795 -0
- data/lib/git/detached_head_info.rb +57 -0
- data/lib/git/diff.rb +437 -86
- data/lib/git/diff_file_numstat_info.rb +31 -0
- data/lib/git/diff_file_patch_info.rb +136 -0
- data/lib/git/diff_file_raw_info.rb +129 -0
- data/lib/git/diff_info.rb +162 -0
- data/lib/git/diff_path_status.rb +107 -0
- data/lib/git/diff_result.rb +34 -0
- data/lib/git/diff_stats.rb +111 -0
- data/lib/git/dirstat_info.rb +102 -0
- data/lib/git/encoding_utils.rb +32 -1
- data/lib/git/errors.rb +285 -0
- data/lib/git/escaped_path.rb +57 -5
- data/lib/git/execution_context/global.rb +31 -0
- data/lib/git/execution_context/repository.rb +151 -0
- data/lib/git/execution_context.rb +559 -0
- data/lib/git/factories.rb +813 -0
- data/lib/git/file_ref.rb +77 -0
- data/lib/git/fsck_object.rb +56 -0
- data/lib/git/fsck_result.rb +132 -0
- data/lib/git/log.rb +306 -90
- data/lib/git/object.rb +563 -141
- data/lib/git/parsers/branch.rb +240 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/config_entry.rb +110 -0
- data/lib/git/parsers/diff.rb +792 -0
- data/lib/git/parsers/fsck.rb +144 -0
- data/lib/git/parsers/grep.rb +42 -0
- data/lib/git/parsers/ls_remote.rb +79 -0
- data/lib/git/parsers/ls_tree.rb +58 -0
- data/lib/git/parsers/remote.rb +162 -0
- data/lib/git/parsers/stash.rb +292 -0
- data/lib/git/parsers/status.rb +251 -0
- data/lib/git/parsers/tag.rb +341 -0
- data/lib/git/parsers/worktree.rb +185 -0
- data/lib/git/path_resolver.rb +206 -0
- data/lib/git/remote.rb +165 -12
- data/lib/git/remote_info.rb +203 -0
- data/lib/git/repository/branching.rb +964 -0
- data/lib/git/repository/committing.rb +246 -0
- data/lib/git/repository/context_helpers.rb +293 -0
- data/lib/git/repository/diffing.rb +785 -0
- data/lib/git/repository/inspecting.rb +252 -0
- data/lib/git/repository/logging.rb +410 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +451 -0
- data/lib/git/repository/object_operations.rb +1551 -0
- data/lib/git/repository/remote_operations.rb +984 -0
- data/lib/git/repository/shared_private.rb +120 -0
- data/lib/git/repository/staging.rb +587 -0
- data/lib/git/repository/stashing.rb +623 -0
- data/lib/git/repository/status_operations.rb +249 -0
- data/lib/git/repository/worktree_operations.rb +339 -0
- data/lib/git/repository.rb +484 -2
- data/lib/git/stash.rb +109 -12
- data/lib/git/stash_info.rb +102 -0
- data/lib/git/stashes.rb +169 -26
- data/lib/git/status.rb +308 -122
- data/lib/git/status_file_info.rb +258 -0
- data/lib/git/status_info.rb +189 -0
- data/lib/git/tag_delete_failure.rb +34 -0
- data/lib/git/tag_delete_result.rb +66 -0
- data/lib/git/tag_info.rb +99 -0
- data/lib/git/url.rb +15 -8
- data/lib/git/version.rb +113 -2
- data/lib/git/version_constraint.rb +85 -0
- data/lib/git/worktree.rb +150 -8
- data/lib/git/worktree_info.rb +128 -0
- data/lib/git/worktrees.rb +118 -13
- data/lib/git.rb +632 -234
- metadata +369 -54
- data/.github/stale.yml +0 -25
- data/.github/workflows/continuous_integration.yml +0 -49
- data/.gitignore +0 -10
- data/Dockerfile.changelog-rs +0 -12
- data/Gemfile +0 -5
- data/ISSUE_TEMPLATE.md +0 -15
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/RELEASING.md +0 -70
- data/Rakefile +0 -60
- data/lib/git/base/factory.rb +0 -99
- data/lib/git/base.rb +0 -711
- data/lib/git/command_line_result.rb +0 -86
- data/lib/git/failed_error.rb +0 -53
- data/lib/git/git_execute_error.rb +0 -7
- data/lib/git/index.rb +0 -5
- data/lib/git/lib.rb +0 -1328
- data/lib/git/path.rb +0 -31
- data/lib/git/signaled_error.rb +0 -50
- data/lib/git/working_directory.rb +0 -4
data/lib/git/repository.rb
CHANGED
|
@@ -1,6 +1,488 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'find'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
|
|
6
|
+
require 'git/configuring'
|
|
7
|
+
require 'git/execution_context/repository'
|
|
8
|
+
require 'git/repository/branching'
|
|
9
|
+
require 'git/repository/context_helpers'
|
|
10
|
+
require 'git/repository/committing'
|
|
11
|
+
require 'git/repository/diffing'
|
|
12
|
+
require 'git/repository/inspecting'
|
|
13
|
+
require 'git/repository/logging'
|
|
14
|
+
require 'git/repository/maintenance'
|
|
15
|
+
require 'git/repository/merging'
|
|
16
|
+
require 'git/repository/object_operations'
|
|
17
|
+
require 'git/repository/remote_operations'
|
|
18
|
+
require 'git/repository/shared_private'
|
|
19
|
+
require 'git/repository/staging'
|
|
20
|
+
require 'git/repository/stashing'
|
|
21
|
+
require 'git/repository/status_operations'
|
|
22
|
+
require 'git/repository/worktree_operations'
|
|
23
|
+
|
|
1
24
|
module Git
|
|
25
|
+
# The main public interface for interacting with a Git repository
|
|
26
|
+
#
|
|
27
|
+
# `Git::Repository` is the **orchestration layer** for all git operations. It acts
|
|
28
|
+
# as the glue between the user-facing API and the underlying components, but
|
|
29
|
+
# contains minimal domain logic itself. For each operation it:
|
|
30
|
+
#
|
|
31
|
+
# 1. **Pre-processes arguments** — transforms user-provided values into forms
|
|
32
|
+
# suitable for the command layer (e.g. path expansion, option normalization,
|
|
33
|
+
# Ruby-idiomatic defaults, deprecation handling, input validation).
|
|
34
|
+
# 2. **Calls commands** — invokes one or more `Git::Commands::*` classes via the
|
|
35
|
+
# injected `Git::ExecutionContext::Repository`.
|
|
36
|
+
# 3. **Builds rich return values** — passes raw command output through
|
|
37
|
+
# `Git::Parsers::*` classes and result-class factory methods to assemble the
|
|
38
|
+
# meaningful Ruby objects the caller expects.
|
|
39
|
+
#
|
|
40
|
+
# Some operations are genuinely one-line delegators when no pre/post-processing is
|
|
41
|
+
# needed (e.g. `add`, `reset`), but many are short orchestration sequences that
|
|
42
|
+
# coordinate argument preparation, one or more command calls, and result assembly.
|
|
43
|
+
#
|
|
44
|
+
# Facade methods are organized into focused modules under `lib/git/repository/`
|
|
45
|
+
# (e.g. {Git::Repository::Staging}) and included into this class.
|
|
46
|
+
#
|
|
47
|
+
# @api public
|
|
48
|
+
#
|
|
49
|
+
class Repository # rubocop:disable Metrics/ClassLength
|
|
50
|
+
include Git::Configuring
|
|
51
|
+
include Git::Repository::Branching
|
|
52
|
+
include Git::Repository::ContextHelpers
|
|
53
|
+
include Git::Repository::Committing
|
|
54
|
+
include Git::Repository::Diffing
|
|
55
|
+
include Git::Repository::Inspecting
|
|
56
|
+
include Git::Repository::Logging
|
|
57
|
+
include Git::Repository::Maintenance
|
|
58
|
+
include Git::Repository::Merging
|
|
59
|
+
include Git::Repository::ObjectOperations
|
|
60
|
+
include Git::Repository::RemoteOperations
|
|
61
|
+
include Git::Repository::Staging
|
|
62
|
+
include Git::Repository::Stashing
|
|
63
|
+
include Git::Repository::StatusOperations
|
|
64
|
+
include Git::Repository::WorktreeOperations
|
|
2
65
|
|
|
3
|
-
|
|
4
|
-
|
|
66
|
+
# Allowed keyword options for deprecated config write operations
|
|
67
|
+
#
|
|
68
|
+
# @return [Array<Symbol>] accepted option keys
|
|
69
|
+
#
|
|
70
|
+
CONFIG_SET_ALLOWED_OPTS = %i[file].freeze
|
|
71
|
+
private_constant :CONFIG_SET_ALLOWED_OPTS
|
|
72
|
+
|
|
73
|
+
# Allowed keyword options for deprecated config read operations
|
|
74
|
+
#
|
|
75
|
+
# @return [Array<Symbol>] accepted option keys
|
|
76
|
+
#
|
|
77
|
+
CONFIG_READ_ALLOWED_OPTS = %i[file].freeze
|
|
78
|
+
private_constant :CONFIG_READ_ALLOWED_OPTS
|
|
79
|
+
|
|
80
|
+
# Deprecation warning emitted by {#config}
|
|
81
|
+
#
|
|
82
|
+
# @return [String] the warning message shown to callers
|
|
83
|
+
#
|
|
84
|
+
CONFIG_DEPRECATION_WARNING =
|
|
85
|
+
'Git::Repository#config is deprecated and will be removed in v6.0.0. ' \
|
|
86
|
+
'Use config_get(name), config_set(name, value), or config_list instead.'
|
|
87
|
+
private_constant :CONFIG_DEPRECATION_WARNING
|
|
88
|
+
|
|
89
|
+
# Deprecation warning emitted by {#global_config}
|
|
90
|
+
#
|
|
91
|
+
# @return [String] the warning message shown to callers
|
|
92
|
+
#
|
|
93
|
+
GLOBAL_CONFIG_DEPRECATION_WARNING =
|
|
94
|
+
'Git::Repository#global_config is deprecated and will be removed in v6.0.0. ' \
|
|
95
|
+
'Use config_get(name, global: true), config_set(name, value, global: true), ' \
|
|
96
|
+
'or config_list(global: true) instead.'
|
|
97
|
+
private_constant :GLOBAL_CONFIG_DEPRECATION_WARNING
|
|
98
|
+
|
|
99
|
+
# @return [Git::ExecutionContext::Repository] the execution context used to run
|
|
100
|
+
# git commands for this repository
|
|
101
|
+
#
|
|
102
|
+
# @api private
|
|
103
|
+
attr_reader :execution_context
|
|
104
|
+
|
|
105
|
+
# @param execution_context [Git::ExecutionContext::Repository] the context used
|
|
106
|
+
# to run git commands for this repository; must not be nil
|
|
107
|
+
#
|
|
108
|
+
# @raise [ArgumentError] if `execution_context` is nil
|
|
109
|
+
#
|
|
110
|
+
def initialize(execution_context:)
|
|
111
|
+
raise ArgumentError, 'execution_context must not be nil' if execution_context.nil?
|
|
112
|
+
|
|
113
|
+
@execution_context = execution_context
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Returns the root of the working tree, or `nil` for a bare repository
|
|
117
|
+
#
|
|
118
|
+
# @example Get the working directory path
|
|
119
|
+
# repository.dir #=> #<Pathname:/path/to/repo>
|
|
120
|
+
#
|
|
121
|
+
# @return [Pathname, nil] the working directory path, or `nil` when bare
|
|
122
|
+
#
|
|
123
|
+
def dir
|
|
124
|
+
working_dir = execution_context.git_work_dir
|
|
125
|
+
working_dir && Pathname.new(working_dir)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Returns the repository (`.git`) directory
|
|
129
|
+
#
|
|
130
|
+
# @example Get the repository directory path
|
|
131
|
+
# repository.repo #=> #<Pathname:/path/to/repo/.git>
|
|
132
|
+
#
|
|
133
|
+
# @return [Pathname, nil] the repository directory path
|
|
134
|
+
#
|
|
135
|
+
def repo
|
|
136
|
+
repository = execution_context.git_dir
|
|
137
|
+
repository && Pathname.new(repository)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Returns the git index file
|
|
141
|
+
#
|
|
142
|
+
# @example Get the index file path
|
|
143
|
+
# repository.index #=> #<Pathname:/path/to/repo/.git/index>
|
|
144
|
+
#
|
|
145
|
+
# @return [Pathname, nil] the index file path
|
|
146
|
+
#
|
|
147
|
+
def index
|
|
148
|
+
index_file = execution_context.git_index_file
|
|
149
|
+
index_file && Pathname.new(index_file)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Returns `self` after emitting a deprecation warning.
|
|
153
|
+
#
|
|
154
|
+
# Legacy callers that used `git.lib.some_method` can migrate to calling the
|
|
155
|
+
# facade method directly on the repository object. This shim will be removed
|
|
156
|
+
# in v6.0.0.
|
|
157
|
+
#
|
|
158
|
+
# @return [self]
|
|
159
|
+
#
|
|
160
|
+
# @api private
|
|
161
|
+
#
|
|
162
|
+
def lib
|
|
163
|
+
Git::Deprecation.warn(
|
|
164
|
+
'Git::Repository#lib is deprecated and will be removed in v6.0.0. ' \
|
|
165
|
+
'Use the repository object directly.'
|
|
166
|
+
)
|
|
167
|
+
self
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @return [String, nil] the git directory path
|
|
171
|
+
#
|
|
172
|
+
# @api private
|
|
173
|
+
def git_dir = execution_context.git_dir
|
|
174
|
+
|
|
175
|
+
# @return [String, nil] the working directory path
|
|
176
|
+
#
|
|
177
|
+
# @api private
|
|
178
|
+
def git_work_dir = execution_context.git_work_dir
|
|
179
|
+
|
|
180
|
+
# @return [String, nil] the index file path
|
|
181
|
+
#
|
|
182
|
+
# @api private
|
|
183
|
+
def git_index_file = execution_context.git_index_file
|
|
184
|
+
|
|
185
|
+
# Returns the installed git version
|
|
186
|
+
#
|
|
187
|
+
# @param timeout [Numeric, nil] seconds to wait for `git version`; `nil`
|
|
188
|
+
# uses the default timeout for this execution context
|
|
189
|
+
#
|
|
190
|
+
# @return [Git::Version] the installed git version
|
|
191
|
+
#
|
|
192
|
+
# @api private
|
|
193
|
+
def git_version(timeout: nil) = execution_context.git_version(timeout: timeout)
|
|
194
|
+
|
|
195
|
+
# @return [String, nil] the SSH wrapper path
|
|
196
|
+
#
|
|
197
|
+
# @api private
|
|
198
|
+
def git_ssh = execution_context.git_ssh
|
|
5
199
|
|
|
200
|
+
# @return [String, :use_global_config] the path to the git binary
|
|
201
|
+
#
|
|
202
|
+
# @api private
|
|
203
|
+
def binary_path = execution_context.binary_path
|
|
204
|
+
|
|
205
|
+
# Reads or writes a git configuration entry
|
|
206
|
+
#
|
|
207
|
+
# Dispatches to one of three modes depending on the arguments supplied:
|
|
208
|
+
#
|
|
209
|
+
# * **List** — `config()` returns all visible config entries as a `Hash`.
|
|
210
|
+
# * **Get** — `config(name)` returns the value for a single key as a `String`.
|
|
211
|
+
# * **Set** — `config(name, value)` writes a value and returns the raw
|
|
212
|
+
# command result.
|
|
213
|
+
#
|
|
214
|
+
# @example List all config entries
|
|
215
|
+
# repo.config #=> { "user.name" => "Alice", "core.bare" => "false" }
|
|
216
|
+
#
|
|
217
|
+
# @example Read a config value
|
|
218
|
+
# repo.config('user.name') #=> "Alice"
|
|
219
|
+
#
|
|
220
|
+
# @example Set a config value
|
|
221
|
+
# repo.config('user.name', 'Alice')
|
|
222
|
+
#
|
|
223
|
+
# @param name [String, Hash, nil] the dotted config key, or an options hash
|
|
224
|
+
# for list mode when `value` and `options` are omitted
|
|
225
|
+
#
|
|
226
|
+
# @param value [#to_s, Hash, nil] the value to set, or an options hash in the
|
|
227
|
+
# legacy `config(name, options)` call shape
|
|
228
|
+
#
|
|
229
|
+
# @param options [Hash] options forwarded to git config
|
|
230
|
+
#
|
|
231
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
232
|
+
#
|
|
233
|
+
# @return [Hash{String => String}, String, Git::CommandLine::Result] all config
|
|
234
|
+
# entries, a single value, or the command result for set mode
|
|
235
|
+
#
|
|
236
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
237
|
+
#
|
|
238
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
239
|
+
#
|
|
240
|
+
def config(name = nil, value = nil, options = {})
|
|
241
|
+
Git::Deprecation.warn(CONFIG_DEPRECATION_WARNING)
|
|
242
|
+
name, value, options = deprecated_normalize_config_args(name, value, options)
|
|
243
|
+
|
|
244
|
+
if !name.nil? && !value.nil?
|
|
245
|
+
deprecated_config_set(name, value, **options)
|
|
246
|
+
elsif name
|
|
247
|
+
deprecated_config_get(name, **options)
|
|
248
|
+
else
|
|
249
|
+
deprecated_config_list(**options)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Read or write a global git configuration entry
|
|
254
|
+
#
|
|
255
|
+
# Dispatches to one of three modes depending on the arguments supplied,
|
|
256
|
+
# targeting the git global config scope (`git config --global`):
|
|
257
|
+
#
|
|
258
|
+
# * **List** — `global_config()` returns all global config entries as a `Hash`.
|
|
259
|
+
# * **Get** — `global_config(name)` returns the value for a single key as a `String`.
|
|
260
|
+
# * **Set** — `global_config(name, value)` writes a value and returns the raw
|
|
261
|
+
# command result.
|
|
262
|
+
#
|
|
263
|
+
# @overload global_config
|
|
264
|
+
#
|
|
265
|
+
# @example List all global config entries
|
|
266
|
+
# repo.global_config #=> { "user.name" => "Alice", "core.autocrlf" => "false" }
|
|
267
|
+
#
|
|
268
|
+
# @return [Hash{String => String}] all global config entries, keyed by their
|
|
269
|
+
# full dotted key names (e.g. `"user.name"`)
|
|
270
|
+
#
|
|
271
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
272
|
+
#
|
|
273
|
+
# @overload global_config(name)
|
|
274
|
+
#
|
|
275
|
+
# @example Read the global committer name
|
|
276
|
+
# repo.global_config('user.name') #=> "Alice"
|
|
277
|
+
#
|
|
278
|
+
# @param name [String] the dotted config key to look up (e.g. `"user.name"`)
|
|
279
|
+
#
|
|
280
|
+
# @return [String] the value of the global config entry
|
|
281
|
+
#
|
|
282
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
283
|
+
#
|
|
284
|
+
# @overload global_config(name, value)
|
|
285
|
+
#
|
|
286
|
+
# @example Set the global committer name
|
|
287
|
+
# repo.global_config('user.name', 'Alice')
|
|
288
|
+
#
|
|
289
|
+
# @param name [String] the dotted config key to write (e.g. `"user.name"`)
|
|
290
|
+
#
|
|
291
|
+
# @param value [#to_s] the value to assign; any object is accepted and
|
|
292
|
+
# converted to a String via `#to_s` before being passed to git
|
|
293
|
+
#
|
|
294
|
+
# @return [Git::CommandLine::Result] the raw result of
|
|
295
|
+
# `git config --global <name> <value>`
|
|
296
|
+
#
|
|
297
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
298
|
+
#
|
|
299
|
+
def global_config(name = nil, value = nil)
|
|
300
|
+
Git::Deprecation.warn(GLOBAL_CONFIG_DEPRECATION_WARNING)
|
|
301
|
+
if !name.nil? && !value.nil?
|
|
302
|
+
deprecated_global_config_set(name, value)
|
|
303
|
+
elsif !name.nil?
|
|
304
|
+
deprecated_global_config_get(name)
|
|
305
|
+
else
|
|
306
|
+
deprecated_global_config_list
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Returns the size of the repository directory in bytes
|
|
311
|
+
#
|
|
312
|
+
# Sums the sizes of every regular file under the repository (`.git`)
|
|
313
|
+
# directory in a single traversal. Symbolic links are not followed, so files
|
|
314
|
+
# that physically live outside the repository (reached through a symlinked
|
|
315
|
+
# directory) are never counted. Files that disappear mid-traversal are
|
|
316
|
+
# silently skipped.
|
|
317
|
+
#
|
|
318
|
+
# @example Get the repository size in bytes
|
|
319
|
+
# repository.repo_size #=> 12345
|
|
320
|
+
#
|
|
321
|
+
# @return [Integer] the total size in bytes of the repository directory
|
|
322
|
+
#
|
|
323
|
+
def repo_size
|
|
324
|
+
repository = repo
|
|
325
|
+
return 0 unless repository&.directory?
|
|
326
|
+
|
|
327
|
+
total = 0
|
|
328
|
+
Find.find(repository.to_s) do |path|
|
|
329
|
+
stat = File.lstat(path)
|
|
330
|
+
total += stat.size if stat.file?
|
|
331
|
+
rescue Errno::ENOENT
|
|
332
|
+
next
|
|
333
|
+
end
|
|
334
|
+
total
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
private
|
|
338
|
+
|
|
339
|
+
# Normalizes deprecated `config` call shapes into positional arguments
|
|
340
|
+
#
|
|
341
|
+
# @param name [String, Hash, nil] config key or an options hash
|
|
342
|
+
#
|
|
343
|
+
# @param value [#to_s, Hash, nil] config value or an options hash
|
|
344
|
+
#
|
|
345
|
+
# @param options [Hash] explicit options hash argument
|
|
346
|
+
#
|
|
347
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
348
|
+
#
|
|
349
|
+
# @return [Array((String, nil), (#to_s, nil), Hash)] normalized
|
|
350
|
+
# `[name, value, options]`
|
|
351
|
+
#
|
|
352
|
+
# @raise [ArgumentError] if deprecated arguments mix an options hash with
|
|
353
|
+
# unexpected additional positional arguments
|
|
354
|
+
#
|
|
355
|
+
def deprecated_normalize_config_args(name, value, options)
|
|
356
|
+
if name.is_a?(Hash)
|
|
357
|
+
raise ArgumentError, 'unexpected positional arguments after options hash' if !value.nil? || !options.empty?
|
|
358
|
+
|
|
359
|
+
[nil, nil, name]
|
|
360
|
+
elsif value.is_a?(Hash)
|
|
361
|
+
raise ArgumentError, 'unexpected third argument when second argument is options hash' unless options.empty?
|
|
362
|
+
|
|
363
|
+
[name, nil, value]
|
|
364
|
+
else
|
|
365
|
+
[name, value, options]
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# Writes a config value using the deprecated `config(name, value, ...)` path
|
|
370
|
+
#
|
|
371
|
+
# @overload deprecated_config_set(name, value, **options)
|
|
372
|
+
#
|
|
373
|
+
# @param name [String] the dotted config key to write
|
|
374
|
+
#
|
|
375
|
+
# @param value [#to_s] the value to assign
|
|
376
|
+
#
|
|
377
|
+
# @param options [Hash] command options
|
|
378
|
+
#
|
|
379
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
380
|
+
#
|
|
381
|
+
# @return [Git::CommandLine::Result] the command result
|
|
382
|
+
#
|
|
383
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
384
|
+
#
|
|
385
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
386
|
+
#
|
|
387
|
+
def deprecated_config_set(name, value, **)
|
|
388
|
+
SharedPrivate.assert_valid_opts!(CONFIG_SET_ALLOWED_OPTS, **)
|
|
389
|
+
Git::Commands::ConfigOptionSyntax::Set.new(@execution_context).call(name, value, **)
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# Reads a config value using the deprecated `config(name, ...)` path
|
|
393
|
+
#
|
|
394
|
+
# @param name [String] the dotted config key to read
|
|
395
|
+
#
|
|
396
|
+
# @param options [Hash] command options
|
|
397
|
+
#
|
|
398
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
399
|
+
#
|
|
400
|
+
# @return [String] the config value
|
|
401
|
+
#
|
|
402
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
403
|
+
#
|
|
404
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
405
|
+
#
|
|
406
|
+
def deprecated_config_get(name, **options)
|
|
407
|
+
SharedPrivate.assert_valid_opts!(CONFIG_READ_ALLOWED_OPTS, **options)
|
|
408
|
+
opts = options[:file] ? { file: options[:file] } : {}
|
|
409
|
+
result = Git::Commands::ConfigOptionSyntax::Get.new(@execution_context).call(name, **opts)
|
|
410
|
+
raise Git::FailedError, result if result.status.exitstatus != 0
|
|
411
|
+
|
|
412
|
+
result.stdout
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# Lists config entries using the deprecated `config(...)` path
|
|
416
|
+
#
|
|
417
|
+
# @param options [Hash] command options
|
|
418
|
+
#
|
|
419
|
+
# @option options [String, nil] :file (nil) path to a custom config file
|
|
420
|
+
#
|
|
421
|
+
# @return [Hash{String => String}] all visible config entries keyed by name
|
|
422
|
+
#
|
|
423
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
424
|
+
#
|
|
425
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
426
|
+
#
|
|
427
|
+
def deprecated_config_list(**options)
|
|
428
|
+
SharedPrivate.assert_valid_opts!(CONFIG_READ_ALLOWED_OPTS, **options)
|
|
429
|
+
opts = options[:file] ? { file: options[:file] } : {}
|
|
430
|
+
lines = Git::Commands::ConfigOptionSyntax::List.new(@execution_context).call(**opts).stdout.split("\n")
|
|
431
|
+
lines.each_with_object({}) do |line, hsh|
|
|
432
|
+
key, value = line.split('=', 2)
|
|
433
|
+
hsh[key] = value || ''
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
# Reads a global config value using the deprecated `global_config(name)` path
|
|
438
|
+
#
|
|
439
|
+
# @param name [String] the dotted config key to read
|
|
440
|
+
#
|
|
441
|
+
# @return [String] the config value
|
|
442
|
+
#
|
|
443
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
444
|
+
#
|
|
445
|
+
def deprecated_global_config_get(name)
|
|
446
|
+
result = Git::Commands::ConfigOptionSyntax::Get.new(@execution_context).call(name, global: true)
|
|
447
|
+
raise Git::FailedError, result if result.status.exitstatus != 0
|
|
448
|
+
|
|
449
|
+
result.stdout
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# Lists global config entries using the deprecated `global_config` path
|
|
453
|
+
#
|
|
454
|
+
# @return [Hash{String => String}] all global config entries keyed by name
|
|
455
|
+
#
|
|
456
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
457
|
+
#
|
|
458
|
+
def deprecated_global_config_list
|
|
459
|
+
lines = Git::Commands::ConfigOptionSyntax::List.new(@execution_context).call(global: true).stdout.split("\n")
|
|
460
|
+
lines.each_with_object({}) do |line, hsh|
|
|
461
|
+
key, value = line.split('=', 2)
|
|
462
|
+
hsh[key] = value || ''
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# Writes a global config value using the deprecated `global_config` path
|
|
467
|
+
#
|
|
468
|
+
# @param name [String] the dotted config key to write
|
|
469
|
+
#
|
|
470
|
+
# @param value [#to_s] the value to assign
|
|
471
|
+
#
|
|
472
|
+
# @return [Git::CommandLine::Result] the command result
|
|
473
|
+
#
|
|
474
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
475
|
+
#
|
|
476
|
+
def deprecated_global_config_set(name, value)
|
|
477
|
+
Git::Commands::ConfigOptionSyntax::Set.new(@execution_context).call(name, value, global: true)
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# All git config scopes are valid in a repository context
|
|
481
|
+
#
|
|
482
|
+
# @return [void]
|
|
483
|
+
#
|
|
484
|
+
def assert_valid_scope!(**)
|
|
485
|
+
nil
|
|
486
|
+
end
|
|
487
|
+
end
|
|
6
488
|
end
|
data/lib/git/stash.rb
CHANGED
|
@@ -1,27 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Git
|
|
4
|
+
# Represents a single stash entry in a Git repository
|
|
5
|
+
#
|
|
6
|
+
# This class is deprecated and will be removed in v6.0.0. Use the
|
|
7
|
+
# {Git::Repository} stash methods and {Git::StashInfo} instead:
|
|
8
|
+
# {Git::Repository#stash_push} replaces `Git::Stash.new(repo, message)` and
|
|
9
|
+
# returns a {Git::StashInfo}, or `nil` when there was nothing to stash.
|
|
10
|
+
#
|
|
11
|
+
# @example Create a stash and inspect the result (deprecated)
|
|
12
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
13
|
+
# stash.message #=> "WIP: feature work"
|
|
14
|
+
# stash.saved? #=> true
|
|
15
|
+
#
|
|
16
|
+
# @example The replacement
|
|
17
|
+
# info = repo.stash_push(message: 'WIP: feature work')
|
|
18
|
+
# info.message #=> "On main: WIP: feature work"
|
|
19
|
+
# info.nil? #=> false
|
|
20
|
+
#
|
|
21
|
+
# @deprecated Use {Git::Repository#stash_push} and {Git::StashInfo} instead
|
|
22
|
+
#
|
|
23
|
+
# @see Git::Repository#stash_push
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
#
|
|
2
27
|
class Stash
|
|
3
|
-
|
|
4
|
-
|
|
28
|
+
# Initialize a Stash object
|
|
29
|
+
#
|
|
30
|
+
# When `existing` is `false` (the default), immediately calls {#save} to push
|
|
31
|
+
# the current working-directory state onto the stash stack.
|
|
32
|
+
#
|
|
33
|
+
# Emits one deprecation warning per object.
|
|
34
|
+
#
|
|
35
|
+
# @example Create a new stash entry
|
|
36
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
37
|
+
# stash.saved? #=> true
|
|
38
|
+
#
|
|
39
|
+
# @example Reference an existing stash without pushing
|
|
40
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
41
|
+
# stash.saved? #=> nil
|
|
42
|
+
#
|
|
43
|
+
# @param base [Git::Repository] the git repository
|
|
44
|
+
#
|
|
45
|
+
# @param message [String] the stash message
|
|
46
|
+
#
|
|
47
|
+
# @param existing [Boolean] (false) when `true`, wraps an existing stash entry
|
|
48
|
+
# without pushing any changes
|
|
49
|
+
#
|
|
50
|
+
# @return [void]
|
|
51
|
+
#
|
|
52
|
+
# @deprecated Use {Git::Repository#stash_push} and {Git::StashInfo} instead
|
|
53
|
+
#
|
|
54
|
+
def initialize(base, message, existing: false)
|
|
55
|
+
Git::Deprecation.warn(
|
|
56
|
+
'Git::Stash is deprecated and will be removed in v6.0.0. ' \
|
|
57
|
+
'Use the Git::Repository stash methods (stash_push, stash_infos, stash_apply) ' \
|
|
58
|
+
'and Git::StashInfo instead.'
|
|
59
|
+
)
|
|
5
60
|
@base = base
|
|
6
61
|
@message = message
|
|
7
62
|
save unless existing
|
|
8
63
|
end
|
|
9
|
-
|
|
64
|
+
|
|
65
|
+
# Saves the current working-directory state to the stash stack
|
|
66
|
+
#
|
|
67
|
+
# @example Save changes to the stash stack
|
|
68
|
+
# stash = Git::Stash.new(repo, 'WIP', existing: true)
|
|
69
|
+
# stash.save #=> true
|
|
70
|
+
#
|
|
71
|
+
# @return [Boolean] `true` if changes were stashed, `false` if there were no
|
|
72
|
+
# local changes to save
|
|
73
|
+
#
|
|
74
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
75
|
+
#
|
|
10
76
|
def save
|
|
11
|
-
|
|
77
|
+
# stash_save is deprecated too; silence it so one Git::Stash call emits one warning
|
|
78
|
+
@saved = Git::Deprecation.silence { stash_repository.stash_save(@message) }
|
|
12
79
|
end
|
|
13
|
-
|
|
80
|
+
|
|
81
|
+
# Returns whether the stash was saved successfully
|
|
82
|
+
#
|
|
83
|
+
# @example Check if changes were stashed
|
|
84
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
85
|
+
# stash.saved? #=> true
|
|
86
|
+
#
|
|
87
|
+
# @return [Boolean, nil] `true` if changes were stashed, `false` if there were no
|
|
88
|
+
# local changes, `nil` if {#save} has not been called (e.g. `existing: true`)
|
|
89
|
+
#
|
|
14
90
|
def saved?
|
|
15
91
|
@saved
|
|
16
92
|
end
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
93
|
+
|
|
94
|
+
# Returns the stash description
|
|
95
|
+
#
|
|
96
|
+
# @example Read the stash message
|
|
97
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
98
|
+
# stash.message #=> "WIP: feature work"
|
|
99
|
+
#
|
|
100
|
+
# @return [String] the stash message
|
|
101
|
+
#
|
|
102
|
+
attr_reader :message
|
|
103
|
+
|
|
104
|
+
# Returns the stash description as a string
|
|
105
|
+
#
|
|
106
|
+
# @example Convert stash to string
|
|
107
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
108
|
+
# stash.to_s #=> "WIP: feature work"
|
|
109
|
+
#
|
|
110
|
+
# @return [String] the stash message
|
|
111
|
+
#
|
|
22
112
|
def to_s
|
|
23
113
|
message
|
|
24
114
|
end
|
|
25
|
-
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
# @return [Git::Repository]
|
|
119
|
+
#
|
|
120
|
+
def stash_repository
|
|
121
|
+
@base
|
|
122
|
+
end
|
|
26
123
|
end
|
|
27
|
-
end
|
|
124
|
+
end
|