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/status.rb
CHANGED
|
@@ -1,108 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Git
|
|
4
|
+
# The Status class gets the status of a git repository. It identifies which
|
|
5
|
+
# files have been modified, added, or deleted, including untracked files.
|
|
6
|
+
# The Status object is an Enumerable of StatusFile objects.
|
|
7
|
+
#
|
|
8
|
+
# @example Inspect repository status
|
|
9
|
+
# repo = Git.open('/path/to/repo')
|
|
10
|
+
# status = repo.status
|
|
11
|
+
# status.changed.each { |path, _file| puts "Modified: #{path}" }
|
|
12
|
+
# status.added.each { |path, _file| puts "Added: #{path}" }
|
|
13
|
+
# status.deleted.each { |path, _file| puts "Deleted: #{path}" }
|
|
14
|
+
# status.untracked.each { |path, _file| puts "Untracked: #{path}" }
|
|
2
15
|
#
|
|
3
|
-
#
|
|
16
|
+
# @deprecated Use {Git::StatusInfo}, returned by {Git::Repository#status_info},
|
|
17
|
+
# instead; this class will be removed in v6.0.0
|
|
18
|
+
#
|
|
19
|
+
# @api public
|
|
4
20
|
#
|
|
5
21
|
class Status
|
|
6
22
|
include Enumerable
|
|
7
23
|
|
|
24
|
+
# Create a new Status for the given repository
|
|
25
|
+
#
|
|
26
|
+
# @param base [Git::Repository] the git object backing this status
|
|
27
|
+
#
|
|
28
|
+
# @deprecated Use {Git::Repository#status_info} instead
|
|
29
|
+
#
|
|
8
30
|
def initialize(base)
|
|
31
|
+
if defined?(Git::Deprecation)
|
|
32
|
+
Git::Deprecation.warn(
|
|
33
|
+
'Git::Status is deprecated and will be removed in v6.0.0. ' \
|
|
34
|
+
'Use Git::Repository#status_info instead.'
|
|
35
|
+
)
|
|
36
|
+
end
|
|
9
37
|
@base = base
|
|
10
|
-
|
|
38
|
+
# The factory returns a hash of file paths to StatusFile objects.
|
|
39
|
+
@files = StatusFileFactory.new(base).construct_files
|
|
11
40
|
end
|
|
12
41
|
|
|
42
|
+
# Return files modified in the index and/or working tree
|
|
13
43
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
44
|
+
# Includes both staged modifications (index vs HEAD) and unstaged modifications
|
|
45
|
+
# (working tree vs index).
|
|
16
46
|
#
|
|
17
|
-
# @return [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
47
|
+
# @return [Hash{String => Git::Status::StatusFile}] changed files keyed by path
|
|
48
|
+
#
|
|
49
|
+
def changed = @changed ||= select_files { |f| f.type == 'M' }
|
|
21
50
|
|
|
51
|
+
# Return files added to the index that are not yet in HEAD
|
|
22
52
|
#
|
|
23
|
-
#
|
|
24
|
-
# File path starts at git base directory
|
|
53
|
+
# @return [Hash{String => Git::Status::StatusFile}] added files keyed by path
|
|
25
54
|
#
|
|
26
|
-
|
|
27
|
-
# @example Check if lib/git.rb has changed.
|
|
28
|
-
# changed?('lib/git.rb')
|
|
29
|
-
# @return [Boolean]
|
|
30
|
-
def changed?(file)
|
|
31
|
-
changed.member?(file)
|
|
32
|
-
end
|
|
55
|
+
def added = @added ||= select_files { |f| f.type == 'A' }
|
|
33
56
|
|
|
57
|
+
# Return files deleted from the index
|
|
34
58
|
#
|
|
35
|
-
#
|
|
36
|
-
# File path starts at git base directory
|
|
59
|
+
# @return [Hash{String => Git::Status::StatusFile}] deleted files keyed by path
|
|
37
60
|
#
|
|
38
|
-
|
|
39
|
-
def added
|
|
40
|
-
@files.select { |_k, f| f.type == 'A' }
|
|
41
|
-
end
|
|
61
|
+
def deleted = @deleted ||= select_files { |f| f.type == 'D' }
|
|
42
62
|
|
|
63
|
+
# Return files present in the working tree but not tracked by git
|
|
43
64
|
#
|
|
44
|
-
#
|
|
45
|
-
# File path starts at git base directory
|
|
65
|
+
# @return [Hash{String => Git::Status::StatusFile}] untracked files keyed by path
|
|
46
66
|
#
|
|
47
|
-
|
|
48
|
-
# @example Check if lib/git.rb is added.
|
|
49
|
-
# added?('lib/git.rb')
|
|
50
|
-
# @return [Boolean]
|
|
51
|
-
def added?(file)
|
|
52
|
-
added.member?(file)
|
|
53
|
-
end
|
|
67
|
+
def untracked = @untracked ||= select_files(&:untracked)
|
|
54
68
|
|
|
69
|
+
# Return `true` if `file` has been modified in the index or working tree
|
|
55
70
|
#
|
|
56
|
-
#
|
|
57
|
-
# File path starts at git base directory
|
|
71
|
+
# @param file [String] the repository-relative path to check
|
|
58
72
|
#
|
|
59
|
-
# @return [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
end
|
|
73
|
+
# @return [Boolean] `true` if the file has been modified
|
|
74
|
+
#
|
|
75
|
+
def changed?(file) = file_in_collection?(:changed, file)
|
|
63
76
|
|
|
77
|
+
# Return `true` if `file` has been added to the index
|
|
64
78
|
#
|
|
65
|
-
#
|
|
66
|
-
# File path starts at git base directory
|
|
79
|
+
# @param file [String] the repository-relative path to check
|
|
67
80
|
#
|
|
68
|
-
# @
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
# @return [Boolean]
|
|
72
|
-
def deleted?(file)
|
|
73
|
-
deleted.member?(file)
|
|
74
|
-
end
|
|
81
|
+
# @return [Boolean] `true` if the file has been added
|
|
82
|
+
#
|
|
83
|
+
def added?(file) = file_in_collection?(:added, file)
|
|
75
84
|
|
|
85
|
+
# Return `true` if `file` has been deleted from the index
|
|
76
86
|
#
|
|
77
|
-
#
|
|
78
|
-
# File path starts at git base directory
|
|
87
|
+
# @param file [String] the repository-relative path to check
|
|
79
88
|
#
|
|
80
|
-
# @return [
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
end
|
|
89
|
+
# @return [Boolean] `true` if the file has been deleted
|
|
90
|
+
#
|
|
91
|
+
def deleted?(file) = file_in_collection?(:deleted, file)
|
|
84
92
|
|
|
93
|
+
# Return `true` if `file` is not tracked by git
|
|
85
94
|
#
|
|
86
|
-
#
|
|
87
|
-
# File path starts at git base directory
|
|
95
|
+
# @param file [String] the repository-relative path to check
|
|
88
96
|
#
|
|
89
|
-
# @
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
# @return [Boolean] `true` if the file is untracked
|
|
98
|
+
#
|
|
99
|
+
def untracked?(file) = file_in_collection?(:untracked, file)
|
|
100
|
+
|
|
101
|
+
# Return the {Git::Status::StatusFile} for the given path
|
|
102
|
+
#
|
|
103
|
+
# @param file [String] the repository-relative path
|
|
104
|
+
#
|
|
105
|
+
# @return [Git::Status::StatusFile, nil] the status file, or `nil` if not found
|
|
106
|
+
#
|
|
107
|
+
def [](file) = @files[file]
|
|
96
108
|
|
|
109
|
+
# Iterate over all status files
|
|
110
|
+
#
|
|
111
|
+
# @overload each
|
|
112
|
+
#
|
|
113
|
+
# @return [Enumerator<Git::Status::StatusFile>] an enumerator over all status files
|
|
114
|
+
#
|
|
115
|
+
# @overload each(&block)
|
|
116
|
+
#
|
|
117
|
+
# @return [Array<Git::Status::StatusFile>] the full list of status files
|
|
118
|
+
#
|
|
119
|
+
# @yield [file] each {Git::Status::StatusFile} in the repository
|
|
120
|
+
#
|
|
121
|
+
# @yieldparam file [Git::Status::StatusFile] a single file's status
|
|
122
|
+
#
|
|
123
|
+
# @yieldreturn [void]
|
|
124
|
+
#
|
|
125
|
+
def each(&) = @files.values.each(&)
|
|
126
|
+
|
|
127
|
+
# Return a formatted multi-line string representation of the status
|
|
128
|
+
#
|
|
129
|
+
# @return [String] one indented block per file showing its SHA, mode, type,
|
|
130
|
+
# stage, and untracked flag
|
|
131
|
+
#
|
|
97
132
|
def pretty
|
|
98
|
-
|
|
99
|
-
each do |file|
|
|
100
|
-
out << pretty_file(file)
|
|
101
|
-
end
|
|
102
|
-
out << "\n"
|
|
103
|
-
out
|
|
133
|
+
map { |file| pretty_file(file) }.join << "\n"
|
|
104
134
|
end
|
|
105
135
|
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
# Format a single file's status as an indented multi-line string
|
|
139
|
+
#
|
|
140
|
+
# @param file [Git::Status::StatusFile] the file to format
|
|
141
|
+
#
|
|
142
|
+
# @return [String] the formatted status block for this file
|
|
143
|
+
#
|
|
106
144
|
def pretty_file(file)
|
|
107
145
|
<<~FILE
|
|
108
146
|
#{file.path}
|
|
@@ -114,84 +152,232 @@ module Git
|
|
|
114
152
|
FILE
|
|
115
153
|
end
|
|
116
154
|
|
|
117
|
-
#
|
|
155
|
+
# Return a hash of files for which the block returns a truthy value
|
|
156
|
+
#
|
|
157
|
+
# @return [Hash{String => Git::Status::StatusFile}] matching files keyed by path
|
|
158
|
+
#
|
|
159
|
+
# @yield [file] each {Git::Status::StatusFile} in the repository
|
|
160
|
+
#
|
|
161
|
+
# @yieldparam file [Git::Status::StatusFile] a single file's status
|
|
162
|
+
#
|
|
163
|
+
# @yieldreturn [Boolean] truthy to include the file in the result
|
|
164
|
+
#
|
|
165
|
+
def select_files(&block)
|
|
166
|
+
@files.select { |_path, file| block.call(file) }
|
|
167
|
+
end
|
|
118
168
|
|
|
119
|
-
|
|
120
|
-
|
|
169
|
+
# Return `true` if `file_path` exists in the named status collection
|
|
170
|
+
#
|
|
171
|
+
# @param collection_name [Symbol] the collection to check (e.g. `:changed`)
|
|
172
|
+
#
|
|
173
|
+
# @param file_path [String] the repository-relative path to look up
|
|
174
|
+
#
|
|
175
|
+
# @return [Boolean] `true` if the path is present in the collection
|
|
176
|
+
#
|
|
177
|
+
def file_in_collection?(collection_name, file_path)
|
|
178
|
+
collection = public_send(collection_name)
|
|
179
|
+
if ignore_case?
|
|
180
|
+
downcased_keys(collection_name).include?(file_path.downcase)
|
|
181
|
+
else
|
|
182
|
+
collection.key?(file_path)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Return a memoized set of downcased keys for the named collection
|
|
187
|
+
#
|
|
188
|
+
# @param collection_name [Symbol] the collection whose keys to downcase
|
|
189
|
+
#
|
|
190
|
+
# @return [Set<String>] the lowercased path keys
|
|
191
|
+
#
|
|
192
|
+
def downcased_keys(collection_name)
|
|
193
|
+
@_downcased_keys ||= {}
|
|
194
|
+
@_downcased_keys[collection_name] ||=
|
|
195
|
+
public_send(collection_name).keys.to_set(&:downcase)
|
|
121
196
|
end
|
|
122
197
|
|
|
123
|
-
|
|
124
|
-
|
|
198
|
+
# Return `true` when git is configured to ignore filename case
|
|
199
|
+
#
|
|
200
|
+
# Reads `core.ignoreCase` with {Git::Repository#config_get}. Returns `false`
|
|
201
|
+
# when the config value is absent.
|
|
202
|
+
#
|
|
203
|
+
# @return [Boolean] `true` when `core.ignoreCase` is `"true"`
|
|
204
|
+
#
|
|
205
|
+
def ignore_case?
|
|
206
|
+
return @ignore_case if defined?(@ignore_case)
|
|
207
|
+
|
|
208
|
+
@ignore_case = (@base.config_get('core.ignoreCase')&.value == 'true')
|
|
125
209
|
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
126
212
|
|
|
127
|
-
|
|
213
|
+
module Git
|
|
214
|
+
class Status
|
|
215
|
+
# Represents a single file's status in the git repository. Each instance
|
|
216
|
+
# holds information about a file's state in the index and working tree.
|
|
217
|
+
#
|
|
218
|
+
# @deprecated Use {Git::StatusFileInfo}, held by {Git::StatusInfo#files},
|
|
219
|
+
# instead; this class will be removed in v6.0.0
|
|
220
|
+
#
|
|
221
|
+
# @api public
|
|
222
|
+
#
|
|
128
223
|
class StatusFile
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
224
|
+
# The repository-relative file path
|
|
225
|
+
#
|
|
226
|
+
# @return [String] the path
|
|
227
|
+
attr_reader :path
|
|
228
|
+
|
|
229
|
+
# The change type for this file
|
|
230
|
+
#
|
|
231
|
+
# @return [String, nil] `"M"` for modified, `"A"` for added, `"D"` for deleted,
|
|
232
|
+
# or `nil` when not applicable
|
|
233
|
+
attr_reader :type
|
|
234
|
+
|
|
235
|
+
# The merge stage for this file
|
|
236
|
+
#
|
|
237
|
+
# @return [String, nil] `"0"` for normal entries, or a non-zero value during
|
|
238
|
+
# a merge conflict
|
|
239
|
+
attr_reader :stage
|
|
240
|
+
|
|
241
|
+
# The file mode recorded in the index
|
|
242
|
+
#
|
|
243
|
+
# @return [String, nil] the octal file mode (e.g. `"100644"`), or `nil`
|
|
244
|
+
attr_reader :mode_index
|
|
245
|
+
|
|
246
|
+
# The file mode recorded in HEAD
|
|
247
|
+
#
|
|
248
|
+
# @return [String, nil] the octal file mode (e.g. `"100644"`), or `nil`
|
|
249
|
+
attr_reader :mode_repo
|
|
250
|
+
|
|
251
|
+
# The SHA of the index version of this file
|
|
252
|
+
#
|
|
253
|
+
# @return [String, nil] the SHA-1 hex digest, or `nil` if unavailable
|
|
254
|
+
attr_reader :sha_index
|
|
132
255
|
|
|
256
|
+
# The SHA of the HEAD version of this file
|
|
257
|
+
#
|
|
258
|
+
# @return [String, nil] the SHA-1 hex digest, or `nil` if unavailable
|
|
259
|
+
attr_reader :sha_repo
|
|
260
|
+
|
|
261
|
+
# Whether this file is untracked
|
|
262
|
+
#
|
|
263
|
+
# @return [Boolean, nil] `true` when the file is not tracked by git
|
|
264
|
+
attr_reader :untracked
|
|
265
|
+
|
|
266
|
+
# Initialize a new StatusFile with the given git object and data hash
|
|
267
|
+
#
|
|
268
|
+
# @param base [Git::Repository] the git object
|
|
269
|
+
#
|
|
270
|
+
# @param hash [Hash] raw status data for this file
|
|
271
|
+
#
|
|
133
272
|
def initialize(base, hash)
|
|
134
|
-
@base
|
|
135
|
-
@path
|
|
136
|
-
@type
|
|
137
|
-
@stage
|
|
273
|
+
@base = base
|
|
274
|
+
@path = hash[:path]
|
|
275
|
+
@type = hash[:type]
|
|
276
|
+
@stage = hash[:stage]
|
|
138
277
|
@mode_index = hash[:mode_index]
|
|
139
|
-
@mode_repo
|
|
140
|
-
@sha_index
|
|
141
|
-
@sha_repo
|
|
142
|
-
@untracked
|
|
278
|
+
@mode_repo = hash[:mode_repo]
|
|
279
|
+
@sha_index = hash[:sha_index]
|
|
280
|
+
@sha_repo = hash[:sha_repo]
|
|
281
|
+
@untracked = hash[:untracked]
|
|
143
282
|
end
|
|
144
283
|
|
|
284
|
+
# Return a blob object for the index or repo version of this file
|
|
285
|
+
#
|
|
286
|
+
# @param type [Symbol] `:index` (default) for the index version, or
|
|
287
|
+
# `:repo` for the HEAD version
|
|
288
|
+
#
|
|
289
|
+
# @return [Git::Object::Blob, nil] the blob object, or `nil` if no SHA
|
|
290
|
+
# is available for the requested version
|
|
291
|
+
#
|
|
145
292
|
def blob(type = :index)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
else
|
|
149
|
-
begin
|
|
150
|
-
@base.object(@sha_index)
|
|
151
|
-
rescue
|
|
152
|
-
@base.object(@sha_repo)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
293
|
+
sha = type == :repo ? sha_repo : (sha_index || sha_repo)
|
|
294
|
+
@base.object(sha) if sha
|
|
155
295
|
end
|
|
156
296
|
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
157
299
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
300
|
+
module Git
|
|
301
|
+
class Status
|
|
302
|
+
# A factory class responsible for fetching git status data and building
|
|
303
|
+
# a hash of StatusFile objects.
|
|
304
|
+
#
|
|
305
|
+
# @api private
|
|
306
|
+
#
|
|
307
|
+
class StatusFileFactory
|
|
308
|
+
# Create a new factory backed by the given git object
|
|
309
|
+
#
|
|
310
|
+
# @param base [Git::Repository] the git object used as the status data provider
|
|
311
|
+
#
|
|
312
|
+
def initialize(base)
|
|
313
|
+
@base = base
|
|
314
|
+
end
|
|
166
315
|
|
|
167
|
-
|
|
168
|
-
|
|
316
|
+
# Gather all status data and build a hash of file paths to StatusFile objects
|
|
317
|
+
#
|
|
318
|
+
# @return [Hash{String => Git::Status::StatusFile}] file paths mapped to
|
|
319
|
+
# their status objects
|
|
320
|
+
#
|
|
321
|
+
def construct_files
|
|
322
|
+
files_data = fetch_all_files_data
|
|
323
|
+
files_data.transform_values do |data|
|
|
324
|
+
StatusFile.new(@base, data)
|
|
325
|
+
end
|
|
169
326
|
end
|
|
170
|
-
end
|
|
171
327
|
|
|
172
|
-
|
|
173
|
-
ignore = @base.lib.ignored_files
|
|
328
|
+
private
|
|
174
329
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
330
|
+
# Fetch and merge status information from multiple git commands
|
|
331
|
+
#
|
|
332
|
+
# @return [Hash{String => Hash}] raw per-file status data keyed by path
|
|
333
|
+
#
|
|
334
|
+
def fetch_all_files_data
|
|
335
|
+
files = @base.ls_files # Start with files tracked in the index.
|
|
336
|
+
merge_untracked_files(files)
|
|
337
|
+
merge_modified_files(files)
|
|
338
|
+
merge_head_diffs(files)
|
|
339
|
+
files
|
|
340
|
+
end
|
|
179
341
|
|
|
180
|
-
|
|
342
|
+
# Merge untracked working-tree files into `files`
|
|
343
|
+
#
|
|
344
|
+
# @param files [Hash] the in-progress files hash to update in place
|
|
345
|
+
#
|
|
346
|
+
# @return [void]
|
|
347
|
+
#
|
|
348
|
+
def merge_untracked_files(files)
|
|
349
|
+
@base.untracked_files.each do |file|
|
|
350
|
+
files[file] = { path: file, untracked: true }
|
|
351
|
+
end
|
|
181
352
|
end
|
|
182
|
-
end
|
|
183
353
|
|
|
184
|
-
|
|
185
|
-
#
|
|
186
|
-
@
|
|
187
|
-
|
|
354
|
+
# Merge index-versus-working-tree diff data into `files`
|
|
355
|
+
#
|
|
356
|
+
# @param files [Hash] the in-progress files hash to update in place
|
|
357
|
+
#
|
|
358
|
+
# @return [void]
|
|
359
|
+
#
|
|
360
|
+
def merge_modified_files(files)
|
|
361
|
+
# Merge changes between the index and the working directory.
|
|
362
|
+
@base.diff_files.each do |path, data|
|
|
363
|
+
(files[path] ||= {}).merge!(data)
|
|
364
|
+
end
|
|
188
365
|
end
|
|
189
|
-
end
|
|
190
366
|
|
|
191
|
-
|
|
192
|
-
#
|
|
193
|
-
@
|
|
194
|
-
|
|
367
|
+
# Merge HEAD-versus-index diff data into `files`, if commits exist
|
|
368
|
+
#
|
|
369
|
+
# @param files [Hash] the in-progress files hash to update in place
|
|
370
|
+
#
|
|
371
|
+
# @return [void]
|
|
372
|
+
#
|
|
373
|
+
def merge_head_diffs(files)
|
|
374
|
+
is_empty = @base.no_commits?
|
|
375
|
+
return if is_empty
|
|
376
|
+
|
|
377
|
+
# Merge changes between HEAD and the index.
|
|
378
|
+
@base.diff_index('HEAD').each do |path, data|
|
|
379
|
+
(files[path] ||= {}).merge!(data)
|
|
380
|
+
end
|
|
195
381
|
end
|
|
196
382
|
end
|
|
197
383
|
end
|