diff --git a/rust/agama-autoinstall/src/auto_loader.rs b/rust/agama-autoinstall/src/auto_loader.rs index bfd2ea1f45..1c5921e85c 100644 --- a/rust/agama-autoinstall/src/auto_loader.rs +++ b/rust/agama-autoinstall/src/auto_loader.rs @@ -63,12 +63,12 @@ impl ConfigAutoLoader { /// locations. It does not report problems for these locations. /// /// See [Self::load] for further information. - pub async fn load(&self, urls: &Vec) -> anyhow::Result<()> { + pub async fn load(&self, urls: &[String]) -> anyhow::Result<()> { let loader = ConfigLoader::new(self.insecure); if urls.is_empty() { self.load_predefined_config(loader).await } else { - self.load_user_config(loader, &urls).await + self.load_user_config(loader, urls).await } } @@ -90,7 +90,7 @@ impl ConfigAutoLoader { /// Loads configuration files from pre-defined locations. async fn load_predefined_config(&self, loader: ConfigLoader) -> anyhow::Result<()> { for url in PREDEFINED_LOCATIONS { - match loader.load(&url).await { + match loader.load(url).await { Ok(()) => { println!("Configuration loaded from {url}"); return Ok(()); diff --git a/rust/agama-autoinstall/src/scripts.rs b/rust/agama-autoinstall/src/scripts.rs index bdda0cdde3..4295aacf51 100644 --- a/rust/agama-autoinstall/src/scripts.rs +++ b/rust/agama-autoinstall/src/scripts.rs @@ -67,7 +67,7 @@ impl ScriptsRunner { pub async fn run(&mut self, url: &str) -> anyhow::Result<()> { create_dir_all(&self.path)?; - let file_name = self.file_name_for(&url)?; + let file_name = self.file_name_for(url)?; let path = self.path.join(&file_name); self.save_script(url, &path).await?; @@ -92,17 +92,17 @@ impl ScriptsRunner { } fn file_name_for(&mut self, url: &str) -> anyhow::Result { - let parsed = Url::parse(&url)?; + let parsed = Url::parse(url)?; self.idx += 1; let unnamed = PathBuf::from(format!("{}-unnamed.sh", self.idx)); - let Some(path) = parsed.path_segments() else { + let Some(mut path) = parsed.path_segments() else { return Ok(unnamed); }; Ok(path - .last() + .next_back() .map(|p| PathBuf::from(format!("{}-{p}", self.idx))) .unwrap_or(unnamed)) } @@ -113,11 +113,11 @@ impl ScriptsRunner { .write(true) .truncate(true) .mode(0o700) - .open(&path)?; + .open(path)?; while let Err(error) = Transfer::get(url, &mut file, self.insecure) { eprintln!("Could not load the script from {url}: {error}"); - if !self.should_retry(&url, &error.to_string()).await? { + if !self.should_retry(url, &error.to_string()).await? { return Err(anyhow!(error)); } } diff --git a/rust/agama-bootloader/src/service.rs b/rust/agama-bootloader/src/service.rs index b45847b832..fb22a0304e 100644 --- a/rust/agama-bootloader/src/service.rs +++ b/rust/agama-bootloader/src/service.rs @@ -20,7 +20,7 @@ use agama_utils::{ actor::{self, Actor, Handler, MessageHandler}, - api::{bootloader::Config, Issue}, + api::bootloader::Config, issue, }; use async_trait::async_trait; @@ -45,7 +45,6 @@ pub enum Error { pub struct Starter { connection: zbus::Connection, client: Option>, - issues: Handler, } impl Starter { @@ -53,11 +52,10 @@ impl Starter { /// /// * `connection`: connection to the D-Bus. /// * `issues`: handler to the issues service. - pub fn new(connection: zbus::Connection, issues: Handler) -> Self { + pub fn new(connection: zbus::Connection, _issues: Handler) -> Self { Self { connection, client: None, - issues, } } @@ -73,10 +71,7 @@ impl Starter { Some(client) => client, None => Box::new(Client::new(self.connection.clone()).await?), }; - let service = Service { - client: client, - issues: self.issues, - }; + let service = Service { client }; let handler = actor::spawn(service); Ok(handler) } @@ -87,19 +82,12 @@ impl Starter { /// It is responsible for handling the bootloader configuration. pub struct Service { client: Box, - issues: Handler, } impl Service { pub fn starter(connection: zbus::Connection, issues: Handler) -> Starter { Starter::new(connection, issues) } - - /// Returns configuration issues. - fn find_issues(&self) -> Vec { - // TODO: get issues from bootloader proposal - vec![] - } } impl Actor for Service { diff --git a/rust/agama-bootloader/src/test_utils.rs b/rust/agama-bootloader/src/test_utils.rs index f0ddb0c9e5..42aabd413a 100644 --- a/rust/agama-bootloader/src/test_utils.rs +++ b/rust/agama-bootloader/src/test_utils.rs @@ -57,13 +57,19 @@ pub struct TestClient { state: Arc>, } -impl TestClient { - pub fn new() -> Self { +impl Default for TestClient { + fn default() -> Self { let state = TestClientState::default(); Self { state: Arc::new(Mutex::new(state)), } } +} + +impl TestClient { + pub fn new() -> Self { + Self::default() + } pub async fn state(&self) -> TestClientState { self.state.lock().await.clone() diff --git a/rust/agama-cli/src/auth_tokens_file.rs b/rust/agama-cli/src/auth_tokens_file.rs index b91efa5124..dc950c4c0f 100644 --- a/rust/agama-cli/src/auth_tokens_file.rs +++ b/rust/agama-cli/src/auth_tokens_file.rs @@ -43,10 +43,7 @@ impl AuthTokensFile { /// Default path for the tokens file in user's home directory. pub fn default_path() -> io::Result { let Some(path) = home::home_dir() else { - return Err(io::Error::new( - io::ErrorKind::Other, - "Cannot find the user's home directory", - )); + return Err(io::Error::other("Cannot find the user's home directory")); }; Ok(path.join(AUTH_TOKENS_FILE)) @@ -141,7 +138,7 @@ mod tests { #[test] fn test_remove_host() { let path = Path::new("tests/tokens.json"); - let mut file = AuthTokensFile::read_from_path(&path).unwrap(); + let mut file = AuthTokensFile::read_from_path(path).unwrap(); assert!(file.get_token("my-server.lan").is_some()); file.remove_host("my-server.lan"); diff --git a/rust/agama-cli/src/config.rs b/rust/agama-cli/src/config.rs index fda210caa2..72b20469ac 100644 --- a/rust/agama-cli/src/config.rs +++ b/rust/agama-cli/src/config.rs @@ -367,7 +367,7 @@ async fn edit( // FIXME: invalid profile still gets loaded let updated = std::fs::read_to_string(&path).context(format!("Reading from file {:?}", path))?; - validate(&http_client, CliInput::Full(updated.clone()), false).await?; + validate(http_client, CliInput::Full(updated.clone()), false).await?; return Ok(serde_json::from_str(&updated)?); } @@ -397,7 +397,7 @@ async fn monitor_progress(monitor: MonitorClient) -> anyhow::Result<()> { let task = tokio::spawn(async move { show_progress(monitor, true).await; }); - let _ = task.await?; + task.await?; Ok(()) } diff --git a/rust/agama-cli/src/lib.rs b/rust/agama-cli/src/lib.rs index 3a1137b6f3..4c78ad7d3b 100644 --- a/rust/agama-cli/src/lib.rs +++ b/rust/agama-cli/src/lib.rs @@ -205,7 +205,7 @@ async fn build_http_client( if let Some(token) = find_client_token(&client.base_url) { return Ok(client.authenticated(&token)?); } - return Err(ServiceError::NotAuthenticated.into()); + Err(ServiceError::NotAuthenticated.into()) } else { Ok(client.unauthenticated()?) } @@ -233,7 +233,7 @@ async fn build_ws_client(api_url: Url, insecure: bool) -> anyhow::Result anyhow::Result { let sanitized_host = host.trim_end_matches('/').to_string(); diff --git a/rust/agama-cli/src/progress.rs b/rust/agama-cli/src/progress.rs index d9b42ba9a3..a442639c02 100644 --- a/rust/agama-cli/src/progress.rs +++ b/rust/agama-cli/src/progress.rs @@ -82,9 +82,9 @@ impl ProgressMonitor { // and finish all that no longer have progress let mut to_remove = vec![]; for (scope, bar) in &bars { - if !active_scopes.contains(&scope) { + if !active_scopes.contains(scope) { bar.finish_with_message("done"); - to_remove.push(scope.clone()); + to_remove.push(*scope); } } for scope in to_remove { diff --git a/rust/agama-cli/src/questions.rs b/rust/agama-cli/src/questions.rs index 311c3b2f3f..1bae922bb9 100644 --- a/rust/agama-cli/src/questions.rs +++ b/rust/agama-cli/src/questions.rs @@ -80,7 +80,7 @@ struct AnswersWrapper { } async fn set_answers(client: HTTPClient, path: &str) -> anyhow::Result<()> { - let file = File::open(&path)?; + let file = File::open(path)?; let reader = BufReader::new(file); let wrapper: AnswersWrapper = serde_json::from_reader(reader)?; client.set_answers(wrapper.answers).await?; diff --git a/rust/agama-files/src/lib.rs b/rust/agama-files/src/lib.rs index 96a62ffc85..e2598e77fc 100644 --- a/rust/agama-files/src/lib.rs +++ b/rust/agama-files/src/lib.rs @@ -99,7 +99,7 @@ mod tests { .call(message::RunScripts::new(ScriptsGroup::Pre)) .await .unwrap(); - assert_eq!(ran, false); + assert!(!ran); let test_file_1 = ctx.tmp_dir.path().join("file-1.txt"); let test_file_2 = ctx.tmp_dir.path().join("file-2.txt"); @@ -130,7 +130,7 @@ mod tests { .call(message::RunScripts::new(ScriptsGroup::Pre)) .await .unwrap(); - assert_eq!(ran, true); + assert!(ran); // Wait until the scripts are executed. while let Ok(event) = ctx.events_rx.recv().await { @@ -150,7 +150,7 @@ mod tests { let config = r#"{ "files": [{ "destination": "/etc/README.md", "content": "Some text" }] }"#; - let config: Config = serde_json::from_str(&config).unwrap(); + let config: Config = serde_json::from_str(config).unwrap(); ctx.handler .call(message::SetConfig::with(config)) .await diff --git a/rust/agama-files/src/runner.rs b/rust/agama-files/src/runner.rs index 7dff2cbe48..66a768ed0d 100644 --- a/rust/agama-files/src/runner.rs +++ b/rust/agama-files/src/runner.rs @@ -94,7 +94,7 @@ impl ScriptsRunner { /// /// * `scripts`: scripts to run. pub async fn run(&self, scripts: &[&Script]) -> Result<(), Error> { - let scripts: Vec<_> = self.find_scripts_to_run(&scripts); + let scripts: Vec<_> = self.find_scripts_to_run(scripts); self.start_progress(&scripts); let mut resolv_linked = false; @@ -130,7 +130,7 @@ impl ScriptsRunner { return Ok(()); }; - if !self.should_retry(&script, error).await? { + if !self.should_retry(script, error).await? { return Ok(()); } } @@ -157,7 +157,7 @@ impl ScriptsRunner { } let answer = ask_question(&self.questions, question).await?; - return Ok(answer.action == "Yes"); + Ok(answer.action == "Yes") } /// Runs the script at the given path. @@ -218,7 +218,7 @@ impl ScriptsRunner { /// It exclues any script that already ran. fn find_scripts_to_run<'a>(&self, scripts: &[&'a Script]) -> Vec<&'a Script> { scripts - .into_iter() + .iter() .filter(|s| { let stdout_file = self .workdir @@ -353,7 +353,7 @@ mod tests { chroot: Some(chroot), }); script - .write(&self.scripts_dir()) + .write(self.scripts_dir()) .expect("Could not write the script"); script } diff --git a/rust/agama-files/src/service.rs b/rust/agama-files/src/service.rs index c432b6664e..b632e61f53 100644 --- a/rust/agama-files/src/service.rs +++ b/rust/agama-files/src/service.rs @@ -45,11 +45,17 @@ pub enum Error { #[error(transparent)] Scripts(#[from] scripts::Error), #[error(transparent)] - Software(#[from] software::service::Error), + Software(Box), #[error(transparent)] Actor(#[from] actor::Error), } +impl From for Error { + fn from(error: software::service::Error) -> Self { + Self::Software(Box::new(error)) + } +} + const DEFAULT_SCRIPTS_DIR: &str = "run/agama/scripts"; const DEFAULT_WORK_DIR: &str = "/"; const DEFAULT_INSTALL_DIR: &str = "/mnt"; @@ -168,8 +174,7 @@ impl Service { } packages.push(Resolvable::new("agama-scripts", ResolvableType::Package)); } - _ = self - .software + self.software .call(agama_software::message::SetResolvables::new( "agama-scripts".to_string(), packages, diff --git a/rust/agama-hostname/src/lib.rs b/rust/agama-hostname/src/lib.rs index a4a09b8c4f..89b906666c 100644 --- a/rust/agama-hostname/src/lib.rs +++ b/rust/agama-hostname/src/lib.rs @@ -56,7 +56,6 @@ mod tests { struct Context { events_rx: broadcast::Receiver, handler: Handler, - issues: Handler, } impl AsyncTestContext for Context { @@ -66,11 +65,7 @@ mod tests { let handler = start_service(events_tx, issues.clone()).await; - Self { - events_rx, - handler, - issues, - } + Self { events_rx, handler } } } diff --git a/rust/agama-hostname/src/model.rs b/rust/agama-hostname/src/model.rs index 1f6fca0ed3..0907c3e8f5 100644 --- a/rust/agama-hostname/src/model.rs +++ b/rust/agama-hostname/src/model.rs @@ -33,7 +33,7 @@ pub trait ModelAdapter: Send + 'static { let name = self.static_hostname()?; Ok(SystemInfo { - r#static: (!name.is_empty()).then(|| name), + r#static: (!name.is_empty()).then_some(name), hostname: self.hostname()?, }) } diff --git a/rust/agama-iscsi/src/monitor.rs b/rust/agama-iscsi/src/monitor.rs index 02ea533836..1f07985251 100644 --- a/rust/agama-iscsi/src/monitor.rs +++ b/rust/agama-iscsi/src/monitor.rs @@ -31,7 +31,6 @@ use agama_utils::{ progress, }; use serde::Deserialize; -use serde_json; use tokio::sync::broadcast; use tokio_stream::StreamExt; use zbus::{message, Connection, MatchRule, MessageStream}; diff --git a/rust/agama-iscsi/src/test_utils.rs b/rust/agama-iscsi/src/test_utils.rs index 0640606d3e..d1eb265cd9 100644 --- a/rust/agama-iscsi/src/test_utils.rs +++ b/rust/agama-iscsi/src/test_utils.rs @@ -68,13 +68,19 @@ pub struct TestClient { state: Arc>, } -impl TestClient { - pub fn new() -> Self { +impl Default for TestClient { + fn default() -> Self { let state = TestClientState::default(); Self { state: Arc::new(Mutex::new(state)), } } +} + +impl TestClient { + pub fn new() -> Self { + Self::default() + } pub async fn state(&self) -> TestClientState { self.state.lock().await.clone() diff --git a/rust/agama-l10n/src/lib.rs b/rust/agama-l10n/src/lib.rs index c8885f69c0..9a1b4a08ee 100644 --- a/rust/agama-l10n/src/lib.rs +++ b/rust/agama-l10n/src/lib.rs @@ -207,7 +207,7 @@ mod tests { locale: Some("xx_XX.UTF-8".to_string()), timezone: Some("Unknown/Unknown".to_string()), }; - let _ = ctx.handler.call(message::SetConfig::with(config)).await?; + ctx.handler.call(message::SetConfig::with(config)).await?; let found_issues = ctx.issues.call(issue::message::Get).await?; let l10n_issues = found_issues.get(&Scope::L10n).unwrap(); diff --git a/rust/agama-l10n/src/model.rs b/rust/agama-l10n/src/model.rs index 49799eb42a..59c959cbd8 100644 --- a/rust/agama-l10n/src/model.rs +++ b/rust/agama-l10n/src/model.rs @@ -218,7 +218,7 @@ impl ModelAdapter for Model { // unfortunately the console font cannot be set via the "systemd-firstboot" tool, // we need to write it directly to the config file - if let Some(entry) = self.locales_db.find_locale(&locale) { + if let Some(entry) = self.locales_db.find_locale(locale) { if let Some(font) = &entry.consolefont { // the font entry is missing in a file created by "systemd-firstboot", just append it at the end let mut file = OpenOptions::new() diff --git a/rust/agama-l10n/src/model/keyboard.rs b/rust/agama-l10n/src/model/keyboard.rs index 908702b75c..edba9e1530 100644 --- a/rust/agama-l10n/src/model/keyboard.rs +++ b/rust/agama-l10n/src/model/keyboard.rs @@ -67,27 +67,6 @@ impl KeymapsDatabase { } } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_sorting_keymaps() { - let entries = vec![ - Keymap::new("es".parse().unwrap(), "Spanish"), - Keymap::new("us".parse().unwrap(), "English (US)"), - Keymap::new("de".parse().unwrap(), "German"), - ]; - - let db = KeymapsDatabase::with_entries(&entries); - let keymaps = db.entries(); - - assert_eq!(keymaps[0].description.to_string(), "English (US)"); - assert_eq!(keymaps[1].description.to_string(), "German"); - assert_eq!(keymaps[2].description.to_string(), "Spanish"); - } -} - /// Returns the list of keymaps to offer. /// /// It only includes the keyboards supported by `localectl` but getting @@ -126,3 +105,24 @@ fn get_keymap_descriptions() -> HashMap { keymaps } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sorting_keymaps() { + let entries = vec![ + Keymap::new("es".parse().unwrap(), "Spanish"), + Keymap::new("us".parse().unwrap(), "English (US)"), + Keymap::new("de".parse().unwrap(), "German"), + ]; + + let db = KeymapsDatabase::with_entries(&entries); + let keymaps = db.entries(); + + assert_eq!(keymaps[0].description.to_string(), "English (US)"); + assert_eq!(keymaps[1].description.to_string(), "German"); + assert_eq!(keymaps[2].description.to_string(), "Spanish"); + } +} diff --git a/rust/agama-lib/src/auth.rs b/rust/agama-lib/src/auth.rs index b6e972a358..71631bd7d0 100644 --- a/rust/agama-lib/src/auth.rs +++ b/rust/agama-lib/src/auth.rs @@ -174,10 +174,7 @@ impl AuthToken { fn user_token_path() -> io::Result { let Some(path) = home::home_dir() else { - return Err(io::Error::new( - io::ErrorKind::Other, - "Cannot find the user's home directory", - )); + return Err(io::Error::other("Cannot find the user's home directory")); }; Ok(path.join(USER_TOKEN_PATH)) @@ -219,6 +216,12 @@ impl Default for TokenClaims { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct ClientId(Uuid); +impl Default for ClientId { + fn default() -> Self { + Self::new() + } +} + impl ClientId { pub fn new() -> Self { ClientId(Uuid::new_v4()) diff --git a/rust/agama-lib/src/http/base_http_client.rs b/rust/agama-lib/src/http/base_http_client.rs index 1ceb64fa03..cda0088fa6 100644 --- a/rust/agama-lib/src/http/base_http_client.rs +++ b/rust/agama-lib/src/http/base_http_client.rs @@ -154,7 +154,7 @@ impl BaseHTTPClient { pub async fn post( &self, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result where T: DeserializeOwned, @@ -174,7 +174,7 @@ impl BaseHTTPClient { pub async fn post_void( &self, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result<(), BaseHTTPClientError> { let response = self .request_response(reqwest::Method::POST, path, object) @@ -191,7 +191,7 @@ impl BaseHTTPClient { pub async fn put( &self, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result where T: DeserializeOwned, @@ -211,7 +211,7 @@ impl BaseHTTPClient { pub async fn put_void( &self, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result<(), BaseHTTPClientError> { let response = self .request_response(reqwest::Method::PUT, path, object) @@ -228,7 +228,7 @@ impl BaseHTTPClient { pub async fn patch( &self, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result where T: DeserializeOwned, @@ -242,7 +242,7 @@ impl BaseHTTPClient { pub async fn patch_void( &self, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result<(), BaseHTTPClientError> { let response = self .request_response(reqwest::Method::PATCH, path, object) @@ -298,7 +298,7 @@ impl BaseHTTPClient { &self, method: reqwest::Method, path: &str, - object: &impl Serialize, + object: &(impl Serialize + ?Sized), ) -> Result { self.client .request(method, self.url(path)?) diff --git a/rust/agama-lib/src/http/websocket.rs b/rust/agama-lib/src/http/websocket.rs index c32aa094d8..5f82280dee 100644 --- a/rust/agama-lib/src/http/websocket.rs +++ b/rust/agama-lib/src/http/websocket.rs @@ -79,7 +79,7 @@ impl WebSocketClient { .danger_accept_invalid_certs(insecure) .danger_accept_invalid_hostnames(insecure) .build()?; - let tls_connector: native_tls::TlsConnector = tls_connector.into(); + let tls_connector: native_tls::TlsConnector = tls_connector; let connector = Connector::NativeTls(tls_connector); let uri: Uri = url.as_str().parse()?; diff --git a/rust/agama-lib/src/logs.rs b/rust/agama-lib/src/logs.rs index 300ffdae91..6fe4368d01 100644 --- a/rust/agama-lib/src/logs.rs +++ b/rust/agama-lib/src/logs.rs @@ -148,7 +148,7 @@ impl LogItem for LogPath { let options = CopyOptions::new(); copy_items(&[self.src_path.as_str()], dst_path, &options) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "Copying of a file failed"))?; + .map_err(|_| io::Error::other("Copying of a file failed"))?; if let Some(name) = dst_file.file_name().and_then(|fname| fname.to_str()) { let dst_name = name.trim_start_matches("."); @@ -256,10 +256,7 @@ fn compress_logs(tmp_dir: &TempDir, result: &String) -> io::Result<()> { if res.success() { set_archive_permissions(PathBuf::from(result)) } else { - Err(io::Error::new( - io::ErrorKind::Other, - "Cannot create tar archive", - )) + Err(io::Error::other("Cannot create tar archive")) } } diff --git a/rust/agama-lib/src/network/store.rs b/rust/agama-lib/src/network/store.rs index 9527d212fd..dcc2fecfe8 100644 --- a/rust/agama-lib/src/network/store.rs +++ b/rust/agama-lib/src/network/store.rs @@ -48,10 +48,7 @@ impl NetworkStore { pub async fn load(&self) -> NetworkStoreResult { let connections = NetworkConnectionsCollection(self.network_client.connections().await?); - Ok(NetworkSettings { - connections, - ..Default::default() - }) + Ok(NetworkSettings { connections }) } pub async fn store(&self, settings: &NetworkSettings) -> NetworkStoreResult<()> { diff --git a/rust/agama-lib/src/questions/http_client.rs b/rust/agama-lib/src/questions/http_client.rs index 26ce6745e9..8403100121 100644 --- a/rust/agama-lib/src/questions/http_client.rs +++ b/rust/agama-lib/src/questions/http_client.rs @@ -103,7 +103,7 @@ impl HTTPClient { let patch = Patch::with_update(&config)?; - _ = self.client.patch_void("/v2/config", &patch).await?; + self.client.patch_void("/v2/config", &patch).await?; Ok(()) } diff --git a/rust/agama-lib/src/storage/client/dasd.rs b/rust/agama-lib/src/storage/client/dasd.rs index 940e45d2b1..d448d8b4e6 100644 --- a/rust/agama-lib/src/storage/client/dasd.rs +++ b/rust/agama-lib/src/storage/client/dasd.rs @@ -100,7 +100,7 @@ impl<'a> DASDClient<'a> { let pairs = self.config_pairs(config).await?; let to_activate: Vec<&str> = pairs .iter() - .filter(|(system, _config)| system.enabled == false) + .filter(|(system, _config)| !system.enabled) .filter(|(_system, config)| config.state.unwrap_or_default() == DASDDeviceState::Active) .map(|(system, _config)| system.id.as_str()) .collect(); @@ -108,7 +108,7 @@ impl<'a> DASDClient<'a> { let to_deactivate: Vec<&str> = pairs .iter() - .filter(|(system, _config)| system.enabled == true) + .filter(|(system, _config)| system.enabled) .filter(|(_system, config)| config.state == Some(DASDDeviceState::Offline)) .map(|(system, _config)| system.id.as_str()) .collect(); @@ -129,7 +129,7 @@ impl<'a> DASDClient<'a> { .filter(|(system, config)| { if config.format == Some(true) { true - } else if config.format == None { + } else if config.format.is_none() { !system.formatted } else { false diff --git a/rust/agama-lib/src/storage/client/iscsi.rs b/rust/agama-lib/src/storage/client/iscsi.rs index 01cb4dfa4c..691ea5a2b2 100644 --- a/rust/agama-lib/src/storage/client/iscsi.rs +++ b/rust/agama-lib/src/storage/client/iscsi.rs @@ -163,7 +163,7 @@ impl<'a> ISCSIClient<'a> { /// * `address`: target address in string-like form. /// * `port`: target port. /// * `auth`: authentication options. - pub async fn discover<'b>( + pub async fn discover( &self, address: &str, port: u32, diff --git a/rust/agama-lib/src/storage/client/zfcp.rs b/rust/agama-lib/src/storage/client/zfcp.rs index 63ad9c27b6..d1b8e64a38 100644 --- a/rust/agama-lib/src/storage/client/zfcp.rs +++ b/rust/agama-lib/src/storage/client/zfcp.rs @@ -244,7 +244,7 @@ impl<'a> ZFCPClient<'a> { let id = channel_mapping .get(&dev.channel) .ok_or_else(|| ServiceError::ZFCPControllerNotFound(dev.channel.clone()))?; - self.activate_disk(&id, &dev.wwpn, &dev.lun).await?; + self.activate_disk(id, &dev.wwpn, &dev.lun).await?; } Ok(()) diff --git a/rust/agama-lib/src/storage/http_client/iscsi.rs b/rust/agama-lib/src/storage/http_client/iscsi.rs index 58aebd2c09..ef11ddfb30 100644 --- a/rust/agama-lib/src/storage/http_client/iscsi.rs +++ b/rust/agama-lib/src/storage/http_client/iscsi.rs @@ -48,7 +48,7 @@ impl ISCSIHTTPClient { Ok(None) } - pub async fn set_config(&self, config: &Box) -> Result<(), ISCSIHTTPClientError> { + pub async fn set_config(&self, config: &RawValue) -> Result<(), ISCSIHTTPClientError> { Ok(self.client.post_void("/iscsi/config", config).await?) } } diff --git a/rust/agama-lib/src/store.rs b/rust/agama-lib/src/store.rs index 4b8bfe28fd..7f2c5538d5 100644 --- a/rust/agama-lib/src/store.rs +++ b/rust/agama-lib/src/store.rs @@ -42,7 +42,7 @@ use crate::{ #[derive(Debug, thiserror::Error)] pub enum StoreError { #[error(transparent)] - DASD(#[from] DASDStoreError), + Dasd(#[from] DASDStoreError), #[error(transparent)] Hostname(#[from] HostnameStoreError), #[error(transparent)] @@ -50,9 +50,9 @@ pub enum StoreError { #[error(transparent)] Storage(#[from] StorageStoreError), #[error(transparent)] - ISCSI(#[from] ISCSIHTTPClientError), + Iscsi(#[from] ISCSIHTTPClientError), #[error(transparent)] - ZFCP(#[from] ZFCPStoreError), + Zfcp(#[from] ZFCPStoreError), #[error("Could not calculate the context")] InvalidStoreContext, } diff --git a/rust/agama-manager/src/hardware.rs b/rust/agama-manager/src/hardware.rs index 3db3a57aff..9d1a1c9d18 100644 --- a/rust/agama-manager/src/hardware.rs +++ b/rust/agama-manager/src/hardware.rs @@ -143,7 +143,7 @@ impl HardwareNode { /// /// * `json`: JSON string reference. fn from_json(json: &str) -> Result { - let node = serde_json::from_str(&json).map_err(|error| Error::Parse { + let node = serde_json::from_str(json).map_err(|error| Error::Parse { json: json.to_string(), source: error, })?; @@ -158,7 +158,7 @@ impl HardwareNode { /// * `id`: id to search for (e.g., "cpu", "memory", etc.). pub fn find_by_id(&self, id: &str) -> Option<&HardwareNode> { if self.id == id { - return Some(&self); + return Some(self); } for children in &self.children { @@ -184,7 +184,7 @@ impl HardwareNode { fn search_by_class<'a>(&'a self, class: &str, results: &mut Vec<&'a HardwareNode>) { if self.class == class { - results.push(&self); + results.push(self); } for children in &self.children { @@ -282,7 +282,7 @@ mod tests { #[tokio::test] async fn test_to_hardware_info() -> Result<(), Box> { let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); - let mut registry = Registry::new_from_file(&fixtures.join("lshw.json")); + let mut registry = Registry::new_from_file(fixtures.join("lshw.json")); registry.read().await?; let node = registry.to_hardware_info(); assert_eq!( @@ -297,7 +297,7 @@ mod tests { #[tokio::test] async fn test_to_hardware_info_qemu() -> Result<(), Box> { let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); - let mut registry = Registry::new_from_file(&fixtures.join("lshw-qemu.json")); + let mut registry = Registry::new_from_file(fixtures.join("lshw-qemu.json")); registry.read().await?; let node = registry.to_hardware_info(); assert_eq!( @@ -326,7 +326,7 @@ mod tests { #[tokio::test] async fn test_to_hardware_incomplete() -> Result<(), Box> { let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../test/share"); - let mut registry = Registry::new_from_file(&fixtures.join("lshw-incomplete.json")); + let mut registry = Registry::new_from_file(fixtures.join("lshw-incomplete.json")); registry.read().await?; let node = registry.to_hardware_info(); assert_eq!(node.cpu, None); diff --git a/rust/agama-manager/src/service.rs b/rust/agama-manager/src/service.rs index 980f87e127..1991603dde 100644 --- a/rust/agama-manager/src/service.rs +++ b/rust/agama-manager/src/service.rs @@ -60,11 +60,11 @@ pub enum Error { #[error(transparent)] Security(#[from] security::service::Error), #[error(transparent)] - Software(#[from] software::service::Error), + Software(Box), #[error(transparent)] Storage(#[from] storage::service::Error), #[error(transparent)] - Files(#[from] files::service::Error), + Files(Box), #[error(transparent)] Issues(#[from] issue::service::Error), #[error(transparent)] @@ -99,6 +99,18 @@ pub enum Error { S390(#[from] s390::service::Error), } +impl From for Error { + fn from(error: software::service::Error) -> Self { + Self::Software(Box::new(error)) + } +} + +impl From for Error { + fn from(error: files::service::Error) -> Self { + Self::Files(Box::new(error)) + } +} + pub struct Starter { questions: Handler, events: event::Sender, @@ -545,9 +557,9 @@ impl Service { if let Some(product) = product { if let Some(id) = &product.id { - let mode = product.mode.as_ref().map(|m| m.as_str()); + let mode = product.mode.as_deref(); tracing::debug!("Setting product and mode to {} and {:?}", id, mode); - let product_spec = self.products.find(&id, mode)?; + let product_spec = self.products.find(id, mode)?; let product = RwLock::new(product_spec.clone()); self.product = Some(Arc::new(product)); } @@ -591,7 +603,7 @@ impl Service { }; let mut software_config = self.config.software.clone().unwrap_or_default(); - let product_config = software_config.product.get_or_insert_default(); + let product_config = software_config.product.get_or_insert_with(Default::default); let product = product.read().await; product_config.id = Some(product.id.clone()); product_config.mode = product.mode.clone(); @@ -836,8 +848,10 @@ impl MessageHandler for Service { .storage .call(storage::message::GetConfigFromModel::new(message.model)) .await?; - let mut config = Config::default(); - config.storage = storage; + let config = Config { + storage, + ..Default::default() + }; self.update_config(config).await } } diff --git a/rust/agama-network/src/model.rs b/rust/agama-network/src/model.rs index 62297f565d..4565ce5ca6 100644 --- a/rust/agama-network/src/model.rs +++ b/rust/agama-network/src/model.rs @@ -750,10 +750,7 @@ impl TryFrom for Connection { } if let Some(mac) = conn.mac_address { - connection.mac_address = match MacAddr6::from_str(mac.as_str()) { - Ok(mac) => Some(mac), - Err(_) => None, - } + connection.mac_address = MacAddr6::from_str(mac.as_str()).ok(); } connection.ip_config.addresses = conn.addresses; @@ -776,7 +773,7 @@ impl TryFrom for NetworkConnection { let custom_mac = conn.custom_mac_address.to_string(); let method4 = Some(conn.ip_config.method4.to_string()); let method6 = Some(conn.ip_config.method6.to_string()); - let mac_address = conn.mac_address.and_then(|mac| Some(mac.to_string())); + let mac_address = conn.mac_address.map(|mac| mac.to_string()); let custom_mac_address = (!custom_mac.is_empty()).then_some(custom_mac); let nameservers = conn.ip_config.nameservers; let dns_searchlist = conn.ip_config.dns_searchlist; diff --git a/rust/agama-network/src/nm/client.rs b/rust/agama-network/src/nm/client.rs index 38678a4140..8e700735ce 100644 --- a/rust/agama-network/src/nm/client.rs +++ b/rust/agama-network/src/nm/client.rs @@ -41,7 +41,6 @@ use crate::types::{AccessPoint, AddFlags, ConnectionFlags, Device, DeviceType, U use agama_utils::dbus::get_optional_property; use semver::Version; use uuid::Uuid; -use zbus; use zbus::zvariant::{ObjectPath, OwnedObjectPath}; /// Simplified NetworkManager D-Bus client. @@ -101,14 +100,13 @@ impl<'a> NetworkManagerClient<'a> { if let Err(error) = fs::remove_file(not_copy_path) { tracing::error!("Cannot remove {} file {:?}", NOT_COPY_NETWORK_PATH, error); } - } else { - if let Err(error) = OpenOptions::new() - .create(true) - .write(true) - .open(not_copy_path) - { - tracing::error!("Cannot write {} file {:?}", NOT_COPY_NETWORK_PATH, error); - } + } else if let Err(error) = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(not_copy_path) + { + tracing::error!("Cannot write {} file {:?}", NOT_COPY_NETWORK_PATH, error); }; }; @@ -230,9 +228,7 @@ impl<'a> NetworkManagerClient<'a> { match connection_from_dbus(settings) { Ok(mut connection) => { - let state = states - .get(&connection.id) - .map(|s| NmConnectionState(s.clone())); + let state = states.get(&connection.id).map(|s| NmConnectionState(*s)); if let Some(state) = state { connection.state = state.try_into().unwrap_or_default(); } @@ -356,11 +352,9 @@ impl<'a> NetworkManagerClient<'a> { tracing::info!("Activating connection {}", &conn.id); self.activate_connection(path).await?; - } else { - if conn.is_down() || conn.is_removed() { - tracing::info!("Deactivating connection {}", &conn.id); - self.deactivate_connection(path).await?; - } + } else if conn.is_down() || conn.is_removed() { + tracing::info!("Deactivating connection {}", &conn.id); + self.deactivate_connection(path).await?; } Ok(()) } @@ -539,7 +533,7 @@ impl<'a> NetworkManagerClient<'a> { match proxy.get_secrets("802-11-wireless-security").await { Ok(secrets) => { if let Some(secret) = secrets.get("802-11-wireless-security") { - wireless.password = get_optional_property(&secret, "psk")?; + wireless.password = get_optional_property(secret, "psk")?; } } Err(_) => { diff --git a/rust/agama-network/src/nm/proxies.rs b/rust/agama-network/src/nm/proxies.rs index f17d492f06..1ce18ffc21 100644 --- a/rust/agama-network/src/nm/proxies.rs +++ b/rust/agama-network/src/nm/proxies.rs @@ -852,6 +852,11 @@ pub trait IP4Config { fn wins_servers(&self) -> zbus::Result>; } +#[allow(dead_code)] +pub type IP6Address = (Vec, u32, Vec); +#[allow(dead_code)] +pub type IP6Route = (Vec, u32, Vec, u32); + #[proxy( interface = "org.freedesktop.NetworkManager.IP6Config", default_service = "org.freedesktop.NetworkManager", @@ -866,7 +871,7 @@ pub trait IP6Config { /// Addresses property #[zbus(property)] - fn addresses(&self) -> zbus::Result, u32, Vec)>>; + fn addresses(&self) -> zbus::Result>; /// DnsOptions property #[zbus(property)] @@ -896,7 +901,7 @@ pub trait IP6Config { /// Routes property #[zbus(property)] - fn routes(&self) -> zbus::Result, u32, Vec, u32)>>; + fn routes(&self) -> zbus::Result>; /// Searches property #[zbus(property)] diff --git a/rust/agama-network/src/nm/watcher.rs b/rust/agama-network/src/nm/watcher.rs index 141ca193e2..e12330befe 100644 --- a/rust/agama-network/src/nm/watcher.rs +++ b/rust/agama-network/src/nm/watcher.rs @@ -252,7 +252,7 @@ impl ActionDispatcher<'_> { ) -> Result<(), NmError> { let proxy = self.proxies.find_or_add_active_connection(&path).await?; let id = proxy.id().await?; - let state = proxy.state().await.map(|s| NmConnectionState(s.clone()))?; + let state = proxy.state().await.map(NmConnectionState)?; if let Ok(state) = state.try_into() { _ = self .actions_tx @@ -272,7 +272,7 @@ impl ActionDispatcher<'_> { ) -> Result<(), NmError> { if let Some(proxy) = self.proxies.remove_active_connection(&path) { let id = proxy.id().await?; - let state = proxy.state().await.map(|s| NmConnectionState(s.clone()))?; + let state = proxy.state().await.map(NmConnectionState)?; if let Ok(state) = state.try_into() { _ = self .actions_tx diff --git a/rust/agama-proxy/src/service.rs b/rust/agama-proxy/src/service.rs index b793a4630b..9f2520d2de 100644 --- a/rust/agama-proxy/src/service.rs +++ b/rust/agama-proxy/src/service.rs @@ -183,7 +183,7 @@ impl State { std::fs::create_dir_all(parent)?; } - proxy_config.write_to(&path)?; + proxy_config.write_to(path)?; self.load(true); Ok(()) } diff --git a/rust/agama-s390/src/test_utils.rs b/rust/agama-s390/src/test_utils.rs index 2b103252d2..bc3c8a4cab 100644 --- a/rust/agama-s390/src/test_utils.rs +++ b/rust/agama-s390/src/test_utils.rs @@ -63,13 +63,19 @@ pub struct TestDASDClient { state: Arc>, } -impl TestDASDClient { - pub fn new() -> Self { +impl Default for TestDASDClient { + fn default() -> Self { let state = TestDASDClientState::default(); Self { state: Arc::new(Mutex::new(state)), } } +} + +impl TestDASDClient { + pub fn new() -> Self { + Self::default() + } pub async fn state(&self) -> TestDASDClientState { self.state.lock().await.clone() diff --git a/rust/agama-security/src/certificate.rs b/rust/agama-security/src/certificate.rs index 22e9d2c5f2..8a9e419ecd 100644 --- a/rust/agama-security/src/certificate.rs +++ b/rust/agama-security/src/certificate.rs @@ -120,9 +120,7 @@ impl Certificate { /// * `name`: X509 names. /// * `nid`: entry identifier. fn extract_entry(name: &X509NameRef, nid: Nid) -> Option { - let Some(entry) = name.entries_by_nid(nid).next() else { - return None; - }; + let entry = name.entries_by_nid(nid).next()?; entry.data().as_utf8().map(|l| l.to_string()).ok() } diff --git a/rust/agama-security/src/message.rs b/rust/agama-security/src/message.rs index bbc75ac29b..3b6e33133a 100644 --- a/rust/agama-security/src/message.rs +++ b/rust/agama-security/src/message.rs @@ -53,7 +53,7 @@ impl CheckCertificate { /// /// * `certificate`: X509 certificate. /// * `name`: certificate name. It is used as the filename (without the extension) when - /// importing the certificate. + /// importing the certificate. pub fn new(certificate: X509, name: &str) -> Self { Self { certificate, diff --git a/rust/agama-security/src/service.rs b/rust/agama-security/src/service.rs index c16345bf4b..572509d5a7 100644 --- a/rust/agama-security/src/service.rs +++ b/rust/agama-security/src/service.rs @@ -68,8 +68,8 @@ impl Starter { self } - pub fn with_workdir(mut self, workdir: &PathBuf) -> Self { - self.workdir = workdir.clone(); + pub fn with_workdir(mut self, workdir: &Path) -> Self { + self.workdir = workdir.to_path_buf(); self } @@ -128,9 +128,7 @@ impl State { /// * `name`: certificate name (e.g., "registration_server") pub fn import(&mut self, certificate: &Certificate, name: &str) -> Result<(), Error> { let path = self.workdir.join(format!("{name}.pem")); - certificate - .import(&path) - .map_err(|e| Error::CertificateIO(e))?; + certificate.import(&path).map_err(Error::CertificateIO)?; self.imported.push(name.to_string()); Ok(()) } @@ -178,7 +176,7 @@ impl State { let output = process::Command::new("update-ca-certificates") .arg("--root") - .arg(&directory) + .arg(directory) .output()?; if !output.status.success() { diff --git a/rust/agama-server/src/profile/web.rs b/rust/agama-server/src/profile/web.rs index 109233f31f..219839b045 100644 --- a/rust/agama-server/src/profile/web.rs +++ b/rust/agama-server/src/profile/web.rs @@ -157,7 +157,7 @@ async fn validate(body: String) -> Result, ProfileServic let validator = ProfileValidator::default_schema().context("Setting up profile validator")?; let result = validator .validate_str(&profile_string) - .context(format!("Could not validate the profile")) + .context("Could not validate the profile".to_string()) .map_err(make_internal)?; Ok(Json(result)) diff --git a/rust/agama-server/src/server/web.rs b/rust/agama-server/src/server/web.rs index b69acf14a3..42d4e8ddaf 100644 --- a/rust/agama-server/src/server/web.rs +++ b/rust/agama-server/src/server/web.rs @@ -53,7 +53,7 @@ use tokio_util::io::ReaderStream; #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Manager(#[from] manager::service::Error), + Manager(Box), #[error(transparent)] Questions(#[from] question::service::Error), #[error(transparent)] @@ -62,6 +62,12 @@ pub enum Error { Json(#[from] serde_json::Error), } +impl From for Error { + fn from(error: manager::service::Error) -> Self { + Self::Manager(Box::new(error)) + } +} + impl IntoResponse for Error { fn into_response(self) -> Response { tracing::warn!("Server return error {}", self); @@ -72,8 +78,8 @@ impl IntoResponse for Error { let mut status = StatusCode::BAD_REQUEST; if let Error::Manager(error) = &self { - if matches!(error, ManagerError::PendingIssues { issues: _ }) - || matches!(error, ManagerError::Busy { scopes }) + if matches!(**error, ManagerError::PendingIssues { issues: _ }) + || matches!(**error, ManagerError::Busy { scopes: _ }) { status = StatusCode::UNPROCESSABLE_ENTITY; } diff --git a/rust/agama-server/src/web/service.rs b/rust/agama-server/src/web/service.rs index 8948b9103d..a97d39979e 100644 --- a/rust/agama-server/src/web/service.rs +++ b/rust/agama-server/src/web/service.rs @@ -20,7 +20,7 @@ use super::http::{login, login_from_query, logout, session}; use super::{config::ServiceConfig, state::ServiceState}; -use agama_lib::{auth::TokenClaims, http}; +use agama_lib::auth::TokenClaims; use agama_utils::api::event; use axum::http::HeaderValue; use axum::middleware::Next; diff --git a/rust/agama-server/src/web/ws.rs b/rust/agama-server/src/web/ws.rs index c822a6a6f8..507a438269 100644 --- a/rust/agama-server/src/web/ws.rs +++ b/rust/agama-server/src/web/ws.rs @@ -32,17 +32,6 @@ use axum::{ Extension, }; use std::sync::Arc; -use tokio::sync::broadcast; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Error serializing WebSocket message")] - Serialize(#[from] serde_json::Error), - #[error("Could not receive the event")] - RecvEvent(#[from] broadcast::error::RecvError), - #[error("Websocket closed")] - WebSocketClosed(#[from] axum::Error), -} pub async fn ws_handler( State(state): State, @@ -52,7 +41,7 @@ pub async fn ws_handler( ws.on_upgrade(move |socket| handle_socket(socket, state.events, client_id)) } -async fn handle_socket(mut socket: WebSocket, events: event::Sender, client_id: Arc) { +async fn handle_socket(mut socket: WebSocket, events: event::Sender, _client_id: Arc) { let mut events_rx = events.subscribe(); loop { diff --git a/rust/agama-software/src/model/conflict.rs b/rust/agama-software/src/model/conflict.rs index 05c3392051..99b101cfa2 100644 --- a/rust/agama-software/src/model/conflict.rs +++ b/rust/agama-software/src/model/conflict.rs @@ -35,29 +35,3 @@ impl From for (u32, u32) { (solve.conflict_id, solve.solution_id) } } - -/// Information about possible solution for conflict -#[derive(Clone, Debug, Serialize, Deserialize, utoipa::ToSchema)] -#[serde(rename_all = "camelCase")] -pub struct Solution { - /// conflict id - pub id: u32, - /// localized description of solution - pub description: String, - /// localized details about solution. Can be missing - pub details: Option, -} - -/// Information about conflict when resolving software -#[derive(Clone, Debug, Serialize, Deserialize, utoipa::ToSchema)] -#[serde(rename_all = "camelCase")] -pub struct Conflict { - /// conflict id - pub id: u32, - /// localized description of conflict - pub description: String, - /// localized details about conflict. Can be missing - pub details: Option, - /// list of possible solutions - pub solutions: Vec, -} diff --git a/rust/agama-software/src/model/registration.rs b/rust/agama-software/src/model/registration.rs index d6a07c5041..9c1c76edfc 100644 --- a/rust/agama-software/src/model/registration.rs +++ b/rust/agama-software/src/model/registration.rs @@ -93,8 +93,8 @@ impl Registration { ) -> RegistrationResult<()> { // Use the product's version as default. let version = addon.version.clone().unwrap_or(self.version.clone()); - let code = addon.code.as_ref().map(|c| c.as_str()); - self.activate_product(&zypp, &addon.id, &version, code)?; + let code = addon.code.as_deref(); + self.activate_product(zypp, &addon.id, &version, code)?; self.addons.push(addon.clone()); Ok(()) } @@ -124,11 +124,7 @@ impl Registration { let service = suseconnect_agama::activate_product( product, params, - self.connect_params - .email - .as_ref() - .map(|e| e.as_str()) - .unwrap_or(""), + self.connect_params.email.as_deref().unwrap_or(""), )?; if let Some(file) = Self::credentials_from_url(&service.url) { @@ -217,7 +213,7 @@ impl Registration { fn copy_files(&self, target_dir: &Utf8PathBuf) -> Result<(), RegistrationError> { for path in &self.config_files { let target_path = match path.strip_prefix(&self.root_dir) { - Ok(relative_path) => target_dir.join(&relative_path), + Ok(relative_path) => target_dir.join(relative_path), Err(_) => { let relative_path = path.strip_prefix("/").unwrap_or(path); target_dir.join(relative_path) @@ -348,12 +344,11 @@ impl RegistrationBuilder { email: self.email.clone(), language: "en-us".to_string().into(), url: self.url.clone(), - ..Default::default() }; // https://github.com/agama-project/agama/blob/master/service/lib/agama/registration.rb#L294 let version = self.version.split(".").next().unwrap_or("1"); let arch = Arch::current().expect("Failed to determine the architecture"); - let target_distro = format!("{}-{}-{}", &self.product, version, arch.to_string()); + let target_distro = format!("{}-{}-{}", &self.product, version, arch); tracing::debug!("Announcing system {target_distro}"); let creds = handle_registration_error( || suseconnect_agama::announce_system(params.clone(), &target_distro), @@ -414,7 +409,7 @@ where }) = &result { if code.is_fixable_by_import() { - let x509 = X509::from_pem(¤t_certificate.as_bytes()).unwrap(); + let x509 = X509::from_pem(current_certificate.as_bytes()).unwrap(); match should_trust_certificate(&x509, security_srv) { Ok(true) => { if let Err(error) = suseconnect_agama::reload_certificates() { diff --git a/rust/agama-software/src/model/state.rs b/rust/agama-software/src/model/state.rs index c97c473034..7a056e7f07 100644 --- a/rust/agama-software/src/model/state.rs +++ b/rust/agama-software/src/model/state.rs @@ -142,7 +142,7 @@ impl<'a> SoftwareStateBuilder<'a> { /// Builds the [SoftwareState] combining all the sources. pub fn build(self) -> SoftwareState { - let mut state = self.from_product_spec(); + let mut state = self.build_from_product_spec(); if let Some(system) = self.system { self.add_system_config(&mut state, system); @@ -329,7 +329,7 @@ impl<'a> SoftwareStateBuilder<'a> { } } - fn from_product_spec(&self) -> SoftwareState { + fn build_from_product_spec(&self) -> SoftwareState { let software = &self.product.software; let kernel_repos = self.kernel_cmdline.get_last("inst.install_url"); let repositories = if let Some(kernel_repos) = kernel_repos { @@ -340,7 +340,7 @@ impl<'a> SoftwareStateBuilder<'a> { let alias = format!("agama-{}", i); Repository { name: alias.clone(), - alias: alias, + alias, url: url.to_string(), enabled: true, } @@ -500,11 +500,11 @@ impl ResolvablesState { r#type: ResolvableType, selection: ResolvableSelection, ) { - if let Some(entry) = self.0.get(&(name.to_string(), r#type)) { - if let ResolvableSelection::AutoSelected { .. } = entry { - tracing::debug!("Could not modify the {name} state because it is auto selected."); - return; - } + if let Some(ResolvableSelection::AutoSelected { .. }) = + self.0.get(&(name.to_string(), r#type)) + { + tracing::debug!("Could not modify the {name} state because it is auto selected."); + return; } self.0.insert((name.to_string(), r#type), selection); } @@ -575,11 +575,10 @@ impl ResolvableSelection { } pub fn selected(&self) -> bool { - match self { - ResolvableSelection::Selected => true, - ResolvableSelection::AutoSelected { skip_if_missing: _ } => true, - _ => false, - } + matches!( + self, + ResolvableSelection::Selected | ResolvableSelection::AutoSelected { .. } + ) } } @@ -637,8 +636,8 @@ impl Addon { pub fn new(id: &str, version: Option, code: Option) -> Self { Addon { id: id.to_string(), - version: version, - code: code, + version, + code, } } } diff --git a/rust/agama-software/src/service.rs b/rust/agama-software/src/service.rs index 248d122330..fbd58f21c0 100644 --- a/rust/agama-software/src/service.rs +++ b/rust/agama-software/src/service.rs @@ -50,7 +50,7 @@ pub enum Error { #[error(transparent)] Actor(#[from] actor::Error), #[error("Failed to send message to libzypp thread: {0}")] - ZyppSender(#[from] tokio::sync::mpsc::error::SendError), + ZyppSender(Box>), #[error("Failed to receive result from libzypp thread: {0}")] ZyppReceiver(#[from] tokio::sync::oneshot::error::RecvError), #[error(transparent)] @@ -62,11 +62,23 @@ pub enum Error { #[error("There is no {0} product")] WrongProduct(String), #[error(transparent)] - ZyppServerError(#[from] zypp_server::ZyppServerError), + ZyppServerError(Box), #[error(transparent)] ZyppError(#[from] zypp_agama::errors::ZyppError), } +impl From> for Error { + fn from(error: tokio::sync::mpsc::error::SendError) -> Self { + Self::ZyppSender(Box::new(error)) + } +} + +impl From for Error { + fn from(error: zypp_server::ZyppServerError) -> Self { + Self::ZyppServerError(Box::new(error)) + } +} + /// Starts the software service. pub struct Starter { model: Option>>, @@ -321,8 +333,7 @@ impl Service { product.registration_url = self .kernel_cmdline .get_last("inst.register_url") - .map(|url| Url::parse(&url).ok()) - .flatten(); + .and_then(|url| Url::parse(&url).ok()); } /// Completes the configuration with the product mode if it is missing. @@ -471,7 +482,7 @@ fn find_repository(dir: &PathBuf, name: &str) -> Option { return None; } - let url_string = format!("dir:{}", dir.display().to_string()); + let url_string = format!("dir:{}", dir.display()); let Ok(url) = Url::parse(&url_string) else { tracing::warn!( "'{}' is not a valid URL. Ignoring the repository.", @@ -526,8 +537,8 @@ mod tests { #[test] fn test_find_mandatory_repositories() -> Result<(), Box> { let tmp_dir = TempDir::with_prefix("test")?; - std::fs::create_dir_all(&tmp_dir.path().join(LIVE_REPO_DIR))?; - std::fs::create_dir_all(&tmp_dir.path().join(DUD_REPO_DIR))?; + std::fs::create_dir_all(tmp_dir.path().join(LIVE_REPO_DIR))?; + std::fs::create_dir_all(tmp_dir.path().join(DUD_REPO_DIR))?; let tmp_dir_str = tmp_dir.as_ref().to_str().unwrap(); let repositories = find_mandatory_repositories(tmp_dir.as_ref()); diff --git a/rust/agama-software/src/zypp_server.rs b/rust/agama-software/src/zypp_server.rs index f52dd8a677..bf510f22a6 100644 --- a/rust/agama-software/src/zypp_server.rs +++ b/rust/agama-software/src/zypp_server.rs @@ -56,7 +56,7 @@ pub enum ZyppDispatchError { #[error(transparent)] Zypp(#[from] ZyppError), #[error("libzypp error: {0}")] - ZyppServer(#[from] ZyppServerError), + ZyppServer(Box), #[error("Response channel closed")] ResponseChannelClosed, #[error("Target creation failed: {0}")] @@ -65,6 +65,12 @@ pub enum ZyppDispatchError { Progress(#[from] progress::service::Error), } +impl From for ZyppDispatchError { + fn from(error: ZyppServerError) -> Self { + Self::ZyppServer(Box::new(error)) + } +} + #[derive(thiserror::Error, Debug)] pub enum ZyppServerError { #[error("Response channel closed")] @@ -74,7 +80,7 @@ pub enum ZyppServerError { RecvError(#[from] oneshot::error::RecvError), #[error("Sender error: {0}")] - SendError(#[from] mpsc::error::SendError), + SendError(Box>), #[error("Error from libzypp: {0}")] ZyppError(#[from] zypp_agama::ZyppError), @@ -89,6 +95,12 @@ pub enum ZyppServerError { IO(#[from] std::io::Error), } +impl From> for ZyppServerError { + fn from(error: mpsc::error::SendError) -> Self { + Self::SendError(Box::new(error)) + } +} + pub type ZyppServerResult = Result; pub enum SoftwareAction { @@ -117,7 +129,7 @@ pub enum SoftwareAction { pub enum RegistrationStatus { #[default] NotRegistered, - Registered(Registration), + Registered(Box), Failed(RegistrationError), } @@ -256,7 +268,7 @@ impl ZyppServer { "Starting packages installation", )); - zypp.switch_target(&self.install_dir.to_string())?; + zypp.switch_target(self.install_dir.as_ref())?; let result = zypp.commit( &mut download_callback, &mut install_callback, @@ -289,11 +301,12 @@ impl ZyppServer { Ok(state) } + #[allow(clippy::too_many_arguments)] fn write( &mut self, state: SoftwareState, progress: Handler, - questions: Handler, + _questions: Handler, security_srv: Handler, security: &mut callbacks::Security, tx: oneshot::Sender>>, @@ -318,7 +331,7 @@ impl ZyppServer { let old_state = self.read(zypp)?; if let Some(registration_config) = &state.registration { - self.update_registration(registration_config, &zypp, &security_srv, &mut issues); + self.update_registration(registration_config, zypp, &security_srv, &mut issues); } self.trusted_keys = state.trusted_gpg_keys; @@ -386,7 +399,7 @@ impl ZyppServer { ); if let Err(error) = result { - let message = format!("Could not read the repositories"); + let message = "Could not read the repositories".to_string(); issues.push( Issue::new("software.load_source", &message).with_details(&error.to_string()), ); @@ -418,7 +431,7 @@ impl ZyppServer { match selection { ResolvableSelection::AutoSelected { skip_if_missing } => { issues.append(&mut self.select_resolvable( - &zypp, + zypp, name, *r#type, zypp_agama::ResolvableSelected::Installation, @@ -427,7 +440,7 @@ impl ZyppServer { } ResolvableSelection::Selected => { issues.append(&mut self.select_resolvable( - &zypp, + zypp, name, *r#type, zypp_agama::ResolvableSelected::User, @@ -447,10 +460,9 @@ impl ZyppServer { // unselect packages including the autoselected dependencies for (name, r#type, selection) in &state.resolvables.to_vec() { - match selection { - ResolvableSelection::Removed => self.unselect_resolvable(&zypp, name, *r#type), - _ => {} - }; + if selection == &ResolvableSelection::Removed { + self.unselect_resolvable(zypp, name, *r#type) + } } _ = progress.cast(progress::message::Finish::new(Scope::Software)); @@ -509,13 +521,13 @@ impl ZyppServer { ) -> Result<(), ZyppDispatchError> { if let Err(error) = self.remove_dud_repo(zypp) { tracing::warn!("Failed to remove the DUD repository: {error}"); - tx.send(Err(error.into())) + tx.send(Err(error)) .map_err(|_| ZyppDispatchError::ResponseChannelClosed)?; return Ok(()); } if let Err(error) = self.disable_local_repos(zypp) { tracing::warn!("Failed to disable local repositories: {error}"); - tx.send(Err(error.into())) + tx.send(Err(error)) .map_err(|_| ZyppDispatchError::ResponseChannelClosed)?; return Ok(()); } @@ -525,13 +537,13 @@ impl ZyppServer { if let Err(error) = self.modify_full_repo(zypp) { tracing::warn!("Failed to modify the full repository: {error}"); - tx.send(Err(error.into())) + tx.send(Err(error)) .map_err(|_| ZyppDispatchError::ResponseChannelClosed)?; return Ok(()); } if let Err(error) = self.copy_files() { tracing::warn!("Failed to copy zypp files: {error}"); - tx.send(Err(error.into())) + tx.send(Err(error)) .map_err(|_| ZyppDispatchError::ResponseChannelClosed)?; return Ok(()); } @@ -775,8 +787,8 @@ impl ZyppServer { zypp: &zypp_agama::Zypp, ) -> Result<(), ZyppDispatchError> { let proposal = SoftwareProposal { - used_space: self.used_space(&zypp)?, - patterns: self.patterns_selection(&product, &zypp)?, + used_space: self.used_space(zypp)?, + patterns: self.patterns_selection(&product, zypp)?, }; tx.send(Ok(proposal)) @@ -874,9 +886,9 @@ impl ZyppServer { registration = registration.with_url(url); } - match registration.register(&zypp, security_srv) { + match registration.register(zypp, security_srv) { Ok(registration) => { - self.registration = RegistrationStatus::Registered(registration); + self.registration = RegistrationStatus::Registered(Box::new(registration)); } Err(error) => { issues.push( @@ -903,7 +915,7 @@ impl ZyppServer { }; for addon in addons { - if registration.is_addon_registered(&addon) { + if registration.is_addon_registered(addon) { tracing::info!("Skipping already registered add-on {}", &addon.id); continue; } diff --git a/rust/agama-software/tests/zypp_server.rs b/rust/agama-software/tests/zypp_server.rs index d13bba0104..98beaed2f6 100644 --- a/rust/agama-software/tests/zypp_server.rs +++ b/rust/agama-software/tests/zypp_server.rs @@ -36,7 +36,6 @@ use std::fs; use std::path::Path; use std::result::Result; use tokio::sync::{broadcast, oneshot}; -use tracing_subscriber; fn cleanup_past_leftovers(root_dir: &Path) { remove_repos(root_dir); @@ -68,7 +67,7 @@ async fn test_start_zypp_server() { let root_dir = Utf8Path::new(env!("CARGO_MANIFEST_DIR")).join("../zypp-agama/fixtures/zypp_repos_root"); - cleanup_past_leftovers(&root_dir.as_std_path()); + cleanup_past_leftovers(root_dir.as_std_path()); let zypp_root = Utf8Path::new(env!("CARGO_MANIFEST_DIR")).join("../zypp-agama/fixtures/zypp_root_tmp"); @@ -134,9 +133,8 @@ async fn test_start_zypp_server() { let result: ZyppServerResult> = rx.await.expect("Failed to receive response from server"); - assert_eq!( + assert!( result.is_ok(), - true, "SoftwareAction::Write failed: {:?}", result.unwrap_err() ); diff --git a/rust/agama-storage/src/monitor.rs b/rust/agama-storage/src/monitor.rs index d29ad3af78..7b98fcea09 100644 --- a/rust/agama-storage/src/monitor.rs +++ b/rust/agama-storage/src/monitor.rs @@ -28,7 +28,6 @@ use agama_utils::{ issue, progress, }; use serde::Deserialize; -use serde_json; use std::pin::Pin; use tokio::sync::broadcast; use tokio_stream::{Stream, StreamExt, StreamMap}; @@ -203,7 +202,7 @@ impl Monitor { let stream = proxy .receive_system_changed() .await? - .map(|signal| Signal::SystemChanged(signal)); + .map(Signal::SystemChanged); Ok(Box::pin(stream)) } @@ -214,7 +213,7 @@ impl Monitor { let stream = proxy .receive_proposal_changed() .await? - .map(|signal| Signal::ProposalChanged(signal)); + .map(Signal::ProposalChanged); Ok(Box::pin(stream)) } @@ -225,7 +224,7 @@ impl Monitor { let stream = proxy .receive_progress_changed() .await? - .map(|signal| Signal::ProgressChanged(signal)); + .map(Signal::ProgressChanged); Ok(Box::pin(stream)) } @@ -236,7 +235,7 @@ impl Monitor { let stream = proxy .receive_progress_finished() .await? - .map(|signal| Signal::ProgressFinished(signal)); + .map(Signal::ProgressFinished); Ok(Box::pin(stream)) } } diff --git a/rust/agama-storage/src/test_utils.rs b/rust/agama-storage/src/test_utils.rs index c8cacdbf59..726beb6d2e 100644 --- a/rust/agama-storage/src/test_utils.rs +++ b/rust/agama-storage/src/test_utils.rs @@ -70,13 +70,19 @@ pub struct TestClient { state: Arc>, } -impl TestClient { - pub fn new() -> Self { +impl Default for TestClient { + fn default() -> Self { let state = TestClientState::default(); Self { state: Arc::new(Mutex::new(state)), } } +} + +impl TestClient { + pub fn new() -> Self { + Self::default() + } pub async fn state(&self) -> TestClientState { self.state.lock().await.clone() diff --git a/rust/agama-transfer/src/file_finder.rs b/rust/agama-transfer/src/file_finder.rs index 832d4d2bfc..730b25b3b8 100644 --- a/rust/agama-transfer/src/file_finder.rs +++ b/rust/agama-transfer/src/file_finder.rs @@ -18,10 +18,7 @@ // To contact SUSE LLC about this file by physical or electronic mail, you may // find current contact information at www.suse.com. -use std::{ - io::Write, - path::{Path, PathBuf}, -}; +use std::{io::Write, path::Path}; use super::{ file_systems::{FileSystem, FileSystemsList}, @@ -65,7 +62,7 @@ impl FileFinder { ) -> TransferResult<()> { eprintln!("Searching {} in {}", &file_name, &file_system.block_device); - file_system.ensure_mounted(|mount_point: &PathBuf| { + file_system.ensure_mounted(|mount_point: &Path| { let file_name = file_name.strip_prefix("/").unwrap_or(file_name); let source = mount_point.join(file_name); Self::copy_file(source, writer) diff --git a/rust/agama-transfer/src/file_systems.rs b/rust/agama-transfer/src/file_systems.rs index 711c5ab312..b197160dc7 100644 --- a/rust/agama-transfer/src/file_systems.rs +++ b/rust/agama-transfer/src/file_systems.rs @@ -19,7 +19,10 @@ // find current contact information at www.suse.com. /// Module to search for file systems. -use std::{path::PathBuf, process::Command}; +use std::{ + path::{Path, PathBuf}, + process::Command, +}; use regex::Regex; @@ -58,7 +61,7 @@ impl FileSystem { /// struct. pub fn ensure_mounted(&self, func: F) -> TransferResult<()> where - F: FnOnce(&PathBuf) -> TransferResult<()>, + F: FnOnce(&Path) -> TransferResult<()>, { const DEFAULT_MOUNT_PATH: &str = "/run/agama/mount"; let default_mount_point = PathBuf::from(DEFAULT_MOUNT_PATH); @@ -83,14 +86,11 @@ impl FileSystem { return false; }; - match fstype.as_str() { - "" | "crypto_LUKS" | "swap" => false, - _ => true, - } + !matches!(fstype.as_str(), "" | "crypto_LUKS" | "swap") } /// Mounts file system from the given mount point. - fn mount(&self, mount_point: &PathBuf) -> TransferResult<()> { + fn mount(&self, mount_point: &Path) -> TransferResult<()> { std::fs::create_dir_all(mount_point)?; let output = Command::new("mount") .args([ @@ -107,7 +107,7 @@ impl FileSystem { } /// Umounts file system from the given mount point. - fn umount(&self, mount_point: &PathBuf) -> TransferResult<()> { + fn umount(&self, mount_point: &Path) -> TransferResult<()> { Command::new("umount") .arg(mount_point.display().to_string()) .output()?; @@ -143,7 +143,7 @@ impl FileSystemsList { /// /// * `name`: block device name. pub fn find_by_name(&self, name: &str) -> Option<&FileSystem> { - self.file_systems.iter().find(|fs| name == &fs.block_device) + self.file_systems.iter().find(|fs| name == fs.block_device) } /// Returns the file systems with the given label name. @@ -280,7 +280,6 @@ mod tests { mount_point: None, transport: Some("usb".to_string()), label: Some("OEMDRV".to_string()), - ..Default::default() }; vec![vda1, vdb1, usb] } diff --git a/rust/agama-users/src/model.rs b/rust/agama-users/src/model.rs index 26b09a5830..7fca0439fd 100644 --- a/rust/agama-users/src/model.rs +++ b/rust/agama-users/src/model.rs @@ -117,7 +117,7 @@ impl Model { let useradd = ChrootCommand::new(self.install_dir.clone())? .cmd("useradd") - .args(["-G", "wheel", &user_name]) + .args(["-G", "wheel", user_name]) .output()?; if !useradd.status.success() { @@ -269,7 +269,7 @@ impl Model { let chfn = ChrootCommand::new(self.install_dir.clone())? .cmd("chfn") - .args(["-f", &full_name, &user_name]) + .args(["-f", full_name, user_name]) .output()?; if !chfn.status.success() { @@ -291,10 +291,10 @@ impl Model { impl ModelAdapter for Model { fn install(&self, config: &Config) -> Result<(), service::Error> { if let Some(first_user) = &config.first_user { - self.add_first_user(&first_user)?; + self.add_first_user(first_user)?; } if let Some(root_user) = &config.root { - self.add_root_user(&root_user)?; + self.add_root_user(root_user)?; } Ok(()) diff --git a/rust/agama-users/src/password.rs b/rust/agama-users/src/password.rs index d8f7f7951e..b6f5dd40f4 100644 --- a/rust/agama-users/src/password.rs +++ b/rust/agama-users/src/password.rs @@ -31,7 +31,6 @@ use std::{ io::Write, process::{Command, Stdio}, }; -use thiserror; #[derive(thiserror::Error, Debug)] pub enum PasswordCheckerError { @@ -104,7 +103,7 @@ mod test { #[test] #[cfg(not(ci))] fn test_passwords() { - let checker = PasswordChecker::default(); + let checker = PasswordChecker; let result = checker.check("nots3cr3t.").unwrap(); assert!(matches!(result, PasswordCheckResult::Success(_))); diff --git a/rust/agama-users/src/service.rs b/rust/agama-users/src/service.rs index d1a91b34bc..f920c7255c 100644 --- a/rust/agama-users/src/service.rs +++ b/rust/agama-users/src/service.rs @@ -87,7 +87,7 @@ impl Starter { }; let service = Service { full_config: Config::new(), - model: model, + model, issues: self.issues, events: self.events, }; @@ -241,7 +241,7 @@ impl MessageHandler for Service { &mut self, message: message::CheckPassword, ) -> Result { - let checker = PasswordChecker::default(); + let checker = PasswordChecker; Ok(checker.check(&message.password)?) } } diff --git a/rust/agama-utils/src/api/files/config.rs b/rust/agama-utils/src/api/files/config.rs index 3be239bf8a..6986d978e4 100644 --- a/rust/agama-utils/src/api/files/config.rs +++ b/rust/agama-utils/src/api/files/config.rs @@ -99,7 +99,7 @@ fn resolve_urls_for( ) -> Result<(), FileSourceError> { if let Some(ref mut files) = files { for file in files { - file.resolve_url(&base_uri)?; + file.resolve_url(base_uri)?; } } Ok(()) @@ -153,7 +153,7 @@ mod tests { updated.merge(original); let pre_scripts = updated.pre.unwrap(); assert_eq!(pre_scripts.len(), 1); - let script = pre_scripts.get(0).unwrap(); + let script = pre_scripts.first().unwrap(); assert_eq!(&script.base.name, "updated"); } diff --git a/rust/agama-utils/src/api/files/file_source.rs b/rust/agama-utils/src/api/files/file_source.rs index 64548e01bb..217e198772 100644 --- a/rust/agama-utils/src/api/files/file_source.rs +++ b/rust/agama-utils/src/api/files/file_source.rs @@ -85,7 +85,7 @@ impl FileSource { match &self { FileSource::Text { content } => file.write_all(content.as_bytes())?, // Transfer::get will fail if the URL is relative. - FileSource::Remote { url } => Transfer::get(&url.to_string(), &mut file, false)?, + FileSource::Remote { url } => Transfer::get(url.as_str(), &mut file, false)?, } file.flush()?; diff --git a/rust/agama-utils/src/api/files/scripts.rs b/rust/agama-utils/src/api/files/scripts.rs index 14576d60e1..86b84935f0 100644 --- a/rust/agama-utils/src/api/files/scripts.rs +++ b/rust/agama-utils/src/api/files/scripts.rs @@ -300,7 +300,7 @@ impl ScriptsRepository { /// /// * `groups`: groups of scripts to clear. pub fn clear(&mut self, groups: &[ScriptsGroup]) -> Result<(), Error> { - for group in ScriptsGroup::iter().filter(|g| groups.contains(&g)) { + for group in ScriptsGroup::iter().filter(|g| groups.contains(g)) { let path = self.workdir.join(group.to_string()); if path.exists() { std::fs::remove_dir_all(path)?; diff --git a/rust/agama-utils/src/api/network/config.rs b/rust/agama-utils/src/api/network/config.rs index 0b36a87a00..71b0d0f600 100644 --- a/rust/agama-utils/src/api/network/config.rs +++ b/rust/agama-utils/src/api/network/config.rs @@ -133,7 +133,7 @@ mod tests { updated1.merge(original1); assert_eq!(updated1.connections.as_ref().unwrap().0.len(), 1); // use the updated1 list let connections = updated1.connections.unwrap(); - let connection = connections.0.get(0).unwrap(); + let connection = connections.0.first().unwrap(); assert_eq!(&connection.id, "eth1"); // Test without a list of connections diff --git a/rust/agama-utils/src/api/network/settings.rs b/rust/agama-utils/src/api/network/settings.rs index b9a0586807..ca46ddad49 100644 --- a/rust/agama-utils/src/api/network/settings.rs +++ b/rust/agama-utils/src/api/network/settings.rs @@ -134,7 +134,7 @@ impl Default for BondSettings { } } -#[derive(Clone, Debug, Serialize, Deserialize, utoipa::ToSchema, PartialEq)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, utoipa::ToSchema, PartialEq)] pub struct BridgeSettings { #[serde(skip_serializing_if = "Option::is_none")] pub stp: Option, @@ -150,19 +150,6 @@ pub struct BridgeSettings { pub ports: Vec, } -impl Default for BridgeSettings { - fn default() -> Self { - Self { - stp: None, - priority: None, - forward_delay: None, - hello_time: None, - max_age: None, - ports: vec![], - } - } -} - #[derive(Clone, Debug, Serialize, Deserialize, utoipa::ToSchema, PartialEq)] pub struct VlanSettings { pub parent: String, diff --git a/rust/agama-utils/src/api/progress.rs b/rust/agama-utils/src/api/progress.rs index a75464bc87..e336767349 100644 --- a/rust/agama-utils/src/api/progress.rs +++ b/rust/agama-utils/src/api/progress.rs @@ -60,28 +60,28 @@ impl Progress { scope, size: steps.len(), steps: steps.clone(), - step: steps.first().map_or(String::new(), |s| s.clone()), + step: steps.first().cloned().unwrap_or_default(), index: 1, } } - pub fn next(&mut self) -> Result<(), Error> { + pub fn advance(&mut self) -> Result<(), Error> { if self.index >= self.size { return Err(Error::MissingStep(self.scope)); } self.index += 1; - self.step = self.get_step(self.index).unwrap_or(String::new()); + self.step = self.get_step(self.index).unwrap_or_default(); Ok(()) } pub fn next_with_step(&mut self, step: String) -> Result<(), Error> { - self.next()?; + self.advance()?; self.step = step; Ok(()) } fn get_step(&self, index: usize) -> Option { - self.steps.get(index - 1).map(|s| s.clone()) + self.steps.get(index - 1).cloned() } } diff --git a/rust/agama-utils/src/api/security.rs b/rust/agama-utils/src/api/security.rs index 960e276a36..da1d82a72d 100644 --- a/rust/agama-utils/src/api/security.rs +++ b/rust/agama-utils/src/api/security.rs @@ -74,9 +74,9 @@ impl SSLFingerprint { } } -impl ToString for SSLFingerprint { - fn to_string(&self) -> String { - self.fingerprint.clone() +impl std::fmt::Display for SSLFingerprint { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.fingerprint) } } diff --git a/rust/agama-utils/src/api/software/config.rs b/rust/agama-utils/src/api/software/config.rs index 365dc51caa..a9a75474cf 100644 --- a/rust/agama-utils/src/api/software/config.rs +++ b/rust/agama-utils/src/api/software/config.rs @@ -125,17 +125,8 @@ impl From> for PatternsConfig { impl From>> for PatternsConfig { fn from(map: HashMap>) -> Self { - let add = if let Some(to_add) = map.get("add") { - Some(to_add.to_owned()) - } else { - None - }; - - let remove = if let Some(to_remove) = map.get("remove") { - Some(to_remove.to_owned()) - } else { - None - }; + let add = map.get("add").map(|to_add| to_add.to_owned()); + let remove = map.get("remove").map(|to_remove| to_remove.to_owned()); Self::PatternsMap(PatternsMap { add, remove }) } diff --git a/rust/agama-utils/src/api/users/config.rs b/rust/agama-utils/src/api/users/config.rs index 68a2d6c483..0dd22a5a3b 100644 --- a/rust/agama-utils/src/api/users/config.rs +++ b/rust/agama-utils/src/api/users/config.rs @@ -155,7 +155,7 @@ impl RootUserConfig { return false; } - return true; + true } } @@ -166,31 +166,31 @@ mod test { #[test] fn test_parse_user_password() { let password_str = r#"{ "password": "$a$b123", "hashedPassword": true }"#; - let password: UserPassword = serde_json::from_str(&password_str).unwrap(); + let password: UserPassword = serde_json::from_str(password_str).unwrap(); assert_eq!(&password.password, "$a$b123"); - assert_eq!(password.hashed_password, true); + assert!(password.hashed_password); let password_str = r#"{ "password": "$a$b123" }"#; - let password: UserPassword = serde_json::from_str(&password_str).unwrap(); + let password: UserPassword = serde_json::from_str(password_str).unwrap(); assert_eq!(&password.password, "$a$b123"); - assert_eq!(password.hashed_password, false); + assert!(!password.hashed_password); } #[test] fn test_is_empty() { - assert_eq!(Config::default().is_empty(), true); + assert!(Config::default().is_empty()); let empty_user_config = Config { first_user: Some(FirstUserConfig::default()), ..Default::default() }; - assert_eq!(empty_user_config.is_empty(), true); + assert!(empty_user_config.is_empty()); let empty_root_config = Config { root: Some(RootUserConfig::default()), ..Default::default() }; - assert_eq!(empty_root_config.is_empty(), true); + assert!(empty_root_config.is_empty()); let password = UserPassword { password: "secret".to_string(), @@ -210,7 +210,7 @@ mod test { first_user: Some(user_with_password), ..Default::default() }; - assert_eq!(user_with_password_config.is_empty(), false); + assert!(!user_with_password_config.is_empty()); let root_with_password = RootUserConfig { password: Some(password.clone()), @@ -220,7 +220,7 @@ mod test { root: Some(root_with_password), ..Default::default() }; - assert_eq!(root_with_password_config.is_empty(), false); + assert!(!root_with_password_config.is_empty()); let root_with_empty_password = RootUserConfig { password: Some(empty_password.clone()), @@ -230,7 +230,7 @@ mod test { root: Some(root_with_empty_password), ..Default::default() }; - assert_eq!(root_with_empty_password_config.is_empty(), true); + assert!(root_with_empty_password_config.is_empty()); let root_with_ssh_key = RootUserConfig { ssh_public_key: Some("12345678".to_string()), @@ -240,12 +240,12 @@ mod test { root: Some(root_with_ssh_key), ..Default::default() }; - assert_eq!(root_with_ssh_key_config.is_empty(), false); + assert!(!root_with_ssh_key_config.is_empty()); } #[test] fn test_user_is_valid() { - assert_eq!(FirstUserConfig::default().is_valid(), false); + assert!(!FirstUserConfig::default().is_valid()); let valid_user = FirstUserConfig { user_name: Some("firstuser".to_string()), @@ -255,7 +255,7 @@ mod test { hashed_password: false, }), }; - assert_eq!(valid_user.is_valid(), true); + assert!(valid_user.is_valid()); let empty_user_name = FirstUserConfig { user_name: Some("".to_string()), @@ -265,7 +265,7 @@ mod test { hashed_password: false, }), }; - assert_eq!(empty_user_name.is_valid(), false); + assert!(!empty_user_name.is_valid()); let empty_full_name = FirstUserConfig { user_name: Some("firstuser".to_string()), @@ -275,7 +275,7 @@ mod test { hashed_password: false, }), }; - assert_eq!(empty_full_name.is_valid(), false); + assert!(!empty_full_name.is_valid()); let empty_password = FirstUserConfig { user_name: Some("firstuser".to_string()), @@ -285,6 +285,6 @@ mod test { hashed_password: false, }), }; - assert_eq!(empty_password.is_valid(), false); + assert!(!empty_password.is_valid()); } } diff --git a/rust/agama-utils/src/kernel_cmdline.rs b/rust/agama-utils/src/kernel_cmdline.rs index b301bf7c07..941c568a65 100644 --- a/rust/agama-utils/src/kernel_cmdline.rs +++ b/rust/agama-utils/src/kernel_cmdline.rs @@ -59,10 +59,7 @@ impl KernelCmdline { pub fn parse_str(content: &str) -> Self { let mut args: HashMap> = HashMap::default(); for param in content.split_whitespace() { - let (key, value) = param - .split_once("=") - .map(|(k, v)| (k, v)) - .unwrap_or_else(|| (param, "1")); + let (key, value) = param.split_once("=").unwrap_or((param, "1")); args.entry(key.to_lowercase()) .and_modify(|v| v.push(value.to_string())) diff --git a/rust/agama-utils/src/lib.rs b/rust/agama-utils/src/lib.rs index 617bf4e0a5..fd33eac4fa 100644 --- a/rust/agama-utils/src/lib.rs +++ b/rust/agama-utils/src/lib.rs @@ -54,7 +54,7 @@ pub mod helpers { /// /// Symlinks are recreated pointing to the same target as the original one. pub fn copy_dir_all(source: &Utf8Path, target: &Utf8Path) -> Result<(), std::io::Error> { - fs::create_dir_all(&target)?; + fs::create_dir_all(target)?; for entry in source.read_dir_utf8()? { let entry = entry?; let ty = fs::symlink_metadata(entry.path())?; diff --git a/rust/agama-utils/src/licenses.rs b/rust/agama-utils/src/licenses.rs index 6c25bde71f..3257d34736 100644 --- a/rust/agama-utils/src/licenses.rs +++ b/rust/agama-utils/src/licenses.rs @@ -85,10 +85,7 @@ impl Registry { self.fallback.clear(); let territories = get_territories().map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::Other, - format!("Cannot read the territories list: {}", e), - ) + std::io::Error::other(format!("Cannot read the territories list: {}", e)) })?; for territory in territories.territory { @@ -109,7 +106,7 @@ impl Registry { /// If a translation is not found for the given language, it returns the default text. pub fn find(&self, id: &str, language: &LanguageTag) -> Option { let license = self.licenses.iter().find(|l| l.id.as_str() == id)?; - let license_language = self.find_language(&license, &language).unwrap_or_default(); + let license_language = self.find_language(license, language).unwrap_or_default(); self.read_license_content(id, &license_language).ok() } @@ -193,7 +190,7 @@ impl Registry { candidates .into_iter() - .find(|c| license.languages.contains(&c)) + .find(|c| license.languages.contains(c)) } /// Returns a vector with the licenses from the repository. diff --git a/rust/agama-utils/src/products.rs b/rust/agama-utils/src/products.rs index 8b2be9ea67..2d9fa21b6a 100644 --- a/rust/agama-utils/src/products.rs +++ b/rust/agama-utils/src/products.rs @@ -136,8 +136,7 @@ impl Registry { /// /// * `id`: product ID. /// * `mode`: product mode. Required only if the product has modes. - pub fn find(&self, id: &str, mode: Option<&str>) -> Result { - let mut mode = mode.clone(); + pub fn find<'a>(&'a self, id: &str, mut mode: Option<&'a str>) -> Result { let Some(template) = self.products.iter().find(|p| p.id == id) else { return Err(Error::UnknownProduct(id.to_string())); }; @@ -508,7 +507,7 @@ mod test { assert_eq!(tw.id, "Tumbleweed"); assert_eq!(tw.name, "openSUSE Tumbleweed"); assert_eq!(tw.icon, "Tumbleweed.svg"); - assert_eq!(tw.registration, false); + assert!(!tw.registration); assert_eq!(tw.version, None); let translations = &tw.translations; @@ -556,7 +555,7 @@ mod test { let sles = ctx.registry.find("SLES", Some("standard")).unwrap(); assert_eq!(sles.id, "SLES"); assert_eq!(sles.name, "SUSE Linux Enterprise Server 16.1"); - assert_eq!(sles.registration, true); + assert!(sles.registration); assert_eq!(sles.version, Some("16.1".to_string())); let translations = &sles.translations; diff --git a/rust/agama-utils/src/progress/message.rs b/rust/agama-utils/src/progress/message.rs index 5a0e98df63..e6b4c201a5 100644 --- a/rust/agama-utils/src/progress/message.rs +++ b/rust/agama-utils/src/progress/message.rs @@ -154,13 +154,14 @@ impl Message for GetStage { /// Determines whether the progress is empty. /// /// It can specify a scope to limit the query. +#[derive(Default)] pub struct IsEmpty { pub scope: Option, } impl IsEmpty { pub fn new() -> Self { - IsEmpty { scope: None } + Self::default() } pub fn with_scope(scope: Scope) -> Self { diff --git a/rust/agama-utils/src/progress/service.rs b/rust/agama-utils/src/progress/service.rs index e49b747ef5..70e168bc98 100644 --- a/rust/agama-utils/src/progress/service.rs +++ b/rust/agama-utils/src/progress/service.rs @@ -62,8 +62,7 @@ impl Starter { status: Status::default(), }; - let handler = actor::spawn(service); - handler + actor::spawn(service) } } @@ -143,7 +142,7 @@ impl MessageHandler for Service { async fn handle(&mut self, message: message::SetStage) -> Result<(), Error> { self.status.stage = message.stage; self.events.send(Event::StageChanged { - stage: self.status.stage.clone(), + stage: self.status.stage, })?; Ok(()) } @@ -213,7 +212,7 @@ impl MessageHandler for Service { let Some(progress) = self.get_mut_progress(message.scope) else { return Err(Error::MissingProgress(message.scope)); }; - progress.next()?; + progress.advance()?; let progress = progress.clone(); self.send_progress_changed(progress)?; Ok(()) diff --git a/rust/agama-utils/src/question/service.rs b/rust/agama-utils/src/question/service.rs index 8e15596c27..944566444f 100644 --- a/rust/agama-utils/src/question/service.rs +++ b/rust/agama-utils/src/question/service.rs @@ -65,7 +65,7 @@ impl Service { config.answers.as_ref().and_then(|answers_vec| { answers_vec .iter() - .find(|a| a.answers_to(&spec)) + .find(|a| a.answers_to(spec)) .map(|r| r.answer.clone()) }) }); diff --git a/rust/agama-utils/src/test/dbus.rs b/rust/agama-utils/src/test/dbus.rs index d485927ba7..dac87759b2 100644 --- a/rust/agama-utils/src/test/dbus.rs +++ b/rust/agama-utils/src/test/dbus.rs @@ -49,7 +49,8 @@ struct Started { impl Drop for Started { fn drop(&mut self) { - self.child.kill().unwrap(); + let _ = self.child.kill(); + let _ = self.child.wait(); } } @@ -75,7 +76,7 @@ impl DBusServer { } async fn start(self) -> Result, zbus::Error> { - let child = Command::new("/usr/bin/dbus-daemon") + let mut child = Command::new("/usr/bin/dbus-daemon") .args([ "--config-file", "../share/dbus-test.conf", @@ -85,7 +86,14 @@ impl DBusServer { .spawn() .expect("to start the testing D-Bus daemon"); - let connection = async_retry(|| connection_to(&self.address)).await?; + let connection = match async_retry(|| connection_to(&self.address)).await { + Ok(c) => c, + Err(e) => { + let _ = child.kill(); + let _ = child.wait(); + return Err(e); + } + }; Ok(DBusServer { address: self.address, diff --git a/rust/suseconnect-agama/src/lib.rs b/rust/suseconnect-agama/src/lib.rs index e313610c6f..5cd900dc8b 100644 --- a/rust/suseconnect-agama/src/lib.rs +++ b/rust/suseconnect-agama/src/lib.rs @@ -302,7 +302,7 @@ impl TryFrom for Credentials { "Missing credentials key".to_string(), )); }; - let Some(login) = credentials.get(0).and_then(Value::as_str) else { + let Some(login) = credentials.first().and_then(Value::as_str) else { return Err(Error::UnexpectedResponse("Missing login key".to_string())); }; let Some(password) = credentials.get(1).and_then(Value::as_str) else { @@ -519,7 +519,6 @@ mod tests { use super::*; use serde_json::json; use std::fs; - use tempfile; #[test] fn test_check_error_success() { diff --git a/rust/xtask/src/main.rs b/rust/xtask/src/main.rs index a6c318d892..76b13648ea 100644 --- a/rust/xtask/src/main.rs +++ b/rust/xtask/src/main.rs @@ -26,7 +26,7 @@ mod tasks { Ok(()) } - const GENERATED: &'static str = + const GENERATED: &str = "---\nNOTE: This documentation is generated. Run `cargo xtask markdown` to update it.\n"; /// Generate Agama's CLI documentation in markdown format. diff --git a/rust/zypp-agama/src/lib.rs b/rust/zypp-agama/src/lib.rs index 6ff0c8c013..cc784f47a0 100644 --- a/rust/zypp-agama/src/lib.rs +++ b/rust/zypp-agama/src/lib.rs @@ -423,7 +423,7 @@ impl Zypp { let mut closure = progress; let cb = get_zypp_progress_callback(&closure); let mut status: Status = Status::default(); - let status_ptr = &mut status as *mut _ as *mut Status; + let status_ptr = &mut status as *mut _; let c_alias = CString::new(alias).unwrap(); let c_url = CString::new(url).unwrap(); zypp_agama_sys::add_repository(