git 1.19.1 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (265) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -1
  3. data/AI_POLICY.md +24 -0
  4. data/CHANGELOG.md +689 -0
  5. data/CODE_OF_CONDUCT.md +25 -0
  6. data/CONTRIBUTING.md +1175 -97
  7. data/GOVERNANCE.md +106 -0
  8. data/LICENSE +1 -1
  9. data/MAINTAINERS.md +17 -4
  10. data/README.md +476 -320
  11. data/UPGRADING.md +1138 -0
  12. data/git.gemspec +124 -36
  13. data/lib/git/author.rb +39 -7
  14. data/lib/git/author_info.rb +66 -0
  15. data/lib/git/branch.rb +615 -65
  16. data/lib/git/branch_delete_failure.rb +34 -0
  17. data/lib/git/branch_delete_result.rb +66 -0
  18. data/lib/git/branch_info.rb +237 -0
  19. data/lib/git/branches.rb +167 -44
  20. data/lib/git/command_line/base.rb +247 -0
  21. data/lib/git/command_line/capturing.rb +308 -0
  22. data/lib/git/command_line/result.rb +88 -0
  23. data/lib/git/command_line/streaming.rb +236 -0
  24. data/lib/git/command_line.rb +52 -0
  25. data/lib/git/commands/add.rb +139 -0
  26. data/lib/git/commands/am/abort.rb +43 -0
  27. data/lib/git/commands/am/apply.rb +263 -0
  28. data/lib/git/commands/am/continue.rb +43 -0
  29. data/lib/git/commands/am/quit.rb +43 -0
  30. data/lib/git/commands/am/retry.rb +49 -0
  31. data/lib/git/commands/am/show_current_patch.rb +64 -0
  32. data/lib/git/commands/am/skip.rb +42 -0
  33. data/lib/git/commands/am.rb +33 -0
  34. data/lib/git/commands/apply.rb +242 -0
  35. data/lib/git/commands/archive/list_formats.rb +46 -0
  36. data/lib/git/commands/archive.rb +145 -0
  37. data/lib/git/commands/arguments.rb +4521 -0
  38. data/lib/git/commands/base.rb +502 -0
  39. data/lib/git/commands/branch/copy.rb +102 -0
  40. data/lib/git/commands/branch/create.rb +177 -0
  41. data/lib/git/commands/branch/delete.rb +88 -0
  42. data/lib/git/commands/branch/list.rb +178 -0
  43. data/lib/git/commands/branch/move.rb +102 -0
  44. data/lib/git/commands/branch/set_upstream.rb +86 -0
  45. data/lib/git/commands/branch/show_current.rb +49 -0
  46. data/lib/git/commands/branch/unset_upstream.rb +53 -0
  47. data/lib/git/commands/branch.rb +34 -0
  48. data/lib/git/commands/cat_file/batch.rb +385 -0
  49. data/lib/git/commands/cat_file/filtered.rb +105 -0
  50. data/lib/git/commands/cat_file/raw.rb +271 -0
  51. data/lib/git/commands/cat_file.rb +49 -0
  52. data/lib/git/commands/checkout/branch.rb +153 -0
  53. data/lib/git/commands/checkout/files.rb +116 -0
  54. data/lib/git/commands/checkout.rb +38 -0
  55. data/lib/git/commands/checkout_index.rb +106 -0
  56. data/lib/git/commands/clean.rb +102 -0
  57. data/lib/git/commands/clone.rb +241 -0
  58. data/lib/git/commands/commit.rb +273 -0
  59. data/lib/git/commands/commit_tree.rb +101 -0
  60. data/lib/git/commands/config_option_syntax/add.rb +86 -0
  61. data/lib/git/commands/config_option_syntax/get.rb +121 -0
  62. data/lib/git/commands/config_option_syntax/get_all.rb +118 -0
  63. data/lib/git/commands/config_option_syntax/get_color.rb +95 -0
  64. data/lib/git/commands/config_option_syntax/get_color_bool.rb +96 -0
  65. data/lib/git/commands/config_option_syntax/get_regexp.rb +119 -0
  66. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +111 -0
  67. data/lib/git/commands/config_option_syntax/list.rb +111 -0
  68. data/lib/git/commands/config_option_syntax/remove_section.rb +79 -0
  69. data/lib/git/commands/config_option_syntax/rename_section.rb +83 -0
  70. data/lib/git/commands/config_option_syntax/replace_all.rb +109 -0
  71. data/lib/git/commands/config_option_syntax/set.rb +119 -0
  72. data/lib/git/commands/config_option_syntax/unset.rb +92 -0
  73. data/lib/git/commands/config_option_syntax/unset_all.rb +94 -0
  74. data/lib/git/commands/config_option_syntax.rb +56 -0
  75. data/lib/git/commands/describe.rb +156 -0
  76. data/lib/git/commands/diff.rb +657 -0
  77. data/lib/git/commands/diff_files.rb +519 -0
  78. data/lib/git/commands/diff_index.rb +499 -0
  79. data/lib/git/commands/fetch.rb +354 -0
  80. data/lib/git/commands/fsck.rb +138 -0
  81. data/lib/git/commands/gc.rb +134 -0
  82. data/lib/git/commands/grep.rb +339 -0
  83. data/lib/git/commands/init.rb +101 -0
  84. data/lib/git/commands/log.rb +634 -0
  85. data/lib/git/commands/ls_files.rb +195 -0
  86. data/lib/git/commands/ls_remote.rb +161 -0
  87. data/lib/git/commands/ls_tree.rb +135 -0
  88. data/lib/git/commands/maintenance/register.rb +77 -0
  89. data/lib/git/commands/maintenance/run.rb +109 -0
  90. data/lib/git/commands/maintenance/start.rb +71 -0
  91. data/lib/git/commands/maintenance/stop.rb +60 -0
  92. data/lib/git/commands/maintenance/unregister.rb +84 -0
  93. data/lib/git/commands/maintenance.rb +31 -0
  94. data/lib/git/commands/merge/abort.rb +44 -0
  95. data/lib/git/commands/merge/continue.rb +44 -0
  96. data/lib/git/commands/merge/quit.rb +46 -0
  97. data/lib/git/commands/merge/start.rb +250 -0
  98. data/lib/git/commands/merge.rb +28 -0
  99. data/lib/git/commands/merge_base.rb +91 -0
  100. data/lib/git/commands/mv.rb +82 -0
  101. data/lib/git/commands/name_rev.rb +119 -0
  102. data/lib/git/commands/pull.rb +382 -0
  103. data/lib/git/commands/push.rb +251 -0
  104. data/lib/git/commands/read_tree.rb +154 -0
  105. data/lib/git/commands/remote/add.rb +96 -0
  106. data/lib/git/commands/remote/get_url.rb +68 -0
  107. data/lib/git/commands/remote/list.rb +56 -0
  108. data/lib/git/commands/remote/prune.rb +63 -0
  109. data/lib/git/commands/remote/remove.rb +52 -0
  110. data/lib/git/commands/remote/rename.rb +76 -0
  111. data/lib/git/commands/remote/set_branches.rb +70 -0
  112. data/lib/git/commands/remote/set_head.rb +89 -0
  113. data/lib/git/commands/remote/set_url.rb +78 -0
  114. data/lib/git/commands/remote/set_url_add.rb +70 -0
  115. data/lib/git/commands/remote/set_url_delete.rb +71 -0
  116. data/lib/git/commands/remote/show.rb +77 -0
  117. data/lib/git/commands/remote/update.rb +79 -0
  118. data/lib/git/commands/remote.rb +42 -0
  119. data/lib/git/commands/repack.rb +281 -0
  120. data/lib/git/commands/reset.rb +154 -0
  121. data/lib/git/commands/rev_parse.rb +304 -0
  122. data/lib/git/commands/revert/abort.rb +45 -0
  123. data/lib/git/commands/revert/continue.rb +62 -0
  124. data/lib/git/commands/revert/quit.rb +47 -0
  125. data/lib/git/commands/revert/skip.rb +44 -0
  126. data/lib/git/commands/revert/start.rb +158 -0
  127. data/lib/git/commands/revert.rb +29 -0
  128. data/lib/git/commands/rm.rb +113 -0
  129. data/lib/git/commands/show.rb +632 -0
  130. data/lib/git/commands/show_ref/exclude_existing.rb +119 -0
  131. data/lib/git/commands/show_ref/exists.rb +80 -0
  132. data/lib/git/commands/show_ref/list.rb +149 -0
  133. data/lib/git/commands/show_ref/verify.rb +122 -0
  134. data/lib/git/commands/show_ref.rb +42 -0
  135. data/lib/git/commands/stash/apply.rb +81 -0
  136. data/lib/git/commands/stash/branch.rb +67 -0
  137. data/lib/git/commands/stash/clear.rb +43 -0
  138. data/lib/git/commands/stash/create.rb +60 -0
  139. data/lib/git/commands/stash/drop.rb +73 -0
  140. data/lib/git/commands/stash/list.rb +43 -0
  141. data/lib/git/commands/stash/pop.rb +87 -0
  142. data/lib/git/commands/stash/push.rb +112 -0
  143. data/lib/git/commands/stash/show.rb +158 -0
  144. data/lib/git/commands/stash/store.rb +72 -0
  145. data/lib/git/commands/stash.rb +38 -0
  146. data/lib/git/commands/status.rb +174 -0
  147. data/lib/git/commands/symbolic_ref/delete.rb +72 -0
  148. data/lib/git/commands/symbolic_ref/read.rb +99 -0
  149. data/lib/git/commands/symbolic_ref/update.rb +79 -0
  150. data/lib/git/commands/symbolic_ref.rb +38 -0
  151. data/lib/git/commands/tag/create.rb +142 -0
  152. data/lib/git/commands/tag/delete.rb +57 -0
  153. data/lib/git/commands/tag/list.rb +146 -0
  154. data/lib/git/commands/tag/verify.rb +71 -0
  155. data/lib/git/commands/tag.rb +26 -0
  156. data/lib/git/commands/update_ref/batch.rb +145 -0
  157. data/lib/git/commands/update_ref/delete.rb +90 -0
  158. data/lib/git/commands/update_ref/update.rb +103 -0
  159. data/lib/git/commands/update_ref.rb +42 -0
  160. data/lib/git/commands/version.rb +60 -0
  161. data/lib/git/commands/worktree/add.rb +139 -0
  162. data/lib/git/commands/worktree/list.rb +64 -0
  163. data/lib/git/commands/worktree/lock.rb +58 -0
  164. data/lib/git/commands/worktree/management_base.rb +51 -0
  165. data/lib/git/commands/worktree/move.rb +66 -0
  166. data/lib/git/commands/worktree/prune.rb +67 -0
  167. data/lib/git/commands/worktree/remove.rb +63 -0
  168. data/lib/git/commands/worktree/repair.rb +76 -0
  169. data/lib/git/commands/worktree/unlock.rb +47 -0
  170. data/lib/git/commands/worktree.rb +43 -0
  171. data/lib/git/commands/write_tree.rb +68 -0
  172. data/lib/git/commands.rb +88 -0
  173. data/lib/git/config.rb +72 -5
  174. data/lib/git/config_entry_info.rb +106 -0
  175. data/lib/git/configuring.rb +795 -0
  176. data/lib/git/detached_head_info.rb +57 -0
  177. data/lib/git/diff.rb +437 -86
  178. data/lib/git/diff_file_numstat_info.rb +31 -0
  179. data/lib/git/diff_file_patch_info.rb +136 -0
  180. data/lib/git/diff_file_raw_info.rb +129 -0
  181. data/lib/git/diff_info.rb +162 -0
  182. data/lib/git/diff_path_status.rb +107 -0
  183. data/lib/git/diff_result.rb +34 -0
  184. data/lib/git/diff_stats.rb +111 -0
  185. data/lib/git/dirstat_info.rb +102 -0
  186. data/lib/git/encoding_utils.rb +32 -1
  187. data/lib/git/errors.rb +285 -0
  188. data/lib/git/escaped_path.rb +57 -5
  189. data/lib/git/execution_context/global.rb +31 -0
  190. data/lib/git/execution_context/repository.rb +151 -0
  191. data/lib/git/execution_context.rb +559 -0
  192. data/lib/git/factories.rb +813 -0
  193. data/lib/git/file_ref.rb +77 -0
  194. data/lib/git/fsck_object.rb +56 -0
  195. data/lib/git/fsck_result.rb +132 -0
  196. data/lib/git/log.rb +306 -90
  197. data/lib/git/object.rb +563 -141
  198. data/lib/git/parsers/branch.rb +240 -0
  199. data/lib/git/parsers/cat_file.rb +111 -0
  200. data/lib/git/parsers/config_entry.rb +110 -0
  201. data/lib/git/parsers/diff.rb +792 -0
  202. data/lib/git/parsers/fsck.rb +144 -0
  203. data/lib/git/parsers/grep.rb +42 -0
  204. data/lib/git/parsers/ls_remote.rb +79 -0
  205. data/lib/git/parsers/ls_tree.rb +58 -0
  206. data/lib/git/parsers/remote.rb +162 -0
  207. data/lib/git/parsers/stash.rb +292 -0
  208. data/lib/git/parsers/status.rb +251 -0
  209. data/lib/git/parsers/tag.rb +341 -0
  210. data/lib/git/parsers/worktree.rb +185 -0
  211. data/lib/git/path_resolver.rb +206 -0
  212. data/lib/git/remote.rb +165 -12
  213. data/lib/git/remote_info.rb +203 -0
  214. data/lib/git/repository/branching.rb +964 -0
  215. data/lib/git/repository/committing.rb +246 -0
  216. data/lib/git/repository/context_helpers.rb +293 -0
  217. data/lib/git/repository/diffing.rb +785 -0
  218. data/lib/git/repository/inspecting.rb +252 -0
  219. data/lib/git/repository/logging.rb +410 -0
  220. data/lib/git/repository/maintenance.rb +65 -0
  221. data/lib/git/repository/merging.rb +451 -0
  222. data/lib/git/repository/object_operations.rb +1551 -0
  223. data/lib/git/repository/remote_operations.rb +984 -0
  224. data/lib/git/repository/shared_private.rb +120 -0
  225. data/lib/git/repository/staging.rb +587 -0
  226. data/lib/git/repository/stashing.rb +623 -0
  227. data/lib/git/repository/status_operations.rb +249 -0
  228. data/lib/git/repository/worktree_operations.rb +339 -0
  229. data/lib/git/repository.rb +484 -2
  230. data/lib/git/stash.rb +109 -12
  231. data/lib/git/stash_info.rb +102 -0
  232. data/lib/git/stashes.rb +169 -26
  233. data/lib/git/status.rb +308 -122
  234. data/lib/git/status_file_info.rb +258 -0
  235. data/lib/git/status_info.rb +189 -0
  236. data/lib/git/tag_delete_failure.rb +34 -0
  237. data/lib/git/tag_delete_result.rb +66 -0
  238. data/lib/git/tag_info.rb +99 -0
  239. data/lib/git/url.rb +15 -8
  240. data/lib/git/version.rb +113 -2
  241. data/lib/git/version_constraint.rb +85 -0
  242. data/lib/git/worktree.rb +150 -8
  243. data/lib/git/worktree_info.rb +128 -0
  244. data/lib/git/worktrees.rb +118 -13
  245. data/lib/git.rb +632 -234
  246. metadata +369 -54
  247. data/.github/stale.yml +0 -25
  248. data/.github/workflows/continuous_integration.yml +0 -49
  249. data/.gitignore +0 -10
  250. data/Dockerfile.changelog-rs +0 -12
  251. data/Gemfile +0 -5
  252. data/ISSUE_TEMPLATE.md +0 -15
  253. data/PULL_REQUEST_TEMPLATE.md +0 -9
  254. data/RELEASING.md +0 -70
  255. data/Rakefile +0 -60
  256. data/lib/git/base/factory.rb +0 -99
  257. data/lib/git/base.rb +0 -711
  258. data/lib/git/command_line_result.rb +0 -86
  259. data/lib/git/failed_error.rb +0 -53
  260. data/lib/git/git_execute_error.rb +0 -7
  261. data/lib/git/index.rb +0 -5
  262. data/lib/git/lib.rb +0 -1328
  263. data/lib/git/path.rb +0 -31
  264. data/lib/git/signaled_error.rb +0 -50
  265. data/lib/git/working_directory.rb +0 -4
