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.
Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +27 -0
  3. data/.github/copilot-instructions.md +3 -8
  4. data/.github/hooks/bin-setup-on-worktree.json +11 -0
  5. data/.github/hooks/run-bin-setup-once.sh +14 -0
  6. data/.github/skills/breaking-change-analysis/SKILL.md +6 -9
  7. data/.github/skills/ci-cd-troubleshooting/SKILL.md +2 -2
  8. data/.github/skills/command-implementation/REFERENCE.md +34 -33
  9. data/.github/skills/command-implementation/SKILL.md +5 -4
  10. data/.github/skills/command-test-conventions/SKILL.md +13 -9
  11. data/.github/skills/command-yard-documentation/SKILL.md +14 -6
  12. data/.github/skills/development-workflow/SKILL.md +20 -14
  13. data/.github/skills/facade-implementation/REFERENCE.md +19 -22
  14. data/.github/skills/facade-implementation/SKILL.md +0 -5
  15. data/.github/skills/facade-test-conventions/SKILL.md +4 -7
  16. data/.github/skills/facade-yard-documentation/SKILL.md +8 -2
  17. data/.github/skills/make-skill-template/SKILL.md +53 -3
  18. data/.github/skills/pr-readiness-review/SKILL.md +22 -2
  19. data/.github/skills/project-context/SKILL.md +16 -23
  20. data/.github/skills/pull-request-review/SKILL.md +2 -2
  21. data/.github/skills/rebase/SKILL.md +148 -0
  22. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +1 -1
  23. data/.github/skills/resolve-feedback/SKILL.md +288 -0
  24. data/.github/skills/review-arguments-dsl/CHECKLIST.md +3 -3
  25. data/.github/skills/reviewing-skills/SKILL.md +28 -3
  26. data/.github/skills/test-debugging/SKILL.md +20 -19
  27. data/.github/skills/yard-documentation/SKILL.md +671 -483
  28. data/.github/skills/yard-documentation/element-rules.md +162 -0
  29. data/.github/skills-deprecated/README.md +21 -0
  30. data/.github/{skills → skills-deprecated}/extract-command-from-lib/SKILL.md +9 -9
  31. data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/SKILL.md +12 -12
  32. data/.github/workflows/continuous_integration.yml +3 -2
  33. data/.rubocop.yml +7 -39
  34. data/.yard-lint.yml +75 -0
  35. data/CONTRIBUTING.md +186 -174
  36. data/Gemfile +17 -0
  37. data/README.md +86 -23
  38. data/Rakefile +3 -21
  39. data/UPGRADING.md +219 -70
  40. data/docker/test/Dockerfile +32 -0
  41. data/docker/test/docker-compose.yml +0 -0
  42. data/git.gemspec +3 -4
  43. data/lib/git/author.rb +20 -1
  44. data/lib/git/branch.rb +26 -6
  45. data/lib/git/branch_delete_failure.rb +3 -0
  46. data/lib/git/branch_delete_result.rb +6 -3
  47. data/lib/git/branch_info.rb +6 -6
  48. data/lib/git/command_line/base.rb +6 -13
  49. data/lib/git/command_line/capturing.rb +67 -10
  50. data/lib/git/command_line/result.rb +0 -8
  51. data/lib/git/command_line/streaming.rb +45 -5
  52. data/lib/git/command_line.rb +4 -3
  53. data/lib/git/commands/add.rb +61 -53
  54. data/lib/git/commands/am/abort.rb +2 -2
  55. data/lib/git/commands/am/apply.rb +109 -98
  56. data/lib/git/commands/am/continue.rb +2 -2
  57. data/lib/git/commands/am/quit.rb +2 -2
  58. data/lib/git/commands/am/retry.rb +4 -2
  59. data/lib/git/commands/am/show_current_patch.rb +1 -1
  60. data/lib/git/commands/am/skip.rb +2 -2
  61. data/lib/git/commands/am.rb +2 -2
  62. data/lib/git/commands/apply.rb +7 -2
  63. data/lib/git/commands/archive/list_formats.rb +3 -3
  64. data/lib/git/commands/archive.rb +7 -2
  65. data/lib/git/commands/arguments.rb +1370 -359
  66. data/lib/git/commands/base.rb +111 -13
  67. data/lib/git/commands/branch/copy.rb +29 -21
  68. data/lib/git/commands/branch/create.rb +72 -68
  69. data/lib/git/commands/branch/delete.rb +25 -17
  70. data/lib/git/commands/branch/list.rb +76 -60
  71. data/lib/git/commands/branch/move.rb +29 -21
  72. data/lib/git/commands/branch/set_upstream.rb +8 -8
  73. data/lib/git/commands/branch/show_current.rb +3 -3
  74. data/lib/git/commands/branch/unset_upstream.rb +4 -8
  75. data/lib/git/commands/branch.rb +2 -2
  76. data/lib/git/commands/cat_file/batch.rb +36 -20
  77. data/lib/git/commands/cat_file/filtered.rb +12 -12
  78. data/lib/git/commands/cat_file/raw.rb +13 -13
  79. data/lib/git/commands/cat_file.rb +4 -4
  80. data/lib/git/commands/checkout/branch.rb +7 -5
  81. data/lib/git/commands/checkout/files.rb +5 -4
  82. data/lib/git/commands/checkout.rb +4 -4
  83. data/lib/git/commands/checkout_index.rb +5 -4
  84. data/lib/git/commands/clean.rb +6 -4
  85. data/lib/git/commands/clone.rb +5 -4
  86. data/lib/git/commands/commit.rb +5 -4
  87. data/lib/git/commands/commit_tree.rb +5 -4
  88. data/lib/git/commands/config_option_syntax/add.rb +7 -4
  89. data/lib/git/commands/config_option_syntax/get.rb +9 -5
  90. data/lib/git/commands/config_option_syntax/get_all.rb +7 -4
  91. data/lib/git/commands/config_option_syntax/get_color.rb +8 -4
  92. data/lib/git/commands/config_option_syntax/get_color_bool.rb +7 -4
  93. data/lib/git/commands/config_option_syntax/get_regexp.rb +8 -4
  94. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +8 -4
  95. data/lib/git/commands/config_option_syntax/list.rb +8 -4
  96. data/lib/git/commands/config_option_syntax/remove_section.rb +7 -2
  97. data/lib/git/commands/config_option_syntax/rename_section.rb +7 -2
  98. data/lib/git/commands/config_option_syntax/replace_all.rb +7 -2
  99. data/lib/git/commands/config_option_syntax/set.rb +7 -2
  100. data/lib/git/commands/config_option_syntax/unset.rb +7 -4
  101. data/lib/git/commands/config_option_syntax/unset_all.rb +7 -2
  102. data/lib/git/commands/describe.rb +5 -4
  103. data/lib/git/commands/diff.rb +13 -12
  104. data/lib/git/commands/diff_files.rb +7 -6
  105. data/lib/git/commands/diff_index.rb +10 -7
  106. data/lib/git/commands/fetch.rb +6 -4
  107. data/lib/git/commands/fsck.rb +6 -4
  108. data/lib/git/commands/gc.rb +6 -4
  109. data/lib/git/commands/grep.rb +6 -5
  110. data/lib/git/commands/init.rb +6 -4
  111. data/lib/git/commands/log.rb +287 -285
  112. data/lib/git/commands/ls_files.rb +69 -65
  113. data/lib/git/commands/ls_remote.rb +62 -56
  114. data/lib/git/commands/ls_tree.rb +50 -46
  115. data/lib/git/commands/maintenance/register.rb +25 -23
  116. data/lib/git/commands/maintenance/run.rb +7 -2
  117. data/lib/git/commands/maintenance/start.rb +7 -2
  118. data/lib/git/commands/maintenance/stop.rb +7 -2
  119. data/lib/git/commands/maintenance/unregister.rb +7 -2
  120. data/lib/git/commands/merge/abort.rb +2 -2
  121. data/lib/git/commands/merge/continue.rb +2 -2
  122. data/lib/git/commands/merge/quit.rb +2 -2
  123. data/lib/git/commands/merge/start.rb +7 -2
  124. data/lib/git/commands/merge.rb +2 -2
  125. data/lib/git/commands/merge_base.rb +7 -2
  126. data/lib/git/commands/mv.rb +7 -2
  127. data/lib/git/commands/name_rev.rb +7 -2
  128. data/lib/git/commands/pull.rb +7 -2
  129. data/lib/git/commands/push.rb +7 -2
  130. data/lib/git/commands/read_tree.rb +7 -2
  131. data/lib/git/commands/remote/add.rb +7 -2
  132. data/lib/git/commands/remote/get_url.rb +4 -2
  133. data/lib/git/commands/remote/list.rb +4 -2
  134. data/lib/git/commands/remote/prune.rb +4 -2
  135. data/lib/git/commands/remote/remove.rb +4 -2
  136. data/lib/git/commands/remote/rename.rb +4 -2
  137. data/lib/git/commands/remote/set_branches.rb +9 -2
  138. data/lib/git/commands/remote/set_head.rb +12 -5
  139. data/lib/git/commands/remote/set_url.rb +9 -2
  140. data/lib/git/commands/remote/set_url_add.rb +11 -2
  141. data/lib/git/commands/remote/set_url_delete.rb +9 -2
  142. data/lib/git/commands/remote/show.rb +18 -12
  143. data/lib/git/commands/remote/update.rb +19 -12
  144. data/lib/git/commands/remote.rb +2 -2
  145. data/lib/git/commands/repack.rb +67 -63
  146. data/lib/git/commands/reset.rb +51 -44
  147. data/lib/git/commands/rev_parse.rb +135 -128
  148. data/lib/git/commands/revert/abort.rb +2 -2
  149. data/lib/git/commands/revert/continue.rb +7 -2
  150. data/lib/git/commands/revert/quit.rb +2 -2
  151. data/lib/git/commands/revert/skip.rb +2 -2
  152. data/lib/git/commands/revert/start.rb +7 -2
  153. data/lib/git/commands/revert.rb +2 -2
  154. data/lib/git/commands/rm.rb +35 -36
  155. data/lib/git/commands/show.rb +1 -1
  156. data/lib/git/commands/show_ref/exclude_existing.rb +3 -4
  157. data/lib/git/commands/show_ref/exists.rb +15 -13
  158. data/lib/git/commands/show_ref/list.rb +39 -35
  159. data/lib/git/commands/show_ref/verify.rb +29 -27
  160. data/lib/git/commands/show_ref.rb +4 -4
  161. data/lib/git/commands/stash/apply.rb +31 -25
  162. data/lib/git/commands/stash/branch.rb +10 -8
  163. data/lib/git/commands/stash/clear.rb +7 -5
  164. data/lib/git/commands/stash/create.rb +10 -8
  165. data/lib/git/commands/stash/drop.rb +15 -9
  166. data/lib/git/commands/stash/list.rb +9 -5
  167. data/lib/git/commands/stash/pop.rb +21 -12
  168. data/lib/git/commands/stash/push.rb +20 -11
  169. data/lib/git/commands/stash/show.rb +21 -12
  170. data/lib/git/commands/stash/store.rb +19 -10
  171. data/lib/git/commands/stash.rb +2 -2
  172. data/lib/git/commands/status.rb +7 -2
  173. data/lib/git/commands/symbolic_ref/delete.rb +18 -14
  174. data/lib/git/commands/symbolic_ref/read.rb +24 -20
  175. data/lib/git/commands/symbolic_ref/update.rb +20 -17
  176. data/lib/git/commands/symbolic_ref.rb +4 -4
  177. data/lib/git/commands/tag/create.rb +45 -42
  178. data/lib/git/commands/tag/delete.rb +5 -3
  179. data/lib/git/commands/tag/list.rb +47 -44
  180. data/lib/git/commands/tag/verify.rb +12 -12
  181. data/lib/git/commands/tag.rb +2 -2
  182. data/lib/git/commands/update_ref/batch.rb +6 -1
  183. data/lib/git/commands/update_ref/delete.rb +19 -21
  184. data/lib/git/commands/update_ref/update.rb +22 -25
  185. data/lib/git/commands/update_ref.rb +4 -4
  186. data/lib/git/commands/version.rb +14 -11
  187. data/lib/git/commands/worktree/add.rb +50 -51
  188. data/lib/git/commands/worktree/list.rb +17 -17
  189. data/lib/git/commands/worktree/lock.rb +12 -12
  190. data/lib/git/commands/worktree/move.rb +16 -16
  191. data/lib/git/commands/worktree/prune.rb +2 -2
  192. data/lib/git/commands/worktree/remove.rb +2 -2
  193. data/lib/git/commands/worktree/repair.rb +2 -2
  194. data/lib/git/commands/worktree/unlock.rb +2 -2
  195. data/lib/git/commands/write_tree.rb +2 -2
  196. data/lib/git/commands.rb +4 -3
  197. data/lib/git/config.rb +47 -1
  198. data/lib/git/configuring.rb +89 -15
  199. data/lib/git/detached_head_info.rb +4 -1
  200. data/lib/git/diff.rb +2 -5
  201. data/lib/git/diff_file_numstat_info.rb +3 -1
  202. data/lib/git/diff_file_patch_info.rb +3 -1
  203. data/lib/git/diff_file_raw_info.rb +3 -1
  204. data/lib/git/diff_info.rb +8 -15
  205. data/lib/git/diff_path_status.rb +16 -3
  206. data/lib/git/diff_result.rb +3 -1
  207. data/lib/git/diff_stats.rb +15 -0
  208. data/lib/git/dirstat_info.rb +24 -8
  209. data/lib/git/encoding_utils.rb +32 -1
  210. data/lib/git/errors.rb +19 -9
  211. data/lib/git/escaped_path.rb +55 -3
  212. data/lib/git/execution_context/repository.rb +15 -0
  213. data/lib/git/execution_context.rb +76 -74
  214. data/lib/git/file_ref.rb +6 -3
  215. data/lib/git/fsck_object.rb +8 -0
  216. data/lib/git/fsck_result.rb +26 -15
  217. data/lib/git/log.rb +152 -5
  218. data/lib/git/object.rb +284 -8
  219. data/lib/git/parsers/branch.rb +18 -0
  220. data/lib/git/parsers/cat_file.rb +2 -2
  221. data/lib/git/parsers/diff.rb +213 -5
  222. data/lib/git/parsers/fsck.rb +11 -0
  223. data/lib/git/parsers/ls_remote.rb +1 -1
  224. data/lib/git/parsers/stash.rb +51 -0
  225. data/lib/git/parsers/tag.rb +38 -0
  226. data/lib/git/remote.rb +34 -2
  227. data/lib/git/repository/branching.rb +23 -21
  228. data/lib/git/repository/committing.rb +46 -6
  229. data/lib/git/repository/context_helpers.rb +45 -16
  230. data/lib/git/repository/diffing.rb +32 -23
  231. data/lib/git/repository/factories.rb +153 -28
  232. data/lib/git/repository/inspecting.rb +1 -1
  233. data/lib/git/repository/logging.rb +169 -30
  234. data/lib/git/repository/maintenance.rb +1 -1
  235. data/lib/git/repository/merging.rb +3 -3
  236. data/lib/git/repository/object_operations.rb +108 -14
  237. data/lib/git/repository/remote_operations.rb +150 -171
  238. data/lib/git/repository/shared_private.rb +7 -5
  239. data/lib/git/repository/staging.rb +36 -12
  240. data/lib/git/repository/stashing.rb +16 -16
  241. data/lib/git/repository/status_operations.rb +1 -1
  242. data/lib/git/repository/worktree_operations.rb +1 -1
  243. data/lib/git/repository.rb +287 -6
  244. data/lib/git/stash.rb +16 -21
  245. data/lib/git/stash_info.rb +4 -4
  246. data/lib/git/stashes.rb +20 -26
  247. data/lib/git/status.rb +25 -13
  248. data/lib/git/tag_delete_failure.rb +3 -0
  249. data/lib/git/tag_delete_result.rb +6 -3
  250. data/lib/git/tag_info.rb +1 -0
  251. data/lib/git/url.rb +12 -5
  252. data/lib/git/version.rb +6 -4
  253. data/lib/git/version_constraint.rb +4 -0
  254. data/lib/git.rb +400 -314
  255. data/redesign/3_architecture_implementation.md +81 -30
  256. data/redesign/Phase 4 - Step A.md +6 -0
  257. data/redesign/Phase 4 - Step B.md +921 -0
  258. data/redesign/Phase 4 - Step C.md +833 -0
  259. data/redesign/c1a-public-api-scope.tsv +256 -0
  260. data/redesign/phase-4-step-b-test-audit.tsv +485 -0
  261. data/tasks/yard.rake +24 -17
  262. metadata +24 -58
  263. data/commitlint.test +0 -4
  264. data/lib/git/args_builder.rb +0 -103
  265. data/lib/git/command_line_result.rb +0 -8
  266. data/lib/git/deprecation.rb +0 -9
  267. data/lib/git/repository/configuring.rb +0 -351
  268. data/tasks/test.rake +0 -25
  269. /data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -0
  270. /data/.github/{skills → skills-deprecated}/review-backward-compatibility/SKILL.md +0 -0
