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
data/lib/git/status.rb
CHANGED
|
@@ -12,37 +12,112 @@ module Git
|
|
|
12
12
|
class Status
|
|
13
13
|
include Enumerable
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Create a new Status for the given repository
|
|
16
|
+
#
|
|
17
|
+
# @param base [Git::Base, Git::Repository] the git object backing this status
|
|
18
|
+
#
|
|
16
19
|
def initialize(base)
|
|
17
20
|
@base = base
|
|
18
21
|
# The factory returns a hash of file paths to StatusFile objects.
|
|
19
22
|
@files = StatusFileFactory.new(base).construct_files
|
|
20
23
|
end
|
|
21
24
|
|
|
22
|
-
#
|
|
25
|
+
# Return files modified in the index and/or working tree
|
|
26
|
+
#
|
|
27
|
+
# Includes both staged modifications (index vs HEAD) and unstaged modifications
|
|
28
|
+
# (working tree vs index).
|
|
29
|
+
#
|
|
30
|
+
# @return [Hash{String => Git::Status::StatusFile}] changed files keyed by path
|
|
31
|
+
#
|
|
23
32
|
def changed = @changed ||= select_files { |f| f.type == 'M' }
|
|
33
|
+
|
|
34
|
+
# Return files added to the index that are not yet in HEAD
|
|
35
|
+
#
|
|
36
|
+
# @return [Hash{String => Git::Status::StatusFile}] added files keyed by path
|
|
37
|
+
#
|
|
24
38
|
def added = @added ||= select_files { |f| f.type == 'A' }
|
|
39
|
+
|
|
40
|
+
# Return files deleted from the index
|
|
41
|
+
#
|
|
42
|
+
# @return [Hash{String => Git::Status::StatusFile}] deleted files keyed by path
|
|
43
|
+
#
|
|
25
44
|
def deleted = @deleted ||= select_files { |f| f.type == 'D' }
|
|
26
|
-
|
|
45
|
+
|
|
46
|
+
# Return files present in the working tree but not tracked by git
|
|
47
|
+
#
|
|
48
|
+
# @return [Hash{String => Git::Status::StatusFile}] untracked files keyed by path
|
|
49
|
+
#
|
|
27
50
|
def untracked = @untracked ||= select_files(&:untracked)
|
|
28
51
|
|
|
29
|
-
#
|
|
52
|
+
# Return `true` if `file` has been modified in the index or working tree
|
|
53
|
+
#
|
|
54
|
+
# @param file [String] the repository-relative path to check
|
|
55
|
+
#
|
|
56
|
+
# @return [Boolean] `true` if the file has been modified
|
|
57
|
+
#
|
|
30
58
|
def changed?(file) = file_in_collection?(:changed, file)
|
|
59
|
+
|
|
60
|
+
# Return `true` if `file` has been added to the index
|
|
61
|
+
#
|
|
62
|
+
# @param file [String] the repository-relative path to check
|
|
63
|
+
#
|
|
64
|
+
# @return [Boolean] `true` if the file has been added
|
|
65
|
+
#
|
|
31
66
|
def added?(file) = file_in_collection?(:added, file)
|
|
67
|
+
|
|
68
|
+
# Return `true` if `file` has been deleted from the index
|
|
69
|
+
#
|
|
70
|
+
# @param file [String] the repository-relative path to check
|
|
71
|
+
#
|
|
72
|
+
# @return [Boolean] `true` if the file has been deleted
|
|
73
|
+
#
|
|
32
74
|
def deleted?(file) = file_in_collection?(:deleted, file)
|
|
75
|
+
|
|
76
|
+
# Return `true` if `file` is not tracked by git
|
|
77
|
+
#
|
|
78
|
+
# @param file [String] the repository-relative path to check
|
|
79
|
+
#
|
|
80
|
+
# @return [Boolean] `true` if the file is untracked
|
|
81
|
+
#
|
|
33
82
|
def untracked?(file) = file_in_collection?(:untracked, file)
|
|
34
83
|
|
|
35
|
-
#
|
|
84
|
+
# Return the {Git::Status::StatusFile} for the given path
|
|
85
|
+
#
|
|
86
|
+
# @param file [String] the repository-relative path
|
|
87
|
+
#
|
|
88
|
+
# @return [Git::Status::StatusFile, nil] the status file, or `nil` if not found
|
|
89
|
+
#
|
|
36
90
|
def [](file) = @files[file]
|
|
91
|
+
|
|
92
|
+
# Iterate over all status files
|
|
93
|
+
#
|
|
94
|
+
# @yield [file] each {Git::Status::StatusFile} in the repository
|
|
95
|
+
#
|
|
96
|
+
# @yieldparam file [Git::Status::StatusFile] a single file's status
|
|
97
|
+
#
|
|
98
|
+
# @return [Enumerator<Git::Status::StatusFile>] if no block is given
|
|
99
|
+
#
|
|
100
|
+
# @return [Array<Git::Status::StatusFile>] if a block is given
|
|
101
|
+
#
|
|
37
102
|
def each(&) = @files.values.each(&)
|
|
38
103
|
|
|
39
|
-
#
|
|
104
|
+
# Return a formatted multi-line string representation of the status
|
|
105
|
+
#
|
|
106
|
+
# @return [String] one indented block per file showing its SHA, mode, type,
|
|
107
|
+
# stage, and untracked flag
|
|
108
|
+
#
|
|
40
109
|
def pretty
|
|
41
110
|
map { |file| pretty_file(file) }.join << "\n"
|
|
42
111
|
end
|
|
43
112
|
|
|
44
113
|
private
|
|
45
114
|
|
|
115
|
+
# Format a single file's status as an indented multi-line string
|
|
116
|
+
#
|
|
117
|
+
# @param file [Git::Status::StatusFile] the file to format
|
|
118
|
+
#
|
|
119
|
+
# @return [String] the formatted status block for this file
|
|
120
|
+
#
|
|
46
121
|
def pretty_file(file)
|
|
47
122
|
<<~FILE
|
|
48
123
|
#{file.path}
|
|
@@ -54,10 +129,26 @@ module Git
|
|
|
54
129
|
FILE
|
|
55
130
|
end
|
|
56
131
|
|
|
132
|
+
# Return a hash of files for which the block returns a truthy value
|
|
133
|
+
#
|
|
134
|
+
# @yield [file] each {Git::Status::StatusFile} in the repository
|
|
135
|
+
#
|
|
136
|
+
# @yieldparam file [Git::Status::StatusFile] a single file's status
|
|
137
|
+
#
|
|
138
|
+
# @return [Hash{String => Git::Status::StatusFile}] matching files keyed by path
|
|
139
|
+
#
|
|
57
140
|
def select_files(&block)
|
|
58
141
|
@files.select { |_path, file| block.call(file) }
|
|
59
142
|
end
|
|
60
143
|
|
|
144
|
+
# Return `true` if `file_path` exists in the named status collection
|
|
145
|
+
#
|
|
146
|
+
# @param collection_name [Symbol] the collection to check (e.g. `:changed`)
|
|
147
|
+
#
|
|
148
|
+
# @param file_path [String] the repository-relative path to look up
|
|
149
|
+
#
|
|
150
|
+
# @return [Boolean] `true` if the path is present in the collection
|
|
151
|
+
#
|
|
61
152
|
def file_in_collection?(collection_name, file_path)
|
|
62
153
|
collection = public_send(collection_name)
|
|
63
154
|
if ignore_case?
|
|
@@ -67,12 +158,25 @@ module Git
|
|
|
67
158
|
end
|
|
68
159
|
end
|
|
69
160
|
|
|
161
|
+
# Return a memoized set of downcased keys for the named collection
|
|
162
|
+
#
|
|
163
|
+
# @param collection_name [Symbol] the collection whose keys to downcase
|
|
164
|
+
#
|
|
165
|
+
# @return [Set<String>] the lowercased path keys
|
|
166
|
+
#
|
|
70
167
|
def downcased_keys(collection_name)
|
|
71
168
|
@_downcased_keys ||= {}
|
|
72
169
|
@_downcased_keys[collection_name] ||=
|
|
73
170
|
public_send(collection_name).keys.to_set(&:downcase)
|
|
74
171
|
end
|
|
75
172
|
|
|
173
|
+
# Return `true` when git is configured to ignore filename case
|
|
174
|
+
#
|
|
175
|
+
# Reads `core.ignoreCase` from the repository config. Returns `false` if
|
|
176
|
+
# the config value is absent or if reading it raises {Git::FailedError}.
|
|
177
|
+
#
|
|
178
|
+
# @return [Boolean] `true` when `core.ignoreCase` is `"true"`
|
|
179
|
+
#
|
|
76
180
|
def ignore_case?
|
|
77
181
|
return @_ignore_case if defined?(@_ignore_case)
|
|
78
182
|
|
|
@@ -80,13 +184,65 @@ module Git
|
|
|
80
184
|
rescue Git::FailedError
|
|
81
185
|
@_ignore_case = false
|
|
82
186
|
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
83
189
|
|
|
190
|
+
module Git
|
|
191
|
+
class Status
|
|
84
192
|
# Represents a single file's status in the git repository. Each instance
|
|
85
193
|
# holds information about a file's state in the index and working tree.
|
|
194
|
+
#
|
|
195
|
+
# @api public
|
|
196
|
+
#
|
|
86
197
|
class StatusFile
|
|
87
|
-
|
|
88
|
-
|
|
198
|
+
# The repository-relative file path
|
|
199
|
+
#
|
|
200
|
+
# @return [String] the path
|
|
201
|
+
attr_reader :path
|
|
89
202
|
|
|
203
|
+
# The change type for this file
|
|
204
|
+
#
|
|
205
|
+
# @return [String, nil] `"M"` for modified, `"A"` for added, `"D"` for deleted,
|
|
206
|
+
# or `nil` when not applicable
|
|
207
|
+
attr_reader :type
|
|
208
|
+
|
|
209
|
+
# The merge stage for this file
|
|
210
|
+
#
|
|
211
|
+
# @return [String, nil] `"0"` for normal entries, or a non-zero value during
|
|
212
|
+
# a merge conflict
|
|
213
|
+
attr_reader :stage
|
|
214
|
+
|
|
215
|
+
# The file mode recorded in the index
|
|
216
|
+
#
|
|
217
|
+
# @return [String, nil] the octal file mode (e.g. `"100644"`), or `nil`
|
|
218
|
+
attr_reader :mode_index
|
|
219
|
+
|
|
220
|
+
# The file mode recorded in HEAD
|
|
221
|
+
#
|
|
222
|
+
# @return [String, nil] the octal file mode (e.g. `"100644"`), or `nil`
|
|
223
|
+
attr_reader :mode_repo
|
|
224
|
+
|
|
225
|
+
# The SHA of the index version of this file
|
|
226
|
+
#
|
|
227
|
+
# @return [String, nil] the SHA-1 hex digest, or `nil` if unavailable
|
|
228
|
+
attr_reader :sha_index
|
|
229
|
+
|
|
230
|
+
# The SHA of the HEAD version of this file
|
|
231
|
+
#
|
|
232
|
+
# @return [String, nil] the SHA-1 hex digest, or `nil` if unavailable
|
|
233
|
+
attr_reader :sha_repo
|
|
234
|
+
|
|
235
|
+
# Whether this file is untracked
|
|
236
|
+
#
|
|
237
|
+
# @return [Boolean, nil] `true` when the file is not tracked by git
|
|
238
|
+
attr_reader :untracked
|
|
239
|
+
|
|
240
|
+
# Initialize a new StatusFile with the given git object and data hash
|
|
241
|
+
#
|
|
242
|
+
# @param base [Git::Base, Git::Repository] the git object
|
|
243
|
+
#
|
|
244
|
+
# @param hash [Hash] raw status data for this file
|
|
245
|
+
#
|
|
90
246
|
def initialize(base, hash)
|
|
91
247
|
@base = base
|
|
92
248
|
@path = hash[:path]
|
|
@@ -99,24 +255,51 @@ module Git
|
|
|
99
255
|
@untracked = hash[:untracked]
|
|
100
256
|
end
|
|
101
257
|
|
|
102
|
-
#
|
|
258
|
+
# Return a blob object for the index or repo version of this file
|
|
259
|
+
#
|
|
260
|
+
# @param type [Symbol] `:index` (default) for the index version, or
|
|
261
|
+
# `:repo` for the HEAD version
|
|
262
|
+
#
|
|
263
|
+
# @return [Git::Object::Blob, nil] the blob object, or `nil` if no SHA
|
|
264
|
+
# is available for the requested version
|
|
265
|
+
#
|
|
103
266
|
def blob(type = :index)
|
|
104
267
|
sha = type == :repo ? sha_repo : (sha_index || sha_repo)
|
|
105
268
|
@base.object(sha) if sha
|
|
106
269
|
end
|
|
107
270
|
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
108
273
|
|
|
274
|
+
module Git
|
|
275
|
+
class Status
|
|
109
276
|
# A factory class responsible for fetching git status data and building
|
|
110
277
|
# a hash of StatusFile objects.
|
|
278
|
+
#
|
|
111
279
|
# @api private
|
|
280
|
+
#
|
|
112
281
|
class StatusFileFactory
|
|
282
|
+
# Create a new factory backed by the given git object
|
|
283
|
+
#
|
|
284
|
+
# When `base` is a {Git::Repository} (which exposes `#diff_index`
|
|
285
|
+
# directly), it is used as the data provider. When `base` is a
|
|
286
|
+
# {Git::Base} (the legacy path), `base.lib` is used instead.
|
|
287
|
+
#
|
|
288
|
+
# @param base [Git::Base, Git::Repository] the git object used as the
|
|
289
|
+
# status data provider
|
|
290
|
+
#
|
|
113
291
|
def initialize(base)
|
|
114
292
|
@base = base
|
|
115
|
-
|
|
293
|
+
# When base is Git::Repository (which exposes #diff_index directly),
|
|
294
|
+
# use it as the data provider. Otherwise use base.lib (legacy path).
|
|
295
|
+
@provider = base.respond_to?(:diff_index) ? base : base.lib
|
|
116
296
|
end
|
|
117
297
|
|
|
118
|
-
#
|
|
119
|
-
#
|
|
298
|
+
# Gather all status data and build a hash of file paths to StatusFile objects
|
|
299
|
+
#
|
|
300
|
+
# @return [Hash{String => Git::Status::StatusFile}] file paths mapped to
|
|
301
|
+
# their status objects
|
|
302
|
+
#
|
|
120
303
|
def construct_files
|
|
121
304
|
files_data = fetch_all_files_data
|
|
122
305
|
files_data.transform_values do |data|
|
|
@@ -126,33 +309,56 @@ module Git
|
|
|
126
309
|
|
|
127
310
|
private
|
|
128
311
|
|
|
129
|
-
#
|
|
312
|
+
# Fetch and merge status information from multiple git commands
|
|
313
|
+
#
|
|
314
|
+
# @return [Hash{String => Hash}] raw per-file status data keyed by path
|
|
315
|
+
#
|
|
130
316
|
def fetch_all_files_data
|
|
131
|
-
files = @
|
|
317
|
+
files = @provider.ls_files # Start with files tracked in the index.
|
|
132
318
|
merge_untracked_files(files)
|
|
133
319
|
merge_modified_files(files)
|
|
134
320
|
merge_head_diffs(files)
|
|
135
321
|
files
|
|
136
322
|
end
|
|
137
323
|
|
|
324
|
+
# Merge untracked working-tree files into `files`
|
|
325
|
+
#
|
|
326
|
+
# @param files [Hash] the in-progress files hash to update in place
|
|
327
|
+
#
|
|
328
|
+
# @return [void]
|
|
329
|
+
#
|
|
138
330
|
def merge_untracked_files(files)
|
|
139
|
-
@
|
|
331
|
+
@provider.untracked_files.each do |file|
|
|
140
332
|
files[file] = { path: file, untracked: true }
|
|
141
333
|
end
|
|
142
334
|
end
|
|
143
335
|
|
|
336
|
+
# Merge index-versus-working-tree diff data into `files`
|
|
337
|
+
#
|
|
338
|
+
# @param files [Hash] the in-progress files hash to update in place
|
|
339
|
+
#
|
|
340
|
+
# @return [void]
|
|
341
|
+
#
|
|
144
342
|
def merge_modified_files(files)
|
|
145
343
|
# Merge changes between the index and the working directory.
|
|
146
|
-
@
|
|
344
|
+
@provider.diff_files.each do |path, data|
|
|
147
345
|
(files[path] ||= {}).merge!(data)
|
|
148
346
|
end
|
|
149
347
|
end
|
|
150
348
|
|
|
349
|
+
# Merge HEAD-versus-index diff data into `files`, if commits exist
|
|
350
|
+
#
|
|
351
|
+
# @param files [Hash] the in-progress files hash to update in place
|
|
352
|
+
#
|
|
353
|
+
# @return [void]
|
|
354
|
+
#
|
|
151
355
|
def merge_head_diffs(files)
|
|
152
|
-
|
|
356
|
+
# Git::Repository exposes #no_commits?; Git::Lib exposes #empty?.
|
|
357
|
+
is_empty = @provider.respond_to?(:no_commits?) ? @provider.no_commits? : @provider.empty?
|
|
358
|
+
return if is_empty
|
|
153
359
|
|
|
154
360
|
# Merge changes between HEAD and the index.
|
|
155
|
-
@
|
|
361
|
+
@provider.diff_index('HEAD').each do |path, data|
|
|
156
362
|
(files[path] ||= {}).merge!(data)
|
|
157
363
|
end
|
|
158
364
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Represents a tag that failed to be deleted
|
|
5
|
+
#
|
|
6
|
+
# This is an immutable data object returned as part of {Git::TagDeleteResult}
|
|
7
|
+
# when one or more tags could not be deleted.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# failure = Git::TagDeleteFailure.new(
|
|
11
|
+
# name: 'nonexistent',
|
|
12
|
+
# error_message: "tag 'nonexistent' not found."
|
|
13
|
+
# )
|
|
14
|
+
# failure.name #=> 'nonexistent'
|
|
15
|
+
# failure.error_message #=> "tag 'nonexistent' not found."
|
|
16
|
+
#
|
|
17
|
+
# @see Git::TagDeleteResult
|
|
18
|
+
# @see Git::Commands::Tag::Delete
|
|
19
|
+
#
|
|
20
|
+
# @api public
|
|
21
|
+
#
|
|
22
|
+
# @!attribute [r] name
|
|
23
|
+
# The name of the tag that failed to be deleted
|
|
24
|
+
# @return [String]
|
|
25
|
+
#
|
|
26
|
+
# @!attribute [r] error_message
|
|
27
|
+
# The error message from git explaining why the tag could not be deleted
|
|
28
|
+
# @return [String]
|
|
29
|
+
#
|
|
30
|
+
TagDeleteFailure = Data.define(:name, :error_message)
|
|
31
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/tag_info'
|
|
4
|
+
require 'git/tag_delete_failure'
|
|
5
|
+
|
|
6
|
+
module Git
|
|
7
|
+
# Represents the result of a tag delete operation
|
|
8
|
+
#
|
|
9
|
+
# This is an immutable data object returned by {Git::Commands::Tag::Delete#call}.
|
|
10
|
+
# It contains information about which tags were successfully deleted and which
|
|
11
|
+
# failed to be deleted, along with the reason for each failure.
|
|
12
|
+
#
|
|
13
|
+
# Git's `git tag -d` command uses "best effort" semantics - it deletes as many
|
|
14
|
+
# tags as possible and reports errors for those that couldn't be deleted. This
|
|
15
|
+
# result object reflects that behavior, allowing callers to inspect both
|
|
16
|
+
# successes and failures.
|
|
17
|
+
#
|
|
18
|
+
# @example Successful deletion of all tags
|
|
19
|
+
# result = tag_delete.call('v1.0.0', 'v2.0.0')
|
|
20
|
+
# result.success? #=> true
|
|
21
|
+
# result.deleted.map(&:name) #=> ['v1.0.0', 'v2.0.0']
|
|
22
|
+
# result.not_deleted #=> []
|
|
23
|
+
#
|
|
24
|
+
# @example Partial failure (some tags deleted, some not found)
|
|
25
|
+
# result = tag_delete.call('v1.0.0', 'nonexistent', 'v2.0.0')
|
|
26
|
+
# result.success? #=> false
|
|
27
|
+
# result.deleted.map(&:name) #=> ['v1.0.0', 'v2.0.0']
|
|
28
|
+
# result.not_deleted.first.name #=> 'nonexistent'
|
|
29
|
+
# result.not_deleted.first.error_message #=> "tag 'nonexistent' not found."
|
|
30
|
+
#
|
|
31
|
+
# @see Git::TagInfo
|
|
32
|
+
# @see Git::TagDeleteFailure
|
|
33
|
+
# @see Git::Commands::Tag::Delete
|
|
34
|
+
#
|
|
35
|
+
# @api public
|
|
36
|
+
#
|
|
37
|
+
# @!attribute [r] deleted
|
|
38
|
+
# Tags that were successfully deleted
|
|
39
|
+
# @return [Array<Git::TagInfo>]
|
|
40
|
+
#
|
|
41
|
+
# @!attribute [r] not_deleted
|
|
42
|
+
# Tags that could not be deleted, with the reason for each failure
|
|
43
|
+
# @return [Array<Git::TagDeleteFailure>]
|
|
44
|
+
#
|
|
45
|
+
TagDeleteResult = Data.define(:deleted, :not_deleted) do
|
|
46
|
+
# Returns true if all requested tags were successfully deleted
|
|
47
|
+
#
|
|
48
|
+
# @return [Boolean] true if no tags failed to delete, false otherwise
|
|
49
|
+
#
|
|
50
|
+
# @example
|
|
51
|
+
# result = tag_delete.call('v1.0.0')
|
|
52
|
+
# if result.success?
|
|
53
|
+
# puts "All tags deleted successfully"
|
|
54
|
+
# else
|
|
55
|
+
# puts "Some tags could not be deleted:"
|
|
56
|
+
# result.not_deleted.each { |f| puts " #{f.name}: #{f.error_message}" }
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
def success?
|
|
60
|
+
not_deleted.empty?
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/git/tag_info.rb
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/author'
|
|
4
|
+
|
|
5
|
+
module Git
|
|
6
|
+
# Value object representing tag metadata from git tag output
|
|
7
|
+
#
|
|
8
|
+
# This is a lightweight, immutable data structure returned by tag listing
|
|
9
|
+
# commands. It contains only the data parsed from git output without any
|
|
10
|
+
# repository context or operations.
|
|
11
|
+
#
|
|
12
|
+
# @example Annotated tag
|
|
13
|
+
# info = Git::TagInfo.new(
|
|
14
|
+
# name: 'v1.0.0',
|
|
15
|
+
# oid: 'abc123def456', # tag object's ID
|
|
16
|
+
# target_oid: 'def456abc789', # commit it points to
|
|
17
|
+
# objecttype: 'tag',
|
|
18
|
+
# tagger_name: 'John Doe',
|
|
19
|
+
# tagger_email: '<john@example.com>',
|
|
20
|
+
# tagger_date: '2024-01-15T10:30:00-08:00',
|
|
21
|
+
# message: 'Release version 1.0.0'
|
|
22
|
+
# )
|
|
23
|
+
# info.annotated? #=> true
|
|
24
|
+
# info.tagger.name #=> 'John Doe'
|
|
25
|
+
#
|
|
26
|
+
# @example Lightweight tag
|
|
27
|
+
# info = Git::TagInfo.new(
|
|
28
|
+
# name: 'v1.0.0',
|
|
29
|
+
# oid: nil, # no tag object exists
|
|
30
|
+
# target_oid: 'def456abc789', # commit ID
|
|
31
|
+
# objecttype: 'commit',
|
|
32
|
+
# tagger_name: nil,
|
|
33
|
+
# tagger_email: nil,
|
|
34
|
+
# tagger_date: nil,
|
|
35
|
+
# message: nil
|
|
36
|
+
# )
|
|
37
|
+
# info.lightweight? #=> true
|
|
38
|
+
# info.tagger #=> nil
|
|
39
|
+
#
|
|
40
|
+
# @see Git::Tag for the full-featured tag object with operations
|
|
41
|
+
# @see Git::Commands::Tag::List for the command that produces these
|
|
42
|
+
#
|
|
43
|
+
# @api public
|
|
44
|
+
#
|
|
45
|
+
# @!attribute [r] name
|
|
46
|
+
# @return [String] the tag name (e.g., 'v1.0.0')
|
|
47
|
+
#
|
|
48
|
+
# @!attribute [r] oid
|
|
49
|
+
# The object ID of the tag object itself.
|
|
50
|
+
#
|
|
51
|
+
# For annotated tags, this is the tag object's ID. For lightweight tags,
|
|
52
|
+
# this is nil because lightweight tags are not objects in the git database.
|
|
53
|
+
#
|
|
54
|
+
# @return [String, nil] the tag object's ID, or nil for lightweight tags
|
|
55
|
+
#
|
|
56
|
+
# @!attribute [r] target_oid
|
|
57
|
+
# The object ID of the commit this tag ultimately points to.
|
|
58
|
+
#
|
|
59
|
+
# For both annotated and lightweight tags, this is the commit ID that the
|
|
60
|
+
# tag resolves to (i.e., the dereferenced target).
|
|
61
|
+
#
|
|
62
|
+
# @return [String] the commit ID this tag points to
|
|
63
|
+
#
|
|
64
|
+
# @!attribute [r] objecttype
|
|
65
|
+
# @return [String] 'tag' for annotated tags, 'commit' for lightweight tags
|
|
66
|
+
#
|
|
67
|
+
# @!attribute [r] tagger_name
|
|
68
|
+
# @return [String, nil] the tagger's name, or nil for lightweight tags
|
|
69
|
+
#
|
|
70
|
+
# @!attribute [r] tagger_email
|
|
71
|
+
# @return [String, nil] the tagger's email, or nil for lightweight tags
|
|
72
|
+
#
|
|
73
|
+
# @!attribute [r] tagger_date
|
|
74
|
+
# @return [String, nil] the tag date in ISO 8601 format, or nil for lightweight tags
|
|
75
|
+
#
|
|
76
|
+
# @!attribute [r] message
|
|
77
|
+
# @return [String, nil] the tag message, or nil for lightweight tags
|
|
78
|
+
#
|
|
79
|
+
TagInfo = Data.define(:name, :oid, :target_oid, :objecttype, :tagger_name, :tagger_email, :tagger_date, :message) do
|
|
80
|
+
# @return [Boolean] true if this is an annotated tag (oid is present)
|
|
81
|
+
def annotated?
|
|
82
|
+
!oid.nil?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @return [Boolean] true if this is a lightweight tag (oid is nil)
|
|
86
|
+
def lightweight?
|
|
87
|
+
oid.nil?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Return the tagger as an Author object
|
|
91
|
+
#
|
|
92
|
+
# @return [Git::Author, nil] the tagger as an Author object, or nil for lightweight tags
|
|
93
|
+
def tagger
|
|
94
|
+
return nil unless annotated? && tagger_name && tagger_email
|
|
95
|
+
|
|
96
|
+
# Git::Author expects format "Name <email> timestamp timezone"
|
|
97
|
+
# We construct a minimal format that will parse correctly
|
|
98
|
+
author = Git::Author.new('')
|
|
99
|
+
author.name = tagger_name
|
|
100
|
+
# Remove angle brackets if present
|
|
101
|
+
author.email = tagger_email.gsub(/\A<|>\z/, '')
|
|
102
|
+
author
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
data/lib/git/version.rb
CHANGED
|
@@ -2,6 +2,113 @@
|
|
|
2
2
|
|
|
3
3
|
module Git
|
|
4
4
|
# The current gem version
|
|
5
|
-
#
|
|
6
|
-
|
|
5
|
+
#
|
|
6
|
+
# @return [String] the current gem version
|
|
7
|
+
VERSION = '5.0.0.beta.1'
|
|
8
|
+
|
|
9
|
+
# Represents a git version with major, minor, and patch components
|
|
10
|
+
#
|
|
11
|
+
# Git versions follow a strict major.minor.patch format. This class provides
|
|
12
|
+
# parsing from git command output (which may include platform suffixes) and
|
|
13
|
+
# comparison operations for version gating.
|
|
14
|
+
#
|
|
15
|
+
# @!attribute [r] major
|
|
16
|
+
# The major version number
|
|
17
|
+
# @return [Integer]
|
|
18
|
+
#
|
|
19
|
+
# @!attribute [r] minor
|
|
20
|
+
# The minor version number
|
|
21
|
+
# @return [Integer]
|
|
22
|
+
#
|
|
23
|
+
# @!attribute [r] patch
|
|
24
|
+
# The patch version number
|
|
25
|
+
# @return [Integer]
|
|
26
|
+
#
|
|
27
|
+
# @example Creating a version directly
|
|
28
|
+
# version = Git::Version.new(2, 42, 1)
|
|
29
|
+
# version.to_s #=> "2.42.1"
|
|
30
|
+
#
|
|
31
|
+
# @example Parsing from git version output
|
|
32
|
+
# Git::Version.parse('git version 2.42.1') #=> Git::Version.new(2, 42, 1)
|
|
33
|
+
# Git::Version.parse('2.39.2 (Apple Git-143)') #=> Git::Version.new(2, 39, 2)
|
|
34
|
+
#
|
|
35
|
+
# @example Parsing versions with platform suffixes
|
|
36
|
+
# Git::Version.parse('2.42.0.windows.1') #=> Git::Version.new(2, 42, 0)
|
|
37
|
+
#
|
|
38
|
+
# @example Comparing versions
|
|
39
|
+
# Git::Version.new(2, 42, 1) > Git::Version.new(2, 28, 0) #=> true
|
|
40
|
+
#
|
|
41
|
+
# @api public
|
|
42
|
+
#
|
|
43
|
+
Version = Data.define(:major, :minor, :patch) do
|
|
44
|
+
include Comparable
|
|
45
|
+
|
|
46
|
+
# Parse a version string into a Version object
|
|
47
|
+
#
|
|
48
|
+
# Handles git's version output format, stripping platform suffixes
|
|
49
|
+
# (like `.windows.1` or `.vfs.0`) and padding two-segment versions
|
|
50
|
+
# to three segments.
|
|
51
|
+
#
|
|
52
|
+
# @example Parse various version string formats
|
|
53
|
+
# Git::Version.parse('2.42.1') #=> Git::Version.new(2, 42, 1)
|
|
54
|
+
# Git::Version.parse('git version 2.42.1') #=> Git::Version.new(2, 42, 1)
|
|
55
|
+
# Git::Version.parse('2.42.0.windows.1') #=> Git::Version.new(2, 42, 0)
|
|
56
|
+
#
|
|
57
|
+
# @param string [String] version string to parse
|
|
58
|
+
#
|
|
59
|
+
# @return [Git::Version] the parsed version
|
|
60
|
+
#
|
|
61
|
+
# @raise [Git::UnexpectedResultError] if the string cannot be parsed as a version
|
|
62
|
+
#
|
|
63
|
+
def self.parse(string)
|
|
64
|
+
version_match = string&.match(/(\d+)\.(\d+)(?:\.(\d+))?/)
|
|
65
|
+
raise Git::UnexpectedResultError, "Invalid version: #{string.inspect}" unless version_match
|
|
66
|
+
|
|
67
|
+
major = version_match[1].to_i
|
|
68
|
+
minor = version_match[2].to_i
|
|
69
|
+
patch = (version_match[3] || '0').to_i
|
|
70
|
+
|
|
71
|
+
new(major, minor, patch)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Compare this version to another
|
|
75
|
+
#
|
|
76
|
+
# @param other [Git::Version] the version to compare to
|
|
77
|
+
#
|
|
78
|
+
# @return [Integer] -1, 0, or 1
|
|
79
|
+
#
|
|
80
|
+
def <=>(other)
|
|
81
|
+
[major, minor, patch] <=> [other.major, other.minor, other.patch]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Return the version as a dotted string
|
|
85
|
+
#
|
|
86
|
+
# @return [String] the version in "major.minor.patch" format
|
|
87
|
+
#
|
|
88
|
+
def to_s
|
|
89
|
+
"#{major}.#{minor}.#{patch}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Return a readable representation
|
|
93
|
+
#
|
|
94
|
+
# @return [String] inspect string
|
|
95
|
+
#
|
|
96
|
+
def inspect
|
|
97
|
+
"#<Git::Version #{self}>"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Return the version as an array of integers
|
|
101
|
+
#
|
|
102
|
+
# Useful when legacy code expects the array shape returned by the
|
|
103
|
+
# deprecated {Git::Lib#current_command_version} method.
|
|
104
|
+
#
|
|
105
|
+
# @return [Array<Integer>] [major, minor, patch]
|
|
106
|
+
#
|
|
107
|
+
# @example
|
|
108
|
+
# Git.git_version.to_a #=> [2, 42, 0]
|
|
109
|
+
#
|
|
110
|
+
def to_a
|
|
111
|
+
deconstruct
|
|
112
|
+
end
|
|
113
|
+
end
|
|
7
114
|
end
|