data/git.gemspec CHANGED
@@ -1,52 +1,140 @@
1
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
- require 'git/version'
3
-
4
- Gem::Specification.new do |s|
5
- s.author = 'Scott Chacon and others'
6
- s.email = 'schacon@gmail.com'
7
- s.homepage = 'http://github.com/ruby-git/ruby-git'
8
- s.license = 'MIT'
9
- s.name = 'git'
10
- s.summary = 'An API to create, read, and manipulate Git repositories'
11
- s.description = <<~DESCRIPTION
1
+ # frozen_string_literal: true
2
+
3
+ # Read the version out of lib/git/version.rb rather than requiring it.
4
+ #
5
+ # The Gemfile uses `gemspec`, so Bundler evaluates this file on every `bundle exec`.
6
+ # `require`ing lib/git/version.rb here would therefore load it before SimpleCov
7
+ # starts in spec_helper, leaving it invisible to the coverage report -- an
8
+ # unmeasured hole in the 100% coverage gate. See the "Test coverage policy" section
9
+ # of CONTRIBUTING.md.
10
+ #
11
+ # release-please rewrites the `VERSION = '...'` assignment in place (see
12
+ # `version-file` in .release-please-config.json), so matching on it stays correct
13
+ # across releases. If the match ever fails, the raise below stops the build
14
+ # immediately rather than letting a nil version reach the specification.
15
+ version = File.read(File.expand_path('lib/git/version.rb', __dir__))[/^\s*VERSION\s*=\s*['"]([^'"]+)['"]/, 1]
16
+ raise 'Could not determine Git::VERSION from lib/git/version.rb' if version.nil?
17
+
18
+ Gem::Specification.new do |spec|
19
+ spec.author = 'Scott Chacon and others'
20
+ spec.email = 'schacon@gmail.com'
21
+ spec.homepage = 'http://github.com/ruby-git/ruby-git'
22
+ spec.license = 'MIT'
23
+ spec.name = 'git'
24
+ spec.summary = 'An API to create, read, and manipulate Git repositories'
25
+ spec.description = <<~DESCRIPTION
12
26
  The git gem provides an API that can be used to