data/lib/git/branch.rb CHANGED
@@ -139,17 +139,37 @@ module Git
139
139
  # Archives this branch and writes the result to a file
140
140
  #
141
141
  # @example Archive to a tar file
142
- # git.branch('main').archive('/tmp/main.tar')
142
+ # git.branch('main').archive('/tmp/main.tar', format: 'tar')
143
143
  #
144
144
  # @example Archive to a zip file
145
145
  # git.branch('main').archive('/tmp/main.zip', format: 'zip')
146
146
  #
147
+ # @example Archive a remote branch to a tgz file
148
+ # git.remote('origin').branch('main').archive('/tmp/main.tgz', format: 'tgz')
149
+ #
147
150
  # @param file [String] path to the destination archive file
148
151
  #
149
152
  # @param opts [Hash] archive options (see {Git::Repository#archive})
150
153
  #
154
+ # @option opts [String] :format ('zip') archive format for this wrapper:
155
+ # `'tar'`, `'zip'`, or `'tgz'`
156
+ #
157
+ # @option opts [String] :prefix (nil) prefix prepended to every filename
158
+ # in the archive
159
+ #
160
+ # @option opts [String] :path (nil) path within the tree to include in the
161
+ # archive
162
+ #
163
+ # @option opts [String] :remote (nil) retrieve the archive from a remote
164
+ # repository
165
+ #
166
+ # @option opts [Boolean, nil] :add_gzip (nil) apply gzip compression after
167
+ # writing the archive; set automatically when `format: 'tgz'` is given
168
+ #
151
169
  # @return [String] the path to the written archive file
