Hello community, here is the log from the commit of package yast2-ruby-bindings for openSUSE:Factory checked in at 2016-06-02 12:49:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2-ruby-bindings (Old) and /work/SRC/openSUSE:Factory/.yast2-ruby-bindings.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "yast2-ruby-bindings" Changes: -------- --- /work/SRC/openSUSE:Factory/yast2-ruby-bindings/yast2-ruby-bindings.changes 2016-01-13 22:43:13.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.yast2-ruby-bindings.new/yast2-ruby-bindings.changes 2016-06-02 12:49:39.000000000 +0200 @@ -1,0 +2,21 @@ +Mon May 30 14:38:02 UTC 2016 - lslezak@suse.cz + +- Improve the debugger support - use the same code also at run + time, allow using `Y2DEBUGGER` also in installed system + (FATE#318421) +- 3.1.48 + +------------------------------------------------------------------- +Mon May 23 12:30:17 UTC 2016 - lslezak@suse.cz + +- Added support for running the Ruby debugger (FATE#318421) +- Allow running the Ruby debugger from the generic crash handler + if the debugger is installed +- 3.1.47 + +------------------------------------------------------------------- +Mon Mar 7 16:12:00 UTC 2016 - jreidinger@suse.com + +- update code according to updated yast ruby style guide + +------------------------------------------------------------------- Old: ---- yast2-ruby-bindings-3.1.46.tar.bz2 New: ---- yast2-ruby-bindings-3.1.48.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-ruby-bindings.spec ++++++ --- /var/tmp/diff_new_pack.JBC3zK/_old 2016-06-02 12:49:40.000000000 +0200 +++ /var/tmp/diff_new_pack.JBC3zK/_new 2016-06-02 12:49:40.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2-ruby-bindings -Version: 3.1.46 +Version: 3.1.48 Release: 0 Url: https://github.com/yast/yast-ruby-bindings BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -47,6 +47,17 @@ BuildRequires: libyui-ncurses >= 2.47.3 # The mentioned test requires screen in order to be executed in headless systems BuildRequires: screen + +# only a soft dependency, the Ruby debugger is optional +Suggests: rubygem(%{rb_default_ruby_abi}:byebug) + +# Unfortunately we cannot move this to macros.yast, +# bcond within macros are ignored by osc/OBS. +%bcond_with yast_run_ci_tests +%if %{with yast_run_ci_tests} +BuildRequires: rubygem(yast-rake-ci) +%endif + Requires: ruby Summary: Ruby bindings for the YaST platform License: GPL-2.0 @@ -80,6 +91,11 @@ make test ARGS=-V cd - +# run extra CI checks (in Jenkins) +%if %{with yast_run_ci_tests} +%yast_ci_check +%endif + %files %defattr (-, root, root) %{_libdir}/YaST2/plugin/libpy2lang_ruby.so ++++++ yast2-ruby-bindings-3.1.46.tar.bz2 -> yast2-ruby-bindings-3.1.48.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/.rubocop.yml new/yast2-ruby-bindings-3.1.48/.rubocop.yml --- old/yast2-ruby-bindings-3.1.46/.rubocop.yml 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/.rubocop.yml 2016-05-31 09:44:05.000000000 +0200 @@ -46,20 +46,6 @@ Style/Documentation: Enabled: false -# Offense count: 1 -Style/DoubleNegation: - Enabled: false - -# Offense count: 3 -# Configuration parameters: MinBodyLength. -Style/GuardClause: - Enabled: false - -# Offense count: 10 -# Configuration parameters: MaxLineLength. -Style/IfUnlessModifier: - Enabled: false - # Yast API: WFM.SetLanguage, SCR.Read # i18n: N_, Nn_ Style/MethodName: @@ -81,3 +67,8 @@ # Offense count: 1 (@__last_exception) Style/TrivialAccessors: Enabled: false + +# the debugger invocation is deliberate here, it's not a forgotten leftover... +Lint/Debugger: + Exclude: + - src/ruby/yast/debugger.rb diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/README.md new/yast2-ruby-bindings-3.1.48/README.md --- old/yast2-ruby-bindings-3.1.46/README.md 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/README.md 2016-05-31 09:44:05.000000000 +0200 @@ -1,7 +1,7 @@ # Yast2-ruby-bindings -Travis: [![Build Status](https://travis-ci.org/yast/yast-ruby-bindings.svg?branch=master)](https://travis-ci.org/yast/yast-ruby-bindings) -Jenkins: [![Jenkins Build](http://img.shields.io/jenkins/s/https/ci.opensuse.org/yast-ruby-bindings-master.svg)](https://ci.opensuse.org/view/Yast/job/yast-ruby-bindings-master/) +[![Travis Build Status](https://travis-ci.org/yast/yast-ruby-bindings.svg?branch=master)](https://travis-ci.org/yast/yast-ruby-bindings) +[![Jenkins Build Status](http://ci.opensuse.org/buildStatus/icon?job=yast-ruby-bindings-master)](http://ci.opensuse.org/view/Yast/job/yast-ruby-bindings-master/) It is part of [YaST](http://yast.github.io) where you can find more information about YaST and its component system. The Ruby bindings cover only the connection to diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/package/yast2-ruby-bindings.changes new/yast2-ruby-bindings-3.1.48/package/yast2-ruby-bindings.changes --- old/yast2-ruby-bindings-3.1.46/package/yast2-ruby-bindings.changes 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/package/yast2-ruby-bindings.changes 2016-05-31 09:44:05.000000000 +0200 @@ -1,4 +1,25 @@ ------------------------------------------------------------------- +Mon May 30 14:38:02 UTC 2016 - lslezak@suse.cz + +- Improve the debugger support - use the same code also at run + time, allow using `Y2DEBUGGER` also in installed system + (FATE#318421) +- 3.1.48 + +------------------------------------------------------------------- +Mon May 23 12:30:17 UTC 2016 - lslezak@suse.cz + +- Added support for running the Ruby debugger (FATE#318421) +- Allow running the Ruby debugger from the generic crash handler + if the debugger is installed +- 3.1.47 + +------------------------------------------------------------------- +Mon Mar 7 16:12:00 UTC 2016 - jreidinger@suse.com + +- update code according to updated yast ruby style guide + +------------------------------------------------------------------- Wed Jan 13 09:36:59 UTC 2016 - jreidinger@suse.com - Move transdb initialization to C part to keep it together with diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/package/yast2-ruby-bindings.spec new/yast2-ruby-bindings-3.1.48/package/yast2-ruby-bindings.spec --- old/yast2-ruby-bindings-3.1.46/package/yast2-ruby-bindings.spec 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/package/yast2-ruby-bindings.spec 2016-05-31 09:44:05.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2-ruby-bindings -Version: 3.1.46 +Version: 3.1.48 Url: https://github.com/yast/yast-ruby-bindings Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -47,6 +47,17 @@ BuildRequires: libyui-ncurses >= 2.47.3 # The mentioned test requires screen in order to be executed in headless systems BuildRequires: screen + +# only a soft dependency, the Ruby debugger is optional +Suggests: rubygem(%{rb_default_ruby_abi}:byebug) + +# Unfortunately we cannot move this to macros.yast, +# bcond within macros are ignored by osc/OBS. +%bcond_with yast_run_ci_tests +%if %{with yast_run_ci_tests} +BuildRequires: rubygem(yast-rake-ci) +%endif + Requires: ruby Summary: Ruby bindings for the YaST platform License: GPL-2.0 @@ -80,6 +91,11 @@ make test ARGS=-V cd - +# run extra CI checks (in Jenkins) +%if %{with yast_run_ci_tests} +%yast_ci_check +%endif + %files %defattr (-, root, root) %{_libdir}/YaST2/plugin/libpy2lang_ruby.so diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/binary/Builtin.cc new/yast2-ruby-bindings-3.1.48/src/binary/Builtin.cc --- old/yast2-ruby-bindings-3.1.46/src/binary/Builtin.cc 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/binary/Builtin.cc 2016-05-31 09:44:05.000000000 +0200 @@ -514,29 +514,10 @@ return list; } - + // documented in builtins.rb static VALUE regexpsub (VALUE o, VALUE i, VALUE p, VALUE m) { - /** - * @builtin regexpsub - * @short Regex Substitution - * @param string INPUT - * @param string PATTERN - * @param string OUTPUT - * @return string - * - * @description - * Searches a string for a POSIX Extended Regular Expression match - * and returns <i>OUTPUT</i> with the matched subexpressions - * substituted or <b>nil</b> if no match was found. - * - * @see regex(7) - * - * @usage regexpsub ("aaabbb", "(.*ab)", "s_\\1_e") -> "s_aaab_e" - * @usage regexpsub ("aaabbb", "(.*ba)", "s_\\1_e") -> nil - */ - if (NIL_P(i) || NIL_P(p)) return Qnil; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/builtins.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/builtins.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/builtins.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/builtins.rb 2016-05-31 09:44:05.000000000 +0200 @@ -146,9 +146,20 @@ end end - # - Removes element from a list - # - Remove key/value pair from a map - # - Remove item from term + # Remove *element* from a **copy** of *object*. + # + # @param object [::Hash,::Array,Yast::Term,nil] a container + # @param element [Object,Integer,nil] + # Any key for Hash; + # Integer for Array and Term (negative means out of bounds!); + # terms are indexed from 1 (**one**) + # @return [Object,nil] + # Always returns a **copy** of *object*. + # The copy is unchanged if either *object* or *element* is + # `nil`, or if an Integer *element* is out of bounds. + # otherwise the key/index *element* is removed from the copy. + # @raise [RuntimeError] if *object* has an unexpected type + # # @deprecated use native ruby method {::Hash#delete}, {::Array#delete_at} # or {Yast::Term#params} (call delete_at on term params) def self.remove(object, element) @@ -366,13 +377,11 @@ return Yast.deep_copy(list) if offset1 < 0 || offset2 >= list.size || (offset1 > offset2) res = [] - if offset1 > 0 - res.concat list[0..offset1 - 1] - end - res.concat list[offset1..offset2].reverse! - if offset2 < list.size - 1 - res.concat list[offset2 + 1..-1] - end + + res.concat(list[0..offset1 - 1]) if offset1 > 0 + res.concat(list[offset1..offset2].reverse!) + res.concat(list[offset2 + 1..-1]) if offset2 < list.size - 1 + Yast.deep_copy(res) end end @@ -571,9 +580,7 @@ # Yast compatible way how to format string with type conversion # see tostring for type conversion def self.sformat(format, *args) - if format.nil? || !format.is_a?(::String) - return nil - end + return nil if format.nil? || !format.is_a?(::String) return format if args.empty? @@ -1033,6 +1040,29 @@ # # In a condition, use `string =~ pattern` which returns integer or nil. + # @method self.regexpsub(input, pattern, output) + # + # @param input [String] a string to search + # @param pattern [String] a regex in the C(!) syntax + # @param output [String] a template for what to return + # @return [String, nil] replacement, or no match + # @see regexpmatch notes about regex syntax + # + # Searches a string for a POSIX Extended Regular Expression match + # and returns *output* with the matched subexpressions + # substituted or `nil` if no match was found. + # + # If *string* or *pattern* is `nil`, or + # if pattern is an invalid regex, `nil` is returned. + # If *output* is `nil` or any other non-String, an Exception is raised. + # + # @example Usage + # Builtins.regexpsub("lose", "(.*)s(.*)", "\\1v\\2") # -> "love" + # @example Usage misunderstood + # Builtins.regexpsub("lose", "s", "v") # -> "v" + # @example No match + # Builtins.regexpsub("team", "I", "profit") # -> nil + ########################################################### # Yast Term Builtins ########################################################### @@ -1120,12 +1150,10 @@ raise "unknown value from comparison #{i1 <=> u2}" end end - unless ss1.empty? - res += ss1.reverse - end - unless ss2.empty? - res += ss2.reverse - end + + res += ss1.reverse unless ss1.empty? + res += ss2.reverse unless ss2.empty? + Yast.deep_copy(res.reverse) end @@ -1177,12 +1205,8 @@ end end - unless ss1.empty? - res += ss1.reverse - end - unless ss2.empty? - res += ss2.reverse - end + res += ss1.reverse unless ss1.empty? + res += ss2.reverse unless ss2.empty? Yast.deep_copy(res.reverse) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/debugger.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/debugger.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/debugger.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/debugger.rb 2016-05-31 09:44:05.000000000 +0200 @@ -0,0 +1,208 @@ + +require "yast" + +module Yast + class Debugger + class << self + include Yast::Logger + include Yast::UIShortcuts + + # Start the Ruby debugger. It handles the current UI mode and displays + # an user request if the debugger front-end needs to be started manually. + # @param [Boolean] remote if set to true the server is accesible from network. + # By default the debugger can connect only from the local machine, not from + # the network. If you need remote debugging then enable it. + # WARNING: There is no authentication, everybody can connect to + # the debugger! Use only in a trusted network as this is actually + # a backdoor to the system! For secure connection use SSH and start + # the debugger locally after connecting via SSH. + # @param [Fixnum] port the port number where the debugger server will + # listen to + # @param [Boolean] start_client autostart the debugger client + # (ignored in remote debugging) + # @example Start the debugger with default settings: + # require "yast/debugger" + # Yast::Debugger.start + # @example When using the debugger temporary you can use just simple: + # require "byebug" + # byebug + def start(remote: false, port: 3344, start_client: true) + return unless load_debugger + + # do not start the server if it is already running + if Byebug.started? + log.warn "The debugger is already running at port #{Byebug.actual_port}" + log.warn "Skipping the server setup" + else + Yast.import "UI" + if UI.TextMode || remote || !start_client + # in textmode or in remote mode ask the user to start + # the debugger client manually + UI.OpenDialog(Label(debugger_message(remote, port))) + popup = true + else + # in GUI open an xterm session with the debugger + start_gui_session(port) + end + + # start the server and wait for connection, add an extra delay + # if we start the front end automatically to get the server ready + # (to avoid "Broken pipe" error) + # FIXME: looks like a race condition inside byebug itself... + start_server(remote, port, delay: !popup) + + UI.CloseDialog if popup + end + + # start the debugger session + byebug + # Now you can inspect the current state in the debugger, + # or use "next" to continue. + # Use "help" command to see the available commands, see more at + # https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md + end + + # start the Ruby debugger if "Y2DEBUGGER" environment + # variable is set to "1", "remote" or "manual" (the test is case + # insensitive, "y2debugger" variable can be also used) + def start_from_env + # do not evaluate the debugger request again for each client started, + # run the debugger evaluation only once + return if @debugger_handled + @debugger_handled = true + + debug = env_value + return if debug != "1" && debug != "remote" && debug != "manual" + + # FIXME: the UI.TextMode call is used here just to force the UI + # initialization, if it is initialized inside the start method the + # ncurses UI segfaults :-( + # interestengly, the Qt UI works correctly... + Yast.import "UI" + log.info "text mode: #{UI.TextMode}" + + log.info "Debugger set to: #{debug}" + start(remote: debug == "remote", start_client: debug != "manual") + end + + # is the Ruby debugger installed and can be loaded? + # @return [Boolean] true if the debugger is present + def installed? + require "byebug" + true + rescue LoadError + false + end + + private + + # read the debugger value from Y2DEBUGGER environment variable, + # do case insensitive match + # @return [String,nil] environment value or nil if not defined + def env_value + # sort the keys to have a deterministic behavior and to prefer Y2DEBUGGER + # over the other variants, then do a case insensitive search + key = ENV.keys.sort.find { |k| k.match(/\AY2DEBUGGER\z/i) } + log.debug "Found debugger key: #{key.inspect}" + key ? ENV[key] : nil + end + + # load the Ruby debugger, report an error on failure + # @return [Boolean] true if the debugger was loaded successfuly, + # false on error + def load_debugger + require "byebug" + require "byebug/core" + true + rescue LoadError + # catch loading error, the debugger is optional (might not be present) + Yast.import "Report" + Report.Error(format("Cannot load the Ruby debugger.\n" \ + "Make sure '%s' Ruby gem is installed.", "byebug")) + false + end + + # starts the debugger server and waits for a client connection + # @param [Boolean] remote if set to true the server is accesible from network + # @param [Fixnum] port the port number used by the server + # @param [Boolean] delay add extra delay after starting the server + def start_server(remote, port, delay: false) + Byebug.wait_connection = true + host = remote ? "0.0.0.0" : "localhost" + log.info "Starting debugger server (#{host}:#{port}), waiting for connection..." + Byebug.start_server(host, port) + # extra delay if needed + sleep(3) if delay + end + + # starts a debugger session in xterm + # @param [Fixnum] port the port number to connect to + def start_gui_session(port) + job = fork do + # wait until the main thread starts the debugger and opens the port + # for listening + loop do + break if port_open?(port) + sleep(1) + end + + # start the debugger client in an xterm session + exec "xterm", "-e", "byebug", "-R", "#{port}" + end + + # detach the process, we do not wait for it so avoid zombies + Process.detach(job) + end + + # compose the popup message describing how to manually connect to + # the running debugger + # @param [Boolean] remote boolean flag indicating whether the debugger + # can be accessed remotely + # @param [Fixnum] port the port number used by the debugger + # @return [String] text + def debugger_message(remote, port) + if remote + # get the local IP addresses + require "socket" + remote_ips = Socket.ip_address_list.select { |a| a.ipv4? && !a.ipv4_loopback? } + cmd = remote_ips.map { |a| debugger_cmd(a.ip_address, port) }.join("\n") + + if remote_ips.size > 1 + prefix = "To connect to the debugger from a remote machine use one of these commands:" + else + prefix = "To connect to the debugger from a remote machine use this command:" + end + else + prefix = "To start the debugger switch to another console and run:" + cmd = debugger_cmd(nil, port) + end + + "#{prefix}\n\n#{cmd}\n\nWaiting for the connection..." + end + + # construct a debugger command displayed to user in a popup + # @param [String,nil] host the machine host name or IP address, nil if + # the debugger can be accessed only locally + # @param [Fixnum] port the port number used by the debugger + # @return [String] byebug command label + def debugger_cmd(host, port) + host_param = host ? "#{host}:" : "" + " byebug -R #{host_param}#{port}" + end + + # is the target port open? + # @param [Fixnum] port the port number + # @return [Boolean] true if the port is open, false otherwise + def port_open?(port) + require "socket" + + begin + TCPSocket.new("localhost", port).close + true + rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH + false + end + end + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/i18n.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/i18n.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/i18n.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/i18n.rb 2016-05-31 09:44:05.000000000 +0200 @@ -113,7 +113,7 @@ FastGettext::Translation.n_(singular, plural, num) end - private + private def available_locales # the first item is used as the fallback diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/logger.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/logger.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/logger.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/logger.rb 2016-05-31 09:44:05.000000000 +0200 @@ -37,11 +37,11 @@ caller[caller_frame] =~ /(.+):(\d+):in `([^']+)'/ y2_logger(level, "Ruby", Regexp.last_match(1), Regexp.last_match(2).to_i, Regexp.last_match(3), res) - if backtrace - y2_logger_helper(level, [2, "------------- Backtrace begin -------------"]) - caller(3).each { |frame| y2_logger_helper(level, [4, frame]) } - y2_logger_helper(level, [2, "------------- Backtrace end ---------------"]) - end + return unless backtrace + + y2_logger_helper(level, [2, "------------- Backtrace begin -------------"]) + caller(3).each { |frame| y2_logger_helper(level, [4, frame]) } + y2_logger_helper(level, [2, "------------- Backtrace end ---------------"]) end # write to log debug message with arguments formated by {Yast::Builtins.sformat} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/ops.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/ops.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/ops.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/ops.rb 2016-05-31 09:44:05.000000000 +0200 @@ -443,9 +443,8 @@ # stupid nil handling fval = @value[i] sval = other[i] - if sval.nil? && !fval.nil? - return 1 - end + + return 1 if sval.nil? && !fval.nil? # we need to use out builtin, but also we need to res = Ops.comparable_object(fval, @localized) <=> sval diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/path.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/path.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/path.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/path.rb 2016-05-31 09:44:05.000000000 +0200 @@ -55,7 +55,7 @@ size <=> other.size end - private + private attr_reader :components COMPLEX_CHAR_REGEX = /[^a-zA-Z0-9_-]/ @@ -110,11 +110,11 @@ end end - unless buffer.empty? - return if invalid_buffer?(buffer) + return if buffer.empty? - @components << modify_buffer(buffer) - end + return if invalid_buffer?(buffer) + + @components << modify_buffer(buffer) end def invalid_buffer?(buffer) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/rspec/scr.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/rspec/scr.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/rspec/scr.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/rspec/scr.rb 2016-05-31 09:44:05.000000000 +0200 @@ -63,12 +63,12 @@ end Yast::WFM.SCRSetDefault(@scr_handle) - if block_given? - begin - yield - ensure - reset_scr_root - end + return unless block_given? + + begin + yield + ensure + reset_scr_root end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/wfm.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/wfm.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/wfm.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/wfm.rb 2016-05-31 09:44:05.000000000 +0200 @@ -1,6 +1,7 @@ require "yast/builtinx" require "yast/builtins" require "yast/ops" +require "yast/debugger" # @private we need it as clients is called in global contenxt GLOBAL_WFM_CONTEXT = proc {} @@ -8,6 +9,8 @@ # Wrapper class for WFM component in Yast # See yast documentation for WFM module WFM + extend Yast::Logger + # Returns list of arguments passed to client or element at given index # # @example Get all args @@ -181,11 +184,26 @@ call_builtin(Regexp.last_match(1), Regexp.last_match(2).to_i, *args) end + def self.ask_to_run_debugger? + Yast.import "Mode" + + !Mode.auto && Debugger.installed? + end + + # @param [Exception] e the caught exception + # @return [String] human readable exception description + def self.internal_error_msg(e) + "Internal error. Please report a bug report with logs.\n" \ + "Details: #{e.message}\n" \ + "Caller: #{e.backtrace.first}" + end + # @private wrapper to run client in ruby def self.run_client(client) Builtins.y2milestone "Call client %1", client code = File.read client begin + Debugger.start_from_env result = eval(code, GLOBAL_WFM_CONTEXT.binding, client) allowed_types = Ops::TYPES_MAP.values.flatten @@ -203,10 +221,26 @@ e.message, e.backtrace ) - Yast.import "Report" - Report.Error "Internal error. Please report a bug report with logs.\n" \ - "Details: #{e.message}\n" \ - "Caller: #{e.backtrace.first}" + + msg = internal_error_msg(e) + + if ask_to_run_debugger? + Yast.import "Popup" + Yast.import "Label" + msg += "\n\nStart the Ruby debugger now and debug the issue?" \ + " (Experts only!)" + + if Popup.YesNoHeadline(Label.ErrorMsg, msg) + Debugger.start + # Now you can restart the client and watch it step-by-step with + # "next"/"step" commands or you can add some breakpoints into + # the code and use "continue". + retry + end + else + Yast.import "Report" + Report.Error(msg) + end rescue Exception => e Builtins.y2internal("Error reporting failed with '%1' and backtrace %2", e.message, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast/yast.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast/yast.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast/yast.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast/yast.rb 2016-05-31 09:44:05.000000000 +0200 @@ -120,9 +120,7 @@ mod = Yast.const_get module_name # if never included, then include - if !target.class.include? mod - target.class.send(:include, mod) - end + target.class.send(:include, mod) unless target.class.include?(mod) encoded_name = path_without_suffix.gsub(/[-.\/]/, "_") initialized_variable = "@" + encoded_name + "initialized" @@ -189,8 +187,7 @@ return Yast::call_yast_function("#{mname}", :#{sname}, $1, $2.to_i, *args) end END - end - if stype == :variable + elsif stype == :variable m.module_eval <<-"END" def self.#{sname} return Yast::call_yast_function("#{mname}", :#{sname}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/src/ruby/yast.rb new/yast2-ruby-bindings-3.1.48/src/ruby/yast.rb --- old/yast2-ruby-bindings-3.1.46/src/ruby/yast.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/src/ruby/yast.rb 2016-05-31 09:44:05.000000000 +0200 @@ -49,7 +49,6 @@ # unshift it in reverse order to keep precedence Yast.y2paths.reverse.each do |p| dir_path = File.join(p, "lib") - if File.exist? dir_path - $LOAD_PATH.unshift dir_path - end + + $LOAD_PATH.unshift dir_path if File.exist? dir_path end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/tests/ruby/builtins_regexps_spec.rb new/yast2-ruby-bindings-3.1.48/tests/ruby/builtins_regexps_spec.rb --- old/yast2-ruby-bindings-3.1.46/tests/ruby/builtins_regexps_spec.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/tests/ruby/builtins_regexps_spec.rb 2016-05-31 09:44:05.000000000 +0200 @@ -35,7 +35,34 @@ end describe ".regexpsub" do - it "works as expected" do + def regexpsub(input, pattern, output) + Yast::Builtins.regexpsub(input, pattern, output) + end + + it "handles nil in INPUT or PATTERN, returning nil" do + expect(regexpsub(nil, "I", "profit")).to eq(nil) + expect(regexpsub(nil, "I", nil)).to eq(nil) + expect(regexpsub("team", nil, "profit")).to eq(nil) + expect(regexpsub("team", nil, nil)).to eq(nil) + end + + it "raises TypeError if OUTPUT is nil" do + expect { regexpsub("team", "I", nil) }.to raise_error(TypeError) + end + + it "returns nil if there's no match" do + expect(regexpsub("team", "I", "profit")).to eq(nil) + end + + it "returns OUTPUT (not INPUT!) if there is a match" do + expect(regexpsub("lose", "s", "v")).to eq("v") + end + + it "substitutes match groups in OUTPUT" do + expect(regexpsub("lose", "(.*)s(.*)", "\\1v\\2")).to eq("love") + end + + it "works on legacy tests" do expect(Yast::Builtins.regexpsub(nil, nil, nil)).to eq(nil) # from Yast documentation @@ -43,11 +70,11 @@ expect(Yast::Builtins.regexpsub("aaabbb", "(.*ba)", "s_\\1_e")).to eq(nil) # from sysconfig remove whitespaces - expect(Yast::Builtins.regexpsub(" lest test\tsrst\t", - "^[ \t]*(([^ \t]*[ \t]*[^ \t]+)*)[ \t]*$", - "\\1")).to eq("lest test\tsrst") - expect(Yast::Builtins.regexpsub("", "^[ \t]*(([^ \t]*[ \t]*[^ \t]+)*)[ \t]*$", "\\1")).to eq("") - expect(Yast::Builtins.regexpsub(" \t ", "^[ \t]*(([^ \t]*[ \t]*[^ \t]+)*)[ \t]*$", "\\1")).to eq("") + pattern = "^[ \t]*(([^ \t]*[ \t]*[^ \t]+)*)[ \t]*$" + expect(Yast::Builtins.regexpsub(" lest test\tsrst\t", pattern, "\\1")) + .to eq("lest test\tsrst") + expect(Yast::Builtins.regexpsub("", pattern, "\\1")).to eq("") + expect(Yast::Builtins.regexpsub(" \t ", pattern, "\\1")).to eq("") # the result must be UTF-8 string expect(Yast::Builtins.regexpsub("aaabbb", "(.*ab)", "s_\\1_e").encoding).to eq(Encoding::UTF_8) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-ruby-bindings-3.1.46/tests/ruby/y2logger_spec.rb new/yast2-ruby-bindings-3.1.48/tests/ruby/y2logger_spec.rb --- old/yast2-ruby-bindings-3.1.46/tests/ruby/y2logger_spec.rb 2016-01-13 11:00:12.000000000 +0100 +++ new/yast2-ruby-bindings-3.1.48/tests/ruby/y2logger_spec.rb 2016-05-31 09:44:05.000000000 +0200 @@ -44,15 +44,16 @@ it "does not crash when logging an invalid UTF-8 string" do # do not process this string otherwise you'll get an exception :-) - invalid_utf8 = "invalid sequence: \xE3\x80" - # just make sure it is really an UTF-8 string - expect(invalid_utf8.encoding).to eq(Encoding::UTF_8) + invalid_utf8 = "invalid sequence: " + 0xE3.chr + 0x80.chr + # just make sure it is really an invalid UTF-8 string + invalid_utf8.force_encoding(Encoding::UTF_8) + expect(invalid_utf8.valid_encoding?).to eq(false) expect { Yast.y2milestone(invalid_utf8) }.not_to raise_error end it "does not crash when logging ASCII string with invalid UTF-8" do # do not process this string otherwise you'll get an exception :-) - invalid_ascii = "invalid sequence: \xE3\x80" + invalid_ascii = "invalid sequence: " + 0xE3.chr + 0x80.chr invalid_ascii.force_encoding(Encoding::ASCII) expect { Yast.y2milestone(invalid_ascii) }.not_to raise_error end