ruby_git 0.3.6 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bcb191c36fedc350022fcc895d95c33ae96903e3154acc4d289b0cdb01b8078
4
- data.tar.gz: af5e459bce99053a239d1fb6da6376fc4df3609c8e95f9059d490a578716e84c
3
+ metadata.gz: 51c942c1d3e14a3d22755da43c9ea15bb80ddd92b31e40b53c008eee0a47de42
4
+ data.tar.gz: 3194cd1143c85ed1c532189c4ca010bbf2fad93aa9fe95293c3861a62feb665b
5
5
  SHA512:
6
- metadata.gz: baa4727ff238bd5efdc70f95919e203dd9552c7109f1398193ee1a909788516ead998eb03d72bd0131ae7fde44b681650386aba68627c018bf39c5dc140f8792
7
- data.tar.gz: 0dd9357dd4521393b3e4e947162f6d53eb96d6e44d833a1f8e17878507f14bf3c7f70e8516eabdc64b72ee7974f6495e0ae454f8d8e6a3a6fa11090a205a5af0
6
+ metadata.gz: 18c2c2af28e5a23aa74786e1a9addc9d11d2ede3d968e76db11bdef609a4b8eff52c52b9d65b8a6ee6ce286f73eeb59adbad0f784d54d01d74568813b335b736
7
+ data.tar.gz: 73a8c700ef019fab3e63df64d26a9919c3789d3094180c759e4262de4fe9ec67100aa1a399003f542b2c668e67fa58428603e946e134526536e64917da35b020
data/.commitlintrc.yml CHANGED
@@ -15,6 +15,23 @@ rules:
15
15
  # Run `npx commitlint --print-config` to see the current setting for all
16
16
  # rules.
17
17
  #
18
- body-leading-blank: [2, always]
19
- footer-leading-blank: [2, always]
20
- type-enum: [2, always, [build, ci, chore, docs, feat, fix, perf, refactor, revert, style, test]]
18
+ header-max-length: [2, always, 100] # Header can not exceed 100 chars
19
+
20
+ type-case: [2, always, lower-case] # Type must be lower case
21
+ type-empty: [2, never] # Type must not be empty
22
+
23
+ # Supported conventional commit types
24
+ type-enum: [2, always, [build, ci, chore, docs, feat, fix, perf, refactor, revert, style, test]]
25
+
26
+ scope-case: [2, always, lower-case] # Scope must be lower case
27
+
28
+ # Error if subject is one of these cases (encourages lower-case)
29
+ subject-case: [2, never, [sentence-case, start-case, pascal-case, upper-case]]
30
+ subject-empty: [2, never] # Subject must not be empty
31
+ subject-full-stop: [2, never, "."] # Subject must not end with a period
32
+
33
+ body-leading-blank: [2, always] # Body must have a blank line before it
34
+ body-max-line-length: [2, always, 100] # Body lines can not exceed 100 chars
35
+
36
+ footer-leading-blank: [2, always] # Footer must have a blank line before it
37
+ footer-max-line-length: [2, always, 100] # Footer lines can not exceed 100 chars
@@ -1,25 +1,30 @@
1
- name: Conventional Commits
1
+ ---
2
+ name: Conventional Commits
2
3
 
3
- on:
4
- pull_request:
5
- branches:
6
- - main
4
+ permissions:
5
+ contents: read
7
6
 
8
- jobs:
9
- commit-lint:
10
- name: Verify Conventional Commits
7
+ on:
8
+ pull_request:
9
+ branches:
10
+ - main
11
11
 
12
- if: >-
13
- github.event_name == 'workflow_dispatch' ||
14
- (github.event_name == 'pull_request' && !startsWith(github.event.pull_request.head.ref, 'release-please--'))
12
+ jobs:
13
+ commit-lint:
14
+ name: Verify Conventional Commits
15
15
 
16
- runs-on: ubuntu-latest
16
+ # Skip this job if this is a release PR
17
+ if: >-
18
+ github.event_name == 'workflow_dispatch' ||
19
+ (github.event_name == 'pull_request' && !startsWith(github.event.pull_request.head.ref, 'release-please--'))
17
20
 
