From 6417fee4a19a09c4f997ab7b96a92d187824a623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Fri, 18 Mar 2016 14:26:31 +0100 Subject: [PATCH 01/12] updated rpmlint config --- package/yast2-rpmlintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/yast2-rpmlintrc b/package/yast2-rpmlintrc index 0d7a1fc0f..0f86a54ef 100644 --- a/package/yast2-rpmlintrc +++ b/package/yast2-rpmlintrc @@ -1 +1 @@ -addFilter("invalid-desktopfile") +addFilter("desktopfile-without-binary") From 2c82b7dd241a2df6cd1bbacca681c01b8f427d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 9 Jun 2015 22:32:54 +0200 Subject: [PATCH 02/12] file conflicts support --- .../packages/src/modules/PackageCallbacks.rb | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/library/packages/src/modules/PackageCallbacks.rb b/library/packages/src/modules/PackageCallbacks.rb index 949a73d35..92f8ed56c 100644 --- a/library/packages/src/modules/PackageCallbacks.rb +++ b/library/packages/src/modules/PackageCallbacks.rb @@ -2487,6 +2487,110 @@ def ProcessDone nil end + # handle the file conflict detection start callback + def FileConflictStart + log.info "Starting file conflict check..." + # TRANSLATORS: progress bar label + label = _("Checking file conflicts...") + + if Mode.commandline + CommandLine.PrintVerbose(label) + elsif UI.WidgetExists(:progressCurrentPackage) + # package slideshow with progress already present + UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) + UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) + else + # TRANSLATORS: help text for the file conflict detection progress + help = _("

Detecting the file conflicts is in progress.

") + Progress.Simple(label, "", 100, help) + end + end + + # Handle the file conflict detection progress callback. + # @param progress [Fixnum] progress in percents + # @return [Boolean] true = continue, false = abort + def FileConflictProgress(progress) + log.debug "File conflict progress: #{progress}%" + + sleep(1) + + if Mode.commandline + CommandLine.PrintVerboseNoCR("#{CLEAR_PROGRESS_TEXT}#{progress}%") + elsif UI.WidgetExists(:progressCurrentPackage) + UI.ChangeWidget(Id(:progressCurrentPackage), :Value, progress) + else + UI.ChangeWidget(Id(:pb), :Value, progress) + end + + ui = UI.PollInput + ui != :abort && ui != :cancel + end + + # Handle the file conflict detection result callback. + # Ask to user whether to continue. In the AutoYaST mode an error is reported + # but the installation will continue ignoring the confliucts. + # @param excluded_packages [Array] packages ignored in the check + # (e.g. not available for check in the download-as-needed mode) + # @param conflicts [Array] list of translated descriptions of + # the detected file conflicts + # @return [Boolean] true = continue, false = abort + def FileConflictReport(excluded_packages, conflicts) + log.info "Excluded #{excluded_packages.size} packages in file conflict check" + log.debug "Excluded packages: #{excluded_packages.inspect}" + log.info "Found #{conflicts.size} conflicts: #{conflicts.join("\n\n")}" + + # just continue installing packages if there is no conflict + return true if conflicts.empty? + + # don't ask in autoyast or command line mode, just report/log the issues and continue + if Mode.autoinst || Mode.autoupgrade || Mode.commandline + # TRANSLATORS: An error message, %s is the actual list of detected conflicts + Report.Error(_("File conflicts detected, the conflicting files will " \ + "be overwritten:\n\n%s") % conflicts.join("\n")) + return true + end + + button_box = ButtonBox( + PushButton(Id(:continue), Opt(:default, :okButton), Label.ContinueButton), + PushButton(Id(:cancel), Opt(:cancelButton), Label.CancelButton) + ) + + # TRANSLATORS: A popup label, use max. 70 chars per line, use more lines if needed + label = _("File conflicts happen when two packages attempt to install\n" \ + "files with the same name but different contents. If you continue,\n" \ + "the conflicting files will be replaced losing the previous content.") + + # TRANSLATORS: Popup heading + heading = n_("A File Conflict Detected", "File Conflicts Detected", conflicts.size) + + dialog = VBox( + Left(Heading(heading)), + VSpacing(0.2), + Left(Label(label)), + MinSize(65, 15, RichText(Opt(:plainText), conflicts.join("\n\n"))), + button_box + ) + + UI.OpenDialog(dialog) + + begin + UI.SetFocus(Id(:continue)) + ret = UI.UserInput + log.info "User Input: #{ret}" + ret == :continue + ensure + UI.CloseDialog + end + end + + # Handle the file conflict detection finish callback. + def FileConflictFinish + log.info "File conflict check finished" + return if Mode.commandline + + Progress.Finish unless UI.WidgetExists(:progressCurrentPackage) + end + # Register callbacks for media change def SetMediaCallbacks Pkg.CallbackMediaChange( @@ -2759,6 +2863,13 @@ def SetProgressReportCallbacks nil end + def SetFileConflictsCallbacks + Pkg.CallbackFileConflictStart(fun_ref(method(:FileConflictStart), "void ()")) + Pkg.CallbackFileConflictProgress(fun_ref(method(:FileConflictProgress), "boolean (integer)")) + Pkg.CallbackFileConflictReport(fun_ref(method(:FileConflictReport), "boolean (list, list)")) + Pkg.CallbackFileConflictFinish(fun_ref(method(:FileConflictFinish), "void ()")) + end + # Register package manager callbacks def InitPackageCallbacks SetProcessCallbacks() @@ -2775,6 +2886,8 @@ def InitPackageCallbacks SetProgressReportCallbacks() + SetFileConflictsCallbacks() + # authentication callback Pkg.CallbackAuthentication( fun_ref( From 55ccbdf1f0ec0bed4d3b71a38471c2857a71e615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Fri, 18 Mar 2016 14:37:08 +0100 Subject: [PATCH 03/12] trailing whitespace removed --- library/packages/src/modules/PackageCallbacks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/packages/src/modules/PackageCallbacks.rb b/library/packages/src/modules/PackageCallbacks.rb index 92f8ed56c..9fa76d42b 100644 --- a/library/packages/src/modules/PackageCallbacks.rb +++ b/library/packages/src/modules/PackageCallbacks.rb @@ -2500,7 +2500,7 @@ def FileConflictStart UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) else - # TRANSLATORS: help text for the file conflict detection progress + # TRANSLATORS: help text for the file conflict detection progress help = _("

Detecting the file conflicts is in progress.

