From 4357ff2f74c0b0082741af5e1015ef4da334a430 Mon Sep 17 00:00:00 2001 From: Naz Date: Tue, 29 Jul 2025 10:05:46 +0100 Subject: =?UTF-8?q?=F0=9F=8E=A8style:=20some=20formatting=20here=20and=20t?= =?UTF-8?q?here?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/types.rs') diff --git a/src/types.rs b/src/types.rs index fef9071..3947bfa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,5 @@ use futures_util::StreamExt; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use std::path::PathBuf; use tokio::{fs, io::AsyncWriteExt}; @@ -96,7 +96,9 @@ impl AppImage { } pub async fn remove(&self) -> Result<(), Box> { let home = std::env::var("HOME")?; - let symlink_path = PathBuf::from(home).join(".local/bin").join(&self.executable); + let symlink_path = PathBuf::from(home) + .join(".local/bin") + .join(&self.executable); let index_path = index_dir().join(format!("{}.json", &self.executable)); fs::remove_file(&self.file_path).await?; -- cgit v1.2.3 From f419a08d2861d76dce3d2a8206d6f1eb24bf1f2e Mon Sep 17 00:00:00 2001 From: Naz Date: Tue, 29 Jul 2025 13:24:35 +0100 Subject: =?UTF-8?q?=F0=9F=94=A7refactor:=20use=20separate=20structs=20for?= =?UTF-8?q?=20download=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types.rs | 135 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 101 insertions(+), 34 deletions(-) (limited to 'src/types.rs') diff --git a/src/types.rs b/src/types.rs index 3947bfa..e0397a1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -23,33 +23,87 @@ pub struct SourceMetadata { pub url: String, } -impl AppImage { - pub async fn save_to_index(&self, appname: &str) -> Result<(), Box> { - fs::create_dir_all(&index_dir()).await?; +#[derive(Debug)] +pub struct PackageManager { + pub downloader: Downloader, + pub index: Index, + pub symlink_manager: SymlinkManager, +} - let index_file = &index_dir().join(format!("{appname}.json")); +#[derive(Debug, Default)] +pub struct Downloader {} - let json = serde_json::to_string_pretty(self)?; - fs::write(index_file, json).await?; +#[derive(Debug, Default)] +pub struct Index {} + +#[derive(Debug, Default)] +pub struct SymlinkManager {} + +impl PackageManager { + pub async fn install( + appimage: &AppImage, + appname: &str, + ) -> Result<(), Box> { + if index_dir() + .join(format!("{}.json", &appimage.executable)) + .exists() + { + Err(format!("{} is already installed.", &appimage.executable).into()) + } else { + // Try to extract filename from URL or use default + let url = &appimage.source.meta.url; + let filename = match url.split('/').next_back() { + Some(name) => name.to_string(), + None => format!("{}.AppImage", appimage.executable), + }; + let path = &appimages_dir().join(filename); + + let downloader = crate::Downloader::new(); + downloader.download_with_progress(url, path).await?; + + let index = crate::Index::new(); + index.add(appimage, appname).await?; + + let sm = crate::SymlinkManager::new(); + sm.create(appimage).await?; + Ok(()) + } + } + pub async fn remove(appname: &str) -> Result<(), Box> { + let index_file_path = index_dir().join(format!("{appname}.json")); + let index_file_content = fs::read_to_string(&index_file_path).await?; + let appimage: AppImage = serde_json::from_str(&index_file_content)?; + + let home = std::env::var("HOME")?; + let symlink_path = PathBuf::from(home) + .join(".local/bin") + .join(&appimage.executable); + let index_path = index_dir().join(format!("{}.json", &appimage.executable)); + + fs::remove_file(&appimage.file_path).await?; + fs::remove_file(symlink_path).await?; + fs::remove_file(index_path).await?; Ok(()) } - pub async fn download_from_url(&self) -> Result<(), Box> { - fs::create_dir_all(&appimages_dir()).await?; +} - // Try to extract filename from URL or use default - let url = &self.source.meta.url; - let filename = match url.split('/').next_back() { - Some(name) => name.to_string(), - None => format!("{}.AppImage", &self.executable), - }; - let file_path = &appimages_dir().join(filename); +impl Downloader { + pub fn new() -> Self { + Self {} + } + pub async fn download_with_progress( + &self, + url: &str, + path: &PathBuf, + ) -> Result<(), Box> { + fs::create_dir_all(&appimages_dir()).await?; let resp = reqwest::get(&url.to_string()).await?; let total_size = resp.content_length().unwrap_or(0); let bar = make_progress_bar(total_size); - let mut out = tokio::fs::File::create(&file_path).await?; + let mut out = tokio::fs::File::create(&path).await?; // Stream download with progress updates let mut stream = resp.bytes_stream(); @@ -66,20 +120,46 @@ impl AppImage { #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; - let mut perms = fs::metadata(&file_path).await?.permissions(); + let mut perms = fs::metadata(&path).await?.permissions(); perms.set_mode(0o755); - fs::set_permissions(&file_path, perms).await?; + fs::set_permissions(&path, perms).await?; } Ok(()) } - pub async fn create_symlink(&self) -> Result<(), Box> { +} + +impl Index { + pub fn new() -> Self { + Self {} + } + pub async fn add( + &self, + appimage: &AppImage, + appname: &str, + ) -> Result<(), Box> { + fs::create_dir_all(&index_dir()).await?; + + let index_file = &index_dir().join(format!("{appname}.json")); + + let json = serde_json::to_string_pretty(appimage)?; + fs::write(index_file, json).await?; + + Ok(()) + } +} + +impl SymlinkManager { + pub fn new() -> Self { + Self {} + } + pub async fn create(&self, appimage: &AppImage) -> Result<(), Box> { let home = std::env::var("HOME")?; let local_bin = PathBuf::from(home).join(".local/bin"); fs::create_dir_all(&local_bin).await?; - let symlink_path = local_bin.join(&self.executable); + let symlink_path = local_bin.join(&appimage.executable); #[cfg(unix)] { @@ -89,22 +169,9 @@ impl AppImage { fs::remove_file(&symlink_path).await?; } - std::os::unix::fs::symlink(&self.file_path, &symlink_path)?; + std::os::unix::fs::symlink(&appimage.file_path, &symlink_path)?; } - Ok(()) - } - pub async fn remove(&self) -> Result<(), Box> { - let home = std::env::var("HOME")?; - let symlink_path = PathBuf::from(home) - .join(".local/bin") - .join(&self.executable); - let index_path = index_dir().join(format!("{}.json", &self.executable)); - - fs::remove_file(&self.file_path).await?; - fs::remove_file(symlink_path).await?; - fs::remove_file(index_path).await?; - Ok(()) } } -- cgit v1.2.3 From bd8adb9f0193f1482ca866b06cf133ff68fd9a8e Mon Sep 17 00:00:00 2001 From: Naz Date: Tue, 29 Jul 2025 13:46:43 +0100 Subject: =?UTF-8?q?=F0=9F=94=A7refactor:=20remove=20types.rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types.rs | 177 ----------------------------------------------------------- 1 file changed, 177 deletions(-) delete mode 100644 src/types.rs (limited to 'src/types.rs') diff --git a/src/types.rs b/src/types.rs deleted file mode 100644 index e0397a1..0000000 --- a/src/types.rs +++ /dev/null @@ -1,177 +0,0 @@ -use futures_util::StreamExt; -use serde::{Deserialize, Serialize}; -use std::path::PathBuf; -use tokio::{fs, io::AsyncWriteExt}; - -use crate::{appimages_dir, index_dir, make_progress_bar}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct AppImage { - pub file_path: PathBuf, - pub executable: String, - pub source: Source, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Source { - pub identifier: String, - pub meta: SourceMetadata, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct SourceMetadata { - pub url: String, -} - -#[derive(Debug)] -pub struct PackageManager { - pub downloader: Downloader, - pub index: Index, - pub symlink_manager: SymlinkManager, -} - -#[derive(Debug, Default)] -pub struct Downloader {} - -#[derive(Debug, Default)] -pub struct Index {} - -#[derive(Debug, Default)] -pub struct SymlinkManager {} - -impl PackageManager { - pub async fn install( - appimage: &AppImage, - appname: &str, - ) -> Result<(), Box> { - if index_dir() - .join(format!("{}.json", &appimage.executable)) - .exists() - { - Err(format!("{} is already installed.", &appimage.executable).into()) - } else { - // Try to extract filename from URL or use default - let url = &appimage.source.meta.url; - let filename = match url.split('/').next_back() { - Some(name) => name.to_string(), - None => format!("{}.AppImage", appimage.executable), - }; - let path = &appimages_dir().join(filename); - - let downloader = crate::Downloader::new(); - downloader.download_with_progress(url, path).await?; - - let index = crate::Index::new(); - index.add(appimage, appname).await?; - - let sm = crate::SymlinkManager::new(); - sm.create(appimage).await?; - Ok(()) - } - } - pub async fn remove(appname: &str) -> Result<(), Box> { - let index_file_path = index_dir().join(format!("{appname}.json")); - let index_file_content = fs::read_to_string(&index_file_path).await?; - let appimage: AppImage = serde_json::from_str(&index_file_content)?; - - let home = std::env::var("HOME")?; - let symlink_path = PathBuf::from(home) - .join(".local/bin") - .join(&appimage.executable); - let index_path = index_dir().join(format!("{}.json", &appimage.executable)); - - fs::remove_file(&appimage.file_path).await?; - fs::remove_file(symlink_path).await?; - fs::remove_file(index_path).await?; - - Ok(()) - } -} - -impl Downloader { - pub fn new() -> Self { - Self {} - } - pub async fn download_with_progress( - &self, - url: &str, - path: &PathBuf, - ) -> Result<(), Box> { - fs::create_dir_all(&appimages_dir()).await?; - - let resp = reqwest::get(&url.to_string()).await?; - let total_size = resp.content_length().unwrap_or(0); - - let bar = make_progress_bar(total_size); - let mut out = tokio::fs::File::create(&path).await?; - - // Stream download with progress updates - let mut stream = resp.bytes_stream(); - while let Some(chunk) = stream.next().await { - let chunk = chunk?; - let len = chunk.len() as u64; - out.write_all(&chunk).await?; - bar.inc(len); - } - - bar.finish_with_message("Download complete!"); - - // Make executable - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - let mut perms = fs::metadata(&path).await?.permissions(); - perms.set_mode(0o755); - fs::set_permissions(&path, perms).await?; - } - - Ok(()) - } -} - -impl Index { - pub fn new() -> Self { - Self {} - } - pub async fn add( - &self, - appimage: &AppImage, - appname: &str, - ) -> Result<(), Box> { - fs::create_dir_all(&index_dir()).await?; - - let index_file = &index_dir().join(format!("{appname}.json")); - - let json = serde_json::to_string_pretty(appimage)?; - fs::write(index_file, json).await?; - - Ok(()) - } -} - -impl SymlinkManager { - pub fn new() -> Self { - Self {} - } - pub async fn create(&self, appimage: &AppImage) -> Result<(), Box> { - let home = std::env::var("HOME")?; - let local_bin = PathBuf::from(home).join(".local/bin"); - - fs::create_dir_all(&local_bin).await?; - - let symlink_path = local_bin.join(&appimage.executable); - - #[cfg(unix)] - { - use tokio::fs; - - if symlink_path.exists() { - fs::remove_file(&symlink_path).await?; - } - - std::os::unix::fs::symlink(&appimage.file_path, &symlink_path)?; - } - - Ok(()) - } -} -- cgit v1.2.3