18
- steps:
19
- - name: Checkout
20
- uses: actions/checkout@v4
21
- with: { fetch-depth: 0 }
21
+ runs-on: ubuntu-latest
22
22
 
23
- - name: Check Commit Messages
24
- uses: wagoid/commitlint-github-action@v6
25
- with: { configFile: .commitlintrc.yml }
23
+ steps:
24
+ - name: Checkout
25
+ uses: actions/checkout@v4
26
+ with: { fetch-depth: 0 }
27
+
28
+ - name: Check Commit Messages
29
+ uses: wagoid/commitlint-github-action@v6
30
+ with: { configFile: .commitlintrc.yml }
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.3.6"
2
+ ".": "0.4.0"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Change Log
2
2
 
3
+ ## [0.4.0](https://github.com/main-branch/ruby_git/compare/v0.3.6...v0.4.0) (2025-06-06)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * this gem now raises `RubyGit::ArgumentError` where before it raised
9
+
10
+ ### Features
11
+
12
+ * Upgrade process_executer dependency to 4.x ([86d94cd](https://github.com/main-branch/ruby_git/commit/86d94cd1e4291c99ac910996b0e0c03e2e2d2d3d))
13
+
14
+
15
+ ### Other Changes
16
+
17
+ * Configure release-please to includes all changes in the CHANGELOG ([7b08f32](https://github.com/main-branch/ruby_git/commit/7b08f320a0968bae33aa5cd80d15b8a3cd598cc0))
18
+ * Move EncodingNormalizer from RubyGit to RubyGit::CommandLine ([9110533](https://github.com/main-branch/ruby_git/commit/911053333665a6add6a5081737febd8b10cda304))
19
+
3
20
  ## [0.3.6](https://github.com/main-branch/ruby_git/compare/v0.3.5...v0.3.6) (2025-04-17)
4
21
 
5
22
 
data/Gemfile CHANGED
@@ -2,5 +2,4 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- # Specify your gem's dependencies in ruby_git.gemspec
6
5
  gemspec
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rchardet'
4
+
5
+ module RubyGit
6
+ module CommandLine
7
+ # Utility to normalize string encoding
8
+ # @api public
9
+ module EncodingNormalizer
10
+ # Detects the character encoding used to create a string or binary data
11
+ #
12
+ # Detects the encoding of a string or return binary if it cannot be detected
13
+ #
14
+ # @example
15
+ # EncodingNormalizer.detect_encoding("Hello, world!") #=> "ascii"
16
+ # EncodingNormalizer.detect_encoding("\xCB\xEF\xF1\xE5\xEC") #=> "ISO-8859-7"
17
+ # EncodingNormalizer.detect_encoding("\xC0\xCC\xB0\xCD\xC0\xBA") #=> "EUC-KR"
18
+ #
19
+ # @param str [String] the string to detect the encoding of
20
+ # @return [String] the detected encoding
21
+ #
22
+ def self.detect_encoding(str)
23
+ CharDet.detect(str)&.dig('encoding') || Encoding::BINARY.name
24
+ end
25
+
26
+ # Normalizes the encoding to normalize_to
27
+ #
28
+ # @example
29
+ # EncodingNormalizer.normalize("Hello, world!") #=> "Hello, world!"
30
+ # EncodingNormalizer.normalize("\xCB\xEF\xF1\xE5\xEC") #=> "Λορεμ"
31
+ # EncodingNormalizer.normalize("\xC0\xCC\xB0\xCD\xC0\xBA") #=> "이것은"
32
+ #
33
+ # @param str [String] the string to normalize
34
+ # @param normalize_to [String] the name of the encoding to normalize to
35
+ #
36
+ # @return [String] the string with encoding converted to normalize_to
37
+ #
38
+ # @raise [Encoding::UndefinedConversionError] if the string cannot be converted to the default encoding
39
+ #
40
+ def self.normalize(str, normalize_to: Encoding::UTF_8.name)
41
+ encoding_options = { invalid: :replace, undef: :replace }
42
+
43
+ detected_encoding = detect_encoding(str)
44
+
45
+ return str if str.valid_encoding? && detected_encoding == normalize_to
46
+
47
+ str.encode(normalize_to, detected_encoding, **encoding_options)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -9,14 +9,12 @@ module RubyGit
9
9
  #
10
10
  # @api public
11
11
  #
12
- class Options < ProcessExecuter::Options::RunOptions
12
+ class Options < ProcessExecuter::Options::RunWithCaptureOptions
13
13
  # Alias for brevity
14
14
  OptionDefinition = ProcessExecuter::Options::OptionDefinition
15
15
 
16
16
  private
17
17
 
18
- # :nocov: SimpleCov on JRuby reports the last with the last argument line is not covered
19
-
20
18
  # The options allowed for objects of this class
21
19
  # @return [Array<OptionDefinition>]
22
20
  # @api private
@@ -24,25 +22,24 @@ module RubyGit
24
22
  [
25
23
  *super,
26
24
  OptionDefinition.new(:normalize_encoding, default: false, validator: method(:validate_normalize_encoding)),
27
- OptionDefinition.new(:chomp, default: false, validator: method(:validate_chomp)),
28
- OptionDefinition.new(:raise_git_errors, default: true, validator: method(:validate_raise_git_errors))
25
+ OptionDefinition.new(:chomp, default: false, validator: method(:validate_chomp))
29
26
  ].freeze
30
27
  end
31
- # :nocov:
32
28
 
33
- # Validate the raise_git_errors option value
34
- # @return [String, nil] the error message if the value is not valid
29
+ # Wrap ProcessExecuter::ArgumentError in a RubyGit::ArgumentError
30
+ # @return [void]
31
+ # @raise [RubyGit::ArgumentError] if the options are invalid
35
32
  # @api private
36
- def validate_raise_git_errors
37
- return if [true, false].include?(raise_git_errors)
38
-
39
- errors << "raise_git_errors must be true or false but was #{raise_git_errors.inspect}"
33
+ def validate_options
34
+ super
35
+ rescue ProcessExecuter::ArgumentError => e
36
+ raise RubyGit::ArgumentError, e.message, cause: e
40
37
  end
41
38
 
42
39
  # Validate the normalize_encoding option value
43
40
  # @return [String, nil] the error message if the value is not valid
44
41
  # @api private
45
- def validate_normalize_encoding
42
+ def validate_normalize_encoding(_key, _value)
46
43
  return if [true, false].include?(normalize_encoding)
47
44
 
48
45
  errors << "normalize_encoding must be true or false but was #{normalize_encoding.inspect}"
@@ -51,7 +48,7 @@ module RubyGit
51
48
  # Validate the chomp option value
52
49
  # @return [String, nil] the error message if the value is not valid
53
50
  # @api private
54
- def validate_chomp
51
+ def validate_chomp(_key, _value)
55
52
  return if [true, false].include?(chomp)
56
53
 
57
54
  errors << "chomp must be true or false but was #{chomp.inspect}"
@@ -7,27 +7,30 @@ module RubyGit
7
7
  module CommandLine
8
8
  # The result of running a git command
9
9
  #
10
- # Adds stdout and stderr processing to the `ProcessExecuter::Result` class.
10
+ # Adds stdout and stderr processing to the `ProcessExecuter::ResultWithCapture` class.
11
11
  #
12
12
  # @api public
13
13
  #
14
14
  class Result < SimpleDelegator
15
15
  # @!method initialize(result)
16
16
  # Initialize a new result object
17
+ #
17
18
  # @example
18
- # result = ProcessExecuter.run('echo hello')
19
+ # result = Git::CommandLine.run_with_capture('git', 'status')
19
20
  # RubyGit::CommandLine::Result.new(result)
20
- # @param [ProcessExecuter::Result] result The result of running the command
21
+ #
22
+ # @param [ProcessExecuter::ResultWithCapture] result The result of running the command
23
+ #
21
24
  # @return [RubyGit::CommandLine::Result]
25
+ #
22
26
  # @api public
23
27
 
24
28
  # Return the processed stdout output (or original if it was not processed)
25
29
  #
26
- # This output is only returned if a stdout redirection is a
27
- # `ProcessExecuter::MonitoredPipe`.
28
- #
29
30
  # @example
30
- # result = ProcessExecuter.run('echo hello': out: StringIO.new)
31
+ # result = RubyGit::CommandLine::Result.new(
32
+ # ProcessExecuter.run_with_capture('echo hello')
33
+ # )
31
34
  # result.stdout #=> "hello\n"
32
35
  #
33
36
  # @return [String, nil]
@@ -39,20 +42,25 @@ module RubyGit
39
42
  # Process the captured stdout output
40
43
  #
41
44
  # @example
42
- # result = ProcessExecuter.run('echo hello', out: StringIO.new)
45
+ # result = RubyGit::CommandLine::Result.new(
46
+ # ProcessExecuter.run_with_capture('echo hello')
47
+ # )
43
48
  # result.stdout #=> "hello\n"
44
49
  # result.process_stdout { |stdout, _result| stdout.upcase }
45
50
  # result.stdout #=> "HELLO\n"
46
51
  # result.unprocessed_stdout #=> "hello\n"
47
52
  #
48
53
  # @example Chain processing
49
- # result = ProcessExecuter.run('echo hello', out: StringIO.new)
54
+ # result = RubyGit::CommandLine::Result.new(
55
+ # ProcessExecuter.run_with_capture('echo hello')
56
+ # )
50
57
  # result.stdout #=> "hello\n"
58
+ # # Here is the chain processing:
51
59
  # result.process_stdout { |s| s.upcase }.process_stdout { |s| s.reverse }
52
60
  # result.stdout #=> "OLLEH\n"
53
61
  # result.unprocessed_stdout #=> "hello\n"
54
62
  #
55
- # @return [String, nil]
63
+ # @return [self]
56
64
  #
57
65
  # @yield [stdout, result] Yields the stdout output and the result object
58
66
  # @yieldparam stdout [String] The output to process
@@ -62,16 +70,19 @@ module RubyGit
62
70
  # @api public
63
71
  #
64
72
  def process_stdout(&block)
65
- return if block.nil?
73
+ return self if block.nil?
66
74
 
67
75
  @processed_stdout = block.call(stdout, self)
76
+
68
77
  self
69
78
  end
70
79
 
71
80
  # Returns the original stdout output before it was processed
72
81
  #
73
82
  # @example
74
- # result = ProcessExecuter.run('echo hello', out: StringIO.new)
83
+ # result = RubyGit::CommandLine::Result.new(
84
+ # ProcessExecuter.run_with_capture('echo hello')
85
+ # )
75
86
  # result.stdout #=> "hello\n"
76
87
  # result.unprocessed_stdout #=> "hello\n"
77
88
  # result.process_stdout { |s| s.upcase }
@@ -92,7 +103,9 @@ module RubyGit
92
103
  # `ProcessExecuter::MonitoredPipe`.
93
104
  #
94
105
  # @example
95
- # result = ProcessExecuter.run('echo hello 1>&2': err: StringIO.new)
106
+ # result = RubyGit::CommandLine::Result.new(
107
+ # ProcessExecuter.run_with_capture('echo hello >&2')
108
+ # )
96
109
  # result.stderr #=> "hello\n"
97
110
  #
98
111
  # @return [String, nil]
@@ -104,20 +117,25 @@ module RubyGit
104
117
  # Process the captured stderr output
105
118
  #
106
119
  # @example
107
- # result = ProcessExecuter.run('echo hello 1>&2', err: StringIO.new)
120
+ # result = RubyGit::CommandLine::Result.new(
121
+ # ProcessExecuter.run_with_capture('echo hello >&2')
122
+ # )
108
123
  # result.stderr #=> "hello\n"
109
124
  # result.process_stderr { |stderr, _result| stderr.upcase }
110
125
  # result.stderr #=> "HELLO\n"
111
126
  # result.unprocessed_stderr #=> "hello\n"
112
127
  #
113
128
  # @example Chain processing
114
- # result = ProcessExecuter.run('echo hello 1>&2', err: StringIO.new)
129
+ # result = RubyGit::CommandLine::Result.new(
130
+ # ProcessExecuter.run_with_capture('echo hello >&2')
131
+ # )
115
132
  # result.stderr #=> "hello\n"
133
+ # # Here is the chain processing:
116
134
  # result.process_stderr { |s| s.upcase }.process_stderr { |s| s.reverse }
117
135
  # result.stderr #=> "OLLEH\n"
118
136
  # result.unprocessed_stderr #=> "hello\n"
119
137
  #
120
- # @return [String, nil]
138
+ # @return [self]
121
139
  #
122
140
  # @yield [stderr, result] Yields the stderr output and the result object
123
141
  # @yieldparam stderr [String] The output to process
@@ -127,16 +145,19 @@ module RubyGit
127
145
  # @api public
128
146
  #
129
147
  def process_stderr(&block)
130
- return if block.nil?
148
+ return self if block.nil?
131
149
 
132
150
  @processed_stderr = block.call(stderr, self)
151
+
133
152
  self
134
153
  end
135
154
 
136
155
  # Returns the original stderr output before it was processed
137
156
  #
138
157
  # @example
139
- # result = ProcessExecuter.run('echo hello 1>&2', err: StringIO.new)
158
+ # result = RubyGit::CommandLine::Result.new(
159
+ # ProcessExecuter.run_with_capture('echo hello >&2')
160
+ # )
140
161
  # result.stderr #=> "hello\n"
141
162
  # result.unprocessed_stderr #=> "hello\n"
142
163
  # result.process_stderr { |stderr| stderr.upcase }
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'encoding_normalizer'
3
4
  require_relative 'result'
5
+
4
6
  require 'ruby_git/errors'
5
7
 
6
8
  module RubyGit
@@ -152,7 +154,7 @@ module RubyGit
152
154
  #
153
155
  # @return [RubyGit::CommandLine::Result] the result of the command
154
156
  #
155
- # @raise [ArgumentError] if `args` or `options_hash` are not valid
157
+ # @raise [RubyGit::ArgumentError] if `args` or `options_hash` are not valid
156
158
  #
157
159
  # @raise [RubyGit::FailedError] if the command returned a non-zero exitstatus
158
160
  #
@@ -163,18 +165,27 @@ module RubyGit
163
165
  # @raise [RubyGit::ProcessIOError] if an exception was raised while collecting subprocess output
164
166
  #
165
167
  def call(*args, **options_hash)
166
- options_hash[:raise_errors] = false
167
168
  options = RubyGit::CommandLine::Options.new(logger: logger, **options_hash)
168
- begin
169
- result = run_with_chdir([env, *build_git_cmd(args)], options)
169
+ result = run(*args, options)
170
+ process_result(result, options)
171
+ end
172
+
173
+ private
174
+
175
+ # Run the git command with the given arguments and options
176
+ # @return [ProcessExecuter::ResultWithCapture] the result of the command
177
+ # @api private
178
+ def run(*args, options)
179
+ # We don't want ProcessExecuter to raise an error if the command fails, but
180
+ # we want to preserve the value of the raise_errors option to use in
181
+ # process_result.
182
+ options.merge(raise_errors: false).then do |options|
183
+ run_with_chdir([env, *build_git_cmd(args)], options)
170
184
  rescue ProcessExecuter::ProcessIOError => e
171
185
  raise RubyGit::ProcessIOError.new(e.message), cause: e.exception.cause
172
186
  end
173
- process_result(result)
174
187
  end
175
188
 
176
- private
177
-
178
189
  # Run command with options with special handling for the `chdir` option on JRuby
179
190
  #
180
191
  # JRuby does not support the `chdir` option in `Process.spawn`. Note that this
@@ -183,7 +194,7 @@ module RubyGit
183
194
  # @param args [Array<String>] the command to run
184
195
  # @param options [RubyGit::CommandLine::Options] the options to pass to `Process.spawn`
185
196
  #
186
- # @return [ProcessExecuter::Result] the result of the command
197
+ # @return [ProcessExecuter::ResultWithCapture] the result of the command
187
198
  #
188
199
  # @api private
189
200
  #
@@ -195,7 +206,9 @@ module RubyGit
195
206
  Dir.chdir(options.chdir) do
196
207
  saved_chdir = options.chdir
197
208
  options.merge!(chdir: :not_set)
198
- run_and_handle_spawn_error(args, options).tap do
209
+ begin
210
+ run_and_handle_spawn_error(args, options)
211
+ ensure
199
212
  options.merge!(chdir: saved_chdir)
200
213
  end
201
214
  end
@@ -210,14 +223,14 @@ module RubyGit
210
223
  # @param args [Array<String>] the command to run
211
224
  # @param options [RubyGit::CommandLine::Options] the options to pass to `Process.spawn`
212
225
  #
213
- # @return [ProcessExecuter::Result] the result of the command
226
+ # @return [ProcessExecuter::ResultWithCapture] the result of the command
214
227
  #
215
228
  # @api private
216
229
  #
217
230
  def run_and_handle_spawn_error(args, options)
218
- ProcessExecuter.run_with_options(args, options)
231
+ ProcessExecuter.run_with_capture(*args, options)
219
232
  rescue ProcessExecuter::SpawnError => e
220
- raise RubyGit::SpawnError, e.message
233
+ raise RubyGit::SpawnError, e.message, cause: e
221
234
  end
222
235
 
223
236
  # Returns true if running on JRuby
@@ -228,11 +241,15 @@ module RubyGit
228
241
  def jruby? = RUBY_ENGINE == 'jruby'
229
242
 
230
243
  # Build the git command line from the available sources to send to `Process.spawn`
244
+ #
245
+ # @raise [RubyGit::ArgumentError] if the args array contains an array
246
+ #
231
247
  # @return [Array<String>]
248
+ #
232
249
  # @api private
233
250
  #
234
251
  def build_git_cmd(args)
235
- raise ArgumentError, 'The args array can not contain an array' if args.any? { |a| a.is_a?(Array) }
252
+ raise RubyGit::ArgumentError, 'The args array can not contain an array' if args.any? { |a| a.is_a?(Array) }
236
253
 
237
254
  [binary_path, *global_options, *args].map(&:to_s)
238
255
  end
@@ -248,18 +265,21 @@ module RubyGit
248
265
  # @return [RubyGit::CommandLineResult] the result of the command to return to the caller
249
266
  #
250
267
  # @raise [RubyGit::FailedError] if the command failed
268
+ #
251
269
  # @raise [RubyGit::SignaledError] if the command was signaled
270
+ #
252
271
  # @raise [RubyGit::TimeoutError] if the command times out
272
+ #
253
273
  # @raise [RubyGit::ProcessIOError] if an exception was raised while collecting subprocess output
254
274
  #
255
275
  # @api private
256
276
  #
257
- def process_result(result)
277
+ def process_result(result, options)
258
278
  RubyGit::CommandLine::Result.new(result).tap do |processed_result|
259
- raise_any_errors(processed_result) if processed_result.options.raise_git_errors
279
+ raise_any_errors(processed_result) if options.raise_errors
260
280
 
261
- processed_result.process_stdout { |s, r| process_output(s, r) }
262
- processed_result.process_stderr { |s, r| process_output(s, r) }
281
+ processed_result.process_stdout { |output, result| process_output(output, result) }
282
+ processed_result.process_stderr { |output, result| process_output(output, result) }
263
283
  end
264
284
  end
265
285
 
@@ -303,7 +323,7 @@ module RubyGit
303
323
 
304
324
  output =
305
325
  if result.options.normalize_encoding
306
- output.lines.map { |l| RubyGit::EncodingNormalizer.normalize(l) }.join
326
+ output.lines.map { |l| EncodingNormalizer.normalize(l) }.join
307
327
  else
308
328
  output.dup
309
329
  end
@@ -16,6 +16,7 @@ module RubyGit
16
16
  # ```text
17
17
  # StandardError
18
18
  # └─> RubyGit::Error
19
+ # ├─> RubyGit::ArgumentError
19
20
  # ├─> RubyGit::CommandLineError
20
21
  # │ ├─> RubyGit::FailedError
21
22
  # │ └─> RubyGit::SignaledError
@@ -28,6 +29,7 @@ module RubyGit
28
29
  # | Error Class | Description |
29
30
  # | --- | --- |
30
31
  # | `Error` | This catch-all error serves as the base class for other custom errors raised by the git gem. |
32
+ # | `ArgumentError` | Raised when an invalid argument is passed to a method. |
31
33
  # | `CommandLineError` | A subclass of this error is raised when there is a problem executing the git command line. |
32
34
  # | `FailedError` | This error is raised when the git command line exits with a non-zero status code that is not expected by the git gem. |
33
35
  # | `SignaledError` | This error is raised when the git command line is terminated as a result of receiving a signal. This could happen if the process is forcibly terminated or if there is a serious system error. |
@@ -66,6 +68,19 @@ module RubyGit
66
68
 
67
69
  # rubocop:enable Layout/LineLength
68
70
 
71
+ # Raised when an invalid argument is passed to a method
72
+ #
73
+ # @example Raising RubyGit::ArgumentError due to invalid option value
74
+ # begin
75
+ # RubyGit::CommandLine.run('status', timeout_after: 'not_a_number')
76
+ # rescue RubyGit::ArgumentError => e
77
+ # e.message #=> 'timeout_after must be nil or a non-negative real number but was "not_a_number"'
78
+ # end
79
+ #
80
+ # @api public
81
+ #
82
+ class ArgumentError < RubyGit::Error; end
83
+
69
84
  # Raised when a git command fails or exits because of an uncaught signal
70
85
  #
71
86
  # The git command executed, status, stdout, and stderr are available from this
@@ -3,5 +3,5 @@
3
3
  module RubyGit
4
4
  # The ruby_git gem version
5
5
  #
6
- VERSION = '0.3.6'
6
+ VERSION = '0.4.0'
7
7
  end
data/lib/ruby_git.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'ruby_git/command_line'
4
- require_relative 'ruby_git/encoding_normalizer'
5
4
  require_relative 'ruby_git/errors'
6
5
  require_relative 'ruby_git/option_validators'
7
6
  require_relative 'ruby_git/repository'
@@ -161,9 +160,7 @@ module RubyGit
161
160
  # or git was not found on the path.
162
161
  #
163
162
  def self.binary_version
164
- command = %w[version]
165
- options = { out: StringIO.new, err: StringIO.new }
166
- version_string = RubyGit::CommandLine.run(*command, **options).stdout[/\d+\.\d+(\.\d+)+/]
163
+ version_string = RubyGit::CommandLine.run('version').stdout[/\d+\.\d+(\.\d+)+/]
167
164
  version_string.split('.').collect(&:to_i)
168
165
  end
169
166
  end
@@ -33,4 +33,4 @@
33
33
  }
34
34
  ],
35
35
  "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
36
- }
36
+ }
data/ruby_git.gemspec CHANGED
@@ -56,7 +56,7 @@ Gem::Specification.new do |spec|
56
56
  spec.add_development_dependency 'yardstick', '~> 0.9'
57
57
  end
58
58
 
59
- spec.add_dependency 'process_executer', '~> 3.2'
59
+ spec.add_dependency 'process_executer', '~> 4.0'
60
60
  spec.add_dependency 'rchardet', '~> 1.9'
61
61
 
62
62
  spec.metadata['rubygems_mfa_required'] = 'true'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_git
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Couball
@@ -203,14 +203,14 @@ dependencies:
203
203
  requirements:
204
204
  - - "~>"
205
205
  - !ruby/object:Gem::Version
206
- version: '3.2'
206
+ version: '4.0'
207
207
  type: :runtime
208
208
  prerelease: false
209
209
  version_requirements: !ruby/object:Gem::Requirement
210
210
  requirements:
211
211
  - - "~>"
212
212
  - !ruby/object:Gem::Version
213
- version: '3.2'
213
+ version: '4.0'
214
214
  - !ruby/object:Gem::Dependency
215
215
  name: rchardet
216
216
  requirement: !ruby/object:Gem::Requirement
@@ -263,10 +263,10 @@ files:
263
263
  - bin/setup
264
264
  - lib/ruby_git.rb
265
265
  - lib/ruby_git/command_line.rb
266
+ - lib/ruby_git/command_line/encoding_normalizer.rb
266
267
  - lib/ruby_git/command_line/options.rb
267
268
  - lib/ruby_git/command_line/result.rb
268
269
  - lib/ruby_git/command_line/runner.rb
269
- - lib/ruby_git/encoding_normalizer.rb
270
270
  - lib/ruby_git/errors.rb
271
271
  - lib/ruby_git/option_validators.rb
272
272
  - lib/ruby_git/repository.rb
@@ -295,8 +295,8 @@ metadata:
295
295
  allowed_push_host: https://rubygems.org
296
296
  homepage_uri: https://github.com/main-branch/ruby_git
297
297
  source_code_uri: https://github.com/main-branch/ruby_git
298
- documentation_uri: https://rubydoc.info/gems/ruby_git/0.3.6
299
- changelog_uri: https://rubydoc.info/gems/ruby_git/0.3.6/file/CHANGELOG.md
298
+ documentation_uri: https://rubydoc.info/gems/ruby_git/0.4.0
299
+ changelog_uri: https://rubydoc.info/gems/ruby_git/0.4.0/file/CHANGELOG.md
300
300
  rubygems_mfa_required: 'true'
301
301
  rdoc_options: []
302
302
  require_paths:
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rchardet'
4
-
5
- module RubyGit
6
- # Utility to normalize string encoding
7
- # @api public
8
- module EncodingNormalizer
9
- # Detects the character encoding used to create a string or binary data
10
- #
11
- # Detects the encoding of a string or return binary if it cannot be detected
12
- #
13
- # @example
14
- # RubyGit::EncodingNormalizer.detect_encoding("Hello, world!") #=> "ascii"
15
- # RubyGit::EncodingNormalizer.detect_encoding("\xCB\xEF\xF1\xE5\xEC") #=> "ISO-8859-7"
16
- # RubyGit::EncodingNormalizer.detect_encoding("\xC0\xCC\xB0\xCD\xC0\xBA") #=> "EUC-KR"
17
- #
18
- # @param str [String] the string to detect the encoding of
19
- # @return [String] the detected encoding
20
- #
21
- def self.detect_encoding(str)
22
- CharDet.detect(str)&.dig('encoding') || Encoding::BINARY.name
23
- end
24
-
25
- # Normalizes the encoding to normalize_to
26
- #
27
- # @example
28
- # RubyGit::EncodingNormalizer.normalize("Hello, world!") #=> "Hello, world!"
29
- # RubyGit::EncodingNormalizer.normalize("\xCB\xEF\xF1\xE5\xEC") #=> "Λορεμ"
30
- # RubyGit::EncodingNormalizer.normalize("\xC0\xCC\xB0\xCD\xC0\xBA") #=> "이것은"
31
- #
32
- # @param str [String] the string to normalize
33
- # @param normalize_to [String] the name of the encoding to normalize to
34
- #
35
- # @return [String] the string with encoding converted to normalize_to
36
- #
37
- # @raise [Encoding::UndefinedConversionError] if the string cannot be converted to the default encoding
38
- #
39
- def self.normalize(str, normalize_to: Encoding::UTF_8.name)
40
- encoding_options = { invalid: :replace, undef: :replace }
41
-
42
- detected_encoding = detect_encoding(str)
43
-
44
- return str if str.valid_encoding? && detected_encoding == normalize_to
45
-
46
- str.encode(normalize_to, detected_encoding, **encoding_options)
47
- end
48
- end
49
- end