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
@@ -3,13 +3,15 @@
3
3
  module Git
4
4
  # Immutable value object representing a single directory's contribution to a diff
5
5
  #
6
- # @api public
7
- #
8
- # @example
6
+ # @example Create a DirstatEntry
9
7
  # info = Git::DirstatEntry.new(directory: 'lib/commands/', percentage: 45.2)
10
8
  # info.directory #=> "lib/commands/"
11
9
  # info.percentage #=> 45.2
12
10
  #
11
+ # @api private
12
+ #
13
+ # Work in progress; this class is internal for now and may be made public in a future release.
14
+ #
13
15
  # @!attribute [r] directory
14
16
  # @return [String] the directory path (always ends with '/')
15
17
  #
@@ -22,9 +24,7 @@ module Git
22
24
  #
23
25
  # Contains the list of directories and their contribution percentages to the diff.
24
26
  #
25
- # @api public
26
- #
27
- # @example
27
+ # @example Create a DirstatInfo
28
28
  # dirstat = Git::DirstatInfo.new(
29
29
  # entries: [
30
30
  # Git::DirstatEntry.new(directory: 'lib/commands/', percentage: 45.2),
@@ -35,6 +35,10 @@ module Git
35
35
  # dirstat['lib/commands/'] #=> 45.2
36
36
  # dirstat.to_h #=> { "lib/commands/" => 45.2, "spec/unit/" => 30.1 }
37
37
  #
38
+ # @api private
39
+ #
40
+ # Work in progress; this class is internal for now and may be made public in a future release.
41
+ #
38
42
  # @!attribute [r] entries
39
43
  # @return [Array<DirstatEntry>] directory statistics in order from git output
40
44
  #
@@ -42,6 +46,7 @@ module Git
42
46
  # Look up percentage by directory path
43
47
  #
44
48
  # @param directory [String] the directory path
49
+ #
45
50
  # @return [Float, nil] the percentage or nil if not found
46
51
  #
47
52
  def [](directory)
@@ -74,8 +79,19 @@ module Git
74
79
 
75
80
  # Iterate over entries
76
81
  #
77
- # @yield [DirstatEntry] each entry
78
- # @return [Enumerator] if no block given
82
+ # @overload each
83
+ #
84
+ # @return [Enumerator<Git::DirstatEntry>] an enumerator over all dirstat entries
85
+ #
86
+ # @overload each(&block)
87
+ #
88
+ # @return [Array<Git::DirstatEntry>] the full list of dirstat entries
89
+ #
90
+ # @yield [entry] each dirstat entry
91
+ #
92
+ # @yieldparam entry [Git::DirstatEntry] a single dirstat entry
93
+ #
94
+ # @yieldreturn [void]
79
95
  #
80
96
  def each(&block)
81
97
  entries.each(&block)
@@ -3,25 +3,56 @@
3
3
  require 'rchardet'
4
4
 
5
5
  module Git
6
- # Method that can be used to detect and normalize string encoding
6
+ # Provides helpers for detecting and normalizing string encodings
7
+ #
8
+ # `default_encoding` refers to {Git::EncodingUtils.default_encoding}, which is
9
+ # derived from this source file's encoding declaration
10
+ #
11
+ # @api private
12
+ #
7
13
  module EncodingUtils
14
+ # Returns the default encoding name used by this source file
15
+ #
16
+ # @return [String] the source file encoding name
17
+ #
8
18
  def self.default_encoding
9
19
  __ENCODING__.name
10
20
  end
11
21
 
22
+ # Returns the fallback encoding name used when detection fails
23
+ #
24
+ # @return [String] the fallback encoding name
25
+ #
12
26
  def self.best_guess_encoding
13
27
  # Encoding::ASCII_8BIT.name
14
28
  Encoding::UTF_8.name
15
29
  end
16
30
 
31
+ # Returns the detected encoding name for the given string
32
+ #
33
+ # @param str [String] the string whose encoding should be detected
34
+ #
35
+ # @return [String] the detected encoding name or the fallback encoding name
36
+ #
17
37
  def self.detected_encoding(str)