13
27
  create, read, and manipulate Git repositories by wrapping system calls to the git
14
28
  command line. The API can be used for working with Git in complex interactions
15
29
  including branching and merging, object inspection and manipulation, history, patch
16
30
  generation and more.
17
31
  DESCRIPTION
18
- s.version = Git::VERSION
32
+ spec.version = version
19
33
 
34
+ spec.metadata['homepage_uri'] = spec.homepage
35
+ spec.metadata['source_code_uri'] = spec.homepage
36
+ spec.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}/file/CHANGELOG.md"
37
+ spec.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}"
38
+ spec.metadata['rubygems_mfa_required'] = 'true'
20
39
 
21
- s.metadata['homepage_uri'] = s.homepage
22
- s.metadata['source_code_uri'] = s.homepage
23
- s.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}/file/CHANGELOG.md"
24
- s.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}"
40
+ spec.require_paths = ['lib']
41
+ spec.required_ruby_version = '>= 3.2.0'
42
+ spec.requirements = ['git 2.28.0 or greater']
25
43
 
26
- s.require_paths = ['lib']
27
- s.required_ruby_version = '>= 2.3'
28
- s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=)
29
- s.requirements = ['git 1.6.0.0, or greater']
44
+ spec.add_dependency 'activesupport', '>= 5.0'
45
+ spec.add_dependency 'addressable', '~> 2.8'
46
+ spec.add_dependency 'process_executer', '~> 4.1'
47
+ spec.add_dependency 'rchardet', '~> 1.9'
30
48
 