") Progress.Simple(label, "", 100, help) end From 857c960f9cd32b137deadfe78c98d9dd36101103 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 21 Mar 2016 14:43:57 +0100 Subject: [PATCH 04/12] Fixed the callbacks for CLI UI.PollInput without a dialog open will throw a C++ exception and terminate the program --- library/packages/src/modules/PackageCallbacks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/packages/src/modules/PackageCallbacks.rb b/library/packages/src/modules/PackageCallbacks.rb index 9fa76d42b..3ff8ad972 100644 --- a/library/packages/src/modules/PackageCallbacks.rb +++ b/library/packages/src/modules/PackageCallbacks.rb @@ -2522,7 +2522,7 @@ def FileConflictProgress(progress) UI.ChangeWidget(Id(:pb), :Value, progress) end - ui = UI.PollInput + ui = UI.PollInput unless Mode.commandline ui != :abort && ui != :cancel end From c53a8f99d1db16a5141a258efcdf6ba31480c709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 22 Mar 2016 14:55:24 +0100 Subject: [PATCH 05/12] refactoring - move the file conflict callbacks ... to a separate file --- library/packages/src/Makefile.am | 1 + .../src/modules/FileConflictCallbacks.rb | 152 ++++++++++++++++++ .../packages/src/modules/PackageCallbacks.rb | 117 +------------- 3 files changed, 160 insertions(+), 110 deletions(-) create mode 100644 library/packages/src/modules/FileConflictCallbacks.rb diff --git a/library/packages/src/Makefile.am b/library/packages/src/Makefile.am index ff4b9dd63..5fc30da00 100644 --- a/library/packages/src/Makefile.am +++ b/library/packages/src/Makefile.am @@ -1,6 +1,7 @@ # Sources for yast2 module_DATA = \ + modules/FileConflictCallbacks.rb \ modules/PackageCallbacks.rb \ modules/SignatureCheckDialogs.rb \ modules/PackageLock.rb \ diff --git a/library/packages/src/modules/FileConflictCallbacks.rb b/library/packages/src/modules/FileConflictCallbacks.rb new file mode 100644 index 000000000..0529307e8 --- /dev/null +++ b/library/packages/src/modules/FileConflictCallbacks.rb @@ -0,0 +1,152 @@ + +# ------------------------------------------------------------------------------ +# Copyright (c) 2016 SUSE LLC +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of version 2 of the GNU General Public License as published by the +# Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# ------------------------------------------------------------------------------ +# + +require "yast" + +module Yast + # Provides the default Callbacks for Pkg:: + class FileConflictCallbacksClass < Module + include Yast::Logger + + def main + Yast.import "Pkg" + Yast.import "UI" + Yast.import "Progress" + Yast.import "Mode" + Yast.import "CommandLine" + Yast.import "Report" + Yast.import "Wizard" + Yast.import "Label" + + textdomain "base" + end + + # handle the file conflict detection start callback + def FileConflictStart + log.info "Starting the file conflict check..." + # TRANSLATORS: progress bar label + label = _("Checking file conflicts...") + + if Mode.commandline + CommandLine.PrintVerbose(label) + elsif UI.WidgetExists(:progressCurrentPackage) + # package slideshow with progress already present + UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) + UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) + else + # TRANSLATORS: help text for the file conflict detection progress + help = _("

Detecting the file conflicts is in progress.

") + Progress.Simple(label, "", 100, help) + end + end + + # Handle the file conflict detection progress callback. + # @param progress [Fixnum] progress in percents + # @return [Boolean] true = continue, false = abort + def FileConflictProgress(progress) + log.debug "File conflict progress: #{progress}%" + + # FIXME: remove this, just make the progress visible for testing + sleep(1) + + if Mode.commandline + CommandLine.PrintVerboseNoCR("#{CLEAR_PROGRESS_TEXT}#{progress}%") + elsif UI.WidgetExists(:progressCurrentPackage) + UI.ChangeWidget(Id(:progressCurrentPackage), :Value, progress) + else + UI.ChangeWidget(Id(:pb), :Value, progress) + end + + ui = UI.PollInput unless Mode.commandline + ui != :abort && ui != :cancel + end + + # Handle the file conflict detection result callback. + # Ask to user whether to continue. In the AutoYaST mode an error is reported + # but the installation will continue ignoring the confliucts. + # @param excluded_packages [Array] packages ignored in the check + # (e.g. not available for check in the download-as-needed mode) + # @param conflicts [Array] list of translated descriptions of + # the detected file conflicts + # @return [Boolean] true = continue, false = abort + def FileConflictReport(excluded_packages, conflicts) + log.info "Excluded #{excluded_packages.size} packages in file conflict check" + log.debug "Excluded packages: #{excluded_packages.inspect}" + log.info "Found #{conflicts.size} conflicts: #{conflicts.join("\n\n")}" + + # just continue installing packages if there is no conflict + return true if conflicts.empty? + + # don't ask in autoyast or command line mode, just report/log the issues and continue + if Mode.auto || Mode.commandline + # TRANSLATORS: An error message, %s is the actual list of detected conflicts + Report.Error(_("File conflicts detected, these conflicting files will " \ + "be overwritten:\n\n%s") % conflicts.join("\n")) + return true + end + + UI.OpenDialog(dialog(conflicts)) + + begin + UI.SetFocus(Id(:continue)) + ret = UI.UserInput + log.info "User Input: #{ret}" + ret == :continue + ensure + UI.CloseDialog + end + end + + # Handle the file conflict detection finish callback. + def FileConflictFinish + log.info "File conflict check finished" + return if Mode.commandline + + Progress.Finish unless UI.WidgetExists(:progressCurrentPackage) + end + + private + + # Construct the file conflicts dialog. + # @param [Array] conflicts file conflicts reported by libzypp + # (in human readable form) + # @return [Term] UI term + def dialog(conflicts) + button_box = ButtonBox( + PushButton(Id(:continue), Opt(:default, :okButton), Label.ContinueButton), + PushButton(Id(:abort), Opt(:cancelButton), Label.AbortButton) + ) + + # TRANSLATORS: A popup label, use max. 70 chars per line, use more lines if needed + label = _("File conflicts happen when two packages attempt to install\n" \ + "files with the same name but different contents. If you continue,\n" \ + "the conflicting files will be replaced losing the previous content.") + + # TRANSLATORS: Popup heading + heading = n_("A File Conflict Detected", "File Conflicts Detected", conflicts.size) + + VBox( + Left(Heading(heading)), + VSpacing(0.2), + Left(Label(label)), + MinSize(65, 15, RichText(Opt(:plainText), conflicts.join("\n\n"))), + button_box + ) + end + end + + FileConflictCallbacks = FileConflictCallbacksClass.new + FileConflictCallbacks.main +end diff --git a/library/packages/src/modules/PackageCallbacks.rb b/library/packages/src/modules/PackageCallbacks.rb index 3ff8ad972..6ee79e749 100644 --- a/library/packages/src/modules/PackageCallbacks.rb +++ b/library/packages/src/modules/PackageCallbacks.rb @@ -65,6 +65,7 @@ def main Yast.import "Progress" Yast.import "FileUtils" Yast.import "SignatureCheckCallbacks" + Yast.import "FileConflictCallbacks" @_provide_popup = false @_package_popup = false @@ -2487,110 +2488,6 @@ def ProcessDone nil end - # handle the file conflict detection start callback - def FileConflictStart - log.info "Starting file conflict check..." - # TRANSLATORS: progress bar label - label = _("Checking file conflicts...") - - if Mode.commandline - CommandLine.PrintVerbose(label) - elsif UI.WidgetExists(:progressCurrentPackage) - # package slideshow with progress already present - UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) - UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) - else - # TRANSLATORS: help text for the file conflict detection progress - help = _("

