qbash 0.0.4 → 0.0.6

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: 513c4fae2df78a6b4ae254b80dcd5e306c34a68cb8c1e869c3073ee612504d41
4
- data.tar.gz: 424695c22db403cfa8ad40def087742cb804a08e4d5c858f378c02ebd3a12303
3
+ metadata.gz: ddc357961a48953ee7c479583b6d648d9ad34873510e7ef6d8096a7bd8e596b5
4
+ data.tar.gz: 16dfe814c412365131380e239a93e90532419ece6e66fb3ce0c74bf6566cae5b
5
5
  SHA512:
6
- metadata.gz: 9fd4f01dd7ba2cbc6da044367d45d14a07e699c632e9ce421674b151095972465e7e3cd86e13bc3efcc80b29a33c9d62cf976c94b56db82578026a0734ba64e3
7
- data.tar.gz: e71a4444310641326ce9eb07d312eeaa5157f1c78faf8dcc0c1effc068df8ce50a3bcc3b184849ade9079bfb936a076bf774834ba1590191fe81ea62c835f8b9
6
+ metadata.gz: 15ae921b000efb256d6907b1b69cda9e60a63612d25eccab76b09f0c765d6aa9d1337ed43580b3bf18cfd84a73e69b4f16aaad62065c8df9644a87779c0d8485
7
+ data.tar.gz: 6de449a43159e54803266ca16cb960bd09772abbb9a33ad3b5fa77fa25be63cef6e38fa0edb003c342e2c495bfd37b98035365aa76a9a2b9271d99385498ac96
data/Gemfile CHANGED
@@ -32,9 +32,9 @@ gem 'random-port', '~>0.0', require: false
32
32
  gem 'rspec-rails', '7.0.1', require: false
33
33
  gem 'rubocop', '1.66.1', require: false
34
34
  gem 'rubocop-performance', '1.22.1', require: false
35
- gem 'rubocop-rspec', '3.0.5', require: false
35
+ gem 'rubocop-rspec', '3.1.0', require: false
36
36
  gem 'simplecov', '0.22.0', require: false
37
37
  gem 'simplecov-cobertura', '2.1.0', require: false
38
38
  gem 'w3c_validators', '1.3.7', require: false
39
- gem 'webmock', '3.23.1', require: false
39
+ gem 'webmock', '3.24.0', require: false
40
40
  gem 'yard', '0.9.37', require: false
data/Gemfile.lock CHANGED
@@ -5,6 +5,7 @@ PATH
5
5
  backtrace (> 0)
6
6
  elapsed (> 0)
7
7
  loog (> 0)
8
+ tago (> 0)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
@@ -94,7 +95,7 @@ GEM
94
95
  i18n (1.14.6)
95
96
  concurrent-ruby (~> 1.0)
96
97
  io-console (0.7.2)
97
- irb (1.14.0)
98
+ irb (1.14.1)
98
99
  rdoc (>= 4.0.0)
99
100
  reline (>= 0.4.2)
100
101
  json (2.7.2)
@@ -166,7 +167,7 @@ GEM
166
167
  regexp_parser (2.9.2)
167
168
  reline (0.5.10)
168
169
  io-console (~> 0.5)
169
- rexml (3.3.7)
170
+ rexml (3.3.8)
170
171
  rspec-core (3.13.1)
171
172
  rspec-support (~> 3.13.0)
172
173
  rspec-expectations (3.13.3)
@@ -199,7 +200,7 @@ GEM
199
200
  rubocop-performance (1.22.1)
200
201
  rubocop (>= 1.48.1, < 2.0)
201
202
  rubocop-ast (>= 1.31.1, < 2.0)
202
- rubocop-rspec (3.0.5)
203
+ rubocop-rspec (3.1.0)
203
204
  rubocop (~> 1.61)
204
205
  ruby-progressbar (1.13.0)
205
206
  securerandom (0.3.1)
@@ -225,11 +226,11 @@ GEM
225
226
  json (>= 1.8)
226
227
  nokogiri (~> 1.6)
227
228
  rexml (~> 3.2)