18
38
  CharDet.detect(str)['encoding'] || best_guess_encoding
19
39
  end
20
40
 
41
+ # Returns replacement options used when transcoding invalid byte sequences
42
+ #
43
+ # @return [Hash<Symbol, Symbol>] options for replacing invalid and undefined bytes
44
+ #
21
45
  def self.encoding_options
22
46
  { invalid: :replace, undef: :replace }
23
47
  end
24
48
 
49
+ # Returns the given string converted to {Git::EncodingUtils.default_encoding}
50
+ #
51
+ # @param str [String] the string to normalize
52
+ #
53
+ # @return [String] the original or transcoded string in
54
+ # {Git::EncodingUtils.default_encoding}
55
+ #
25
56
  def self.normalize_encoding(str)
26
57
  return str if str.valid_encoding? && str.encoding.name == default_encoding
27
58
 
data/lib/git/errors.rb CHANGED
@@ -54,11 +54,17 @@ module Git
54
54
  # end
55
55
  #
56
56
  # @see Git::CommandLineError
57
+ #
57
58
  # @see Git::FailedError
59
+ #
58
60
  # @see Git::SignaledError
61
+ #
59
62
  # @see Git::TimeoutError
63
+ #
60
64
  # @see Git::ProcessIOError
65
+ #
61
66
  # @see Git::UnexpectedResultError
67
+ #
62
68
  # @see Git::VersionError
63
69
  #
64
70
  # @api public
@@ -94,11 +100,11 @@ module Git
94
100
  #
95
101
  # @example
96
102
  # `exit 1` # set $? appropriately for this example
97
- # result = Git::CommandLineResult.new(%w[git status], $?, 'stdout', 'stderr')
103
+ # result = Git::CommandLine::Result.new(%w[git status], $?, 'stdout', 'stderr')
98
104
  # error = Git::CommandLineError.new(result)
99
105
  # error.to_s #=> '["git", "status"], status: pid 89784 exit 1, stderr: "stderr"'
100
106
  #
101
- # @param result [Git::CommandLineResult] the result of the git command including
107
+ # @param result [Git::CommandLine::Result] the result of the git command including
102
108
  # the git command, status, stdout, and stderr
103
109
  #
104
110
  def initialize(result)
@@ -117,14 +123,12 @@ module Git
117
123
  #{result.git_cmd}, status: #{result.status}, stderr: #{result.stderr.inspect}
118
124
  MESSAGE
119
125
 
120
- # @attribute [r] result
121
- #
122
126
  # The result of the git command including the git command and its status and output
123
127
  #
124
128
  # @example
125
- # error.result #=> #<Git::CommandLineResult:0x00000001046bd488 ...>
129
+ # error.result #=> #<Git::CommandLine::Result:0x00000001046bd488 ...>
126
130
  #
127
- # @return [Git::CommandLineResult]
131
+ # @return [Git::CommandLine::Result]
128
132
  #
129
133
  attr_reader :result
130
134
  end
@@ -160,12 +164,12 @@ module Git
160
164
  # command = %w[sleep 10]
161
165
  # timeout_duration = 1
162
166
  # status = ProcessExecuter.spawn(*command, timeout: timeout_duration)
163
- # result = Git::CommandLineResult.new(command, status, 'stdout', 'err output')
167
+ # result = Git::CommandLine::Result.new(command, status, 'stdout', 'err output')
164
168
  # error = Git::TimeoutError.new(result, timeout_duration)
165
169
  # error.error_message
166
170
  # #=> '["sleep", "10"], status: pid 70144 SIGKILL (signal 9), stderr: "err output", timed out after 1s'
167
171
  #
168
- # @param result [Git::CommandLineResult] the result of the git command including
172
+ # @param result [Git::CommandLine::Result] the result of the git command including
169
173
  # the git command, status, stdout, and stderr
170
174
  #
171
175
  # @param timeout_duration [Numeric] the amount of time the subprocess was allowed
@@ -192,7 +196,7 @@ module Git
192
196
  #
193
197
  # @example
