Skip to content

Commit

Permalink
refactor(rust): introduce a new "transfer" module (#1660)
Browse files Browse the repository at this point in the history
- Introduce a new `transfer` module containing an API to download files.
- The idea is to extend this API in the future to support other [URL

types](https://github.com/yast/yast-installation/blob/master/doc/url.md).
- This module replaces the old "download" function.
  • Loading branch information
imobachgs authored Oct 9, 2024
2 parents 143314d + c50672e commit 3c2dc87
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 22 deletions.
8 changes: 4 additions & 4 deletions rust/agama-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ mod progress;
mod questions;

use crate::error::CliError;
use agama_lib::error::ServiceError;
use agama_lib::manager::ManagerClient;
use agama_lib::progress::ProgressMonitor;
use agama_lib::{
error::ServiceError, manager::ManagerClient, progress::ProgressMonitor, transfer::Transfer,
};
use auth::run as run_auth_cmd;
use commands::Commands;
use config::run as run_config_cmd;
Expand Down Expand Up @@ -158,7 +158,7 @@ pub async fn run_command(cli: Cli) -> Result<(), ServiceError> {
Commands::Questions(subcommand) => run_questions_cmd(subcommand).await?,
Commands::Logs(subcommand) => run_logs_cmd(subcommand).await?,
Commands::Auth(subcommand) => run_auth_cmd(subcommand).await?,
Commands::Download { url } => crate::profile::download(&url, std::io::stdout())?,
Commands::Download { url } => Transfer::get(&url, std::io::stdout())?,
};

Ok(())
Expand Down
19 changes: 3 additions & 16 deletions rust/agama-cli/src/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ use agama_lib::{
auth::AuthToken,
install_settings::InstallSettings,
profile::{AutoyastProfile, ProfileEvaluator, ProfileValidator, ValidationResult},
transfer::Transfer,
Store as SettingsStore,
};
use anyhow::Context;
use clap::Subcommand;
use curl::easy::Easy;
use std::os::unix::process::CommandExt;
use std::{
fs::File,
io::{stdout, Write},
io::stdout,
path::{Path, PathBuf},
process::Command,
};
Expand Down Expand Up @@ -78,19 +78,6 @@ pub enum ProfileCommands {
},
}

pub fn download(url: &str, mut out_fd: impl Write) -> anyhow::Result<()> {
let mut handle = Easy::new();
handle.url(url)?;

let mut transfer = handle.transfer();
transfer.write_function(|buf|
// unwrap here is ok, as we want to kill download if we failed to write content
Ok(out_fd.write(buf).unwrap()))?;
transfer.perform()?;

Ok(())
}

fn validate(path: &PathBuf) -> anyhow::Result<()> {
let validator = ProfileValidator::default_schema()?;
// let path = Path::new(&path);
Expand Down Expand Up @@ -138,7 +125,7 @@ async fn import(url_string: String, dir: Option<PathBuf>) -> anyhow::Result<()>
AutoyastProfile::new(&url)?.read_into(output_fd)?;
} else {
// just download profile
download(&url_string, output_fd)?;
Transfer::get(&url_string, output_fd)?;
}

// exec shell scripts
Expand Down
7 changes: 5 additions & 2 deletions rust/agama-lib/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
// To contact SUSE LLC about this file by physical or electronic mail, you may
// find current contact information at www.suse.com.

use curl;
use serde_json;
use std::io;
use thiserror::Error;
use zbus::{self, zvariant};

use crate::transfer::TransferError;

#[derive(Error, Debug)]
pub enum ServiceError {
#[error("Cannot generate Agama logs: {0}")]
Expand Down Expand Up @@ -66,12 +67,14 @@ pub enum ServiceError {
// Specific error when something does not work as expected, but it is not user fault
#[error("Internal error. Please report a bug and attach logs. Details: {0}")]
InternalError(String),
#[error("Could not read the file: '{0}'")]
CouldNotTransferFile(#[from] TransferError),
}

#[derive(Error, Debug)]
pub enum ProfileError {
#[error("Could not read the profile")]
Unreachable(#[from] curl::Error),
Unreachable(#[from] TransferError),
#[error("Jsonnet evaluation failed:\n{0}")]
EvaluationError(String),
#[error("I/O error")]
Expand Down
1 change: 1 addition & 0 deletions rust/agama-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub mod proxies;
mod store;
pub use store::Store;
pub mod questions;
pub mod transfer;
use crate::error::ServiceError;
use reqwest::{header, Client};

Expand Down
37 changes: 37 additions & 0 deletions rust/agama-lib/src/transfer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! File transfer API for Agama.
//!
//! Implement a file transfer API which, in the future, will support Agama specific URLs. Check the
//! YaST document about [URL handling in the
//! installer](https://github.com/yast/yast-installation/blob/master/doc/url.md) for further
//! information.
//!
//! At this point, it only supports those schemes supported by CURL.
use std::io::Write;

use curl::easy::Easy;
use thiserror::Error;

#[derive(Error, Debug)]
#[error(transparent)]
pub struct TransferError(#[from] curl::Error);
pub type TransferResult<T> = Result<T, TransferError>;

/// File transfer API
pub struct Transfer {}

impl Transfer {
/// Retrieves and writes the data from an URL
///
/// * `url`: URL to get the data from.
/// * `out_fd`: where to write the data.
pub fn get(url: &str, mut out_fd: impl Write) -> TransferResult<()> {
let mut handle = Easy::new();
handle.url(url)?;

let mut transfer = handle.transfer();
transfer.write_function(|buf| Ok(out_fd.write(buf).unwrap()))?;
transfer.perform()?;
Ok(())
}
}

0 comments on commit 3c2dc87

Please sign in to comment.