31
- s.add_runtime_dependency 'addressable', '~> 2.8'
32
- s.add_runtime_dependency 'rchardet', '~> 1.8'
49
+ # Not every development dependency is installed on every runtime. Each predicate
50
+ # below names one reason for holding a gem back, which keeps the dependency list
51
+ # itself a flat, readable list. Deriving one predicate from another also keeps
52
+ # coupled gems from drifting apart when a condition changes.
53
+ #
54
+ # These are local variables rather than methods deliberately. The Gemfile uses
55
+ # `gemspec`, so Bundler evaluates this file on every `bundle exec`, and a top-level
56
+ # `def` -- including one written inside this block, since a block is not a definition
57
+ # scope -- would define a private method on Object in every one of those processes.
33
58
 
34
- s.add_development_dependency 'bump', '~> 0.10'
35
- s.add_development_dependency 'create_github_release', '~> 0.2'
36
- s.add_development_dependency 'minitar', '~> 0.9'
37
- s.add_development_dependency 'mocha', '~> 2.1'
38
- s.add_development_dependency 'rake', '~> 13.0'
39
- s.add_development_dependency 'test-unit', '~> 3.3'
59
+ # JRuby (which reports RUBY_PLATFORM as 'java') and TruffleRuby build no C extensions
60
+ # and do not run the docs build.
61
+ mri = !(RUBY_PLATFORM == 'java' || RUBY_ENGINE == 'truffleruby')
40
62
 