194
198
  # `kill -9 $$` # set $? appropriately for this example
195
- # result = Git::CommandLineResult.new(%w[git status], $?, '', "killed")
199
+ # result = Git::CommandLine::Result.new(%w[git status], $?, '', "killed")
196
200
  # error = Git::TimeoutError.new(result, 10)
197
201
  # error.timeout_duration #=> 10
198
202
  #
@@ -234,7 +238,9 @@ module Git
234
238
  # Create a VersionError
235
239
  #
236
240
  # @param subject [#to_s] the entity with the version requirement (e.g., "The git gem", a Class)
241
+ #
237
242
  # @param constraint [Git::VersionConstraint] the version constraint that was violated
243
+ #
238
244
  # @param actual_version [Git::Version] the installed git version
239
245
  #
240
246
  def initialize(subject:, constraint:, actual_version:)
@@ -264,6 +270,10 @@ module Git
264
270
 
265
271
  private
266
272
 
273
+ # Builds the error message for the violated version constraint.
274
+ #
275
+ # @return [String]
276
+ #
267
277
  def build_message
268
278
  if constraint.too_new?(actual_version)
269
279
  "#{subject} requires git < #{constraint.before} (found #{actual_version})"
@@ -8,10 +8,15 @@ module Git
8
8
  # characters (e.g. \t for TAB, \n for LF, \\ for backslash) or bytes with values
9
9
  # larger than 0x80 (e.g. octal \302\265 for "micro" in UTF-8).
10
10
  #
11
- # @example
12
- # Git::GitPath.new('\302\265').unescape # => "µ"
11
+ # @example Decode octal UTF-8 bytes
12
+ # Git::EscapedPath.new('\302\265').unescape # => "µ"
13
+ #
14
+ # @api private
13
15
  #
14
16
  class EscapedPath
17
+ # Maps single-character escapes to their decoded byte values
18
+ #
19
+ # @return [Hash<String, Integer>] escape characters mapped to byte values
15
20
  UNESCAPES = {
16
21
  'a' => 0x07,
17
22
  'b' => 0x08,
@@ -26,13 +31,27 @@ module Git
26
31
  "'" => 0x27
27
32
  }.freeze
28
33
 
34
+ # Returns the escaped path as provided by git output
35
+ #
36
+ # @return [String] the escaped path string
29
37
  attr_reader :path
30
38
 
39
+ # Initializes an escaped path wrapper
40
+ #
41
+ # @param path [String] the path string with Git-style escape sequences
42
+ #
43
+ # @return [void]
31
44
  def initialize(path)
32
45
  @path = path
33
46
  end
34
47
 
35
- # Convert an escaped path to an unescaped path
48
+ # Converts an escaped path to an unescaped UTF-8 path
49
+ #
50
+ # @example Decode escaped path output
51
+ # Git::EscapedPath.new("dir/\\342\\230\\240\\n").unescape
52
+ # # => "dir/☠\n"
53
+ #
54
+ # @return [String] the decoded path string
36
55
  def unescape
37
56
  bytes = escaped_path_to_bytes(path)
38
57
  str = bytes.pack('C*')
@@ -41,18 +60,46 @@ module Git
41
60
 
42
61
  private
43
62
 
63
+ # Extracts an octal escape sequence starting at the given index
64
+ #
65
+ # @param path [String] the escaped path string
66
+ #
67
+ # @param index [Integer] the index where the sequence starts
68
+ #
69
+ # @return [Array(Integer, Integer)] decoded byte and consumed character count
44
70
  def extract_octal(path, index)
45
71
  [path[(index + 1)..(index + 3)].to_i(8), 4]
46
72
  end
47
73
 
74
+ # Extracts a single-character escape sequence at the given index
75
+ #
76
+ # @param path [String] the escaped path string
77
+ #
78
+ # @param index [Integer] the index where the sequence starts
79
+ #
80
+ # @return [Array(Integer, Integer)] decoded byte and consumed character count
48
81
  def extract_escape(path, index)
49
82
  [UNESCAPES[path[index + 1]], 2]
50
83
  end