152
170
  #
171
+ # @raise [ArgumentError] when archive options or destination path are invalid
172
+ #
153
173
  # @raise [Git::FailedError] if `git archive` fails
154
174
  #
155
175
  def archive(file, opts = {})
@@ -175,14 +195,14 @@ module Git
175
195
  #
176
196
  # @param message [String] commit message used when the block returns truthy
177
197
  #
178
- # @yield Executes the block with this branch checked out
179
- #
180
- # @yieldreturn [Object] return a truthy value to commit all changes, a falsy value to hard-reset
181
- #
182
198
  # @return [String] git's stdout from the final checkout back to the original branch
183
199
  #
184
200
  # @raise [Git::FailedError] if any of the underlying git operations (checkout, commit, reset) fail
185
201
  #
202
+ # @yield Executes the block with this branch checked out
203
+ #
204
+ # @yieldreturn [Object] return a truthy value to commit all changes, a falsy value to hard-reset
205
+ #
186
206
  def in_branch(message = 'in branch work')
187
207
  old_current = branch_repository.current_branch
188
208
  checkout
@@ -327,7 +347,7 @@ module Git
327
347
  #
328
348
  # @param commit [String] the commit SHA to point this branch at
329
349
  #
330
- # @return [Git::CommandLineResult] the result of calling `git update-ref`
350
+ # @return [Git::CommandLine::Result] the result of calling `git update-ref`
331
351
  #