41
- unless RUBY_PLATFORM == 'java'
42
- s.add_development_dependency 'redcarpet', '~> 3.5'
43
- s.add_development_dependency 'yard', '~> 0.9', '>= 0.9.28'
44
- s.add_development_dependency 'yardstick', '~> 0.9'
45
- end
63
+ # irb stopped being a default gem in Ruby 3.4. JRuby and TruffleRuby ship their own.
64
+ install_irb = mri
65
+
66
+ # Ruby 4.0.0 dropped fiddle from the default gems. On Windows, irb loads
67
+ # reline/io/windows.rb, which requires fiddle/import for the Win32 console API, so
68
+ # bin/console cannot start without it; every other platform takes reline's ANSI IO
69
+ # gate and never loads that file. Derived from install_irb because fiddle exists only
70
+ # to serve irb and, being a C extension, could not install where irb is not.
71
+ install_fiddle = install_irb && Gem.win_platform?
72
+
73
+ # The docs toolchain is supported on MRI only. redcarpet, YARD's Markdown renderer,
74
+ # is also a C extension and so could not install on JRuby regardless.
75
+ install_docs = mri
76
+
77
+ # yard-lint requires Ruby >= 3.3.
78
+ install_yard_lint = install_docs && Gem.ruby_version >= Gem::Version.new('3.3.0')
79
+
80
+ # i18n 1.15+ uses Fiber.[] (Ruby 3.2 Fiber storage), which TruffleRuby < 34.0.0 does
81
+ # not implement, so those runtimes hold at the last release that works there.
82
+ pin_old_i18n = RUBY_ENGINE == 'truffleruby' &&
83
+ Gem::Version.new(RUBY_ENGINE_VERSION) < Gem::Version.new('34.0.0')
84
+
85
+ spec.add_development_dependency 'create_github_release', '~> 2.1'
86
+ spec.add_development_dependency 'fiddle', '~> 1.1' if install_fiddle
87
+ spec.add_development_dependency 'fuubar', '~> 2.5'
88
+ spec.add_development_dependency 'i18n', '< 1.15' if pin_old_i18n
89
+ spec.add_development_dependency 'irb', '~> 1.16' if install_irb
90
+ spec.add_development_dependency 'main_branch_shared_rubocop_config', '~> 0.1'
91
+ spec.add_development_dependency 'parallel_tests', '~> 5.6'
92
+ spec.add_development_dependency 'rake', '~> 13.3'
93
+ spec.add_development_dependency 'redcarpet', '~> 3.6' if install_docs
94
+ spec.add_development_dependency 'rspec', '~> 3.13'
95
+ spec.add_development_dependency 'rubocop', '~> 1.82'
96
+ spec.add_development_dependency 'simplecov', '~> 1.0'
97
+ spec.add_development_dependency 'simplecov-lcov', '~> 0.9'
98
+ spec.add_development_dependency 'simplecov-rspec', '~> 1.1'
99
+ spec.add_development_dependency 'yard', '~> 0.9', '>= 0.9.28' if install_docs
100
+ spec.add_development_dependency 'yard_example_test', '~> 0.2', '>= 0.2.1' if install_docs
101
+ spec.add_development_dependency 'yard-lint', '~> 1.8' if install_yard_lint
46
102
 
