Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
8 changes: 5 additions & 3 deletions rust/Cargo.lock

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

2 changes: 2 additions & 0 deletions rust/agama-software/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ thiserror = "2.0.12"
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread", "sync"] }
tokio-stream = "0.1.16"
tracing = "0.1.41"
url = "2.5.7"
utoipa = { version = "5.2.0", features = ["axum_extras", "uuid"] }
zypp-agama = { path = "../zypp-agama" }

[dev-dependencies]
serde_yaml = "0.9.34"
tempfile = "3.23.0"
60 changes: 30 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::{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,16 @@ pub struct Model {
selected_product: Option<ProductSpec>,
progress: Handler<progress::Service>,
question: Handler<question::Service>,
/// Predefined repositories (from the off-line media and Driver Update Disks).
/// They cannot be altered through user configuration.
predefined_repositories: Vec<Repository>,
}

impl Model {
/// Initializes the struct with the information from the underlying system.
pub fn new(
zypp_sender: mpsc::UnboundedSender<SoftwareAction>,
predefined_repositories: Vec<Repository>,
progress: Handler<progress::Service>,
question: Handler<question::Service>,
) -> Result<Self, service::Error> {
Expand All @@ -95,29 +99,9 @@ impl Model {
selected_product: None,
progress,
question,
predefined_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]
Expand All @@ -143,11 +127,27 @@ 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 "predefined" field as this struct holds the information to determine
// which repositories are "predefined".
let predefined_urls: Vec<_> = self
.predefined_repositories
.iter()
.map(|r| r.url.as_str())
.collect();
for repo in system_info.repositories.iter_mut() {
repo.predefined = predefined_urls.contains(&repo.url.as_str());
}

Ok(system_info)
}

async fn refresh(&mut self) -> Result<(), service::Error> {
Expand All @@ -170,14 +170,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