From 1c3b561fa8d7a370651c77f6b8e22c8aa9c8d9f1 Mon Sep 17 00:00:00 2001 From: Namilskyy Date: Tue, 9 Dec 2025 17:54:00 +0300 Subject: Fix multibinary installing --- src/main.rs | 2 - src/pkgtoolkit/git_source.rs | 1 - src/pkgtoolkit/install.rs | 121 +++++++++++++++++++++++++++---------------- 3 files changed, 75 insertions(+), 49 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4de9e55..bc019c8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,7 +78,6 @@ struct RemoteInstallArgs { #[tokio::main] async fn main() -> Result<(), Box> { - let cli: Cli = Cli::parse(); match &cli.command { @@ -211,7 +210,6 @@ async fn main() -> Result<(), Box> { pkg.install()?; println!("Package '{}' installed successfully.", pkg.name); } else { - let config = Config::parse().unwrap(); if args.http { println!("Installing {} via HTTP", pkgname); diff --git a/src/pkgtoolkit/git_source.rs b/src/pkgtoolkit/git_source.rs index 0bedf0a..d20feb0 100644 --- a/src/pkgtoolkit/git_source.rs +++ b/src/pkgtoolkit/git_source.rs @@ -73,7 +73,6 @@ impl GitSource { } } - // 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() { diff --git a/src/pkgtoolkit/install.rs b/src/pkgtoolkit/install.rs index 37155c2..4eeff2f 100644 --- a/src/pkgtoolkit/install.rs +++ b/src/pkgtoolkit/install.rs @@ -88,18 +88,26 @@ impl InstallOperations for Package { ))); } - let staging_dir = Path::new(&config.paths.cache_dir).join("staging"); - create_dir_all(&staging_dir)?; - all_files = Self::collect_files_from_dir(&staging_dir, &staging_dir)? + let build_dir = + Path::new(&config.paths.cache_dir).join(format!("{}-{}", self.name, self.version)); + let target_release = build_dir.join("target/release"); + + if !target_release.exists() { + return Err(std::io::Error::other(format!( + "target/release directory not found: {}", + target_release.display() + ))); + } + + all_files = Self::collect_files_from_dir(&target_release, &target_release)? .iter() - .map(|rel| format!("/{}", rel)) // Преобразуйте в абсолютные пути (предполагаем root=/) + .map(|rel| format!("/{}", rel)) .collect(); for file in &all_files { - let src = staging_dir.join(file.trim_start_matches('/')); - let dest = Path::new(file); + let src = target_release.join(file.trim_start_matches('/')); + let dest = Path::new(&install_meta.install.path).join(file.trim_start_matches('/')); - // Check if source file exists if !src.exists() { log::warn!("Source file not found: {:?}, skipping", src); continue; @@ -109,7 +117,7 @@ impl InstallOperations for Package { create_dir_all(parent)?; } - fs::copy(&src, dest).map_err(|e| { + fs::copy(&src, &dest).map_err(|e| { std::io::Error::other(format!( "Failed to copy {} to {}: {}", src.display(), @@ -117,16 +125,45 @@ impl InstallOperations for Package { e )) })?; - // TODO: Set proper permissions - } - fs::remove_dir_all(&staging_dir)?; + // Set permissions + let mode = u32::from_str_radix(&install_meta.install.mode, 8).map_err(|_| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Invalid mode string in INSTALL", + ) + })?; + let perms = Permissions::from_mode(mode); + set_permissions(&dest, perms).map_err(|e| { + std::io::Error::other(format!( + "Failed to set permissions for {}: {}", + dest.display(), + e + )) + })?; + + let output = Command::new("chown") + .arg(format!( + "{}:{}", + install_meta.install.user, install_meta.install.group + )) + .arg(&dest) + .output() + .map_err(|e| std::io::Error::other(format!("'chown' command failed: {}", e)))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + log::warn!( + "Warning: 'chown' command failed for {} (requires root?):\n{}", + dest.display(), + stderr + ); + } + } } else { log::info!( "No BUILD file or it's empty. Treating as binary package. Installing via INSTALL config or custom script." ); - - // Validate custom script before execution if let Some(ref script) = install_meta.install.custom_script { Self::validate_custom_script(script)?; } @@ -169,10 +206,8 @@ impl InstallOperations for Package { dest_path.to_string_lossy().ends_with('/') ); - // Check if dest_path is a directory, if so, copy all executables from target/release if dest_path.is_dir() || dest_path.to_string_lossy().ends_with('/') { log::info!("Taking multi-binary package path"); - // Multi-binary package - copy all executables from target/release let target_release = build_dir.join("target/release"); if !target_release.exists() { return Err(std::io::Error::other(format!( @@ -181,7 +216,6 @@ impl InstallOperations for Package { ))); } - // Create destination directory if it doesn't exist create_dir_all(dest_path).map_err(|e| { std::io::Error::other(format!("Failed to create dest dir: {}", e)) })?; @@ -191,41 +225,36 @@ impl InstallOperations for Package { let entry = entry?; let path = entry.path(); - // Check if it's an executable file - if path.is_file() - && let Ok(metadata) = fs::metadata(&path) { - let mode = metadata.permissions().mode(); + if path.is_file() + && let Ok(metadata) = fs::metadata(&path) + { + let mode = metadata.permissions().mode(); + log::debug!("Checking file: {:?}, mode: {:o}", path.file_name(), mode); + if mode & 0o111 != 0 { + let file_name = path.file_name().unwrap().to_string_lossy(); + let dest_file = dest_path.join(&*file_name); + + log::info!( + "Copying executable: {} to {}", + file_name, + dest_file.display() + ); + fs::copy(&path, &dest_file).map_err(|e| { + std::io::Error::other(format!( + "Failed to copy {}: {}", + file_name, e + )) + })?; + + copied_files.push(dest_file); + } else { log::debug!( - "Checking file: {:?}, mode: {:o}", + "File {:?} is not executable (mode: {:o})", path.file_name(), mode ); - if mode & 0o111 != 0 { - let file_name = path.file_name().unwrap().to_string_lossy(); - let dest_file = dest_path.join(&*file_name); - - log::info!( - "Copying executable: {} to {}", - file_name, - dest_file.display() - ); - fs::copy(&path, &dest_file).map_err(|e| { - std::io::Error::other(format!( - "Failed to copy {}: {}", - file_name, e - )) - })?; - - copied_files.push(dest_file); - } else { - log::debug!( - "File {:?} is not executable (mode: {:o})", - path.file_name(), - mode - ); - } } - + } } if copied_files.is_empty() { -- cgit v1.2.3