47
103
  # Specify which files should be added to the gem when it is released.
48
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
49
- s.files = Dir.chdir(File.expand_path(__dir__)) do
50
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(tests|spec|features|bin)/}) }
104
+ #
105
+ # This is an allowlist rather than a denylist. A denylist admitted every new
106
+ # development-only path by default, so the gem shipped `.github/`, `tasks/`, the
107
+ # husky hooks, and -- the reason this became an allowlist -- the `.claude/skills`
108
+ # symlink. Extracting a symlink needs a privilege that Windows grants only under
109
+ # Developer Mode or an elevated shell, so installing the gem there either failed
110
+ # outright or, on RubyGems new enough to fall back to a copy, silently duplicated
111
+ # the whole skills tree into the installed gem.
112
+ #
113
+ # spec/unit/gemspec_spec.rb guards both directions: nothing in the list may be a
114
+ # symlink, and every tracked file under lib/ must be present, so the allowlist
115
+ # cannot quietly drop runtime code.
116
+ #
117
+ # doc_files must stay in sync with the extra files named in .yardopts -- those are
118
+ # what rubydoc.info renders for the published documentation, so a file listed there
119
+ # but absent from the gem becomes a broken link.
120
+ doc_files = %w[
121
+ AI_POLICY.md
122
+ CHANGELOG.md
123
+ CODE_OF_CONDUCT.md
124
+ CONTRIBUTING.md
125
+ GOVERNANCE.md
126
+ LICENSE
127
+ MAINTAINERS.md
128
+ README.md
129
+ UPGRADING.md
130
+ ]
131
+
132
+ # .yardopts drives the rubydoc.info build; the gemspec is included by convention.
133
+ build_files = %w[.yardopts git.gemspec]
134
+
135
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
136
+ `git ls-files -z`.split("\x0").select do |f|
137
+ f.start_with?('lib/') || doc_files.include?(f) || build_files.include?(f)
138
+ end
51
139
  end
