git 4.3.2 → 5.0.0.beta.2
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 +73 -2705
- data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +188 -0
- 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/KEYWORD_ARG_REMEDIATION.md +22 -0
- data/.github/skills/extract-facade-from-base-lib/SKILL.md +600 -0
- data/.github/skills/facade-implementation/REFERENCE.md +840 -0
- data/.github/skills/facade-implementation/SKILL.md +274 -0
- data/.github/skills/facade-test-conventions/SKILL.md +394 -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 +12 -3
- data/.rubocop_todo.yml +23 -5
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -40
- data/CONTRIBUTING.md +694 -53
- data/README.md +67 -15
- data/Rakefile +61 -9
- data/UPGRADING.md +141 -0
- data/commitlint.test +4 -0
- data/git.gemspec +18 -7
- data/lib/git/args_builder.rb +0 -8
- data/lib/git/branch.rb +369 -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 +122 -24
- data/lib/git/command_line/base.rb +255 -0
- data/lib/git/command_line/capturing.rb +251 -0
- data/lib/git/command_line/result.rb +96 -0
- data/lib/git/command_line/streaming.rb +196 -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 +404 -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 +369 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +216 -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 +107 -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 +57 -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 +87 -0
- data/lib/git/config.rb +17 -0
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +665 -0
- data/lib/git/deprecation.rb +9 -0
- data/lib/git/detached_head_info.rb +54 -0
- data/lib/git/diff.rb +293 -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 +67 -19
- data/lib/git/diff_result.rb +32 -0
- data/lib/git/diff_stats.rb +51 -14
- data/lib/git/dirstat_info.rb +86 -0
- data/lib/git/errors.rb +65 -2
- data/lib/git/execution_context/global.rb +31 -0
- data/lib/git/execution_context/repository.rb +136 -0
- data/lib/git/execution_context.rb +501 -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/log.rb +9 -2
- data/lib/git/object.rb +90 -27
- data/lib/git/parsers/branch.rb +224 -0
- data/lib/git/parsers/cat_file.rb +111 -0
- data/lib/git/parsers/config_entry.rb +110 -0
- data/lib/git/parsers/diff.rb +585 -0
- data/lib/git/parsers/fsck.rb +133 -0
- data/lib/git/parsers/grep.rb +42 -0
- data/lib/git/parsers/ls_remote.rb +79 -0
- data/lib/git/parsers/ls_tree.rb +58 -0
- data/lib/git/parsers/stash.rb +208 -0
- data/lib/git/parsers/tag.rb +257 -0
- data/lib/git/remote.rb +120 -9
- data/lib/git/repository/branching.rb +743 -0
- data/lib/git/repository/committing.rb +187 -0
- data/lib/git/repository/configuring.rb +351 -0
- data/lib/git/repository/context_helpers.rb +264 -0
- data/lib/git/repository/diffing.rb +775 -0
- data/lib/git/repository/factories.rb +682 -0
- data/lib/git/repository/inspecting.rb +252 -0
- data/lib/git/repository/logging.rb +247 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +357 -0
- data/lib/git/repository/object_operations.rb +1199 -0
- data/lib/git/repository/path_resolver.rb +207 -0
- data/lib/git/repository/remote_operations.rb +898 -0
- data/lib/git/repository/shared_private.rb +51 -0
- data/lib/git/repository/staging.rb +554 -0
- data/lib/git/repository/stashing.rb +143 -0
- data/lib/git/repository/status_operations.rb +201 -0
- data/lib/git/repository/worktree_operations.rb +159 -0
- data/lib/git/repository.rb +203 -1
- data/lib/git/stash.rb +78 -4
- data/lib/git/stash_info.rb +104 -0
- data/lib/git/stashes.rb +125 -13
- data/lib/git/status.rb +215 -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 +108 -6
- data/lib/git/worktrees.rb +94 -7
- data/lib/git.rb +260 -61
- data/redesign/1_architecture_existing.md +54 -18
- data/redesign/2_architecture_redesign.md +365 -46
- data/redesign/3_architecture_implementation.md +1497 -63
- data/redesign/Phase 4 - Step A.md +360 -0
- data/redesign/beta_release.md +107 -0
- data/redesign/c1c2_audit.md +566 -0
- data/redesign/c1c2_bucket6_lib_orphans.md +626 -0
- data/redesign/config_design.rb +501 -0
- 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 +365 -22
- data/lib/git/base.rb +0 -1128
- data/lib/git/index.rb +0 -6
- data/lib/git/lib.rb +0 -2277
- 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,252 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/describe'
|
|
4
|
+
require 'git/commands/fsck'
|
|
5
|
+
require 'git/commands/show'
|
|
6
|
+
require 'git/parsers/fsck'
|
|
7
|
+
require 'git/repository/shared_private'
|
|
8
|
+
|
|
9
|
+
module Git
|
|
10
|
+
class Repository
|
|
11
|
+
# Facade methods for read-only repository inspection operations
|
|
12
|
+
#
|
|
13
|
+
# These methods report on the contents and integrity of the repository.
|
|
14
|
+
#
|
|
15
|
+
# Included by {Git::Repository}.
|
|
16
|
+
#
|
|
17
|
+
# @api public
|
|
18
|
+
#
|
|
19
|
+
module Inspecting
|
|
20
|
+
# Give a human-readable name to a commit based on the most recent reachable tag
|
|
21
|
+
#
|
|
22
|
+
# Runs `git describe` to find the nearest tag reachable from `committish` and
|
|
23
|
+
# formats a version string. When the tag points directly at the commit, only the
|
|
24
|
+
# tag name is shown. Otherwise, the tag name is suffixed with the number of
|
|
25
|
+
# additional commits and the abbreviated commit SHA (e.g. `v1.0.0-3-gabcdef1`).
|
|
26
|
+
#
|
|
27
|
+
# @example Describe HEAD
|
|
28
|
+
# repo.describe #=> "v1.0.0"
|
|
29
|
+
#
|
|
30
|
+
# @example Describe a specific commit
|
|
31
|
+
# repo.describe('abc123') #=> "v1.0.0-3-gabcdef1"
|
|
32
|
+
#
|
|
33
|
+
# @example Describe using any tag (not just annotated tags)
|
|
34
|
+
# repo.describe(nil, tags: true) #=> "v1.0.0-lightweight"
|
|
35
|
+
#
|
|
36
|
+
# @example Require an exact tag match
|
|
37
|
+
# repo.describe(nil, exact_match: true)
|
|
38
|
+
#
|
|
39
|
+
# @example Use the legacy hyphenated key (still accepted)
|
|
40
|
+
# repo.describe(nil, :'exact-match' => true)
|
|
41
|
+
#
|
|
42
|
+
# @param committish [String, nil] the commit-ish to describe; defaults to HEAD
|
|
43
|
+
# when `nil`
|
|
44
|
+
#
|
|
45
|
+
# @param opts [Hash] options forwarded to `git describe`
|
|
46
|
+
#
|
|
47
|
+
# @option opts [Boolean, nil] :all (nil) use any ref in `refs/`, not just tags
|
|
48
|
+
#
|
|
49
|
+
# @option opts [Boolean, nil] :tags (nil) use lightweight tags as well as
|
|
50
|
+
# annotated ones
|
|
51
|
+
#
|
|
52
|
+
# @option opts [Boolean, nil] :contains (nil) describe the tag that contains the
|
|
53
|
+
# commit, rather than the nearest reachable one
|
|
54
|
+
#
|
|
55
|
+
# @option opts [Boolean, String, nil] :abbrev (nil) number of hex digits for the
|
|
56
|
+
# abbreviated object name; `true` uses git's default length
|
|
57
|
+
#
|
|
58
|
+
# @option opts [Boolean, String, nil] :dirty (nil) append a dirty-state mark to
|
|
59
|
+
# the description; `true` appends `-dirty`, a String appends that string
|
|
60
|
+
#
|
|
61
|
+
# @option opts [Boolean, String, nil] :broken (nil) like `:dirty` but treats
|
|
62
|
+
# broken repository links as dirty
|
|
63
|
+
#
|
|
64
|
+
# @option opts [Integer, String, nil] :candidates (nil) number of candidate tags
|
|
65
|
+
# to consider; increasing above 10 may yield a more accurate result
|
|
66
|
+
#
|
|
67
|
+
# @option opts [Boolean, nil] :exact_match (nil) only succeed when the commit is
|
|
68
|
+
# pointed to by a tag directly (no suffix)
|
|
69
|
+
#
|
|
70
|
+
# The legacy hyphenated key `:"exact-match"` is also accepted and is
|
|
71
|
+
# automatically translated to `:exact_match`.
|
|
72
|
+
#
|
|
73
|
+
# @option opts [Boolean, nil] :debug (nil) verbosely display the search strategy
|
|
74
|
+
#
|
|
75
|
+
# @option opts [Boolean, nil] :long (nil) always output the long format even when
|
|
76
|
+
# the commit matches a tag exactly
|
|
77
|
+
#
|
|
78
|
+
# @option opts [String, Array<String>, nil] :match (nil) only consider tags
|
|
79
|
+
# matching the given `glob(7)` pattern; pass an array for multiple patterns
|
|
80
|
+
#
|
|
81
|
+
# @option opts [String, Array<String>, nil] :exclude (nil) do not consider tags
|
|
82
|
+
# matching the given `glob(7)` pattern; pass an array for multiple patterns
|
|
83
|
+
#
|
|
84
|
+
# @option opts [Boolean, nil] :always (nil) show the abbreviated commit SHA as
|
|
85
|
+
# fallback when the commit cannot be described
|
|
86
|
+
#
|
|
87
|
+
# @option opts [Boolean, nil] :first_parent (nil) follow only the first parent of
|
|
88
|
+
# merge commits when searching for the nearest tag
|
|
89
|
+
#
|
|
90
|
+
# @return [String] the human-readable description of the commit, with trailing
|
|
91
|
+
# newlines preserved
|
|
92
|
+
#
|
|
93
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
94
|
+
#
|
|
95
|
+
# @raise [ArgumentError] when `committish` looks like a command-line flag (starts
|
|
96
|
+
# with `-`), or when `opts` contains any key not in the documented option list
|
|
97
|
+
#
|
|
98
|
+
def describe(committish = nil, opts = {})
|
|
99
|
+
raise ArgumentError, "Invalid commit-ish object: '#{committish}'" if committish&.start_with?('-')
|
|
100
|
+
|
|
101
|
+
opts = opts.dup
|
|
102
|
+
if opts.key?(:'exact-match')
|
|
103
|
+
opts[:exact_match] ||= opts[:'exact-match']
|
|
104
|
+
opts.delete(:'exact-match')
|
|
105
|
+
end
|
|
106
|
+
SharedPrivate.assert_valid_opts!(DESCRIBE_ALLOWED_OPTS, **opts)
|
|
107
|
+
commit_ishes = Array(committish).compact
|
|
108
|
+
Git::Commands::Describe.new(@execution_context).call(*commit_ishes, **opts).stdout
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Show a single git object (a commit, tag, tree, or blob)
|
|
112
|
+
#
|
|
113
|
+
# @example Show the HEAD commit
|
|
114
|
+
# repo.show
|
|
115
|
+
#
|
|
116
|
+
# @example Show a specific commit
|
|
117
|
+
# repo.show('HEAD~1')
|
|
118
|
+
#
|
|
119
|
+
# @example Show the contents of a file at a revision
|
|
120
|
+
# repo.show('HEAD', 'README.md')
|
|
121
|
+
#
|
|
122
|
+
# @param objectish [String, nil] the object to show; a ref, SHA, or
|
|
123
|
+
# `objectish:path` expression
|
|
124
|
+
#
|
|
125
|
+
# Defaults to `HEAD` when `nil`.
|
|
126
|
+
#
|
|
127
|
+
# @param path [String, nil] the file whose contents to show at `objectish`,
|
|
128
|
+
# when given
|
|
129
|
+
#
|
|
130
|
+
# Combined with `objectish` as `objectish:path`. When `objectish` is `nil`
|
|
131
|
+
# and `path` is given, `HEAD` is used as the objectish, so
|
|
132
|
+
# `show(nil, 'README.md')` resolves to `HEAD:README.md`.
|
|
133
|
+
#
|
|
134
|
+
# @return [String] git's stdout from the show, with trailing newlines
|
|
135
|
+
# preserved
|
|
136
|
+
#
|
|
137
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
138
|
+
#
|
|
139
|
+
def show(objectish = nil, path = nil)
|
|
140
|
+
object = path ? "#{objectish || 'HEAD'}:#{path}" : objectish
|
|
141
|
+
Git::Commands::Show.new(@execution_context).call(*[object].compact).stdout
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Option keys accepted by {#describe}
|
|
145
|
+
DESCRIBE_ALLOWED_OPTS = %i[
|
|
146
|
+
all tags contains abbrev dirty broken candidates
|
|
147
|
+
exact_match debug long match exclude always first_parent
|
|
148
|
+
].freeze
|
|
149
|
+
private_constant :DESCRIBE_ALLOWED_OPTS
|
|
150
|
+
|
|
151
|
+
# Option keys accepted by {#fsck}
|
|
152
|
+
#
|
|
153
|
+
# `:progress`/`:no_progress` are intentionally excluded: progress output is
|
|
154
|
+
# always suppressed (see {#fsck}), so callers may not toggle it.
|
|
155
|
+
FSCK_ALLOWED_OPTS = %i[
|
|
156
|
+
tags root unreachable cache no_reflogs
|
|
157
|
+
full no_full strict verbose lost_found dangling no_dangling
|
|
158
|
+
connectivity_only name_objects no_name_objects references no_references
|
|
159
|
+
].freeze
|
|
160
|
+
private_constant :FSCK_ALLOWED_OPTS
|
|
161
|
+
|
|
162
|
+
# Verify the connectivity and validity of the objects in the database
|
|
163
|
+
#
|
|
164
|
+
# Runs `git fsck` and returns the categorized objects it flags. Progress
|
|
165
|
+
# output is always suppressed (`--no-progress`) so that stdout contains only
|
|
166
|
+
# the machine-parsable findings.
|
|
167
|
+
#
|
|
168
|
+
# @overload fsck(*objects, **options)
|
|
169
|
+
#
|
|
170
|
+
# @example Check repository integrity
|
|
171
|
+
# result = repo.fsck
|
|
172
|
+
# result.dangling.each { |obj| puts "#{obj.type}: #{obj.oid}" }
|
|
173
|
+
#
|
|
174
|
+
# @example Check if the repository is clean
|
|
175
|
+
# repo.fsck.empty? #=> true
|
|
176
|
+
#
|
|
177
|
+
# @example List root commits
|
|
178
|
+
# repo.fsck(root: true).root.each { |obj| puts obj.oid }
|
|
179
|
+
#
|
|
180
|
+
# @example Check specific objects
|
|
181
|
+
# repo.fsck('abc1234', 'def5678')
|
|
182
|
+
#
|
|
183
|
+
# @param objects [Array<String>] specific objects to treat as heads for the
|
|
184
|
+
# unreachability trace
|
|
185
|
+
#
|
|
186
|
+
# When none are given, git fsck defaults to the index file, all refs, and
|
|
187
|
+
# all reflogs.
|
|
188
|
+
#
|
|
189
|
+
# @param options [Hash] options for the fsck command
|
|
190
|
+
#
|
|
191
|
+
# @option options [Boolean, nil] :tags (nil) report tags
|
|
192
|
+
#
|
|
193
|
+
# @option options [Boolean, nil] :root (nil) report root nodes
|
|
194
|
+
#
|
|
195
|
+
# @option options [Boolean, nil] :unreachable (nil) print objects that exist
|
|
196
|
+
# but are not reachable from any reference node
|
|
197
|
+
#
|
|
198
|
+
# @option options [Boolean, nil] :cache (nil) consider objects recorded in the
|
|
199
|
+
# index as head nodes for reachability
|
|
200
|
+
#
|
|
201
|
+
# @option options [Boolean, nil] :no_reflogs (nil) do not consider commits
|
|
202
|
+
# referenced only by reflogs to be reachable
|
|
203
|
+
#
|
|
204
|
+
# @option options [Boolean, nil] :full (nil) also check alternate object
|
|
205
|
+
# pools and packed archives, not just the local store
|
|
206
|
+
#
|
|
207
|
+
# @option options [Boolean, nil] :no_full (nil) skip alternate object pools and
|
|
208
|
+
# packed archives
|
|
209
|
+
#
|
|
210
|
+
# @option options [Boolean, nil] :strict (nil) enable stricter checking
|
|
211
|
+
#
|
|
212
|
+
# @option options [Boolean, nil] :verbose (nil) be chatty
|
|
213
|
+
#
|
|
214
|
+
# @option options [Boolean, nil] :lost_found (nil) write dangling objects
|
|
215
|
+
# into `.git/lost-found`
|
|
216
|
+
#
|
|
217
|
+
# This modifies the repository by creating files.
|
|
218
|
+
#
|
|
219
|
+
# @option options [Boolean, nil] :dangling (nil) print dangling objects
|
|
220
|
+
#
|
|
221
|
+
# @option options [Boolean, nil] :no_dangling (nil) suppress dangling object
|
|
222
|
+
# reporting
|
|
223
|
+
#
|
|
224
|
+
# @option options [Boolean, nil] :connectivity_only (nil) check only
|
|
225
|
+
# connectivity; faster but does not validate blob content
|
|
226
|
+
#
|
|
227
|
+
# @option options [Boolean, nil] :name_objects (nil) show the name of each
|
|
228
|
+
# reachable object alongside its identifier
|
|
229
|
+
#
|
|
230
|
+
# @option options [Boolean, nil] :no_name_objects (nil) suppress object name
|
|
231
|
+
# display
|
|
232
|
+
#
|
|
233
|
+
# @option options [Boolean, nil] :references (nil) check reference database
|
|
234
|
+
# consistency
|
|
235
|
+
#
|
|
236
|
+
# @option options [Boolean, nil] :no_references (nil) skip reference checking
|
|
237
|
+
#
|
|
238
|
+
# @return [Git::FsckResult] the objects flagged by fsck, categorized by status
|
|
239
|
+
#
|
|
240
|
+
# @raise [ArgumentError] when unsupported options are provided
|
|
241
|
+
#
|
|
242
|
+
# @raise [Git::FailedError] when git exits outside the allowed range (exit
|
|
243
|
+
# code > 7)
|
|
244
|
+
#
|
|
245
|
+
def fsck(*objects, **)
|
|
246
|
+
SharedPrivate.assert_valid_opts!(FSCK_ALLOWED_OPTS, **)
|
|
247
|
+
result = Git::Commands::Fsck.new(@execution_context).call(*objects, **, no_progress: true)
|
|
248
|
+
Git::Parsers::Fsck.parse(result.stdout)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/log'
|
|
4
|
+
require 'git/log'
|
|
5
|
+
require 'git/repository/shared_private'
|
|
6
|
+
|
|
7
|
+
module Git
|
|
8
|
+
class Repository
|
|
9
|
+
# Facade methods for querying commit history
|
|
10
|
+
#
|
|
11
|
+
# Included by {Git::Repository}.
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
#
|
|
15
|
+
module Logging
|
|
16
|
+
FULL_LOG_COMMITS_ALLOWED_OPTS = %i[
|
|
17
|
+
count all cherry since until grep author between object path_limiter skip merges
|
|
18
|
+
].freeze
|
|
19
|
+
private_constant :FULL_LOG_COMMITS_ALLOWED_OPTS
|
|
20
|
+
|
|
21
|
+
# Returns commits within the given revision range
|
|
22
|
+
#
|
|
23
|
+
# @overload full_log_commits(opts = {})
|
|
24
|
+
#
|
|
25
|
+
# @example Return commits from all refs
|
|
26
|
+
# repo.full_log_commits(all: true).first['sha']
|
|
27
|
+
# #=> "a1b2c3d4..."
|
|
28
|
+
#
|
|
29
|
+
# @example Return commits between two revisions
|
|
30
|
+
# repo.full_log_commits(between: ['v1.0.0', 'HEAD']).map { |c| c['sha'] }
|
|
31
|
+
# #=> ["d4e5f6...", "a1b2c3..."]
|
|
32
|
+
#
|
|
33
|
+
# @param opts [Hash] options for the log query
|
|
34
|
+
#
|
|
35
|
+
# @option opts [Integer, nil] :count (nil) maximum number of commits to return
|
|
36
|
+
#
|
|
37
|
+
# @option opts [Boolean, nil] :all (nil) include commits reachable from any ref
|
|
38
|
+
#
|
|
39
|
+
# @option opts [Boolean, nil] :cherry (nil) omit commits equivalent to cherry-picked commits
|
|
40
|
+
#
|
|
41
|
+
# @option opts [String] :since (nil) include commits newer than this date expression
|
|
42
|
+
#
|
|
43
|
+
# @option opts [String] :until (nil) include commits older than this date expression
|
|
44
|
+
#
|
|
45
|
+
# @option opts [String] :grep (nil) only include commits whose message matches this pattern
|
|
46
|
+
#
|
|
47
|
+
# @option opts [String] :author (nil) only include commits whose author matches this pattern
|
|
48
|
+
#
|
|
49
|
+
# @option opts [Array<String>] :between (nil) revision range as two commit-ish values
|
|
50
|
+
#
|
|
51
|
+
# When both `:between` and `:object` are provided, `:between` takes precedence.
|
|
52
|
+
#
|
|
53
|
+
# @option opts [String] :object (nil) single revision range expression for git log
|
|
54
|
+
#
|
|
55
|
+
# Ignored when `:between` is provided.
|
|
56
|
+
#
|
|
57
|
+
# @option opts [String, Pathname, Array<String, Pathname>] :path_limiter (nil)
|
|
58
|
+
# only include commits that impact files from the specified path(s)
|
|
59
|
+
#
|
|
60
|
+
# @option opts [Integer] :skip (nil) skip this many commits before output
|
|
61
|
+
#
|
|
62
|
+
# @option opts [Boolean, nil] :merges (nil) include only merge commits
|
|
63
|
+
#
|
|
64
|
+
# @return [Array<Hash>] the parsed raw log output for each commit
|
|
65
|
+
#
|
|
66
|
+
# @raise [ArgumentError] if unsupported options are provided
|
|
67
|
+
#
|
|
68
|
+
# @raise [ArgumentError] if `:count` is not an Integer
|
|
69
|
+
#
|
|
70
|
+
# @raise [Git::FailedError] if git exits with a non-zero exit status
|
|
71
|
+
#
|
|
72
|
+
# @see https://git-scm.com/docs/git-log git-log
|
|
73
|
+
#
|
|
74
|
+
def full_log_commits(opts = {})
|
|
75
|
+
SharedPrivate.assert_valid_opts!(FULL_LOG_COMMITS_ALLOWED_OPTS, **opts)
|
|
76
|
+
Private.validate_log_count_option!(opts)
|
|
77
|
+
Private.validate_log_between_option!(opts)
|
|
78
|
+
|
|
79
|
+
call_opts = Private.log_base_call_options(opts, skip: opts[:skip], merges: opts[:merges])
|
|
80
|
+
revision_range_args = Private.log_revision_range_args(opts)
|
|
81
|
+
Private.run_log_command(@execution_context, revision_range_args, call_opts)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns a new {Git::Log} query builder scoped to this repository
|
|
85
|
+
#
|
|
86
|
+
# @example Build a log query and execute it
|
|
87
|
+
# results = repo.log(50).author('Alice').since('2 weeks ago').execute
|
|
88
|
+
# results.each { |commit| puts commit.sha }
|
|
89
|
+
#
|
|
90
|
+
# @param count [Integer, Symbol, nil] the maximum number of commits to return,
|
|
91
|
+
# or `:all` / `nil` to return all commits; passed directly to {Git::Log#initialize}
|
|
92
|
+
#
|
|
93
|
+
# @return [Git::Log] a new log query builder
|
|
94
|
+
#
|
|
95
|
+
# @see Git::Log
|
|
96
|
+
#
|
|
97
|
+
def log(count = 30)
|
|
98
|
+
Git::Log.new(self, count)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Internal helpers for {Logging} that should not be mixed into
|
|
102
|
+
# {Git::Repository} instances
|
|
103
|
+
#
|
|
104
|
+
# @api private
|
|
105
|
+
#
|
|
106
|
+
module Private
|
|
107
|
+
module_function
|
|
108
|
+
|
|
109
|
+
def validate_log_count_option!(opts)
|
|
110
|
+
return if opts[:count].nil? || opts[:count].is_a?(Integer)
|
|
111
|
+
|
|
112
|
+
raise ArgumentError, "The log count option must be an Integer but was #{opts[:count].inspect}"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def validate_log_between_option!(opts)
|
|
116
|
+
between = opts[:between]
|
|
117
|
+
return if between.nil?
|
|
118
|
+
return if between.is_a?(Array) && between.length == 2 && between.none?(&:nil?)
|
|
119
|
+
|
|
120
|
+
raise ArgumentError,
|
|
121
|
+
"The log between option must be an Array with exactly two non-nil values but was #{between.inspect}"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def log_revision_range_args(opts)
|
|
125
|
+
if opts[:between]
|
|
126
|
+
["#{opts[:between][0]}..#{opts[:between][1]}"]
|
|
127
|
+
elsif opts[:object].is_a?(String)
|
|
128
|
+
[opts[:object]]
|
|
129
|
+
else
|
|
130
|
+
[]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def log_base_call_options(opts, extra = {})
|
|
135
|
+
{
|
|
136
|
+
all: opts[:all],
|
|
137
|
+
cherry: opts[:cherry],
|
|
138
|
+
since: opts[:since],
|
|
139
|
+
until: opts[:until],
|
|
140
|
+
grep: opts[:grep],
|
|
141
|
+
author: opts[:author],
|
|
142
|
+
max_count: opts[:count],
|
|
143
|
+
path: opts[:path_limiter] ? Array(opts[:path_limiter]) : nil
|
|
144
|
+
}.merge(extra).compact
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def run_log_command(execution_context, revision_range_args, call_opts)
|
|
148
|
+
log_or_empty_on_unborn do
|
|
149
|
+
result = Git::Commands::Log.new(execution_context).call(
|
|
150
|
+
*revision_range_args,
|
|
151
|
+
no_color: true,
|
|
152
|
+
pretty: 'raw',
|
|
153
|
+
**call_opts
|
|
154
|
+
)
|
|
155
|
+
RawLogParser.new(result.stdout.split("\n")).parse
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def log_or_empty_on_unborn
|
|
160
|
+
yield
|
|
161
|
+
rescue Git::FailedError => e
|
|
162
|
+
raise unless e.result.status.exitstatus == 128 &&
|
|
163
|
+
e.result.stderr =~ /does not have any commits yet/
|
|
164
|
+
|
|
165
|
+
[]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Parser for `git log --pretty=raw` output into commit hashes
|
|
169
|
+
#
|
|
170
|
+
# @api private
|
|
171
|
+
#
|
|
172
|
+
class RawLogParser
|
|
173
|
+
def initialize(lines)
|
|
174
|
+
@lines = lines
|
|
175
|
+
@commits = []
|
|
176
|
+
@current_commit = nil
|
|
177
|
+
@in_message = false
|
|
178
|
+
@last_metadata_key = nil
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Parse raw `git log --pretty=raw` lines into commit hashes
|
|
182
|
+
#
|
|
183
|
+
# @return [Array<Hash>] the parsed commits in command output order
|
|
184
|
+
#
|
|
185
|
+
def parse
|
|
186
|
+
@lines.each { |line| process_line(line.chomp) }
|
|
187
|
+
finalize_commit
|
|
188
|
+
@commits
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
private
|
|
192
|
+
|
|
193
|
+
def process_line(line)
|
|
194
|
+
if line.empty?
|
|
195
|
+
@in_message = !@in_message
|
|
196
|
+
return
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
@in_message = false if @in_message && !line.start_with?(' ')
|
|
200
|
+
|
|
201
|
+
@in_message ? process_message_line(line) : process_metadata_line(line)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def process_message_line(line)
|
|
205
|
+
@current_commit['message'] << "#{line[4..]}\n"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def process_metadata_line(line)
|
|
209
|
+
if line.start_with?(' ') && @last_metadata_key
|
|
210
|
+
@current_commit[@last_metadata_key] << "\n#{line[1..]}"
|
|
211
|
+
return
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
key, *value = line.split
|
|
215
|
+
value = value.join(' ')
|
|
216
|
+
@last_metadata_key = nil
|
|
217
|
+
dispatch_metadata_key(key, value)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def dispatch_metadata_key(key, value)
|
|
221
|
+
case key
|
|
222
|
+
when 'commit'
|
|
223
|
+
start_new_commit(value)
|
|
224
|
+
when 'parent'
|
|
225
|
+
@current_commit['parent'] << value
|
|
226
|
+
else
|
|
227
|
+
@current_commit[key] = value
|
|
228
|
+
@last_metadata_key = key
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def start_new_commit(sha)
|
|
233
|
+
finalize_commit
|
|
234
|
+
@current_commit = { 'sha' => sha, 'message' => +'', 'parent' => [] }
|
|
235
|
+
@last_metadata_key = nil
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def finalize_commit
|
|
239
|
+
@commits << @current_commit if @current_commit
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
private_constant :RawLogParser
|
|
243
|
+
end
|
|
244
|
+
private_constant :Private
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'git/commands/gc'
|
|
4
|
+
require 'git/commands/repack'
|
|
5
|
+
|
|
6
|
+
module Git
|
|
7
|
+
class Repository
|
|
8
|
+
# Facade methods for repository maintenance and optimization operations
|
|
9
|
+
#
|
|
10
|
+
# These methods pack objects, compress history, prune unreachable objects, and
|
|
11
|
+
# otherwise keep the repository in good health.
|
|
12
|
+
#
|
|
13
|
+
# Included by {Git::Repository}.
|
|
14
|
+
#
|
|
15
|
+
# @api public
|
|
16
|
+
#
|
|
17
|
+
module Maintenance
|
|
18
|
+
# Repack loose objects into pack files
|
|
19
|
+
#
|
|
20
|
+
# Packs all unpacked objects and removes redundant pack files. This is
|
|
21
|
+
# equivalent to running `git repack -a -d`, which packs all objects into a
|
|
22
|
+
# single pack and deletes any packs that become redundant.
|
|
23
|
+
#
|
|
24
|
+
# This method uses the fixed options `a: true, d: true` (matching the 4.x
|
|
25
|
+
# behavior). No additional options are exposed.
|
|
26
|
+
#
|
|
27
|
+
# @example Repack the repository
|
|
28
|
+
# repo.repack
|
|
29
|
+
#
|
|
30
|
+
# @return [String] the stdout from `git repack`. Git writes all progress
|
|
31
|
+
# and summary output to stderr, so the returned string is typically empty.
|
|
32
|
+
# Returns `String` to match the 4.x public contract (`Git::Lib#command`
|
|
33
|
+
# returned `result.stdout`).
|
|
34
|
+
#
|
|
35
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
36
|
+
#
|
|
37
|
+
def repack
|
|
38
|
+
Git::Commands::Repack.new(@execution_context).call(a: true, d: true).stdout
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Run garbage collection to optimize and clean up the repository
|
|
42
|
+
#
|
|
43
|
+
# Runs `git gc` to perform housekeeping tasks including object compression,
|
|
44
|
+
# pruning of unreachable objects, and ref packing. This is equivalent to
|
|
45
|
+
# running `git gc --prune --aggressive --auto`.
|
|
46
|
+
#
|
|
47
|
+
# This method uses the fixed options `prune: true, aggressive: true, auto: true`
|
|
48
|
+
# (matching the 4.x behavior). No additional options are exposed.
|
|
49
|
+
#
|
|
50
|
+
# @example Run garbage collection
|
|
51
|
+
# repo.gc
|
|
52
|
+
#
|
|
53
|
+
# @return [String] the stdout from `git gc`. Git writes all progress
|
|
54
|
+
# and summary output to stderr, so the returned string is typically empty.
|
|
55
|
+
# Returns `String` to match the 4.x public contract (`Git::Lib#command`
|
|
56
|
+
# returned `result.stdout`).
|
|
57
|
+
#
|
|
58
|
+
# @raise [Git::FailedError] when git exits with a non-zero exit status
|
|
59
|
+
#
|
|
60
|
+
def gc
|
|
61
|
+
Git::Commands::Gc.new(@execution_context).call(prune: true, aggressive: true, auto: true).stdout
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|