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 +4 -4
- data/.commitlintrc.yml +20 -3
- data/.github/workflows/enforce_conventional_commits.yml +24 -19
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile +0 -1
- data/lib/ruby_git/command_line/encoding_normalizer.rb +51 -0
- data/lib/ruby_git/command_line/options.rb +11 -14
- data/lib/ruby_git/command_line/result.rb +39 -18
- data/lib/ruby_git/command_line/runner.rb +38 -18
- data/lib/ruby_git/errors.rb +15 -0
- data/lib/ruby_git/version.rb +1 -1
- data/lib/ruby_git.rb +1 -4
- data/release-please-config.json +1 -1
- data/ruby_git.gemspec +1 -1
- metadata +6 -6
- data/lib/ruby_git/encoding_normalizer.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51c942c1d3e14a3d22755da43c9ea15bb80ddd92b31e40b53c008eee0a47de42
|
4
|
+
data.tar.gz: 3194cd1143c85ed1c532189c4ca010bbf2fad93aa9fe95293c3861a62feb665b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
19
|
-
|
20
|
-
type-
|
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
|
-
|
1
|
+
---
|
2
|
+
name: Conventional Commits
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
branches:
|
6
|
-
- main
|
4
|
+
permissions:
|
5
|
+
contents: read
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
on:
|
8
|
+
pull_request:
|
9
|
+
branches:
|
10
|
+
- main
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
jobs:
|
13
|
+
commit-lint:
|
14
|
+
name: Verify Conventional Commits
|
15
15
|
|
16
|
-
|
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
|
-
|
19
|
-
- name: Checkout
|
20
|
-
uses: actions/checkout@v4
|
21
|
-
with: { fetch-depth: 0 }
|
21
|
+
runs-on: ubuntu-latest
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
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 }
|
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
@@ -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::
|
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
|
-
#
|
34
|
-
# @return [
|
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
|
37
|
-
|
38
|
-
|
39
|
-
|
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::
|
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 =
|
19
|
+
# result = Git::CommandLine.run_with_capture('git', 'status')
|
19
20
|
# RubyGit::CommandLine::Result.new(result)
|
20
|
-
#
|
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 =
|
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 =
|
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 =
|
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 [
|
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 =
|
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 =
|
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 =
|
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 =
|
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 [
|
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 =
|
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
|
-
|
169
|
-
|
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::
|
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
|
-
|
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::
|
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.
|
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
|
279
|
+
raise_any_errors(processed_result) if options.raise_errors
|
260
280
|
|
261
|
-
processed_result.process_stdout { |
|
262
|
-
processed_result.process_stderr { |
|
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|
|
326
|
+
output.lines.map { |l| EncodingNormalizer.normalize(l) }.join
|
307
327
|
else
|
308
328
|
output.dup
|
309
329
|
end
|
data/lib/ruby_git/errors.rb
CHANGED
@@ -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
|
data/lib/ruby_git/version.rb
CHANGED
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
|
-
|
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
|
data/release-please-config.json
CHANGED
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', '~>
|
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.
|
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: '
|
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: '
|
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.
|
299
|
-
changelog_uri: https://rubydoc.info/gems/ruby_git/0.
|
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
|