git 1.19.1 → 5.5.0
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/.yardopts +5 -1
- data/AI_POLICY.md +24 -0
- data/CHANGELOG.md +689 -0
- data/CODE_OF_CONDUCT.md +25 -0
- data/CONTRIBUTING.md +1175 -97
- data/GOVERNANCE.md +106 -0
- data/LICENSE +1 -1
- data/MAINTAINERS.md +17 -4
- data/README.md +476 -320
- data/UPGRADING.md +1138 -0
- data/git.gemspec +124 -36
- data/lib/git/author.rb +39 -7
- data/lib/git/author_info.rb +66 -0
- data/lib/git/branch.rb +615 -65
- data/lib/git/branch_delete_failure.rb +34 -0
- data/lib/git/branch_delete_result.rb +66 -0
- data/lib/git/branch_info.rb +237 -0
- data/lib/git/branches.rb +167 -44
- data/lib/git/command_line/base.rb +247 -0
- data/lib/git/command_line/capturing.rb +308 -0
- data/lib/git/command_line/result.rb +88 -0
- data/lib/git/command_line/streaming.rb +236 -0
- data/lib/git/command_line.rb +52 -0
- data/lib/git/commands/add.rb +139 -0
- data/lib/git/commands/am/abort.rb +43 -0
- data/lib/git/commands/am/apply.rb +263 -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 +49 -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 +242 -0
- data/lib/git/commands/archive/list_formats.rb +46 -0
- data/lib/git/commands/archive.rb +145 -0
- data/lib/git/commands/arguments.rb +4521 -0
- data/lib/git/commands/base.rb +502 -0
- data/lib/git/commands/branch/copy.rb +102 -0
- data/lib/git/commands/branch/create.rb +177 -0
- data/lib/git/commands/branch/delete.rb +88 -0
- data/lib/git/commands/branch/list.rb +178 -0
- data/lib/git/commands/branch/move.rb +102 -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 +53 -0
- data/lib/git/commands/branch.rb +34 -0
- data/lib/git/commands/cat_file/batch.rb +385 -0
- data/lib/git/commands/cat_file/filtered.rb +105 -0
- data/lib/git/commands/cat_file/raw.rb +271 -0
- data/lib/git/commands/cat_file.rb +49 -0
- data/lib/git/commands/checkout/branch.rb +153 -0
- data/lib/git/commands/checkout/files.rb +116 -0
- data/lib/git/commands/checkout.rb +38 -0
- data/lib/git/commands/checkout_index.rb +106 -0
- data/lib/git/commands/clean.rb +102 -0
- data/lib/git/commands/clone.rb +241 -0
- data/lib/git/commands/commit.rb +273 -0
- data/lib/git/commands/commit_tree.rb +101 -0
- data/lib/git/commands/config_option_syntax/add.rb +86 -0
- data/lib/git/commands/config_option_syntax/get.rb +121 -0
- data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
- data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
- data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
- data/lib/git/commands/config_option_syntax/list.rb +111 -0
- data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
- data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
- data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
- data/lib/git/commands/config_option_syntax/set.rb +119 -0
- data/lib/git/commands/config_option_syntax/unset.rb +92 -0
- data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
- data/lib/git/commands/config_option_syntax.rb +56 -0
- data/lib/git/commands/describe.rb +156 -0
- data/lib/git/commands/diff.rb +657 -0
- data/lib/git/commands/diff_files.rb +519 -0
- data/lib/git/commands/diff_index.rb +499 -0
- data/lib/git/commands/fetch.rb +354 -0
- data/lib/git/commands/fsck.rb +138 -0
- data/lib/git/commands/gc.rb +134 -0
- data/lib/git/commands/grep.rb +339 -0
- data/lib/git/commands/init.rb +101 -0
- data/lib/git/commands/log.rb +634 -0
- data/lib/git/commands/ls_files.rb +195 -0
- data/lib/git/commands/ls_remote.rb +161 -0
- data/lib/git/commands/ls_tree.rb +135 -0
- data/lib/git/commands/maintenance/register.rb +77 -0
- data/lib/git/commands/maintenance/run.rb +109 -0
- data/lib/git/commands/maintenance/start.rb +71 -0
- data/lib/git/commands/maintenance/stop.rb +60 -0
- data/lib/git/commands/maintenance/unregister.rb +84 -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 +250 -0
- data/lib/git/commands/merge.rb +28 -0
- data/lib/git/commands/merge_base.rb +91 -0
- data/lib/git/commands/mv.rb +82 -0
- data/lib/git/commands/name_rev.rb +119 -0
- data/lib/git/commands/pull.rb +382 -0
- data/lib/git/commands/push.rb +251 -0
- data/lib/git/commands/read_tree.rb +154 -0
- data/lib/git/commands/remote/add.rb +96 -0
- data/lib/git/commands/remote/get_url.rb +68 -0
- data/lib/git/commands/remote/list.rb +56 -0
- data/lib/git/commands/remote/prune.rb +63 -0
- data/lib/git/commands/remote/remove.rb +52 -0
- data/lib/git/commands/remote/rename.rb +76 -0
- data/lib/git/commands/remote/set_branches.rb +70 -0
- data/lib/git/commands/remote/set_head.rb +89 -0
- data/lib/git/commands/remote/set_url.rb +78 -0
- data/lib/git/commands/remote/set_url_add.rb +70 -0
- data/lib/git/commands/remote/set_url_delete.rb +71 -0
- data/lib/git/commands/remote/show.rb +77 -0
- data/lib/git/commands/remote/update.rb +79 -0
- data/lib/git/commands/remote.rb +42 -0
- data/lib/git/commands/repack.rb +281 -0
- data/lib/git/commands/reset.rb +154 -0
- data/lib/git/commands/rev_parse.rb +304 -0
- data/lib/git/commands/revert/abort.rb +45 -0
- data/lib/git/commands/revert/continue.rb +62 -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 +158 -0
- data/lib/git/commands/revert.rb +29 -0
- data/lib/git/commands/rm.rb +113 -0
- data/lib/git/commands/show.rb +632 -0
- data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
- data/lib/git/commands/show_ref/exists.rb +80 -0
- data/lib/git/commands/show_ref/list.rb +149 -0
- data/lib/git/commands/show_ref/verify.rb +122 -0
- data/lib/git/commands/show_ref.rb +42 -0
- data/lib/git/commands/stash/apply.rb +81 -0
- data/lib/git/commands/stash/branch.rb +67 -0
- data/lib/git/commands/stash/clear.rb +43 -0
- data/lib/git/commands/stash/create.rb +60 -0
- data/lib/git/commands/stash/drop.rb +73 -0
- data/lib/git/commands/stash/list.rb +43 -0
- data/lib/git/commands/stash/pop.rb +87 -0
- data/lib/git/commands/stash/push.rb +112 -0
- data/lib/git/commands/stash/show.rb +158 -0
- data/lib/git/commands/stash/store.rb +72 -0
- data/lib/git/commands/stash.rb +38 -0
- data/lib/git/commands/status.rb +174 -0
- data/lib/git/commands/symbolic_ref/delete.rb +72 -0
- data/lib/git/commands/symbolic_ref/read.rb +99 -0
- data/lib/git/commands/symbolic_ref/update.rb +79 -0
- data/lib/git/commands/symbolic_ref.rb +38 -0
- data/lib/git/commands/tag/create.rb +142 -0
- data/lib/git/commands/tag/delete.rb +57 -0
- data/lib/git/commands/tag/list.rb +146 -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 +145 -0
- data/lib/git/commands/update_ref/delete.rb +90 -0
- data/lib/git/commands/update_ref/update.rb +103 -0
- data/lib/git/commands/update_ref.rb +42 -0
- data/lib/git/commands/version.rb +60 -0
- data/lib/git/commands/worktree/add.rb +139 -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 +88 -0
- data/lib/git/config.rb +72 -5
- data/lib/git/config_entry_info.rb +106 -0
- data/lib/git/configuring.rb +795 -0
- data/lib/git/detached_head_info.rb +57 -0
- data/lib/git/diff.rb +437 -86
- data/lib/git/diff_file_numstat_info.rb +31 -0
- data/lib/git/diff_file_patch_info.rb +136 -0
- data/lib/git/diff_file_raw_info.rb +129 -0
- data/lib/git/diff_info.rb +162 -0
- data/lib/git/diff_path_status.rb +107 -0
- data/lib/git/diff_result.rb +34 -0
- data/lib/git/diff_stats.rb +111 -0
- data/lib/git/dirstat_info.rb +102 -0
- data/lib/git/encoding_utils.rb +32 -1
- data/lib/git/errors.rb +285 -0
- data/lib/git/escaped_path.rb +57 -5
- data/lib/git/execution_context/global.rb +31 -0
- data/lib/git/execution_context/repository.rb +151 -0
- data/lib/git/execution_context.rb +559 -0
- data/lib/git/factories.rb +813 -0
- data/lib/git/file_ref.rb +77 -0
- data/lib/git/fsck_object.rb +56 -0
- data/lib/git/fsck_result.rb +132 -0
- data/lib/git/log.rb +306 -90
- data/lib/git/object.rb +563 -141
- data/lib/git/parsers/branch.rb +240 -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 +792 -0
- data/lib/git/parsers/fsck.rb +144 -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/remote.rb +162 -0
- data/lib/git/parsers/stash.rb +292 -0
- data/lib/git/parsers/status.rb +251 -0
- data/lib/git/parsers/tag.rb +341 -0
- data/lib/git/parsers/worktree.rb +185 -0
- data/lib/git/path_resolver.rb +206 -0
- data/lib/git/remote.rb +165 -12
- data/lib/git/remote_info.rb +203 -0
- data/lib/git/repository/branching.rb +964 -0
- data/lib/git/repository/committing.rb +246 -0
- data/lib/git/repository/context_helpers.rb +293 -0
- data/lib/git/repository/diffing.rb +785 -0
- data/lib/git/repository/inspecting.rb +252 -0
- data/lib/git/repository/logging.rb +410 -0
- data/lib/git/repository/maintenance.rb +65 -0
- data/lib/git/repository/merging.rb +451 -0
- data/lib/git/repository/object_operations.rb +1551 -0
- data/lib/git/repository/remote_operations.rb +984 -0
- data/lib/git/repository/shared_private.rb +120 -0
- data/lib/git/repository/staging.rb +587 -0
- data/lib/git/repository/stashing.rb +623 -0
- data/lib/git/repository/status_operations.rb +249 -0
- data/lib/git/repository/worktree_operations.rb +339 -0
- data/lib/git/repository.rb +484 -2
- data/lib/git/stash.rb +109 -12
- data/lib/git/stash_info.rb +102 -0
- data/lib/git/stashes.rb +169 -26
- data/lib/git/status.rb +308 -122
- data/lib/git/status_file_info.rb +258 -0
- data/lib/git/status_info.rb +189 -0
- data/lib/git/tag_delete_failure.rb +34 -0
- data/lib/git/tag_delete_result.rb +66 -0
- data/lib/git/tag_info.rb +99 -0
- data/lib/git/url.rb +15 -8
- data/lib/git/version.rb +113 -2
- data/lib/git/version_constraint.rb +85 -0
- data/lib/git/worktree.rb +150 -8
- data/lib/git/worktree_info.rb +128 -0
- data/lib/git/worktrees.rb +118 -13
- data/lib/git.rb +632 -234
- metadata +369 -54
- data/.github/stale.yml +0 -25
- data/.github/workflows/continuous_integration.yml +0 -49
- data/.gitignore +0 -10
- data/Dockerfile.changelog-rs +0 -12
- data/Gemfile +0 -5
- data/ISSUE_TEMPLATE.md +0 -15
- data/PULL_REQUEST_TEMPLATE.md +0 -9
- data/RELEASING.md +0 -70
- data/Rakefile +0 -60
- data/lib/git/base/factory.rb +0 -99
- data/lib/git/base.rb +0 -711
- data/lib/git/command_line_result.rb +0 -86
- data/lib/git/failed_error.rb +0 -53
- data/lib/git/git_execute_error.rb +0 -7
- data/lib/git/index.rb +0 -5
- data/lib/git/lib.rb +0 -1328
- data/lib/git/path.rb +0 -31
- data/lib/git/signaled_error.rb +0 -50
- data/lib/git/working_directory.rb +0 -4
data/lib/git/file_ref.rb
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Immutable value object representing a reference to a file at a specific point in time
|
|
5
|
+
#
|
|
6
|
+
# FileRef encapsulates the mode, SHA, and path of a file as it exists on one side
|
|
7
|
+
# of a diff. This is used to represent either the source (before) or destination
|
|
8
|
+
# (after) state of a file in a diff operation.
|
|
9
|
+
#
|
|
10
|
+
# When a file doesn't exist on a side of the diff (e.g., src for new files,
|
|
11
|
+
# dst for deleted files), the entire FileRef should be nil rather than having
|
|
12
|
+
# a FileRef with nil attributes.
|
|
13
|
+
#
|
|
14
|
+
#
|
|
15
|
+
# @example A modified file's source reference
|
|
16
|
+
# src = Git::FileRef.new(mode: '100644', sha: 'abc1234', path: 'lib/foo.rb')
|
|
17
|
+
#
|
|
18
|
+
# @example A new file (src would be nil, not a FileRef)
|
|
19
|
+
# # src = nil
|
|
20
|
+
# dst = Git::FileRef.new(mode: '100644', sha: 'def5678', path: 'lib/new_file.rb')
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
#
|
|
24
|
+
# Work in progress; this class is internal for now and may be made public in a future release.
|
|
25
|
+
#
|
|
26
|
+
# @!attribute [r] mode
|
|
27
|
+
# @return [String] the file mode (e.g., '100644' for regular file, '100755' for executable,
|
|
28
|
+
# '120000' for symlink)
|
|
29
|
+
#
|
|
30
|
+
# @!attribute [r] sha
|
|
31
|
+
# @return [String] the blob SHA (object identifier)
|
|
32
|
+
#
|
|
33
|
+
# @!attribute [r] path
|
|
34
|
+
# @return [String] the file path relative to repository root
|
|
35
|
+
#
|
|
36
|
+
FileRef = Data.define(:mode, :sha, :path) do
|
|
37
|
+
# Check if this is a regular file (not executable, symlink, etc.)
|
|
38
|
+
#
|
|
39
|
+
# @return [Boolean] true if mode is 100644
|
|
40
|
+
#
|
|
41
|
+
def regular_file?
|
|
42
|
+
mode == '100644'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Check if this is an executable file
|
|
46
|
+
#
|
|
47
|
+
# @return [Boolean] true if mode is 100755
|
|
48
|
+
#
|
|
49
|
+
def executable?
|
|
50
|
+
mode == '100755'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Check if this is a symbolic link
|
|
54
|
+
#
|
|
55
|
+
# @return [Boolean] true if mode is 120000
|
|
56
|
+
#
|
|
57
|
+
def symlink?
|
|
58
|
+
mode == '120000'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Return the mode as an integer (parsed as octal)
|
|
62
|
+
#
|
|
63
|
+
# Useful for bit operations on file permissions.
|
|
64
|
+
#
|
|
65
|
+
# @example Check file permissions
|
|
66
|
+
# ref.mode_bits & 0o777 # => 0o644 (420 decimal)
|
|
67
|
+
#
|
|
68
|
+
# @example Check if group writable
|
|
69
|
+
# (ref.mode_bits & 0o020) != 0
|
|
70
|
+
#
|
|
71
|
+
# @return [Integer] the mode as an integer
|
|
72
|
+
#
|
|
73
|
+
def mode_bits
|
|
74
|
+
mode.to_i(8)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Represents an object returned by `git fsck`
|
|
5
|
+
#
|
|
6
|
+
# This class provides information about dangling, missing, unreachable, or
|
|
7
|
+
# problematic Git objects found during repository integrity checks.
|
|
8
|
+
#
|
|
9
|
+
# @api public
|
|
10
|
+
#
|
|
11
|
+
class FsckObject
|
|
12
|
+
# The type of the Git object
|
|
13
|
+
#
|
|
14
|
+
# @return [Symbol] one of :commit, :tree, :blob, or :tag
|
|
15
|
+
attr_reader :type
|
|
16
|
+
|
|
17
|
+
# The object identifier (OID) of the object
|
|
18
|
+
#
|
|
19
|
+
# @return [String] the 40-character object identifier
|
|
20
|
+
attr_reader :oid
|
|
21
|
+
|
|
22
|
+
# A warning or error message associated with this object
|
|
23
|
+
#
|
|
24
|
+
# @return [String, nil] the message, or nil if no message
|
|
25
|
+
attr_reader :message
|
|
26
|
+
|
|
27
|
+
# A name describing how the object is reachable (from --name-objects)
|
|
28
|
+
#
|
|
29
|
+
# @return [String, nil] the name, or nil if not provided
|
|
30
|
+
attr_reader :name
|
|
31
|
+
|
|
32
|
+
# Create a new FsckObject
|
|
33
|
+
#
|
|
34
|
+
# @param type [Symbol] the object type (:commit, :tree, :blob, or :tag)
|
|
35
|
+
#
|
|
36
|
+
# @param oid [String] the 40-character object identifier
|
|
37
|
+
#
|
|
38
|
+
# @param message [String, nil] optional warning/error message
|
|
39
|
+
#
|
|
40
|
+
# @param name [String, nil] optional name from --name-objects (e.g., "HEAD~2^2:src/")
|
|
41
|
+
#
|
|
42
|
+
def initialize(type:, oid:, message: nil, name: nil)
|
|
43
|
+
@type = type
|
|
44
|
+
@oid = oid
|
|
45
|
+
@message = message
|
|
46
|
+
@name = name
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns the OID as the string representation
|
|
50
|
+
#
|
|
51
|
+
# @return [String] the object identifier
|
|
52
|
+
def to_s
|
|
53
|
+
oid
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Git
|
|
4
|
+
# Represents the result of running `git fsck`
|
|
5
|
+
#
|
|
6
|
+
# This class provides structured access to the objects found during a
|
|
7
|
+
# repository integrity check, categorized by their status.
|
|
8
|
+
#
|
|
9
|
+
# @api public
|
|
10
|
+
#
|
|
11
|
+
class FsckResult
|
|
12
|
+
# Objects not referenced by any other object
|
|
13
|
+
#
|
|
14
|
+
# @return [Array<Git::FsckObject>]
|
|
15
|
+
attr_reader :dangling
|
|
16
|
+
|
|
17
|
+
# Objects that are referenced but not present in the repository
|
|
18
|
+
#
|
|
19
|
+
# @return [Array<Git::FsckObject>]
|
|
20
|
+
attr_reader :missing
|
|
21
|
+
|
|
22
|
+
# Objects not reachable from any ref
|
|
23
|
+
#
|
|
24
|
+
# @return [Array<Git::FsckObject>]
|
|
25
|
+
attr_reader :unreachable
|
|
26
|
+
|
|
27
|
+
# Objects with warnings (each includes a message)
|
|
28
|
+
#
|
|
29
|
+
# @return [Array<Git::FsckObject>]
|
|
30
|
+
attr_reader :warnings
|
|
31
|
+
|
|
32
|
+
# Root nodes (commits with no parents) when --root is used
|
|
33
|
+
#
|
|
34
|
+
# @return [Array<Git::FsckObject>]
|
|
35
|
+
attr_reader :root
|
|
36
|
+
|
|
37
|
+
# Tagged objects when --tags is used
|
|
38
|
+
#
|
|
39
|
+
# @return [Array<Git::FsckObject>]
|
|
40
|
+
attr_reader :tagged
|
|
41
|
+
|
|
42
|
+
# rubocop:disable Metrics/ParameterLists
|
|
43
|
+
|
|
44
|
+
# Create a new FsckResult
|
|
45
|
+
#
|
|
46
|
+
# @param dangling [Array<Git::FsckObject>] dangling objects
|
|
47
|
+
#
|
|
48
|
+
# @param missing [Array<Git::FsckObject>] missing objects
|
|
49
|
+
#
|
|
50
|
+
# @param unreachable [Array<Git::FsckObject>] unreachable objects
|
|
51
|
+
#
|
|
52
|
+
# @param warnings [Array<Git::FsckObject>] objects with warnings
|
|
53
|
+
#
|
|
54
|
+
# @param root [Array<Git::FsckObject>] root nodes
|
|
55
|
+
#
|
|
56
|
+
# @param tagged [Array<Git::FsckObject>] tagged objects
|
|
57
|
+
#
|
|
58
|
+
def initialize(dangling: [], missing: [], unreachable: [], warnings: [], root: [], tagged: [])
|
|
59
|
+
@dangling = dangling
|
|
60
|
+
@missing = missing
|
|
61
|
+
@unreachable = unreachable
|
|
62
|
+
@warnings = warnings
|
|
63
|
+
@root = root
|
|
64
|
+
@tagged = tagged
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# rubocop:enable Metrics/ParameterLists
|
|
68
|
+
|
|
69
|
+
# Returns true if any issues were found
|
|
70
|
+
#
|
|
71
|
+
# @example Check for repository issues
|
|
72
|
+
# result = git.fsck
|
|
73
|
+
# puts "Repository has issues!" if result.any_issues?
|
|
74
|
+
#
|
|
75
|
+
# @return [Boolean]
|
|
76
|
+
#
|
|
77
|
+
def any_issues?
|
|
78
|
+
[dangling, missing, unreachable, warnings].any?(&:any?)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns true if no issues were found
|
|
82
|
+
#
|
|
83
|
+
# @example Check if the result is empty
|
|
84
|
+
# result = git.fsck
|
|
85
|
+
# puts "Repository is clean" if result.empty?
|
|
86
|
+
#
|
|
87
|
+
# @return [Boolean]
|
|
88
|
+
#
|
|
89
|
+
def empty?
|
|
90
|
+
!any_issues?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Returns all objects from all categories (excluding informational root/tagged)
|
|
94
|
+
#
|
|
95
|
+
# @example Iterate over all objects
|
|
96
|
+
# result = git.fsck
|
|
97
|
+
# result.all_objects.each { |obj| puts obj.oid }
|
|
98
|
+
#
|
|
99
|
+
# @return [Array<Git::FsckObject>]
|
|
100
|
+
#
|
|
101
|
+
def all_objects
|
|
102
|
+
dangling + missing + unreachable + warnings
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns the total number of issues found
|
|
106
|
+
#
|
|
107
|
+
# @example Count all issues
|
|
108
|
+
# result = git.fsck
|
|
109
|
+
# puts "Found #{result.count} issues"
|
|
110
|
+
#
|
|
111
|
+
# @return [Integer]
|
|
112
|
+
#
|
|
113
|
+
def count
|
|
114
|
+
all_objects.size
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns a hash representation of the result
|
|
118
|
+
#
|
|
119
|
+
# @example Convert to a hash
|
|
120
|
+
# result = git.fsck
|
|
121
|
+
# result.to_h # => { dangling: [...], missing: [...], ... }
|
|
122
|
+
#
|
|
123
|
+
# @return [Hash{Symbol => Array<Git::FsckObject>}]
|
|
124
|
+
#
|
|
125
|
+
def to_h
|
|
126
|
+
{
|
|
127
|
+
dangling: dangling, missing: missing, unreachable: unreachable,
|
|
128
|
+
warnings: warnings, root: root, tagged: tagged
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
data/lib/git/log.rb
CHANGED
|
@@ -1,131 +1,347 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
module Git
|
|
4
|
+
# Builds and executes a `git log` query
|
|
5
|
+
#
|
|
6
|
+
# This class provides a fluent interface for building complex `git log` queries.
|
|
7
|
+
#
|
|
8
|
+
# Queries default to returning 30 commits; call {#max_count} with `:all` to
|
|
9
|
+
# return every matching commit. Calling {#all} adds the `--all` flag to include
|
|
10
|
+
# all refs in the search but does not change the number of commits returned.
|
|
11
|
+
#
|
|
12
|
+
# The query is lazily executed when results are requested either via the modern
|
|
13
|
+
# `#execute` method or the deprecated Enumerable methods.
|
|
14
|
+
#
|
|
15
|
+
# @example Using the modern `execute` API
|
|
16
|
+
# log = git.log.max_count(50).between('v1.0', 'v1.1').author('Scott')
|
|
17
|
+
# results = log.execute
|
|
18
|
+
# puts "Found #{results.size} commits."
|
|
19
|
+
# results.each { |commit| puts commit.sha }
|
|
20
|
+
#
|
|
21
|
+
# @api public
|
|
22
|
+
#
|
|
4
23
|
class Log
|
|
5
24
|
include Enumerable
|
|
6
25
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
26
|
+
# An immutable, Enumerable collection of `Git::Object::Commit` objects.
|
|
27
|
+
# Returned by `Git::Log#execute`.
|
|
28
|
+
#
|
|
29
|
+
# @api public
|
|
30
|
+
Result = Data.define(:commits) do
|
|
31
|
+
include Enumerable
|
|
12
32
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@
|
|
16
|
-
|
|
17
|
-
|
|
33
|
+
# Iterates over each commit in query order
|
|
34
|
+
#
|
|
35
|
+
# @overload each
|
|
36
|
+
# @example Get an enumerator
|
|
37
|
+
# results.each.map(&:sha)
|
|
38
|
+
#
|
|
39
|
+
# @return [Enumerator<Git::Object::Commit>] an enumerator over commits
|
|
40
|
+
#
|
|
41
|
+
# @overload each(&block)
|
|
42
|
+
# @example Iterate with a block
|
|
43
|
+
# results.each { |commit| puts commit.sha }
|
|
44
|
+
#
|
|
45
|
+
# @yield [commit] each commit from the result
|
|
46
|
+
#
|
|
47
|
+
# @yieldparam commit [Git::Object::Commit] a commit in query order
|
|
48
|
+
#
|
|
49
|
+
# @yieldreturn [void]
|
|
50
|
+
#
|
|
51
|
+
# @return [Array<Git::Object::Commit>] the commit array
|
|
52
|
+
#
|
|
53
|
+
def each(&block) = commits.each(&block)
|
|
18
54
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@
|
|
22
|
-
|
|
23
|
-
|
|
55
|
+
# Returns the last commit in the result
|
|
56
|
+
#
|
|
57
|
+
# @return [Git::Object::Commit, nil] the last commit, or `nil` when empty
|
|
58
|
+
#
|
|
59
|
+
def last = commits.last
|
|
24
60
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@
|
|
28
|
-
|
|
29
|
-
|
|
61
|
+
# Returns a commit by index or a slice of commits by range
|
|
62
|
+
#
|
|
63
|
+
# @param index [Integer, Range] the commit index or range to retrieve
|
|
64
|
+
#
|
|
65
|
+
# @return [Git::Object::Commit, Array<Git::Object::Commit>, nil] the selected
|
|
66
|
+
# commit or commits
|
|
67
|
+
#
|
|
68
|
+
def [](index) = commits[index]
|
|
30
69
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@
|
|
34
|
-
|
|
35
|
-
|
|
70
|
+
# Returns the commits joined with newlines
|
|
71
|
+
#
|
|
72
|
+
# @return [String] newline-separated commits
|
|
73
|
+
#
|
|
74
|
+
def to_s = commits.join("\n")
|
|
36
75
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@
|
|
40
|
-
|
|
76
|
+
# Returns the number of commits in the result
|
|
77
|
+
#
|
|
78
|
+
# @return [Integer] the commit count
|
|
79
|
+
#
|
|
80
|
+
def size = commits.size
|
|
41
81
|
end
|
|
42
82
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
83
|
+
# Create a new Git::Log object
|
|
84
|
+
#
|
|
85
|
+
# @example
|
|
86
|
+
# git = Git.open('.')
|
|
87
|
+
# Git::Log.new(git)
|
|
88
|
+
#
|
|
89
|
+
# @param base [Git::Repository] the git repository object
|
|
90
|
+
#
|
|
91
|
+
# @param max_count [Integer, Symbol, nil] the number of commits to return, or
|
|
92
|
+
# `:all` or `nil` to return all
|
|
93
|
+
#
|
|
94
|
+
# Passing max_count to {#initialize} is equivalent to calling {#max_count} on the object.
|
|
95
|
+
#
|
|
96
|
+
def initialize(base, max_count = 30)
|
|
97
|
+
@base = base
|
|
98
|
+
@options = {}
|
|
99
|
+
@dirty = true
|
|
100
|
+
self.max_count(max_count)
|
|
47
101
|
end
|
|
48
102
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
103
|
+
# Set query options using a fluent interface.
|
|
104
|
+
# Each method returns `self` to allow for chaining.
|
|
105
|
+
#
|
|
106
|
+
# Sets the maximum number of commits to return
|
|
107
|
+
#
|
|
108
|
+
# @param num [Integer, Symbol, nil] the maximum commit count, or `:all` / `nil`
|
|
109
|
+
# for no limit
|
|
110
|
+
#
|
|
111
|
+
# @return [Git::Log] the current query builder
|
|
112
|
+
#
|
|
113
|
+
def max_count(num) = set_option(:count, num == :all ? nil : num)
|
|
54
114
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
115
|
+
# Includes commits reachable from all refs
|
|
116
|
+
#
|
|
117
|
+
# @return [Git::Log] the current query builder
|
|
118
|
+
#
|
|
119
|
+
def all = set_option(:all, true)
|
|
60
120
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
121
|
+
# Sets the revision range expression for the log query
|
|
122
|
+
#
|
|
123
|
+
# @param objectish [String] a git revision expression to pass to `git log`
|
|
124
|
+
#
|
|
125
|
+
# @return [Git::Log] the current query builder
|
|
126
|
+
#
|
|
127
|
+
def object(objectish) = set_option(:object, objectish)
|
|
66
128
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
129
|
+
# Filters commits by author pattern
|
|
130
|
+
#
|
|
131
|
+
# @param regex [String] a pattern matched against author names
|
|
132
|
+
#
|
|
133
|
+
# @return [Git::Log] the current query builder
|
|
134
|
+
#
|
|
135
|
+
def author(regex) = set_option(:author, regex)
|
|
72
136
|
|
|
73
|
-
|
|
74
|
-
|
|
137
|
+
# Filters commits by commit message pattern
|
|
138
|
+
#
|
|
139
|
+
# @param regex [String] a pattern matched against commit messages
|
|
140
|
+
#
|
|
141
|
+
# @return [Git::Log] the current query builder
|
|
142
|
+
#
|
|
143
|
+
def grep(regex) = set_option(:grep, regex)
|
|
144
|
+
|
|
145
|
+
# Interprets {#grep} and {#author} patterns as Perl-compatible regular expressions
|
|
146
|
+
#
|
|
147
|
+
# Selects PCRE instead of git's default POSIX basic regular expressions for
|
|
148
|
+
# every pattern in the query. Requires a git built with PCRE support.
|
|
149
|
+
#
|
|
150
|
+
# @example Match a metacharacter against a non-ASCII character on Git for Windows
|
|
151
|
+
# repo.log.perl_regexp.grep('^.PFEL').execute
|
|
152
|
+
#
|
|
153
|
+
# @return [Git::Log] the current query builder
|
|
154
|
+
#
|
|
155
|
+
# @note On Git for Windows, git's default regex engine matches *bytes* rather
|
|
156
|
+
# than characters, so a metacharacter such as `.` or a POSIX class such as
|
|
157
|
+
# `[[:alpha:]]` never matches a whole multi-byte character. The match fails
|
|
158
|
+
# silently: git exits zero and the result is empty. PCRE does match characters
|
|
159
|
+
# on that platform, but it is a different dialect than git's default, so
|
|
160
|
+
# selecting it is a deliberate choice by the caller.
|
|
161
|
+
#
|
|
162
|
+
def perl_regexp = set_option(:perl_regexp, true)
|
|
163
|
+
|
|
164
|
+
# Limits commits to those that touch the given path or paths
|
|
165
|
+
#
|
|
166
|
+
# @param path [String, Pathname, Array<String, Pathname>] path limiter input
|
|
167
|
+
#
|
|
168
|
+
# @return [Git::Log] the current query builder
|
|
169
|
+
#
|
|
170
|
+
def path(path) = set_option(:path_limiter, path)
|
|
171
|
+
|
|
172
|
+
# Skips a number of commits before returning results
|
|
173
|
+
#
|
|
174
|
+
# @param num [Integer] the number of commits to skip
|
|
175
|
+
#
|
|
176
|
+
# @return [Git::Log] the current query builder
|
|
177
|
+
#
|
|
178
|
+
def skip(num) = set_option(:skip, num)
|
|
179
|
+
|
|
180
|
+
# Includes only commits newer than the given date expression
|
|
181
|
+
#
|
|
182
|
+
# @param date [String] a git-compatible date expression
|
|
183
|
+
#
|
|
184
|
+
# @return [Git::Log] the current query builder
|
|
185
|
+
#
|
|
186
|
+
def since(date) = set_option(:since, date)
|
|
187
|
+
|
|
188
|
+
# Includes only commits older than the given date expression
|
|
189
|
+
#
|
|
190
|
+
# @param date [String] a git-compatible date expression
|
|
191
|
+
#
|
|
192
|
+
# @return [Git::Log] the current query builder
|
|
193
|
+
#
|
|
194
|
+
def until(date) = set_option(:until, date)
|
|
195
|
+
|
|
196
|
+
# Limits commits to the given revision range
|
|
197
|
+
#
|
|
198
|
+
# @param val1 [String] the first revision
|
|
199
|
+
#
|
|
200
|
+
# @param val2 [String, nil] the second revision; when `nil`, validation fails
|
|
201
|
+
# at execution time
|
|
202
|
+
#
|
|
203
|
+
# @return [Git::Log] the current query builder
|
|
204
|
+
#
|
|
205
|
+
def between(val1, val2 = nil) = set_option(:between, [val1, val2])
|
|
206
|
+
|
|
207
|
+
# Omits commits equivalent to cherry-picked commits
|
|
208
|
+
#
|
|
209
|
+
# @return [Git::Log] the current query builder
|
|
210
|
+
#
|
|
211
|
+
def cherry = set_option(:cherry, true)
|
|
212
|
+
|
|
213
|
+
# Includes only merge commits
|
|
214
|
+
#
|
|
215
|
+
# @return [Git::Log] the current query builder
|
|
216
|
+
#
|
|
217
|
+
def merges = set_option(:merges, true)
|
|
218
|
+
|
|
219
|
+
# Executes the git log command and returns an immutable result object
|
|
220
|
+
#
|
|
221
|
+
# This is the preferred way to get log data. It separates the query
|
|
222
|
+
# building from the execution, making the API more predictable.
|
|
223
|
+
#
|
|
224
|
+
# @example
|
|
225
|
+
# query = g.log.since('2 weeks ago').author('Scott')
|
|
226
|
+
# results = query.execute
|
|
227
|
+
# puts "Found #{results.size} commits"
|
|
228
|
+
# results.each do |commit|
|
|
229
|
+
# # ...
|
|
230
|
+
# end
|
|
231
|
+
#
|
|
232
|
+
# @return [Git::Log::Result] an object containing the log results
|
|
233
|
+
#
|
|
234
|
+
def execute
|
|
235
|
+
run_log_if_dirty
|
|
236
|
+
Result.new(@commits)
|
|
75
237
|
end
|
|
76
238
|
|
|
239
|
+
# @!group Deprecated Enumerable Interface
|
|
77
240
|
|
|
78
|
-
#
|
|
241
|
+
# @deprecated Use {#execute} and call `each` on the result.
|
|
242
|
+
def each(&)
|
|
243
|
+
Git::Deprecation.warn(
|
|
244
|
+
'Calling Git::Log#each is deprecated and will be removed in v6.0.0. ' \
|
|
245
|
+
'Call #execute and then #each on the result object.'
|
|
246
|
+
)
|
|
247
|
+
run_log_if_dirty
|
|
248
|
+
@commits.each(&)
|
|
249
|
+
end
|
|
79
250
|
|
|
251
|
+
# @deprecated Use {#execute} and call `size` on the result.
|
|
80
252
|
def size
|
|
81
|
-
|
|
82
|
-
|
|
253
|
+
Git::Deprecation.warn(
|
|
254
|
+
'Calling Git::Log#size is deprecated and will be removed in v6.0.0. ' \
|
|
255
|
+
'Call #execute and then #size on the result object.'
|
|
256
|
+
)
|
|
257
|
+
run_log_if_dirty
|
|
258
|
+
@commits.size
|
|
83
259
|
end
|
|
84
260
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
261
|
+
# @deprecated Use {#execute} and call `to_s` on the result.
|
|
262
|
+
def to_s
|
|
263
|
+
Git::Deprecation.warn(
|
|
264
|
+
'Calling Git::Log#to_s is deprecated and will be removed in v6.0.0. ' \
|
|
265
|
+
'Call #execute and then #to_s on the result object.'
|
|
266
|
+
)
|
|
267
|
+
run_log_if_dirty
|
|
268
|
+
@commits.join("\n")
|
|
88
269
|
end
|
|
89
270
|
|
|
271
|
+
# @deprecated Use {#execute} and call the method on the result.
|
|
90
272
|
def first
|
|
91
|
-
|
|
92
|
-
|
|
273
|
+
Git::Deprecation.warn(
|
|
274
|
+
'Calling Git::Log#first is deprecated and will be removed in v6.0.0. ' \
|
|
275
|
+
'Call #execute and then #first on the result object.'
|
|
276
|
+
)
|
|
277
|
+
run_log_if_dirty
|
|
278
|
+
@commits.first
|
|
93
279
|
end
|
|
94
280
|
|
|
281
|
+
# @deprecated Use {#execute} and call the method on the result.
|
|
95
282
|
def last
|
|
96
|
-
|
|
97
|
-
|
|
283
|
+
Git::Deprecation.warn(
|
|
284
|
+
'Calling Git::Log#last is deprecated and will be removed in v6.0.0. ' \
|
|
285
|
+
'Call #execute and then #last on the result object.'
|
|
286
|
+
)
|
|
287
|
+
run_log_if_dirty
|
|
288
|
+
@commits.last
|
|
98
289
|
end
|
|
99
290
|
|
|
291
|
+
# @param index [Integer, Range] the commit index or range to retrieve
|
|
292
|
+
#
|
|
293
|
+
# @return [Git::Object::Commit, Array<Git::Object::Commit>, nil] the selected
|
|
294
|
+
# commit or commits
|
|
295
|
+
#
|
|
296
|
+
# @deprecated Use {#execute} and call the method on the result.
|
|
297
|
+
#
|
|
100
298
|
def [](index)
|
|
101
|
-
|
|
102
|
-
|
|
299
|
+
Git::Deprecation.warn(
|
|
300
|
+
'Calling Git::Log#[] is deprecated and will be removed in v6.0.0. ' \
|
|
301
|
+
'Call #execute and then #[] on the result object.'
|
|
302
|
+
)
|
|
303
|
+
run_log_if_dirty
|
|
304
|
+
@commits[index]
|
|
103
305
|
end
|
|
104
306
|
|
|
307
|
+
# @!endgroup
|
|
105
308
|
|
|
106
309
|
private
|
|
107
310
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
log = @base.lib.full_log_commits(
|
|
122
|
-
count: @count, all: @all, object: @object, path_limiter: @path, since: @since,
|
|
123
|
-
author: @author, grep: @grep, skip: @skip, until: @until, between: @between,
|
|
124
|
-
cherry: @cherry
|
|
125
|
-
)
|
|
126
|
-
@commits = log.map { |c| Git::Object::Commit.new(@base, c['sha'], c) }
|
|
127
|
-
end
|
|
311
|
+
# Sets a log query option and marks cached results dirty
|
|
312
|
+
#
|
|
313
|
+
# @param key [Symbol] the option key
|
|
314
|
+
#
|
|
315
|
+
# @param value [Object] the option value
|
|
316
|
+
#
|
|
317
|
+
# @return [Git::Log] the current query builder
|
|
318
|
+
#
|
|
319
|
+
def set_option(key, value)
|
|
320
|
+
@dirty = true
|
|
321
|
+
@options[key] = value
|
|
322
|
+
self
|
|
323
|
+
end
|
|
128
324
|
|
|
129
|
-
|
|
325
|
+
# @return [Git::Repository]
|
|
326
|
+
#
|
|
327
|
+
def log_repository
|
|
328
|
+
@base
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Refreshes cached commits when query options have changed
|
|
332
|
+
#
|
|
333
|
+
# @return [void]
|
|
334
|
+
#
|
|
335
|
+
# @raise [ArgumentError] if configured query options are invalid
|
|
336
|
+
#
|
|
337
|
+
# @raise [Git::FailedError] if the underlying `git log` command fails
|
|
338
|
+
#
|
|
339
|
+
def run_log_if_dirty
|
|
340
|
+
return unless @dirty
|
|
130
341
|
|
|
342
|
+
log_data = log_repository.full_log_commits(@options)
|
|
343
|
+
@commits = log_data.map { |c| Git::Object::Commit.new(@base, c['sha'], c) }
|
|
344
|
+
@dirty = false
|
|
345
|
+
end
|
|
346
|
+
end
|
|
131
347
|
end
|