diff --git a/service/lib/agama/software/manager.rb b/service/lib/agama/software/manager.rb index 45cf2bb4eb..c3f83ff969 100644 --- a/service/lib/agama/software/manager.rb +++ b/service/lib/agama/software/manager.rb @@ -231,9 +231,7 @@ def add_pattern(id) res = Yast::Pkg.ResolvableInstall(id, :pattern) logger.info "Adding pattern #{res.inspect}" Yast::PackagesProposal.AddResolvables(PROPOSAL_ID, :pattern, [id]) - - res = Yast::Pkg.PkgSolve(unused = true) - logger.info "Solver run #{res.inspect}" + proposal.solve_dependencies selected_patterns_changed true @@ -245,9 +243,7 @@ def remove_pattern(id) res = Yast::Pkg.ResolvableNeutral(id, :pattern, force = false) logger.info "Removing pattern #{res.inspect}" Yast::PackagesProposal.RemoveResolvables(PROPOSAL_ID, :pattern, [id]) - - res = Yast::Pkg.PkgSolve(unused = true) - logger.info "Solver run #{res.inspect}" + proposal.solve_dependencies selected_patterns_changed true @@ -262,9 +258,7 @@ def assign_patterns(ids) Yast::PackagesProposal.SetResolvables(PROPOSAL_ID, :pattern, ids) ids.each { |p| Yast::Pkg.ResolvableInstall(p, :pattern) } logger.info "Setting patterns to #{ids.inspect}" - - res = Yast::Pkg.PkgSolve(unused = true) - logger.info "Solver run #{res.inspect}" + proposal.solve_dependencies selected_patterns_changed [] @@ -383,7 +377,9 @@ def build_products end def proposal - @proposal ||= Proposal.new + @proposal ||= Proposal.new.tap do |proposal| + proposal.on_issues_change { update_issues } + end end def import_gpg_keys diff --git a/service/lib/agama/software/proposal.rb b/service/lib/agama/software/proposal.rb index 62bbb03095..e990a5c598 100644 --- a/service/lib/agama/software/proposal.rb +++ b/service/lib/agama/software/proposal.rb @@ -90,10 +90,27 @@ def calculate @proposal = Yast::Packages.Proposal(force_reset = true, reinit = false, _simple = true) solve_dependencies - update_issues valid? end + # Runs the solver to satisfy the dependencies. + # + # Issues are updated once the solver finishes. + # + # @return [Boolean] whether the solver ran successfully + def solve_dependencies + res = Yast::Pkg.PkgSolve(unused = true) + logger.info "Solver run #{res.inspect}" + update_issues + + return true if res + + logger.error "Solver failed: #{Yast::Pkg.LastError}" + logger.error "Details: #{Yast::Pkg.LastErrorDetails}" + logger.error "Solver errors: #{Yast::Pkg.PkgSolveErrors}" + false + end + # Returns the count of packages to install # # @return [Integer] count of packages to install @@ -172,12 +189,10 @@ def select_base_product # # @return [Array] def update_issues - self.issues = [] - return unless proposal - msgs = [] - msgs.concat(warning_messages(proposal)) + msgs.concat(warning_messages(proposal)) if proposal msgs.concat(solver_messages) + issues = msgs.map do |msg| Issue.new(msg, source: Issue::Source::CONFIG, @@ -187,22 +202,6 @@ def update_issues self.issues = issues end - # Runs the solver to satisfy the solve_dependencies - # - # If the solver failed, it logs the error. - # - # @return [Boolean] whether the solver ran successfully - def solve_dependencies - res = Yast::Pkg.PkgSolve(unused = true) - logger.info "Solver run #{res.inspect}" - return true if res - - logger.error "Solver failed: #{Yast::Pkg.LastError}" - logger.error "Details: #{Yast::Pkg.LastErrorDetails}" - logger.error "Solver errors: #{Yast::Pkg.PkgSolveErrors}" - false - end - # Extracts the warning messages from the proposal result # # @param proposal_result [Hash] Proposal result; it might contain a "warning" key with warning diff --git a/service/test/agama/software/manager_test.rb b/service/test/agama/software/manager_test.rb index 5a8af33802..c25e15f4b9 100644 --- a/service/test/agama/software/manager_test.rb +++ b/service/test/agama/software/manager_test.rb @@ -59,7 +59,8 @@ :languages= => nil, set_resolvables: nil, packages_count: "500 MB", - issues: proposal_issues + issues: proposal_issues, + on_issues_change: nil ) end diff --git a/service/test/agama/software/proposal_test.rb b/service/test/agama/software/proposal_test.rb index 1c3c176589..57eabc637b 100644 --- a/service/test/agama/software/proposal_test.rb +++ b/service/test/agama/software/proposal_test.rb @@ -26,7 +26,7 @@ describe Agama::Software::Proposal do subject(:proposal) { described_class.new(logger: logger) } - let(:logger) { Logger.new($stdout) } + let(:logger) { Logger.new($stdout, level: :warn) } let(:destdir) { "/mnt" } let(:result) { {} } let(:last_error) { "" } @@ -111,6 +111,42 @@ end end + describe "#solve_dependencies" do + it "calls the solver" do + expect(Yast::Pkg).to receive(:PkgSolve) + subject.solve_dependencies + end + + context "if the solver successes" do + before do + allow(Yast::Pkg).to receive(:PkgSolve).and_return(true) + end + + it "returns true" do + expect(subject.solve_dependencies).to eq(true) + end + end + + context "if the solver fails" do + before do + allow(Yast::Pkg).to receive(:PkgSolve).and_return(false) + end + + let(:solve_errors) { 2 } + + it "returns false" do + expect(subject.solve_dependencies).to eq(false) + end + + it "registers solver issue" do + subject.solve_dependencies + expect(subject.issues).to contain_exactly( + an_object_having_attributes(description: "Found 2 dependency issues.") + ) + end + end + end + describe "#set_resolvables" do it "adds the list of packages/patterns to the proposal" do expect(Yast::PackagesProposal).to receive(:SetResolvables)