From 9e1a1d901ef8d67bce20b226bb758a2135e6312d Mon Sep 17 00:00:00 2001 From: LDprg Date: Wed, 15 May 2024 18:35:19 +0000 Subject: [PATCH] Start spliting into smalle modules. Starting with downloads --- run.sh | 2 +- src/decompress.rs | 107 +++++++++++++++++-------------------- src/downloader.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++ src/log.rs | 25 +++++++++ src/main.rs | 92 +++++--------------------------- 5 files changed, 218 insertions(+), 139 deletions(-) create mode 100644 src/downloader.rs create mode 100644 src/log.rs diff --git a/run.sh b/run.sh index 18100d1..910b71b 100755 --- a/run.sh +++ b/run.sh @@ -1,3 +1,3 @@ #!/bin/sh -cargo run -- --input ./test_packages/elfutils/ --output ./out/elfutils/ +cargo run -- --input ./test_packages/xz/ --output ./out/xz/ diff --git a/src/decompress.rs b/src/decompress.rs index 530176a..1717b6a 100644 --- a/src/decompress.rs +++ b/src/decompress.rs @@ -1,71 +1,62 @@ use std::path::Path; -use std::process::exit; - -use log::error; use tokio::pin; use tokio_stream::Stream; use tokio_util::{bytes::Buf, io::StreamReader}; -use crate::fatal; +use crate::log::*; pub async fn decompress( stream: impl Stream>>, output: &Path, - file_name: &str, -) -> String { - let mut file_name = String::from(file_name.trim()); - + extension: &str, +) { // TODO: create a more elegant and efficent way to determine compression algo and file name - if file_name.ends_with(".tar.zst") { - let decoder = - async_compression::tokio::bufread::ZstdDecoder::new(StreamReader::new(stream)); - - pin!(decoder); - - tokio_tar::Archive::new(decoder) - .unpack(&output) - .await - .expect("Cannot unpack archive"); - - file_name.truncate(file_name.len() - ".tar.zst".len()) - } else if file_name.ends_with(".tar.xz") { - let decoder = async_compression::tokio::bufread::XzDecoder::new(StreamReader::new(stream)); - - pin!(decoder); - - tokio_tar::Archive::new(decoder) - .unpack(&output) - .await - .expect("Cannot unpack archive"); - - file_name.truncate(file_name.len() - ".tar.xz".len()) - } else if file_name.ends_with(".tar.gz") { - let decoder = - async_compression::tokio::bufread::GzipDecoder::new(StreamReader::new(stream)); - - pin!(decoder); - - tokio_tar::Archive::new(decoder) - .unpack(&output) - .await - .expect("Cannot unpack archive"); - - file_name.truncate(file_name.len() - ".tar.gz".len()) - } else if file_name.ends_with(".tar.bz2") { - let decoder = async_compression::tokio::bufread::BzDecoder::new(StreamReader::new(stream)); - - pin!(decoder); - - tokio_tar::Archive::new(decoder) - .unpack(&output) - .await - .expect("Cannot unpack archive"); - - file_name.truncate(file_name.len() - ".tar.bz2".len()) - } else { - fatal!("Extension of \"{}\" not supported!", file_name); + match extension { + ".tar.zst" => { + let decoder = + async_compression::tokio::bufread::ZstdDecoder::new(StreamReader::new(stream)); + + pin!(decoder); + + tokio_tar::Archive::new(decoder) + .unpack(&output) + .await + .expect("Cannot unpack archive"); + } + ".tar.xz" => { + let decoder = + async_compression::tokio::bufread::XzDecoder::new(StreamReader::new(stream)); + + pin!(decoder); + + tokio_tar::Archive::new(decoder) + .unpack(&output) + .await + .expect("Cannot unpack archive"); + } + ".tar.gz" => { + let decoder = + async_compression::tokio::bufread::GzipDecoder::new(StreamReader::new(stream)); + + pin!(decoder); + + tokio_tar::Archive::new(decoder) + .unpack(&output) + .await + .expect("Cannot unpack archive"); + } + ".tar.bz2" => { + let decoder = + async_compression::tokio::bufread::BzDecoder::new(StreamReader::new(stream)); + + pin!(decoder); + + tokio_tar::Archive::new(decoder) + .unpack(&output) + .await + .expect("Cannot unpack archive"); + } + _ => fatal!("Extension of \"{}\" not supported!", extension), } - - file_name } diff --git a/src/downloader.rs b/src/downloader.rs new file mode 100644 index 0000000..ddaaf49 --- /dev/null +++ b/src/downloader.rs @@ -0,0 +1,131 @@ +use std::cmp::min; +use std::path::Path; + +use indicatif::{MultiProgress, ProgressBar}; +use tokio_stream::StreamExt; +use url::Url; + +use crate::decompress::decompress; +use crate::log::*; +use crate::{bars::ProgressStyle, somebuild_config::Config}; + +pub struct Download<'a> { + bar: ProgressBar, + config: &'a Config, + output: &'a Path, + #[allow(dead_code)] + pub full_file_name: String, + #[allow(dead_code)] + pub file_name: String, + #[allow(dead_code)] + pub extension: String, +} + +impl<'a> Download<'a> { + pub fn new(multibar: &MultiProgress, config: &'a Config, output: &'a Path) -> Self { + let bar = multibar.add(ProgressBar::new(1)); + let name = Url::parse(&config.source.url) + .unwrap() + .path_segments() + .unwrap() + .last() + .unwrap() + .trim() + .to_string(); + + let (full_file_name, file_name, extension) = if name.ends_with(".tar.zst") { + ( + name.clone(), + name.split_at(name.len() - ".tar.zst".len()).0.to_string(), + ".tar.zst".to_string(), + ) + } else if name.ends_with(".tar.xz") { + ( + name.clone(), + name.split_at(name.len() - ".tar.xz".len()).0.to_string(), + ".tar.xz".to_string(), + ) + } else if name.ends_with(".tar.gz") { + ( + name.clone(), + name.split_at(name.len() - ".tar.gz".len()).0.to_string(), + ".tar.gz".to_string(), + ) + } else if name.ends_with(".tar.bz2") { + ( + name.clone(), + name.split_at(name.len() - ".tar.bz2".len()).0.to_string(), + ".tar.bz2".to_string(), + ) + } else { + fatal!("Extension of \"{}\" not supported!", name); + }; + + Self { + bar, + config, + output, + full_file_name, + file_name, + extension, + } + } + + pub async fn download(&self) { + self.bar.set_style(ProgressStyle::Download.value()); + self.bar.set_message(format!( + "Starting {}-{}", + self.config.general.name, self.config.source.version + )); + + self.bar.tick(); + + let response = reqwest::get(&self.config.source.url).await.unwrap(); + + let total_size = response.content_length().unwrap_or(0); + + self.bar.set_length(total_size); + self.bar.set_message(format!( + "Downloading {}-{}", + self.config.general.name, self.config.source.version + )); + + let mut hasher = blake3::Hasher::new(); + let mut downloaded: u64 = 0; + + let stream = response.bytes_stream().map(|result| { + result + .inspect(|result| { + let new = min(downloaded + (result.len() as u64), total_size); + downloaded = new; + self.bar.set_position(new); + }) + .inspect(|result| { + hasher.update(result); + }) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)) + }); + + decompress(stream, self.output, &self.extension).await; + + info!("Extract Folder:\t{}", self.file_name); + + let hash = hasher.finalize(); + + if hash.to_string() != self.config.source.hash { + fatal!( + "Hash error for \"{}\" specified \n\t \"{}\" found\n\t \"{}\"", + self.config.source.url, + self.config.source.hash, + hash.to_string() + ); + } + } + + pub fn finish(&self) { + self.bar.finish_with_message(format!( + "Finished downloading {}-{}", + self.config.general.name, self.config.source.version + )); + } +} diff --git a/src/log.rs b/src/log.rs new file mode 100644 index 0000000..c53193a --- /dev/null +++ b/src/log.rs @@ -0,0 +1,25 @@ +pub use std::process::exit; + +#[allow(unused_imports)] +pub use log::error; + +#[allow(unused_imports)] +pub use log::warn; + +#[allow(unused_imports)] +pub use log::info; + +#[allow(unused_imports)] +pub use log::debug; + +#[macro_export] +macro_rules! fatal { + ( $($var:tt)* ) => { + { + error!($($var)*); + exit(1); + } + }; +} + +pub(crate) use fatal; diff --git a/src/main.rs b/src/main.rs index 2274642..b85d515 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,33 +1,25 @@ mod bars; mod decompress; +mod downloader; +mod log; mod paths; mod somebuild_config; use clap::Parser; use indicatif::ProgressBar; -use log::{error, info}; + use run_script::ScriptOptions; -use std::cmp::min; use std::path::Path; use std::process::exit; use tokio::fs::{self, File}; use tokio::io::AsyncReadExt; -use tokio_stream::StreamExt; -use url::Url; use crate::bars::{create_multibar, ProgressStyle}; -use crate::decompress::decompress; +use crate::downloader::Download; +use crate::log::*; use crate::paths::normalize_path; use crate::somebuild_config::Config; -#[macro_export] -macro_rules! fatal { - ( $($var:tt)* ) => { - error!($($var)*); - exit(1); - }; -} - /// A package builder for Some OS #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -100,66 +92,9 @@ async fn main() { config.general.name, config.source.version, config.source.release ); - let bar = multibar.add(ProgressBar::new(1)); - bar.set_style(ProgressStyle::Download.value()); - bar.set_message(format!( - "Starting {}-{}", - config.general.name, config.source.version - )); - - bar.tick(); + let down = Download::new(&multibar, &config, &output); - let response = reqwest::get(&config.source.url).await.unwrap(); - - let total_size = response.content_length().unwrap_or(0); - - bar.set_length(total_size); - bar.set_message(format!( - "Downloading {}-{}", - config.general.name, config.source.version - )); - - let mut hasher = blake3::Hasher::new(); - let mut downloaded: u64 = 0; - - let stream = response.bytes_stream().map(|result| { - result - .inspect(|result| { - let new = min(downloaded + (result.len() as u64), total_size); - downloaded = new; - bar.set_position(new); - }) - .inspect(|result| { - hasher.update(result); - }) - .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)) - }); - - let file_name = decompress( - stream, - &output, - Url::parse(&config.source.url) - .unwrap() - .path_segments() - .unwrap() - .last() - .unwrap(), - ) - .await; - let file_name = file_name.as_str(); - - info!("Extract Folder:\t{}", file_name); - - let hash = hasher.finalize(); - - if hash.to_string() != config.source.hash { - fatal!( - "Hash error for \"{}\" specified \n\t \"{}\" found\n\t \"{}\"", - config.source.url, - config.source.hash, - hash.to_string() - ); - } + down.download().await; let bar_build = multibar.add(ProgressBar::new(3)); bar_build.set_style(ProgressStyle::Build.value()); @@ -169,13 +104,10 @@ async fn main() { config.general.name, config.source.version )); - bar.finish_with_message(format!( - "Finished downloading {}-{}", - config.general.name, config.source.version - )); - bar_build.tick(); + down.finish(); + let configure_cmd = config .build .setup @@ -184,7 +116,7 @@ async fn main() { .to_string(); let mut options = ScriptOptions::new(); - options.working_directory = Some(output.join(file_name)); + options.working_directory = Some(output.join(&down.file_name)); let (code, out, error) = run_script::run_script!(configure_cmd, options).unwrap(); if code != 0 { @@ -208,7 +140,7 @@ async fn main() { .to_string(); let mut options = ScriptOptions::new(); - options.working_directory = Some(output.join(file_name)); + options.working_directory = Some(output.join(&down.file_name)); let (code, out, error) = run_script::run_script!(make_cmd, options).unwrap(); if code != 0 { @@ -235,7 +167,7 @@ async fn main() { .to_string(); let mut options = ScriptOptions::new(); - options.working_directory = Some(output.join(file_name)); + options.working_directory = Some(output.join(&down.file_name)); let (code, out, error) = run_script::run_script!(make_install_cmd, options).unwrap(); if code != 0 {