Detecting the file conflicts is in progress.

") - Progress.Simple(label, "", 100, help) - end - end - - # Handle the file conflict detection progress callback. - # @param progress [Fixnum] progress in percents - # @return [Boolean] true = continue, false = abort - def FileConflictProgress(progress) - log.debug "File conflict progress: #{progress}%" - - sleep(1) - - if Mode.commandline - CommandLine.PrintVerboseNoCR("#{CLEAR_PROGRESS_TEXT}#{progress}%") - elsif UI.WidgetExists(:progressCurrentPackage) - UI.ChangeWidget(Id(:progressCurrentPackage), :Value, progress) - else - UI.ChangeWidget(Id(:pb), :Value, progress) - end - - ui = UI.PollInput unless Mode.commandline - ui != :abort && ui != :cancel - end - - # Handle the file conflict detection result callback. - # Ask to user whether to continue. In the AutoYaST mode an error is reported - # but the installation will continue ignoring the confliucts. - # @param excluded_packages [Array] packages ignored in the check - # (e.g. not available for check in the download-as-needed mode) - # @param conflicts [Array] list of translated descriptions of - # the detected file conflicts - # @return [Boolean] true = continue, false = abort - def FileConflictReport(excluded_packages, conflicts) - log.info "Excluded #{excluded_packages.size} packages in file conflict check" - log.debug "Excluded packages: #{excluded_packages.inspect}" - log.info "Found #{conflicts.size} conflicts: #{conflicts.join("\n\n")}" - - # just continue installing packages if there is no conflict - return true if conflicts.empty? - - # don't ask in autoyast or command line mode, just report/log the issues and continue - if Mode.autoinst || Mode.autoupgrade || Mode.commandline - # TRANSLATORS: An error message, %s is the actual list of detected conflicts - Report.Error(_("File conflicts detected, the conflicting files will " \ - "be overwritten:\n\n%s") % conflicts.join("\n")) - return true - end - - button_box = ButtonBox( - PushButton(Id(:continue), Opt(:default, :okButton), Label.ContinueButton), - PushButton(Id(:cancel), Opt(:cancelButton), Label.CancelButton) - ) - - # TRANSLATORS: A popup label, use max. 70 chars per line, use more lines if needed - label = _("File conflicts happen when two packages attempt to install\n" \ - "files with the same name but different contents. If you continue,\n" \ - "the conflicting files will be replaced losing the previous content.") - - # TRANSLATORS: Popup heading - heading = n_("A File Conflict Detected", "File Conflicts Detected", conflicts.size) - - dialog = VBox( - Left(Heading(heading)), - VSpacing(0.2), - Left(Label(label)), - MinSize(65, 15, RichText(Opt(:plainText), conflicts.join("\n\n"))), - button_box - ) - - UI.OpenDialog(dialog) - - begin - UI.SetFocus(Id(:continue)) - ret = UI.UserInput - log.info "User Input: #{ret}" - ret == :continue - ensure - UI.CloseDialog - end - end - - # Handle the file conflict detection finish callback. - def FileConflictFinish - log.info "File conflict check finished" - return if Mode.commandline - - Progress.Finish unless UI.WidgetExists(:progressCurrentPackage) - end - # Register callbacks for media change def SetMediaCallbacks Pkg.CallbackMediaChange( @@ -2863,11 +2760,11 @@ def SetProgressReportCallbacks nil end - def SetFileConflictsCallbacks - Pkg.CallbackFileConflictStart(fun_ref(method(:FileConflictStart), "void ()")) - Pkg.CallbackFileConflictProgress(fun_ref(method(:FileConflictProgress), "boolean (integer)")) - Pkg.CallbackFileConflictReport(fun_ref(method(:FileConflictReport), "boolean (list, list)")) - Pkg.CallbackFileConflictFinish(fun_ref(method(:FileConflictFinish), "void ()")) + def SetFileConflictCallbacks + Pkg.CallbackFileConflictStart(fun_ref(FileConflictCallbacks.method(:FileConflictStart), "void ()")) + Pkg.CallbackFileConflictProgress(fun_ref(FileConflictCallbacks.method(:FileConflictProgress), "boolean (integer)")) + Pkg.CallbackFileConflictReport(fun_ref(FileConflictCallbacks.method(:FileConflictReport), "boolean (list, list)")) + Pkg.CallbackFileConflictFinish(fun_ref(FileConflictCallbacks.method(:FileConflictFinish), "void ()")) end # Register package manager callbacks @@ -2886,7 +2783,7 @@ def InitPackageCallbacks SetProgressReportCallbacks() - SetFileConflictsCallbacks() + SetFileConflictCallbacks() # authentication callback Pkg.CallbackAuthentication( From 78f693cbdc13d1621b8e0a57789d661f6b5326c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 22 Mar 2016 16:47:14 +0100 Subject: [PATCH 06/12] added missing constant --- library/packages/src/modules/FileConflictCallbacks.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/packages/src/modules/FileConflictCallbacks.rb b/library/packages/src/modules/FileConflictCallbacks.rb index 0529307e8..a8b922f20 100644 --- a/library/packages/src/modules/FileConflictCallbacks.rb +++ b/library/packages/src/modules/FileConflictCallbacks.rb @@ -16,10 +16,18 @@ require "yast" module Yast - # Provides the default Callbacks for Pkg:: + # Provides the default file conflicts callbacks for Pkg:: + # + # Notes: Libzypp runs the check only in the DownloadInAdvance mode, + # in other modes the check is skipped. That basically means the check is + # skipped during the initial installation (it uses DownloadAsNeeded mode). + # class FileConflictCallbacksClass < Module include Yast::Logger + # text to clean progress bar in command line + CLEAR_PROGRESS_TEXT = "\b" * 10 + " " * 10 + "\b" * 10 + def main Yast.import "Pkg" Yast.import "UI" From 6667b1e4b085e47503cc794611033cc7ef476d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Thu, 24 Mar 2016 19:28:08 +0100 Subject: [PATCH 07/12] move the file conflicts to lib/packages/file_conflict_callbacks.rb added initial unit tests --- library/packages/src/Makefile.am | 2 +- .../lib/packages/file_conflict_callbacks.rb | 169 ++++++++++++ .../src/modules/FileConflictCallbacks.rb | 160 ------------ .../packages/src/modules/PackageCallbacks.rb | 9 +- library/packages/test/Makefile.am | 1 + .../test/file_conflict_callbacks_test.rb | 247 ++++++++++++++++++ 6 files changed, 422 insertions(+), 166 deletions(-) create mode 100644 library/packages/src/lib/packages/file_conflict_callbacks.rb delete mode 100644 library/packages/src/modules/FileConflictCallbacks.rb create mode 100644 library/packages/test/file_conflict_callbacks_test.rb diff --git a/library/packages/src/Makefile.am b/library/packages/src/Makefile.am index 5fc30da00..0216584c1 100644 --- a/library/packages/src/Makefile.am +++ b/library/packages/src/Makefile.am @@ -1,7 +1,6 @@ # Sources for yast2 module_DATA = \ - modules/FileConflictCallbacks.rb \ modules/PackageCallbacks.rb \ modules/SignatureCheckDialogs.rb \ modules/PackageLock.rb \ @@ -24,6 +23,7 @@ ylibdir = "${yast2dir}/lib/packages" ylib_DATA = \ lib/packages/commit_result.rb \ lib/packages/dummy_callbacks.rb \ + lib/packages/file_conflict_callbacks.rb \ lib/packages/update_message.rb \ lib/packages/update_messages_view.rb diff --git a/library/packages/src/lib/packages/file_conflict_callbacks.rb b/library/packages/src/lib/packages/file_conflict_callbacks.rb new file mode 100644 index 000000000..96c2fcdf9 --- /dev/null +++ b/library/packages/src/lib/packages/file_conflict_callbacks.rb @@ -0,0 +1,169 @@ + +# ------------------------------------------------------------------------------ +# Copyright (c) 2016 SUSE LLC +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of version 2 of the GNU General Public License as published by the +# Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# ------------------------------------------------------------------------------ +# + +require "yast" + +module Packages + # Default file conflicts callbacks for package bindings. To register the + # callbacks in Yast::Pkg just call {Package::FileConflictCallbacks.register} + class FileConflictCallbacks + class << self + include Yast::Logger + include Yast::I18n + include Yast::UIShortcuts + + # register the file conflict callbacks + def register + Yast.import "Pkg" + Yast.import "UI" + Yast.import "Progress" + Yast.import "Mode" + Yast.import "CommandLine" + Yast.import "Report" + Yast.import "Label" + Yast.import "PackageCallbacks" + + textdomain "base" + + register_file_conflict_callbacks + end + + private + + def fun_ref(*args) + Yast::FunRef.new(*args) + end + + def register_file_conflict_callbacks + Yast::Pkg.CallbackFileConflictStart(fun_ref(method(:start), "void ()")) + Yast::Pkg.CallbackFileConflictProgress(fun_ref(method(:progress), + "boolean (integer)")) + Yast::Pkg.CallbackFileConflictReport(fun_ref(method(:report), + "boolean (list, list)")) + Yast::Pkg.CallbackFileConflictFinish(fun_ref(method(:finish), "void ()")) + + nil + end + + # handle the file conflict detection start callback + def start + log.info "Starting the file conflict check..." + # TRANSLATORS: progress bar label + label = _("Checking file conflicts...") + + if Yast::Mode.commandline + Yast::CommandLine.PrintVerbose(label) + elsif Yast::UI.WidgetExists(:progressCurrentPackage) + # package slideshow with progress already present + Yast::UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) + Yast::UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) + else + # TRANSLATORS: help text for the file conflict detection progress + help = _("