51
84
 
85
+ # Extracts a non-escaped character byte at the given index
86
+ #
87
+ # @param path [String] the escaped path string
88
+ #
89
+ # @param index [Integer] the index of the character to decode
90
+ #
91
+ # @return [Array(Integer, Integer)] decoded byte and consumed character count
52
92
  def extract_single_char(path, index)
53
93
  [path[index].ord, 1]
54
94
  end
55
95
 
96
+ # Decodes the next byte from the escaped path at the given index
97
+ #
98
+ # @param path [String] the escaped path string
99
+ #
100
+ # @param index [Integer] the index to decode from
101
+ #
102
+ # @return [Array(Integer, Integer)] decoded byte and consumed character count
56
103
  def next_byte(path, index)
57
104
  if path[index] == '\\' && path[index + 1] >= '0' && path[index + 1] <= '7'
58
105
  extract_octal(path, index)
@@ -63,6 +110,11 @@ module Git
63
110
  end
64
111
  end
65
112
 
113
+ # Converts an escaped path string into decoded bytes
114
+ #
115
+ # @param path [String] the escaped path string
116
+ #
117
+ # @return [Array<Integer>] decoded bytes in order
66
118
  def escaped_path_to_bytes(path)
67
119
  index = 0
68
120
  [].tap do |bytes|
@@ -116,6 +116,21 @@ module Git
116
116
  #
117
117
  # @param overrides [Hash] keyword arguments to override in the new instance
118
118
  #
119
+ # @option overrides [String, nil] :git_dir path to the `.git` directory
120
+ #
121
+ # @option overrides [String, nil] :git_work_dir path to the working tree
122
+ #
123
+ # @option overrides [String, nil] :git_index_file path to the index file
124
+ #
125
+ # @option overrides [String, :use_global_config] :binary_path path to the git
126
+ # binary
127
+ #
128
+ # @option overrides [String, nil, :use_global_config] :git_ssh the SSH
129
+ # wrapper path
130
+ #
131
+ # @option overrides [Logger, nil] :logger the logger to use in the
132
+ # CommandLine layer
133
+ #
119
134
  # @return [Git::ExecutionContext::Repository] the new context
120
135
  #
121
136
  # @api private
@@ -222,8 +222,6 @@ module Git
222
222
  #
223
223
  # @overload command_capturing(*args, **options_hash)
224
224
  #
225
- # Runs a git command and returns the result
226
- #
227
225
  # Args should exclude the 'git' command itself and global options. Remember to
228
226
  # splat the arguments if given as an array.
229
227
  #
@@ -241,64 +239,64 @@ module Git
241
239
  #
242
240
  # @param args [Array<String>] the command and its arguments
243
241
  #
244
- # @param options_hash [Hash] the options to pass to the command
242
+ # @return [Git::CommandLine::Result] the result of the command
245
243
  #
246
- # @option options_hash [IO, nil] :in the IO object to use as stdin, or nil to
247
- # inherit the parent process stdin
244
+ # @param options_hash [Hash] the options to pass to the command
248
245
  #
249
- # Must be a real IO object with a file descriptor.
246
+ # @option options_hash [IO, nil] :in the IO object to use as stdin, or nil to
247
+ # inherit the parent process stdin
250
248
  #
251
- # @option options_hash [IO, String, #write, nil] :out the destination for
252
- # captured stdout
249
+ # Must be a real IO object with a file descriptor.
253
250
  #
254
- # @option options_hash [IO, String, #write, nil] :err the destination for
255
- # captured stderr
251
+ # @option options_hash [IO, String, #write, nil] :out the destination for
252
+ # captured stdout
256
253
  #
257
- # @option options_hash [Boolean, nil] :normalize (true) normalize the output
258
- # encoding to UTF-8
254
+ # @option options_hash [IO, String, #write, nil] :err the destination for
255
+ # captured stderr
259
256
  #
260
- # @option options_hash [Boolean, nil] :chomp (true) remove trailing newlines
261
- # from the output
257
+ # @option options_hash [Boolean, nil] :normalize (true) normalize the output
258
+ # encoding to UTF-8
262
259
  #