332
352
  # @raise [Git::FailedError] if git exits with a non-zero exit status
333
353
  #
@@ -15,16 +15,19 @@ module Git
15
15
  # failure.error_message #=> "branch 'nonexistent' not found."
16
16
  #
17
17
  # @see Git::BranchDeleteResult
18
+ #
18
19
  # @see Git::Commands::Branch::Delete
19
20
  #
20
21
  # @api public
21
22
  #
22
23
  # @!attribute [r] name
23
24
  # The name of the branch that failed to be deleted
25
+ #
24
26
  # @return [String]
25
27
  #
26
28
  # @!attribute [r] error_message
27
29
  # The error message from git explaining why the branch could not be deleted
30
+ #
28
31
  # @return [String]
29
32
  #
30
33
  BranchDeleteFailure = Data.define(:name, :error_message)
@@ -29,25 +29,27 @@ module Git
29
29
  # result.not_deleted.first.error_message #=> "branch 'nonexistent' not found."
30
30
  #
31
31
  # @see Git::BranchInfo
32
+ #
32
33
  # @see Git::BranchDeleteFailure
34
+ #
33
35
  # @see Git::Commands::Branch::Delete
34
36
  #
35
37
  # @api public
36
38
  #
37
39
  # @!attribute [r] deleted
38
40
  # Branches that were successfully deleted