Detecting the file conflicts is in progress.

") + Yast::Progress.Simple(label, "", 100, help) + end + end + + # Handle the file conflict detection progress callback. + # @param [Fixnum] progress progress in percents + # @return [Boolean] true = continue, false = abort + def progress(progress) + log.debug "File conflict progress: #{progress}%" + + if Yast::Mode.commandline + Yast::CommandLine.PrintVerboseNoCR("#{Yast::PackageCallbacksClass::CLEAR_PROGRESS_TEXT}#{progress}%") + elsif Yast::UI.WidgetExists(:progressCurrentPackage) + Yast::UI.ChangeWidget(Id(:progressCurrentPackage), :Value, progress) + else + Yast::UI.ChangeWidget(Id(:pb), :Value, progress) + end + + ui = Yast::UI.PollInput unless Yast::Mode.commandline + ui != :abort && ui != :cancel + end + + # Handle the file conflict detection result callback. + # Ask to user whether to continue. In the AutoYaST mode an error is reported + # but the installation will continue ignoring the confliucts. + # @param excluded_packages [Array] packages ignored in the check + # (e.g. not available for check in the download-as-needed mode) + # @param conflicts [Array] list of translated descriptions of + # the detected file conflicts + # @return [Boolean] true = continue, false = abort + def report(excluded_packages, conflicts) + log.info "Excluded #{excluded_packages.size} packages in file conflict check" + log.debug "Excluded packages: #{excluded_packages.inspect}" + log.info "Found #{conflicts.size} conflicts: #{conflicts.join("\n\n")}" + + # just continue installing packages if there is no conflict + return true if conflicts.empty? + + # don't ask in autoyast or command line mode, just report/log the issues and continue + if Yast::Mode.auto || Yast::Mode.commandline + # TRANSLATORS: An error message, %s is the actual list of detected conflicts + Yast::Report.Error(_("File conflicts detected, these conflicting files will " \ + "be overwritten:\n\n%s") % conflicts.join("\n")) + return true + end + + Yast::UI.OpenDialog(dialog(conflicts)) + + begin + Yast::UI.SetFocus(Id(:continue)) + ret = Yast::UI.UserInput + log.info "User Input: #{ret}" + ret == :continue + ensure + Yast::UI.CloseDialog + end + end + + # Handle the file conflict detection finish callback. + def finish + log.info "File conflict check finished" + return if Yast::Mode.commandline + + Yast::Progress.Finish unless Yast::UI.WidgetExists(:progressCurrentPackage) + end + + # Construct the file conflicts dialog. + # @param [Array] conflicts file conflicts reported by libzypp + # (in human readable form) + # @return [Term] UI term + def dialog(conflicts) + button_box = ButtonBox( + PushButton(Id(:continue), Opt(:default, :okButton), Yast::Label.ContinueButton), + PushButton(Id(:abort), Opt(:cancelButton), Yast::Label.AbortButton) + ) + + # TRANSLATORS: A popup label, use max. 70 chars per line, use more lines if needed + label = _("File conflicts happen when two packages attempt to install\n" \ + "files with the same name but different contents. If you continue,\n" \ + "the conflicting files will be replaced losing the previous content.") + + # TRANSLATORS: Popup heading + heading = n_("A File Conflict Detected", "File Conflicts Detected", conflicts.size) + + VBox( + Left(Heading(heading)), + VSpacing(0.2), + Left(Label(label)), + MinSize(65, 15, RichText(Opt(:plainText), conflicts.join("\n\n"))), + button_box + ) + end + end + end +end diff --git a/library/packages/src/modules/FileConflictCallbacks.rb b/library/packages/src/modules/FileConflictCallbacks.rb deleted file mode 100644 index a8b922f20..000000000 --- a/library/packages/src/modules/FileConflictCallbacks.rb +++ /dev/null @@ -1,160 +0,0 @@ - -# ------------------------------------------------------------------------------ -# Copyright (c) 2016 SUSE LLC -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of version 2 of the GNU General Public License as published by the -# Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# ------------------------------------------------------------------------------ -# - -require "yast" - -module Yast - # Provides the default file conflicts callbacks for Pkg:: - # - # Notes: Libzypp runs the check only in the DownloadInAdvance mode, - # in other modes the check is skipped. That basically means the check is - # skipped during the initial installation (it uses DownloadAsNeeded mode). - # - class FileConflictCallbacksClass < Module - include Yast::Logger - - # text to clean progress bar in command line - CLEAR_PROGRESS_TEXT = "\b" * 10 + " " * 10 + "\b" * 10 - - def main - Yast.import "Pkg" - Yast.import "UI" - Yast.import "Progress" - Yast.import "Mode" - Yast.import "CommandLine" - Yast.import "Report" - Yast.import "Wizard" - Yast.import "Label" - - textdomain "base" - end - - # handle the file conflict detection start callback - def FileConflictStart - log.info "Starting the file conflict check..." - # TRANSLATORS: progress bar label - label = _("Checking file conflicts...") - - if Mode.commandline - CommandLine.PrintVerbose(label) - elsif UI.WidgetExists(:progressCurrentPackage) - # package slideshow with progress already present - UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) - UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) - else - # TRANSLATORS: help text for the file conflict detection progress - help = _("