263
- # @option options_hash [Boolean, nil] :merge (false) merge stdout and stderr
264
- # into a single output
260
+ # @option options_hash [Boolean, nil] :chomp (true) remove trailing newlines
261
+ # from the output
265
262
  #
266
- # @option options_hash [String, nil] :chdir the directory to run the command in
263
+ # @option options_hash [Boolean, nil] :merge (false) merge stdout and stderr
264
+ # into a single output
267
265
  #
268
- # @option options_hash [Hash] :env additional environment variable overrides
269
- # for this command
266
+ # @option options_hash [String, nil] :chdir the directory to run the command in
270
267
  #
271
- # @option options_hash [Boolean, nil] :raise_on_failure (true) whether to raise on
272
- # non-zero exit
268
+ # @option options_hash [Hash] :env additional environment variable overrides
269
+ # for this command
273
270
  #
274
- # @option options_hash [Numeric, nil] :timeout the maximum seconds to wait for
275
- # the command to complete
271
+ # @option options_hash [Boolean, nil] :raise_on_failure (true) whether to raise on
272
+ # non-zero exit
276
273
  #
277
- # If timeout is nil, the global timeout from {Git::Config} is used.
274
+ # @option options_hash [Numeric, nil] :timeout the maximum seconds to wait for
275
+ # the command to complete
278
276
  #
279
- # If timeout is zero, the timeout will not be enforced.
277
+ # If timeout is nil, the global timeout from {Git::Config} is used.
280
278
  #
281
- # If the command times out, it is killed via a `SIGKILL` signal and
282
- # `Git::TimeoutError` is raised.
279
+ # If timeout is zero, the timeout will not be enforced.
283
280
  #
284
- # If the command does not respond to SIGKILL, it will hang this method.
281
+ # If the command times out, it is killed via a `SIGKILL` signal and
282
+ # `Git::TimeoutError` is raised.
285
283
  #
286
- # @return [Git::CommandLineResult] the result of the command
284
+ # If the command does not respond to SIGKILL, it will hang this method.
287
285
  #
288
- # @raise [ArgumentError] if an unknown option is passed
286
+ # @raise [ArgumentError] if an unknown option is passed
289
287
  #
290
- # @raise [Git::FailedError] if the command failed (when raise_on_failure is
291
- # true)
288
+ # @raise [Git::FailedError] if the command failed (when raise_on_failure is
289
+ # true)
292
290
  #
293
- # @raise [Git::SignaledError] if the command was signaled
291
+ # @raise [Git::SignaledError] if the command was signaled
294
292
  #
295
- # @raise [Git::TimeoutError] if the command times out
293
+ # @raise [Git::TimeoutError] if the command times out
296
294
  #
297
- # @raise [Git::ProcessIOError] if an exception was raised while collecting
298
- # subprocess output
295
+ # @raise [Git::ProcessIOError] if an exception was raised while collecting
296
+ # subprocess output
299
297
  #
300
- # The exception's `result` attribute is a {Git::CommandLineResult} which will
301
- # contain the result of the command including the exit status, stdout, and stderr.
298
+ # The exception's `result` attribute is a {Git::CommandLine::Result} which will
299
+ # contain the result of the command including the exit status, stdout, and stderr.
302
300
  #
303
301
  # @note Individual command classes (under {Git::Commands}) can selectively expose
304
302
  # `:timeout` and `:env` and other options to their callers by declaring them as
@@ -340,58 +338,58 @@ module Git
340
338
  #
341
339
  # @param args [Array<String>] the git command and its arguments
342
340
  #
343
- # @param options_hash [Hash] the options to pass to the command
341
+ # @return [Git::CommandLine::Result] the result of the command
344
342
  #
345
- # @option options_hash [IO, nil] :in the IO object to use as stdin, or nil to
346
- # inherit the parent process stdin
343
+ # @param options_hash [Hash] the options to pass to the command
347
344
  #