228
- webmock (3.23.1)
229
+ webmock (3.24.0)
229
230
  addressable (>= 2.8.0)
230
231
  crack (>= 0.3.2)
231
232
  hashdiff (>= 0.4.0, < 2.0.0)
232
- webrick (1.8.1)
233
+ webrick (1.8.2)
233
234
  yard (0.9.37)
234
235
  zeitwerk (2.6.18)
235
236
 
@@ -253,11 +254,11 @@ DEPENDENCIES
253
254
  rspec-rails (= 7.0.1)
254
255
  rubocop (= 1.66.1)
255
256
  rubocop-performance (= 1.22.1)
256
- rubocop-rspec (= 3.0.5)
257
+ rubocop-rspec (= 3.1.0)
257
258
  simplecov (= 0.22.0)
258
259
  simplecov-cobertura (= 2.1.0)
259
260
  w3c_validators (= 1.3.7)
260
- webmock (= 3.23.1)
261
+ webmock (= 3.24.0)
261
262
  yard (= 0.9.37)
262
263
 
263
264
  BUNDLED WITH
data/README.md CHANGED
@@ -32,6 +32,9 @@ stdout = qbash('echo "Hello, world!"', log: $stdout)
32
32
 
33
33
  If the command fails, an exception will be raised.
34
34
 