Detecting the file conflicts is in progress.

") - Progress.Simple(label, "", 100, help) - end - end - - # Handle the file conflict detection progress callback. - # @param progress [Fixnum] progress in percents - # @return [Boolean] true = continue, false = abort - def FileConflictProgress(progress) - log.debug "File conflict progress: #{progress}%" - - # FIXME: remove this, just make the progress visible for testing - sleep(1) - - if Mode.commandline - CommandLine.PrintVerboseNoCR("#{CLEAR_PROGRESS_TEXT}#{progress}%") - elsif UI.WidgetExists(:progressCurrentPackage) - UI.ChangeWidget(Id(:progressCurrentPackage), :Value, progress) - else - UI.ChangeWidget(Id(:pb), :Value, progress) - end - - ui = UI.PollInput unless Mode.commandline - ui != :abort && ui != :cancel - end - - # Handle the file conflict detection result callback. - # Ask to user whether to continue. In the AutoYaST mode an error is reported - # but the installation will continue ignoring the confliucts. - # @param excluded_packages [Array] packages ignored in the check - # (e.g. not available for check in the download-as-needed mode) - # @param conflicts [Array] list of translated descriptions of - # the detected file conflicts - # @return [Boolean] true = continue, false = abort - def FileConflictReport(excluded_packages, conflicts) - log.info "Excluded #{excluded_packages.size} packages in file conflict check" - log.debug "Excluded packages: #{excluded_packages.inspect}" - log.info "Found #{conflicts.size} conflicts: #{conflicts.join("\n\n")}" - - # just continue installing packages if there is no conflict - return true if conflicts.empty? - - # don't ask in autoyast or command line mode, just report/log the issues and continue - if Mode.auto || Mode.commandline - # TRANSLATORS: An error message, %s is the actual list of detected conflicts - Report.Error(_("File conflicts detected, these conflicting files will " \ - "be overwritten:\n\n%s") % conflicts.join("\n")) - return true - end - - UI.OpenDialog(dialog(conflicts)) - - begin - UI.SetFocus(Id(:continue)) - ret = UI.UserInput - log.info "User Input: #{ret}" - ret == :continue - ensure - UI.CloseDialog - end - end - - # Handle the file conflict detection finish callback. - def FileConflictFinish - log.info "File conflict check finished" - return if Mode.commandline - - Progress.Finish unless UI.WidgetExists(:progressCurrentPackage) - end - - private - - # Construct the file conflicts dialog. - # @param [Array] conflicts file conflicts reported by libzypp - # (in human readable form) - # @return [Term] UI term - def dialog(conflicts) - button_box = ButtonBox( - PushButton(Id(:continue), Opt(:default, :okButton), Label.ContinueButton), - PushButton(Id(:abort), Opt(:cancelButton), Label.AbortButton) - ) - - # TRANSLATORS: A popup label, use max. 70 chars per line, use more lines if needed - label = _("File conflicts happen when two packages attempt to install\n" \ - "files with the same name but different contents. If you continue,\n" \ - "the conflicting files will be replaced losing the previous content.") - - # TRANSLATORS: Popup heading - heading = n_("A File Conflict Detected", "File Conflicts Detected", conflicts.size) - - VBox( - Left(Heading(heading)), - VSpacing(0.2), - Left(Label(label)), - MinSize(65, 15, RichText(Opt(:plainText), conflicts.join("\n\n"))), - button_box - ) - end - end - - FileConflictCallbacks = FileConflictCallbacksClass.new - FileConflictCallbacks.main -end diff --git a/library/packages/src/modules/PackageCallbacks.rb b/library/packages/src/modules/PackageCallbacks.rb index 6ee79e749..f4c02b3cb 100644 --- a/library/packages/src/modules/PackageCallbacks.rb +++ b/library/packages/src/modules/PackageCallbacks.rb @@ -25,6 +25,7 @@ require "yast" require "uri" require "packages/dummy_callbacks" +require "packages/file_conflict_callbacks" module Yast # Provides the default Callbacks for Pkg:: @@ -65,7 +66,6 @@ def main Yast.import "Progress" Yast.import "FileUtils" Yast.import "SignatureCheckCallbacks" - Yast.import "FileConflictCallbacks" @_provide_popup = false @_package_popup = false @@ -2761,14 +2761,13 @@ def SetProgressReportCallbacks end def SetFileConflictCallbacks - Pkg.CallbackFileConflictStart(fun_ref(FileConflictCallbacks.method(:FileConflictStart), "void ()")) - Pkg.CallbackFileConflictProgress(fun_ref(FileConflictCallbacks.method(:FileConflictProgress), "boolean (integer)")) - Pkg.CallbackFileConflictReport(fun_ref(FileConflictCallbacks.method(:FileConflictReport), "boolean (list, list)")) - Pkg.CallbackFileConflictFinish(fun_ref(FileConflictCallbacks.method(:FileConflictFinish), "void ()")) + log.warn "Registering file conflict callbacks" + ::Packages::FileConflictCallbacks.register end # Register package manager callbacks def InitPackageCallbacks + log.warn "*** INIT Registering callbacks" SetProcessCallbacks() SetProvideCallbacks() diff --git a/library/packages/test/Makefile.am b/library/packages/test/Makefile.am index d02cc2d3e..2a83ec62b 100644 --- a/library/packages/test/Makefile.am +++ b/library/packages/test/Makefile.am @@ -1,6 +1,7 @@ TESTS = \ commit_result_test.rb \ dummy_callbacks_test.rb \ + file_conflict_callbacks_test.rb \ package_callbacks_test.rb \ packages_ui_test.rb \ product_test.rb \ diff --git a/library/packages/test/file_conflict_callbacks_test.rb b/library/packages/test/file_conflict_callbacks_test.rb new file mode 100644 index 000000000..45f3c3bb3 --- /dev/null +++ b/library/packages/test/file_conflict_callbacks_test.rb @@ -0,0 +1,247 @@ +#! /usr/bin/env rspec + +require_relative "test_helper" + +require "packages/file_conflict_callbacks" + +# a helper class to replace Yast::Pkg +class DummyPkg + # remember the registered file conflict callback handlers to test them later + attr_reader :fc_start, :fc_progress, :fc_report, :fc_finish + + def CallbackFileConflictStart(func) + @fc_start = func + end + + def CallbackFileConflictProgress(func) + @fc_progress = func + end + + def CallbackFileConflictReport(func) + @fc_report = func + end + + def CallbackFileConflictFinish(func) + @fc_finish = func + end +end + +describe Packages::FileConflictCallbacks do + let(:dummy_pkg) { DummyPkg.new } + + before do + stub_const("Yast::Pkg", dummy_pkg) + + # do not print anything + Yast.import "CommandLine" + allow(Yast::CommandLine).to receive(:Print) + allow(Yast::CommandLine).to receive(:PrintVerbose) + allow(Yast::CommandLine).to receive(:PrintVerboseNoCR) + end + + describe ".register" do + it "calls the Pkg methods for registering the file conflicts handlers" do + expect(dummy_pkg).to receive(:CallbackFileConflictStart) + expect(dummy_pkg).to receive(:CallbackFileConflictProgress) + expect(dummy_pkg).to receive(:CallbackFileConflictReport) + expect(dummy_pkg).to receive(:CallbackFileConflictFinish) + + Packages::FileConflictCallbacks.register + end + end + + describe "the registered start callback handler" do + let(:start_cb) do + Packages::FileConflictCallbacks.register + dummy_pkg.fc_start + end + + context "in the command line mode" do + before do + allow(Yast::Mode).to receive(:commandline).and_return(true) + end + + it "does not call any UI method" do + ui = double("no method call expected") + stub_const("Yast::UI", ui) + + start_cb.call + end + end + + context "in UI mode" do + # TODO + it "should initialize the progress" + it "should open a new progress" + end + end + + describe "the registered progress callback handler" do + let(:progress_cb) do + Packages::FileConflictCallbacks.register + dummy_pkg.fc_progress + end + + # fake progress value (percent) + let(:progress) { 42 } + + context "in the command line mode" do + before do + allow(Yast::Mode).to receive(:commandline).and_return(true) + end + + it "does not call any UI method" do + ui = double("no method call expected") + stub_const("Yast::UI", ui) + + progress_cb.call(progress) + end + + it "prints the current progress" do + expect(Yast::CommandLine).to receive(:PrintVerboseNoCR).with(/42%/) + + progress_cb.call(progress) + end + + it "returns true to continue" do + expect(progress_cb.call(progress)).to eq(true) + end + end + + context "in UI mode" do + it "returns false to abort if user clicks Abort" do + expect(Yast::UI).to receive(:PollInput).and_return(:abort) + + expect(progress_cb.call(progress)).to eq(false) + end + + it "returns true to continue when no user input" do + expect(Yast::UI).to receive(:PollInput).and_return(nil) + + expect(progress_cb.call(progress)).to eq(true) + end + + it "returns true to continue on unknown user input" do + expect(Yast::UI).to receive(:PollInput).and_return(:next) + + expect(progress_cb.call(progress)).to eq(true) + end + end + end + + describe "the registered report callback handler" do + let(:report_cb) do + Packages::FileConflictCallbacks.register + dummy_pkg.fc_report + end + + context "no conflict found" do + let(:conflicts) { [] } + let(:excluded) { [] } + + before do + allow(Yast::Mode).to receive(:commandline).and_return(true) + end + + it "does not check the command line mode, it behaves same as in the UI mode" do + expect(Yast::Mode).to_not receive(:commandline) + report_cb.call(excluded, conflicts) + end + + it "does not call any UI method" do + ui = double("no method call expected") + stub_const("Yast::UI", ui) + + report_cb.call(excluded, conflicts) + end + + it "returns true to continue" do + expect(report_cb.call(excluded, conflicts)).to eq(true) + end + end + + context "conflicts found" do + let(:conflicts) { [ "conflict1!", "conflict2!" ] } + let(:excluded) { [] } + + context "in the command line mode" do + before do + allow(Yast::Mode).to receive(:commandline).and_return(true) + end + + it "does not call any UI method" do + ui = double("no method call expected") + stub_const("Yast::UI", ui) + + report_cb.call(excluded, conflicts) + end + + it "prints the found conflicts" do + expect(Yast::Report).to receive(:Error) + + report_cb.call(excluded, conflicts) + end + + it "returns true to continue" do + expect(report_cb.call(excluded, conflicts)).to eq(true) + end + end + + context "in AutoYaST mode" do + # TODO + end + + context "in UI mode" do + before do + allow(Yast::UI).to receive(:OpenDialog) + allow(Yast::UI).to receive(:CloseDialog) + allow(Yast::UI).to receive(:SetFocus) + end + + it "opens a Popup dialog, waits for user input and closes the dialog" do + expect(Yast::UI).to receive(:OpenDialog).ordered + expect(Yast::UI).to receive(:UserInput).ordered + expect(Yast::UI).to receive(:CloseDialog).ordered + + report_cb.call(excluded, conflicts) + end + + it "returns false to abort if user clicks Abort" do + expect(Yast::UI).to receive(:UserInput).and_return(:abort) + + expect(report_cb.call(excluded, conflicts)).to eq(false) + end + + it "returns true to continue if user clicks Continue" do + expect(Yast::UI).to receive(:UserInput).and_return(:continue) + + expect(report_cb.call(excluded, conflicts)).to eq(true) + end + end + end + end + + describe "the registered finish callback handler" do + let(:finish_cb) do + Packages::FileConflictCallbacks.register + dummy_pkg.fc_finish + end + + context "in the command line mode" do + before do + allow(Yast::Mode).to receive(:commandline).and_return(true) + end + + it "does not call any UI method" do + ui = double("no method call expected") + stub_const("Yast::UI", ui) + + finish_cb.call + end + end + + context "in UI mode" do + # TODO + end + end +end From f34d972d6f5688c37e5685c70b4d87c26e36188c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 29 Mar 2016 09:49:12 +0200 Subject: [PATCH 08/12] set also the progress label --- library/packages/src/lib/packages/file_conflict_callbacks.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/packages/src/lib/packages/file_conflict_callbacks.rb b/library/packages/src/lib/packages/file_conflict_callbacks.rb index 96c2fcdf9..d69616ce7 100644 --- a/library/packages/src/lib/packages/file_conflict_callbacks.rb +++ b/library/packages/src/lib/packages/file_conflict_callbacks.rb @@ -73,6 +73,8 @@ def start # TRANSLATORS: help text for the file conflict detection progress help = _("