41
+ #
39
42
  # @return [Array<Git::BranchInfo>]
40
43
  #
41
44
  # @!attribute [r] not_deleted
42
45
  # Branches that could not be deleted, with the reason for each failure
46
+ #
43
47
  # @return [Array<Git::BranchDeleteFailure>]
44
48
  #
45
49
  BranchDeleteResult = Data.define(:deleted, :not_deleted) do
46
50
  # Returns true if all requested branches were successfully deleted
47
51
  #
48
- # @return [Boolean] true if no branches failed to delete, false otherwise
49
- #
50
- # @example
52
+ # @example Check if the delete operation succeeded
51
53
  # result = branch_delete.call('feature-branch')
52
54
  # if result.success?
53
55
  # puts "All branches deleted successfully"
@@ -56,6 +58,7 @@ module Git
56
58
  # result.not_deleted.each { |f| puts " #{f.name}: #{f.error_message}" }
57
59
  # end
58
60
  #
61
+ # @return [Boolean] true if no branches failed to delete, false otherwise
59
62
  def success?
60
63
  not_deleted.empty?
61
64
  end
@@ -7,6 +7,12 @@ module Git
7
7
  # - remote_name: the remote name (e.g., 'origin') for remote branches, nil for local
8
8
  # - branch_name: the branch name without the remote prefix
9
9
  #
10
+ # @example Parse branch refnames
11
+ # 'main' => { remote_name: nil, branch_name: 'main' }
12
+ # 'remotes/origin/main' => { remote_name: 'origin', branch_name: 'main' }
13
+ # 'feature/foo' => { remote_name: nil, branch_name: 'feature/foo' }
14
+ # 'remotes/origin/feature/bar' => { remote_name: 'origin', branch_name: 'feature/bar' }
15
+ #
10
16
  # @note This regex is similar to Git::Branch::BRANCH_NAME_REGEXP but uses \A/\z anchors
11
17
  # instead of ^/$ for stricter matching. As part of the architectural redesign,
12
18
  # Git::Branch will eventually be refactored to use BranchInfo internally, at which
@@ -18,12 +24,6 @@ module Git
18
24
  # ambiguity in git refnames that can only be resolved with knowledge of configured
19
25
  # remotes. See: https://github.com/ruby-git/ruby-git/issues/919
20
26
  #
21
- # @example
22
- # 'main' => { remote_name: nil, branch_name: 'main' }
23
- # 'remotes/origin/main' => { remote_name: 'origin', branch_name: 'main' }
24
- # 'feature/foo' => { remote_name: nil, branch_name: 'feature/foo' }
25
- # 'remotes/origin/feature/bar' => { remote_name: 'origin', branch_name: 'feature/bar' }
26
- #
27
27
  # @api private
