Hello community, here is the log from the commit of package rubygem-cheetah for openSUSE:Factory checked in at 2016-03-16 10:26:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-cheetah (Old) and /work/SRC/openSUSE:Factory/.rubygem-cheetah.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-cheetah" Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-cheetah/rubygem-cheetah.changes 2015-01-29 09:55:47.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-cheetah.new/rubygem-cheetah.changes 2016-03-16 10:26:23.000000000 +0100 @@ -2 +2 @@ -Thu Jan 22 10:23:09 UTC 2015 - [email protected] +Sat Dec 19 05:30:47 UTC 2015 - [email protected] @@ -4 +4,21 @@ -- Use ruby-macros >= 5 and follow packaging guidelines +- updated to version 0.5.0 + see installed CHANGELOG + + 0.5.0 (2015-12-18) + ------------------ + + * Added chroot option for executing in different system root. + * Added ENV overwrite option. + * Allowed to specify known exit codes that are not errors. + * Documented how to execute in different working directory. + * Allowed passing nil as :stdin to be same as :stdout and :strerr. + * Converted parameters for command to strings with `.to_s`. + * Adapted testsuite to new rspec. + * Updated documentation with various fixes. + * Dropped support for Ruby 1.9.3. + * Added support for Ruby 2.1 and 2.2. + +------------------------------------------------------------------- +Wed Nov 5 15:50:28 UTC 2014 - [email protected] + +- adapt to new rubygem packaging Old: ---- cheetah-0.4.0.gem New: ---- cheetah-0.5.0.gem gem2rpm.yml ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-cheetah.spec ++++++ --- /var/tmp/diff_new_pack.ICxtm6/_old 2016-03-16 10:26:24.000000000 +0100 +++ /var/tmp/diff_new_pack.ICxtm6/_new 2016-03-16 10:26:24.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package rubygem-cheetah # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,8 +16,15 @@ # +# +# This file was generated with a gem2rpm.yml and not just plain gem2rpm. +# All sections marked as MANUAL, license headers, summaries and descriptions +# can be maintained in that file. Please consult this file before editing any +# of those fields +# + Name: rubygem-cheetah -Version: 0.4.0 +Version: 0.5.0 Release: 0 %define mod_name cheetah %define mod_full_name %{mod_name}-%{version} @@ -27,6 +34,7 @@ BuildRequires: ruby-macros >= 5 Url: https://github.com/openSUSE/cheetah Source: http://rubygems.org/gems/%{mod_full_name}.gem +Source1: gem2rpm.yml Summary: Your swiss army knife for executing external commands in Ruby safely License: MIT Group: Development/Languages/Ruby @@ -41,7 +49,7 @@ %install %gem_install \ - --doc-files="LICENSE README.md" \ + --doc-files="CHANGELOG LICENSE README.md" \ -f %gem_packages ++++++ cheetah-0.4.0.gem -> cheetah-0.5.0.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/CHANGELOG new/CHANGELOG --- old/CHANGELOG 1970-01-01 01:00:00.000000000 +0100 +++ new/CHANGELOG 2015-12-18 15:34:32.000000000 +0100 @@ -1,11 +1,25 @@ +0.5.0 (2015-12-18) +------------------ + +* Added chroot option for executing in different system root. +* Added ENV overwrite option. +* Allowed to specify known exit codes that are not errors. +* Documented how to execute in different working directory. +* Allowed passing nil as :stdin to be same as :stdout and :strerr. +* Converted parameters for command to strings with `.to_s`. +* Adapted testsuite to new rspec. +* Updated documentation with various fixes. +* Dropped support for Ruby 1.9.3. +* Added support for Ruby 2.1 and 2.2. + 0.4.0 (2013-11-21) ------------------ * Implemented incremental logging. The input and both outputs of the executed command are now logged one-by-line by the default recorder. A custom recorder can record them on even finer granularity. -* Dropped support of Ruby 1.8.7. -* Added support of Ruby 2.0.0. +* Dropped support for Ruby 1.8.7. +* Added support for Ruby 2.0.0. * Internal code improvements. 0.3.0 (2012-06-21) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md --- old/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/README.md 2015-12-18 15:34:32.000000000 +0100 @@ -1,5 +1,9 @@ Cheetah ======= +[](https://travis-ci.org/openSUSE/cheetah) +[](https://codeclimate.com/github/openSUSE/cheetah) +[](https://coveralls.io/r/openSUSE/cheetah?branch=master) + Your swiss army knife for executing external commands in Ruby safely and conveniently. @@ -9,11 +13,11 @@ ```ruby # Run a command and capture its output -files = Cheetah.run("ls", "-la", :stdout => :capture) +files = Cheetah.run("ls", "-la", stdout: :capture) # Run a command and capture its output into a stream File.open("files.txt", "w") do |stdout| - Cheetah.run("ls", "-la", :stdout => stdout) + Cheetah.run("ls", "-la", stdout: stdout) end # Run a command and handle errors @@ -22,7 +26,7 @@ rescue Cheetah::ExecutionFailed => e puts e.message puts "Standard output: #{e.stdout}" - puts "Error ouptut: #{e.stderr}" + puts "Error output: #{e.stderr}" end ``` @@ -34,7 +38,11 @@ * Piping commands together * 100% secure (shell expansion is impossible by design) * Raises exceptions on errors (no more manual status code checks) + but allows to specify which non-zero codes are not an error + * Thread-safety + * Allows overriding environment variables * Optional logging for easy debugging + * Running on changed root ( requires chroot permission ) Non-features ------------ @@ -63,13 +71,16 @@ ```ruby Cheetah.run("tar", "xzf", "foo.tar.gz") + +Cheetah converts each argument to a string using `#to_s`. + ``` ### Passing Input Using the `:stdin` option you can pass a string to command's standard input: ```ruby -Cheetah.run("python", :stdin => source_code) +Cheetah.run("python", stdin: source_code) ``` If the input is big you may want to avoid passing it in one huge string. In that @@ -78,7 +89,7 @@ ```ruby File.open("huge_program.py") do |stdin| - Cheetah.run("python", :stdin => stdin) + Cheetah.run("python", stdin: stdin) end ``` @@ -88,7 +99,7 @@ You will receive the output as a return value of the call: ```ruby -files = Cheetah.run("ls", "-la", :stdout => :capture) +files = Cheetah.run("ls", "-la", stdout: :capture) ``` The same technique works with the error output — just use the `:stderr` option. @@ -96,7 +107,7 @@ array: ```ruby -results, errors = Cheetah.run("grep", "-r", "User", ".", :stdout => :capture, :stderr => :capture) +results, errors = Cheetah.run("grep", "-r", "User", ".", stdout: => :capture, stderr: => :capture) ``` If the output is big you may want to avoid capturing it into a huge string. In @@ -105,7 +116,7 @@ ```ruby File.open("files.txt", "w") do |stdout| - Cheetah.run("ls", "-la", :stdout => stdout) + Cheetah.run("ls", "-la", stdout: stdout) end ``` @@ -115,12 +126,12 @@ the commands together with their arguments as arrays: ```ruby -processes = Cheetah.run(["ps", "aux"], ["grep", "ruby"], :stdout => :capture) +processes = Cheetah.run(["ps", "aux"], ["grep", "ruby"], stdout: :capture) ``` ### Error Handling -If the command can't be executed for some reason or returns a non-zero exit +If the command can't be executed for some reason or returns an unexpected non-zero exit status, Cheetah raises an exception with detailed information about the failure: ```ruby @@ -130,7 +141,8 @@ rescue Cheetah::ExecutionFailed => e puts e.message puts "Standard output: #{e.stdout}" - puts "Error ouptut: #{e.stderr}" + puts "Error output: #{e.stderr}" + puts "Exit status: #{e.status.exitstatus}" end ``` ### Logging @@ -139,7 +151,55 @@ status, input and both outputs to it: ```ruby -Cheetah.run("ls -l", :logger => logger) +Cheetah.run("ls -l", logger: logger) +``` + +### Overwriting env + +If the command needs adapted environment variables, use the :env option. +Passed hash is used to update existing env (for details see ENV.update). +Nil value means unset variable. Environment is restored to its original state after +running the command. + +```ruby + Cheetah.run("env", env: { "LC_ALL" => "C" }) +``` + +### Expecting Non-zero Exit Status + +If command is expected to return valid a non-zero exit status like `grep` command +which return `1` if given regexp is not found, then option `:allowed_exitstatus` +can be used: + +```ruby +# Run a command, handle exitstatus and handle errors +begin + exitstatus = Cheetah.run("grep", "userA", "/etc/passwd", allowed_exitstatus: 1) + if exitstates == 0 + puts "found" + else + puts "not found" + end +rescue Cheetah::ExecutionFailed => e + puts e.message + puts "Standard output: #{e.stdout}" + puts "Error output: #{e.stderr}" + puts "Exit status: #{e.status.exitstatus}" +end +``` + +Exit status is returned as last element of result. If it is only captured thing, +then it is return without array. +Supported input for `allowed_exitstatus` are anything supporting include, fixnum +or nil for no allowed existatus. + +```ruby +# allowed inputs +allowed_exitstatus: 1 +allowed_exitstatus: 1..5 +allowed_exitstatus: [1, 2] +allowed_exitstatus: object_with_include_method +allowed_exitstatus: nil ``` ### Setting Defaults @@ -149,13 +209,33 @@ ```ruby # If you're tired of passing the :logger option all the time... -Cheetah.default_options = { :logger = my_logger } +Cheetah.default_options = { :logger => my_logger } Cheetah.run("./configure") Cheetah.run("make") Cheetah.run("make", "install") Cheetah.default_options = {} ``` +### Changing Working Directory + +If diferent working directory is needed for running program, then suggested +usage is to enclose call into `Dir.chdir` method. + +```ruby +Dir.chdir("/workspace") do + Cheetah.run("make") +end +``` + +### Changing System Root + +If a command needs to be executed in different system root then the `:chroot` +option can be used: + +```ruby +Cheetah.run("/usr/bin/inspect", chroot: "/mnt/target_system") +``` + ### More Information For more information, see the @@ -164,7 +244,7 @@ Compatibility ------------- -Cheetah should run well on any Unix system with Ruby 1.9.3 or 2.0.0. Non-Unix +Cheetah should run well on any Unix system with Ruby 2.0.0, 2.1 and 2.2. Non-Unix systems and different Ruby implementations/versions may work too but they were not tested. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/VERSION new/VERSION --- old/VERSION 1970-01-01 01:00:00.000000000 +0100 +++ new/VERSION 2015-12-18 15:34:32.000000000 +0100 @@ -1 +1 @@ -0.4.0 +0.5.0 Files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/cheetah/version.rb new/lib/cheetah/version.rb --- old/lib/cheetah/version.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/cheetah/version.rb 2015-12-18 15:34:32.000000000 +0100 @@ -1,3 +1,4 @@ +# Cheetah namespace module Cheetah # Cheetah version (uses [semantic versioning](http://semver.org/)). VERSION = File.read(File.dirname(__FILE__) + "/../../VERSION").strip diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/cheetah.rb new/lib/cheetah.rb --- old/lib/cheetah.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/cheetah.rb 2015-12-18 15:34:32.000000000 +0100 @@ -22,11 +22,11 @@ # * Handling of interactive commands # # @example Run a command and capture its output -# files = Cheetah.run("ls", "-la", :stdout => :capture) +# files = Cheetah.run("ls", "-la", stdout: :capture) # # @example Run a command and capture its output into a stream # File.open("files.txt", "w") do |stdout| -# Cheetah.run("ls", "-la", :stdout => stdout) +# Cheetah.run("ls", "-la", stdout: stdout) # end # # @example Run a command and handle errors @@ -125,11 +125,15 @@ # A recorder that does not record anyting. Used by {Cheetah.run} when no # logger is passed. class NullRecorder < Recorder - def record_commands(commands); end - def record_stdin(stdin); end - def record_stdout(stdout); end - def record_stderr(stderr); end - def record_status(status); end + def record_commands(_commands); end + + def record_stdin(_stdin); end + + def record_stdout(_stdout); end + + def record_stderr(_stderr); end + + def record_status(_status); end end # A default recorder. It uses the `Logger::INFO` level for normal messages and @@ -138,16 +142,16 @@ class DefaultRecorder < Recorder # @private STREAM_INFO = { - :stdin => { :name => "Standard input", :method => :info }, - :stdout => { :name => "Standard output", :method => :info }, - :stderr => { :name => "Error output", :method => :error } + stdin: { name: "Standard input", method: :info }, + stdout: { name: "Standard output", method: :info }, + stderr: { name: "Error output", method: :error } } def initialize(logger) @logger = logger - @stream_used = { :stdin => false, :stdout => false, :stderr => false } - @stream_buffer = { :stdin => "", :stdout => "", :stderr => "" } + @stream_used = { stdin: false, stdout: false, stderr: false } + @stream_buffer = { stdin: "", stdout: "", stderr: "" } end def record_commands(commands) @@ -172,7 +176,7 @@ log_stream_remainder(:stderr) @logger.send status.success? ? :info : :error, - "Status: #{status.exitstatus}" + "Status: #{status.exitstatus}" end protected @@ -183,7 +187,8 @@ def log_stream_increment(stream, data) @stream_buffer[stream] + data =~ /\A((?:.*\n)*)(.*)\z/ - lines, rest = $1, $2 + lines = Regexp.last_match(1) + rest = Regexp.last_match(2) lines.each_line { |l| log_stream_line(stream, l) } @@ -192,9 +197,9 @@ end def log_stream_remainder(stream) - if @stream_used[stream] && !@stream_buffer[stream].empty? - log_stream_line(stream, @stream_buffer[stream]) - end + return if !@stream_used[stream] || @stream_buffer[stream].empty? + + log_stream_line(stream, @stream_buffer[stream]) end def log_stream_line(stream, line) @@ -207,10 +212,12 @@ # @private BUILTIN_DEFAULT_OPTIONS = { - :stdin => "", - :stdout => nil, - :stderr => nil, - :logger => nil + stdin: "", + stdout: nil, + stderr: nil, + logger: nil, + env: {}, + chroot: "/" } READ = 0 # @private @@ -225,7 +232,7 @@ # By default, no values are specified here. # # @example Setting a logger once for execution of multiple commands - # Cheetah.default_options = { :logger = my_logger } + # Cheetah.default_options = { logger: my_logger } # Cheetah.run("./configure") # Cheetah.run("make") # Cheetah.run("make", "install") @@ -244,7 +251,7 @@ # multiple command case, the execution succeeds if the last command can be # executed and returns a zero exit status.) # - # Commands and their arguments never undergo shell expansion — they are + # Commands and their arguments never undergo shell expansion - they are # passed directly to the operating system. While this may create some # inconvenience in certain cases, it eliminates a whole class of security # bugs. @@ -296,6 +303,14 @@ # execution # @option options [Recorder, nil] :recorder (DefaultRecorder.new) recorder # to handle the command execution logging + # @option options [Fixnum, .include?, nil] :allowed_exitstatus (nil) + # Allows to specify allowed exit codes that do not cause exception. It + # adds as last element of result exitstatus. + # @option options [Hash] :env ({}) + # Allows to update ENV for the time of running the command. if key maps to nil value it + # is deleted from ENV. + # @option options [String] :chroot ("/") + # Allows to run on different system root. # # @example # Cheetah.run("tar", "xzf", "foo.tar.gz") @@ -325,16 +340,16 @@ # in the first variant # # @example - # processes = Cheetah.run(["ps", "aux"], ["grep", "ruby"], :stdout => :capture) + # processes = Cheetah.run(["ps", "aux"], ["grep", "ruby"], stdout: :capture) # # @raise [ExecutionFailed] when the execution fails # # @example Run a command and capture its output - # files = Cheetah.run("ls", "-la", :stdout => capture) + # files = Cheetah.run("ls", "-la", stdout: :capture) # # @example Run a command and capture its output into a stream # File.open("files.txt", "w") do |stdout| - # Cheetah.run("ls", "-la", :stdout => stdout) + # Cheetah.run("ls", "-la", stdout: stdout) # end # # @example Run a command and handle errors @@ -345,10 +360,35 @@ # puts "Standard output: #{e.stdout}" # puts "Error ouptut: #{e.stderr}" # end + # + # @example Run a command with expected false and handle errors + # begin + # # exit code 1 for grep mean not found + # result = Cheetah.run("grep", "userA", "/etc/passwd", allowed_exitstatus: 1) + # if result == 0 + # puts "found" + # else + # puts "not found" + # end + # rescue Cheetah::ExecutionFailed => e + # puts e.message + # puts "Standard output: #{e.stdout}" + # puts "Error ouptut: #{e.stderr}" + # end + # + # @example more complex example with allowed_exitstatus + # stdout, exitcode = Cheetah.run("cmd", stdout: :capture, allowed_exitstatus: 1..5) + # + def run(*args) options = args.last.is_a?(Hash) ? args.pop : {} options = BUILTIN_DEFAULT_OPTIONS.merge(@default_options).merge(options) + options[:stdin] ||= "" # allow passing nil stdin see issue gh#11 + if !options[:allowed_exitstatus].respond_to?(:include?) + options[:allowed_exitstatus] = Array(options[:allowed_exitstatus]) + end + streamed = compute_streamed(options) streams = build_streams(options, streamed) commands = build_commands(args) @@ -356,39 +396,47 @@ recorder.record_commands(commands) - pid, pipes = fork_commands(commands) + pid, pipes = fork_commands(commands, options) select_loop(streams, pipes, recorder) - pid, status = Process.wait2(pid) + _pid, status = Process.wait2(pid) begin - check_errors(commands, status, streams, streamed) + check_errors(commands, status, streams, streamed, options) ensure recorder.record_status(status) end - build_result(streams, options) + build_result(streams, status, options) end private # Parts of Cheetah.run + def with_env(env, &block) + old_env = ENV.to_hash + ENV.update(env) + block.call + ensure + ENV.replace(old_env) + end + def compute_streamed(options) # The assumption for :stdout and :stderr is that anything except :capture # and nil is an IO-like object. We avoid detecting it directly to allow # passing StringIO, mocks, etc. { - :stdin => !options[:stdin].is_a?(String), - :stdout => ![nil, :capture].include?(options[:stdout]), - :stderr => ![nil, :capture].include?(options[:stderr]) + stdin: !options[:stdin].is_a?(String), + stdout: ![nil, :capture].include?(options[:stdout]), + stderr: ![nil, :capture].include?(options[:stderr]) } end def build_streams(options, streamed) { - :stdin => streamed[:stdin] ? options[:stdin] : StringIO.new(options[:stdin]), - :stdout => streamed[:stdout] ? options[:stdout] : StringIO.new(""), - :stderr => streamed[:stderr] ? options[:stderr] : StringIO.new("") + stdin: streamed[:stdin] ? options[:stdin] : StringIO.new(options[:stdin]), + stdout: streamed[:stdout] ? options[:stdout] : StringIO.new(""), + stderr: streamed[:stderr] ? options[:stderr] : StringIO.new("") } end @@ -410,7 +458,8 @@ # The following code ensures that the result consistently (in all three # cases) contains an array of arrays specifying commands and their # arguments. - args.all? { |a| a.is_a?(Array) } ? args : [args] + commands = args.all? { |a| a.is_a?(Array) } ? args : [args] + commands.map { |c| c.map(&:to_s) } end def build_recorder(options) @@ -421,54 +470,90 @@ end end - def fork_commands_recursive(commands, pipes) + # Reopen *stream* to write **into** the writing half of *pipe* + # and close the reading half of *pipe*. + # @param pipe [Array<IO>] a pair of IOs as returned from IO.pipe + # @param stream [IO] + def into_pipe(stream, pipe) + stream.reopen(pipe[WRITE]) + pipe[WRITE].close + pipe[READ].close + end + + # Reopen *stream* to read **from** the reading half of *pipe* + # and close the writing half of *pipe*. + # @param pipe [Array<IO>] a pair of IOs as returned from IO.pipe + # @param stream [IO] + def from_pipe(stream, pipe) + stream.reopen(pipe[READ]) + pipe[READ].close + pipe[WRITE].close + end + + def chroot_step(options) + return options if [nil, "/"].include?(options[:chroot]) + + options = options.dup + # delete chroot option otherwise in pipe will chroot each fork recursivelly + root = options.delete(:chroot) + Dir.chroot(root) + # curdir can be outside chroot which is considered as security problem + Dir.chdir("/") + + options + end + + def fork_commands_recursive(commands, pipes, options) fork do begin + # support chrooting + options = chroot_step(options) + if commands.size == 1 - pipes[:stdin][WRITE].close - STDIN.reopen(pipes[:stdin][READ]) - pipes[:stdin][READ].close + from_pipe(STDIN, pipes[:stdin]) else pipe_to_child = IO.pipe - fork_commands_recursive(commands[0..-2], { - :stdin => pipes[:stdin], - :stdout => pipe_to_child, - :stderr => pipes[:stderr] - }) + fork_commands_recursive(commands[0..-2], + { + stdin: pipes[:stdin], + stdout: pipe_to_child, + stderr: pipes[:stderr] + }, + options + ) pipes[:stdin][READ].close pipes[:stdin][WRITE].close - pipe_to_child[WRITE].close - STDIN.reopen(pipe_to_child[READ]) - pipe_to_child[READ].close + from_pipe(STDIN, pipe_to_child) end - pipes[:stdout][READ].close - STDOUT.reopen(pipes[:stdout][WRITE]) - pipes[:stdout][WRITE].close - - pipes[:stderr][READ].close - STDERR.reopen(pipes[:stderr][WRITE]) - pipes[:stderr][WRITE].close + into_pipe(STDOUT, pipes[:stdout]) + into_pipe(STDERR, pipes[:stderr]) # All file descriptors from 3 above should be closed here, but since I # don't know about any way how to detect the maximum file descriptor # number portably in Ruby, I didn't implement it. Patches welcome. command, *args = commands.last - exec([command, command], *args) + with_env(options[:env]) do + exec([command, command], *args) + end rescue SystemCallError => e + # depends when failed, if pipe is already redirected or not, so lets find it + output = pipes[:stderr][WRITE].closed? ? STDERR : pipes[:stderr][WRITE] + output.puts e.message + exit!(127) end end end - def fork_commands(commands) - pipes = { :stdin => IO.pipe, :stdout => IO.pipe, :stderr => IO.pipe } + def fork_commands(commands, options) + pipes = { stdin: IO.pipe, stdout: IO.pipe, stderr: IO.pipe } - pid = fork_commands_recursive(commands, pipes) + pid = fork_commands_recursive(commands, pipes, options) [ pipes[:stdin][READ], @@ -508,7 +593,7 @@ break if pipes_readable.empty? && pipes_writable.empty? ios_read, ios_write, ios_error = select(pipes_readable, pipes_writable, - pipes_readable + pipes_writable) + pipes_readable + pipes_writable) if !ios_error.empty? raise IOError, "Error when communicating with executed program." @@ -540,39 +625,52 @@ end end - def check_errors(commands, status, streams, streamed) + def check_errors(commands, status, streams, streamed, options) return if status.success? + return if options[:allowed_exitstatus].include?(status.exitstatus) stderr_part = if streamed[:stderr] - " (error output streamed away)" - elsif streams[:stderr].string.empty? - " (no error output)" - else - lines = streams[:stderr].string.split("\n") - ": " + lines.first + (lines.size > 1 ? " (...)" : "") - end + " (error output streamed away)" + elsif streams[:stderr].string.empty? + " (no error output)" + else + lines = streams[:stderr].string.split("\n") + ": " + lines.first + (lines.size > 1 ? " (...)" : "") + end raise ExecutionFailed.new( commands, status, streamed[:stdout] ? nil : streams[:stdout].string, streamed[:stderr] ? nil : streams[:stderr].string, - "Execution of #{format_commands(commands)} " + + "Execution of #{format_commands(commands)} " \ "failed with status #{status.exitstatus}#{stderr_part}." ) end - def build_result(streams, options) - case [options[:stdout] == :capture, options[:stderr] == :capture] - when [false, false] - nil - when [true, false] - streams[:stdout].string - when [false, true] - streams[:stderr].string - when [true, true] - [streams[:stdout].string, streams[:stderr].string] + def build_result(streams, status, options) + res = case [options[:stdout] == :capture, options[:stderr] == :capture] + when [false, false] + nil + when [true, false] + streams[:stdout].string + when [false, true] + streams[:stderr].string + when [true, true] + [streams[:stdout].string, streams[:stderr].string] + end + + # do not capture only for empty array or nil converted to empty array + if !options[:allowed_exitstatus].is_a?(Array) || !options[:allowed_exitstatus].empty? + if res.nil? + res = status.exitstatus + else + res = Array(res) + res << status.exitstatus + end end + + res end def format_commands(commands) @@ -582,4 +680,3 @@ self.default_options = {} end - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 1970-01-01 01:00:00.000000000 +0100 +++ new/metadata 2015-12-18 15:34:38.000000000 +0100 @@ -1,78 +1,55 @@ --- !ruby/object:Gem::Specification name: cheetah version: !ruby/object:Gem::Version - version: 0.4.0 - prerelease: + version: 0.5.0 platform: ruby authors: - David Majda autorequire: bindir: bin cert_chain: [] -date: 2013-11-21 00:00:00.000000000 Z +date: 2015-12-18 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: abstract_method requirement: !ruby/object:Gem::Requirement - none: false requirements: - - - ~> + - - "~>" - !ruby/object:Gem::Version version: '1.2' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement - none: false requirements: - - - ~> + - - "~>" - !ruby/object:Gem::Version version: '1.2' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement - none: false requirements: - - - ! '>=' + - - "~>" - !ruby/object:Gem::Version - version: '0' + version: '3.3' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement - none: false requirements: - - - ! '>=' + - - "~>" - !ruby/object:Gem::Version - version: '0' -- !ruby/object:Gem::Dependency - name: redcarpet - requirement: !ruby/object:Gem::Requirement - none: false - requirements: - - - ! '>=' - - !ruby/object:Gem::Version - version: '0' - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - none: false - requirements: - - - ! '>=' - - !ruby/object:Gem::Version - version: '0' + version: '3.3' - !ruby/object:Gem::Dependency name: yard requirement: !ruby/object:Gem::Requirement - none: false requirements: - - - ! '>=' + - - "~>" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement - none: false requirements: - - - ! '>=' + - - "~>" - !ruby/object:Gem::Version version: '0' description: Your swiss army knife for executing external commands in Ruby safely @@ -91,27 +68,26 @@ homepage: https://github.com/openSUSE/cheetah licenses: - MIT +metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement - none: false requirements: - - - ! '>=' + - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement - none: false requirements: - - - ! '>=' + - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: -rubygems_version: 1.8.23 +rubygems_version: 2.4.5.1 signing_key: -specification_version: 3 +specification_version: 4 summary: Your swiss army knife for executing external commands in Ruby safely and conveniently. test_files: [] ++++++ gem2rpm.yml ++++++ # --- # ## used by gem2rpm # :summary: this is a custom summary # ## used by gem2rpm # :description: |- # this is a custom description # # it can be multiline # ## used by gem2rpm # :license: MIT or Ruby # ## used by gem2rpm and gem_packages # :version_suffix: -x_y # ## used by gem2rpm and gem_packages # :disable_docs: true # ## used by gem2rpm # :disable_automatic_rdoc_dep: true # ## used by gem2rpm # :preamble: |- # BuildRequires: foobar # Requires: foobar # ## used by gem2rpm # :patches: # foo.patch: -p1 # bar.patch: # ## used by gem2rpm :sources: # - foo.desktop # - bar.desktop # :gem_install_args: '....' # ## used by gem2rpm # :pre_install: |- # %if 0%{?use_system_libev} # export USE_VENDORED_LIBEV="no" # %endif # ## used by gem2rpm # :post_install: |- # # delete custom files here or do other fancy stuff # install -D -m 0644 %{S:1} %{buildroot}%{_bindir}/gem2rpm-opensuse # ## used by gem2rpm # :testsuite_command: |- # (pushd %{buildroot}%{gem_base}/gems/%{mod_full_name} && rake test) # ## used by gem2rpm # :filelist: |- # /usr/bin/gem2rpm-opensuse # ## used by gem2rpm # :scripts: # :post: |- # /bin/echo foo # ## used by gem_packages # :main: # :preamble: |- # Requires: util-linux # Recommends: pwgen # :filelist: |- # /usr/bin/gem2rpm-opensuse # ## used by gem_packages # :custom: # apache: # :preamble: |- # Requires: ..... # :filelist: |- # /etc/apache2/conf.d/passenger.conf # :summary: Custom summary is optional # :description: |- # Custom description is optional # # bar # :post: |- # /bin/echo foo #
