git 5.0.0.beta.2 → 5.0.0.beta.4
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/.dockerignore +27 -0
- data/.github/copilot-instructions.md +3 -8
- data/.github/hooks/bin-setup-on-worktree.json +11 -0
- data/.github/hooks/run-bin-setup-once.sh +14 -0
- data/.github/skills/breaking-change-analysis/SKILL.md +6 -9
- data/.github/skills/ci-cd-troubleshooting/SKILL.md +2 -2
- data/.github/skills/command-implementation/REFERENCE.md +34 -33
- data/.github/skills/command-implementation/SKILL.md +5 -4
- data/.github/skills/command-test-conventions/SKILL.md +13 -9
- data/.github/skills/command-yard-documentation/SKILL.md +14 -6
- data/.github/skills/development-workflow/SKILL.md +20 -14
- data/.github/skills/facade-implementation/REFERENCE.md +19 -22
- data/.github/skills/facade-implementation/SKILL.md +0 -5
- data/.github/skills/facade-test-conventions/SKILL.md +4 -7
- data/.github/skills/facade-yard-documentation/SKILL.md +8 -2
- data/.github/skills/make-skill-template/SKILL.md +53 -3
- data/.github/skills/pr-readiness-review/SKILL.md +22 -2
- data/.github/skills/project-context/SKILL.md +16 -23
- data/.github/skills/pull-request-review/SKILL.md +2 -2
- data/.github/skills/rebase/SKILL.md +148 -0
- data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +1 -1
- data/.github/skills/resolve-feedback/SKILL.md +288 -0
- data/.github/skills/review-arguments-dsl/CHECKLIST.md +3 -3
- data/.github/skills/reviewing-skills/SKILL.md +28 -3
- data/.github/skills/test-debugging/SKILL.md +20 -19
- data/.github/skills/yard-documentation/SKILL.md +671 -483
- data/.github/skills/yard-documentation/element-rules.md +162 -0
- data/.github/skills-deprecated/README.md +21 -0
- data/.github/{skills → skills-deprecated}/extract-command-from-lib/SKILL.md +9 -9
- data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/SKILL.md +12 -12
- data/.github/workflows/continuous_integration.yml +3 -2
- data/.rubocop.yml +7 -39
- data/.yard-lint.yml +75 -0
- data/CONTRIBUTING.md +186 -174
- data/Gemfile +17 -0
- data/README.md +86 -23
- data/Rakefile +3 -21
- data/UPGRADING.md +219 -70
- data/docker/test/Dockerfile +32 -0
- data/docker/test/docker-compose.yml +0 -0
- data/git.gemspec +3 -4
- data/lib/git/author.rb +20 -1
- data/lib/git/branch.rb +26 -6
- data/lib/git/branch_delete_failure.rb +3 -0
- data/lib/git/branch_delete_result.rb +6 -3
- data/lib/git/branch_info.rb +6 -6
- data/lib/git/command_line/base.rb +6 -13
- data/lib/git/command_line/capturing.rb +67 -10
- data/lib/git/command_line/result.rb +0 -8
- data/lib/git/command_line/streaming.rb +45 -5
- data/lib/git/command_line.rb +4 -3
- data/lib/git/commands/add.rb +61 -53
- data/lib/git/commands/am/abort.rb +2 -2
- data/lib/git/commands/am/apply.rb +109 -98
- data/lib/git/commands/am/continue.rb +2 -2
- data/lib/git/commands/am/quit.rb +2 -2
- data/lib/git/commands/am/retry.rb +4 -2
- data/lib/git/commands/am/show_current_patch.rb +1 -1
- data/lib/git/commands/am/skip.rb +2 -2
- data/lib/git/commands/am.rb +2 -2
- data/lib/git/commands/apply.rb +7 -2
- data/lib/git/commands/archive/list_formats.rb +3 -3
- data/lib/git/commands/archive.rb +7 -2
- data/lib/git/commands/arguments.rb +1370 -359
- data/lib/git/commands/base.rb +111 -13
- data/lib/git/commands/branch/copy.rb +29 -21
- data/lib/git/commands/branch/create.rb +72 -68
- data/lib/git/commands/branch/delete.rb +25 -17
- data/lib/git/commands/branch/list.rb +76 -60
- data/lib/git/commands/branch/move.rb +29 -21
- data/lib/git/commands/branch/set_upstream.rb +8 -8
- data/lib/git/commands/branch/show_current.rb +3 -3
- data/lib/git/commands/branch/unset_upstream.rb +4 -8
- data/lib/git/commands/branch.rb +2 -2
- data/lib/git/commands/cat_file/batch.rb +36 -20
- data/lib/git/commands/cat_file/filtered.rb +12 -12
- data/lib/git/commands/cat_file/raw.rb +13 -13
- data/lib/git/commands/cat_file.rb +4 -4
- data/lib/git/commands/checkout/branch.rb +7 -5
- data/lib/git/commands/checkout/files.rb +5 -4
- data/lib/git/commands/checkout.rb +4 -4
- data/lib/git/commands/checkout_index.rb +5 -4
- data/lib/git/commands/clean.rb +6 -4
- data/lib/git/commands/clone.rb +5 -4
- data/lib/git/commands/commit.rb +5 -4
- data/lib/git/commands/commit_tree.rb +5 -4
- data/lib/git/commands/config_option_syntax/add.rb +7 -4
- data/lib/git/commands/config_option_syntax/get.rb +9 -5
- data/lib/git/commands/config_option_syntax/get_all.rb +7 -4
- data/lib/git/commands/config_option_syntax/get_color.rb +8 -4
- data/lib/git/commands/config_option_syntax/get_color_bool.rb +7 -4
- data/lib/git/commands/config_option_syntax/get_regexp.rb +8 -4
- data/lib/git/commands/config_option_syntax/get_urlmatch.rb +8 -4
- data/lib/git/commands/config_option_syntax/list.rb +8 -4
- data/lib/git/commands/config_option_syntax/remove_section.rb +7 -2
- data/lib/git/commands/config_option_syntax/rename_section.rb +7 -2
- data/lib/git/commands/config_option_syntax/replace_all.rb +7 -2
- data/lib/git/commands/config_option_syntax/set.rb +7 -2
- data/lib/git/commands/config_option_syntax/unset.rb +7 -4
- data/lib/git/commands/config_option_syntax/unset_all.rb +7 -2
- data/lib/git/commands/describe.rb +5 -4
- data/lib/git/commands/diff.rb +13 -12
- data/lib/git/commands/diff_files.rb +7 -6
- data/lib/git/commands/diff_index.rb +10 -7
- data/lib/git/commands/fetch.rb +6 -4
- data/lib/git/commands/fsck.rb +6 -4
- data/lib/git/commands/gc.rb +6 -4
- data/lib/git/commands/grep.rb +6 -5
- data/lib/git/commands/init.rb +6 -4
- data/lib/git/commands/log.rb +287 -285
- data/lib/git/commands/ls_files.rb +69 -65
- data/lib/git/commands/ls_remote.rb +62 -56
- data/lib/git/commands/ls_tree.rb +50 -46
- data/lib/git/commands/maintenance/register.rb +25 -23
- data/lib/git/commands/maintenance/run.rb +7 -2
- data/lib/git/commands/maintenance/start.rb +7 -2
- data/lib/git/commands/maintenance/stop.rb +7 -2
- data/lib/git/commands/maintenance/unregister.rb +7 -2
- data/lib/git/commands/merge/abort.rb +2 -2
- data/lib/git/commands/merge/continue.rb +2 -2
- data/lib/git/commands/merge/quit.rb +2 -2
- data/lib/git/commands/merge/start.rb +7 -2
- data/lib/git/commands/merge.rb +2 -2
- data/lib/git/commands/merge_base.rb +7 -2
- data/lib/git/commands/mv.rb +7 -2
- data/lib/git/commands/name_rev.rb +7 -2
- data/lib/git/commands/pull.rb +7 -2
- data/lib/git/commands/push.rb +7 -2
- data/lib/git/commands/read_tree.rb +7 -2
- data/lib/git/commands/remote/add.rb +7 -2
- data/lib/git/commands/remote/get_url.rb +4 -2
- data/lib/git/commands/remote/list.rb +4 -2
- data/lib/git/commands/remote/prune.rb +4 -2
- data/lib/git/commands/remote/remove.rb +4 -2
- data/lib/git/commands/remote/rename.rb +4 -2
- data/lib/git/commands/remote/set_branches.rb +9 -2
- data/lib/git/commands/remote/set_head.rb +12 -5
- data/lib/git/commands/remote/set_url.rb +9 -2
- data/lib/git/commands/remote/set_url_add.rb +11 -2
- data/lib/git/commands/remote/set_url_delete.rb +9 -2
- data/lib/git/commands/remote/show.rb +18 -12
- data/lib/git/commands/remote/update.rb +19 -12
- data/lib/git/commands/remote.rb +2 -2
- data/lib/git/commands/repack.rb +67 -63
- data/lib/git/commands/reset.rb +51 -44
- data/lib/git/commands/rev_parse.rb +135 -128
- data/lib/git/commands/revert/abort.rb +2 -2
- data/lib/git/commands/revert/continue.rb +7 -2
- data/lib/git/commands/revert/quit.rb +2 -2
- data/lib/git/commands/revert/skip.rb +2 -2
- data/lib/git/commands/revert/start.rb +7 -2
- data/lib/git/commands/revert.rb +2 -2
- data/lib/git/commands/rm.rb +35 -36
- data/lib/git/commands/show.rb +1 -1
- data/lib/git/commands/show_ref/exclude_existing.rb +3 -4
- data/lib/git/commands/show_ref/exists.rb +15 -13
- data/lib/git/commands/show_ref/list.rb +39 -35
- data/lib/git/commands/show_ref/verify.rb +29 -27
- data/lib/git/commands/show_ref.rb +4 -4
- data/lib/git/commands/stash/apply.rb +31 -25
- data/lib/git/commands/stash/branch.rb +10 -8
- data/lib/git/commands/stash/clear.rb +7 -5
- data/lib/git/commands/stash/create.rb +10 -8
- data/lib/git/commands/stash/drop.rb +15 -9
- data/lib/git/commands/stash/list.rb +9 -5
- data/lib/git/commands/stash/pop.rb +21 -12
- data/lib/git/commands/stash/push.rb +20 -11
- data/lib/git/commands/stash/show.rb +21 -12
- data/lib/git/commands/stash/store.rb +19 -10
- data/lib/git/commands/stash.rb +2 -2
- data/lib/git/commands/status.rb +7 -2
- data/lib/git/commands/symbolic_ref/delete.rb +18 -14
- data/lib/git/commands/symbolic_ref/read.rb +24 -20
- data/lib/git/commands/symbolic_ref/update.rb +20 -17
- data/lib/git/commands/symbolic_ref.rb +4 -4
- data/lib/git/commands/tag/create.rb +45 -42
- data/lib/git/commands/tag/delete.rb +5 -3
- data/lib/git/commands/tag/list.rb +47 -44
- data/lib/git/commands/tag/verify.rb +12 -12
- data/lib/git/commands/tag.rb +2 -2
- data/lib/git/commands/update_ref/batch.rb +6 -1
- data/lib/git/commands/update_ref/delete.rb +19 -21
- data/lib/git/commands/update_ref/update.rb +22 -25
- data/lib/git/commands/update_ref.rb +4 -4
- data/lib/git/commands/version.rb +14 -11
- data/lib/git/commands/worktree/add.rb +50 -51
- data/lib/git/commands/worktree/list.rb +17 -17
- data/lib/git/commands/worktree/lock.rb +12 -12
- data/lib/git/commands/worktree/move.rb +16 -16
- data/lib/git/commands/worktree/prune.rb +2 -2
- data/lib/git/commands/worktree/remove.rb +2 -2
- data/lib/git/commands/worktree/repair.rb +2 -2
- data/lib/git/commands/worktree/unlock.rb +2 -2
- data/lib/git/commands/write_tree.rb +2 -2
- data/lib/git/commands.rb +4 -3
- data/lib/git/config.rb +47 -1
- data/lib/git/configuring.rb +89 -15
- data/lib/git/detached_head_info.rb +4 -1
- data/lib/git/diff.rb +2 -5
- data/lib/git/diff_file_numstat_info.rb +3 -1
- data/lib/git/diff_file_patch_info.rb +3 -1
- data/lib/git/diff_file_raw_info.rb +3 -1
- data/lib/git/diff_info.rb +8 -15
- data/lib/git/diff_path_status.rb +16 -3
- data/lib/git/diff_result.rb +3 -1
- data/lib/git/diff_stats.rb +15 -0
- data/lib/git/dirstat_info.rb +24 -8
- data/lib/git/encoding_utils.rb +32 -1
- data/lib/git/errors.rb +19 -9
- data/lib/git/escaped_path.rb +55 -3
- data/lib/git/execution_context/repository.rb +15 -0
- data/lib/git/execution_context.rb +76 -74
- data/lib/git/file_ref.rb +6 -3
- data/lib/git/fsck_object.rb +8 -0
- data/lib/git/fsck_result.rb +26 -15
- data/lib/git/log.rb +152 -5
- data/lib/git/object.rb +284 -8
- data/lib/git/parsers/branch.rb +18 -0
- data/lib/git/parsers/cat_file.rb +2 -2
- data/lib/git/parsers/diff.rb +213 -5
- data/lib/git/parsers/fsck.rb +11 -0
- data/lib/git/parsers/ls_remote.rb +1 -1
- data/lib/git/parsers/stash.rb +51 -0
- data/lib/git/parsers/tag.rb +38 -0
- data/lib/git/remote.rb +34 -2
- data/lib/git/repository/branching.rb +23 -21
- data/lib/git/repository/committing.rb +46 -6
- data/lib/git/repository/context_helpers.rb +45 -16
- data/lib/git/repository/diffing.rb +32 -23
- data/lib/git/repository/factories.rb +153 -28
- data/lib/git/repository/inspecting.rb +1 -1
- data/lib/git/repository/logging.rb +169 -30
- data/lib/git/repository/maintenance.rb +1 -1
- data/lib/git/repository/merging.rb +3 -3
- data/lib/git/repository/object_operations.rb +108 -14
- data/lib/git/repository/remote_operations.rb +150 -171
- data/lib/git/repository/shared_private.rb +7 -5
- data/lib/git/repository/staging.rb +36 -12
- data/lib/git/repository/stashing.rb +16 -16
- data/lib/git/repository/status_operations.rb +1 -1
- data/lib/git/repository/worktree_operations.rb +1 -1
- data/lib/git/repository.rb +287 -6
- data/lib/git/stash.rb +16 -21
- data/lib/git/stash_info.rb +4 -4
- data/lib/git/stashes.rb +20 -26
- data/lib/git/status.rb +25 -13
- data/lib/git/tag_delete_failure.rb +3 -0
- data/lib/git/tag_delete_result.rb +6 -3
- data/lib/git/tag_info.rb +1 -0
- data/lib/git/url.rb +12 -5
- data/lib/git/version.rb +6 -4
- data/lib/git/version_constraint.rb +4 -0
- data/lib/git.rb +400 -314
- data/redesign/3_architecture_implementation.md +81 -30
- data/redesign/Phase 4 - Step A.md +6 -0
- data/redesign/Phase 4 - Step B.md +921 -0
- data/redesign/Phase 4 - Step C.md +833 -0
- data/redesign/c1a-public-api-scope.tsv +256 -0
- data/redesign/phase-4-step-b-test-audit.tsv +485 -0
- data/tasks/yard.rake +24 -17
- metadata +24 -58
- data/commitlint.test +0 -4
- data/lib/git/args_builder.rb +0 -103
- data/lib/git/command_line_result.rb +0 -8
- data/lib/git/deprecation.rb +0 -9
- data/lib/git/repository/configuring.rb +0 -351
- data/tasks/test.rake +0 -25
- /data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -0
- /data/.github/{skills → skills-deprecated}/review-backward-compatibility/SKILL.md +0 -0
data/lib/git/parsers/diff.rb
CHANGED
|
@@ -57,6 +57,8 @@ module Git
|
|
|
57
57
|
# \\{old_dir => new_dir}/file.rb
|
|
58
58
|
# dir/\\{old_name.rb => new_name.rb}
|
|
59
59
|
RENAME_PATTERN = /\A(.+) => (.+)\z/
|
|
60
|
+
|
|
61
|
+
# Brace-expanded rename format from git numstat -M output
|
|
60
62
|
BRACE_RENAME_PATTERN = /\A(.*)\{(.+) => (.+)\}(.*)\z/
|
|
61
63
|
|
|
62
64
|
module_function
|
|
@@ -64,8 +66,11 @@ module Git
|
|
|
64
66
|
# Build a DiffResult from parsed components
|
|
65
67
|
#
|
|
66
68
|
# @param files [Array] array of file info objects
|
|
69
|
+
#
|
|
67
70
|
# @param shortstat [Hash] parsed shortstat data
|
|
71
|
+
#
|
|
68
72
|
# @param dirstat [Git::DirstatInfo, nil] parsed dirstat data
|
|
73
|
+
#
|
|
69
74
|
# @return [Git::DiffResult]
|
|
70
75
|
#
|
|
71
76
|
def build_result(files:, shortstat:, dirstat:)
|
|
@@ -96,6 +101,7 @@ module Git
|
|
|
96
101
|
# # => { files_changed: 3, insertions: 10, deletions: 5 }
|
|
97
102
|
#
|
|
98
103
|
# @param line [String, nil] the shortstat line
|
|
104
|
+
#
|
|
99
105
|
# @return [Hash] { files_changed:, insertions:, deletions: }
|
|
100
106
|
#
|
|
101
107
|
def parse_shortstat(line)
|
|
@@ -115,6 +121,7 @@ module Git
|
|
|
115
121
|
# # => #<Git::DirstatInfo entries: [...]>
|
|
116
122
|
#
|
|
117
123
|
# @param lines [Array<String>] dirstat output lines
|
|
124
|
+
#
|
|
118
125
|
# @return [Git::DirstatInfo]
|
|
119
126
|
#
|
|
120
127
|
def parse_dirstat(lines)
|
|
@@ -129,6 +136,7 @@ module Git
|
|
|
129
136
|
# Parse a stat value (handles '-' for binary files)
|
|
130
137
|
#
|
|
131
138
|
# @param value [String] the stat value string
|
|
139
|
+
#
|
|
132
140
|
# @return [Integer] the numeric value (0 for binary files)
|
|
133
141
|
#
|
|
134
142
|
def parse_stat_value(value)
|
|
@@ -138,6 +146,7 @@ module Git
|
|
|
138
146
|
# Unescape quoted path from git output
|
|
139
147
|
#
|
|
140
148
|
# @param path [String] potentially quoted path
|
|
149
|
+
#
|
|
141
150
|
# @return [String] unescaped path
|
|
142
151
|
#
|
|
143
152
|
def unescape_path(path)
|
|
@@ -153,7 +162,9 @@ module Git
|
|
|
153
162
|
# Parse numstat output into DiffResult
|
|
154
163
|
#
|
|
155
164
|
# @param output [String] raw numstat + shortstat output
|
|
165
|
+
#
|
|
156
166
|
# @param include_dirstat [Boolean] whether dirstat output is expected
|
|
167
|
+
#
|
|
157
168
|
# @return [Git::DiffResult]
|
|
158
169
|
#
|
|
159
170
|
def parse(output, include_dirstat: false)
|
|
@@ -170,6 +181,7 @@ module Git
|
|
|
170
181
|
# Parse numstat lines into DiffFileNumstatInfo array
|
|
171
182
|
#
|
|
172
183
|
# @param lines [Array<String>] numstat lines
|
|
184
|
+
#
|
|
173
185
|
# @return [Array<Git::DiffFileNumstatInfo>]
|
|
174
186
|
#
|
|
175
187
|
def parse_file_stats(lines)
|
|
@@ -188,7 +200,9 @@ module Git
|
|
|
188
200
|
# Parse numstat lines into a path -> stats hash (for combining with other formats)
|
|
189
201
|
#
|
|
190
202
|
# @param lines [Array<String>] numstat lines
|
|
203
|
+
#
|
|
191
204
|
# @param include_binary [Boolean] whether to include binary flag
|
|
205
|
+
#
|
|
192
206
|
# @return [Hash<String, Hash>] path to stats mapping (keyed by destination path)
|
|
193
207
|
#
|
|
194
208
|
def parse_as_map(lines, include_binary: false)
|
|
@@ -200,6 +214,16 @@ module Git
|
|
|
200
214
|
end
|
|
201
215
|
end
|
|
202
216
|
|
|
217
|
+
# Builds stats data from a numstat entry
|
|
218
|
+
#
|
|
219
|
+
# @param insertions_s [String] insertions field from numstat output
|
|
220
|
+
#
|
|
221
|
+
# @param deletions_s [String] deletions field from numstat output
|
|
222
|
+
#
|
|
223
|
+
# @param include_binary [Boolean] whether to include the `:binary` key
|
|
224
|
+
#
|
|
225
|
+
# @return [Hash] stats hash with insertion and deletion totals
|
|
226
|
+
#
|
|
203
227
|
def build_stats(insertions_s, deletions_s, include_binary)
|
|
204
228
|
stats = { insertions: Diff.parse_stat_value(insertions_s),
|
|
205
229
|
deletions: Diff.parse_stat_value(deletions_s) }
|
|
@@ -210,7 +234,9 @@ module Git
|
|
|
210
234
|
# Split output into numstat, shortstat, and dirstat sections
|
|
211
235
|
#
|
|
212
236
|
# @param lines [Array<String>] all output lines
|
|
237
|
+
#
|
|
213
238
|
# @param include_dirstat [Boolean] whether to expect dirstat section
|
|
239
|
+
#
|
|
214
240
|
# @return [Array] [numstat_lines, shortstat_line, dirstat_lines]
|
|
215
241
|
#
|
|
216
242
|
def split_sections(lines, include_dirstat)
|
|
@@ -224,7 +250,8 @@ module Git
|
|
|
224
250
|
# Parse potential rename path into [dst_path, src_path]
|
|
225
251
|
#
|
|
226
252
|
# @param filename [String] the path string from numstat output
|
|
227
|
-
#
|
|
253
|
+
#
|
|
254
|
+
# @return [Array(String, (String, nil))] [destination_path, source_path_or_nil]
|
|
228
255
|
#
|
|
229
256
|
def parse_rename_path(filename)
|
|
230
257
|
if (match = filename.match(BRACE_RENAME_PATTERN))
|
|
@@ -245,7 +272,9 @@ module Git
|
|
|
245
272
|
# Parse combined raw + numstat + shortstat output into DiffResult
|
|
246
273
|
#
|
|
247
274
|
# @param output [String] combined output
|
|
275
|
+
#
|
|
248
276
|
# @param include_dirstat [Boolean] whether dirstat output is expected
|
|
277
|
+
#
|
|
249
278
|
# @return [Git::DiffResult]
|
|
250
279
|
#
|
|
251
280
|
def parse(output, include_dirstat: false)
|
|
@@ -262,8 +291,10 @@ module Git
|
|
|
262
291
|
# Split output into raw, numstat, shortstat, and dirstat sections
|
|
263
292
|
#
|
|
264
293
|
# @param output [String] combined output
|
|
294
|
+
#
|
|
265
295
|
# @param include_dirstat [Boolean] whether to expect dirstat section
|
|
266
|
-
#
|
|
296
|
+
#
|
|
297
|
+
# @return [Array(Array<String>, Array<String>, (String, nil), Array<String>)]
|
|
267
298
|
#
|
|
268
299
|
def split_sections(output, include_dirstat)
|
|
269
300
|
lines = output.split("\n").reject(&:empty?)
|
|
@@ -279,7 +310,9 @@ module Git
|
|
|
279
310
|
# Parse a single --raw output line
|
|
280
311
|
#
|
|
281
312
|
# @param line [String] a single raw output line
|
|
313
|
+
#
|
|
282
314
|
# @param numstat_map [Hash<String, Hash>] path to stats mapping
|
|
315
|
+
#
|
|
283
316
|
# @return [Git::DiffFileRawInfo]
|
|
284
317
|
#
|
|
285
318
|
def parse_raw_line(line, numstat_map)
|
|
@@ -289,6 +322,12 @@ module Git
|
|
|
289
322
|
build_raw_info(parsed, stats)
|
|
290
323
|
end
|
|
291
324
|
|
|
325
|
+
# Parses the fields from a raw diff line
|
|
326
|
+
#
|
|
327
|
+
# @param line [String] a single raw output line
|
|
328
|
+
#
|
|
329
|
+
# @return [Hash] parsed metadata for one raw diff entry
|
|
330
|
+
#
|
|
292
331
|
def parse_raw_line_parts(line)
|
|
293
332
|
parts = line[1..].split(/\s+/, 5)
|
|
294
333
|
status_char, *paths = parts[4].split("\t")
|
|
@@ -298,6 +337,14 @@ module Git
|
|
|
298
337
|
similarity: similarity, src_path: src_path, dst_path: dst_path }
|
|
299
338
|
end
|
|
300
339
|
|
|
340
|
+
# Builds a raw diff file info object from parsed metadata and stats
|
|
341
|
+
#
|
|
342
|
+
# @param parsed [Hash] parsed metadata from {#parse_raw_line_parts}
|
|
343
|
+
#
|
|
344
|
+
# @param stats [Hash] insertion, deletion, and binary information
|
|
345
|
+
#
|
|
346
|
+
# @return [Git::DiffFileRawInfo]
|
|
347
|
+
#
|
|
301
348
|
def build_raw_info(parsed, stats)
|
|
302
349
|
Git::DiffFileRawInfo.new(
|
|
303
350
|
src: build_file_ref(parsed[:modes][0], parsed[:shas][0], parsed[:src_path]),
|
|
@@ -309,7 +356,8 @@ module Git
|
|
|
309
356
|
# Parse status character and optional similarity percentage
|
|
310
357
|
#
|
|
311
358
|
# @param status_char [String] e.g., 'M', 'A', 'R075'
|
|
312
|
-
#
|
|
359
|
+
#
|
|
360
|
+
# @return [Array(Symbol, (Integer, nil))] [status, similarity]
|
|
313
361
|
#
|
|
314
362
|
def parse_status(status_char)
|
|
315
363
|
letter = status_char[0]
|
|
@@ -320,7 +368,8 @@ module Git
|
|
|
320
368
|
# Extract source and destination paths from raw output paths
|
|
321
369
|
#
|
|
322
370
|
# @param paths [Array<String>] paths array
|
|
323
|
-
#
|
|
371
|
+
#
|
|
372
|
+
# @return [Array((String, nil), (String, nil))] [src_path, dst_path]
|
|
324
373
|
#
|
|
325
374
|
def extract_paths(paths)
|
|
326
375
|
if paths.length == 2
|
|
@@ -334,8 +383,11 @@ module Git
|
|
|
334
383
|
# Build a FileRef, returning nil if the file doesn't exist on this side
|
|
335
384
|
#
|
|
336
385
|
# @param mode [String] file mode
|
|
386
|
+
#
|
|
337
387
|
# @param sha [String] file SHA
|
|
388
|
+
#
|
|
338
389
|
# @param path [String, nil] file path
|
|
390
|
+
#
|
|
339
391
|
# @return [Git::FileRef, nil]
|
|
340
392
|
#
|
|
341
393
|
def build_file_ref(mode, sha, path)
|
|
@@ -347,19 +399,43 @@ module Git
|
|
|
347
399
|
|
|
348
400
|
# Parser for --patch output (combined with numstat)
|
|
349
401
|
module Patch
|
|
402
|
+
# Header line pattern for each patch file section
|
|
350
403
|
DIFF_HEADER_PATTERN = %r{\Adiff --git ("?)a/(.+?)\1 ("?)b/(.+?)\3\z}
|
|
404
|
+
|
|
405
|
+
# Index line pattern with source/destination SHAs and optional mode
|
|
351
406
|
INDEX_PATTERN = /^index ([0-9a-f]{4,40})\.\.([0-9a-f]{4,40})( ......)?/
|
|
407
|
+
|
|
408
|
+
# File mode line pattern for file creation and deletion
|
|
352
409
|
FILE_MODE_PATTERN = /^(new|deleted) file mode (......)/
|
|
410
|
+
|
|
411
|
+
# Old mode line pattern for mode changes
|
|
353
412
|
OLD_MODE_PATTERN = /^old mode (......)/
|
|
413
|
+
|
|
414
|
+
# New mode line pattern for mode changes
|
|
354
415
|
NEW_MODE_PATTERN = /^new mode (......)/
|
|
416
|
+
|
|
417
|
+
# Binary patch marker line pattern
|
|
355
418
|
BINARY_PATTERN = /^Binary files /
|
|
419
|
+
|
|
420
|
+
# Git binary patch header line pattern
|
|
356
421
|
GIT_BINARY_PATCH_PATTERN = /^GIT binary patch$/
|
|
422
|
+
|
|
423
|
+
# Rename source path line pattern
|
|
357
424
|
RENAME_FROM_PATTERN = /^rename from (.+)$/
|
|
425
|
+
|
|
426
|
+
# Rename destination path line pattern
|
|
358
427
|
RENAME_TO_PATTERN = /^rename to (.+)$/
|
|
428
|
+
|
|
429
|
+
# Copy source path line pattern
|
|
359
430
|
COPY_FROM_PATTERN = /^copy from (.+)$/
|
|
431
|
+
|
|
432
|
+
# Copy destination path line pattern
|
|
360
433
|
COPY_TO_PATTERN = /^copy to (.+)$/
|
|
434
|
+
|
|
435
|
+
# Similarity percentage line pattern
|
|
361
436
|
SIMILARITY_PATTERN = /^similarity index (\d+)%$/
|
|
362
437
|
|
|
438
|
+
# Maps patch metadata status words to diff status symbols
|
|
363
439
|
PATCH_STATUS_MAP = {
|
|
364
440
|
'new' => :added,
|
|
365
441
|
'deleted' => :deleted,
|
|
@@ -374,7 +450,9 @@ module Git
|
|
|
374
450
|
# Parse combined patch + numstat + shortstat output into DiffResult
|
|
375
451
|
#
|
|
376
452
|
# @param output [String] combined output
|
|
453
|
+
#
|
|
377
454
|
# @param include_dirstat [Boolean] whether dirstat output is expected
|
|
455
|
+
#
|
|
378
456
|
# @return [Git::DiffResult]
|
|
379
457
|
#
|
|
380
458
|
def parse(output, include_dirstat: false)
|
|
@@ -393,8 +471,10 @@ module Git
|
|
|
393
471
|
# Split output into numstat, shortstat, dirstat, and patch sections
|
|
394
472
|
#
|
|
395
473
|
# @param output [String] combined output
|
|
474
|
+
#
|
|
396
475
|
# @param include_dirstat [Boolean] whether to expect dirstat section
|
|
397
|
-
#
|
|
476
|
+
#
|
|
477
|
+
# @return [Array(Array<String>, (String, nil), Array<String>, String)]
|
|
398
478
|
#
|
|
399
479
|
def split_sections(output, include_dirstat)
|
|
400
480
|
lines = output.lines
|
|
@@ -404,6 +484,16 @@ module Git
|
|
|
404
484
|
split_pre_diff(pre_diff_lines, include_dirstat, patch_text)
|
|
405
485
|
end
|
|
406
486
|
|
|
487
|
+
# Splits pre-patch lines into numstat, shortstat, and dirstat sections
|
|
488
|
+
#
|
|
489
|
+
# @param pre_diff_lines [Array<String>] lines before the first diff header
|
|
490
|
+
#
|
|
491
|
+
# @param include_dirstat [Boolean] whether dirstat output is expected
|
|
492
|
+
#
|
|
493
|
+
# @param patch_text [String] patch text starting at the first diff header
|
|
494
|
+
#
|
|
495
|
+
# @return [Array(Array<String>, (String, nil), Array<String>, String)]
|
|
496
|
+
#
|
|
407
497
|
def split_pre_diff(pre_diff_lines, include_dirstat, patch_text)
|
|
408
498
|
shortstat_index = pre_diff_lines.index { |l| l.match?(/^\s*\d+\s+files?\s+changed/) }
|
|
409
499
|
return [pre_diff_lines, nil, [], patch_text] unless shortstat_index
|
|
@@ -413,10 +503,17 @@ module Git
|
|
|
413
503
|
end
|
|
414
504
|
|
|
415
505
|
# Methods for parsing patch metadata lines (index, mode, rename, etc.)
|
|
506
|
+
#
|
|
416
507
|
# @api private
|
|
417
508
|
module PatchMetadataParser
|
|
418
509
|
private
|
|
419
510
|
|
|
511
|
+
# Parses a metadata line for the current patch file
|
|
512
|
+
#
|
|
513
|
+
# @param line [String] a metadata line from the patch block
|
|
514
|
+
#
|
|
515
|
+
# @return [void]
|
|
516
|
+
#
|
|
420
517
|
def parse_metadata_line(line)
|
|
421
518
|
try_parse_index(line)
|
|
422
519
|
try_parse_file_mode(line)
|
|
@@ -426,6 +523,12 @@ module Git
|
|
|
426
523
|
try_mark_binary(line)
|
|
427
524
|
end
|
|
428
525
|
|
|
526
|
+
# Parses index metadata and updates mode defaults when present
|
|
527
|
+
#
|
|
528
|
+
# @param line [String] a metadata line from the patch block
|
|
529
|
+
#
|
|
530
|
+
# @return [void]
|
|
531
|
+
#
|
|
429
532
|
def try_parse_index(line)
|
|
430
533
|
return unless (match = line.match(INDEX_PATTERN))
|
|
431
534
|
|
|
@@ -437,6 +540,12 @@ module Git
|
|
|
437
540
|
@current_file[:src_mode] = @current_file[:dst_mode] = mode
|
|
438
541
|
end
|
|
439
542
|
|
|
543
|
+
# Parses file creation and deletion mode lines
|
|
544
|
+
#
|
|
545
|
+
# @param line [String] a metadata line from the patch block
|
|
546
|
+
#
|
|
547
|
+
# @return [void]
|
|
548
|
+
#
|
|
440
549
|
def try_parse_file_mode(line)
|
|
441
550
|
return unless (match = line.match(FILE_MODE_PATTERN))
|
|
442
551
|
|
|
@@ -445,6 +554,12 @@ module Git
|
|
|
445
554
|
apply_file_mode(type, mode)
|
|
446
555
|
end
|
|
447
556
|
|
|
557
|
+
# Parses old/new mode lines and detects type changes
|
|
558
|
+
#
|
|
559
|
+
# @param line [String] a metadata line from the patch block
|
|
560
|
+
#
|
|
561
|
+
# @return [void]
|
|
562
|
+
#
|
|
448
563
|
def try_parse_old_new_mode(line)
|
|
449
564
|
if (match = line.match(OLD_MODE_PATTERN))
|
|
450
565
|
@current_file[:src_mode] = match[1]
|
|
@@ -455,6 +570,10 @@ module Git
|
|
|
455
570
|
end
|
|
456
571
|
end
|
|
457
572
|
|
|
573
|
+
# Marks the current entry as a type change when type bits differ
|
|
574
|
+
#
|
|
575
|
+
# @return [void]
|
|
576
|
+
#
|
|
458
577
|
def detect_type_change
|
|
459
578
|
src_mode = @current_file[:src_mode]
|
|
460
579
|
dst_mode = @current_file[:dst_mode]
|
|
@@ -465,6 +584,14 @@ module Git
|
|
|
465
584
|
@current_file[:status] = :type_changed if src_mode[0, 3] != dst_mode[0, 3]
|
|
466
585
|
end
|
|
467
586
|
|
|
587
|
+
# Applies source or destination mode updates based on file operation type
|
|
588
|
+
#
|
|
589
|
+
# @param type [String] operation type (`'new'` or `'deleted'`)
|
|
590
|
+
#
|
|
591
|
+
# @param mode [String] file mode from patch metadata
|
|
592
|
+
#
|
|
593
|
+
# @return [void]
|
|
594
|
+
#
|
|
468
595
|
def apply_file_mode(type, mode)
|
|
469
596
|
case type
|
|
470
597
|
when 'new'
|
|
@@ -476,11 +603,29 @@ module Git
|
|
|
476
603
|
end
|
|
477
604
|
end
|
|
478
605
|
|
|
606
|
+
# Parses rename or copy metadata for the current patch file
|
|
607
|
+
#
|
|
608
|
+
# @param line [String] a metadata line from the patch block
|
|
609
|
+
#
|
|
610
|
+
# @return [Symbol, nil] parsed status when a rename or copy line matches
|
|
611
|
+
#
|
|
479
612
|
def try_parse_rename(line)
|
|
480
613
|
try_parse_rename_or_copy(line, RENAME_FROM_PATTERN, RENAME_TO_PATTERN, :renamed) ||
|
|
481
614
|
try_parse_rename_or_copy(line, COPY_FROM_PATTERN, COPY_TO_PATTERN, :copied)
|
|
482
615
|
end
|
|
483
616
|
|
|
617
|
+
# Parses one side of rename or copy metadata
|
|
618
|
+
#
|
|
619
|
+
# @param line [String] a metadata line from the patch block
|
|
620
|
+
#
|
|
621
|
+
# @param from_pattern [Regexp] pattern for source path lines
|
|
622
|
+
#
|
|
623
|
+
# @param to_pattern [Regexp] pattern for destination path lines
|
|
624
|
+
#
|
|
625
|
+
# @param status [Symbol] status to set when a pattern matches
|
|
626
|
+
#
|
|
627
|
+
# @return [Symbol, nil] the assigned status when matched
|
|
628
|
+
#
|
|
484
629
|
def try_parse_rename_or_copy(line, from_pattern, to_pattern, status)
|
|
485
630
|
if (match = line.match(from_pattern))
|
|
486
631
|
@current_file[:src_path] = Diff.unescape_path(match[1])
|
|
@@ -491,22 +636,43 @@ module Git
|
|
|
491
636
|
end
|
|
492
637
|
end
|
|
493
638
|
|
|
639
|
+
# Parses similarity index metadata
|
|
640
|
+
#
|
|
641
|
+
# @param line [String] a metadata line from the patch block
|
|
642
|
+
#
|
|
643
|
+
# @return [Integer, nil] parsed similarity percentage when matched
|
|
644
|
+
#
|
|
494
645
|
def try_parse_similarity(line)
|
|
495
646
|
return unless (match = line.match(SIMILARITY_PATTERN))
|
|
496
647
|
|
|
497
648
|
@current_file[:similarity] = match[1].to_i
|
|
498
649
|
end
|
|
499
650
|
|
|
651
|
+
# Marks the current file as binary when binary markers are present
|
|
652
|
+
#
|
|
653
|
+
# @param line [String] a metadata line from the patch block
|
|
654
|
+
#
|
|
655
|
+
# @return [Boolean, nil] true when binary metadata is detected
|
|
656
|
+
#
|
|
500
657
|
def try_mark_binary(line)
|
|
501
658
|
@current_file[:binary] = true if line.match?(BINARY_PATTERN) || line.match?(GIT_BINARY_PATCH_PATTERN)
|
|
502
659
|
end
|
|
503
660
|
end
|
|
504
661
|
|
|
505
662
|
# Stateful parser for unified diff patch output
|
|
663
|
+
#
|
|
506
664
|
# @api private
|
|
507
665
|
class PatchFileParser
|
|
508
666
|
include PatchMetadataParser
|
|
509
667
|
|
|
668
|
+
# Initializes parser state for a patch text block
|
|
669
|
+
#
|
|
670
|
+
# @param patch_text [String] unified diff patch text
|
|
671
|
+
#
|
|
672
|
+
# @param numstat_map [Hash<String, Hash>] path to insert/delete stats
|
|
673
|
+
#
|
|
674
|
+
# @return [void]
|
|
675
|
+
#
|
|
510
676
|
def initialize(patch_text, numstat_map = {})
|
|
511
677
|
@patch_text = patch_text
|
|
512
678
|
@numstat_map = numstat_map
|
|
@@ -514,6 +680,10 @@ module Git
|
|
|
514
680
|
@current_file = nil
|
|
515
681
|
end
|
|
516
682
|
|
|
683
|
+
# Parses patch text into file patch info objects
|
|
684
|
+
#
|
|
685
|
+
# @return [Array<Git::DiffFilePatchInfo>]
|
|
686
|
+
#
|
|
517
687
|
def parse
|
|
518
688
|
@patch_text.split("\n").each { |line| process_line(line) }
|
|
519
689
|
finalize_current_file
|
|
@@ -522,6 +692,12 @@ module Git
|
|
|
522
692
|
|
|
523
693
|
private
|
|
524
694
|
|
|
695
|
+
# Processes one patch line and updates parser state
|
|
696
|
+
#
|
|
697
|
+
# @param line [String] a single line from patch text
|
|
698
|
+
#
|
|
699
|
+
# @return [void]
|
|
700
|
+
#
|
|
525
701
|
def process_line(line)
|
|
526
702
|
if (match = line.match(DIFF_HEADER_PATTERN))
|
|
527
703
|
start_new_file(match, line)
|
|
@@ -530,6 +706,14 @@ module Git
|
|
|
530
706
|
end
|
|
531
707
|
end
|
|
532
708
|
|
|
709
|
+
# Starts a new file section from a `diff --git` header
|
|
710
|
+
#
|
|
711
|
+
# @param match [MatchData] parsed header match for current diff file
|
|
712
|
+
#
|
|
713
|
+
# @param line [String] raw `diff --git` header line
|
|
714
|
+
#
|
|
715
|
+
# @return [void]
|
|
716
|
+
#
|
|
533
717
|
def start_new_file(match, line)
|
|
534
718
|
finalize_current_file
|
|
535
719
|
@current_file = default_file_state.merge(
|
|
@@ -539,16 +723,30 @@ module Git
|
|
|
539
723
|
)
|
|
540
724
|
end
|
|
541
725
|
|
|
726
|
+
# Builds the default state hash for a new patch file entry
|
|
727
|
+
#
|
|
728
|
+
# @return [Hash] default metadata for an in-progress file parse
|
|
729
|
+
#
|
|
542
730
|
def default_file_state
|
|
543
731
|
{ src_mode: nil, dst_mode: nil, src_sha: '', dst_sha: '',
|
|
544
732
|
src_path: nil, dst_path: nil, status: :modified, similarity: nil, binary: false }
|
|
545
733
|
end
|
|
546
734
|
|
|
735
|
+
# Appends metadata and patch text to the current file entry
|
|
736
|
+
#
|
|
737
|
+
# @param line [String] a metadata or patch content line
|
|
738
|
+
#
|
|
739
|
+
# @return [void]
|
|
740
|
+
#
|
|
547
741
|
def append_to_current_file(line)
|
|
548
742
|
parse_metadata_line(line)
|
|
549
743
|
@current_file[:patch] = "#{@current_file[:patch]}\n#{line}"
|
|
550
744
|
end
|
|
551
745
|
|
|
746
|
+
# Finalizes and stores the current file entry
|
|
747
|
+
#
|
|
748
|
+
# @return [void]
|
|
749
|
+
#
|
|
552
750
|
def finalize_current_file
|
|
553
751
|
return unless @current_file
|
|
554
752
|
|
|
@@ -556,6 +754,10 @@ module Git
|
|
|
556
754
|
@current_file = nil
|
|
557
755
|
end
|
|
558
756
|
|
|
757
|
+
# Builds a finalized patch info object for the current file
|
|
758
|
+
#
|
|
759
|
+
# @return [Git::DiffFilePatchInfo]
|
|
760
|
+
#
|
|
559
761
|
def build_patch_info
|
|
560
762
|
path = @current_file[:dst_path] || @current_file[:src_path]
|
|
561
763
|
stats = @numstat_map.fetch(path, { insertions: 0, deletions: 0 })
|
|
@@ -568,6 +770,12 @@ module Git
|
|
|
568
770
|
)
|
|
569
771
|
end
|
|
570
772
|
|
|
773
|
+
# Builds a file reference for one side of the diff entry
|
|
774
|
+
#
|
|
775
|
+
# @param side [Symbol] diff side key (`:src` or `:dst`)
|
|
776
|
+
#
|
|
777
|
+
# @return [Git::FileRef, nil]
|
|
778
|
+
#
|
|
571
779
|
def build_file_ref(side)
|
|
572
780
|
path = @current_file[:"#{side}_path"]
|
|
573
781
|
return nil if path.nil?
|
data/lib/git/parsers/fsck.rb
CHANGED
|
@@ -60,6 +60,7 @@ module Git
|
|
|
60
60
|
# # => #<Git::FsckResult dangling: [...], missing: [...]>
|
|
61
61
|
#
|
|
62
62
|
# @param stdout [String] output from git fsck command
|
|
63
|
+
#
|
|
63
64
|
# @return [Git::FsckResult] the parsed result
|
|
64
65
|
#
|
|
65
66
|
def parse(stdout)
|
|
@@ -71,7 +72,9 @@ module Git
|
|
|
71
72
|
# Parse a single line of fsck output
|
|
72
73
|
#
|
|
73
74
|
# @param line [String] a line of output
|
|
75
|
+
#
|
|
74
76
|
# @param result [Hash] the result hash to populate
|
|
77
|
+
#
|
|
75
78
|
# @return [Boolean] true if the line was parsed
|
|
76
79
|
#
|
|
77
80
|
def parse_line(line, result)
|
|
@@ -84,7 +87,9 @@ module Git
|
|
|
84
87
|
# Parse a dangling/missing/unreachable object line
|
|
85
88
|
#
|
|
86
89
|
# @param line [String] a line of output
|
|
90
|
+
#
|
|
87
91
|
# @param result [Hash] the result hash to populate
|
|
92
|
+
#
|
|
88
93
|
# @return [Boolean] true if the line was parsed
|
|
89
94
|
#
|
|
90
95
|
def parse_object_line(line, result)
|
|
@@ -96,7 +101,9 @@ module Git
|
|
|
96
101
|
# Parse a warning line
|
|
97
102
|
#
|
|
98
103
|
# @param line [String] a line of output
|
|
104
|
+
#
|
|
99
105
|
# @param result [Hash] the result hash to populate
|
|
106
|
+
#
|
|
100
107
|
# @return [Boolean] true if the line was parsed
|
|
101
108
|
#
|
|
102
109
|
def parse_warning_line(line, result)
|
|
@@ -108,7 +115,9 @@ module Git
|
|
|
108
115
|
# Parse a root line
|
|
109
116
|
#
|
|
110
117
|
# @param line [String] a line of output
|
|
118
|
+
#
|
|
111
119
|
# @param result [Hash] the result hash to populate
|
|
120
|
+
#
|
|
112
121
|
# @return [Boolean] true if the line was parsed
|
|
113
122
|
#
|
|
114
123
|
def parse_root_line(line, result)
|
|
@@ -120,7 +129,9 @@ module Git
|
|
|
120
129
|
# Parse a tagged line
|
|
121
130
|
#
|
|
122
131
|
# @param line [String] a line of output
|
|
132
|
+
#
|
|
123
133
|
# @param result [Hash] the result hash to populate
|
|
134
|
+
#
|
|
124
135
|
# @return [Boolean] true if the line was parsed
|
|
125
136
|
#
|
|
126
137
|
def parse_tagged_line(line, result)
|
|
@@ -36,7 +36,7 @@ module Git
|
|
|
36
36
|
#
|
|
37
37
|
# @param line [String] a single line from ls-remote stdout
|
|
38
38
|
#
|
|
39
|
-
# @return [Array(String, String
|
|
39
|
+
# @return [Array(String, (String, nil), Hash)] `[type, name, value]` where
|
|
40
40
|
# `value` is `{ ref: String, sha: String }`
|
|
41
41
|
#
|
|
42
42
|
# @raise [Git::UnexpectedResultError] if the line is not in `<sha>\t<ref>` format
|