git 4.4.5 → 5.0.0.beta.1
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/.github/copilot-instructions.md +67 -2705
- data/.github/pull_request_template.md +3 -1
- data/.github/skills/breaking-change-analysis/SKILL.md +102 -0
- data/.github/skills/ci-cd-troubleshooting/SKILL.md +264 -0
- data/.github/skills/command-implementation/REFERENCE.md +993 -0
- data/.github/skills/command-implementation/SKILL.md +229 -0
- data/.github/skills/command-test-conventions/SKILL.md +660 -0
- data/.github/skills/command-yard-documentation/SKILL.md +426 -0
- data/.github/skills/dependency-management/SKILL.md +72 -0
- data/.github/skills/development-workflow/SKILL.md +506 -0
- data/.github/skills/extract-command-from-lib/SKILL.md +487 -0
- data/.github/skills/extract-facade-from-base-lib/SKILL.md +586 -0
- data/.github/skills/facade-implementation/REFERENCE.md +840 -0
- data/.github/skills/facade-implementation/SKILL.md +260 -0
- data/.github/skills/facade-test-conventions/SKILL.md +380 -0
- data/.github/skills/facade-yard-documentation/SKILL.md +429 -0
- data/.github/skills/make-skill-template/SKILL.md +176 -0
- data/.github/skills/pr-readiness-review/SKILL.md +185 -0
- data/.github/skills/project-context/SKILL.md +313 -0
- data/.github/skills/pull-request-review/SKILL.md +168 -0
- data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +131 -0
- data/.github/skills/release-management/SKILL.md +125 -0
- data/.github/skills/review-arguments-dsl/CHECKLIST.md +788 -0
- data/.github/skills/review-arguments-dsl/SKILL.md +214 -0
- data/.github/skills/review-backward-compatibility/SKILL.md +275 -0
- data/.github/skills/review-cross-command-consistency/SKILL.md +139 -0
- data/.github/skills/reviewing-skills/SKILL.md +189 -0
- data/.github/skills/rspec-unit-testing-standards/SKILL.md +639 -0
- data/.github/skills/tdd-refactor-step/SKILL.md +236 -0
- data/.github/skills/test-debugging/SKILL.md +160 -0
- data/.github/skills/yard-documentation/SKILL.md +793 -0
- data/.github/workflows/continuous_integration.yml +3 -67
- data/.github/workflows/enforce_conventional_commits.yml +1 -1
- data/.github/workflows/experimental_continuous_integration.yml +2 -2
- data/.github/workflows/release.yml +3 -4
- data/.gitignore +8 -1
- data/.husky/pre-commit +13 -0
- data/.release-please-manifest.json +1 -1
- data/.rspec +3 -0
- data/.rubocop.yml +7 -3
- data/.rubocop_todo.yml +23 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -98
- data/CONTRIBUTING.md +694 -53
- data/LICENSE +1 -1
- data/README.md +17 -17
- data/Rakefile +61 -9
- data/commitlint.test +4 -0
- data/git.gemspec +15 -9
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/base.rb +488 -424
- data/lib/git/branch.rb +117 -59
- data/lib/git/branch_delete_failure.rb +31 -0
- data/lib/git/branch_delete_result.rb +63 -0
- data/lib/git/branch_info.rb +178 -0
- data/lib/git/branches.rb +130 -24
- data/lib/git/command_line/base.rb +245 -0
- data/lib/git/command_line/capturing.rb +249 -0
- data/lib/git/command_line/result.rb +96 -0
- data/lib/git/command_line/streaming.rb +194 -0
- data/lib/git/command_line.rb +43 -322
- data/lib/git/command_line_result.rb +4 -88
- data/lib/git/commands/add.rb +131 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +252 -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 +47 -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 +237 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +140 -0
- data/lib/git/commands/arguments.rb +3510 -0
- data/lib/git/commands/base.rb +403 -0
- data/lib/git/commands/branch/copy.rb +94 -0
- data/lib/git/commands/branch/create.rb +173 -0
- data/lib/git/commands/branch/delete.rb +80 -0
- data/lib/git/commands/branch/list.rb +162 -0
- data/lib/git/commands/branch/move.rb +94 -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 +57 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +364 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +210 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +151 -0
- data/lib/git/commands/checkout/files.rb +115 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +105 -0
- data/lib/git/commands/clean.rb +100 -0
- data/lib/git/commands/clone.rb +240 -0
- data/lib/git/commands/commit.rb +272 -0
- data/lib/git/commands/commit_tree.rb +100 -0
- data/lib/git/commands/config_option_syntax/add.rb +83 -0
- data/lib/git/commands/config_option_syntax/get.rb +117 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +115 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +91 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +93 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +115 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +102 -0
- data/lib/git/commands/config_option_syntax/list.rb +107 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +74 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +78 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +104 -0
- data/lib/git/commands/config_option_syntax/set.rb +114 -0
- data/lib/git/commands/config_option_syntax/unset.rb +89 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +89 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +155 -0
- data/lib/git/commands/diff.rb +656 -0
- data/lib/git/commands/diff_files.rb +518 -0
- data/lib/git/commands/diff_index.rb +496 -0
- data/lib/git/commands/fetch.rb +352 -0
- data/lib/git/commands/fsck.rb +136 -0
- data/lib/git/commands/gc.rb +132 -0
- data/lib/git/commands/grep.rb +338 -0
- data/lib/git/commands/init.rb +99 -0
- data/lib/git/commands/log.rb +632 -0
- data/lib/git/commands/ls_files.rb +191 -0
- data/lib/git/commands/ls_remote.rb +155 -0
- data/lib/git/commands/ls_tree.rb +131 -0
- data/lib/git/commands/maintenance/register.rb +75 -0
- data/lib/git/commands/maintenance/run.rb +104 -0
- data/lib/git/commands/maintenance/start.rb +66 -0
- data/lib/git/commands/maintenance/stop.rb +55 -0
- data/lib/git/commands/maintenance/unregister.rb +79 -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 +245 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +86 -0
- data/lib/git/commands/mv.rb +77 -0
- data/lib/git/commands/name_rev.rb +114 -0
- data/lib/git/commands/pull.rb +377 -0
- data/lib/git/commands/push.rb +246 -0
- data/lib/git/commands/read_tree.rb +149 -0
- data/lib/git/commands/remote/add.rb +91 -0
- data/lib/git/commands/remote/get_url.rb +66 -0
- data/lib/git/commands/remote/list.rb +54 -0
- data/lib/git/commands/remote/prune.rb +61 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +69 -0
- data/lib/git/commands/remote/set_branches.rb +63 -0
- data/lib/git/commands/remote/set_head.rb +82 -0
- data/lib/git/commands/remote/set_url.rb +71 -0
- data/lib/git/commands/remote/set_url_add.rb +61 -0
- data/lib/git/commands/remote/set_url_delete.rb +64 -0
- data/lib/git/commands/remote/show.rb +71 -0
- data/lib/git/commands/remote/update.rb +72 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +277 -0
- data/lib/git/commands/reset.rb +147 -0
- data/lib/git/commands/rev_parse.rb +297 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +57 -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 +153 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +114 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +120 -0
- data/lib/git/commands/show_ref/exists.rb +78 -0
- data/lib/git/commands/show_ref/list.rb +145 -0
- data/lib/git/commands/show_ref/verify.rb +120 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +75 -0
- data/lib/git/commands/stash/branch.rb +65 -0
- data/lib/git/commands/stash/clear.rb +41 -0
- data/lib/git/commands/stash/create.rb +58 -0
- data/lib/git/commands/stash/drop.rb +67 -0
- data/lib/git/commands/stash/list.rb +39 -0
- data/lib/git/commands/stash/pop.rb +78 -0
- data/lib/git/commands/stash/push.rb +103 -0
- data/lib/git/commands/stash/show.rb +149 -0
- data/lib/git/commands/stash/store.rb +63 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +169 -0
- data/lib/git/commands/symbolic_ref/delete.rb +68 -0
- data/lib/git/commands/symbolic_ref/read.rb +95 -0
- data/lib/git/commands/symbolic_ref/update.rb +76 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +139 -0
- data/lib/git/commands/tag/delete.rb +55 -0
- data/lib/git/commands/tag/list.rb +143 -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 +140 -0
- data/lib/git/commands/update_ref/delete.rb +92 -0
- data/lib/git/commands/update_ref/update.rb +106 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +52 -0
- data/lib/git/commands/worktree/add.rb +140 -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 +89 -0
- data/lib/git/detached_head_info.rb +54 -0
- data/lib/git/diff.rb +297 -7
- data/lib/git/diff_file_numstat_info.rb +29 -0
- data/lib/git/diff_file_patch_info.rb +134 -0
- data/lib/git/diff_file_raw_info.rb +127 -0
- data/lib/git/diff_info.rb +169 -0
- data/lib/git/diff_path_status.rb +78 -19
- data/lib/git/diff_result.rb +32 -0
- data/lib/git/diff_stats.rb +59 -14
- data/lib/git/dirstat_info.rb +86 -0
- data/lib/git/errors.rb +65 -2
- data/lib/git/execution_context/global.rb +56 -0
- data/lib/git/execution_context/repository.rb +147 -0
- data/lib/git/execution_context.rb +482 -0
- data/lib/git/file_ref.rb +74 -0
- data/lib/git/fsck_object.rb +9 -9
- data/lib/git/fsck_result.rb +1 -1
- data/lib/git/lib.rb +1606 -1084
- data/lib/git/log.rb +15 -2
- data/lib/git/object.rb +92 -22
- data/lib/git/parsers/branch.rb +224 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/diff.rb +585 -0
- data/lib/git/parsers/fsck.rb +133 -0
- data/lib/git/parsers/grep.rb +42 -0
- data/lib/git/parsers/ls_tree.rb +58 -0
- data/lib/git/parsers/stash.rb +208 -0
- data/lib/git/parsers/tag.rb +257 -0
- data/lib/git/remote.rb +133 -9
- data/lib/git/repository/branching.rb +572 -0
- data/lib/git/repository/committing.rb +191 -0
- data/lib/git/repository/configuring.rb +156 -0
- data/lib/git/repository/diffing.rb +775 -0
- data/lib/git/repository/inspecting.rb +153 -0
- data/lib/git/repository/logging.rb +247 -0
- data/lib/git/repository/merging.rb +295 -0
- data/lib/git/repository/object_operations.rb +1101 -0
- data/lib/git/repository/path_resolver.rb +207 -0
- data/lib/git/repository/remote_operations.rb +753 -0
- data/lib/git/repository/shared_private.rb +51 -0
- data/lib/git/repository/staging.rb +390 -0
- data/lib/git/repository/stashing.rb +107 -0
- data/lib/git/repository/status_operations.rb +180 -0
- data/lib/git/repository/worktree_operations.rb +159 -0
- data/lib/git/repository.rb +264 -1
- data/lib/git/stash.rb +85 -4
- data/lib/git/stash_info.rb +104 -0
- data/lib/git/stashes.rb +130 -13
- data/lib/git/status.rb +226 -18
- data/lib/git/tag_delete_failure.rb +31 -0
- data/lib/git/tag_delete_result.rb +63 -0
- data/lib/git/tag_info.rb +105 -0
- data/lib/git/version.rb +109 -2
- data/lib/git/version_constraint.rb +81 -0
- data/lib/git/worktree.rb +120 -5
- data/lib/git/worktrees.rb +107 -7
- data/lib/git.rb +118 -69
- data/redesign/1_architecture_existing.md +54 -18
- data/redesign/2_architecture_redesign.md +365 -46
- data/redesign/3_architecture_implementation.md +1451 -54
- data/tasks/gem_tasks.rake +4 -0
- data/tasks/npm_tasks.rake +7 -0
- data/tasks/rspec.rake +48 -0
- data/tasks/rubocop.rake +2 -9
- data/tasks/test.rake +13 -1
- data/tasks/yard.rake +34 -7
- metadata +351 -22
- data/lib/git/index.rb +0 -6
- data/lib/git/path.rb +0 -38
- data/lib/git/working_directory.rb +0 -6
- /data/{release-please-config.json → .release-please-config.json} +0 -0
data/lib/git.rb
CHANGED
|
@@ -1,57 +1,63 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'active_support'
|
|
3
4
|
require 'active_support/deprecation'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# configured according to the GIT_DEPRECATION_BEHAVIOR environment variable.
|
|
8
|
-
#
|
|
6
|
+
require 'git/version'
|
|
7
|
+
|
|
9
8
|
module Git
|
|
10
|
-
# The deprecation instance used to emit deprecation warnings for the Git gem
|
|
11
|
-
#
|
|
12
|
-
# @api public
|
|
13
9
|
Deprecation = ActiveSupport::Deprecation.new('5.0.0', 'Git')
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Deprecation.behavior = behavior.to_sym
|
|
26
|
-
end
|
|
11
|
+
# Minimum git version required by this gem
|
|
12
|
+
#
|
|
13
|
+
# Commands and features may require newer versions, but this is the absolute
|
|
14
|
+
# minimum supported version for the gem as a whole.
|
|
15
|
+
#
|
|
16
|
+
# @return [Git::Version]
|
|
17
|
+
#
|
|
18
|
+
# @api public
|
|
19
|
+
#
|
|
20
|
+
MINIMUM_GIT_VERSION = Version.parse('2.28.0')
|
|
27
21
|
end
|
|
28
22
|
|
|
29
23
|
require 'git/author'
|
|
30
|
-
require 'git/base'
|
|
31
24
|
require 'git/branch'
|
|
25
|
+
require 'git/branch_info'
|
|
32
26
|
require 'git/branches'
|
|
33
27
|
require 'git/command_line_result'
|
|
34
28
|
require 'git/command_line'
|
|
29
|
+
require 'git/commands/init'
|
|
35
30
|
require 'git/config'
|
|
36
31
|
require 'git/diff'
|
|
32
|
+
require 'git/diff_file_numstat_info'
|
|
33
|
+
require 'git/diff_file_patch_info'
|
|
34
|
+
require 'git/diff_file_raw_info'
|
|
35
|
+
require 'git/diff_info'
|
|
36
|
+
require 'git/parsers/diff'
|
|
37
|
+
require 'git/diff_result'
|
|
38
|
+
require 'git/dirstat_info'
|
|
37
39
|
require 'git/encoding_utils'
|
|
38
40
|
require 'git/errors'
|
|
39
41
|
require 'git/escaped_path'
|
|
42
|
+
require 'git/execution_context'
|
|
43
|
+
require 'git/file_ref'
|
|
40
44
|
require 'git/fsck_object'
|
|
41
45
|
require 'git/fsck_result'
|
|
42
|
-
require 'git/
|
|
46
|
+
require 'git/version_constraint'
|
|
43
47
|
require 'git/lib'
|
|
44
48
|
require 'git/log'
|
|
45
49
|
require 'git/object'
|
|
46
|
-
require 'git/path'
|
|
47
50
|
require 'git/remote'
|
|
48
51
|
require 'git/repository'
|
|
52
|
+
require 'git/base'
|
|
49
53
|
require 'git/status'
|
|
50
54
|
require 'git/stash'
|
|
55
|
+
require 'git/stash_info'
|
|
51
56
|
require 'git/stashes'
|
|
57
|
+
require 'git/tag_delete_failure'
|
|
58
|
+
require 'git/tag_delete_result'
|
|
59
|
+
require 'git/tag_info'
|
|
52
60
|
require 'git/url'
|
|
53
|
-
require 'git/version'
|
|
54
|
-
require 'git/working_directory'
|
|
55
61
|
require 'git/worktree'
|
|
56
62
|
require 'git/worktrees'
|
|
57
63
|
|
|
@@ -62,29 +68,13 @@ require 'git/worktrees'
|
|
|
62
68
|
#
|
|
63
69
|
# @author Scott Chacon (mailto:schacon@gmail.com)
|
|
64
70
|
#
|
|
65
|
-
module Git
|
|
66
|
-
# Internal alias for Git::Lib, used by the gem itself after the public constant
|
|
67
|
-
# is deprecated. Code outside the gem should not reference this constant.
|
|
68
|
-
# @api private
|
|
69
|
-
LibImpl = remove_const(:Lib)
|
|
70
|
-
|
|
71
|
-
# @api private
|
|
72
|
-
def self.const_missing(name)
|
|
73
|
-
return super unless name == :Lib
|
|
74
|
-
|
|
75
|
-
Git::Deprecation.warn(
|
|
76
|
-
'Git::Lib is deprecated and will be removed in version 5.x. ' \
|
|
77
|
-
'Use the #lib accessor on the object returned by Git.init, Git.open, or Git.clone instead.'
|
|
78
|
-
)
|
|
79
|
-
const_set(:Lib, LibImpl)
|
|
80
|
-
end
|
|
81
|
-
|
|
71
|
+
module Git
|
|
82
72
|
# g.config('user.name', 'Scott Chacon') # sets value
|
|
83
73
|
# g.config('user.email', 'email@email.com') # sets value
|
|
84
74
|
# g.config('user.name') # returns 'Scott Chacon'
|
|
85
75
|
# g.config # returns whole config hash
|
|
86
76
|
def config(name = nil, value = nil)
|
|
87
|
-
lib =
|
|
77
|
+
lib = Git::Lib.new
|
|
88
78
|
if name && value
|
|
89
79
|
# set value
|
|
90
80
|
lib.config_set(name, value)
|
|
@@ -158,9 +148,9 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
158
148
|
#
|
|
159
149
|
# @param directory [Pathname, nil] The directory to clone into
|
|
160
150
|
#
|
|
161
|
-
# If `directory` is a relative
|
|
162
|
-
# given. If `
|
|
163
|
-
# directory.
|
|
151
|
+
# If `directory` is a relative path it is relative to the `:chdir` option if
|
|
152
|
+
# given. If `:chdir` is not given, `directory` is relative to the current
|
|
153
|
+
# working directory.
|
|
164
154
|
#
|
|
165
155
|
# If `nil`, `directory` will be set to the basename of the last component of
|
|
166
156
|
# the path from the `repository_url`. For example, for the URL:
|
|
@@ -211,9 +201,14 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
211
201
|
# @option options [String] :origin Use the value instead `origin` to track
|
|
212
202
|
# the upstream repository.
|
|
213
203
|
#
|
|
214
|
-
# @option options [Pathname] :
|
|
215
|
-
#
|
|
216
|
-
# `
|
|
204
|
+
# @option options [Pathname] :chdir Run `git clone` from within this directory.
|
|
205
|
+
#
|
|
206
|
+
# The `directory` parameter (or the repository basename when `directory` is nil)
|
|
207
|
+
# is resolved relative to `:chdir`, just as if you had `cd`'d into it before
|
|
208
|
+
# running `git clone`. The returned path is the join of `:chdir` and the
|
|
209
|
+
# cloned directory path.
|
|
210
|
+
#
|
|
211
|
+
# @option options [Pathname] :path Deprecated — use `:chdir` instead.
|
|
217
212
|
#
|
|
218
213
|
# @option options [Boolean] :recursive After the clone is created, initialize
|
|
219
214
|
# all submodules within, using their default settings.
|
|
@@ -226,8 +221,10 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
226
221
|
#
|
|
227
222
|
# @example Clone into a different directory `my-ruby-git`
|
|
228
223
|
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', 'my-ruby-git')
|
|
229
|
-
#
|
|
230
|
-
#
|
|
224
|
+
#
|
|
225
|
+
# @example Clone into a specific parent directory
|
|
226
|
+
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', chdir: '/path/to/projects')
|
|
227
|
+
# # clones into /path/to/projects/ruby-git
|
|
231
228
|
#
|
|
232
229
|
# @example Create a bare repository in the directory `ruby-git.git`
|
|
233
230
|
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', bare: true)
|
|
@@ -255,8 +252,6 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
255
252
|
# of the cloned local working copy or cloned repository.
|
|
256
253
|
#
|
|
257
254
|
def self.clone(repository_url, directory = nil, options = {})
|
|
258
|
-
clone_to_options = options.slice(:bare, :mirror)
|
|
259
|
-
directory ||= Git::URL.clone_to(repository_url, **clone_to_options)
|
|
260
255
|
Base.clone(repository_url, directory, options)
|
|
261
256
|
end
|
|
262
257
|
|
|
@@ -308,22 +303,10 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
308
303
|
# See +clone+ for options. Does not obey the <tt>:remote</tt> option,
|
|
309
304
|
# since the .git info will be deleted anyway; always uses the default
|
|
310
305
|
# remote, 'origin.'
|
|
311
|
-
#
|
|
312
|
-
# <tt>options[:branch]</tt> is the short name of the ref: a branch name such as
|
|
313
|
-
# 'main' or a tag name such as 'v1.0.0'. A full ref path such as
|
|
314
|
-
# 'refs/tags/v1.0.0' or a commit SHA is not accepted.
|
|
315
|
-
#
|
|
316
|
-
# Removing +.git+ is not atomic. If it fails, the exported files are complete and
|
|
317
|
-
# usable, but the directory keeps whatever part of +.git+ could not be deleted.
|
|
318
|
-
# Nothing is cleaned up, because the exported files are the deliverable and the
|
|
319
|
-
# leftover has to be removed by hand once the cause of the failure is fixed.
|
|
320
|
-
#
|
|
321
|
-
# @raise [SystemCallError] if the +.git+ directory cannot be removed. The exported
|
|
322
|
-
# files are left in place, and the directory keeps whatever part of +.git+ could
|
|
323
|
-
# not be deleted.
|
|
324
306
|
def self.export(repository, name, options = {})
|
|
325
307
|
options.delete(:remote)
|
|
326
308
|
repo = clone(repository, name, { depth: 1 }.merge(options))
|
|
309
|
+
repo.checkout("origin/#{options[:branch]}") if options[:branch]
|
|
327
310
|
FileUtils.rm_r File.join(repo.dir.to_s, '.git')
|
|
328
311
|
end
|
|
329
312
|
|
|
@@ -334,7 +317,7 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
334
317
|
# g.config('user.name') # returns 'Scott Chacon'
|
|
335
318
|
# g.config # returns whole config hash
|
|
336
319
|
def self.global_config(name = nil, value = nil)
|
|
337
|
-
lib =
|
|
320
|
+
lib = Git::Lib.new(nil, nil)
|
|
338
321
|
if name && value
|
|
339
322
|
# set value
|
|
340
323
|
lib.global_config_set(name, value)
|
|
@@ -376,6 +359,8 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
376
359
|
# and converted to an absolute path using
|
|
377
360
|
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
|
|
378
361
|
#
|
|
362
|
+
# @option options [Pathname] :separate_git_dir Alias for `:repository`.
|
|
363
|
+
#
|
|
379
364
|
# @option options [String, nil] :git_ssh An optional custom SSH command
|
|
380
365
|
#
|
|
381
366
|
# - If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
|
|
@@ -404,7 +389,30 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
404
389
|
# @see https://git-scm.com/docs/git-init git init
|
|
405
390
|
#
|
|
406
391
|
def self.init(directory = '.', options = {})
|
|
407
|
-
|
|
392
|
+
require_relative 'git/commands/init'
|
|
393
|
+
|
|
394
|
+
options = options.dup
|
|
395
|
+
options[:repository] ||= options.delete(:separate_git_dir)
|
|
396
|
+
init_opts = options.slice(:bare, :initial_branch)
|
|
397
|
+
init_opts[:separate_git_dir] = options[:repository] if options.key?(:repository)
|
|
398
|
+
Git::Commands::Init.new(Git::Lib.new(nil, options[:log])).call(directory, **init_opts)
|
|
399
|
+
|
|
400
|
+
open_initialized_repository(directory, options)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Open the repository after initialization
|
|
404
|
+
#
|
|
405
|
+
# @param directory [String] the directory containing the repository
|
|
406
|
+
# @param options [Hash] the options hash
|
|
407
|
+
# @return [Git::Base] the opened repository
|
|
408
|
+
# @api private
|
|
409
|
+
#
|
|
410
|
+
private_class_method def self.open_initialized_repository(directory, options)
|
|
411
|
+
if options[:bare]
|
|
412
|
+
Git.bare(options[:repository] || directory, options.slice(:log, :git_ssh).compact)
|
|
413
|
+
else
|
|
414
|
+
Git.open(directory, options.slice(:log, :git_ssh, :index, :repository).compact)
|
|
415
|
+
end
|
|
408
416
|
end
|
|
409
417
|
|
|
410
418
|
# returns a Hash containing information about the references
|
|
@@ -416,7 +424,7 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
416
424
|
# @param [String|NilClass] location the target repository location or nil for '.'
|
|
417
425
|
# @return [{String=>Hash}] the available references of the target repo.
|
|
418
426
|
def self.ls_remote(location = nil, options = {})
|
|
419
|
-
|
|
427
|
+
Git::Lib.new.ls_remote(location, options)
|
|
420
428
|
end
|
|
421
429
|
|
|
422
430
|
# Open a an existing Git working directory
|
|
@@ -473,6 +481,37 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
473
481
|
Base.open(working_dir, options)
|
|
474
482
|
end
|
|
475
483
|
|
|
484
|
+
# Return the version of a git binary as a {Git::Version}
|
|
485
|
+
#
|
|
486
|
+
# @param binary_path [String, nil] path to the git binary; defaults to
|
|
487
|
+
# `Git::Base.config.binary_path`
|
|
488
|
+
#
|
|
489
|
+
# @return [Git::Version] the parsed git version
|
|
490
|
+
#
|
|
491
|
+
# @raise [Git::UnexpectedResultError] if the version output cannot be parsed
|
|
492
|
+
#
|
|
493
|
+
# @raise [Git::FailedError] if the git binary exits with a non-zero status
|
|
494
|
+
#
|
|
495
|
+
# @raise [Git::Error] if the binary is not found or fails to launch
|
|
496
|
+
#
|
|
497
|
+
# @example Default binary
|
|
498
|
+
# Git.git_version #=> #<Git::Version 2.42.0>
|
|
499
|
+
#
|
|
500
|
+
# @example Explicit binary path
|
|
501
|
+
# Git.git_version('/opt/homebrew/bin/git') #=> #<Git::Version 2.42.0>
|
|
502
|
+
#
|
|
503
|
+
def self.git_version(binary_path = nil)
|
|
504
|
+
path = binary_path || Git::Base.config.binary_path
|
|
505
|
+
Git::Lib.cached_git_version(path) { run_git_version(path) }
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
# @api private
|
|
509
|
+
def self.run_git_version(path)
|
|
510
|
+
output = Git::Commands::Version.new(Git::ExecutionContext::Global.new(binary_path: path)).call.stdout
|
|
511
|
+
Git::Version.parse(output)
|
|
512
|
+
end
|
|
513
|
+
private_class_method :run_git_version
|
|
514
|
+
|
|
476
515
|
# Return the version of the git binary
|
|
477
516
|
#
|
|
478
517
|
# @example
|
|
@@ -480,7 +519,17 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
480
519
|
#
|
|
481
520
|
# @return [Array<Integer>] the version of the git binary
|
|
482
521
|
#
|
|
522
|
+
# @deprecated Use {Git.git_version} instead, which returns a {Git::Version} (not an Array).
|
|
523
|
+
# For the legacy array shape, call: `Git.git_version.to_a`.
|
|
524
|
+
# The optional binary_path argument is preserved: `Git.git_version(binary_path)`.
|
|
525
|
+
#
|
|
483
526
|
def self.binary_version(binary_path = Git::Base.config.binary_path)
|
|
484
|
-
|
|
527
|
+
Git::Deprecation.warn(
|
|
528
|
+
'Git.binary_version is deprecated and will be removed in 6.0. ' \
|
|
529
|
+
'Use Git.git_version instead, which returns a Git::Version ' \
|
|
530
|
+
'(not an Array). For the legacy array shape, call: Git.git_version.to_a. ' \
|
|
531
|
+
'The optional binary_path argument is preserved: Git.git_version(binary_path).'
|
|
532
|
+
)
|
|
533
|
+
git_version(binary_path).to_a
|
|
485
534
|
end
|
|
486
535
|
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Analysis of the Current Git Gem Architecture and Its Challenges
|
|
2
2
|
|
|
3
|
-
This document provides an in-depth look at the current architecture of the `git` gem,
|
|
3
|
+
This document provides an in-depth look at the current architecture of the `git` gem,
|
|
4
|
+
outlining its primary components and the design challenges that have emerged over
|
|
5
|
+
time. Understanding these challenges is the key motivation for the proposed
|
|
6
|
+
architectural redesign.
|
|
4
7
|
|
|
5
8
|
- [1. Overview of the Current Architecture](#1-overview-of-the-current-architecture)
|
|
6
9
|
- [2. Key Architectural Challenges](#2-key-architectural-challenges)
|
|
@@ -11,27 +14,43 @@ This document provides an in-depth look at the current architecture of the `git`
|
|
|
11
14
|
|
|
12
15
|
## 1. Overview of the Current Architecture
|
|
13
16
|
|
|
14
|
-
The gem's current design is centered around three main classes: `Git`, `Git::Base`,
|
|
17
|
+
The gem's current design is centered around three main classes: `Git`, `Git::Base`,
|
|
18
|
+
and `Git::Lib`.
|
|
15
19
|
|
|
16
|
-
- **`Git` (Top-Level Module)**: This module serves as the primary public entry point
|
|
20
|
+
- **`Git` (Top-Level Module)**: This module serves as the primary public entry point
|
|
21
|
+
for creating repository objects. It contains class-level factory methods like
|
|
22
|
+
`Git.open`, `Git.clone`, and `Git.init`. It also provides an interface for
|
|
23
|
+
accessing global git configuration settings.
|
|
17
24
|
|
|
18
|
-
**`Git::Base`**: This is the main object that users interact with after creating or
|
|
25
|
+
- **`Git::Base`**: This is the main object that users interact with after creating or
|
|
26
|
+
opening a repository. It holds the high-level public API for most git operations
|
|
27
|
+
(e.g., `g.commit`, `g.add`, `g.status`). It is responsible for managing the
|
|
28
|
+
repository's state, such as the paths to the working directory and the `.git`
|
|
29
|
+
directory.
|
|
19
30
|
|
|
20
|
-
**`Git::Lib`**: This class is intended to be the low-level wrapper around the `git`
|
|
31
|
+
- **`Git::Lib`**: This class is intended to be the low-level wrapper around the `git`
|
|
32
|
+
command-line tool. It contains the methods that build the specific command-line
|
|
33
|
+
arguments and execute the `git` binary. In practice, it also contains a significant
|
|
34
|
+
amount of logic for parsing the output of these commands.
|
|
21
35
|
|
|
22
36
|
## 2. Key Architectural Challenges
|
|
23
37
|
|
|
24
|
-
While this structure has been functional, several significant design challenges make
|
|
38
|
+
While this structure has been functional, several significant design challenges make
|
|
39
|
+
the codebase difficult to maintain, test, and evolve.
|
|
25
40
|
|
|
26
41
|
### A. Unclear Separation of Concerns
|
|
27
42
|
|
|
28
|
-
The responsibilities between Git::Base and Git::Lib are "muddy" and overlap
|
|
43
|
+
The responsibilities between Git::Base and Git::Lib are "muddy" and overlap
|
|
44
|
+
significantly.
|
|
29
45
|
|
|
30
46
|
- `Git::Base` sometimes contains logic that feels like it should be lower-level.
|
|
31
47
|
|
|
32
|
-
- `Git::Lib`, which should ideally only be concerned with command execution, is
|
|
48
|
+
- `Git::Lib`, which should ideally only be concerned with command execution, is
|
|
49
|
+
filled with high-level logic for parsing command output into specific Ruby objects
|
|
50
|
+
(e.g., parsing log output, diff stats, and branch lists).
|
|
33
51
|
|
|
34
|
-
This blending of responsibilities makes it hard to determine where a specific piece
|
|
52
|
+
This blending of responsibilities makes it hard to determine where a specific piece
|
|
53
|
+
of logic should reside, leading to an inconsistent and confusing internal structure.
|
|
35
54
|
|
|
36
55
|
### B. Circular Dependency
|
|
37
56
|
|
|
@@ -39,28 +58,45 @@ This is the most critical architectural flaw in the current design.
|
|
|
39
58
|
|
|
40
59
|
- A `Git::Base` instance is created.
|
|
41
60
|
|
|
42
|
-
- The first time a command is run, `Git::Base` lazily initializes a `Git::Lib`
|
|
61
|
+
- The first time a command is run, `Git::Base` lazily initializes a `Git::Lib`
|
|
62
|
+
instance via its `.lib` accessor method.
|
|
43
63
|
|
|
44
|
-
- The `Git::Lib` constructor is passed the `Git::Base` instance (`self`) so that it
|
|
64
|
+
- The `Git::Lib` constructor is passed the `Git::Base` instance (`self`) so that it
|
|
65
|
+
can read the repository's path configuration back from the object that is creating
|
|
66
|
+
it.
|
|
45
67
|
|
|
46
|
-
This creates a tight, circular coupling: `Git::Base` depends on `Git::Lib` to execute
|
|
68
|
+
This creates a tight, circular coupling: `Git::Base` depends on `Git::Lib` to execute
|
|
69
|
+
commands, but `Git::Lib` depends on `Git::Base` for its own configuration. This
|
|
70
|
+
pattern makes the classes difficult to instantiate or test in isolation and creates a
|
|
71
|
+
fragile system where changes in one class can have unexpected side effects in the
|
|
72
|
+
other.
|
|
47
73
|
|
|
48
74
|
### C. Undefined Public API Boundary
|
|
49
75
|
|
|
50
|
-
The gem lacks a formally defined public interface. Because `Git::Base` exposes its
|
|
76
|
+
The gem lacks a formally defined public interface. Because `Git::Base` exposes its
|
|
77
|
+
internal `Git::Lib` instance via the public `g.lib` accessor, many users have come to
|
|
78
|
+
rely on `Git::Lib` and its methods as if they were part of the public API.
|
|
51
79
|
|
|
52
80
|
This has two negative consequences:
|
|
53
81
|
|
|
54
|
-
1. It prevents the gem's maintainers from refactoring or changing the internal
|
|
82
|
+
1. It prevents the gem's maintainers from refactoring or changing the internal
|
|
83
|
+
implementation of `Git::Lib` without causing breaking changes for users.
|
|
55
84
|
|
|
56
|
-
2. It exposes complex, internal methods to users, creating a confusing and
|
|
85
|
+
2. It exposes complex, internal methods to users, creating a confusing and
|
|
86
|
+
inconsistent user experience.
|
|
57
87
|
|
|
58
88
|
### D. Slow and Brittle Test Suite
|
|
59
89
|
|
|
60
90
|
The current testing strategy, built on `TestUnit`, suffers from two major issues:
|
|
61
91
|
|
|
62
|
-
- **Over-reliance on Fixtures**: Most tests depend on having a complete, physical git
|
|
92
|
+
- **Over-reliance on Fixtures**: Most tests depend on having a complete, physical git
|
|
93
|
+
repository on the filesystem to run against. Managing these fixtures is cumbersome.
|
|
63
94
|
|
|
64
|
-
- **Excessive Shelling Out**: Because the logic for command execution and output
|
|
95
|
+
- **Excessive Shelling Out**: Because the logic for command execution and output
|
|
96
|
+
parsing are tightly coupled, nearly every test must shell out to the actual `git`
|
|
97
|
+
command-line tool.
|
|
65
98
|
|
|
66
|
-
This makes the test suite extremely slow, especially on non-UNIX platforms like
|
|
99
|
+
This makes the test suite extremely slow, especially on non-UNIX platforms like
|
|
100
|
+
Windows where process creation is more expensive. The slow feedback loop discourages
|
|
101
|
+
frequent testing and makes development more difficult. The brittleness of
|
|
102
|
+
filesystem-dependent tests also leads to flickering or unreliable test runs.
|