diff --git a/service/lib/agama/dbus/storage/manager.rb b/service/lib/agama/dbus/storage/manager.rb index 22f335b966..584771f79a 100644 --- a/service/lib/agama/dbus/storage/manager.rb +++ b/service/lib/agama/dbus/storage/manager.rb @@ -290,7 +290,7 @@ def perform_probe # # @note Skips if no proposal has been calculated yet. def configure_with_current - return unless proposal.storage_json + return unless manager.product_config calculate_proposal(manager.config_json) # The storage proposal with the current settings is not explicitly requested. It is @@ -308,6 +308,21 @@ def calculate_proposal(config_json = nil) manager.configure(config_json) manager.add_packages if manager.proposal.success? + # The "return if unchanged" guard has been removed from the methods below to always + # emit the corresponding signal. + # + # Since signals do not carry payloads yet, the UI cannot update the query cache + # directly and must refetch after receiving the signal. Without emitting the signal, + # the related queries are never invalidated and never refetched, leaving the progress + # overlay blocked indefinitely. + # + # The overlay intentionally waits until fresh data arrives before unblocking, since + # data can take time to appear after progress completes. Dismissing it + # earlier would cause flickering and leave users able to interact with stale data. + # + # It can be reverted (and UI progress adapted accordingly) when signals carry payloads + # that allow the UI to update the cache directly, removing the need to wait for a + # refetch as part of progress completion. update_serialized_config update_serialized_config_model update_serialized_proposal @@ -324,7 +339,7 @@ def calculate_bootloader # Updates the system info if needed. def update_serialized_system serialized_system = serialize_system - return if self.serialized_system == serialized_system + # return if self.serialized_system == serialized_system # This assignment emits a D-Bus PropertiesChanged. self.serialized_system = serialized_system @@ -334,7 +349,7 @@ def update_serialized_system # Updates the config info if needed. def update_serialized_config serialized_config = serialize_config - return if self.serialized_config == serialized_config + # return if self.serialized_config == serialized_config # This assignment emits a D-Bus PropertiesChanged. self.serialized_config = serialized_config @@ -343,7 +358,7 @@ def update_serialized_config # Updates the config model info if needed. def update_serialized_config_model serialized_config_model = serialize_config_model - return if self.serialized_config_model == serialized_config_model + # return if self.serialized_config_model == serialized_config_model # This assignment emits a D-Bus PropertiesChanged. self.serialized_config_model = serialized_config_model @@ -352,7 +367,7 @@ def update_serialized_config_model # Updates the proposal info if needed. def update_serialized_proposal serialized_proposal = serialize_proposal - return if self.serialized_proposal == serialized_proposal + # return if self.serialized_proposal == serialized_proposal # This assignment emits a D-Bus PropertiesChanged. self.serialized_proposal = serialized_proposal @@ -362,7 +377,7 @@ def update_serialized_proposal # Updates the issues info if needed. def update_serialized_issues serialized_issues = serialize_issues - return if self.serialized_issues == serialized_issues + # return if self.serialized_issues == serialized_issues # This assignment emits a D-Bus PropertiesChanged. self.serialized_issues = serialized_issues diff --git a/service/lib/agama/storage/proposal.rb b/service/lib/agama/storage/proposal.rb index 1c1231f57c..5eac9540c9 100644 --- a/service/lib/agama/storage/proposal.rb +++ b/service/lib/agama/storage/proposal.rb @@ -312,7 +312,7 @@ def failed_issue # @return [Issue] def exception_issue(error) Issue.new( - _("A problem ocurred while calculating the storage setup"), + _("A problem occurred while calculating the storage setup"), kind: IssueClasses::PROPOSAL, details: error.message ) diff --git a/service/package/rubygem-agama-yast.changes b/service/package/rubygem-agama-yast.changes index e79a3ddae3..817639fcf8 100644 --- a/service/package/rubygem-agama-yast.changes +++ b/service/package/rubygem-agama-yast.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Wed Apr 8 09:28:31 UTC 2026 - Knut Anderssen + +- Fix for diskless installation making a proposal when + there is at least the product configuration notifying the + system and proposal state (bsc#1260378). + ------------------------------------------------------------------- Mon Mar 23 16:29:40 UTC 2026 - Josef Reidinger diff --git a/service/test/agama/dbus/storage/manager_test.rb b/service/test/agama/dbus/storage/manager_test.rb index c098c53b6c..185988fe6d 100644 --- a/service/test/agama/dbus/storage/manager_test.rb +++ b/service/test/agama/dbus/storage/manager_test.rb @@ -232,7 +232,7 @@ def parse(string) let(:drive2) { instance_double(Y2Storage::Disk, name: "/dev/vdb", sid: 96) } let(:drive3) { instance_double(Y2Storage::Disk, name: "/dev/vdb", sid: 97) } - it "retuns the id of each drive" do + it "returns the id of each drive" do result = parse(subject.serialized_system)[:availableDrives] expect(result).to contain_exactly(95, 96, 97) end @@ -254,7 +254,7 @@ def parse(string) let(:drive1) { instance_double(Y2Storage::Disk, name: "/dev/vda", sid: 95) } let(:drive2) { instance_double(Y2Storage::Disk, name: "/dev/vdb", sid: 96) } - it "retuns the id of each drive" do + it "returns the id of each drive" do result = parse(subject.serialized_system)[:candidateDrives] expect(result).to contain_exactly(95, 96) end @@ -299,7 +299,7 @@ def parse(string) let(:md_raid1) { instance_double(Y2Storage::Md, name: "/dev/md0", sid: 100) } let(:md_raid2) { instance_double(Y2Storage::Md, name: "/dev/md1", sid: 101) } - it "retuns the path of each MD RAID" do + it "returns the path of each MD RAID" do result = parse(subject.serialized_system)[:candidateMdRaids] expect(result).to contain_exactly(100, 101) end @@ -323,7 +323,7 @@ def parse(string) let(:drive) { instance_double(Y2Storage::Disk, name: "/dev/vda", sid: 95) } - it "retuns an empty array" do + it "returns an empty array" do result = parse(subject.serialized_system)[:issues] expect(result).to eq [] end @@ -652,7 +652,7 @@ def parse(string) include_examples "do not activate or probe" include_examples "do not update product configuration" - include_examples "do not emit SystemChanged" + include_examples "emit SystemChanged" include_examples "calculate proposal" end end @@ -722,15 +722,17 @@ def parse(string) { storage: { drives: [ - ptableType: "gpt", - partitions: [ - { - filesystem: { - type: "btrfs", - path: "/" + { + ptableType: "gpt", + partitions: [ + { + filesystem: { + type: "btrfs", + path: "/" + } } - } - ] + ] + } ] } } @@ -825,7 +827,7 @@ def parse(string) include_examples "do not activate or probe" include_examples "do not update product configuration" - include_examples "do not emit SystemChanged" + include_examples "emit SystemChanged" include_examples "calculate new proposal" end end @@ -1123,6 +1125,7 @@ def parse(string) describe "#probe" do before do allow(subject).to receive(:SystemChanged) + allow(subject).to receive(:ProposalChanged) allow(subject).to receive(:ProgressChanged) allow(subject).to receive(:ProgressFinished) @@ -1158,31 +1161,32 @@ def parse(string) end context "when no storage configuration has been set" do - it "does not calculate a new proposal" do - expect(backend).to_not receive(:configure) + it "re-calculates the proposal" do + expect(backend).to receive(:configure).with(nil) subject.probe end - it "does not configure bootloader" do - expect(bootloader).to_not receive(:configure) + it "configures bootloader" do + expect(bootloader).to receive(:configure) subject.probe end - it "does not emit a ProposalChanged signal" do - expect(subject).to_not receive(:ProposalChanged) + it "adjusts the packages to install in the target system" do + allow(proposal).to receive(:success?).and_return(true) + expect(backend).to receive(:add_packages) subject.probe end - it "emits signals for SystemChanged, ProgressChanged and ProgressFinished" do + it "emits signals for ProposalChanged, SystemChanged, ProgressChanged and ProgressFinished" do expect(subject).to receive(:SystemChanged) do |system_str| system = parse(system_str) device = system[:devices].first expect(device[:name]).to eq "/dev/sda" expect(system[:availableDrives]).to eq [device[:sid]] end + expect(subject).to receive(:ProposalChanged) expect(subject).to receive(:ProgressChanged).with(/storage configuration/i) expect(subject).to receive(:ProgressFinished) - subject.probe end end @@ -1251,7 +1255,7 @@ def parse(string) end end - context "if an agama proposal has been succesfully calculated" do + context "if an agama proposal has been successfully calculated" do before do backend.configure(config_json) end