git 4.3.2 → 5.0.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. checksums.yaml +4 -4
  2. data/.github/copilot-instructions.md +67 -2705
  3. data/.github/pull_request_template.md +3 -1
  4. data/.github/skills/breaking-change-analysis/SKILL.md +102 -0
  5. data/.github/skills/ci-cd-troubleshooting/SKILL.md +264 -0
  6. data/.github/skills/command-implementation/REFERENCE.md +993 -0
  7. data/.github/skills/command-implementation/SKILL.md +229 -0
  8. data/.github/skills/command-test-conventions/SKILL.md +660 -0
  9. data/.github/skills/command-yard-documentation/SKILL.md +426 -0
  10. data/.github/skills/dependency-management/SKILL.md +72 -0
  11. data/.github/skills/development-workflow/SKILL.md +506 -0
  12. data/.github/skills/extract-command-from-lib/SKILL.md +487 -0
  13. data/.github/skills/extract-facade-from-base-lib/SKILL.md +586 -0
  14. data/.github/skills/facade-implementation/REFERENCE.md +840 -0
  15. data/.github/skills/facade-implementation/SKILL.md +260 -0
  16. data/.github/skills/facade-test-conventions/SKILL.md +380 -0
  17. data/.github/skills/facade-yard-documentation/SKILL.md +429 -0
  18. data/.github/skills/make-skill-template/SKILL.md +176 -0
  19. data/.github/skills/pr-readiness-review/SKILL.md +185 -0
  20. data/.github/skills/project-context/SKILL.md +313 -0
  21. data/.github/skills/pull-request-review/SKILL.md +168 -0
  22. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +131 -0
  23. data/.github/skills/release-management/SKILL.md +125 -0
  24. data/.github/skills/review-arguments-dsl/CHECKLIST.md +788 -0
  25. data/.github/skills/review-arguments-dsl/SKILL.md +214 -0
  26. data/.github/skills/review-backward-compatibility/SKILL.md +275 -0
  27. data/.github/skills/review-cross-command-consistency/SKILL.md +139 -0
  28. data/.github/skills/reviewing-skills/SKILL.md +189 -0
  29. data/.github/skills/rspec-unit-testing-standards/SKILL.md +639 -0
  30. data/.github/skills/tdd-refactor-step/SKILL.md +236 -0
  31. data/.github/skills/test-debugging/SKILL.md +160 -0
  32. data/.github/skills/yard-documentation/SKILL.md +793 -0
  33. data/.github/workflows/continuous_integration.yml +3 -2
  34. data/.github/workflows/enforce_conventional_commits.yml +1 -1
  35. data/.github/workflows/experimental_continuous_integration.yml +2 -2
  36. data/.github/workflows/release.yml +3 -4
  37. data/.gitignore +8 -0
  38. data/.husky/pre-commit +13 -0
  39. data/.release-please-manifest.json +1 -1
  40. data/.rspec +3 -0
  41. data/.rubocop.yml +7 -3
  42. data/.rubocop_todo.yml +23 -5
  43. data/.yardopts +1 -0
  44. data/CHANGELOG.md +0 -40
  45. data/CONTRIBUTING.md +694 -53
  46. data/README.md +17 -5
  47. data/Rakefile +61 -9
  48. data/commitlint.test +4 -0
  49. data/git.gemspec +14 -8
  50. data/lib/git/args_builder.rb +0 -8
  51. data/lib/git/base.rb +486 -410
  52. data/lib/git/branch.rb +380 -43
  53. data/lib/git/branch_delete_failure.rb +31 -0
  54. data/lib/git/branch_delete_result.rb +63 -0
  55. data/lib/git/branch_info.rb +178 -0
  56. data/lib/git/branches.rb +130 -24
  57. data/lib/git/command_line/base.rb +245 -0
  58. data/lib/git/command_line/capturing.rb +249 -0
  59. data/lib/git/command_line/result.rb +96 -0
  60. data/lib/git/command_line/streaming.rb +194 -0
  61. data/lib/git/command_line.rb +43 -322
  62. data/lib/git/command_line_result.rb +4 -88
  63. data/lib/git/commands/add.rb +131 -0
  64. data/lib/git/commands/am/abort.rb +43 -0
  65. data/lib/git/commands/am/apply.rb +252 -0
  66. data/lib/git/commands/am/continue.rb +43 -0
  67. data/lib/git/commands/am/quit.rb +43 -0
  68. data/lib/git/commands/am/retry.rb +47 -0
  69. data/lib/git/commands/am/show_current_patch.rb +64 -0
  70. data/lib/git/commands/am/skip.rb +42 -0
  71. data/lib/git/commands/am.rb +33 -0
  72. data/lib/git/commands/apply.rb +237 -0
  73. data/lib/git/commands/archive/list_formats.rb +46 -0
  74. data/lib/git/commands/archive.rb +140 -0
  75. data/lib/git/commands/arguments.rb +3510 -0
  76. data/lib/git/commands/base.rb +403 -0
  77. data/lib/git/commands/branch/copy.rb +94 -0
  78. data/lib/git/commands/branch/create.rb +173 -0
  79. data/lib/git/commands/branch/delete.rb +80 -0
  80. data/lib/git/commands/branch/list.rb +162 -0
  81. data/lib/git/commands/branch/move.rb +94 -0
  82. data/lib/git/commands/branch/set_upstream.rb +86 -0
  83. data/lib/git/commands/branch/show_current.rb +49 -0
  84. data/lib/git/commands/branch/unset_upstream.rb +57 -0
  85. data/lib/git/commands/branch.rb +34 -0
  86. data/lib/git/commands/cat_file/batch.rb +364 -0
  87. data/lib/git/commands/cat_file/filtered.rb +105 -0
  88. data/lib/git/commands/cat_file/raw.rb +210 -0
  89. data/lib/git/commands/cat_file.rb +49 -0
  90. data/lib/git/commands/checkout/branch.rb +151 -0
  91. data/lib/git/commands/checkout/files.rb +115 -0
  92. data/lib/git/commands/checkout.rb +38 -0
  93. data/lib/git/commands/checkout_index.rb +105 -0
  94. data/lib/git/commands/clean.rb +100 -0
  95. data/lib/git/commands/clone.rb +240 -0
  96. data/lib/git/commands/commit.rb +272 -0
  97. data/lib/git/commands/commit_tree.rb +100 -0
  98. data/lib/git/commands/config_option_syntax/add.rb +83 -0
  99. data/lib/git/commands/config_option_syntax/get.rb +117 -0
  100. data/lib/git/commands/config_option_syntax/get_all.rb +115 -0
  101. data/lib/git/commands/config_option_syntax/get_color.rb +91 -0
  102. data/lib/git/commands/config_option_syntax/get_color_bool.rb +93 -0
  103. data/lib/git/commands/config_option_syntax/get_regexp.rb +115 -0
  104. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +102 -0
  105. data/lib/git/commands/config_option_syntax/list.rb +107 -0
  106. data/lib/git/commands/config_option_syntax/remove_section.rb +74 -0
  107. data/lib/git/commands/config_option_syntax/rename_section.rb +78 -0
  108. data/lib/git/commands/config_option_syntax/replace_all.rb +104 -0
  109. data/lib/git/commands/config_option_syntax/set.rb +114 -0
  110. data/lib/git/commands/config_option_syntax/unset.rb +89 -0
  111. data/lib/git/commands/config_option_syntax/unset_all.rb +89 -0
  112. data/lib/git/commands/config_option_syntax.rb +56 -0
  113. data/lib/git/commands/describe.rb +155 -0
  114. data/lib/git/commands/diff.rb +656 -0
  115. data/lib/git/commands/diff_files.rb +518 -0
  116. data/lib/git/commands/diff_index.rb +496 -0
  117. data/lib/git/commands/fetch.rb +352 -0
  118. data/lib/git/commands/fsck.rb +136 -0
  119. data/lib/git/commands/gc.rb +132 -0
  120. data/lib/git/commands/grep.rb +338 -0
  121. data/lib/git/commands/init.rb +99 -0
  122. data/lib/git/commands/log.rb +632 -0
  123. data/lib/git/commands/ls_files.rb +191 -0
  124. data/lib/git/commands/ls_remote.rb +155 -0
  125. data/lib/git/commands/ls_tree.rb +131 -0
  126. data/lib/git/commands/maintenance/register.rb +75 -0
  127. data/lib/git/commands/maintenance/run.rb +104 -0
  128. data/lib/git/commands/maintenance/start.rb +66 -0
  129. data/lib/git/commands/maintenance/stop.rb +55 -0
  130. data/lib/git/commands/maintenance/unregister.rb +79 -0
  131. data/lib/git/commands/maintenance.rb +31 -0
  132. data/lib/git/commands/merge/abort.rb +44 -0
  133. data/lib/git/commands/merge/continue.rb +44 -0
  134. data/lib/git/commands/merge/quit.rb +46 -0
  135. data/lib/git/commands/merge/start.rb +245 -0
  136. data/lib/git/commands/merge.rb +28 -0
  137. data/lib/git/commands/merge_base.rb +86 -0
  138. data/lib/git/commands/mv.rb +77 -0
  139. data/lib/git/commands/name_rev.rb +114 -0
  140. data/lib/git/commands/pull.rb +377 -0
  141. data/lib/git/commands/push.rb +246 -0
  142. data/lib/git/commands/read_tree.rb +149 -0
  143. data/lib/git/commands/remote/add.rb +91 -0
  144. data/lib/git/commands/remote/get_url.rb +66 -0
  145. data/lib/git/commands/remote/list.rb +54 -0
  146. data/lib/git/commands/remote/prune.rb +61 -0
  147. data/lib/git/commands/remote/remove.rb +52 -0
  148. data/lib/git/commands/remote/rename.rb +69 -0
  149. data/lib/git/commands/remote/set_branches.rb +63 -0
  150. data/lib/git/commands/remote/set_head.rb +82 -0
  151. data/lib/git/commands/remote/set_url.rb +71 -0
  152. data/lib/git/commands/remote/set_url_add.rb +61 -0
  153. data/lib/git/commands/remote/set_url_delete.rb +64 -0
  154. data/lib/git/commands/remote/show.rb +71 -0
  155. data/lib/git/commands/remote/update.rb +72 -0
  156. data/lib/git/commands/remote.rb +42 -0
  157. data/lib/git/commands/repack.rb +277 -0
  158. data/lib/git/commands/reset.rb +147 -0
  159. data/lib/git/commands/rev_parse.rb +297 -0
  160. data/lib/git/commands/revert/abort.rb +45 -0
  161. data/lib/git/commands/revert/continue.rb +57 -0
  162. data/lib/git/commands/revert/quit.rb +47 -0
  163. data/lib/git/commands/revert/skip.rb +44 -0
  164. data/lib/git/commands/revert/start.rb +153 -0
  165. data/lib/git/commands/revert.rb +29 -0
  166. data/lib/git/commands/rm.rb +114 -0
  167. data/lib/git/commands/show.rb +632 -0
  168. data/lib/git/commands/show_ref/exclude_existing.rb +120 -0
  169. data/lib/git/commands/show_ref/exists.rb +78 -0
  170. data/lib/git/commands/show_ref/list.rb +145 -0
  171. data/lib/git/commands/show_ref/verify.rb +120 -0
  172. data/lib/git/commands/show_ref.rb +42 -0
  173. data/lib/git/commands/stash/apply.rb +75 -0
  174. data/lib/git/commands/stash/branch.rb +65 -0
  175. data/lib/git/commands/stash/clear.rb +41 -0
  176. data/lib/git/commands/stash/create.rb +58 -0
  177. data/lib/git/commands/stash/drop.rb +67 -0
  178. data/lib/git/commands/stash/list.rb +39 -0
  179. data/lib/git/commands/stash/pop.rb +78 -0
  180. data/lib/git/commands/stash/push.rb +103 -0
  181. data/lib/git/commands/stash/show.rb +149 -0
  182. data/lib/git/commands/stash/store.rb +63 -0
  183. data/lib/git/commands/stash.rb +38 -0
  184. data/lib/git/commands/status.rb +169 -0
  185. data/lib/git/commands/symbolic_ref/delete.rb +68 -0
  186. data/lib/git/commands/symbolic_ref/read.rb +95 -0
  187. data/lib/git/commands/symbolic_ref/update.rb +76 -0
  188. data/lib/git/commands/symbolic_ref.rb +38 -0
  189. data/lib/git/commands/tag/create.rb +139 -0
  190. data/lib/git/commands/tag/delete.rb +55 -0
  191. data/lib/git/commands/tag/list.rb +143 -0
  192. data/lib/git/commands/tag/verify.rb +71 -0
  193. data/lib/git/commands/tag.rb +26 -0
  194. data/lib/git/commands/update_ref/batch.rb +140 -0
  195. data/lib/git/commands/update_ref/delete.rb +92 -0
  196. data/lib/git/commands/update_ref/update.rb +106 -0
  197. data/lib/git/commands/update_ref.rb +42 -0
  198. data/lib/git/commands/version.rb +52 -0
  199. data/lib/git/commands/worktree/add.rb +140 -0
  200. data/lib/git/commands/worktree/list.rb +64 -0
  201. data/lib/git/commands/worktree/lock.rb +58 -0
  202. data/lib/git/commands/worktree/management_base.rb +51 -0
  203. data/lib/git/commands/worktree/move.rb +66 -0
  204. data/lib/git/commands/worktree/prune.rb +67 -0
  205. data/lib/git/commands/worktree/remove.rb +63 -0
  206. data/lib/git/commands/worktree/repair.rb +76 -0
  207. data/lib/git/commands/worktree/unlock.rb +47 -0
  208. data/lib/git/commands/worktree.rb +43 -0
  209. data/lib/git/commands/write_tree.rb +68 -0
  210. data/lib/git/commands.rb +89 -0
  211. data/lib/git/detached_head_info.rb +54 -0
  212. data/lib/git/diff.rb +297 -7
  213. data/lib/git/diff_file_numstat_info.rb +29 -0
  214. data/lib/git/diff_file_patch_info.rb +134 -0
  215. data/lib/git/diff_file_raw_info.rb +127 -0
  216. data/lib/git/diff_info.rb +169 -0
  217. data/lib/git/diff_path_status.rb +78 -19
  218. data/lib/git/diff_result.rb +32 -0
  219. data/lib/git/diff_stats.rb +59 -14
  220. data/lib/git/dirstat_info.rb +86 -0
  221. data/lib/git/errors.rb +65 -2
  222. data/lib/git/execution_context/global.rb +56 -0
  223. data/lib/git/execution_context/repository.rb +147 -0
  224. data/lib/git/execution_context.rb +482 -0
  225. data/lib/git/file_ref.rb +74 -0
  226. data/lib/git/fsck_object.rb +9 -9
  227. data/lib/git/fsck_result.rb +1 -1
  228. data/lib/git/lib.rb +1606 -1028
  229. data/lib/git/log.rb +15 -2
  230. data/lib/git/object.rb +92 -22
  231. data/lib/git/parsers/branch.rb +224 -0
  232. data/lib/git/parsers/cat_file.rb +111 -0
  233. data/lib/git/parsers/diff.rb +585 -0
  234. data/lib/git/parsers/fsck.rb +133 -0
  235. data/lib/git/parsers/grep.rb +42 -0
  236. data/lib/git/parsers/ls_tree.rb +58 -0
  237. data/lib/git/parsers/stash.rb +208 -0
  238. data/lib/git/parsers/tag.rb +257 -0
  239. data/lib/git/remote.rb +133 -9
  240. data/lib/git/repository/branching.rb +572 -0
  241. data/lib/git/repository/committing.rb +191 -0
  242. data/lib/git/repository/configuring.rb +156 -0
  243. data/lib/git/repository/diffing.rb +775 -0
  244. data/lib/git/repository/inspecting.rb +153 -0
  245. data/lib/git/repository/logging.rb +247 -0
  246. data/lib/git/repository/merging.rb +295 -0
  247. data/lib/git/repository/object_operations.rb +1101 -0
  248. data/lib/git/repository/path_resolver.rb +207 -0
  249. data/lib/git/repository/remote_operations.rb +753 -0
  250. data/lib/git/repository/shared_private.rb +51 -0
  251. data/lib/git/repository/staging.rb +390 -0
  252. data/lib/git/repository/stashing.rb +107 -0
  253. data/lib/git/repository/status_operations.rb +180 -0
  254. data/lib/git/repository/worktree_operations.rb +159 -0
  255. data/lib/git/repository.rb +264 -1
  256. data/lib/git/stash.rb +85 -4
  257. data/lib/git/stash_info.rb +104 -0
  258. data/lib/git/stashes.rb +130 -13
  259. data/lib/git/status.rb +224 -18
  260. data/lib/git/tag_delete_failure.rb +31 -0
  261. data/lib/git/tag_delete_result.rb +63 -0
  262. data/lib/git/tag_info.rb +105 -0
  263. data/lib/git/version.rb +109 -2
  264. data/lib/git/version_constraint.rb +81 -0
  265. data/lib/git/worktree.rb +120 -5
  266. data/lib/git/worktrees.rb +107 -7
  267. data/lib/git.rb +114 -18
  268. data/redesign/1_architecture_existing.md +54 -18
  269. data/redesign/2_architecture_redesign.md +365 -46
  270. data/redesign/3_architecture_implementation.md +1451 -54
  271. data/tasks/gem_tasks.rake +4 -0
  272. data/tasks/npm_tasks.rake +7 -0
  273. data/tasks/rspec.rake +48 -0
  274. data/tasks/test.rake +13 -1
  275. data/tasks/yard.rake +34 -7
  276. metadata +349 -20
  277. data/lib/git/index.rb +0 -6
  278. data/lib/git/path.rb +0 -38
  279. data/lib/git/working_directory.rb +0 -6
  280. /data/{release-please-config.json → .release-please-config.json} +0 -0
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git/commands/base'
4
+
5
+ module Git
6
+ module Commands
7
+ module CatFile
8
+ # Queries one or more git objects via the batch stdin streaming protocol
9
+ #
10
+ # Accepts object names (or commands) written to stdin. Three output modes are
11
+ # available, selected by passing exactly one of `batch:`, `batch_check:`, or
12
+ # `batch_command:` as a keyword argument:
13
+ #
14
+ # - **`batch: true`** (`--batch`) — for each named object, write a header line
15
+ # `<sha> <type> <size>` followed by the raw content bytes and a newline
16
+ # separator; missing objects are reported inline as `<name> missing`
17
+ # - **`batch_check: true`** (`--batch-check`) — for each named object, write
18
+ # one metadata line `<sha> <type> <size>`; missing objects as `<name> missing`
19
+ # - **`batch_command: true`** (`--batch-command`) — enter command-dispatch mode;
20
+ # stdin carries named verbs (`contents <object>`, `info <object>`, `flush`),
21
+ # allowing content and metadata requests to be interleaved in a single process
22
+ #
23
+ # All three modes accept a format string instead of `true` to customise the
24
+ # per-object output line (e.g. `batch: "%(objectname) %(objecttype) %(objectsize)"`)
25
+ #
26
+ # When `batch_all_objects: true` is given instead of object names, git enumerates
27
+ # the entire object database itself and stdin is not read (incompatible with
28
+ # `batch_command:`).
29
+ #
30
+ # Missing objects never cause a non-zero exit — they are reported inline.
31
+ #
32
+ # For single-object queries, use {CatFile::Raw}.
33
+ # For filter-processed content, use {CatFile::Filtered}.
34
+ #
35
+ # @see Git::Commands::CatFile
36
+ #
37
+ # @see https://git-scm.com/docs/git-cat-file git-cat-file documentation
38
+ #
39
+ # @note `arguments` block audited against https://git-scm.com/docs/git-cat-file/2.53.0
40
+ #
41
+ # @api private
42
+ #
43
+ class Batch < Base
44
+ arguments do
45
+ literal 'cat-file'
46
+
47
+ # Full content mode: header + raw bytes + newline separator per object;
48
+ # accepts a format string to customise the per-object output header
49
+ # (e.g. `"%(objectname) %(objecttype) %(objectsize)"`)
50
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch
51
+ flag_or_value_option :batch, inline: true
52
+
53
+ # Metadata-only mode: one `<sha> <type> <size>` line per object;
54
+ # accepts a format string to customise the per-object output line
55
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-check
56
+ flag_or_value_option :batch_check, inline: true
57
+
58
+ # Command-dispatch mode: stdin carries `contents`/`info`/`flush` verbs;
59
+ # accepts a format string to customise the output of `info` and `contents` commands
60
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-command
61
+ flag_or_value_option :batch_command, inline: true
62
+
63
+ # Enumerate all objects in the repository without reading stdin.
64
+ # Incompatible with `batch_command:`.
65
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-all-objects
66
+ flag_option :batch_all_objects
67
+
68
+ # Use normal stdio buffering; enables explicit `flush` semantics when used
69
+ # with `batch_command:` and improves throughput with `batch_check:`
70
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---buffer
71
+ flag_option :buffer
72
+
73
+ # Follow symlinks inside the repository when traversing tree objects
74
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---follow-symlinks
75
+ flag_option :follow_symlinks
76
+
77
+ # Allow `--batch-all-objects` to output objects in an arbitrary, potentially
78
+ # faster order
79
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---unordered
80
+ flag_option :unordered
81
+
82
+ # Apply textconv filters to blob content (combine with `batch_command:`)
83
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---textconv
84
+ flag_option :textconv
85
+
86
+ # Apply the full working-tree filter pipeline (combine with `batch_command:`)
87
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---filters
88
+ flag_option :filters
89
+
90
+ # Map committer/author identities through mailmap for all batch modes
91
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---use-mailmap
92
+ flag_option :use_mailmap, negatable: true
93
+
94
+ # Omit objects matching the filter spec from the output (batched modes only)
95
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---filterltfilter-specgt
96
+ value_option :filter, inline: true
97
+
98
+ # Use NUL-delimited input/output instead of newline-delimited
99
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt--Z
100
+ flag_option :Z
101
+
102
+ # Stream stdout to this IO object instead of buffering in memory.
103
+ # When provided, {#call} dispatches to the streaming execution path.
104
+ execution_option :out
105
+
106
+ # Object names (or batch-command lines) are written to stdin, not argv.
107
+ # Using skip_cli: true because these values are fed via stdin — git never
108
+ # sees them as CLI arguments so Ruby must enforce the cross-argument
109
+ # constraints below.
110
+ operand :object, repeatable: true, skip_cli: true
111
+
112
+ conflicts :object, :batch_all_objects
113
+ requires_one_of :object, :batch_all_objects
114
+ end
115
+
116
+ # Execute `git cat-file` in batch stdin-streaming mode.
117
+ #
118
+ # Exactly one of `batch:`, `batch_check:`, or `batch_command:` must be selected.
119
+ # Pass `batch_all_objects: true` instead of object names to enumerate the entire
120
+ # object database without reading stdin.
121
+ #
122
+ # @overload call(*objects, batch: true, **options)
123
+ # Stream one or more named objects; return header + content per object
124
+ #
125
+ # @param objects [Array<String>] object names written to stdin
126
+ #
127
+ # @param batch [Boolean, String] enable `--batch` mode; pass a format string
128
+ # to customise the per-object output header
129
+ # (e.g. `"%(objectname) %(objecttype) %(objectsize)"`)
130
+ #
131
+ # @param options [Hash] command options
132
+ #
133
+ # @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better throughput
134
+ #
135
+ # @option options [Boolean, nil] :follow_symlinks (nil) follow symlinks in trees
136
+ #
137
+ # @option options [Boolean, nil] :unordered (nil) output in arbitrary order
138
+ #
139
+ # @option options [Boolean, nil] :textconv (nil) apply textconv filters
140
+ #
141
+ # @option options [Boolean, nil] :filters (nil) apply full working-tree filters
142
+ #
143
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
144
+ #
145
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
146
+ #
147
+ # @option options [String] :filter (nil) omit objects matching the given filter spec
148
+ #
149
+ # @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
150
+ #
151
+ # @option options [#write, nil] :out (nil) stream stdout to this IO object
152
+ # instead of buffering in memory; when given, `result.stdout` will be `''`
153
+ #
154
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
155
+ #
156
+ # Stdout contains the batch output stream (or `''` when `out:` is given)
157
+ #
158
+ # @raise [ArgumentError] if unsupported options are provided
159
+ #
160
+ # @raise [Git::FailedError] if git exits non-zero (catastrophic failure only;
161
+ # missing objects are reported inline)
162
+ #
163
+ # @overload call(*objects, batch_check: true, **options)
164
+ # Stream one or more named objects; return one metadata line per object
165
+ #
166
+ # @param objects [Array<String>] object names written to stdin
167
+ #
168
+ # @param batch_check [Boolean, String] enable `--batch-check` mode; pass a
169
+ # format string to customise the per-object output line
170
+ # (e.g. `"%(objectname) %(objecttype) %(objectsize)"`)
171
+ #
172
+ # @param options [Hash] command options
173
+ #
174
+ # @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better
175
+ # throughput when processing large numbers of objects
176
+ #
177
+ # @option options [Boolean, nil] :follow_symlinks (nil) follow symlinks in trees
178
+ #
179
+ # @option options [Boolean, nil] :unordered (nil) output in arbitrary order
180
+ #
181
+ # @option options [Boolean, nil] :textconv (nil) apply textconv filters
182
+ #
183
+ # @option options [Boolean, nil] :filters (nil) apply full working-tree filters
184
+ #
185
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
186
+ #
187
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
188
+ #
189
+ # @option options [String] :filter (nil) omit objects matching the given filter spec
190
+ #
191
+ # @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
192
+ #
193
+ # @option options [#write, nil] :out (nil) stream stdout to this IO object
194
+ # instead of buffering in memory; when given, `result.stdout` will be `''`
195
+ #
196
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
197
+ #
198
+ # Stdout contains one metadata line per object (or `''` when `out:` is given)
199
+ #
200
+ # @raise [ArgumentError] if unsupported options are provided
201
+ #
202
+ # @raise [Git::FailedError] if git exits non-zero (catastrophic failure only;
203
+ # missing objects are reported inline)
204
+ #
205
+ # @overload call(*objects, batch_command: true, **options)
206
+ # Dispatch mixed `contents`/`info`/`flush` commands via stdin
207
+ #
208
+ # Each element of `objects` is written verbatim as a stdin line — the caller
209
+ # is responsible for prefixing lines with the appropriate verb
210
+ # (`contents <object>`, `info <object>`, or `flush`).
211
+ #
212
+ # @param objects [Array<String>] pre-formatted command lines to write to stdin
213
+ #
214
+ # @param batch_command [Boolean, String] enable `--batch-command` mode; pass
215
+ # a format string to customise the output of `info` and `contents` commands
216
+ #
217
+ # @param options [Hash] command options
218
+ #
219
+ # @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better throughput
220
+ #
221
+ # @option options [Boolean, nil] :textconv (nil) apply textconv filters
222
+ #
223
+ # @option options [Boolean, nil] :filters (nil) apply full working-tree filters
224
+ #
225
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
226
+ #
227
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
228
+ #
229
+ # @option options [String] :filter (nil) omit objects matching the given filter spec
230
+ #
231
+ # @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
232
+ #
233
+ # @option options [#write, nil] :out (nil) stream stdout to this IO object
234
+ # instead of buffering in memory; when given, `result.stdout` will be `''`
235
+ #
236
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
237
+ #
238
+ # Stdout contains the interleaved command output (or `''` when `out:` is given)
239
+ #
240
+ # @raise [ArgumentError] if unsupported options are provided
241
+ #
242
+ # @raise [Git::FailedError] if git exits non-zero
243
+ #
244
+ # @overload call(batch_all_objects: true, batch: true, **options)
245
+ # Enumerate all objects in the repository with full content
246
+ #
247
+ # @param batch_all_objects [Boolean] enumerate all objects; stdin is not read
248
+ #
249
+ # @param batch [Boolean, String] enable `--batch` mode; pass a format string
250
+ # to customise the per-object output header
251
+ #
252
+ # @param options [Hash] command options
253
+ #
254
+ # @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better throughput
255
+ #
256
+ # @option options [Boolean, nil] :unordered (nil) output in arbitrary order
257
+ #
258
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap for
259
+ # commit and tag objects (`--use-mailmap`)
260
+ #
261
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
262
+ #
263
+ # @option options [String] :filter (nil) omit objects matching the given filter spec
264
+ #
265
+ # @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
266
+ #
267
+ # @option options [#write, nil] :out (nil) stream stdout to this IO object
268
+ # instead of buffering in memory; when given, `result.stdout` will be `''`
269
+ #
270
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
271
+ #
272
+ # Stdout contains the full batch output (or `''` when `out:` is given)
273
+ #
274
+ # @raise [ArgumentError] if unsupported options are provided
275
+ #
276
+ # @raise [Git::FailedError] if git exits non-zero
277
+ #
278
+ # @overload call(batch_all_objects: true, batch_check: true, **options)
279
+ # Enumerate all objects in the repository with metadata only
280
+ #
281
+ # @param batch_all_objects [Boolean] enumerate all objects; stdin is not read
282
+ #
283
+ # @param batch_check [Boolean, String] enable `--batch-check` mode; pass a
284
+ # format string to customise the per-object output line
285
+ #
286
+ # @param options [Hash] command options
287
+ #
288
+ # @option options [Boolean, nil] :buffer (nil) use normal stdio buffering for better
289
+ # throughput when processing large numbers of objects
290
+ #
291
+ # @option options [Boolean, nil] :unordered (nil) output in arbitrary order
292
+ #
293
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap for
294
+ # commit and tag objects (`--use-mailmap`)
295
+ #
296
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
297
+ #
298
+ # @option options [String] :filter (nil) omit objects matching the given filter spec
299
+ #
300
+ # @option options [Boolean, nil] :Z (nil) use NUL-delimited I/O
301
+ #
302
+ # @option options [#write, nil] :out (nil) stream stdout to this IO object
303
+ # instead of buffering in memory; when given, `result.stdout` will be `''`
304
+ #
305
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
306
+ #
307
+ # Stdout contains one metadata line per object (or `''` when `out:` is given)
308
+ #
309
+ # @raise [ArgumentError] if unsupported options are provided
310
+ #
311
+ # @raise [Git::FailedError] if git exits non-zero
312
+ def call(*objects, **)
313
+ bound = args_definition.bind(*objects, **)
314
+ validate_version!
315
+ # `-Z` puts git into NUL I/O mode: input objects must be NUL-terminated.
316
+ # Without `-Z`, the standard newline delimiter is used.
317
+ delimiter = bound.Z? ? "\0" : "\n"
318
+ stdin = Array(bound.object).map { |o| "#{o}#{delimiter}" }.join
319
+ with_stdin(stdin) { |reader| run_batch(bound, reader) }
320
+ end
321
+
322
+ private
323
+
324
+ # Run the bound command with stdin connected to the reader end of the pipe
325
+ #
326
+ # @param bound [Git::Commands::Arguments::Bound] bound argument list
327
+ #
328
+ # @param reader [IO] read end of the stdin pipe
329
+ #
330
+ # @return [Git::CommandLineResult]
331
+ #
332
+ def run_batch(bound, reader)
333
+ result = if bound.execution_options.key?(:out)
334
+ run_batch_streaming(bound, reader)
335
+ else
336
+ run_batch_capturing(bound, reader)
337
+ end
338
+ validate_exit_status!(result)
339
+ result
340
+ end
341
+
342
+ def run_batch_streaming(bound, reader)
343
+ @execution_context.command_streaming(
344
+ *bound,
345
+ in: reader,
346
+ **bound.execution_options,
347
+ raise_on_failure: false
348
+ )
349
+ end
350
+
351
+ def run_batch_capturing(bound, reader)
352
+ @execution_context.command_capturing(
353
+ *bound,
354
+ in: reader,
355
+ **bound.execution_options,
356
+ normalize: false,
357
+ chomp: false,
358
+ raise_on_failure: false
359
+ )
360
+ end
361
+ end
362
+ end
363
+ end
364
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git/commands/base'
4
+
5
+ module Git
6
+ module Commands
7
+ module CatFile
8
+ # Retrieves a single git object after applying working-tree filter processing
9
+ #
10
+ # Runs `git cat-file` with `--textconv` or `--filters`. Both modes require the
11
+ # caller to identify the object by revision **and** path so that git can look up
12
+ # the applicable `.gitattributes` rules:
13
+ #
14
+ # - **`--textconv`** — apply only the textconv filter (binary-to-text conversion
15
+ # defined by `diff.<driver>.textconv` in `.gitattributes`); intended for
16
+ # human-readable display
17
+ # - **`--filters`** — apply the full working-tree pipeline: smudge filter, EOL
18
+ # conversion, and textconv; returns the content exactly as `git checkout`
19
+ # would write it to disk
20
+ #
21
+ # The object can be identified as a combined `<rev>:<path>` string passed as the
22
+ # `rev` operand, or as a bare `<rev>` with `--path=<path>` supplied separately.
23
+ #
24
+ # For unfiltered object access, use {CatFile::Raw}.
25
+ # For batch queries across multiple objects, use {CatFile::Batch}.
26
+ #
27
+ # @note `arguments` block audited against https://git-scm.com/docs/git-cat-file/2.53.0
28
+ #
29
+ # @see Git::Commands::CatFile
30
+ #
31
+ # @see https://git-scm.com/docs/git-cat-file git-cat-file documentation
32
+ #
33
+ # @api private
34
+ #
35
+ class Filtered < Base
36
+ arguments do
37
+ literal 'cat-file'
38
+
39
+ # Apply only the textconv filter (binary-to-text conversion)
40
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---textconv
41
+ flag_option :textconv
42
+
43
+ # Apply the full working-tree filter pipeline (smudge, EOL, textconv)
44
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---filters
45
+ flag_option :filters
46
+
47
+ # Specify the path separately when the rev is passed as a bare revision.
48
+ # When used, the `rev` operand must be a plain revision (not `<rev>:<path>`).
49
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---pathltpathgt
50
+ value_option :path, inline: true
51
+
52
+ end_of_options
53
+
54
+ # Revision identifying the object — either a combined `<rev>:<path>` string
55
+ # (e.g. `HEAD:README.md`) or a bare revision when `--path` is also given
56
+ operand :rev, required: true
57
+ end
58
+
59
+ # @!method call(*, **)
60
+ #
61
+ # Execute `git cat-file --textconv` or `git cat-file --filters`.
62
+ #
63
+ # @overload call(rev, textconv: true, **options)
64
+ # Apply the textconv filter to a single object
65
+ #
66
+ # @param rev [String] combined `<rev>:<path>` identifier (e.g. `HEAD:README.md`),
67
+ # or a bare revision when `path:` is also given
68
+ #
69
+ # @param textconv [Boolean] enable textconv mode
70
+ #
71
+ # @param options [Hash] command options
72
+ #
73
+ # @option options [String] :path (nil) Path to the blob when `rev` is a bare revision
74
+ #
75
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
76
+ #
77
+ # Stdout contains the textconv-processed content
78
+ #
79
+ # @raise [ArgumentError] if unsupported options are provided
80
+ #
81
+ # @raise [Git::FailedError] if the object does not exist or the path is missing
82
+ #
83
+ # @overload call(rev, filters: true, **options)
84
+ # Apply the full working-tree filter pipeline to a single object
85
+ #
86
+ # @param rev [String] combined `<rev>:<path>` identifier (e.g. `HEAD:README.md`),
87
+ # or a bare revision when `path:` is also given
88
+ #
89
+ # @param filters [Boolean] enable full filter pipeline mode
90
+ #
91
+ # @param options [Hash] command options
92
+ #
93
+ # @option options [String] :path (nil) Path to the blob when `rev` is a bare revision
94
+ #
95
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
96
+ #
97
+ # Stdout contains the filter-processed content
98
+ #
99
+ # @raise [ArgumentError] if unsupported options are provided
100
+ #
101
+ # @raise [Git::FailedError] if the object does not exist or the path is missing
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git/commands/base'
4
+
5
+ module Git
6
+ module Commands
7
+ module CatFile
8
+ # Queries a single git object by name passed as a CLI argument
9
+ #
10
+ # Runs `git cat-file` in non-batch mode. Exactly one mode flag or a `<type>`
11
+ # operand must be supplied:
12
+ #
13
+ # - **`-e`** — exit 0 if the object exists and is valid, exit 1 otherwise;
14
+ # no output is written to stdout
15
+ # - **`-t`** — print the object type (`blob`, `tree`, `commit`, or `tag`)
16
+ # - **`-s`** — print the object size in bytes
17
+ # - **`-p`** — pretty-print the object content (format varies by type)
18
+ # - **`<type>`** — print the raw content after validating the object is of
19
+ # the given type (or trivially dereferenceable to it)
20
+ #
21
+ # For queries across multiple objects, use {CatFile::Batch}.
22
+ # For filter-processed content, use {CatFile::Filtered}.
23
+ #
24
+ # @see Git::Commands::CatFile
25
+ #
26
+ # @see https://git-scm.com/docs/git-cat-file git-cat-file documentation
27
+ #
28
+ # @note `arguments` block audited against https://git-scm.com/docs/git-cat-file/2.53.0
29
+ #
30
+ # @api private
31
+ #
32
+ class Raw < Base
33
+ arguments do
34
+ literal 'cat-file'
35
+
36
+ # Exit 0 if object exists and is valid; exit 1 otherwise (no output)
37
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt--e
38
+ flag_option :e
39
+
40
+ # Pretty-print the object content based on its type
41
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt--p
42
+ flag_option :p
43
+
44
+ # Print the object type (`blob`, `tree`, `commit`, or `tag`)
45
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt--t
46
+ flag_option :t
47
+
48
+ # Print the object size in bytes
49
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt--s
50
+ flag_option :s
51
+
52
+ # Allow -t and -s to query broken or corrupt objects of unknown type;
53
+ # rejected by git in any other mode — enforced by constraint below
54
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---allow-unknown-type
55
+ flag_option :allow_unknown_type
56
+
57
+ # Map committer/author identities through the mailmap before reporting size
58
+ # @see https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---use-mailmap
59
+ flag_option :use_mailmap, negatable: true
60
+
61
+ # Stream stdout to this IO object instead of buffering in memory.
62
+ # When provided, {#call} dispatches to the streaming execution path.
63
+ execution_option :out
64
+
65
+ end_of_options
66
+
67
+ # Expected object type — one of `commit`, `tree`, `blob`, or `tag`.
68
+ # Git also accepts a type that the object is trivially dereferenceable to
69
+ # (e.g. `tree` against a commit ref, `blob` against a tag that points to one).
70
+ operand :type
71
+
72
+ # Object name: SHA, ref, `HEAD`, treeish path reference, etc.
73
+ operand :object, required: true
74
+
75
+ requires_one_of :t, :s, when: :allow_unknown_type
76
+ end
77
+
78
+ # Execute `git cat-file` for a single object.
79
+ #
80
+ # Exactly one mode must be selected: pass one of `e: true`, `p: true`,
81
+ # `t: true`, `s: true`, or a positional `type` argument.
82
+ #
83
+ # @overload call(object, e: true, **options)
84
+ # Check whether an object exists
85
+ #
86
+ # @param object [String] object name (SHA, ref, `HEAD`, treeish path, etc.)
87
+ #
88
+ # @param e [Boolean] enable existence-check mode
89
+ #
90
+ # @param options [Hash] command options
91
+ #
92
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
93
+ #
94
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
95
+ #
96
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
97
+ #
98
+ # Exit status 0 means the object exists; exit status 1 means it does not
99
+ #
100
+ # @raise [ArgumentError] if unsupported options are provided
101
+ #
102
+ # @raise [Git::FailedError] if git exits with a status other than 0 or 1
103
+ #
104
+ # @overload call(object, t: true, **options)
105
+ # Print the object type
106
+ #
107
+ # @param object [String] object name
108
+ #
109
+ # @param t [Boolean] enable type-query mode
110
+ #
111
+ # @param options [Hash] command options
112
+ #
113
+ # @option options [Boolean, nil] :allow_unknown_type (nil) allow querying broken or corrupt objects of
114
+ # unknown type
115
+ #
116
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
117
+ #
118
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
119
+ #
120
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
121
+ #
122
+ # Stdout contains the object type string
123
+ #
124
+ # @raise [ArgumentError] if unsupported options are provided
125
+ #
126
+ # @raise [Git::FailedError] if the object does not exist
127
+ #
128
+ # @overload call(object, s: true, **options)
129
+ # Print the object size in bytes
130
+ #
131
+ # @param object [String] object name
132
+ #
133
+ # @param s [Boolean] enable size-query mode
134
+ #
135
+ # @param options [Hash] command options
136
+ #
137
+ # @option options [Boolean, nil] :allow_unknown_type (nil) allow querying broken or corrupt objects of
138
+ # unknown type
139
+ #
140
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
141
+ #
142
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
143
+ #
144
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
145
+ #
146
+ # Stdout contains the object size as a decimal string
147
+ #
148
+ # @raise [ArgumentError] if unsupported options are provided
149
+ #
150
+ # @raise [Git::FailedError] if the object does not exist
151
+ #
152
+ # @overload call(object, p: true, **options)
153
+ # Pretty-print the object content
154
+ #
155
+ # @param object [String] object name
156
+ #
157
+ # @param p [Boolean] enable pretty-print mode
158
+ #
159
+ # @param options [Hash] command options
160
+ #
161
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
162
+ #
163
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
164
+ #
165
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
166
+ #
167
+ # Stdout contains the formatted object content
168
+ #
169
+ # @raise [ArgumentError] if unsupported options are provided
170
+ #
171
+ # @raise [Git::FailedError] if the object does not exist
172
+ #
173
+ # @overload call(type, object, **options)
174
+ # Print the raw content, validating the object is of the given type
175
+ #
176
+ # @param type [String] expected object type — `commit`, `tree`, `blob`, or `tag`
177
+ #
178
+ # @param object [String] object name
179
+ #
180
+ # @param options [Hash] command options
181
+ #
182
+ # @option options [Boolean, nil] :use_mailmap (nil) remap identities via mailmap (`--use-mailmap`)
183
+ #
184
+ # @option options [Boolean, nil] :no_use_mailmap (nil) suppress mailmap remapping (`--no-use-mailmap`)
185
+ #
186
+ # @return [Git::CommandLineResult] the result of calling `git cat-file`
187
+ #
188
+ # Stdout contains the raw object content
189
+ #
190
+ # @raise [ArgumentError] if unsupported options are provided
191
+ #
192
+ # @raise [Git::FailedError] if the object does not exist or is not of the
193
+ # given type
194
+ def call(*, **)
195
+ bound = args_definition.bind(*, **)
196
+ validate_version!
197
+ result = execute_command(bound)
198
+
199
+ # `-e` treats exit 1 as a meaningful result (object not found), but any other
200
+ # non-zero exit (e.g. 128 for a corrupt object database) is still a failure.
201
+ # All other modes treat every non-zero exit as a failure.
202
+ allowed = result.status.success? || (bound.e? && result.status.exitstatus == 1)
203
+ raise Git::FailedError, result unless allowed
204
+
205
+ result
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end