35
+ The function automatically merges `stderr` with `stdout`
36
+ (you can't change this).
37
+
35
38
  It's possible to provide the standard input and environment variables:
36
39
 
37
40
  ```ruby
@@ -82,6 +85,14 @@ qbash("cat #{Shellwords.escape(file)}")
82
85
  Without such an escaping, in this example, a space inside the `file`
83
86
  will lead to an unpredicatable result of the execution.
84
87
 
88
+ You can also set the maximum time for the command:
89
+
90
+ ```ruby
91
+ qbash("sleep 100", timeout: 4)
92
+ ```
93
+
94
+ This command will raise exception after four seconds.
95
+
85
96
  ## How to contribute
86
97
 
87
98
  Read
data/lib/qbash.rb CHANGED
@@ -24,6 +24,7 @@ require 'backtrace'
24
24
  require 'loog'
25
25
  require 'open3'
26
26
  require 'shellwords'
27
+ require 'tago'
27
28
 
28
29
  # Execute one bash command.
29
30
  #
@@ -33,18 +34,27 @@ require 'shellwords'
33
34
  module Kernel
34
35
  # Execute a single bash command.
35
36
  #
37
+ # For example:
38
+ #
39
+ # year = qbash('date +%Y')
40
+ #
36
41
  # If exit code is not zero, an exception will be raised.
37
42
  #
38
43
  # To escape arguments, use +Shellwords.escape()+ method.
39
44
  #
45
+ # Stderr automatically merges with stdout.
46
+ #
47
+ # Read this <a href="https://github.com/yegor256/qbash">README</a> file for more details.
48
+ #
40
49
  # @param [String] cmd The command to run, for example +echo "Hello, world!"+
41
50
  # @param [String] stdin The +stdin+ to provide to the command
42
51
  # @param [Hash] env Hash of environment variables
43
52
  # @param [Loog|IO] log Logging facility with +.debug()+ method (or +$stdout+)
44
- # @param [Array] accept List of accepted exit codes (accepts all if the list is empty)
53
+ # @param [Array] accept List of accepted exit codes (accepts all if the list is +nil+)
45
54
  # @param [Boolean] both If set to TRUE, the function returns an array +(stdout, code)+
55
+ # @param [Integer] timeout If it's set to non-NIL, the execution will fail after this number of seconds
46
56
  # @return [String] Everything that was printed to the +stdout+ by the command
47
- def qbash(cmd, stdin: '', env: {}, log: Loog::NULL, accept: [0], both: false)
57
+ def qbash(cmd, stdin: '', env: {}, log: Loog::NULL, accept: [0], both: false, timeout: nil)
48
58
  cmd = cmd.join(' ') if cmd.is_a?(Array)
49
59
  if log.respond_to?(:debug)
50
60
  log.debug("+ #{cmd}")
@@ -53,25 +63,32 @@ module Kernel
53
63
  end
54
64
  buf = ''
55
65
  e = 1
56
- Open3.popen2e(env, "/bin/bash -c #{Shellwords.escape(cmd)}") do |sin, sout, thr|
57
- sin.write(stdin)
58
- sin.close
59
- until sout.eof?
60
- begin
61
- ln = sout.gets
62
- rescue IOError => e
63
- ln = Backtrace.new(e).to_s
64
- end
65
- if log.respond_to?(:debug)
66
- log.debug(ln)
67
- else
68
- log.print("#{ln}\n")
66
+ start = Time.now
67
+ thread =
68
+ Thread.new do
69
+ Open3.popen2e(env, "/bin/bash -c #{Shellwords.escape(cmd)}") do |sin, sout, thr|
70
+ sin.write(stdin)
71
+ sin.close
72
+ until sout.eof?
73
+ begin
74
+ ln = sout.gets
75
+ rescue IOError => e
76
+ ln = Backtrace.new(e).to_s
77
+ end
78
+ if log.respond_to?(:debug)
79
+ log.debug(ln)
80
+ else
81
+ log.print("#{ln}\n")
82
+ end
83
+ buf += ln
84
+ end
85
+ e = thr.value.to_i
86
+ if !accept.nil? && !accept.include?(e)
87
+ raise "The command '#{cmd}' failed with exit code ##{e} in #{start.ago}\n#{buf}"
88
+ end
69
89
  end
70
- buf += ln
71
90
  end
72
- e = thr.value.to_i
73
- raise "The command '#{cmd}' failed with exit code ##{e}\n#{buf}" if !accept.empty? && !accept.include?(e)
74
- end
91
+ raise "Execution of #{cmd} timed out in #{start.ago}" if thread.join(timeout).nil?
75
92
  return [buf, e] if both
76
93
  buf
77
94
  end
data/qbash.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
27
27
  s.required_ruby_version = '>=3.2'
28
28
  s.name = 'qbash'
29
- s.version = '0.0.4'
29
+ s.version = '0.0.6'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Quick Executor of a BASH Command'
32
32
  s.description =
@@ -42,5 +42,6 @@ Gem::Specification.new do |s|
42
42
  s.add_dependency 'backtrace', '>0'
43
43
  s.add_dependency 'elapsed', '>0'
44
44
  s.add_dependency 'loog', '>0'
45
+ s.add_dependency 'tago', '>0'
45
46
  s.metadata['rubygems_mfa_required'] = 'true'
46
47
  end
data/test/test_qbash.rb CHANGED
@@ -57,6 +57,12 @@ class TestQbash < Minitest::Test
57
57
  end
58
58
  end
59
59
 
60
+ def test_with_timeout
61
+ assert_raises do
62
+ qbash('sleep 100', timeout: 0.1)
63
+ end
64
+ end
65
+
60
66
  def test_with_special_symbols
61
67
  assert_equal("'hi'\n", qbash("echo \"'hi'\""))
62
68
  end
@@ -69,13 +75,13 @@ class TestQbash < Minitest::Test
69
75
 
70
76
  def test_ignore_errors
71
77
  Dir.mktmpdir do |home|
72
- qbash("cat #{Shellwords.escape(File.join(home, 'b.txt'))}", accept: [])
78
+ qbash("cat #{Shellwords.escape(File.join(home, 'b.txt'))}", accept: nil)
73
79
  end
74
80
  end
75
81
 
76
82
  def test_with_both
77
83
  Dir.mktmpdir do |home|
78
- stdout, code = qbash("cat #{Shellwords.escape(File.join(home, 'foo.txt'))}", accept: [], both: true)
84
+ stdout, code = qbash("cat #{Shellwords.escape(File.join(home, 'foo.txt'))}", accept: nil, both: true)
79
85
  assert(code.positive?)
80
86
  assert(!stdout.empty?)
81
87
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qbash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-25 00:00:00.000000000 Z
11
+ date: 2024-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tago
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: With the help of Open3 executes bash command and conveniently returns
56
70
  its output and exit code
57
71
  email: yegor256@gmail.com