52
140
  end
data/lib/git/author.rb CHANGED
@@ -1,14 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Git
4
+ # An author in a Git commit
5
+ #
6
+ # @deprecated Use {Git::AuthorInfo} instead; this mutable class will be
7
+ # removed in v6.0.0
8
+ #
9
+ # @api public
10
+ #
2
11
  class Author
3
- attr_accessor :name, :email, :date
4
-
12
+ # @return [String, nil] the author's name
13
+ attr_accessor :name
14
+
15
+ # @return [String, nil] the author's email
16
+ attr_accessor :email
17
+
18
+ # @return [Time, nil] the date the change was authored (author date, not committer date)
19
+ attr_accessor :date
20
+
21
+ # Initializes a new Author object from a string
22
+ #
23
+ # @example
24
+ # Git::Author.new("John Doe <john.doe@example.com> 1627849923 +0200")
25
+ #
26
+ # @param author_string [String] the author string
27
+ #
28
+ # @return [void]
29
+ #
30
+ # @deprecated Use {Git::AuthorInfo.parse} instead
31
+ #
5
32
  def initialize(author_string)
6
- if m = /(.*?) <(.*?)> (\d+) (.*)/.match(author_string)
7
- @name = m[1]
8
- @email = m[2]
9
- @date = Time.at(m[3].to_i)
33
+ if defined?(Git::Deprecation)
34
+ Git::Deprecation.warn(
35
+ 'Git::Author is deprecated and will be removed in v6.0.0. Use Git::AuthorInfo instead.'
36
+ )
10
37
  end
