summaryrefslogtreecommitdiff
path: root/src/pkgtoolkit/index.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkgtoolkit/index.rs')
-rw-r--r--src/pkgtoolkit/index.rs135
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)
+ }
+}