Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ jobs:
- name: Install required packages
run: zypper --non-interactive install --allow-downgrade
clang-devel
libzypp-devel
gcc-c++
git
libopenssl-3-devel
libzypp-devel
make
openssl-3
pam-devel
Expand Down Expand Up @@ -142,20 +142,21 @@ jobs:
run: zypper --non-interactive install --allow-downgrade
clang-devel
dbus-1-daemon
libzypp-devel
gcc-c++
git
glibc-locale
golang-github-google-jsonnet
jq
libopenssl-3-devel
libzypp-devel
make
openssl-3
pam-devel
python-langtable-data
python3-openapi_spec_validator
rustup
timezone
util-linux-systemd
xkeyboard-config

- name: Configure git
Expand Down
7 changes: 4 additions & 3 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/agama-software/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ zypp-agama = { path = "../zypp-agama" }

[dev-dependencies]
serde_yaml = "0.9.34"
tempfile = "3.23.0"
56 changes: 26 additions & 30 deletions rust/agama-software/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use agama_utils::{
actor::Handler,
api::{
software::{Pattern, SoftwareProposal, SystemInfo},
software::{Pattern, Repository, SoftwareProposal, SystemInfo},
Issue,
},
products::{ProductSpec, UserPattern},
Expand Down Expand Up @@ -50,7 +50,7 @@ pub trait ModelAdapter: Send + Sync + 'static {
/// Returns the software system information.
async fn system_info(&self) -> Result<SystemInfo, service::Error>;

async fn compute_proposal(&self) -> Result<SoftwareProposal, service::Error>;
async fn proposal(&self) -> Result<SoftwareProposal, service::Error>;

/// Refresh repositories information.
async fn refresh(&mut self) -> Result<(), service::Error>;
Expand Down Expand Up @@ -81,12 +81,15 @@ pub struct Model {
selected_product: Option<ProductSpec>,
progress: Handler<progress::Service>,
question: Handler<question::Service>,
/// Local repositories (from the off-line media and Driver Update Disks).
repositories: Vec<Repository>,
}

impl Model {
/// Initializes the struct with the information from the underlying system.
pub fn new(
zypp_sender: mpsc::UnboundedSender<SoftwareAction>,
repositories: Vec<Repository>,
progress: Handler<progress::Service>,
question: Handler<question::Service>,
) -> Result<Self, service::Error> {
Expand All @@ -95,33 +98,14 @@ impl Model {
selected_product: None,
progress,
question,
repositories,
})
}

async fn patterns(&self) -> Result<Vec<Pattern>, service::Error> {
let Some(product) = &self.selected_product else {
return Err(service::Error::MissingProduct);
};

let names = product
.software
.user_patterns
.iter()
.map(|user_pattern| match user_pattern {
UserPattern::Plain(name) => name.clone(),
UserPattern::Preselected(preselected) => preselected.name.clone(),
})
.collect();

let (tx, rx) = oneshot::channel();
self.zypp_sender
.send(SoftwareAction::GetPatternsMetadata(names, tx))?;
Ok(rx.await??)
}
}

#[async_trait]
impl ModelAdapter for Model {
// FIXME: the product should be mandatory.
fn set_product(&mut self, product_spec: ProductSpec) {
self.selected_product = Some(product_spec);
}
Expand All @@ -143,11 +127,23 @@ impl ModelAdapter for Model {

/// Returns the software system information.
async fn system_info(&self) -> Result<SystemInfo, service::Error> {
Ok(SystemInfo {
patterns: self.patterns().await?,
repositories: vec![],
addons: vec![],
})
let Some(product_spec) = self.selected_product.clone() else {
return Err(service::Error::MissingProduct);
};

let (tx, rx) = oneshot::channel();
self.zypp_sender
.send(SoftwareAction::GetSystemInfo(product_spec, tx))?;
let mut system_info = rx.await??;

// set "mandatory" field as the info to decide whether the repository is mandatory or not
// lives in this struct.
let local_urls: Vec<_> = self.repositories.iter().map(|r| r.url.as_str()).collect();
for repo in system_info.repositories.iter_mut() {
repo.mandatory = local_urls.contains(&repo.url.as_str());
}

Ok(system_info)
}

async fn refresh(&mut self) -> Result<(), service::Error> {
Expand All @@ -170,14 +166,14 @@ impl ModelAdapter for Model {
Ok(rx.await??)
}

async fn compute_proposal(&self) -> Result<SoftwareProposal, service::Error> {
async fn proposal(&self) -> Result<SoftwareProposal, service::Error> {
let Some(product_spec) = self.selected_product.clone() else {
return Err(service::Error::MissingProduct);
};

let (tx, rx) = oneshot::channel();
self.zypp_sender
.send(SoftwareAction::ComputeProposal(product_spec, tx))?;
.send(SoftwareAction::GetProposal(product_spec, tx))?;
Ok(rx.await??)
}
}
Loading
Loading