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
 =======
+[![Travis 
Build](https://travis-ci.org/openSUSE/cheetah.svg?branch=master)](https://travis-ci.org/openSUSE/cheetah)
+[![Code 
Climate](https://codeclimate.com/github/openSUSE/cheetah/badges/gpa.svg)](https://codeclimate.com/github/openSUSE/cheetah)
+[![Coverage 
Status](https://img.shields.io/coveralls/openSUSE/cheetah.svg)](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
#

Reply via email to