Detecting the file conflicts is in progress.

") Yast::Progress.Simple(label, "", 100, help) + # Set also the progress bar widget label + Yast::Progress.Title(label) end end From 75f2856ee8087cfa443cf9badeabb5ac6ac930eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 29 Mar 2016 12:30:41 +0200 Subject: [PATCH 09/12] more tests small refactoring Rubocop cleanup --- .../lib/packages/file_conflict_callbacks.rb | 28 ++++-- .../test/file_conflict_callbacks_test.rb | 87 +++++++++++++++---- 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/library/packages/src/lib/packages/file_conflict_callbacks.rb b/library/packages/src/lib/packages/file_conflict_callbacks.rb index d69616ce7..dbd757f5f 100644 --- a/library/packages/src/lib/packages/file_conflict_callbacks.rb +++ b/library/packages/src/lib/packages/file_conflict_callbacks.rb @@ -19,6 +19,8 @@ module Packages # Default file conflicts callbacks for package bindings. To register the # callbacks in Yast::Pkg just call {Package::FileConflictCallbacks.register} class FileConflictCallbacks + PKG_INSTALL_WIDGET = :progressCurrentPackage + class << self include Yast::Logger include Yast::I18n @@ -42,6 +44,7 @@ def register private + # Helper function for creating an YaST function reference def fun_ref(*args) Yast::FunRef.new(*args) end @@ -56,7 +59,13 @@ def register_file_conflict_callbacks nil end - + + # Is package installation progress displayed? + # @return [Boolean] true if package installation progress is displayed + def pkg_installation? + Yast::UI.WidgetExists(PKG_INSTALL_WIDGET) + end + # handle the file conflict detection start callback def start log.info "Starting the file conflict check..." @@ -65,10 +74,10 @@ def start if Yast::Mode.commandline Yast::CommandLine.PrintVerbose(label) - elsif Yast::UI.WidgetExists(:progressCurrentPackage) + elsif pkg_installation? # package slideshow with progress already present - Yast::UI.ChangeWidget(Id(:progressCurrentPackage), :Value, 0) - Yast::UI.ChangeWidget(Id(:progressCurrentPackage), :Label, label) + Yast::UI.ChangeWidget(Id(PKG_INSTALL_WIDGET), :Value, 0) + Yast::UI.ChangeWidget(Id(PKG_INSTALL_WIDGET), :Label, label) else # TRANSLATORS: help text for the file conflict detection progress help = _("

