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/stash.rb
CHANGED
|
@@ -1,26 +1,107 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'git/base'
|
|
4
|
+
|
|
3
5
|
module Git
|
|
4
|
-
#
|
|
6
|
+
# Represents a single stash entry in a Git repository
|
|
7
|
+
#
|
|
8
|
+
# @example Create a stash and inspect the result
|
|
9
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
10
|
+
# stash.message #=> "WIP: feature work"
|
|
11
|
+
# stash.saved? #=> true
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
#
|
|
5
15
|
class Stash
|
|
6
|
-
|
|
16
|
+
# Initialize a Stash object
|
|
17
|
+
#
|
|
18
|
+
# When `existing` is `false` (the default), immediately calls {#save} to push
|
|
19
|
+
# the current working-directory state onto the stash stack.
|
|
20
|
+
#
|
|
21
|
+
# @param base [Git::Repository, Git::Base] the git repository
|
|
22
|
+
#
|
|
23
|
+
# @param message [String] the stash message
|
|
24
|
+
#
|
|
25
|
+
# @param existing [Boolean] (false) when `true`, wraps an existing stash entry
|
|
26
|
+
# without pushing any changes
|
|
27
|
+
#
|
|
28
|
+
# @return [void]
|
|
29
|
+
#
|
|
30
|
+
# @example Create a new stash entry
|
|
31
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
32
|
+
# stash.saved? #=> true
|
|
33
|
+
#
|
|
34
|
+
# @example Reference an existing stash without pushing
|
|
35
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
36
|
+
# stash.saved? #=> nil
|
|
37
|
+
#
|
|
38
|
+
def initialize(base, message, existing: false)
|
|
7
39
|
@base = base
|
|
8
40
|
@message = message
|
|
9
|
-
|
|
41
|
+
save unless existing
|
|
10
42
|
end
|
|
11
43
|
|
|
44
|
+
# Saves the current working-directory state to the stash stack
|
|
45
|
+
#
|
|
46
|
+
# @return [Boolean] `true` if changes were stashed, `false` if there were no
|
|
47
|
+
# local changes to save
|
|
48
|
+
#
|
|
49
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
50
|
+
#
|
|
51
|
+
# @example Save changes to the stash stack
|
|
52
|
+
# stash = Git::Stash.new(repo, 'WIP', existing: true)
|
|
53
|
+
# stash.save #=> true
|
|
54
|
+
#
|
|
12
55
|
def save
|
|
13
|
-
@saved =
|
|
56
|
+
@saved = stash_repository.stash_save(@message)
|
|
14
57
|
end
|
|
15
58
|
|
|
59
|
+
# Returns whether the stash was saved successfully
|
|
60
|
+
#
|
|
61
|
+
# @return [Boolean, nil] `true` if changes were stashed, `false` if there were no
|
|
62
|
+
# local changes, `nil` if {#save} has not been called (e.g. `existing: true`)
|
|
63
|
+
#
|
|
64
|
+
# @example Check if changes were stashed
|
|
65
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work')
|
|
66
|
+
# stash.saved? #=> true
|
|
67
|
+
#
|
|
16
68
|
def saved?
|
|
17
69
|
@saved
|
|
18
70
|
end
|
|
19
71
|
|
|
72
|
+
# Returns the stash description
|
|
73
|
+
#
|
|
74
|
+
# @return [String] the stash message
|
|
75
|
+
#
|
|
76
|
+
# @example Read the stash message
|
|
77
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
78
|
+
# stash.message #=> "WIP: feature work"
|
|
79
|
+
#
|
|
20
80
|
attr_reader :message
|
|
21
81
|
|
|
82
|
+
# Returns the stash description as a string
|
|
83
|
+
#
|
|
84
|
+
# @return [String] the stash message
|
|
85
|
+
#
|
|
86
|
+
# @example Convert stash to string
|
|
87
|
+
# stash = Git::Stash.new(repo, 'WIP: feature work', existing: true)
|
|
88
|
+
# stash.to_s #=> "WIP: feature work"
|
|
89
|
+
#
|
|
22
90
|
def to_s
|
|
23
91
|
message
|
|
24
92
|
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
# Returns the facade interface for stash operations
|
|
97
|
+
#
|
|
98
|
+
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
99
|
+
# The `is_a?` guard will be removed when {Git::Base} is deleted in Phase 4.
|
|
100
|
+
#
|
|
101
|
+
# @return [Git::Repository]
|
|
102
|
+
#
|
|
103
|
+
def stash_repository
|
|
104
|
+
@base.is_a?(Git::Base) ? @base.facade_repository : @base
|
|
105
|
+
end
|
|
25
106
|
end
|
|
26
107
|
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Immutable value object representing stash entry information
|
|
5
|
+
#
|
|
6
|
+
# StashInfo encapsulates the parsed data from `git stash list` output.
|
|
7
|
+
# Each entry contains comprehensive information about the stash including
|
|
8
|
+
# its index, reference name, commit SHA, branch, message, author/committer
|
|
9
|
+
# details, and timestamps.
|
|
10
|
+
#
|
|
11
|
+
# @api public
|
|
12
|
+
#
|
|
13
|
+
# @example Create a StashInfo from parsed stash list output
|
|
14
|
+
# info = Git::StashInfo.new(
|
|
15
|
+
# index: 0,
|
|
16
|
+
# name: 'stash@{0}',
|
|
17
|
+
# oid: 'abc123def456789...',
|
|
18
|
+
# short_oid: 'abc123d',
|
|
19
|
+
# branch: 'main',
|
|
20
|
+
# message: 'WIP on main: abc123 Initial commit',
|
|
21
|
+
# author_name: 'Jane Doe',
|
|
22
|
+
# author_email: 'jane@example.com',
|
|
23
|
+
# author_date: '2026-01-24T10:30:00-08:00',
|
|
24
|
+
# committer_name: 'Jane Doe',
|
|
25
|
+
# committer_email: 'jane@example.com',
|
|
26
|
+
# committer_date: '2026-01-24T10:30:00-08:00'
|
|
27
|
+
# )
|
|
28
|
+
#
|
|
29
|
+
# info.index # => 0
|
|
30
|
+
# info.name # => 'stash@{0}'
|
|
31
|
+
# info.oid # => 'abc123def456789...'
|
|
32
|
+
# info.short_oid # => 'abc123d'
|
|
33
|
+
# info.branch # => 'main'
|
|
34
|
+
# info.message # => 'WIP on main: abc123 Initial commit'
|
|
35
|
+
# info.author_name # => 'Jane Doe'
|
|
36
|
+
# info.author_email # => 'jane@example.com'
|
|
37
|
+
# info.author_date # => '2026-01-24T10:30:00-08:00'
|
|
38
|
+
# info.committer_name # => 'Jane Doe'
|
|
39
|
+
# info.committer_email # => 'jane@example.com'
|
|
40
|
+
# info.committer_date # => '2026-01-24T10:30:00-08:00'
|
|
41
|
+
#
|
|
42
|
+
# @!attribute [r] index
|
|
43
|
+
# @return [Integer] the stash index (0, 1, 2, ...)
|
|
44
|
+
#
|
|
45
|
+
# @!attribute [r] name
|
|
46
|
+
# @return [String] the stash reference name (e.g., 'stash@\\{0\\}')
|
|
47
|
+
#
|
|
48
|
+
# @!attribute [r] oid
|
|
49
|
+
# @return [String] the full 40-character object identifier of the stash
|
|
50
|
+
#
|
|
51
|
+
# @!attribute [r] short_oid
|
|
52
|
+
# @return [String] the abbreviated object identifier (typically 7 characters)
|
|
53
|
+
#
|
|
54
|
+
# @!attribute [r] branch
|
|
55
|
+
# @return [String, nil] the branch name where the stash was created,
|
|
56
|
+
# or nil for custom stash messages
|
|
57
|
+
#
|
|
58
|
+
# @!attribute [r] message
|
|
59
|
+
# @return [String] the stash message (e.g., 'WIP on main: abc123 commit msg')
|
|
60
|
+
#
|
|
61
|
+
# @!attribute [r] author_name
|
|
62
|
+
# @return [String] the name of the stash author
|
|
63
|
+
#
|
|
64
|
+
# @!attribute [r] author_email
|
|
65
|
+
# @return [String] the email of the stash author
|
|
66
|
+
#
|
|
67
|
+
# @!attribute [r] author_date
|
|
68
|
+
# @return [String] the author date in ISO 8601 format
|
|
69
|
+
#
|
|
70
|
+
# @!attribute [r] committer_name
|
|
71
|
+
# @return [String] the name of the stash committer
|
|
72
|
+
#
|
|
73
|
+
# @!attribute [r] committer_email
|
|
74
|
+
# @return [String] the email of the stash committer
|
|
75
|
+
#
|
|
76
|
+
# @!attribute [r] committer_date
|
|
77
|
+
# @return [String] the committer date in ISO 8601 format
|
|
78
|
+
#
|
|
79
|
+
StashInfo = Data.define(
|
|
80
|
+
:index,
|
|
81
|
+
:name,
|
|
82
|
+
:oid,
|
|
83
|
+
:short_oid,
|
|
84
|
+
:branch,
|
|
85
|
+
:message,
|
|
86
|
+
:author_name,
|
|
87
|
+
:author_email,
|
|
88
|
+
:author_date,
|
|
89
|
+
:committer_name,
|
|
90
|
+
:committer_email,
|
|
91
|
+
:committer_date
|
|
92
|
+
) do
|
|
93
|
+
# Returns the stash reference name
|
|
94
|
+
#
|
|
95
|
+
# @return [String] the stash name (e.g., 'stash@\\{0}')
|
|
96
|
+
#
|
|
97
|
+
# @example
|
|
98
|
+
# info.to_s # => 'stash@{0}'
|
|
99
|
+
#
|
|
100
|
+
def to_s
|
|
101
|
+
name
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/lib/git/stashes.rb
CHANGED
|
@@ -1,56 +1,173 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'git/base'
|
|
4
|
+
|
|
3
5
|
module Git
|
|
4
|
-
#
|
|
6
|
+
# Collection of stash entries for a Git repository
|
|
7
|
+
#
|
|
8
|
+
# @example Iterate over stash entries
|
|
9
|
+
# git.stashes.each { |s| puts s.message }
|
|
10
|
+
#
|
|
11
|
+
# @example Check and apply a stash
|
|
12
|
+
# git.stashes.size #=> 2
|
|
13
|
+
# git.stashes.apply
|
|
14
|
+
#
|
|
15
|
+
# @api public
|
|
16
|
+
#
|
|
5
17
|
class Stashes
|
|
6
18
|
include Enumerable
|
|
7
19
|
|
|
20
|
+
# Initialize the stashes collection
|
|
21
|
+
#
|
|
22
|
+
# Loads all existing stash entries from the repository at construction time.
|
|
23
|
+
#
|
|
24
|
+
# @param base [Git::Repository, Git::Base] the git repository
|
|
25
|
+
#
|
|
26
|
+
# @return [void]
|
|
27
|
+
#
|
|
28
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
29
|
+
#
|
|
30
|
+
# @example Load stashes for a repository
|
|
31
|
+
# stashes = Git::Stashes.new(repo)
|
|
32
|
+
# stashes.size #=> 2
|
|
33
|
+
#
|
|
8
34
|
def initialize(base)
|
|
9
35
|
@stashes = []
|
|
10
|
-
|
|
11
36
|
@base = base
|
|
12
37
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@stashes.unshift(Git::Stash.new(@base, message,
|
|
38
|
+
stash_repository.stashes_all.each do |stash|
|
|
39
|
+
message = stash[1]
|
|
40
|
+
@stashes.unshift(Git::Stash.new(@base, message, existing: true))
|
|
16
41
|
end
|
|
17
42
|
end
|
|
18
43
|
|
|
44
|
+
# Returns all stash entries as an array of index and message pairs
|
|
45
|
+
#
|
|
46
|
+
# Entries are listed in oldest-first order matching {Git::Repository#stashes_all}.
|
|
47
|
+
#
|
|
48
|
+
# @example List all stash entries
|
|
49
|
+
# git.stashes.all #=> [[0, "testing-stash-all"], [1, "another-stash"]]
|
|
19
50
|
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
51
|
+
# @return [Array<Array(Integer, String)>] array of `[index, message]` pairs where
|
|
52
|
+
# index 0 is the oldest stash
|
|
53
|
+
#
|
|
54
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
22
55
|
#
|
|
23
|
-
# @example Returns Array of items that have been stashed
|
|
24
|
-
# .all - [0, "testing-stash-all"]]
|
|
25
|
-
# @return [Array]
|
|
26
56
|
def all
|
|
27
|
-
|
|
57
|
+
stash_repository.stashes_all
|
|
28
58
|
end
|
|
29
59
|
|
|
60
|
+
# Saves the current working-directory state to a new stash entry
|
|
61
|
+
#
|
|
62
|
+
# @param message [String] the stash message
|
|
63
|
+
#
|
|
64
|
+
# @return [void]
|
|
65
|
+
#
|
|
66
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
67
|
+
#
|
|
68
|
+
# @example Save current changes to the stash
|
|
69
|
+
# git.stashes.save('WIP: feature work')
|
|
70
|
+
# git.stashes.size #=> 1
|
|
71
|
+
#
|
|
30
72
|
def save(message)
|
|
31
73
|
s = Git::Stash.new(@base, message)
|
|
32
74
|
@stashes.unshift(s) if s.saved?
|
|
33
75
|
end
|
|
34
76
|
|
|
77
|
+
# Applies a stash entry to the working directory
|
|
78
|
+
#
|
|
79
|
+
# @param index [Integer, nil] the stash index to apply (default: latest)
|
|
80
|
+
#
|
|
81
|
+
# @return [String] the output from the git stash apply command
|
|
82
|
+
#
|
|
83
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
84
|
+
#
|
|
85
|
+
# @example Apply the most recent stash
|
|
86
|
+
# git.stashes.apply
|
|
87
|
+
#
|
|
88
|
+
# @example Apply a specific stash by index
|
|
89
|
+
# git.stashes.apply(1)
|
|
90
|
+
#
|
|
35
91
|
def apply(index = nil)
|
|
36
|
-
|
|
92
|
+
stash_repository.stash_apply(index)
|
|
37
93
|
end
|
|
38
94
|
|
|
95
|
+
# Removes all stash entries
|
|
96
|
+
#
|
|
97
|
+
# @return [void]
|
|
98
|
+
#
|
|
99
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
100
|
+
#
|
|
101
|
+
# @example Clear all stashes
|
|
102
|
+
# git.stashes.clear
|
|
103
|
+
# git.stashes.size #=> 0
|
|
104
|
+
#
|
|
39
105
|
def clear
|
|
40
|
-
|
|
106
|
+
stash_repository.stash_clear
|
|
41
107
|
@stashes = []
|
|
108
|
+
nil
|
|
42
109
|
end
|
|
43
110
|
|
|
111
|
+
# Returns the number of stash entries
|
|
112
|
+
#
|
|
113
|
+
# @return [Integer] the number of stashes
|
|
114
|
+
#
|
|
115
|
+
# @example Check how many stashes exist
|
|
116
|
+
# git.stashes.size #=> 2
|
|
117
|
+
#
|
|
44
118
|
def size
|
|
45
119
|
@stashes.size
|
|
46
120
|
end
|
|
47
121
|
|
|
122
|
+
# Iterates over each stash entry in newest-first order
|
|
123
|
+
#
|
|
124
|
+
# @example Iterate over stashes
|
|
125
|
+
# git.stashes.each { |s| puts s.message }
|
|
126
|
+
#
|
|
127
|
+
# @overload each
|
|
128
|
+
#
|
|
129
|
+
# @return [Enumerator<Git::Stash>] an enumerator over stash entries
|
|
130
|
+
#
|
|
131
|
+
# @overload each(&block)
|
|
132
|
+
#
|
|
133
|
+
# @yield [stash] each stash entry
|
|
134
|
+
#
|
|
135
|
+
# @yieldparam stash [Git::Stash] the current stash entry
|
|
136
|
+
#
|
|
137
|
+
# @yieldreturn [void]
|
|
138
|
+
#
|
|
139
|
+
# @return [Array<Git::Stash>] the stash entries
|
|
140
|
+
#
|
|
48
141
|
def each(&)
|
|
49
142
|
@stashes.each(&)
|
|
50
143
|
end
|
|
51
144
|
|
|
145
|
+
# Returns the stash entry at the given index
|
|
146
|
+
#
|
|
147
|
+
# Stashes are stored in newest-first order; index 0 is the most recent stash.
|
|
148
|
+
#
|
|
149
|
+
# @param index [Integer, #to_i] the stash index (0 = most recent)
|
|
150
|
+
#
|
|
151
|
+
# @return [Git::Stash, nil] the stash entry, or `nil` if the index is out of bounds
|
|
152
|
+
#
|
|
153
|
+
# @example Access the most recent stash
|
|
154
|
+
# git.stashes[0].message #=> "WIP: feature work"
|
|
155
|
+
#
|
|
52
156
|
def [](index)
|
|
53
157
|
@stashes[index.to_i]
|
|
54
158
|
end
|
|
159
|
+
|
|
160
|
+
private
|
|
161
|
+
|
|
162
|
+
# Returns the facade interface for stash operations
|
|
163
|
+
#
|
|
164
|
+
# Accepts either a {Git::Repository} (new form) or a {Git::Base} (legacy).
|
|
165
|
+
# The `is_a?` guard will be removed when {Git::Base} is deleted in Phase 4.
|
|
166
|
+
#
|
|
167
|
+
# @return [Git::Repository]
|
|
168
|
+
#
|
|
169
|
+
def stash_repository
|
|
170
|
+
@base.is_a?(Git::Base) ? @base.facade_repository : @base
|
|
171
|
+
end
|
|
55
172
|
end
|
|
56
173
|
end
|