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/archive.rs | |
| parent | e7c49d685efe768c0c1d9c66da7b93b6e118b305 (diff) | |
Fixed logical issues
Diffstat (limited to 'src/pkgtoolkit/archive.rs')
| -rw-r--r-- | src/pkgtoolkit/archive.rs | 136 |
1 files changed, 111 insertions, 25 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, |