Detecting the file conflicts is in progress.

") @@ -86,13 +95,15 @@ def progress(progress) if Yast::Mode.commandline Yast::CommandLine.PrintVerboseNoCR("#{Yast::PackageCallbacksClass::CLEAR_PROGRESS_TEXT}#{progress}%") - elsif Yast::UI.WidgetExists(:progressCurrentPackage) - Yast::UI.ChangeWidget(Id(:progressCurrentPackage), :Value, progress) + elsif pkg_installation? + Yast::UI.ChangeWidget(Id(PKG_INSTALL_WIDGET), :Value, progress) else - Yast::UI.ChangeWidget(Id(:pb), :Value, progress) + Yast::Progress.Step(progress) end ui = Yast::UI.PollInput unless Yast::Mode.commandline + log.info "User input in file conflict progress (#{progress}%): #{ui}" if ui + ui != :abort && ui != :cancel end @@ -137,7 +148,8 @@ def finish log.info "File conflict check finished" return if Yast::Mode.commandline - Yast::Progress.Finish unless Yast::UI.WidgetExists(:progressCurrentPackage) + # finish the opened progress dialog + Yast::Progress.Finish unless pkg_installation? end # Construct the file conflicts dialog. diff --git a/library/packages/test/file_conflict_callbacks_test.rb b/library/packages/test/file_conflict_callbacks_test.rb index 45f3c3bb3..c85399a54 100644 --- a/library/packages/test/file_conflict_callbacks_test.rb +++ b/library/packages/test/file_conflict_callbacks_test.rb @@ -32,7 +32,7 @@ def CallbackFileConflictFinish(func) before do stub_const("Yast::Pkg", dummy_pkg) - # do not print anything + # stub console printing Yast.import "CommandLine" allow(Yast::CommandLine).to receive(:Print) allow(Yast::CommandLine).to receive(:PrintVerbose) @@ -70,9 +70,20 @@ def CallbackFileConflictFinish(func) end context "in UI mode" do - # TODO - it "should initialize the progress" - it "should open a new progress" + it "reuses the package installation progress" do + expect(Yast::UI).to receive(:WidgetExists).and_return(true) + expect(Yast::UI).to receive(:ChangeWidget).twice + + start_cb.call + end + + it "opens a new progress if installation progress was not displayed" do + expect(Yast::UI).to receive(:WidgetExists).and_return(false) + expect(Yast::Progress).to receive(:Simple) + allow(Yast::Progress).to receive(:Title) + + start_cb.call + end end end @@ -111,30 +122,44 @@ def CallbackFileConflictFinish(func) context "in UI mode" do it "returns false to abort if user clicks Abort" do expect(Yast::UI).to receive(:PollInput).and_return(:abort) - + expect(progress_cb.call(progress)).to eq(false) end it "returns true to continue when no user input" do expect(Yast::UI).to receive(:PollInput).and_return(nil) - + expect(progress_cb.call(progress)).to eq(true) end it "returns true to continue on unknown user input" do expect(Yast::UI).to receive(:PollInput).and_return(:next) - + expect(progress_cb.call(progress)).to eq(true) end + + it "uses the existing widget if package installation progress was displayed" do + expect(Yast::UI).to receive(:WidgetExists).and_return(true) + expect(Yast::UI).to receive(:ChangeWidget) + + progress_cb.call(progress) + end + + it "sets the progress if package installation progress was not displayed" do + expect(Yast::UI).to receive(:WidgetExists).and_return(false) + expect(Yast::Progress).to receive(:Step).with(progress) + + progress_cb.call(progress) + end end end - + describe "the registered report callback handler" do let(:report_cb) do Packages::FileConflictCallbacks.register dummy_pkg.fc_report end - + context "no conflict found" do let(:conflicts) { [] } let(:excluded) { [] } @@ -142,7 +167,7 @@ def CallbackFileConflictFinish(func) before do allow(Yast::Mode).to receive(:commandline).and_return(true) end - + it "does not check the command line mode, it behaves same as in the UI mode" do expect(Yast::Mode).to_not receive(:commandline) report_cb.call(excluded, conflicts) @@ -161,7 +186,7 @@ def CallbackFileConflictFinish(func) end context "conflicts found" do - let(:conflicts) { [ "conflict1!", "conflict2!" ] } + let(:conflicts) { ["conflict1!", "conflict2!"] } let(:excluded) { [] } context "in the command line mode" do @@ -186,9 +211,22 @@ def CallbackFileConflictFinish(func) expect(report_cb.call(excluded, conflicts)).to eq(true) end end - + context "in AutoYaST mode" do - # TODO + before do + expect(Yast::Mode).to receive(:auto).and_return(true) + allow(Yast::Report).to receive(:Error) + end + + it "reporrts the found conflicts" do + expect(Yast::Report).to receive(:Error) + + report_cb.call(excluded, conflicts) + end + + it "returns true to continue" do + expect(report_cb.call(excluded, conflicts)).to eq(true) + end end context "in UI mode" do @@ -197,7 +235,7 @@ def CallbackFileConflictFinish(func) allow(Yast::UI).to receive(:CloseDialog) allow(Yast::UI).to receive(:SetFocus) end - + it "opens a Popup dialog, waits for user input and closes the dialog" do expect(Yast::UI).to receive(:OpenDialog).ordered expect(Yast::UI).to receive(:UserInput).ordered @@ -208,13 +246,13 @@ def CallbackFileConflictFinish(func) it "returns false to abort if user clicks Abort" do expect(Yast::UI).to receive(:UserInput).and_return(:abort) - + expect(report_cb.call(excluded, conflicts)).to eq(false) end it "returns true to continue if user clicks Continue" do expect(Yast::UI).to receive(:UserInput).and_return(:continue) - + expect(report_cb.call(excluded, conflicts)).to eq(true) end end @@ -239,9 +277,22 @@ def CallbackFileConflictFinish(func) finish_cb.call end end - + context "in UI mode" do - # TODO + it "no change if installation progress was already displayed" do + ui = double("no method call expected", WidgetExists: true) + stub_const("Yast::UI", ui) + + finish_cb.call + end + + it "closes progress if installation progress was not displayed" do + expect(Yast::UI).to receive(:WidgetExists).and_return(false) + expect(Yast::Progress).to receive(:Finish) + + finish_cb.call + end + end end end From 135dbe63fbfcfe146cee61e371cdb3fbb3bf6494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 29 Mar 2016 12:37:21 +0200 Subject: [PATCH 10/12] adjustet test permissions --- library/packages/test/file_conflict_callbacks_test.rb | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 library/packages/test/file_conflict_callbacks_test.rb diff --git a/library/packages/test/file_conflict_callbacks_test.rb b/library/packages/test/file_conflict_callbacks_test.rb old mode 100644 new mode 100755 index c85399a54..e1a7e2d30 --- a/library/packages/test/file_conflict_callbacks_test.rb +++ b/library/packages/test/file_conflict_callbacks_test.rb @@ -30,6 +30,7 @@ def CallbackFileConflictFinish(func) let(:dummy_pkg) { DummyPkg.new } before do + # catch all callbacks registration calls via this Pkg replacement stub_const("Yast::Pkg", dummy_pkg) # stub console printing From 74013a33382e9b7d0c3a8548ab4fa3c67100df30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 29 Mar 2016 13:00:24 +0200 Subject: [PATCH 11/12] code cleanup --- .../src/lib/packages/file_conflict_callbacks.rb | 12 +++++++----- library/packages/src/modules/PackageCallbacks.rb | 2 -- .../packages/test/file_conflict_callbacks_test.rb | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/library/packages/src/lib/packages/file_conflict_callbacks.rb b/library/packages/src/lib/packages/file_conflict_callbacks.rb index dbd757f5f..b1943819b 100644 --- a/library/packages/src/lib/packages/file_conflict_callbacks.rb +++ b/library/packages/src/lib/packages/file_conflict_callbacks.rb @@ -49,7 +49,10 @@ def fun_ref(*args) Yast::FunRef.new(*args) end + # Register the default file conflicts callbacks def register_file_conflict_callbacks + log.info "Registering file conflict callbacks" + Yast::Pkg.CallbackFileConflictStart(fun_ref(method(:start), "void ()")) Yast::Pkg.CallbackFileConflictProgress(fun_ref(method(:progress), "boolean (integer)")) @@ -60,13 +63,13 @@ def register_file_conflict_callbacks nil end - # Is package installation progress displayed? + # Is the package installation progress displayed? # @return [Boolean] true if package installation progress is displayed def pkg_installation? Yast::UI.WidgetExists(PKG_INSTALL_WIDGET) end - # handle the file conflict detection start callback + # Handle the file conflict detection start callback. def start log.info "Starting the file conflict check..." # TRANSLATORS: progress bar label @@ -81,9 +84,8 @@ def start else # TRANSLATORS: help text for the file conflict detection progress help = _("