38
+
39
+ return unless (m = /(.*?) <(.*?)> (\d+) (.*)/.match(author_string))
40
+
41
+ @name = m[1]
42
+ @email = m[2]
43
+ @date = Time.at(m[3].to_i)
11
44
  end
12
-
13
45
  end
14
46
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Git
4
+ # Immutable value object representing an author or committer identity
5
+ #
6
+ # This is a lightweight, immutable data structure holding the identity data
7
+ # git records for commit authors, committers, and taggers. It replaces the
8
+ # mutable {Git::Author}, which is deprecated.
9
+ #
10
+ # @example Construct from individual values
11
+ # info = Git::AuthorInfo.new(
12
+ # name: 'John Doe',
13
+ # email: 'john.doe@example.com',
14
+ # date: Time.at(1627849923)
15
+ # )
16
+ # info.name #=> 'John Doe'
17
+ #
18
+ # @example Parse from a raw git author string
19
+ # info = Git::AuthorInfo.parse('John Doe <john.doe@example.com> 1627849923 +0200')
20
+ # info.email #=> 'john.doe@example.com'
21
+ # info.date.to_i #=> 1627849923
22
+ #
23
+ # @see Git::Object::Commit#author
24
+ #
25
+ # @see Git::Object::Commit#committer
26
+ #
27
+ # @api public
28
+ #
29
+ # @!attribute [r] name
30
+ # @return [String, nil] the person's name, or `nil` if not available
31
+ #
32
+ # @!attribute [r] email
33
+ # @return [String, nil] the person's email address, or `nil` if not available
34
+ #
35
+ # @!attribute [r] date
36
+ # @return [Time, nil] the timestamp of the change, or `nil` if not available
37
+ #
38
+ AuthorInfo = Data.define(:name, :email, :date) do
39
+ # Parses a raw git identity string into a Git::AuthorInfo
40
+ #
41
+ # The expected format is `"Name <email> timestamp offset"` as emitted by
42
+ # `git cat-file` for the `author`, `committer`, and `tagger` headers. The
43
+ # timestamp is interpreted as seconds since the Unix epoch; the timezone
44
+ # offset is not preserved in the resulting `date`.
45
+ #
46
+ # @example Parse a well-formed identity string
47
+ # Git::AuthorInfo.parse('John Doe <john.doe@example.com> 1627849923 +0200')
48
+ # #=> #<data Git::AuthorInfo name="John Doe", email="john.doe@example.com", ...>
49
+ #
50
+ # @example A string that does not match the expected format
51
+ # Git::AuthorInfo.parse('garbage')
52
+ # #=> #<data Git::AuthorInfo name=nil, email=nil, date=nil>
53
+ #
54
+ # @param author_string [String] the raw identity string to parse
55
+ #
56
+ # @return [Git::AuthorInfo] the parsed identity; all attributes are `nil`
57
+ # when the string does not match the expected format
58
+ #
59
+ def self.parse(author_string)
60
+ match = /(.*?) <(.*?)> (\d+) (.*)/.match(author_string)
61
+ return new(name: nil, email: nil, date: nil) unless match
62
+
63
+ new(name: match[1], email: match[2], date: Time.at(match[3].to_i))
64
+ end
65
+ end
66
+ end