Hello community,

here is the log from the commit of package yast2-registration for 
openSUSE:Factory checked in at 2018-01-28 00:38:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-registration (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-registration.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-registration"

Sun Jan 28 00:38:34 2018 rev:8 rq:569992 version:4.0.19

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-registration/yast2-registration.changes    
2018-01-17 21:44:01.583321567 +0100
+++ 
/work/SRC/openSUSE:Factory/.yast2-registration.new/yast2-registration.changes   
    2018-01-28 00:38:36.083821840 +0100
@@ -1,0 +2,15 @@
+Fri Jan 26 16:05:55 UTC 2018 - [email protected]
+
+- Initial support for the SLE15 offline migration (fate#323163)
+- 4.0.19
+
+-------------------------------------------------------------------
+Wed Jan 17 14:24:58 UTC 2018 - [email protected]
+
+- Try base product registration code first (bsc#1075551).
+  Some add-ons/extensions are not free but can be registered
+  using their base product's registration code. Try it automatically
+  so that the user does not have to enter it again.
+- 4.0.18
+
+-------------------------------------------------------------------

Old:
----
  yast2-registration-4.0.17.tar.bz2

New:
----
  yast2-registration-4.0.19.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-registration.spec ++++++
--- /var/tmp/diff_new_pack.huwZeT/_old  2018-01-28 00:38:36.743791095 +0100
+++ /var/tmp/diff_new_pack.huwZeT/_new  2018-01-28 00:38:36.747790909 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-registration
-Version:        4.0.17
+Version:        4.0.19
 Release:        0
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build

++++++ yast2-registration-4.0.17.tar.bz2 -> yast2-registration-4.0.19.tar.bz2 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/package/yast2-registration.changes 
new/yast2-registration-4.0.19/package/yast2-registration.changes
--- old/yast2-registration-4.0.17/package/yast2-registration.changes    
2018-01-16 17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/package/yast2-registration.changes    
2018-01-26 18:02:02.000000000 +0100
@@ -1,4 +1,19 @@
 -------------------------------------------------------------------
+Fri Jan 26 16:05:55 UTC 2018 - [email protected]
+
+- Initial support for the SLE15 offline migration (fate#323163)
+- 4.0.19
+
+-------------------------------------------------------------------
+Wed Jan 17 14:24:58 UTC 2018 - [email protected]
+
+- Try base product registration code first (bsc#1075551).
+  Some add-ons/extensions are not free but can be registered
+  using their base product's registration code. Try it automatically
+  so that the user does not have to enter it again.
+- 4.0.18
+
+-------------------------------------------------------------------
 Tue Jan 16 12:39:14 UTC 2018 - [email protected]
 
 - Adjust the base product selection so it is not influenced by
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/package/yast2-registration.spec 
new/yast2-registration-4.0.19/package/yast2-registration.spec
--- old/yast2-registration-4.0.17/package/yast2-registration.spec       
2018-01-16 17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/package/yast2-registration.spec       
2018-01-26 18:02:02.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-registration
-Version:        4.0.17
+Version:        4.0.19
 Release:        0
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/src/lib/registration/clients/inst_migration_repos.rb
 
new/yast2-registration-4.0.19/src/lib/registration/clients/inst_migration_repos.rb
--- 
old/yast2-registration-4.0.17/src/lib/registration/clients/inst_migration_repos.rb
  2018-01-16 17:11:08.000000000 +0100
+++ 
new/yast2-registration-4.0.19/src/lib/registration/clients/inst_migration_repos.rb
  2018-01-26 18:02:02.000000000 +0100
@@ -39,10 +39,26 @@
 
       # Pass the target directory to SUSEConnect
       def set_target_path
-        return if Yast::Installation.destdir == "/"
+        destdir = Yast::Installation.destdir || "/"
+        return if destdir == "/"
 
-        log.info("Setting SUSEConnect target directory: 
#{Yast::Installation.destdir}")
-        SUSE::Connect::System.filesystem_root = Yast::Installation.destdir
+        log.info("Setting SUSEConnect target directory: #{destdir}")
+        SUSE::Connect::System.filesystem_root = destdir
+
+        # copy the old config from the upgraded system to inst-sys
+        # to correctly work in the SMT case
+        # FIXME: this should not be needed, it should be possible to read
+        # the config from the /mnt directly...
+        target_path = SUSE::Connect::YaST::DEFAULT_CONFIG_FILE
+        source_path = File.join(destdir, target_path)
+
+        if File.exist?(source_path)
+          log.info("Copying #{source_path} -> #{target_path}")
+          ::FileUtils.cp(source_path, target_path)
+        elsif File.exist?(target_path)
+          log.info("Removing #{target_path}...")
+          ::FileUtils.rm(target_path)
+        end
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/src/lib/registration/connect_helpers.rb 
new/yast2-registration-4.0.19/src/lib/registration/connect_helpers.rb
--- old/yast2-registration-4.0.17/src/lib/registration/connect_helpers.rb       
2018-01-16 17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/src/lib/registration/connect_helpers.rb       
2018-01-26 18:02:02.000000000 +0100
@@ -58,8 +58,15 @@
     # @param message_prefix [String] Prefix before error like affected product 
or addon
     # @param show_update_hint [Boolean] true if an extra hint for registration 
update
     #   should be displayed
+    # @param silent_reg_code_mismatch [Boolean] true if no popup should be 
shown
+    #   if a registration code is provided
+    #   that does not match the registered product.
+    #   It still returns false.
     # @return [Boolean] success
-    def self.catch_registration_errors(message_prefix: "", show_update_hint: 
false, &block)
+    def self.catch_registration_errors(message_prefix: "",
+      show_update_hint: false,
+      silent_reg_code_mismatch: false,
+      &block)
       # import the SSL certificate just once to avoid an infinite loop
       certificate_imported = false
       begin
@@ -96,8 +103,13 @@
           check_smt_api(error_msg)
           report_error(message_prefix + _("Connection to registration server 
failed."), error_msg)
         when 422
-          # Error popup
-          report_error(message_prefix + _("Connection to registration server 
failed."), error_msg)
+          if silent_reg_code_mismatch && e.response.body["error"] =~
+              /does not include the requested product/
+            log.info "Reg code does not work for this product, that's OK"
+          else
+            # Error popup
+            report_error(message_prefix + _("Connection to registration server 
failed."), error_msg)
+          end
         when 400..499
           report_error(message_prefix + _("Registration client error."), 
error_msg)
         when 500..599
@@ -117,39 +129,11 @@
         false
       rescue OpenSSL::SSL::SSLError => e
         log.error "OpenSSL error: #{e}"
-
-        cert = Storage::SSLErrors.instance.ssl_failed_cert
-        error_code = Storage::SSLErrors.instance.ssl_error_code
-        expected_cert_type = 
Storage::Config.instance.reg_server_cert_fingerprint_type
-
-        # in non-AutoYast mode ask the user to import the certificate
-        if !Yast::Mode.autoinst && cert && 
IMPORT_ERROR_CODES.include?(error_code)
-          # retry after successfull import
-          retry if ask_import_ssl_certificate(cert)
-          # in AutoYast mode check whether the certificate fingerprint match
-          # the configured value (if present)
-        elsif Yast::Mode.autoinst && cert && expected_cert_type && 
!expected_cert_type.empty?
-          expected_fingerprint = Fingerprint.new(expected_cert_type,
-            Storage::Config.instance.reg_server_cert_fingerprint)
-
-          if cert.fingerprint(expected_cert_type) == expected_fingerprint
-            # import the certificate and retry (just once)
-            if !certificate_imported
-              import_ssl_certificate(cert)
-              certificate_imported = true
-              retry
-            end
-
-            report_ssl_error(e.message, cert)
-          else
-            # error message
-            Yast::Report.Error(_("Received SSL Certificate does not match " \
-                  "the expected certificate."))
-          end
-        else
-          report_ssl_error(e.message, cert)
+        should_retry = handle_ssl_error(e, certificate_imported)
+        if should_retry
+          certificate_imported = true
+          retry
         end
-
         false
       rescue JSON::ParserError => e
         log.error "JSON parse error"
@@ -186,6 +170,43 @@
       error + "\n\n" + wrap_text(details_msg, max_size)
     end
 
+    # @param error [OpenSSL::SSL::SSLError]
+    # @param certificate_imported [Boolean] have we already imported the 
certificate?
+    # @return [Boolean] should the `rescue` clause `retry`?
+    def self.handle_ssl_error(error, certificate_imported)
+      cert = Storage::SSLErrors.instance.ssl_failed_cert
+      error_code = Storage::SSLErrors.instance.ssl_error_code
+      expected_cert_type = 
Storage::Config.instance.reg_server_cert_fingerprint_type
+
+      # in non-AutoYast mode ask the user to import the certificate
+      if !Yast::Mode.autoinst && cert && 
IMPORT_ERROR_CODES.include?(error_code)
+        # retry after successfull import
+        return true if ask_import_ssl_certificate(cert)
+      # in AutoYast mode check whether the certificate fingerprint match
+      # the configured value (if present)
+      elsif Yast::Mode.autoinst && cert && expected_cert_type && 
!expected_cert_type.empty?
+        expected_fingerprint = Fingerprint.new(expected_cert_type,
+          Storage::Config.instance.reg_server_cert_fingerprint)
+
+        if cert.fingerprint(expected_cert_type) == expected_fingerprint
+          # import the certificate and retry (just once)
+          if !certificate_imported
+            import_ssl_certificate(cert)
+            return true
+          end
+
+          report_ssl_error(error.message, cert)
+        else
+          # error message
+          Yast::Report.Error(_("Received SSL Certificate does not match " \
+                "the expected certificate."))
+        end
+      else
+        report_ssl_error(error.message, cert)
+      end
+      false
+    end
+
     def self.ssl_error_details(cert)
       return "" if cert.nil?
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/src/lib/registration/registration.rb 
new/yast2-registration-4.0.19/src/lib/registration/registration.rb
--- old/yast2-registration-4.0.17/src/lib/registration/registration.rb  
2018-01-16 17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/src/lib/registration/registration.rb  
2018-01-26 18:02:02.000000000 +0100
@@ -167,6 +167,18 @@
       migrations
     end
 
+    def offline_migration_products(installed_products, target_base_product)
+      log.info "Offline migration for: #{target_base_product}."
+      migration_paths = []
+      ConnectHelpers.catch_registration_errors do
+        migration_paths = SUSE::Connect::YaST
+                          .system_offline_migrations(installed_products, 
target_base_product)
+      end
+
+      log.info "Received possible migrations paths: #{migration_paths}"
+      migration_paths
+    end
+
     # Get the list of updates for a base product or self_update_id if defined
     #
     # @return [Array<String>] List of URLs of updates repositories.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/src/lib/registration/registration_ui.rb 
new/yast2-registration-4.0.19/src/lib/registration/registration_ui.rb
--- old/yast2-registration-4.0.17/src/lib/registration/registration_ui.rb       
2018-01-16 17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/src/lib/registration/registration_ui.rb       
2018-01-26 18:02:02.000000000 +0100
@@ -46,7 +46,6 @@
       Yast.import "Mode"
       Yast.import "Popup"
       Yast.import "Wizard"
-      Yast.import "Mode"
     end
 
     # register the system and the base product
@@ -198,6 +197,18 @@
       end
     end
 
+    # According to the official SUSE terminology, "online" refers to a running
+    # system and (offline) to a system that is not running. It's NOT about the
+    # network connectivity
+    def offline_migration_products(products, base_product)
+      Yast::Popup.Feedback(
+        _(CONTACTING_MESSAGE),
+        _("Loading Migration Products...")
+      ) do
+        registration.offline_migration_products(products, base_product)
+      end
+    end
+
     # Register the selected addons, asks for reg. codes if required, 
known_reg_codes
     # @param selected_addons [Array<Addon>] list of addons selected for 
registration,
     #   successfully registered addons are removed from the list
@@ -205,28 +216,29 @@
     #   user entered values
     # @return [Symbol]
     def register_addons(selected_addons, known_reg_codes)
-      # if registering only add-ons which do not need a reg. code (like SDK)
-      # then simply start the registration
-      if selected_addons.all?(&:free)
-        Yast::Wizard.SetContents(
-          # dialog title
-          _("Register Extensions and Modules"),
-          # display only the products which need a registration code
-          Empty(),
-          # help text
-          _("<p>Extensions and Modules are being registered.</p>"),
-          false,
-          false
-        )
-        # when registration fails go back
-        return register_selected_addons(selected_addons, known_reg_codes) ? 
:next : :back
-      else
-        loop do
-          ret = UI::AddonRegCodesDialog.run(selected_addons, known_reg_codes)
-          return ret unless ret == :next
-
-          return :next if register_selected_addons(selected_addons, 
known_reg_codes)
-        end
+      Yast::Wizard.SetContents(
+        # dialog title
+        _("Register Extensions and Modules"),
+        # display only the products which need a registration code
+        Empty(),
+        # help text
+        _("<p>Extensions and Modules are being registered.</p>"),
+        false,
+        false
+      )
+      loop do
+        # If registering only add-ons which do not need a reg. code (like SDK)
+        # then simply start the registration.
+        # Or, try registering the paid add-ons with the base product's key:
+        # eg. use SLES4SAP registration for HA.
+        selected_addons.replace(try_register_addons(selected_addons, 
known_reg_codes))
+        return :next if selected_addons.empty?
+        # cannot be helped by asking for regcodes
+        return :back if selected_addons.all?(&:free)
+
+        # ask user to fill in known_reg_codes
+        ret = UI::AddonRegCodesDialog.run(selected_addons, known_reg_codes)
+        return ret unless ret == :next
       end
     end
 
@@ -321,52 +333,64 @@
       end
     end
 
-    # register all selected addons
-    def register_selected_addons(selected_addons, known_reg_codes)
-      # create duplicate as array is modified in loop for registration order
-      registration_order = selected_addons.clone
-
-      product_succeed = registration_order.map do |product|
-        registered = ConnectHelpers.catch_registration_errors(
-          message_prefix: "#{product.label}\n"
-        ) do
-          register_selected_addon(product, known_reg_codes[product.identifier])
+    # Register those of *selected_addons* that we can without asking
+    # the user for a reg code. The remaining ones are returned.
+    # @param product [Array<Addon>]
+    # @param known_reg_codes [Hash{String => String}] addon id -> reg code
+    # @return [Array<Addon>] the remaining addons
+    def try_register_addons(selected_addons, known_reg_codes)
+      # return those where r_s_a fails
+      selected_addons.reject do |product|
+        reg_code = known_reg_codes[product.identifier]
+        mismatch_ok = false
+        if reg_code
+          log.info "registering add-on using its own regcode"
+        elsif product.free
+          log.info "registering a free add-on"
+        elsif !Yast::Mode.auto
+          log.info "registering add-on using regcode for its base"
+          options = Storage::InstallationOptions.instance
+          reg_code = options.reg_code
+          mismatch_ok = true
         end
-
-        # remove from selected after successful registration
-        if registered
-          selected_addons.reject! { |selected| selected.identifier == 
product.identifier }
-        end
-        registered
+        register_selected_addon(product, reg_code, silent_reg_code_mismatch: 
mismatch_ok)
       end
-
-      !product_succeed.include?(false) # succeed only if noone failed
     end
 
-    def register_selected_addon(product, reg_code)
-      product_service = Yast::Popup.Feedback(
-        _(CONTACTING_MESSAGE),
-        # %s is name of given product
-        _("Registering %s ...") % product.label
+    # @param product [Addon]
+    # @param reg_code [String]
+    # @param silent_reg_code_mismatch [Boolean]
+    # @return [Boolean] success
+    def register_selected_addon(product, reg_code, silent_reg_code_mismatch:)
+      success = ConnectHelpers.catch_registration_errors(
+        message_prefix:           "#{product.label}\n",
+        silent_reg_code_mismatch: silent_reg_code_mismatch
       ) do
-        product_data = {
-          "name"     => product.identifier,
-          "reg_code" => reg_code,
-          "arch"     => product.arch,
-          "version"  => product.version
-        }
+        product_service = Yast::Popup.Feedback(
+          _(CONTACTING_MESSAGE),
+          # %s is name of given product
+          _("Registering %s ...") % product.label
+        ) do
+          product_data = {
+            "name"     => product.identifier,
+            "reg_code" => reg_code,
+            "arch"     => product.arch,
+            "version"  => product.version
+          }
 
-        registration.register_product(product_data)
-      end
+          registration.register_product(product_data)
+        end
 
-      # select repositories to use in installation (e.g. enable/disable 
Updates)
-      select_repositories(product_service) if Yast::Mode.installation || 
Yast::Mode.update
+        # select repositories to use in installation (e.g. enable/disable 
Updates)
+        select_repositories(product_service) if Yast::Mode.installation || 
Yast::Mode.update
 
-      # remember the added service
-      Storage::Cache.instance.addon_services << product_service
+        # remember the added service
+        Storage::Cache.instance.addon_services << product_service
 
-      # mark as registered
-      product.registered
+        # mark as registered
+        product.registered
+      end
+      success
     end
 
     def select_repositories(product_service)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/src/lib/registration/ui/migration_repos_workflow.rb
 
new/yast2-registration-4.0.19/src/lib/registration/ui/migration_repos_workflow.rb
--- 
old/yast2-registration-4.0.17/src/lib/registration/ui/migration_repos_workflow.rb
   2018-01-16 17:11:08.000000000 +0100
+++ 
new/yast2-registration-4.0.19/src/lib/registration/ui/migration_repos_workflow.rb
   2018-01-26 18:02:02.000000000 +0100
@@ -33,6 +33,7 @@
 
       Yast.import "Sequencer"
       Yast.import "Mode"
+      Yast.import "Stage"
       Yast.import "SourceDialogs"
       Yast.import "Linuxrc"
 
@@ -114,6 +115,7 @@
         "load_migration_products"      => {
           abort:  :abort,
           cancel: :abort,
+          empty:  :back,
           next:   "select_migration_products"
         },
         "select_migration_products"    => {
@@ -188,6 +190,11 @@
       def not_installed_products_check
         SwMgmt.init(true)
 
+        # FIXME: do the check also at offline upgrade?
+        # Currently it reads the addons for the new SLES15 which is not
+        # registered yet and fails.
+        return :next if Yast::Stage.initial
+
         Addon.find_all(registration)
 
         UI::NotInstalledProductsDialog.run
@@ -240,10 +247,22 @@
         products.concat(addons)
       end
 
-      # load migration products for the installed products from the 
registration server
+      # load migration products for the installed products from the 
registration server,
+      # loads online or offline migrations depending on the system state
       # @return [Symbol] workflow symbol (:next or :abort)
       def load_migration_products
-        log.info "Loading migration products from server"
+        if Yast::Stage.initial
+          load_migration_products_offline
+        else
+          load_migration_products_online
+        end
+      end
+
+      # load migration products for the installed products from the 
registration server
+      # for the currently running system (online migration)
+      # @return [Symbol] workflow symbol (:next or :abort)
+      def load_migration_products_online
+        log.info "Loading online migration products from the server..."
         self.migrations = registration_ui.migration_products(products)
 
         if migrations.empty?
@@ -255,6 +274,37 @@
         :next
       end
 
+      # load migration products for the installed products from the 
registration server
+      # on a system that is not running (offline migration)
+      # @return [Symbol] workflow symbol (:next or :abort)
+      def load_migration_products_offline
+        base_product = upgraded_base_product
+        if !base_product
+          # TRANSLATORS: Error message
+          Yast::Report.Error(_("Cannot find a base product to upgrade."))
+          return :empty
+        end
+
+        remote_product = OpenStruct.new(
+          arch:         base_product.arch.to_s,
+          identifier:   base_product.name,
+          version:      base_product.version,
+          # FIXME: not supported by Y2Packager::Product yet
+          release_type: nil
+        )
+
+        log.info "Loading offline migration products from the server..."
+        self.migrations = registration_ui.offline_migration_products(products, 
remote_product)
+
+        if migrations.empty?
+          # TRANSLATORS: Error message
+          Yast::Report.Error(_("No migration product found."))
+          return :empty
+        end
+
+        :next
+      end
+
       # run the migration target selection dialog
       # @return [Symbol] workflow symbol (:next or :abort)
       def select_migration_products
@@ -483,6 +533,21 @@
             "using the previous product. The packages from the registration " \
             "repositories can conflict with the new packages.</p>")
       end
+
+      def upgraded_base_product
+        # temporarily run the update mode to let the solver select the product 
for upgrade
+        # (this will correctly handle possible product renames)
+        Yast::Pkg.PkgUpdateAll({})
+        product = Y2Packager::Product.selected_base
+
+        # restore the initial status, the package update will be turned on 
later again
+        Yast::Pkg.PkgReset
+        changed = Yast::Pkg.GetPackages(:removed, true) + 
Yast::Pkg.GetPackages(:selected, true)
+        changed.each { |p| Yast::Pkg.PkgNeutral(p) }
+
+        log.info("Upgraded base product: #{product.inspect}")
+        product
+      end
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/test/connect_helpers_spec.rb 
new/yast2-registration-4.0.19/test/connect_helpers_spec.rb
--- old/yast2-registration-4.0.17/test/connect_helpers_spec.rb  2018-01-16 
17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/test/connect_helpers_spec.rb  2018-01-26 
18:02:02.000000000 +0100
@@ -4,7 +4,7 @@
 require "registration/connect_helpers"
 
 # helper for creating the SCC API error exceptions
-def api_error(code: 400, headers: {}, body: "")
+def api_error(code: 400, headers: {}, body: {})
   SUSE::Connect::ApiError.new(
     OpenStruct.new(
       code:    code,
@@ -123,6 +123,22 @@
       end
     end
 
+    context "'silent_reg_code_mismatch' parameter is set and a mismatch error 
occurs" do
+      before do
+        allow(Registration::UrlHelpers).to receive(:registration_url)
+          .and_return(SUSE::Connect::YaST::DEFAULT_URL)
+      end
+
+      it "does not report an error and returns false" do
+        msg = "Subscription does not include the requested product 'Fountain 
Wristwatch'"
+        exc = api_error(code: 422, body: { "error" => msg })
+
+        expect(Yast::Report).to_not receive(:Error)
+        expect(helpers.catch_registration_errors(silent_reg_code_mismatch: 
true) { raise exc })
+          .to eq(false)
+      end
+    end
+
     context "'show_update_hint' parameter is set to true and error 401 is 
raised" do
       let(:exception) { api_error(code: 401) }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-registration-4.0.17/test/registration_ui_test.rb 
new/yast2-registration-4.0.19/test/registration_ui_test.rb
--- old/yast2-registration-4.0.17/test/registration_ui_test.rb  2018-01-16 
17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/test/registration_ui_test.rb  2018-01-26 
18:02:02.000000000 +0100
@@ -127,21 +127,22 @@
       it "does not ask for reg. code if all addons are free" do
         # user is not asked for any reg. code
         expect(Registration::UI::AddonRegCodesDialog).to_not receive(:run)
-        allow(registration_ui).to receive(:register_selected_addons) { true }
+        allow(registration_ui).to receive(:try_register_addons).and_return([])
 
         # Register Legacy module
         registration_ui.register_addons([addon_legacy], {})
       end
 
       it "returns :next if everything goes fine" do
-        allow(registration_ui).to receive(:register_selected_addons) { true }
+        allow(registration_ui).to receive(:try_register_addons).and_return([])
         expect(registration_ui.register_addons([addon_legacy], {})).to eq :next
       end
 
       it "returns :back if some registration failed" do
         # FIXME: Since the code is not functional, there is currently no 
cleaner
         # way to mock a registration failure
-        allow(registration_ui).to 
receive(:register_selected_addons).and_return false
+        # FIXME: (Some weeks later...) Now there is?
+        allow(registration_ui).to 
receive(:try_register_addons).and_return([addon_legacy])
 
         expect(registration_ui.register_addons([addon_legacy], {})).to eq :back
       end
@@ -152,7 +153,7 @@
 
       it "returns :next if everything goes fine" do
         allow(Registration::UI::AddonRegCodesDialog).to 
receive(:run).and_return(:next)
-        allow(registration_ui).to 
receive(:register_selected_addons).with(any_args) { true }
+        allow(registration_ui).to 
receive(:try_register_addons).with(any_args).and_return([])
 
         selected_addons = [addon_HA_GEO, addon_SDK]
         expect(registration_ui.register_addons(selected_addons, {})).to eq 
:next
@@ -161,8 +162,8 @@
       it "keep asking for a reg. code if some reg. code failed" do
         # Stub user interaction for reg codes
         allow(Registration::UI::AddonRegCodesDialog).to 
receive(:run).and_return(:next, :next)
-        allow(registration_ui).to receive(:register_selected_addons)
-          .with(any_args).and_return(false, true)
+        allow(registration_ui).to receive(:try_register_addons)
+          .with(any_args).and_return([addon_SDK], [])
 
         # Register HA-GEO + SDK addons
         selected_addons = [addon_HA_GEO, addon_SDK]
@@ -173,6 +174,25 @@
 
   end
 
+  describe "#try_register_addons" do
+    context "for a non-free product without a known regcode" do
+      it "uses the base product regcode" do
+        selected_addons = [addon_HA_GEO]
+
+        options = Registration::Storage::InstallationOptions.instance
+        expect(options).to receive(:reg_code).and_return("my_regcode_for_base")
+
+        expect(registration_ui)
+          .to receive(:register_selected_addon)
+          .with(addon_HA_GEO, "my_regcode_for_base", silent_reg_code_mismatch: 
true)
+          .and_return(false)
+
+        expect(registration_ui.send(:try_register_addons, selected_addons, {}))
+          .to eq(selected_addons)
+      end
+    end
+  end
+
   describe "#migration_products" do
     let(:installed_products) { 
load_yaml_fixture("installed_sles12_product.yml") }
     let(:migration_products) { 
load_yaml_fixture("migration_to_sles12_sp1.yml") }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-registration-4.0.17/test/spec_helper.rb 
new/yast2-registration-4.0.19/test/spec_helper.rb
--- old/yast2-registration-4.0.17/test/spec_helper.rb   2018-01-16 
17:11:08.000000000 +0100
+++ new/yast2-registration-4.0.19/test/spec_helper.rb   2018-01-26 
18:02:02.000000000 +0100
@@ -25,10 +25,12 @@
   end
 end
 
-libdir = File.expand_path("../../src/lib", __FILE__)
-$LOAD_PATH.unshift(libdir)
+srcdir = File.expand_path("../../src", __FILE__)
+y2dirs = ENV.fetch("Y2DIR", "").split(":")
+ENV["Y2DIR"] = y2dirs.unshift(srcdir).join(":")
 
-ENV["Y2DIR"] = File.expand_path("../../src", __FILE__)
+libdir = "#{srcdir}/lib"
+$LOAD_PATH.unshift(libdir)
 
 require "suse/connect"
 


Reply via email to