use std::fs; use std::path::Path; use std::process::Command; use std::process; use super::*; use crate::utils::parser; use crate::utils::hardcopy::hardcopy; pub fn install(repo: &String, pkgname: &String) -> Result<(), bool> { let var_path = get_var_path(); let pkg_md_path = var_path.join(format!("{}/{}.md", repo, pkgname)); if !pkg_md_path.exists() { match parser::get_repo_addr(repo) { Ok(repo_addr) => { let rsync_command = format!( "rsync --include='{}.md' --exclude='*' {} {}", pkgname, repo_addr, pkg_md_path.to_str().unwrap() ); let rsync_output = Command::new("sh") .arg("-c") .arg(rsync_command) .output() .expect("Failed to execute rsync"); if !rsync_output.status.success() { eprintln!("broken repo: {}", repo); return Err(false); } if !pkg_md_path.exists() { eprintln!("not found {} in {} repo", pkgname, repo); return Err(true); } } Err(e) => { eprintln!("Repository {} not found: {}", repo, e); return Err(false); } } } let deps = match parser::get_deps(&pkg_md_path) { Ok(deps) => deps, Err(e) => { eprintln!("Failed to parse dependencies {}: {}", &pkg_md_path.to_str().unwrap(), e); return Err(false); } }; for dependency in deps.lines() { let dependency = dependency.trim(); if !dependency.is_empty() { let pkg_dir = Path::new("/pkg").join(repo).join(dependency); if !pkg_dir.exists() { match install(repo, &dependency.to_string()) { Ok(()) => {} Err(_) => {process::exit(1) } } } } } let url = match parser::get_url(&pkg_md_path) { Ok(url) => url, Err(e) => { eprintln!("Failed to parse URL: {}", e); return Err(false); } }; let src = Path::new("/pkg/src"); fs::create_dir_all(&src).expect("Failed to create src directory"); let wget_command: String; let src_dir: String; if url.ends_with(".tar.gz") { wget_command = format!("wget -O- {} | tar -xz -C {}", url, src.to_str().unwrap()); src_dir = format!( "{}/{}", src.to_str().unwrap(), url .rsplit('/') .next() .expect("Failed to extract archive name from URL") .trim_end_matches(".tar.gz")) } else if url.ends_with(".tar.xz") { wget_command = format!("wget -O- {} | tar -xJ -C {}", url, src.to_str().unwrap()); src_dir = format!( "{}/{}", src.to_str().unwrap(), url .rsplit('/') .next() .expect("Failed to extract archive name from URL") .trim_end_matches(".tar.xz")) } else { eprintln!("Unsupported archive format for URL: {}", url); return Err(false); } println!("Downloading and extracting package from: {}", url); let wget_output = Command::new("sh") .arg("-c") .arg(wget_command) .output() .expect("Failed to execute wget and tar"); if !wget_output.status.success() { eprintln!("Failed to download and extract package: {}", String::from_utf8_lossy(&wget_output.stderr)); return Err(false); } // 3. Выполнение bash-скрипта сборки let build_script = match parser::get_build_script(&pkg_md_path) { Ok(script) => script, Err(e) => { eprintln!("Failed to parse build script: {}", e); return Err(false); } }; println!("{}", &src_dir); let build_output = Command::new("sh") .arg("-c") .arg(build_script) .current_dir(&src_dir) .output() .expect("Failed to execute build script"); if !build_output.status.success() { eprintln!("Build failed: {}", String::from_utf8_lossy(&build_output.stderr)); return Err(false); } let build_script_dest = Path::new("/pkg") .join(repo) .join(pkgname) .join("build-script.md"); fs::copy(&pkg_md_path, &build_script_dest).expect("Failed to copy build script"); let pkg_dir = Path::new("/pkg").join(repo).join(pkgname); hardcopy( &pkg_dir.join("bin"), &Path::new("/pkg").join(repo).join("bin"), ).expect("Failed to copy bin directory"); hardcopy( &pkg_dir.join("include"), &Path::new("/pkg").join(repo).join("include"), ).expect("Failed to copy include directory"); hardcopy( &pkg_dir.join("lib"), &Path::new("/pkg").join(repo).join("lib"), ).expect("Failed to copy lib directory"); fs::remove_dir_all(&src_dir).expect("Failed to clean up src directory"); println!("Package {} installed successfully from repo {}", pkgname, repo); Ok(()) }