28
28
  BRANCH_REFNAME_REGEXP = %r{
29
29
  \A # start of string
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'git/command_line'
3
+ require 'git/command_line/result'
4
4
  require 'git/errors'
5
+ require 'process_executer'
5
6
 
6
7
  module Git
7
8
  module CommandLine
@@ -23,7 +24,7 @@ module Git
23
24
  #
24
25
  # @abstract Subclass and implement {#run}
25
26
  #
26
- # @api public
27
+ # @api private
27
28
  #
28
29
  class Base
29
30
  # Create a Base (or subclass) object
@@ -35,7 +36,7 @@ module Git
35
36
  #
36
37
  # @param global_opts [Array<String>] global options to pass to git
37
38
  #
38
- # @param logger [Logger] the logger to use
39
+ # @param logger [Logger] used to log git commands and their results
39
40
  #
40
41
  def initialize(env, binary_path, global_opts, logger)
41
42
  @env = env
@@ -54,8 +55,6 @@ module Git
54
55
  raise NotImplementedError, "#{self.class}#run is not implemented"
55
56
  end
56
57
 
57
- # @attribute [r] env
58
- #
59
58
  # Variables to set (or unset) in the git command's environment
60
59
  #
61
60
  # @example
@@ -70,8 +69,6 @@ module Git
70
69
  #
71
70
  attr_reader :env
72
71
 
73
- # @attribute [r] binary_path
74
- #
75
72
  # The path to the command line binary to run
76
73
  #
77
74
  # @example
@@ -82,8 +79,6 @@ module Git
82
79
  #
83
80
  attr_reader :binary_path
84
81
 
85
- # @attribute [r] global_opts
86
- #
87
82
  # The global options to pass to git
88
83
  #
89
84
  # These are options that are passed to git before the command name and
@@ -99,8 +94,6 @@ module Git
99
94
  #
100
95
  attr_reader :global_opts
101
96
 
102
- # @attribute [r] logger
103
- #
104
97
  # The logger to use for logging git commands and results
105
98
  #
106
99
  # @example
@@ -149,6 +142,8 @@ module Git
149
142
  # Yield to a block that calls ProcessExecuter and translate any ProcessExecuter
150
143
  # errors to their ruby-git equivalents
151
144
  #
145
+ # @return [Object] the return value of the block
146
+ #
152
147
  # @raise [ArgumentError] in place of ProcessExecuter::ArgumentError
153
148
  #
154
149
  # @raise [Git::Error] in place of ProcessExecuter::SpawnError (binary not found or
@@ -161,8 +156,6 @@ module Git
161
156
  # timeout firing and the kill signal being delivered. This is a race in
162
157
  # process_executer's timeout handling and is semantically equivalent to a timeout.
163
158
  #
164
- # @return [Object] the return value of the block
165
- #
166
159
  # @api private
167
160
  #
168
161
  def run_process_executer
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'git/command_line'
3
+ require 'git/command_line/base'
4
+ require 'git/encoding_utils'
4
5
 
5
6
  module Git
6
7
  module CommandLine
@@ -27,6 +28,8 @@ module Git
27
28
  #
28
29
  # @see Git::CommandLine::Streaming
29
30
  #
31
+ # @api private
32
+ #
30
33
  class Capturing < Git::CommandLine::Base
31
34
  # Default options accepted by {#run}
32
35
  #
@@ -139,7 +142,7 @@ module Git
139
142
  # overrides for this command. String keys map to String values (to set) or
140
143
  # `nil` (to unset).
141
144
  #
142
- # @return [Git::CommandLineResult] the result of the command
145
+ # @return [Git::CommandLine::Result] the result of the command
143
146
  #
144
147
  # @raise [ArgumentError] if `args` contains an array or an unknown option is
145
148
  # passed
@@ -164,12 +167,36 @@ module Git
164
167
 
165
168
  private
166
169
 
170
+ # Execute the git command with the given arguments and options, capturing the output
171
+ #
172
+ # @param args [Array<String>] the git command arguments
173
+ #
174
+ # @param options_hash [Hash] the merged run options forwarded from {#run}
175
+ #
176
+ # Only the keys consumed by this method are listed below; remaining keys
177
+ # from {RUN_OPTION_DEFAULTS} (`:normalize`, `:chomp`, `:raise_on_failure`)
178
+ # are present in the hash but are not used here.
179
+ #
180
+ # @option options_hash [IO, nil] :in stdin IO object for the subprocess
181
+ #
182
+ # @option options_hash [#write, nil] :out stdout redirect target
183
+ #
184
+ # @option options_hash [#write, nil] :err stderr redirect target
185
+ #
186
+ # @option options_hash [String, nil] :chdir working directory for the subprocess
187
+ #
188
+ # @option options_hash [Numeric, nil] :timeout execution timeout in seconds
189
+ #
190
+ # @option options_hash [Boolean] :merge (false) merge stdout into stderr
191
+ #
192
+ # @option options_hash [Hash] :env ({}) environment variable overrides
193
+ #
167
194
  # @return [ProcessExecuter::ResultWithCapture] the process result with captured output
168
195
  #
169
196
  # @api private
170
197
  def execute(*args, **options_hash)
171
198
  git_cmd = build_git_cmd(args)
172
- options = execute_options(**options_hash)
199
+ options = execution_options(**options_hash)
173
200
  run_process_executer do
174
201
  ProcessExecuter.run_with_capture(merged_env(options_hash), *git_cmd, **options)
175
202
  end
@@ -177,10 +204,24 @@ module Git
177
204
 
178
205
  # Build the ProcessExecuter options hash for a capturing run
179
206
  #
207
+ # @param options_hash [Hash] the merged run options forwarded from {#run}
208
+ #
209
+ # @option options_hash [IO, nil] :in stdin IO object for the subprocess
210
+ #
211
+ # @option options_hash [#write, nil] :out stdout redirect target
212
+ #
213
+ # @option options_hash [#write, nil] :err stderr redirect target
214
+ #
215
+ # @option options_hash [String, nil] :chdir working directory for the subprocess
216
+ #
217
+ # @option options_hash [Numeric, nil] :timeout execution timeout in seconds
218
+ #
219
+ # @option options_hash [Boolean] :merge (false) merge stdout into stderr
220
+ #
180
221
  # @return [Hash]
181
222
  #
182
223
  # @api private
183
- def execute_options(**options_hash)
224
+ def execution_options(**options_hash)
184
225
  chdir = options_hash[:chdir] || :not_set
185
226
  timeout_after = options_hash[:timeout]
186
227
  merge_output = options_hash[:merge] || false
@@ -190,14 +231,22 @@ module Git
190
231
  end
191
232
  end
192
233
 
193
- # Extract non-nil redirect options (`:in`, `:out`, `:err`) from options_hash
234
+ # Extract non-nil redirect options (`:in`, `:out`, `:err`) from `options`
194
235
  #
195
- # @return [Hash]
236
+ # @param options [Hash] the options hash containing potential redirect options
237
+ #
238
+ # @option options [IO, nil] :in the input IO stream
239
+ #
240
+ # @option options [#write, nil] :out the output IO stream
241
+ #
242
+ # @option options [#write, nil] :err the error IO stream
243
+ #
244
+ # @return [Hash] the non-nil redirect options
196
245
  #
197
246
  # @api private
198
- def redirect_options(options_hash)
247
+ def redirect_options(options)
199
248
  %i[in out err].filter_map do |key|
200
- val = options_hash[key]
249
+ val = options[key]
201
250
  [key, val] unless val.nil?
202
251
  end.to_h
203
252
  end
@@ -207,9 +256,17 @@ module Git
207
256
  #
208
257
  # @param result [ProcessExecuter::ResultWithCapture] the raw result
209
258
  #
210
- # @param options [Hash] the merged run options
259
+ # @param options [Hash] the merged run options forwarded from {#run}
260
+ #
261
+ # @option options [Boolean] :normalize (false) normalize encoding of captured output
262
+ #
263
+ # @option options [Boolean] :chomp (false) chomp trailing newlines from captured output
264
+ #
265
+ # @option options [Numeric, nil] :timeout execution timeout used to construct the result
266
+ #
267
+ # @option options [Boolean] :raise_on_failure (true) raise {Git::FailedError} on non-zero exit
211
268
  #
212
- # @return [Git::CommandLineResult]
269
+ # @return [Git::CommandLine::Result]
213
270
  #
214
271
  # @raise [Git::FailedError] if the command failed and raise_on_failure is true
215
272
  #
@@ -35,8 +35,6 @@ module Git
35
35
  @stderr = stderr
36
36
  end
37
37
 
38
- # @attribute [r] git_cmd
39
- #
40
38
  # The git command that was executed
41
39
  #
42
40
  # @example
@@ -48,8 +46,6 @@ module Git
48
46
  #
49
47
  attr_reader :git_cmd
50
48
 
51
- # @attribute [r] status
52
- #
53
49
  # The process result object returned by ProcessExecuter
54
50
  #
55
51
  # In practice this is a `ProcessExecuter::ResultWithCapture` (from
@@ -66,8 +62,6 @@ module Git
66
62
  #
67
63
  attr_reader :status
68
64
 
69
- # @attribute [r] stdout
70
- #
71
65
  # The output of the process
72
66
  #
73
67
  # @example
@@ -79,8 +73,6 @@ module Git
79
73
  #
80
74
  attr_reader :stdout
81
75
 
82
- # @attribute [r] stderr
83
- #
84
76
  # The error output of the process
85
77
  #
86
78
  # @example
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'git/command_line'
3
+ require 'git/command_line/base'
4
4
  require 'stringio'
5
5
 
6
6
  module Git
@@ -30,6 +30,8 @@ module Git
30
30
  #
31
31
  # @see Git::CommandLine::Capturing
32
32
  #
33
+ # @api private
34
+ #
33
35
  class Streaming < Git::CommandLine::Base
34
36
  # Default options accepted by {#run}
35
37
  #
@@ -89,7 +91,7 @@ module Git
89
91
  # overrides for this command. String keys map to String values (to set) or
90
92
  # `nil` (to unset).
91
93
  #
92
- # @return [Git::CommandLineResult] the result of the command
94
+ # @return [Git::CommandLine::Result] the result of the command
93
95
  #
94
96
  # `result.stdout` will always be `''` (empty) — stdout was streamed to `out:`.
95
97
  # `result.stderr` contains any stderr output captured for diagnostics.
@@ -122,6 +124,28 @@ module Git
122
124
 
123
125
  private
124
126
 
127
+ # Execute the git command in streaming mode
128
+ #
129
+ # @param args [Array<String>] the git command arguments
130
+ #
131
+ # @param err_io [StringIO, #write] the internal stderr destination
132
+ #
133
+ # @param options_hash [Hash] the merged run options forwarded from {#run}
134
+ #
135
+ # Only the keys consumed by this method are listed below; `:err` and
136
+ # `:raise_on_failure` are present in the hash but not used here (`:err`
137
+ # is handled via the separate `err_io:` argument).
138
+ #
139
+ # @option options_hash [IO, nil] :in stdin IO object for the subprocess
140
+ #
141
+ # @option options_hash [#write, nil] :out stdout streaming destination
142
+ #
143
+ # @option options_hash [String, nil] :chdir working directory for the subprocess
144
+ #
145
+ # @option options_hash [Numeric, nil] :timeout execution timeout in seconds
146
+ #
147
+ # @option options_hash [Hash] :env ({}) environment variable overrides
148
+ #
125
149
  # @return [ProcessExecuter::Result] the result of running the command (non-capturing)
126
150
  #
127
151
  # @api private
@@ -135,6 +159,18 @@ module Git
135
159
 
136
160
  # Build the ProcessExecuter options hash for a streaming run
137
161
  #
162
+ # @param err_io [StringIO, #write] the stderr destination (internal buffer or tee)
163
+ #
164
+ # @param options_hash [Hash] the merged run options forwarded from {#run}
165
+ #
166
+ # @option options_hash [IO, nil] :in stdin IO object for the subprocess
167
+ #
168
+ # @option options_hash [#write, nil] :out stdout streaming destination
169
+ #
170
+ # @option options_hash [String, nil] :chdir working directory for the subprocess
171
+ #
172
+ # @option options_hash [Numeric, nil] :timeout execution timeout in seconds
173
+ #
138
174
  # @return [Hash]
139
175
  #
140
176
  # @api private
@@ -170,7 +206,7 @@ module Git
170
206
  end
171
207
  end
172
208
 
173
- # Process the result of a streaming command and return a Git::CommandLineResult
209
+ # Process the result of a streaming command and return a Git::CommandLine::Result
174
210
  #
175
211
  # Constructs stdout as `''` (not captured) and stderr from the internal StringIO.
176
212
  #
@@ -178,9 +214,13 @@ module Git
178
214
  #
179
215
  # @param err_io [StringIO] the internal StringIO that captured stderr
180
216
  #
181
- # @param options [Hash] the merged run options
217
+ # @param options [Hash] the merged run options forwarded from {#run}
218
+ #
219
+ # @option options [Numeric, nil] :timeout execution timeout used to construct the result
220
+ #
221
+ # @option options [Boolean] :raise_on_failure (true) raise {Git::FailedError} on non-zero exit
182
222
  #
183
- # @return [Git::CommandLineResult]
223
+ # @return [Git::CommandLine::Result]
184
224
  #
185
225
  # @api private
186
226
  def process_result(result, err_io, options)
@@ -19,9 +19,7 @@ module Git
19
19
  # {Git::ExecutionContext#command_streaming}.
20
20
  #
21
21
  # Results are returned as {Git::CommandLine::Result} objects (also accessible
22
- # as {Git::CommandLineResult} for backward compatibility).
23
- #
24
- # @api public
22
+ # as {Git::CommandLine::Result} for backward compatibility).
25
23
  #
26
24
  # @example Buffered command via Git::CommandLine::Capturing
27
25
  # cli = Git::CommandLine::Capturing.new(
@@ -39,8 +37,11 @@ module Git
39
37
  # end
40
38
  #
41
39
  # @see Git::CommandLine::Base
40
+ #
42
41
  # @see Git::CommandLine::Result
43
42
  #
43
+ # @api private
44
+ #
44
45
  module CommandLine
45
46
  end
46
47
  end