Detecting the file conflicts is in progress.

") - Yast::Progress.Simple(label, "", 100, help) - # Set also the progress bar widget label - Yast::Progress.Title(label) + # Use the same label for the window title and the progressbar label + Yast::Progress.Simple(label, label, 100, help) end end diff --git a/library/packages/src/modules/PackageCallbacks.rb b/library/packages/src/modules/PackageCallbacks.rb index f4c02b3cb..25b3fbed3 100644 --- a/library/packages/src/modules/PackageCallbacks.rb +++ b/library/packages/src/modules/PackageCallbacks.rb @@ -2761,13 +2761,11 @@ def SetProgressReportCallbacks end def SetFileConflictCallbacks - log.warn "Registering file conflict callbacks" ::Packages::FileConflictCallbacks.register end # Register package manager callbacks def InitPackageCallbacks - log.warn "*** INIT Registering callbacks" SetProcessCallbacks() SetProvideCallbacks() diff --git a/library/packages/test/file_conflict_callbacks_test.rb b/library/packages/test/file_conflict_callbacks_test.rb index e1a7e2d30..57332048c 100755 --- a/library/packages/test/file_conflict_callbacks_test.rb +++ b/library/packages/test/file_conflict_callbacks_test.rb @@ -81,7 +81,6 @@ def CallbackFileConflictFinish(func) it "opens a new progress if installation progress was not displayed" do expect(Yast::UI).to receive(:WidgetExists).and_return(false) expect(Yast::Progress).to receive(:Simple) - allow(Yast::Progress).to receive(:Title) start_cb.call end From 438f12e24d395b4a7a89ef4212de987bb7d79c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 29 Mar 2016 15:01:26 +0200 Subject: [PATCH 12/12] code review fixes --- .../packages/src/lib/packages/file_conflict_callbacks.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/packages/src/lib/packages/file_conflict_callbacks.rb b/library/packages/src/lib/packages/file_conflict_callbacks.rb index b1943819b..d565a27ab 100644 --- a/library/packages/src/lib/packages/file_conflict_callbacks.rb +++ b/library/packages/src/lib/packages/file_conflict_callbacks.rb @@ -17,8 +17,9 @@ module Packages # Default file conflicts callbacks for package bindings. To register the - # callbacks in Yast::Pkg just call {Package::FileConflictCallbacks.register} + # callbacks in Yast::Pkg just call {Packages::FileConflictCallbacks.register} class FileConflictCallbacks + # Widget ID (created by other code) PKG_INSTALL_WIDGET = :progressCurrentPackage class << self @@ -129,7 +130,7 @@ def report(excluded_packages, conflicts) if Yast::Mode.auto || Yast::Mode.commandline # TRANSLATORS: An error message, %s is the actual list of detected conflicts Yast::Report.Error(_("File conflicts detected, these conflicting files will " \ - "be overwritten:\n\n%s") % conflicts.join("\n")) + "be overwritten:\n\n%s") % conflicts.join("\n\n")) return true end @@ -166,8 +167,8 @@ def dialog(conflicts) # TRANSLATORS: A popup label, use max. 70 chars per line, use more lines if needed label = _("File conflicts happen when two packages attempt to install\n" \ - "files with the same name but different contents. If you continue,\n" \ - "the conflicting files will be replaced losing the previous content.") + "files with the same name but different contents. If you continue\n" \ + "the conflicting files will be replaced, losing the previous content.") # TRANSLATORS: Popup heading heading = n_("A File Conflict Detected", "File Conflicts Detected", conflicts.size)