diff options
| author | Namilskyy <alive6863@gmail.com> | 2025-12-06 16:36:44 +0300 |
|---|---|---|
| committer | Namilskyy <alive6863@gmail.com> | 2025-12-06 16:36:44 +0300 |
| commit | def46ae74c3f5974ed448e9877b0e0067a8e67d2 (patch) | |
| tree | 4eda9fe8b6da96ea8f1824a14235286fe6e49c72 /src/pkgtoolkit/index.rs | |
| parent | 79c8ecb6bf4d2fc2df5c90007e7c26b456ddc33f (diff) | |
Big code-cleaning in pkgtoolkit, implemented much functions and fixed logical mistakes
Diffstat (limited to 'src/pkgtoolkit/index.rs')
| -rw-r--r-- | src/pkgtoolkit/index.rs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/pkgtoolkit/index.rs b/src/pkgtoolkit/index.rs new file mode 100644 index 0000000..37e02e4 --- /dev/null +++ b/src/pkgtoolkit/index.rs @@ -0,0 +1,135 @@ +use std::{ + fs::{self, File, create_dir_all}, + io, + path::Path, +}; + +use flate2::read::GzDecoder; +use tar::Archive; +use toml; + +use super::types::{Index, Install, Package}; + +#[allow(dead_code)] +pub trait IndexOperations { + fn gen_index(repo_path: &str) -> Result<bool, std::io::Error>; +} + +impl IndexOperations for Package { + /// Generates an INDEX.toml file for a given repository directory. + /// + /// This function scans the `repo_path` directory for `.mesk` files. + /// For each `.mesk` file found, it extracts the `INSTALL` metadata to get package details. + /// It then collects all package information and serializes it into an `INDEX.toml` file + /// located in the root of the `repo_path` directory. + /// If `license` or `descr` fields are missing in the `INSTALL` file, they are set to empty strings (""). + /// + /// # Arguments + /// * `repo_path` - A string slice representing the path to the repository directory. + /// + /// # Errors + /// + /// Returns an error if: + /// - The `repo_path` directory cannot be read. + /// - An `.mesk` file cannot be opened or read. + /// - The `INSTALL` file cannot be extracted from an archive. + /// - The `INSTALL` file content cannot be parsed as TOML. + /// - The final `INDEX.toml` file cannot be written to disk. + fn gen_index(repo_path: &str) -> Result<bool, std::io::Error> { + let repo_dir = Path::new(repo_path); + if !repo_dir.is_dir() { + return Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("Repository directory does not exist: {}", repo_path), + )); + } + + let mut all_packages = Vec::new(); + + for entry_res in fs::read_dir(repo_path)? { + let entry = entry_res?; + let path = entry.path(); + + if path.extension().and_then(|s| s.to_str()) == Some("mesk") { + log::info!("Processing archive for index: {}", path.display()); + + let temp_extract_dir = std::env::temp_dir().join(format!( + "mesk_index_temp_{}", + path.file_stem().unwrap_or_default().to_string_lossy() + )); + create_dir_all(&temp_extract_dir)?; + + let file = File::open(&path)?; + let gz = GzDecoder::new(file); + let mut archive = Archive::new(gz); + + for tar_entry_res in archive.entries()? { + let mut tar_entry = tar_entry_res?; + let entry_path = tar_entry.path()?; + if entry_path.file_name().and_then(|n| n.to_str()) == Some("INSTALL") { + if let Some(parent_name) = entry_path + .parent() + .and_then(|p| p.file_name()) + .and_then(|n| n.to_str()) + { + let install_extract_path = + temp_extract_dir.join(parent_name).join("INSTALL"); + if let Some(parent_dir) = install_extract_path.parent() { + create_dir_all(parent_dir)?; + } + tar_entry.unpack(&install_extract_path)?; + log::debug!( + "Extracted INSTALL from {} to {}", + path.display(), + install_extract_path.display() + ); + + let install_content = fs::read_to_string(&install_extract_path)?; + let install_data: Install = toml::from_str(&install_content) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + let pkg_for_index = Package { + name: install_data.package.name, + version: install_data.package.version, + arch: install_data.package.arch, + descr: Some( + install_data.package.descr.unwrap_or_default(), + ), + license: Some( + install_data + .package + .license + .unwrap_or_default(), + ), + url: install_data.package.url, + }; + + all_packages.push(pkg_for_index); + break; + } else { + log::warn!( + "INSTALL file in archive {} has unexpected path structure, skipping.", + path.display() + ); + } + } + } + fs::remove_dir_all(&temp_extract_dir)?; + } + } + + let index = Index { + packages: all_packages, + }; + + let index_toml_content = toml::to_string_pretty(&index) + .map_err(|e| std::io::Error::other(format!("Failed to serialize INDEX.toml: {}", e)))?; + + let index_path = repo_dir.join("INDEX.toml"); + fs::write(&index_path, index_toml_content) + .map_err(|e| std::io::Error::other(format!("Failed to write INDEX.toml: {}", e)))?; + + log::info!("Successfully generated INDEX.toml at {:?}", index_path); + Ok(true) + } +} |