348
- # Must be a real IO object with a file descriptor.
345
+ # @option options_hash [IO, nil] :in the IO object to use as stdin, or nil to
346
+ # inherit the parent process stdin
349
347
  #
350
- # @option options_hash [#write, nil] :out destination for streamed stdout
348
+ # Must be a real IO object with a file descriptor.
351
349
  #
352
- # @option options_hash [#write, nil] :err an optional additional destination
353
- # to receive stderr output in real time
350
+ # @option options_hash [#write, nil] :out destination for streamed stdout
354
351
  #
355
- # Stderr is always captured internally; when `err:` is supplied, writes are
356
- # teed to both the internal buffer and this destination. `result.stderr`
357
- # always reflects the internal capture.
352
+ # @option options_hash [#write, nil] :err an optional additional destination
353
+ # to receive stderr output in real time
358
354
  #
359
- # @option options_hash [String, nil] :chdir the directory to run the command in
355
+ # Stderr is always captured internally; when `err:` is supplied, writes are
356
+ # teed to both the internal buffer and this destination. `result.stderr`
357
+ # always reflects the internal capture.
360
358
  #
361
- # @option options_hash [Hash] :env additional environment variable overrides
362
- # for this command
359
+ # @option options_hash [String, nil] :chdir the directory to run the command in
363
360
  #
364
- # @option options_hash [Boolean, nil] :raise_on_failure (true) whether to raise on
365
- # non-zero exit
361
+ # @option options_hash [Hash] :env additional environment variable overrides
362
+ # for this command
366
363
  #
367
- # @option options_hash [Numeric, nil] :timeout
368
- # the maximum seconds to wait for the command to complete
364
+ # @option options_hash [Boolean, nil] :raise_on_failure (true) whether to raise on
365
+ # non-zero exit
369
366
  #
370
- # If timeout is nil, the global timeout from {Git::Config} is used.
367
+ # @option options_hash [Numeric, nil] :timeout the maximum seconds to wait for
368
+ # the command to complete
371
369
  #
372
- # If timeout is zero, the timeout will not be enforced.
370
+ # If timeout is nil, the global timeout from {Git::Config} is used.
373
371
  #
374
- # If the command times out, it is killed via a `SIGKILL` signal and
375
- # `Git::TimeoutError` is raised.
372
+ # If timeout is zero, the timeout will not be enforced.
376
373
  #
377
- # If the command does not respond to SIGKILL, it will hang this method.
374
+ # If the command times out, it is killed via a `SIGKILL` signal and
375
+ # `Git::TimeoutError` is raised.
378
376
  #
379
- # @return [Git::CommandLineResult] the result of the command
377
+ # If the command does not respond to SIGKILL, it will hang this method.
380
378
  #
381
- # `result.stdout` will always be `''` — stdout was streamed to `out:`.
379
+ # `result.stdout` will always be `''` — stdout was streamed to `out:`.
382
380
  #
383
- # `result.stderr` contains any stderr output captured for diagnostics.
381
+ # `result.stderr` contains any stderr output captured for diagnostics.
384
382
  #
385
- # @raise [ArgumentError] if an unknown option is passed
383
+ # @raise [ArgumentError] if an unknown option is passed
386
384
  #
387
- # @raise [Git::FailedError] if the command failed (when raise_on_failure is true)
385
+ # @raise [Git::FailedError] if the command failed (when raise_on_failure is true)
388
386
  #
389
- # @raise [Git::SignaledError] if the command was signaled
387
+ # @raise [Git::SignaledError] if the command was signaled
390
388
  #
391
- # @raise [Git::TimeoutError] if the command times out
389
+ # @raise [Git::TimeoutError] if the command times out
392
390
  #
393
- # @raise [Git::ProcessIOError] if an exception was raised while collecting
394
- # subprocess output
391
+ # @raise [Git::ProcessIOError] if an exception was raised while collecting
392
+ # subprocess output
395
393
  #
396
394
  # @see Git::CommandLine::Streaming#run
397
395
  #
@@ -435,9 +433,16 @@ module Git
435
433
  #
436
434
  # Per `Process.spawn` semantics, a value of `nil` unsets the variable.
