git 4.3.2 → 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 -2
- 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 -0
- 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 -40
- data/CONTRIBUTING.md +694 -53
- data/README.md +17 -5
- data/Rakefile +61 -9
- data/commitlint.test +4 -0
- data/git.gemspec +14 -8
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/base.rb +486 -410
- data/lib/git/branch.rb +380 -43
- 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 -1028
- 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 +224 -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 +114 -18
- 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/test.rake +13 -1
- data/tasks/yard.rake +34 -7
- metadata +349 -20
- 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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Represents a git version constraint with minimum and upper bound versions
|
|
5
|
+
#
|
|
6
|
+
# Used by {Git::Commands::Base.requires_git_version} to declare version requirements
|
|
7
|
+
# and by {Git::VersionError} to report constraint violations.
|
|
8
|
+
#
|
|
9
|
+
# @example Minimum version only
|
|
10
|
+
# constraint = Git::VersionConstraint.new(min: Git::Version.parse('2.30.0'))
|
|
11
|
+
# constraint.too_old?(Git::Version.parse('2.28.0')) #=> true
|
|
12
|
+
# constraint.too_new?(Git::Version.parse('2.28.0')) #=> false
|
|
13
|
+
#
|
|
14
|
+
# @example Upper bound only
|
|
15
|
+
# constraint = Git::VersionConstraint.new(before: Git::Version.parse('2.50.0'))
|
|
16
|
+
# constraint.too_old?(Git::Version.parse('2.51.0')) #=> false
|
|
17
|
+
# constraint.too_new?(Git::Version.parse('2.51.0')) #=> true
|
|
18
|
+
#
|
|
19
|
+
# @example Both bounds
|
|
20
|
+
# constraint = Git::VersionConstraint.new(
|
|
21
|
+
# min: Git::Version.parse('2.30.0'),
|
|
22
|
+
# before: Git::Version.parse('2.50.0')
|
|
23
|
+
# )
|
|
24
|
+
# constraint.satisfied_by?(Git::Version.parse('2.40.0')) #=> true
|
|
25
|
+
#
|
|
26
|
+
# @api public
|
|
27
|
+
#
|
|
28
|
+
VersionConstraint = Data.define(:min, :before) do
|
|
29
|
+
# @param min [Git::Version, nil] minimum version (inclusive)
|
|
30
|
+
# @param before [Git::Version, nil] upper bound version (exclusive)
|
|
31
|
+
def initialize(min: nil, before: nil)
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Check if the given version is too old (below the minimum)
|
|
36
|
+
#
|
|
37
|
+
# @param version [Git::Version] the version to check
|
|
38
|
+
#
|
|
39
|
+
# @return [Boolean] true if version is below the minimum, false otherwise
|
|
40
|
+
#
|
|
41
|
+
def too_old?(version)
|
|
42
|
+
return false unless min
|
|
43
|
+
|
|
44
|
+
version < min
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Check if the given version is too new (at or past the upper bound)
|
|
48
|
+
#
|
|
49
|
+
# @param version [Git::Version] the version to check
|
|
50
|
+
#
|
|
51
|
+
# @return [Boolean] true if version is at or past the upper bound, false otherwise
|
|
52
|
+
#
|
|
53
|
+
def too_new?(version)
|
|
54
|
+
return false unless before
|
|
55
|
+
|
|
56
|
+
version >= before
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Check if the given version satisfies this constraint
|
|
60
|
+
#
|
|
61
|
+
# @param version [Git::Version] the version to check
|
|
62
|
+
#
|
|
63
|
+
# @return [Boolean] true if the version satisfies the constraint
|
|
64
|
+
#
|
|
65
|
+
def satisfied_by?(version)
|
|
66
|
+
!too_old?(version) && !too_new?(version)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Return a human-readable representation of this constraint
|
|
70
|
+
#
|
|
71
|
+
# @return [String] the constraint in git version range form
|
|
72
|
+
#
|
|
73
|
+
def to_s
|
|
74
|
+
return ">= #{min}, < #{before}" if min && before
|
|
75
|
+
return ">= #{min}" if min
|
|
76
|
+
return "< #{before}" if before
|
|
77
|
+
|
|
78
|
+
'any version'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/lib/git/worktree.rb
CHANGED
|
@@ -1,12 +1,52 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'git/
|
|
3
|
+
require 'git/base'
|
|
4
4
|
|
|
5
5
|
module Git
|
|
6
6
|
# A worktree in a Git repository
|
|
7
|
+
#
|
|
8
|
+
# Represents a single linked or main worktree. Constructed by
|
|
9
|
+
# {Git::Repository::WorktreeOperations#worktree} or populated by
|
|
10
|
+
# {Git::Worktrees}.
|
|
11
|
+
#
|
|
12
|
+
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy form)
|
|
13
|
+
# as the `base` argument. The `is_a?(Git::Base)` guard routes git operations
|
|
14
|
+
# through the facade repository and will be removed when {Git::Base} is
|
|
15
|
+
# deleted in Phase 4.
|
|
16
|
+
#
|
|
17
|
+
# @example Add and remove a linked worktree
|
|
18
|
+
# worktree = repo.worktree('/path/to/new-worktree')
|
|
19
|
+
# worktree.add
|
|
20
|
+
# worktree.remove
|
|
21
|
+
#
|
|
22
|
+
# @api public
|
|
23
|
+
#
|
|
7
24
|
class Worktree
|
|
8
|
-
|
|
25
|
+
# Full worktree descriptor including the optional commitish
|
|
26
|
+
#
|
|
27
|
+
# @return [String] the filesystem path, space-separated with the commitish
|
|
28
|
+
# when one was given at construction time
|
|
29
|
+
#
|
|
30
|
+
attr_accessor :full
|
|
9
31
|
|
|
32
|
+
# Filesystem path of this worktree
|
|
33
|
+
#
|
|
34
|
+
# @return [String] the filesystem path of the worktree directory
|
|
35
|
+
#
|
|
36
|
+
attr_accessor :dir
|
|
37
|
+
|
|
38
|
+
# Creates a new Worktree object
|
|
39
|
+
#
|
|
40
|
+
# @param base [Git::Base, Git::Repository] the repository that owns this
|
|
41
|
+
# worktree
|
|
42
|
+
#
|
|
43
|
+
# @param dir [String] filesystem path of the worktree
|
|
44
|
+
#
|
|
45
|
+
# @param gcommit [String, nil] commitish associated with the worktree;
|
|
46
|
+
# when non-nil it is appended to {#full}
|
|
47
|
+
#
|
|
48
|
+
# @return [void]
|
|
49
|
+
#
|
|
10
50
|
def initialize(base, dir, gcommit = nil)
|
|
11
51
|
@full = dir
|
|
12
52
|
@full += " #{gcommit}" unless gcommit.nil?
|
|
@@ -15,25 +55,100 @@ module Git
|
|
|
15
55
|
@gcommit = gcommit
|
|
16
56
|
end
|
|
17
57
|
|
|
58
|
+
# Returns the commit (or commitish string) associated with this worktree
|
|
59
|
+
#
|
|
60
|
+
# When a commitish string was supplied at construction time (e.g. by
|
|
61
|
+
# {Git::Worktrees} which passes the raw SHA from `git worktree list`), that
|
|
62
|
+
# string is returned as-is. Otherwise the value is lazily resolved on first
|
|
63
|
+
# call via `worktree_repository.gcommit(@full)` and the result is memoized.
|
|
64
|
+
#
|
|
65
|
+
# @example When resolved lazily (no commitish at construction)
|
|
66
|
+
# worktree = repo.worktree('/path/to/wt')
|
|
67
|
+
# worktree.gcommit # => #<Git::Object::Commit ...>
|
|
68
|
+
#
|
|
69
|
+
# @example When the commitish was given at construction
|
|
70
|
+
# worktree = repo.worktrees['/path/to/wt']
|
|
71
|
+
# worktree.gcommit # => "4bef5ab8c9..." (raw SHA string)
|
|
72
|
+
#
|
|
73
|
+
# @return [Git::Object::Commit, String] a commit object when lazily
|
|
74
|
+
# resolved, or the raw commitish string when pre-set at construction
|
|
75
|
+
#
|
|
76
|
+
# @raise [Git::FailedError] if git must resolve the commit and exits with a
|
|
77
|
+
# non-zero exit status
|
|
78
|
+
#
|
|
18
79
|
def gcommit
|
|
19
|
-
@gcommit ||=
|
|
80
|
+
@gcommit ||= worktree_repository.gcommit(@full)
|
|
20
81
|
@gcommit
|
|
21
82
|
end
|
|
22
83
|
|
|
84
|
+
# Creates this worktree on disk
|
|
85
|
+
#
|
|
86
|
+
# Runs `git worktree add` for {#dir}, optionally at the commitish passed
|
|
87
|
+
# at construction time.
|
|
88
|
+
#
|
|
89
|
+
# @example Add a worktree
|
|
90
|
+
# worktree = repo.worktree('/path/to/new-worktree')
|
|
91
|
+
# worktree.add
|
|
92
|
+
#
|
|
93
|
+
# @return [String] stdout from the git command
|
|
94
|
+
#
|
|
95
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
96
|
+
#
|
|
23
97
|
def add
|
|
24
|
-
|
|
98
|
+
worktree_repository.worktree_add(@dir, @gcommit)
|
|
25
99
|
end
|
|
26
100
|
|
|
101
|
+
# Removes this worktree from disk
|
|
102
|
+
#
|
|
103
|
+
# Runs `git worktree remove` for {#dir}.
|
|
104
|
+
#
|
|
105
|
+
# @example Remove a worktree
|
|
106
|
+
# worktree.remove
|
|
107
|
+
#
|
|
108
|
+
# @return [String] stdout from the git command (typically empty)
|
|
109
|
+
#
|
|
110
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
111
|
+
#
|
|
27
112
|
def remove
|
|
28
|
-
|
|
113
|
+
worktree_repository.worktree_remove(@dir)
|
|
29
114
|
end
|
|
30
115
|
|
|
116
|
+
# Returns an array containing the full worktree descriptor
|
|
117
|
+
#
|
|
118
|
+
# @example Get the descriptor array
|
|
119
|
+
# worktree.to_a # => ["/path/to/worktree"]
|
|
120
|
+
#
|
|
121
|
+
# @return [Array<String>] array containing the full worktree descriptor
|
|
122
|
+
#
|
|
31
123
|
def to_a
|
|
32
124
|
[@full]
|
|
33
125
|
end
|
|
34
126
|
|
|
127
|
+
# Returns the full worktree descriptor as a string
|
|
128
|
+
#
|
|
129
|
+
# @example Get the descriptor string
|
|
130
|
+
# worktree.to_s # => "/path/to/worktree"
|
|
131
|
+
#
|
|
132
|
+
# @return [String] the full worktree descriptor (path and optional commitish)
|
|
133
|
+
#
|
|
35
134
|
def to_s
|
|
36
135
|
@full
|
|
37
136
|
end
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
# Resolves the {Git::Repository} for worktree operations
|
|
141
|
+
#
|
|
142
|
+
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
143
|
+
# The `is_a?(Git::Base)` guard will be removed when {Git::Base} is deleted
|
|
144
|
+
# in Phase 4.
|
|
145
|
+
#
|
|
146
|
+
# @return [Git::Repository] the repository used for worktree operations
|
|
147
|
+
#
|
|
148
|
+
# @api private
|
|
149
|
+
#
|
|
150
|
+
def worktree_repository
|
|
151
|
+
@base.is_a?(Git::Base) ? @base.facade_repository : @base
|
|
152
|
+
end
|
|
38
153
|
end
|
|
39
154
|
end
|
data/lib/git/worktrees.rb
CHANGED
|
@@ -1,47 +1,147 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'git/base'
|
|
4
|
+
|
|
3
5
|
module Git
|
|
4
|
-
#
|
|
6
|
+
# Collection of all Git worktrees in a repository
|
|
7
|
+
#
|
|
8
|
+
# Wraps every linked and main worktree and provides enumeration and
|
|
9
|
+
# path-based lookup.
|
|
10
|
+
#
|
|
11
|
+
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy
|
|
12
|
+
# form) as the `base` argument. The `is_a?(Git::Base)` guard routes git
|
|
13
|
+
# operations through the facade repository and will be removed when
|
|
14
|
+
# {Git::Base} is deleted in Phase 4.
|
|
15
|
+
#
|
|
16
|
+
# @example Enumerate all worktrees
|
|
17
|
+
# worktrees = repo.worktrees
|
|
18
|
+
# worktrees.each { |wt| puts wt.dir }
|
|
19
|
+
#
|
|
20
|
+
# @api public
|
|
21
|
+
#
|
|
5
22
|
class Worktrees
|
|
6
23
|
include Enumerable
|
|
7
24
|
|
|
25
|
+
# Creates a new Worktrees collection populated from the given repository
|
|
26
|
+
#
|
|
27
|
+
# @param base [Git::Base, Git::Repository] the repository to enumerate
|
|
28
|
+
# worktrees from
|
|
29
|
+
#
|
|
30
|
+
# @return [void]
|
|
31
|
+
#
|
|
32
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
33
|
+
#
|
|
8
34
|
def initialize(base)
|
|
9
35
|
@worktrees = {}
|
|
10
36
|
|
|
11
37
|
@base = base
|
|
12
38
|
|
|
13
|
-
|
|
14
|
-
@base.lib.worktrees_all.each do |w|
|
|
39
|
+
worktree_repository.worktrees_all.each do |w|
|
|
15
40
|
@worktrees[w[0]] = Git::Worktree.new(@base, w[0], w[1])
|
|
16
41
|
end
|
|
17
42
|
end
|
|
18
43
|
|
|
19
|
-
#
|
|
20
|
-
|
|
44
|
+
# Returns the number of worktrees in the collection
|
|
45
|
+
#
|
|
46
|
+
# @example Count all worktrees
|
|
47
|
+
# repo.worktrees.size # => 2
|
|
48
|
+
#
|
|
49
|
+
# @return [Integer] the total number of worktrees
|
|
50
|
+
#
|
|
21
51
|
def size
|
|
22
52
|
@worktrees.size
|
|
23
53
|
end
|
|
24
54
|
|
|
55
|
+
# Iterates over every worktree in the collection
|
|
56
|
+
#
|
|
57
|
+
# @overload each
|
|
58
|
+
#
|
|
59
|
+
# @example Get an enumerator over all worktrees
|
|
60
|
+
# enum = repo.worktrees.each
|
|
61
|
+
#
|
|
62
|
+
# @return [Enumerator<Git::Worktree>] an enumerator over all worktrees
|
|
63
|
+
#
|
|
64
|
+
# @overload each(&block)
|
|
65
|
+
#
|
|
66
|
+
# @example Print every worktree path
|
|
67
|
+
# repo.worktrees.each { |wt| puts wt.dir }
|
|
68
|
+
#
|
|
69
|
+
# @return [Array<Git::Worktree>] the full list of worktrees
|
|
70
|
+
#
|
|
71
|
+
# @yield [worktree] passes each worktree to the block
|
|
72
|
+
#
|
|
73
|
+
# @yieldparam worktree [Git::Worktree] a worktree in the repository
|
|
74
|
+
#
|
|
75
|
+
# @yieldreturn [void]
|
|
76
|
+
#
|
|
25
77
|
def each(&)
|
|
26
78
|
@worktrees.values.each(&)
|
|
27
79
|
end
|
|
28
80
|
|
|
81
|
+
# Returns the worktree with the given path
|
|
82
|
+
#
|
|
83
|
+
# Supports lookup by the filesystem path of the worktree directory or by
|
|
84
|
+
# the full worktree descriptor (path and optional commitish).
|
|
85
|
+
#
|
|
86
|
+
# @example Look up a worktree by path
|
|
87
|
+
# repo.worktrees['/path/to/linked-worktree']
|
|
88
|
+
#
|
|
89
|
+
# @param worktree_name [#to_s] the path (or full descriptor) of the
|
|
90
|
+
# worktree to retrieve
|
|
91
|
+
#
|
|
92
|
+
# @return [Git::Worktree, nil] the matching worktree, or `nil` if not found
|
|
93
|
+
#
|
|
29
94
|
def [](worktree_name)
|
|
30
95
|
@worktrees.values.each_with_object(@worktrees) do |worktree, worktrees|
|
|
31
96
|
worktrees[worktree.full] ||= worktree
|
|
32
97
|
end[worktree_name.to_s]
|
|
33
98
|
end
|
|
34
99
|
|
|
100
|
+
# Returns a string listing all worktrees, one per line
|
|
101
|
+
#
|
|
102
|
+
# @example Display all worktrees
|
|
103
|
+
# puts repo.worktrees.to_s
|
|
104
|
+
#
|
|
105
|
+
# @return [String] a newline-separated listing of worktree descriptors
|
|
106
|
+
#
|
|
35
107
|
def to_s
|
|
36
|
-
out = ''
|
|
108
|
+
out = +''
|
|
37
109
|
@worktrees.each_value do |b|
|
|
38
110
|
out << b.to_s << "\n"
|
|
39
111
|
end
|
|
40
112
|
out
|
|
41
113
|
end
|
|
42
114
|
|
|
115
|
+
# Removes stale administrative files for worktrees that no longer exist
|
|
116
|
+
#
|
|
117
|
+
# Runs `git worktree prune` to clean up any lingering worktree metadata
|
|
118
|
+
# for linked worktrees whose directories have been deleted.
|
|
119
|
+
#
|
|
120
|
+
# @example Prune stale worktree metadata
|
|
121
|
+
# repo.worktrees.prune
|
|
122
|
+
#
|
|
123
|
+
# @return [String] stdout from the git command (typically empty)
|
|
124
|
+
#
|
|
125
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
126
|
+
#
|
|
43
127
|
def prune
|
|
44
|
-
|
|
128
|
+
worktree_repository.worktree_prune
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
# Resolves the {Git::Repository} for this collection of worktrees
|
|
134
|
+
#
|
|
135
|
+
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
136
|
+
# The `is_a?(Git::Base)` guard will be removed when {Git::Base} is deleted
|
|
137
|
+
# in Phase 4.
|
|
138
|
+
#
|
|
139
|
+
# @return [Git::Repository] the repository used to enumerate worktrees
|
|
140
|
+
#
|
|
141
|
+
# @api private
|
|
142
|
+
#
|
|
143
|
+
def worktree_repository
|
|
144
|
+
@base.is_a?(Git::Base) ? @base.facade_repository : @base
|
|
45
145
|
end
|
|
46
146
|
end
|
|
47
147
|
end
|
data/lib/git.rb
CHANGED
|
@@ -3,36 +3,61 @@
|
|
|
3
3
|
require 'active_support'
|
|
4
4
|
require 'active_support/deprecation'
|
|
5
5
|
|
|
6
|
+
require 'git/version'
|
|
7
|
+
|
|
6
8
|
module Git
|
|
7
9
|
Deprecation = ActiveSupport::Deprecation.new('5.0.0', 'Git')
|
|
10
|
+
|
|
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')
|
|
8
21
|
end
|
|
9
22
|
|
|
10
23
|
require 'git/author'
|
|
11
|
-
require 'git/base'
|
|
12
24
|
require 'git/branch'
|
|
25
|
+
require 'git/branch_info'
|
|
13
26
|
require 'git/branches'
|
|
14
27
|
require 'git/command_line_result'
|
|
15
28
|
require 'git/command_line'
|
|
29
|
+
require 'git/commands/init'
|
|
16
30
|
require 'git/config'
|
|
17
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'
|
|
18
39
|
require 'git/encoding_utils'
|
|
19
40
|
require 'git/errors'
|
|
20
41
|
require 'git/escaped_path'
|
|
42
|
+
require 'git/execution_context'
|
|
43
|
+
require 'git/file_ref'
|
|
21
44
|
require 'git/fsck_object'
|
|
22
45
|
require 'git/fsck_result'
|
|
23
|
-
require 'git/
|
|
46
|
+
require 'git/version_constraint'
|
|
24
47
|
require 'git/lib'
|
|
25
48
|
require 'git/log'
|
|
26
49
|
require 'git/object'
|
|
27
|
-
require 'git/path'
|
|
28
50
|
require 'git/remote'
|
|
29
51
|
require 'git/repository'
|
|
52
|
+
require 'git/base'
|
|
30
53
|
require 'git/status'
|
|
31
54
|
require 'git/stash'
|
|
55
|
+
require 'git/stash_info'
|
|
32
56
|
require 'git/stashes'
|
|
57
|
+
require 'git/tag_delete_failure'
|
|
58
|
+
require 'git/tag_delete_result'
|
|
59
|
+
require 'git/tag_info'
|
|
33
60
|
require 'git/url'
|
|
34
|
-
require 'git/version'
|
|
35
|
-
require 'git/working_directory'
|
|
36
61
|
require 'git/worktree'
|
|
37
62
|
require 'git/worktrees'
|
|
38
63
|
|
|
@@ -43,7 +68,7 @@ require 'git/worktrees'
|
|
|
43
68
|
#
|
|
44
69
|
# @author Scott Chacon (mailto:schacon@gmail.com)
|
|
45
70
|
#
|
|
46
|
-
module Git
|
|
71
|
+
module Git
|
|
47
72
|
# g.config('user.name', 'Scott Chacon') # sets value
|
|
48
73
|
# g.config('user.email', 'email@email.com') # sets value
|
|
49
74
|
# g.config('user.name') # returns 'Scott Chacon'
|
|
@@ -123,9 +148,9 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
123
148
|
#
|
|
124
149
|
# @param directory [Pathname, nil] The directory to clone into
|
|
125
150
|
#
|
|
126
|
-
# If `directory` is a relative
|
|
127
|
-
# given. If `
|
|
128
|
-
# 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.
|
|
129
154
|
#
|
|
130
155
|
# If `nil`, `directory` will be set to the basename of the last component of
|
|
131
156
|
# the path from the `repository_url`. For example, for the URL:
|
|
@@ -176,9 +201,14 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
176
201
|
# @option options [String] :origin Use the value instead `origin` to track
|
|
177
202
|
# the upstream repository.
|
|
178
203
|
#
|
|
179
|
-
# @option options [Pathname] :
|
|
180
|
-
#
|
|
181
|
-
# `
|
|
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.
|
|
182
212
|
#
|
|
183
213
|
# @option options [Boolean] :recursive After the clone is created, initialize
|
|
184
214
|
# all submodules within, using their default settings.
|
|
@@ -191,8 +221,10 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
191
221
|
#
|
|
192
222
|
# @example Clone into a different directory `my-ruby-git`
|
|
193
223
|
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', 'my-ruby-git')
|
|
194
|
-
#
|
|
195
|
-
#
|
|
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
|
|
196
228
|
#
|
|
197
229
|
# @example Create a bare repository in the directory `ruby-git.git`
|
|
198
230
|
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', bare: true)
|
|
@@ -220,8 +252,6 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
220
252
|
# of the cloned local working copy or cloned repository.
|
|
221
253
|
#
|
|
222
254
|
def self.clone(repository_url, directory = nil, options = {})
|
|
223
|
-
clone_to_options = options.slice(:bare, :mirror)
|
|
224
|
-
directory ||= Git::URL.clone_to(repository_url, **clone_to_options)
|
|
225
255
|
Base.clone(repository_url, directory, options)
|
|
226
256
|
end
|
|
227
257
|
|
|
@@ -329,6 +359,8 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
329
359
|
# and converted to an absolute path using
|
|
330
360
|
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
|
|
331
361
|
#
|
|
362
|
+
# @option options [Pathname] :separate_git_dir Alias for `:repository`.
|
|
363
|
+
#
|
|
332
364
|
# @option options [String, nil] :git_ssh An optional custom SSH command
|
|
333
365
|
#
|
|
334
366
|
# - If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
|
|
@@ -357,7 +389,30 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
357
389
|
# @see https://git-scm.com/docs/git-init git init
|
|
358
390
|
#
|
|
359
391
|
def self.init(directory = '.', options = {})
|
|
360
|
-
|
|
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
|
|
361
416
|
end
|
|
362
417
|
|
|
363
418
|
# returns a Hash containing information about the references
|
|
@@ -426,6 +481,37 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
426
481
|
Base.open(working_dir, options)
|
|
427
482
|
end
|
|
428
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
|
+
|
|
429
515
|
# Return the version of the git binary
|
|
430
516
|
#
|
|
431
517
|
# @example
|
|
@@ -433,7 +519,17 @@ module Git # rubocop:disable Style/OneClassPerFile
|
|
|
433
519
|
#
|
|
434
520
|
# @return [Array<Integer>] the version of the git binary
|
|
435
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
|
+
#
|
|
436
526
|
def self.binary_version(binary_path = Git::Base.config.binary_path)
|
|
437
|
-
|
|
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
|
|
438
534
|
end
|
|
439
535
|
end
|