summaryrefslogtreecommitdiff
path: root/src/pkgtoolkit/pkgtools.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkgtoolkit/pkgtools.rs')
-rw-r--r--src/pkgtoolkit/pkgtools.rs205
1 files changed, 169 insertions, 36 deletions
diff --git a/src/pkgtoolkit/pkgtools.rs b/src/pkgtoolkit/pkgtools.rs
index 5acbd11..cfd3d59 100644
--- a/src/pkgtoolkit/pkgtools.rs
+++ b/src/pkgtoolkit/pkgtools.rs
@@ -6,8 +6,10 @@ use std::{
io,
path::Path,
process::Command,
- str};
+ str,
+ os::unix::fs::PermissionsExt};
+ use emissary_core::i2np::tunnel::build;
// use emissary_core::i2np::tunnel::build;
use flate2::read::GzDecoder;
use serde::{Deserialize, Serialize};
@@ -81,44 +83,74 @@ impl archs {
#[allow(dead_code)]
impl Package {
- fn builder_backend(&mut self) -> Result<bool, std::io::Error> {
- let config: Config = Config::parse().unwrap();
- let metadata = Self::loadmeta(self).unwrap();
- let path = Path::new(&config.paths.cache_dir).join(format!("{}-{}/BUILD", metadata.0.package.name, metadata.0.package.version));
- let _ = create_dir_all(&path);
-
- if metadata.2.is_none() {
- Err(std::io::Error::new(std::io::ErrorKind::NotFound, "BUILD file not found"))?
- }
-
- match metadata.2.unwrap().build_system {
+ /// Execute the build script for the package.
+ ///
+ /// This function takes the `Build` meta information as an argument and
+ /// executes the build script accordingly. It also handles the different
+ /// build systems supported (Make, CMake, Meson, Cargo).
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the build command fails.
+ fn execute_build(&self, build_meta: &Build) -> Result<(), std::io::Error> {
+ let config = Config::parse()
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
+ let build_dir = Path::new(&config.paths.cache_dir)
+ .join(format!("{}-{}", self.name, self.version));
+
+ let mut cmd = match build_meta.build_system {
BuildSystems::Make => {
- let _setup = Command::new("make")
- .arg("all")
- .arg("all")
- .output();
+ let mut c = Command::new("make");
+ c.current_dir(&build_dir);
+ if build_meta.script.is_some() {
+ c.arg("-f").arg(build_meta.script.as_ref().unwrap());
+ }
+ c.arg("all");
+ c
}
-
BuildSystems::CMake => {
- let _setup = Command::new("cmake")
- .arg("-S")
- .arg(&path)
- .arg("-B")
- .arg(&path)
- .output();
-
- let _make = Command::new("make")
- .arg("-C")
- .arg(&path)
- .output();
+ let build_dir_build = build_dir.join("build");
+ create_dir_all(&build_dir_build)?;
+ let mut c = Command::new("cmake");
+ c.arg("-S").arg(&build_dir)
+ .arg("-B").arg(&build_dir_build)
+ .current_dir(&build_dir);
+ c
}
-
- _ => {
- Err(std::io::Error::new(std::io::ErrorKind::NotFound, "BUILD file not found"))?
+ BuildSystems::Meson => {
+ let build_dir_build = build_dir.join("build");
+ create_dir_all(&build_dir_build)?;
+ let mut c = Command::new("meson");
+ c.arg("setup")
+ .arg(&build_dir_build)
+ .current_dir(&build_dir);
+ c
+ }
+ BuildSystems::Cargo => {
+ let mut c = Command::new("cargo");
+ c.arg("build")
+ .arg("--release")
+ .current_dir(&build_dir);
+ c
}
+ };
+
+ let output = cmd.output().map_err(|e| {
+ std::io::Error::new(
+ std::io::ErrorKind::Other,
+ format!("Build command failed: {}", e),
+ )
+ })?;
+
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ format!("Build failed:\n{}", stderr),
+ ));
}
- Ok(true)
+ Ok(())
}
/// Extracts a .tar.gz archive to the cache directory specified in Config.
@@ -366,15 +398,116 @@ impl Package {
}
Strategies::SOURCE => {
log::info!("Strategy: SOURCE; Running default build hook.");
- todo!();
+ let _ = self.execute_build(&build_meta.unwrap());
}
}
Ok(true)
}
- pub fn install() -> Result<bool, std::io::Error> {
- todo!();
- }
+
+
+ /// Installs the package according to the INSTALL file in the archive.
+ ///
+ /// There are two strategies for installing the package. If the BUILD file is empty, the package is assumed to be a binary package and the default install hook is skipped. If the BUILD file is not empty, the package is assumed to be a source package and the default build hook is skipped.
+ ///
+ /// If the BUILD file is empty and the INSTALL file contains a custom script, the custom script is run instead of the default install hook.
+ /// If the BUILD file is not empty and the INSTALL file contains a custom script, the custom script is ignored.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the BUILD file is invalid or if the build or install hook fails.
+ pub fn install(&mut self) -> Result<bool, std::io::Error> {
+ let config = Config::parse()
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
+ let (install_meta, _setts_meta, build_meta) = Self::loadmeta(self)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
+
+
+ let is_build_present_and_not_empty = build_meta.is_some();
+
+ if is_build_present_and_not_empty {
+ log::info!("Found BUILD file, preparing to build and install package: {}", self.name);
+ let build_meta_ref = build_meta.as_ref().unwrap();
+ self.execute_build(build_meta_ref);
+
+
+ if matches!(build_meta_ref.build_system, BuildSystems::Make) {
+ log::info!("Running 'make install' for package: {}", self.name);
+ let build_dir = Path::new(&config.paths.cache_dir)
+ .join(format!("{}-{}", self.name, self.version));
+ let output = Command::new("make")
+ .arg("install")
+ .current_dir(&build_dir)
+ .output()
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("'make install' failed: {}", e)))?;
+
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ format!("'make install' failed:\n{}", stderr),
+ ));
+ }
+ }
+ } else {
+ log::info!("No BUILD file or it's empty. Treating as binary package. Installing via INSTALL config or custom script.");
+ // Установка бинарного пакета
+ if let Some(ref script) = install_meta.custom_script {
+ log::info!("Executing custom install script for {}", install_meta.package.name);
+ let status = if script.starts_with("./") || script.contains('/') {
+ Command::new("/bin/sh").arg("-c").arg(script).status()
+ } else {
+ Command::new(script).status()
+ }
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to run custom script: {}", e)))?;
+
+ if !status.success() {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "Custom install script failed",
+ ));
+ }
+ } else {
+ log::info!("No custom script. Running default install hook for {}", install_meta.package.name);
+ // --- Дефолтный хук установки ---
+ // 1. Копируем файл из build_dir (предположим, что бинарный файл лежит в корне распакованного архива)
+ let source_file_name = &self.name; // Предполагаем имя файла = имя пакета
+ let build_dir = Path::new(&config.paths.cache_dir)
+ .join(format!("{}-{}", self.name, self.version));
+ let src_path = build_dir.join(source_file_name);
+ let dest_path = Path::new(&install_meta.path);
+
+ // Убедимся, что целевая директория существует
+ if let Some(parent) = dest_path.parent() {
+ create_dir_all(parent)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to create parent dir: {}", e)))?;
+ }
+
+ fs::copy(&src_path, dest_path)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to copy file: {}", e)))?;
+
+ let mode = u32::from_str_radix(&install_meta.mode, 8)
+ .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid mode string in INSTALL"))?;
+ let perms = PermissionsExt::from_mode(mode);
+ fs::set_permissions(dest_path, perms)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to set permissions: {}", e)))?;
+
+ let output = Command::new("chown")
+ .arg(&format!("{}:{}", install_meta.user, install_meta.group))
+ .arg(dest_path)
+ .output()
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("'chown' command failed: {}", e)))?;
+
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ log::warn!("Warning: 'chown' command failed (requires root?):\n{}", stderr);
+ }
+ }
+ }
+
+ log::info!("Package {} installed successfully.", self.name);
+ Ok(true)
+ }
pub fn gen_index() -> Result<bool, std::io::Error> {
todo!();