diff --git a/src/modules/PackageSlideShow.rb b/src/modules/PackageSlideShow.rb index 883638f66..424940968 100644 --- a/src/modules/PackageSlideShow.rb +++ b/src/modules/PackageSlideShow.rb @@ -16,6 +16,7 @@ def main Yast.import "SlideShow" Yast.import "String" Yast.import "Mode" + Yast.import "Packages" @inst_src_names = [] # a list of strings identifying each repository @total_size_installed = 0 @@ -33,6 +34,10 @@ def main @total_installed = 0 @total_pkgs_to_install = 0 + @expected_total_download_size = 0 + @finished_total_download_size = 0 + @current_pkg_download_percent = 0 + # package list (only used in installed system) @installed_packages_list = [] @updated_packages_list = [] @@ -47,6 +52,11 @@ def ResetPackageSummary @removed_packages = 0 @total_downloaded = 0 @total_installed = 0 + @expected_total_download_size = 0 + @finished_total_download_size = 0 + @current_pkg_download_size = 0 + @current_pkg_download_percent = 0 + @current_pkg_name = "" @installed_packages_list = [] @updated_packages_list = [] @@ -75,7 +85,7 @@ def GetPackageSummary # ************** Formatting functions and helpers ************************** # *************************************************************************** - # Sum up all list items. It flattens list and also skip all negative values. + # Sum up all list items. It flattens the list and also skips all negative values. # # @param sizes [Array] Sizes to sum # @return [Fixnum] Sizes sum @@ -83,16 +93,22 @@ def ListSum(sizes) sizes.flatten.select(&:positive?).reduce(0, :+) end + # The total size in bytes to install. + def TotalSizeToInstall + @total_size_to_install + end + + # The current size in bytes that is already installed. def TotalInstalledSize @total_size_installed end # Format number of remaining bytes to be installed as string. # @param [Fixnum] remaining bytes remaining, -1 for 'done' - # @return [String] human readable remaining time or byte / kB/ MB size + # @return [String] human readable remaining time or byte / kB/ MB size # def FormatRemainingSize(remaining) - if Ops.less_than(remaining, 0) + if remaining < 0 # Nothing more to install from this CD (very concise - little space!!) return _("Done.") end @@ -103,10 +119,10 @@ def FormatRemainingSize(remaining) # Format number of remaining packages to be installed as string. # @param [Fixnum] remaining bytes remaining, -1 for 'done' - # @return [String] human readable remaining time or byte / kB/ MB size + # @return [String] human readable remaining time or byte / kB/ MB size # def FormatRemainingCount(remaining) - if Ops.less_than(remaining, 0) + if remaining < 0 # Nothing more to install from this CD (very concise - little space!!) return _("Done.") end @@ -137,54 +153,39 @@ def InitPkgData(force) log.info "total_size_to_install: #{@total_size_to_install}" @total_pkgs_to_install = ListSum(total_pkg_count_per_cd_per_src) @init_pkg_data_complete = true - end - - # Recalculate remaining times per CD based on package sizes remaining - # and data rate so far. Recalculation is only done each 'recalc_interval' - # seconds unless 'force_recalc' is set to 'true'. - # - # @param [Boolean] _force_recalc force recalculation even if timeout not reached yet - # @return true if recalculated, false if not - # - # @see SlideShow.next_recalc_time - # @see Yast2::SystemTime.uptime - def RecalcRemainingTimes(_force_recalc) - true - end - - # Switch unit to seconds if necessary and recalc everything accordingly. - # @return true if just switched from sizes to seconds, false otherwise - # - def SwitchToSecondsIfNecessary - false + @expected_total_download_size = Packages.CountSizeToBeDownloaded end # *************************************************************************** # ***************** Callbacks and progress bars **************************** # *************************************************************************** - # Update progress widgets for the current CD: Label and ProgressBar. - # Use global statistics variables for that. - # @param [Boolean] silent_check don't complain in log file - # - def UpdateCurrentCdProgress(silent_check); end - - # update the overall progress value (download + installation) + # Update the overall progress value (download + installation) def UpdateTotalProgressValue - total_progress = if @total_size_to_install.zero? - 100 # nothing to install. Should not happen + total_size = @total_size_to_install + @expected_total_download_size + + if total_size.zero? + total_progress = 100.0 # Nothing to install. Should not happen. else - TotalInstalledSize() * 100 / @total_size_to_install + current = TotalInstalledSize() + CurrentDownloadSize() + total_progress = 100.0 * current / total_size end - log.debug "Total package installation progress: #{total_progress}%" - SlideShow.StageProgress(total_progress, nil) + log.info "### Total package installation progress: #{total_progress}%" + SlideShow.StageProgress(total_progress.round, nil) + end + + # Calculate the size of the current downloads + def CurrentDownloadSize + current_pkg = @current_pkg_download_size * @current_pkg_download_percent / 100 + @finished_total_download_size + current_pkg end # Update progress widgets # def UpdateTotalProgress(_silent_check) # update the overall progress value (download + installation) + log.info "### UpdateTotalProgressValue" UpdateTotalProgressValue() end @@ -193,24 +194,21 @@ def UpdateTotalProgress(_silent_check) # # @param [Fixnum] pkg_percent package percentage # - def UpdateCurrentPackageProgress(pkg_percent); end - - # update the download rate - def UpdateCurrentPackageRateProgress(_pkg_percent, _bps_avg, _bps_current) - nil + def UpdateCurrentPackageProgress(pkg_percent) + # FIXME: Obsolete? + log.info "### UpdateCurrentPackageProgress #{pkg_percent}" end def DisplayGlobalProgress - rem_string = FormatRemainingSize(@total_size_to_install - @total_size_installed) - - rem_string += ", " unless rem_string.empty? + remaining_string = FormatRemainingSize(@total_size_to_install - @total_size_installed) + remaining_string += ", " unless remaining_string.empty? SlideShow.SetGlobalProgressLabel( Ops.add( SlideShow.CurrentStageDescription, Builtins.sformat( _(" (Remaining: %1%2 packages)"), - rem_string, + remaining_string, @total_pkgs_to_install - @installed_packages - @updated_packages ) ) @@ -219,43 +217,86 @@ def DisplayGlobalProgress nil end - # Callback when file is downloaded ( but not yet installed ) - # @param error[Integer] error code - def DoneProvide(error, _reason, _name) - return if error.nonzero? + # Notification when package download starts + def DownloadStart(pkg_name, download_size) + log.info "### DownloadStart #{pkg_name} size: #{download_size}" + sleep(1) + @current_pkg_name = pkg_name + @current_pkg_download_size = download_size + @current_pkg_download_percent = 0 + UpdateTotalProgressValue() + nil + end + + # Update the download progress for the current package + def DownloadProgress(pkg_percent) + log.info "### DownloadProgress #{pkg_percent}" + @current_pkg_download_percent = pkg_percent + UpdateTotalProgressValue() + nil + end - # move the progress also for downloaded files + # Notification when package download is finished (but not yet installed) + def DownloadEnd(pkg_name) + log.info("### DownloadEnd #{pkg_name}") + CurrentDownloadFinished() UpdateTotalProgressValue() + sleep(3) nil end - # Update progress widgets for all CDs. - # Uses global statistics variables. - # Redraw whole table, time consuming, but called only when all times recalculated. + # Notification about a download error. + # @param [Integer] error Numeric error code + # @param [String] reason + # @param [String] pkg_name + def DownloadError(error, reason, pkg_name) + log.error("Download error #{error} for #{pkg_name}: #{reason}") + CurrentDownloadFinished() + UpdateTotalProgressValue() + nil + end + + # Finalize the sums for the current download + def CurrentDownloadFinished() + @finished_total_download_size += @current_pkg_download_size + @current_pkg_download_size = 0 + @current_pkg_download_percent = 0 + @current_pkg_name = "" + end + + # Notification that a package starts being installed, updated or removed. + # Not to be confused with DownloadStart. + # + # @param [String] pkg_name package name + # @param [String] _pkg_location full path to a package + # @param [String] _pkg_summary package summary (short description) + # @param [Integer] _pkg_size installed package size in bytes + # @param [Boolean] deleting Flag: deleting (true) or installing (false) package? # - def UpdateAllCdProgress(_silent_check) + def PkgInstallStart(pkg_name, _pkg_location, _pkg_summary, _pkg_size, deleting) + @updating = Pkg.PkgInstalled(pkg_name) if !deleting + # Update global progress bar + DisplayGlobalProgress() + nil end - # Return a CD's progress bar ID - # @param [Fixnum] src_no number of the repository (from 0 on) - # @param [Fixnum] cd_no number of the CD within that repository (from 0 on) + # Progress notification while a package is finished being installed, updated or removed. # - def CdProgressId(src_no, cd_no) - Builtins.sformat("Src %1 CD %2", src_no, cd_no) + # @param [Integer] percent of progress of this package + def PkgInstallProgress(_pkg_percent) + nil end - # package start display update - # - this is called at the end of a new package + # Notification that a package is finished being installed, updated or removed. # # @param [String] pkg_name package name # @param [String] pkg_size package size in bytes # @param [Boolean] deleting Flag: deleting (true) or installing (false) package # - def SlideDisplayDone(pkg_name, pkg_size, deleting) + def PkgInstallDone(pkg_name, pkg_size, deleting) if deleting @removed_packages += 1 - @removed_packages_list << pkg_name if Mode.normal else @total_size_installed += pkg_size @@ -266,72 +307,32 @@ def SlideDisplayDone(pkg_name, pkg_size, deleting) DisplayGlobalProgress() if @updating - @updated_packages = Ops.add(@updated_packages, 1) - - if Mode.normal - @updated_packages_list = Builtins.add( - @updated_packages_list, - pkg_name - ) - end + @updated_packages += 1 + @updated_packages_list << pkg_name if Mode.normal else - @installed_packages = Ops.add(@installed_packages, 1) - - if Mode.normal - @installed_packages_list = Builtins.add( - @installed_packages_list, - pkg_name - ) - end + @installed_packages += 1 + @installed_packages_list << pkg_name if Mode.normal end - @total_installed = Ops.add(@total_installed, pkg_size) + @total_installed += pkg_size end nil end - # package start display update - # - this is called at the beginning of a new package - # - # @param [String] pkg_name package name - # @param [String] _pkg_location full path to a package - # @param [String] _pkg_summary package summary (short description) - # @param [Integer] _pkg_size package size in bytes - # @param [Boolean] deleting Flag: deleting (true) or installing (false) package? - # - def SlideDisplayStart(pkg_name, _pkg_location, _pkg_summary, _pkg_size, deleting) - @updating = Pkg.PkgInstalled(pkg_name) if !deleting - # Update global progress bar - DisplayGlobalProgress() - - nil - end - - def SlideGenericProvideStart(pkg_name, size, pattern, remote); end - - def SlideDeltaApplyStart(_pkg_name) - nil - end - - # Package providal start - def SlideProvideStart(_pkg_name, _size, _remote) - nil - end - publish variable: :total_size_to_install, type: "integer" # Used in installation client + publish function: :TotalSizeToInstall, type: "integer ()" # Better substitute for the above publish function: :GetPackageSummary, type: "map ()" publish function: :InitPkgData, type: "void (boolean)" publish function: :UpdateCurrentPackageProgress, type: "void (integer)" - publish function: :UpdateCurrentPackageRateProgress, type: "void (integer, integer, integer)" publish function: :DisplayGlobalProgress, type: "void ()" - publish function: :DoneProvide, type: "void (integer, string, string)" - publish function: :UpdateAllCdProgress, type: "void (boolean)" - publish function: :SlideDisplayDone, type: "void (string, integer, boolean)" - publish function: :SlideDisplayStart, type: "void (string, string, string, integer, boolean)" - publish function: :SlideGenericProvideStart, type: "void (string, integer, string, boolean)" - publish function: :SlideDeltaApplyStart, type: "void (string)" - publish function: :SlideProvideStart, type: "void (string, integer, boolean)" + publish function: :DownloadStart, type: "void (string, integer)" + publish function: :DownloadProgress, type: "void (integer)" + publish function: :DownloadEnd, type: "void (string)" + publish function: :DownloadError, type: "void (integer, string, string)" + publish function: :PkgInstallStart, type: "void (string, integer, string, boolean)" + publish function: :PkgInstallProgress, type: "void (integer)" + publish function: :PkgInstallDone, type: "void (string, integer, boolean)" end PackageSlideShow = PackageSlideShowClass.new diff --git a/src/modules/SlideShowCallbacks.rb b/src/modules/SlideShowCallbacks.rb index 64d28167e..6a7768c7f 100644 --- a/src/modules/SlideShowCallbacks.rb +++ b/src/modules/SlideShowCallbacks.rb @@ -74,34 +74,31 @@ def StartProvide(name, archivesize, remote) @pkg_inprogress = name @_remote_provide = remote - PackageSlideShow.SlideProvideStart(name, archivesize, remote) - + PackageSlideShow.DownloadStart(name, archivesize) if @_remote_provide nil end # during file providal def ProgressProvide(percent) - PackageSlideShow.UpdateCurrentPackageProgress(percent) if @_remote_provide + PackageSlideShow.DownloadProgress(percent) if @_remote_provide + HandleInput() !SlideShow.GetUserAbort end - def ProgressDownload(percent, bps_avg, bps_current) - PackageSlideShow.UpdateCurrentPackageRateProgress( - percent, - bps_avg, - bps_current - ) - - HandleInput() + # Update during package download: Percent, average and current bytes per second. + def ProgressDownload(percent, _bps_avg, _bps_current) !SlideShow.GetUserAbort end # during file providal def DoneProvide(error, reason, name) if @_remote_provide - PackageSlideShow.UpdateCurrentPackageProgress(100) - PackageSlideShow.DoneProvide(error, reason, name) + if (error) + PackageSlideShow.DownloadError(error, reason, name) + else + PackageSlideShow.DownloadEnd + end @_remote_provide = false end return "C" if SlideShow.GetUserAbort @@ -260,7 +257,7 @@ def YesNoAgainWarning(message) # and pass the "deleting" flag as appropriate. # def DisplayStartInstall(pkg_name, pkg_location, pkg_description, pkg_size, deleting) - PackageSlideShow.SlideDisplayStart( + PackageSlideShow.PkgInstallStart( pkg_name, pkg_location, pkg_description, @@ -383,7 +380,7 @@ def DisplayStartInstall(pkg_name, pkg_location, pkg_description, pkg_size, delet nil end - # at start of package install + # Notification that a package starts being installed, updated or removed. def StartPackage(name, location, summary, install_size, is_delete) PackageCallbacks._package_name = name PackageCallbacks._package_size = install_size @@ -394,9 +391,9 @@ def StartPackage(name, location, summary, install_size, is_delete) nil end - # ProgressPackage percent - # + # Progress while a package is being installed, updated or removed. def ProgressPackage(pkg_percent) + PackageSlideShow.PkgInstallProgress(pkg_percent) HandleInput() Builtins.y2milestone("Aborted at %1%%", pkg_percent) if SlideShow.GetUserAbort @@ -404,7 +401,8 @@ def ProgressPackage(pkg_percent) !SlideShow.GetUserAbort end - # at end of install + # Notification that a package is finished being installed, updated or removed. + # # just to override the PackageCallbacks default (which does a 'CloseDialog' :-}) def DonePackage(error, reason) return "I" if SlideShow.GetUserAbort @@ -420,7 +418,7 @@ def DonePackage(error, reason) if Builtins.size(ret).zero? || Builtins.tolower(Builtins.substring(ret, 0, 1)) != "r" - PackageSlideShow.SlideDisplayDone( + PackageSlideShow.PkgInstallDone( PackageCallbacks._package_name, PackageCallbacks._package_size, PackageCallbacks._deleting_package @@ -431,20 +429,11 @@ def DonePackage(error, reason) # at start of file providal def StartDeltaProvide(name, archivesize) - PackageSlideShow.SlideGenericProvideStart( - name, # remote - archivesize, - _("Downloading delta RPM %1 (download size %2)"), - true - ) - nil end # at start of file providal def StartDeltaApply(name) - PackageSlideShow.SlideDeltaApplyStart(name) - nil end diff --git a/test/package_slide_show_test.rb b/test/package_slide_show_test.rb index 1495f11a7..c6548a6e6 100755 --- a/test/package_slide_show_test.rb +++ b/test/package_slide_show_test.rb @@ -17,11 +17,11 @@ end end - describe ".SlideDisplayDone" do + describe ".PkgInstallDone" do context "when deleting package" do it "increases removed counter in summary" do package_slide_show.main # to reset counter - expect { package_slide_show.SlideDisplayDone("test", 1, true) }.to( + expect { package_slide_show.PkgInstallDone("test", 1, true) }.to( change { package_slide_show.GetPackageSummary["removed"] }.from(0).to(1) ) end @@ -29,7 +29,7 @@ it "adds name to removed_list in summary in normal mode" do allow(Yast::Mode).to receive(:normal).and_return(true) package_slide_show.main # to reset counter - expect { package_slide_show.SlideDisplayDone("test", 1, true) }.to( + expect { package_slide_show.PkgInstallDone("test", 1, true) }.to( change { package_slide_show.GetPackageSummary["removed_list"] } .from([]) .to(["test"]) @@ -43,7 +43,7 @@ # TODO: updating non trivial amount of table it "increases installed counter in summary" do package_slide_show.main # to reset counter - expect { package_slide_show.SlideDisplayDone("test", 1, false) }.to( + expect { package_slide_show.PkgInstallDone("test", 1, false) }.to( change { package_slide_show.GetPackageSummary["installed"] }.from(0).to(1) ) end @@ -51,7 +51,7 @@ it "adds name to installed_list in summary in normal mode" do allow(Yast::Mode).to receive(:normal).and_return(true) package_slide_show.main # to reset counter - expect { package_slide_show.SlideDisplayDone("test", 1, false) }.to( + expect { package_slide_show.PkgInstallDone("test", 1, false) }.to( change { package_slide_show.GetPackageSummary["installed_list"] } .from([]) .to(["test"]) @@ -60,7 +60,7 @@ it "adds its size to installed_bytes in summary" do package_slide_show.main # to reset counter - expect { package_slide_show.SlideDisplayDone("test", 502, false) }.to( + expect { package_slide_show.PkgInstallDone("test", 502, false) }.to( change { package_slide_show.GetPackageSummary["installed_bytes"] }.from(0).to(502) ) end @@ -68,13 +68,13 @@ it "sets global progress label in slide show" do expect(Yast::SlideShow).to receive(:SetGlobalProgressLabel) - package_slide_show.SlideDisplayDone("test", 502, false) + package_slide_show.PkgInstallDone("test", 502, false) end it "updates stage progress" do expect(Yast::SlideShow).to receive(:StageProgress) - package_slide_show.SlideDisplayDone("test", 502, false) + package_slide_show.PkgInstallDone("test", 502, false) end end end diff --git a/test/slide_show_callabacks_test.rb b/test/slide_show_callbacks_test.rb similarity index 97% rename from test/slide_show_callabacks_test.rb rename to test/slide_show_callbacks_test.rb index c1a9598da..727f8a0f4 100755 --- a/test/slide_show_callabacks_test.rb +++ b/test/slide_show_callbacks_test.rb @@ -15,7 +15,7 @@ let(:deleting) { false } before do - allow(Yast::PackageSlideShow).to receive(:SlideDisplayStart) + allow(Yast::PackageSlideShow).to receive(:PkgInstallStart) allow(subject).to receive(:HandleInput) allow(Yast::Installation).to receive(:destdir).and_return("/") allow(File).to receive(:exist?).and_return(true)