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,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git/commands/commit'
4
+ require 'git/commands/commit_tree'
5
+ require 'git/commands/write_tree'
6
+ require 'git/repository/shared_private'
7
+
8
+ module Git
9
+ class Repository
10
+ # Facade methods for committing operations: recording commits, manipulating
11
+ # tree objects, and building commit objects outside the working tree
12
+ #
13
+ # Included by {Git::Repository}.
14
+ #
15
+ # @api public
16
+ #
17
+ module Committing
18
+ # Option keys accepted by {#commit}
19
+ COMMIT_ALLOWED_OPTS = %i[
20
+ all amend allow_empty allow_empty_message author date
21
+ gpg_sign no_gpg_sign no_verify
22
+ ].freeze
23
+ private_constant :COMMIT_ALLOWED_OPTS
24
+
25
+ # Option keys accepted by {#commit_tree}
26
+ COMMIT_TREE_ALLOWED_OPTS = %i[parent p parents message m].freeze
27
+ private_constant :COMMIT_TREE_ALLOWED_OPTS
28
+
29
+ # Record staged changes as a new commit
30
+ #
31
+ # @overload commit(message = nil, **options)
32
+ #
33
+ # @example Commit with a message
34
+ # repo.commit('Add README')
35
+ #
36
+ # @example Amend the previous commit, reusing its message
37
+ # repo.commit(nil, amend: true)
38
+ #
39
+ # @example Stage all modified files and commit
40
+ # repo.commit('Cleanup', all: true)
41
+ #
42
+ # @param message [String, nil] the commit message; pass `nil` to omit
43
+ # (e.g. when using `:amend` to reuse the previous message)
44
+ #
45
+ # @param options [Hash] options for the commit command
46
+ #
47
+ # @option options [Boolean, nil] :all (nil) automatically stage modified and
48
+ # deleted files before committing
49
+ #
50
+ # @option options [Boolean, nil] :amend (nil) replace the tip of the current
51
+ # branch with a new commit
52
+ #
53
+ # @option options [Boolean, nil] :allow_empty (nil) allow committing with no
54
+ # changes
55
+ #
56
+ # @option options [Boolean, nil] :allow_empty_message (nil) allow committing
57
+ # with an empty message
58
+ #
59
+ # @option options [String] :author (nil) override the commit author in
60
+ # `A U Thor <author@example.com>` format
61
+ #
62
+ # @option options [String] :date (nil) override the author date
63
+ #
64
+ # @option options [Boolean, nil] :gpg_sign (nil) GPG-sign the commit
65
+ #
66
+ # @option options [Boolean, nil] :no_gpg_sign (nil) disable GPG signing
67
+ #
68
+ # @option options [Boolean, nil] :no_verify (nil) bypass the pre-commit and
69
+ # commit-msg hooks
70
+ #
71
+ # @return [String] git's stdout from the commit
72
+ #
73
+ # @raise [ArgumentError] when unsupported options are provided
74
+ #
75
+ # @raise [Git::FailedError] when git exits with a non-zero exit status
76
+ #
77
+ def commit(message = nil, **opts)
78
+ if opts.key?(:add_all)
79
+ Git::Deprecation.warn('The :add_all option for #commit is deprecated, use :all instead')
80
+ opts[:all] = opts.delete(:add_all)
81
+ end
82
+
83
+ SharedPrivate.assert_valid_opts!(COMMIT_ALLOWED_OPTS, **opts)
84
+
85
+ call_opts = { no_edit: true }
86
+ call_opts[:message] = message if message
87
+
88
+ Git::Commands::Commit.new(@execution_context).call(**call_opts, **opts).stdout
89
+ end
90
+
91
+ # Commit all modified tracked files without explicitly staging them first
92
+ #
93
+ # Equivalent to `commit(message, all: true, **options)`.
94
+ #
95
+ # @overload commit_all(message, **options)
96
+ #
97
+ # @example Commit all changes with a message
98
+ # repo.commit_all('Update everything')
99
+ #
100
+ # @param message [String] the commit message
101
+ #
102
+ # @param options [Hash] additional options forwarded to {#commit}
103
+ #
104
+ # @return [String] git's stdout from the commit
105
+ #
106
+ # @raise [ArgumentError] when unsupported options are provided
107
+ #
108
+ # @raise [Git::FailedError] when git exits with a non-zero exit status
109
+ #
110
+ def commit_all(*, **)
111
+ commit(*, all: true, **)
112
+ end
113
+
114
+ # Create a commit object from a tree SHA without moving HEAD
115
+ #
116
+ # Unlike {#commit}, this does not read the index; it directly wraps
117
+ # `git commit-tree`.
118
+ #
119
+ # @overload commit_tree(tree, **options)
120
+ #
121
+ # @example Commit a tree with a parent
122
+ # repo.commit_tree('deadbeef', message: 'snapshot', parent: 'HEAD')
123
+ #
124
+ # @param tree [String] the tree SHA to commit
125
+ #
126
+ # @param options [Hash] options for the commit-tree command
127
+ #
128
+ # @option options [String] :m (nil) the commit message (short form)
129
+ #
130
+ # @option options [String] :message (nil) the commit message (normalized
131
+ # to `:m` before passing to the command)
132
+ #
133
+ # @option options [String, Array<String>] :p (nil) parent commit SHA(s)
134
+ #
135
+ # @option options [String] :parent (nil) a single parent commit SHA
136
+ # (normalized to `:p`)
137
+ #
138
+ # @option options [Array<String>] :parents (nil) multiple parent commit
139
+ # SHAs (normalized to `:p`)
140
+ #
141
+ # @return [String] the SHA of the newly created commit object
142
+ #
143
+ # @raise [ArgumentError] when unsupported options are provided
144
+ #
145
+ # @raise [Git::FailedError] when git exits with a non-zero exit status
146
+ #
147
+ def commit_tree(tree, **opts)
148
+ SharedPrivate.assert_valid_opts!(COMMIT_TREE_ALLOWED_OPTS, **opts)
149
+
150
+ opts[:p] = opts.delete(:parents) if opts.key?(:parents)
151
+ opts[:p] = opts.delete(:parent) if opts.key?(:parent)
152
+ opts[:m] = opts.delete(:message) if opts.key?(:message)
153
+ opts[:m] = "commit tree #{tree}" unless opts[:m]
154
+
155
+ Git::Commands::CommitTree.new(@execution_context).call(tree, **opts).stdout
156
+ end
157
+
158
+ # Write the current index to a tree object in the object store
159
+ #
160
+ # @example Get the tree SHA of the current index
161
+ # tree_sha = repo.write_tree
162
+ #
163
+ # @return [String] the SHA of the tree object written
164
+ #
165
+ # @raise [Git::FailedError] when git exits with a non-zero exit status
166
+ #
167
+ def write_tree
168
+ Git::Commands::WriteTree.new(@execution_context).call.stdout
169
+ end
170
+
171
+ # Write the current index to a tree object and immediately commit it
172
+ #
173
+ # Combines {#write_tree} and {#commit_tree} in a single call.
174
+ #
175
+ # @overload write_and_commit_tree(**options)
176
+ #
177
+ # @example Commit the current index as a snapshot
178
+ # commit_sha = repo.write_and_commit_tree(message: 'snapshot')
179
+ #
180
+ # @param options [Hash] options forwarded to {#commit_tree}
181
+ #
182
+ # @return [String] the SHA of the newly created commit object
183
+ #
184
+ # @raise [Git::FailedError] when git exits with a non-zero exit status
185
+ #
186
+ def write_and_commit_tree(**)
187
+ commit_tree(write_tree, **)
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git/commands/config_option_syntax'
4
+ require 'git/repository/shared_private'
5
+
6
+ module Git
7
+ class Repository
8
+ # Facade methods for reading and writing git configuration
9
+ #
10
+ # Provides the {#config} method, which dispatches to read a single entry,
11
+ # list all entries, or write a value depending on the arguments supplied.
12
+ #
13
+ # Included by {Git::Repository}.
14
+ #
15
+ # @api public
16
+ #
17
+ module Configuring
18
+ # Option keys accepted by {#config} when writing a value
19
+ CONFIG_SET_ALLOWED_OPTS = %i[file].freeze
20
+ private_constant :CONFIG_SET_ALLOWED_OPTS
21
+
22
+ # Read or write a git configuration entry
23
+ #
24
+ # Dispatches to one of three modes depending on the arguments supplied:
25
+ #
26
+ # * **List** — `config()` returns all visible config entries as a `Hash`.
27
+ # * **Get** — `config(name)` returns the value for a single key as a `String`.
28
+ # * **Set** — `config(name, value)` writes a value and returns the raw
29
+ # command result.
30
+ #
31
+ # @overload config
32
+ #
33
+ # @example List all config entries
34
+ # repo.config #=> { "user.name" => "Alice", "core.bare" => "false" }
35
+ #
36
+ # @return [Hash{String => String}] all visible config entries, keyed by
37
+ # their full dotted key names (e.g. `"user.name"`)
38
+ #
39
+ # @overload config(name)
40
+ #
41
+ # @example Read the committer name from config
42
+ # repo.config('user.name') #=> "Alice"
43
+ #
44
+ # @param name [String] the dotted config key to look up (e.g.
45
+ # `"user.name"`)
46
+ #
47
+ # @return [String] the value of the config entry
48
+ #
49
+ # @overload config(name, value, options = {})
50
+ #
51
+ # @example Set the committer name in local config
52
+ # repo.config('user.name', 'Alice')
53
+ #
54
+ # @example Write a value to a custom config file
55
+ # repo.config('user.name', 'Alice', file: '/path/to/custom/config')
56
+ #
57
+ # @param name [String] the dotted config key to write (e.g.
58
+ # `"user.name"`)
59
+ #
60
+ # @param value [String] the value to assign
61
+ #
62
+ # @param options [Hash] options for the set operation
63
+ #
64
+ # @option options [String, nil] :file (nil) path to a custom config file
65
+ # to write to instead of the repository's default `.git/config`
66
+ #
67
+ # @return [Git::CommandLineResult] the raw result of
68
+ # `git config <name> <value>`
69
+ #
70
+ # @raise [ArgumentError] if unsupported options are provided
71
+ #
72
+ # @raise [Git::FailedError] if git exits with a non-zero exit status
73
+ #
74
+ def config(name = nil, value = nil, options = {})
75
+ if name && value
76
+ Private.config_set(@execution_context, name, value, **options)
77
+ elsif name
78
+ Private.config_get(@execution_context, name)
79
+ else
80
+ Private.config_list(@execution_context)
81
+ end
82
+ end
83
+
84
+ # Private helpers local to {Git::Repository::Configuring}
85
+ #
86
+ # @api private
87
+ #
88
+ module Private
89
+ module_function
90
+
91
+ # Set a config value by key name
92
+ #
93
+ # @overload config_set(execution_context, name, value, **options)
94
+ #
95
+ # @param execution_context [Git::ExecutionContext] the execution context
96
+ #
97
+ # @param name [String] the dotted config key to write (e.g. `"user.name"`)
98
+ #
99
+ # @param value [String] the value to assign
100
+ #
101
+ # @param options [Hash] keyword options forwarded to the command
102
+ #
103
+ # @option options [String, nil] :file (nil) path to a custom config file
104
+ # to write to instead of the repository's default `.git/config`
105
+ #
106
+ # @return [Git::CommandLineResult] the raw result of
107
+ # `git config <name> <value>`
108
+ #
109
+ # @raise [ArgumentError] if unsupported options are provided
110
+ #
111
+ # @raise [Git::FailedError] if git exits with a non-zero exit status
112
+ #
113
+ def config_set(execution_context, name, value, **)
114
+ SharedPrivate.assert_valid_opts!(CONFIG_SET_ALLOWED_OPTS, **)
115
+ Git::Commands::ConfigOptionSyntax::Set.new(execution_context).call(name, value, **)
116
+ end
117
+
118
+ # Retrieve a config value by key name
119
+ #
120
+ # @param execution_context [Git::ExecutionContext] the execution context
121
+ #
122
+ # @param name [String] the dotted config key to look up (e.g. `"user.name"`)
123
+ #
124
+ # @return [String] the value of the config entry
125
+ #
126
+ # @raise [Git::FailedError] if git exits with a non-zero exit status
127
+ #
128
+ def config_get(execution_context, name)
129
+ result = Git::Commands::ConfigOptionSyntax::Get.new(execution_context).call(name)
130
+ raise Git::FailedError, result if result.status.exitstatus != 0
131
+
132
+ result.stdout
133
+ end
134
+
135
+ # Retrieve all config entries as a hash
136
+ #
137
+ # @param execution_context [Git::ExecutionContext] the execution context
138
+ #
139
+ # @return [Hash{String => String}] all config entries, keyed by their full
140
+ # dotted key names (e.g. `"user.name"`)
141
+ #
142
+ # @raise [Git::FailedError] if git exits with a non-zero exit status
143
+ #
144
+ def config_list(execution_context)
145
+ lines = Git::Commands::ConfigOptionSyntax::List.new(execution_context).call.stdout.split("\n")
146
+ lines.each_with_object({}) do |line, hsh|
147
+ key, value = line.split('=', 2)
148
+ hsh[key] = value || ''
149
+ end
150
+ end
151
+ end
152
+
153
+ private_constant :Private
154
+ end
155
+ end
156
+ end