diff options
| author | Namilskyy <alive6863@gmail.com> | 2025-12-07 14:29:35 +0300 |
|---|---|---|
| committer | Namilskyy <alive6863@gmail.com> | 2025-12-07 14:29:35 +0300 |
| commit | 778a979e2e774e1b2e91227fa2db2e56d41927c1 (patch) | |
| tree | ae1560e203477a90edc089c1832e37af83f43540 /src/pkgtoolkit | |
| parent | e7c49d685efe768c0c1d9c66da7b93b6e118b305 (diff) | |
Fixed logical issues
Diffstat (limited to 'src/pkgtoolkit')
| -rw-r--r-- | src/pkgtoolkit/archive.rs | 136 | ||||
| -rw-r--r-- | src/pkgtoolkit/build.rs | 11 | ||||
| -rw-r--r-- | src/pkgtoolkit/git_source.rs | 47 |
3 files changed, 141 insertions, 53 deletions
diff --git a/src/pkgtoolkit/archive.rs b/src/pkgtoolkit/archive.rs index 9d9a7d1..eef0888 100644 --- a/src/pkgtoolkit/archive.rs +++ b/src/pkgtoolkit/archive.rs @@ -39,21 +39,105 @@ impl ArchiveOperations for Package { let cache_dir = &config.paths.cache_dir; create_dir_all(cache_dir)?; - for meta_name in ["INSTALL", "SETTS", "BUILD"] { - let meta_path = Path::new(cache_dir).join(meta_name); - if meta_path.exists() { - fs::remove_file(&meta_path)?; - } + // Extract to temporary directory first + let temp_dir = Path::new(cache_dir).join("temp_extract"); + if temp_dir.exists() { + fs::remove_dir_all(&temp_dir)?; } + fs::create_dir_all(&temp_dir)?; + let file = File::open(path_to_archive)?; let gz = GzDecoder::new(file); let mut archive = Archive::new(gz); - // Unpack directly into the cache directory. Игнорируем AlreadyExists, чтобы не мешать валидации. - match archive.unpack(cache_dir) { + + // Unpack into temporary directory + match archive.unpack(&temp_dir) { Ok(()) => Ok(()), Err(e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()), Err(e) => Err(e), + }?; + + // Read package name from INSTALL file to determine final directory + let install_path = temp_dir.join("INSTALL"); + if !install_path.exists() { + // Try to find INSTALL in subdirectories + for entry in fs::read_dir(&temp_dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + let install_in_subdir = path.join("INSTALL"); + if install_in_subdir.exists() { + // Move contents to temp_dir + for item in fs::read_dir(&path)? { + let item = item?; + let item_path = item.path(); + let dest_path = temp_dir.join(item_path.file_name().unwrap()); + fs::rename(&item_path, &dest_path)?; + } + fs::remove_dir(&path)?; + break; + } + } + } + } + + let mut install_path = None; + let mut pkg_dir_name = None; + + let root_install = temp_dir.join("INSTALL"); + if root_install.exists() { + install_path = Some(root_install); + pkg_dir_name = Some("package".to_string()); + } else { + for entry in fs::read_dir(&temp_dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + let install_in_subdir = path.join("INSTALL"); + if install_in_subdir.exists() { + install_path = Some(install_in_subdir); + pkg_dir_name = Some(path.file_name().unwrap().to_string_lossy().to_string()); + break; + } + } + } + } + + let install_path = install_path.ok_or_else(|| { + io::Error::new( + io::ErrorKind::NotFound, + "INSTALL file not found in archive", + ) + })?; + + let install_content = fs::read_to_string(&install_path)?; + let install_meta: Install = toml::from_str(&install_content) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + let final_dir_name = format!("{}-{}", install_meta.package.name, install_meta.package.version); + let final_dir = Path::new(cache_dir).join(&final_dir_name); + + if final_dir.exists() { + fs::remove_dir_all(&final_dir)?; } + fs::create_dir_all(&final_dir)?; + + if pkg_dir_name.clone().unwrap() == "package" { + for entry in fs::read_dir(&temp_dir)? { + let entry = entry?; + let src_path = entry.path(); + let dest_path = final_dir.join(src_path.file_name().unwrap()); + fs::rename(&src_path, &dest_path)?; + } + fs::remove_dir(&temp_dir)?; + } else { + let pkg_subdir = temp_dir.join(pkg_dir_name.clone().unwrap()); + fs::rename(&pkg_subdir, &final_dir)?; + + fs::remove_dir(&temp_dir)?; + } + + Ok(()) } /// Load meta information from the .mesk archive. @@ -72,7 +156,7 @@ impl ArchiveOperations for Package { /// is not found, or if the 'INSTALL' file is empty. #[allow(clippy::type_complexity)] fn loadmeta( - minimal_package_meta: &mut Self, + minimal_package_meta: &mut Package, ) -> Result<(Install, Option<Setts>, Option<Build>), std::io::Error> { // Changed return type for more flexibility /* @@ -82,34 +166,38 @@ impl ArchiveOperations for Package { version = "1.0.0" arch = "X86_64" descr = "Just example INSTALL script" + license = "BSD-2-Clause" + url = "/repo/my-package.mesk" + git_repo = "https://github.com/example/my-package.git" [install] path = "/usr/bin/my-package" + dependencies = ["package", "i2pd", "llvm-19-devel", "etc..."] # Leave it empty if there are no dependencies user = "root" group = "root" mode = "755" - # Also [install] can be - # path = "/usr/bin/my-package" - # user = "root" - # group = "root" - # mode = "755" - # custom_script = "./install.sh" OR - # custom_script = """ - # echo "Installing my-package" - # sudo apt-get install my-package - # """ + Also [install] can be + path = "/usr/bin/my-package" + user = "root" + group = "root" + mode = "755" + custom_script = "./install.sh" OR + custom_script = """ + echo "Installing my-package" + sudo apt-get install my-package + """ + If there is a custom_script field, mesk will not automatically install your package and other fields in [install] will not be required. */ - let config = Config::parse().map_err(|e| std::io::Error::other(e.to_string()))?; fs::create_dir_all(&config.paths.cache_dir)?; let cache_dir = &config.paths.cache_dir; - let install_path = - Path::new(cache_dir).join(format!("{}/INSTALL", minimal_package_meta.name)); - let setts_path = Path::new(cache_dir).join(format!("{}/SETTS", minimal_package_meta.name)); - let build_path = Path::new(cache_dir).join(format!("{}/BUILD", minimal_package_meta.name)); + let pkg_dir_name = format!("{}-{}", minimal_package_meta.name, minimal_package_meta.version); + let install_path = Path::new(cache_dir).join(format!("{}/INSTALL", pkg_dir_name)); + let setts_path = Path::new(cache_dir).join(format!("{}/SETTS", pkg_dir_name)); + let build_path = Path::new(cache_dir).join(format!("{}/BUILD", pkg_dir_name)); if !install_path.exists() { return Err(io::Error::new( @@ -171,7 +259,6 @@ impl ArchiveOperations for Package { let config = Config::parse().map_err(|e| std::io::Error::other(e.to_string()))?; let cache_root = Path::new(&config.paths.cache_dir); - // Рекурсивно находим все файлы INSTALL под cache_root fn find_install(root: &Path) -> Result<Vec<std::path::PathBuf>, std::io::Error> { let mut installs = Vec::new(); for entry in fs::read_dir(root)? { @@ -208,7 +295,6 @@ impl ArchiveOperations for Package { ) })?; - // Проверим, что структура именно <cachedir>/<packagename>/INSTALL if pkg_dir.parent() != Some(cache_root) { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, diff --git a/src/pkgtoolkit/build.rs b/src/pkgtoolkit/build.rs index a323521..6264b58 100644 --- a/src/pkgtoolkit/build.rs +++ b/src/pkgtoolkit/build.rs @@ -26,7 +26,6 @@ impl BuildOperations for Package { let config = Config::parse().map_err(|e| std::io::Error::other(e.to_string()))?; let build_dir = Path::new(&config.paths.cache_dir).join(format!("{}-{}", self.name, self.version)); - // Check if build directory exists if !build_dir.exists() { return Err(std::io::Error::other(format!( "Build directory not found: {}", @@ -34,7 +33,6 @@ impl BuildOperations for Package { ))); } - // Prepare environment variables let mut cmd_envs: Vec<(String, String)> = Vec::new(); if let Some(ref env_vars) = build_meta.env { for env_line in env_vars.lines() { @@ -44,12 +42,10 @@ impl BuildOperations for Package { } } - // Handle custom build script if provided if let Some(ref script) = build_meta.script { log::info!("Executing custom build script: {}", script); Self::validate_custom_script(script)?; - let mut cmd = if script.starts_with("./") || script.contains('/') { - // Assume it's a file path + let mut cmd = if script.starts_with("./") || script.starts_with('/') { let script_path = build_dir.join(script); if !script_path.exists() { return Err(std::io::Error::other(format!( @@ -62,7 +58,6 @@ impl BuildOperations for Package { inner_cmd.arg(script_path.to_str().unwrap()); inner_cmd } else { - // Inline script let mut inner_cmd = Command::new("/bin/sh"); inner_cmd.arg("-c"); inner_cmd.arg(script); @@ -121,7 +116,7 @@ impl BuildOperations for Package { } } BuildSystems::CMake => { - // Check for CMakeLists.txt + let cmake_file = build_dir.join("CMakeLists.txt"); if !cmake_file.exists() { return Err(std::io::Error::other(format!( @@ -153,7 +148,6 @@ impl BuildOperations for Package { ))); } - // Now build let mut build_cmd = Command::new("make"); build_cmd.current_dir(&build_dir_build); build_cmd.arg("-j").arg(num_cpus::get().to_string()); // Parallel build @@ -174,7 +168,6 @@ impl BuildOperations for Package { } } BuildSystems::Meson => { - // Check for meson.build let meson_file = build_dir.join("meson.build"); if !meson_file.exists() { return Err(std::io::Error::other(format!( diff --git a/src/pkgtoolkit/git_source.rs b/src/pkgtoolkit/git_source.rs index 2f33c14..0bedf0a 100644 --- a/src/pkgtoolkit/git_source.rs +++ b/src/pkgtoolkit/git_source.rs @@ -1,8 +1,8 @@ +use crate::cfg::config::Config; +use crate::pkgtoolkit::types::Package; +use git2::Repository; use std::fs; use std::path::Path; -use git2::Repository; -use crate::pkgtoolkit::types::Package; -use crate::cfg::config::Config; use toml; pub struct GitSource; @@ -15,8 +15,13 @@ impl GitSource { } /// Get source code for a package from its git repository - pub fn get_package_source(package: &Package, config: &Config) -> Result<String, Box<dyn std::error::Error>> { - let git_repo = package.git_repo.as_ref() + pub fn get_package_source( + package: &Package, + config: &Config, + ) -> Result<String, Box<dyn std::error::Error>> { + let git_repo = package + .git_repo + .as_ref() .ok_or("Package does not have a git repository specified")?; let source_dir = Path::new(&config.paths.cache_dir) @@ -31,53 +36,57 @@ impl GitSource { let source_path = source_dir.to_string_lossy().to_string(); println!("Source code downloaded to: {}", source_path); - + Ok(source_path) } /// Get source code for a package by name, first checking INSTALL file, then falling back to index - pub fn get_source_by_name(pkg_name: &str, config: &Config) -> Result<String, Box<dyn std::error::Error>> { - // First try to get git_repo from INSTALL file in cache + pub fn get_source_by_name( + pkg_name: &str, + config: &Config, + ) -> Result<String, Box<dyn std::error::Error>> { let install_path = Path::new(&config.paths.cache_dir).join(format!("{}/INSTALL", pkg_name)); - + if install_path.exists() { let install_content = fs::read_to_string(&install_path)?; let install_data: crate::pkgtoolkit::types::Install = toml::from_str(&install_content) .map_err(|e| format!("Failed to parse INSTALL file: {}", e))?; - + // Check if InstallMeta has git_repo if let Some(git_repo) = install_data.install.git_repo { println!("Found git repository in INSTALL file: {}", git_repo); - + let source_dir = Path::new(&config.paths.cache_dir) .join("sources") .join(&install_data.package.name) .join(&install_data.package.version); fs::create_dir_all(&source_dir)?; - + println!("Cloning {} from {}", install_data.package.name, git_repo); Self::clone_repo(&git_repo, &source_dir)?; - + let source_path = source_dir.to_string_lossy().to_string(); println!("Source code downloaded to: {}", source_path); - + return Ok(source_path); } } - + // Fall back to index if INSTALL file doesn't exist or doesn't have git_repo let index_path = Path::new(&config.paths.cache_dir).join("INDEX.toml"); - + if !index_path.exists() { return Err("Index file not found. Please run 'mesk update' first.".into()); } let index_content = fs::read_to_string(&index_path)?; - let index: crate::pkgtoolkit::types::Index = toml::from_str(&index_content) - .map_err(|e| format!("Failed to parse index: {}", e))?; + let index: crate::pkgtoolkit::types::Index = + toml::from_str(&index_content).map_err(|e| format!("Failed to parse index: {}", e))?; - let package = index.packages.iter() + let package = index + .packages + .iter() .find(|pkg| pkg.name == pkg_name) .ok_or(format!("Package '{}' not found in index", pkg_name))?; |
