cheetah 0.5.2 → 1.0.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/CHANGELOG +6 -0
- data/VERSION +1 -1
- data/lib/cheetah/version.rb +1 -1
- data/lib/cheetah.rb +58 -53
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd4cbe464be1d5ee56434c1a380d958cf0cbcb40095d8f21fcfb3cf7b2320db2
|
4
|
+
data.tar.gz: 3572805d086b24911c1feb6169b5911723a918fcf1ca0547d2f28984e0827ade
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 032f86dbf253379e1663e01d03f8a5a013a13829e4bb5b9c3f880d73611a2c92176e51086402b604cfd20a30d28dfa1571766b9fa2e4eb5377e4c12a6bda1b39
|
7
|
+
data.tar.gz: 1ecf8c2ff66d2eef73b658f925bbb5a7c6292861ce4fd52a9f2ed6fab91e49f3ba25fe5cd84f8da294b6340887872c9ef5100f2799fa8f8c319afbcead8ced3e
|
data/CHANGELOG
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0
|
data/lib/cheetah/version.rb
CHANGED
data/lib/cheetah.rb
CHANGED
@@ -5,7 +5,7 @@ require "logger"
|
|
5
5
|
require "shellwords"
|
6
6
|
require "stringio"
|
7
7
|
|
8
|
-
require File.expand_path(File.dirname(__FILE__)
|
8
|
+
require File.expand_path("#{File.dirname(__FILE__)}/cheetah/version")
|
9
9
|
|
10
10
|
# Your swiss army knife for executing external commands in Ruby safely and
|
11
11
|
# conveniently.
|
@@ -121,6 +121,7 @@ module Cheetah
|
|
121
121
|
#
|
122
122
|
# @abstract
|
123
123
|
# @param [Process::Status] status the executed command exit status
|
124
|
+
# @param [Boolean] allowed_status whether the exit code is in the list of allowed exit codes
|
124
125
|
abstract_method :record_status
|
125
126
|
end
|
126
127
|
|
@@ -135,7 +136,7 @@ module Cheetah
|
|
135
136
|
|
136
137
|
def record_stderr(_stderr); end
|
137
138
|
|
138
|
-
def record_status(_status);
|
139
|
+
def record_status(_status, _allowed_status); end
|
139
140
|
end
|
140
141
|
|
141
142
|
# A default recorder. It uses the `Logger::INFO` level for normal messages and
|
@@ -150,6 +151,8 @@ module Cheetah
|
|
150
151
|
}.freeze
|
151
152
|
|
152
153
|
def initialize(logger)
|
154
|
+
super()
|
155
|
+
|
153
156
|
@logger = logger
|
154
157
|
|
155
158
|
@stream_used = { stdin: false, stdout: false, stderr: false }
|
@@ -172,19 +175,19 @@ module Cheetah
|
|
172
175
|
log_stream_increment(:stderr, stderr)
|
173
176
|
end
|
174
177
|
|
175
|
-
def record_status(status)
|
178
|
+
def record_status(status, allowed_status)
|
176
179
|
log_stream_remainder(:stdin)
|
177
180
|
log_stream_remainder(:stdout)
|
178
181
|
log_stream_remainder(:stderr)
|
179
182
|
|
180
|
-
@logger.send
|
183
|
+
@logger.send allowed_status ? :info : :error,
|
181
184
|
"Status: #{status.exitstatus}"
|
182
185
|
end
|
183
186
|
|
184
187
|
protected
|
185
188
|
|
186
189
|
def format_commands(commands)
|
187
|
-
|
190
|
+
"\"#{commands.map { |c| Shellwords.join(c) }.join(' | ')}\""
|
188
191
|
end
|
189
192
|
|
190
193
|
def log_stream_increment(stream, data)
|
@@ -402,14 +405,19 @@ module Cheetah
|
|
402
405
|
select_loop(streams, pipes, recorder)
|
403
406
|
_pid, status = Process.wait2(pid)
|
404
407
|
|
405
|
-
# when more exit status are allowed, then
|
406
|
-
# not
|
407
|
-
|
408
|
+
# when more exit status are allowed, then pass it below that it did
|
409
|
+
# not fail (bsc#1153749)
|
410
|
+
success = allowed_status?(status, options)
|
408
411
|
|
409
412
|
begin
|
410
|
-
|
413
|
+
report_errors(commands, status, streams, streamed) if !success
|
411
414
|
ensure
|
412
|
-
|
415
|
+
# backward compatibility for recorders with just single parameter
|
416
|
+
if recorder.method(:record_status).arity == 1
|
417
|
+
recorder.record_status(status)
|
418
|
+
else
|
419
|
+
recorder.record_status(status, success)
|
420
|
+
end
|
413
421
|
end
|
414
422
|
|
415
423
|
build_result(streams, status, options)
|
@@ -417,12 +425,11 @@ module Cheetah
|
|
417
425
|
|
418
426
|
private
|
419
427
|
|
420
|
-
def
|
421
|
-
|
428
|
+
def allowed_status?(status, options)
|
429
|
+
exit_status = status.exitstatus
|
430
|
+
return exit_status.zero? unless allowed_exitstatus?(options)
|
422
431
|
|
423
|
-
|
424
|
-
options[:allowed_exitstatus].include?(exitstatus)
|
425
|
-
end
|
432
|
+
options[:allowed_exitstatus].include?(exit_status)
|
426
433
|
end
|
427
434
|
|
428
435
|
# Parts of Cheetah.run
|
@@ -519,51 +526,49 @@ module Cheetah
|
|
519
526
|
|
520
527
|
def fork_commands_recursive(commands, pipes, options)
|
521
528
|
fork do
|
522
|
-
|
523
|
-
|
524
|
-
options = chroot_step(options)
|
525
|
-
|
526
|
-
if commands.size == 1
|
527
|
-
from_pipe(STDIN, pipes[:stdin])
|
528
|
-
else
|
529
|
-
pipe_to_child = IO.pipe
|
530
|
-
|
531
|
-
fork_commands_recursive(commands[0..-2],
|
532
|
-
{
|
533
|
-
stdin: pipes[:stdin],
|
534
|
-
stdout: pipe_to_child,
|
535
|
-
stderr: pipes[:stderr]
|
536
|
-
},
|
537
|
-
options)
|
538
|
-
|
539
|
-
pipes[:stdin][READ].close
|
540
|
-
pipes[:stdin][WRITE].close
|
541
|
-
|
542
|
-
from_pipe(STDIN, pipe_to_child)
|
543
|
-
end
|
529
|
+
# support chrooting
|
530
|
+
options = chroot_step(options)
|
544
531
|
|
545
|
-
|
546
|
-
|
532
|
+
if commands.size == 1
|
533
|
+
from_pipe($stdin, pipes[:stdin])
|
534
|
+
else
|
535
|
+
pipe_to_child = IO.pipe
|
547
536
|
|
548
|
-
|
537
|
+
fork_commands_recursive(commands[0..-2],
|
538
|
+
{
|
539
|
+
stdin: pipes[:stdin],
|
540
|
+
stdout: pipe_to_child,
|
541
|
+
stderr: pipes[:stderr]
|
542
|
+
},
|
543
|
+
options)
|
549
544
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
# depends when failed, if pipe is already redirected or not, so lets find it
|
556
|
-
output = pipes[:stderr][WRITE].closed? ? STDERR : pipes[:stderr][WRITE]
|
557
|
-
output.puts e.message
|
545
|
+
pipes[:stdin][READ].close
|
546
|
+
pipes[:stdin][WRITE].close
|
547
|
+
|
548
|
+
from_pipe($stdin, pipe_to_child)
|
549
|
+
end
|
558
550
|
|
559
|
-
|
551
|
+
into_pipe($stdout, pipes[:stdout])
|
552
|
+
into_pipe($stderr, pipes[:stderr])
|
553
|
+
|
554
|
+
close_fds
|
555
|
+
|
556
|
+
command, *args = commands.last
|
557
|
+
with_env(options[:env]) do
|
558
|
+
exec([command, command], *args)
|
560
559
|
end
|
560
|
+
rescue SystemCallError => e
|
561
|
+
# depends when failed, if pipe is already redirected or not, so lets find it
|
562
|
+
output = pipes[:stderr][WRITE].closed? ? $stderr : pipes[:stderr][WRITE]
|
563
|
+
output.puts e.message
|
564
|
+
|
565
|
+
exit!(127)
|
561
566
|
end
|
562
567
|
end
|
563
568
|
|
564
569
|
# closes all open fds starting with 3 and above
|
565
570
|
def close_fds
|
566
|
-
#
|
571
|
+
# NOTE: this will work only if unix has /proc filesystem. If it does not
|
567
572
|
# have it, it won't close other fds.
|
568
573
|
Dir.glob("/proc/self/fd/*").each do |path|
|
569
574
|
fd = File.basename(path).to_i
|
@@ -655,7 +660,7 @@ module Cheetah
|
|
655
660
|
end
|
656
661
|
end
|
657
662
|
|
658
|
-
def
|
663
|
+
def report_errors(commands, status, streams, streamed)
|
659
664
|
return if status.success?
|
660
665
|
|
661
666
|
stderr_part = if streamed[:stderr]
|
@@ -664,7 +669,7 @@ module Cheetah
|
|
664
669
|
" (no error output)"
|
665
670
|
else
|
666
671
|
lines = streams[:stderr].string.split("\n")
|
667
|
-
":
|
672
|
+
": #{lines.first}#{lines.size > 1 ? ' (...)' : ''}"
|
668
673
|
end
|
669
674
|
|
670
675
|
raise ExecutionFailed.new(
|
@@ -707,7 +712,7 @@ module Cheetah
|
|
707
712
|
end
|
708
713
|
|
709
714
|
def format_commands(commands)
|
710
|
-
|
715
|
+
"\"#{commands.map { |c| Shellwords.join(c) }.join(' | ')}\""
|
711
716
|
end
|
712
717
|
end
|
713
718
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cheetah
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Majda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: abstract_method
|
@@ -77,7 +77,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
77
|
requirements:
|
78
78
|
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version: '
|
80
|
+
version: '2.5'
|
81
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
82
|
requirements:
|
83
83
|
- - ">="
|
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
85
|
version: '0'
|
86
86
|
requirements: []
|
87
87
|
rubyforge_project:
|
88
|
-
rubygems_version: 2.7.6.
|
88
|
+
rubygems_version: 2.7.6.3
|
89
89
|
signing_key:
|
90
90
|
specification_version: 4
|
91
91
|
summary: Your swiss army knife for executing external commands in Ruby safely and
|