437
435
  #
438
- # @param additional_overrides [Hash<String, String|nil>] per-call overrides
436
+ # @param additional_overrides [Hash{String => String, nil}] per-call
437
+ # environment overrides keyed by variable name
438
+ #
439
+ # Pass string environment variable names. Ruby preserves string keys when
440
+ # callers forward a string-keyed Hash with `**`.
439
441
  #
440
- # @return [Hash<String, String|nil>] the merged environment variable overrides
442
+ # @option additional_overrides [String, nil] :"ENV_VAR" value for an arbitrary
443
+ # environment variable name
444
+ #
445
+ # @return [Hash{String => String, nil}] the merged environment variable overrides
441
446
  #
442
447
  # @api private
443
448
  #
@@ -496,6 +501,3 @@ module Git
496
501
  end
497
502
  end
498
503
  end
499
-
500
- require 'git/execution_context/global'
501
- require 'git/execution_context/repository'
data/lib/git/file_ref.rb CHANGED
@@ -11,7 +11,6 @@ module Git
11
11
  # dst for deleted files), the entire FileRef should be nil rather than having
12
12
  # a FileRef with nil attributes.
13
13
  #
14
- # @api public
15
14
  #
16
15
  # @example A modified file's source reference
17
16
  # src = Git::FileRef.new(mode: '100644', sha: 'abc1234', path: 'lib/foo.rb')
@@ -20,6 +19,10 @@ module Git
20
19
  # # src = nil
21
20
  # dst = Git::FileRef.new(mode: '100644', sha: 'def5678', path: 'lib/new_file.rb')
22
21
  #
22
+ # @api private
23
+ #
24
+ # Work in progress; this class is internal for now and may be made public in a future release.
25
+ #
23
26
  # @!attribute [r] mode
24
27
  # @return [String] the file mode (e.g., '100644' for regular file, '100755' for executable,
25
28
  # '120000' for symlink)
@@ -59,14 +62,14 @@ module Git
59
62
  #
60
63
  # Useful for bit operations on file permissions.
61
64
  #
62
- # @return [Integer] the mode as an integer
63
- #
64
65
  # @example Check file permissions
65
66
  # ref.mode_bits & 0o777 # => 0o644 (420 decimal)
66
67
  #
67
68
  # @example Check if group writable
68
69
  # (ref.mode_bits & 0o020) != 0
69
70
  #
71
+ # @return [Integer] the mode as an integer
72
+ #
70
73
  def mode_bits
71
74
  mode.to_i(8)
72
75
  end
@@ -10,26 +10,33 @@ module Git
10
10
  #
11
11
  class FsckObject
12
12
  # The type of the Git object
13
+ #
13
14
  # @return [Symbol] one of :commit, :tree, :blob, or :tag
14
15
  attr_reader :type
15
16
 
16
17
  # The object identifier (OID) of the object
18
+ #
17
19
  # @return [String] the 40-character object identifier
18
20
  attr_reader :oid
19
21
 
20
22
  # A warning or error message associated with this object
23
+ #
21
24
  # @return [String, nil] the message, or nil if no message
22
25
  attr_reader :message
23
26
 
24
27
  # A name describing how the object is reachable (from --name-objects)
28
+ #
25
29
  # @return [String, nil] the name, or nil if not provided
26
30
  attr_reader :name
27
31
 
28
32
  # Create a new FsckObject
29
33
  #
30
34
  # @param type [Symbol] the object type (:commit, :tree, :blob, or :tag)
35
+ #
31
36
  # @param oid [String] the 40-character object identifier
37
+ #
32
38
  # @param message [String, nil] optional warning/error message
39
+ #
33
40
  # @param name [String, nil] optional name from --name-objects (e.g., "HEAD~2^2:src/")
34
41
  #
35
42
  def initialize(type:, oid:, message: nil, name: nil)
@@ -40,6 +47,7 @@ module Git
40
47
  end
41
48
 
42
49
  # Returns the OID as the string representation
50
+ #
43
51
  # @return [String] the object identifier
44
52
  def to_s
45
53
  oid