summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml8
-rw-r--r--examples/BUILD8
-rw-r--r--examples/INSTALL26
-rw-r--r--src/main.rs90
-rw-r--r--src/net/http_package.rs5
-rw-r--r--src/net/i2p_package.rs12
-rw-r--r--src/pkgtoolkit/archive.rs136
-rw-r--r--src/pkgtoolkit/build.rs11
-rw-r--r--src/pkgtoolkit/git_source.rs47
-rw-r--r--tests/pkgtoolkit_funcs.rs16
10 files changed, 241 insertions, 118 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 6c255df..a04c57e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,9 @@ license = "GPL-3.0"
authors = [ "namilsk <namilsk@namilsk.tech>",
"asya <asyamozgoff@gmail.com>" ]
description = "An i2p-based package manager developed by Anthrill project"
+categories = ["command-line-utilities"]
+repository = "https://codeberg.org/Anthrill/mesk.git"
+# or git.community.i2p/Namilsk/mesk
[dependencies]
clap = { version = "4.5.53", features = ["derive"] }
@@ -30,3 +33,8 @@ tempfile = "3.23.0"
tokio-test = "0.4.4"
uuid = { version = "1.19.0", features = ["v4"] }
+[profile.release]
+strip = true
+lto = true
+opt-level = "z"
+
diff --git a/examples/BUILD b/examples/BUILD
index 2684855..8ab88f5 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -1,5 +1,5 @@
# This field required, but its will change nothing if script = "" specified.
-build_system = "CMake" # For example, supported build systems:
+build_system = "Cargo" # For example, supported build systems:
# Enumerate from src/pkgtoolkit
# pub enum BuildSystems {
# Make,
@@ -10,10 +10,12 @@ build_system = "CMake" # For example, supported build systems:
# Environment variables, can be empty or removed
env = """
- export SHELL=/usr/bin/zsh
+ export RUSTFLAGS="-C target-cpu=native"
+ export CARGO_TARGET_DIR="$PWD/target"
"""
# Custom script like from INSTALL
script = """
- make -j6 -f build/Makefile all
+ cargo build --release --target-dir=target
+ strip target/release/mesk
"""
diff --git a/examples/INSTALL b/examples/INSTALL
index d33accf..f7191de 100644
--- a/examples/INSTALL
+++ b/examples/INSTALL
@@ -1,27 +1,31 @@
[package]
-name = "my-package"
-version = "1.0.0"
+name = "mesk"
+version = "0.1.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"
+descr = "Package manager for I2P network with CDN support"
+license = "MIT"
+url = "/repo/mesk.mesk"
+git_repo = "https://github.com/Anthrill/mesk.git"
[install]
-path = "/usr/bin/my-package"
-dependencies = ["package", "i2pd", "llvm-19-devel", "etc..."] # Leave it empty if there are no dependencies
+path = "/usr/bin/mesk"
+dependencies = ["openssl-devel", "zlib-devel", "gcc"] # Leave it empty if there are no dependencies
user = "root"
group = "root"
mode = "755"
# Also [install] can be
-# path = "/usr/bin/my-package"
+# path = "/usr/bin/mesk"
# user = "root"
# group = "root"
# mode = "755"
# custom_script = "./install.sh" OR
# custom_script = """
-# echo "Installing my-package"
-# sudo apt-get install my-package
+# echo "Installing mesk"
+# sudo cp target/release/mesk /usr/bin/mesk
+# sudo chmod 755 /usr/bin/mesk
+# sudo mkdir -p /etc/mesk
+# sudo mkdir -p /var/cache/mesk
+# sudo mkdir -p /var/lib/mesk
# """
# If there is a custom_script field, mesk will not automatically install your package and other fields in [install] will not be required. \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 2bdb29c..068a8fb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,10 +6,10 @@ use crate::cfg::config::Config;
use crate::net::{http_package::HTTPPackage, i2p_package::I2PPackage};
use crate::pkgtoolkit::Package;
-use crate::pkgtoolkit::index::IndexOperations;
-use crate::pkgtoolkit::git_source::GitSource;
use crate::pkgtoolkit::archive::ArchiveOperations;
use crate::pkgtoolkit::build::BuildOperations;
+use crate::pkgtoolkit::git_source::GitSource;
+use crate::pkgtoolkit::index::IndexOperations;
use clap::{Args, Parser, Subcommand};
use std::io::Write;
@@ -72,7 +72,6 @@ struct RemoteInstallArgs {
clean: bool,
}
-
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli: Cli = Cli::parse();
@@ -91,7 +90,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
Err(e) => {
log::error!("Failed to validate package '{}': {}", path, e);
- return Err(e.into());
+ return Err(e.into());
}
}
return Ok(());
@@ -101,24 +100,52 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = Path::new(&pkgname);
if !path.exists() {
- return Err(std::io::Error::other(format!("Package archive not found: {}", pkgname)).into());
+ return Err(std::io::Error::other(format!(
+ "Package archive not found: {}",
+ pkgname
+ ))
+ .into());
}
if !path.is_file() {
- return Err(std::io::Error::other(format!("Path is not a file: {}", pkgname)).into());
+ return Err(
+ std::io::Error::other(format!("Path is not a file: {}", pkgname)).into(),
+ );
}
println!("Extracting archive...");
Package::extract_archive(&pkgname)?;
- let config = Config::parse().unwrap();
+ let config = Config::parse().unwrap();
let cache_dir = &config.paths.cache_dir;
- let install_toml_path = Path::new(cache_dir).join("INSTALL");
-
+
+ // Find the package directory (should be name-version format)
+ let mut pkg_dir_name = None;
+ for entry in std::fs::read_dir(cache_dir)? {
+ let entry = entry?;
+ let path = entry.path();
+ if path.is_dir() {
+ let dir_name = path.file_name().unwrap().to_string_lossy();
+ if dir_name.contains('-') && dir_name != "temp_extract" {
+ let install_path = path.join("INSTALL");
+ if install_path.exists() {
+ pkg_dir_name = Some(dir_name.to_string());
+ break;
+ }
+ }
+ }
+ }
+
+ let pkg_dir_name = pkg_dir_name.ok_or_else(|| {
+ std::io::Error::other("Package directory not found in cache")
+ })?;
+
+ let install_toml_path = Path::new(cache_dir).join(format!("{}/INSTALL", pkg_dir_name));
+
if !install_toml_path.exists() {
- return Err(std::io::Error::other("INSTALL file not found in archive").into());
+ return Err(std::io::Error::other("INSTALL file not found in package directory").into());
}
-
+
let install_content = std::fs::read_to_string(&install_toml_path)?;
let install_data: crate::pkgtoolkit::types::Install = toml::from_str(&install_content)?;
@@ -129,21 +156,25 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Package '{}' built successfully.", pkg.name);
return Ok(());
}
- Commands::Install { pkgname, source: _, args } => {
- let config = Config::parse().unwrap();
+ Commands::Install {
+ pkgname,
+ source: _,
+ args,
+ } => {
+ let config = Config::parse().unwrap();
if args.http {
println!("Installing {} via HTTP", pkgname);
let mut http_client = HTTPPackage::new(config);
- http_client.fetch_index_http().await?;
+ http_client.fetch_index_http().await?;
log::info!("Index fetched successfully.");
http_client.fetch_package_http(pkgname).await?;
log::info!("Package '{}' installed successfully.", pkgname);
} else {
println!("Installing {} via I2P", pkgname);
let mut i2p_client = I2PPackage::new(config);
- i2p_client.fetch_index().await?;
+ i2p_client.fetch_index().await?;
log::info!("Index fetched successfully.");
- i2p_client.fetch_package(pkgname).await?;
+ i2p_client.fetch_package(pkgname).await?;
log::info!("Package '{}' installed successfully.", pkgname);
}
return Ok(());
@@ -153,15 +184,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
return Ok(());
}
Commands::GetSource { pkgname } => {
- let config = Config::parse().unwrap();
+ let config = Config::parse().unwrap();
println!("Getting source of {}", pkgname);
-
let source_path = GitSource::get_source_by_name(pkgname, &config)?;
println!("Source code successfully downloaded to: {}", source_path);
return Ok(());
}
- Commands::DefaultConfig { repo, cachedir, buildir, installed_db } => {
+ Commands::DefaultConfig {
+ repo,
+ cachedir,
+ buildir,
+ installed_db,
+ } => {
println!("Generating config file");
if cachedir.is_none() && repo.is_none() && buildir.is_none() {
let config = Config::default().unwrap();
@@ -173,12 +208,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
log::warn!("Writing the default config to /etc/mesk/mesk.toml");
let path = Path::new("/etc/mesk/mesk.toml");
- std::fs::create_dir_all(path.parent().unwrap())?;
- let mut file = std::fs::File::create(path)?;
+ std::fs::create_dir_all(path.parent().unwrap())?;
+ let mut file = std::fs::File::create(path)?;
file.write_all(config.as_bytes())?;
println!("Config tool ending work.");
} else {
- let config = Config::generate(repo, cachedir, buildir, installed_db).unwrap();
+ let config = Config::generate(repo, cachedir, buildir, installed_db).unwrap();
println!("---- Start of generated config ----");
println!("{:?}", config);
@@ -187,19 +222,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
log::warn!("Writing the default config to /etc/mesk/mesk.toml");
let path = Path::new("/etc/mesk/mesk.toml");
- std::fs::create_dir_all(path.parent().unwrap())?;
- let mut file = std::fs::File::create(path)?;
- file.write_all(config.as_bytes())?;
+ std::fs::create_dir_all(path.parent().unwrap())?;
+ let mut file = std::fs::File::create(path)?;
+ file.write_all(config.as_bytes())?;
println!("Config tool ending work.");
}
return Ok(());
}
Commands::Update => {
- let config = Config::parse().unwrap();
+ let config = Config::parse().unwrap();
println!("Updating index from {}", config.repo.repo_url);
let mut i2p_client = I2PPackage::new(config);
- i2p_client.fetch_index().await?;
+ i2p_client.fetch_index().await?;
println!("Index updated successfully.");
return Ok(());
}
@@ -223,5 +258,4 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
return Ok(());
}
}
-
}
diff --git a/src/net/http_package.rs b/src/net/http_package.rs
index 4566e05..4924805 100644
--- a/src/net/http_package.rs
+++ b/src/net/http_package.rs
@@ -12,9 +12,8 @@ use std::{collections::HashMap, path::Path};
use tar::Archive;
use tokio::{fs::File, io::AsyncWriteExt};
-use crate::pkgtoolkit::install::InstallOperations;
use crate::pkgtoolkit::archive::ArchiveOperations;
-
+use crate::pkgtoolkit::install::InstallOperations;
pub struct HTTPPackage {
pub config: Config,
@@ -278,7 +277,7 @@ impl HTTPPackage {
// Install the package
log::info!("Installing package '{}'...", package_name);
let mut package = package_info.clone();
-
+
match package.install() {
Ok(_) => {
log::info!("Package '{}' installed successfully.", package_name);
diff --git a/src/net/i2p_package.rs b/src/net/i2p_package.rs
index cebfa34..fed3361 100644
--- a/src/net/i2p_package.rs
+++ b/src/net/i2p_package.rs
@@ -1,5 +1,7 @@
use crate::cfg::config::Config;
use crate::pkgtoolkit::Package;
+use crate::pkgtoolkit::archive::ArchiveOperations;
+use crate::pkgtoolkit::install::InstallOperations;
use flate2::read::GzDecoder;
use futures_util::stream::TryStreamExt;
use indicatif::{ProgressBar, ProgressStyle};
@@ -9,9 +11,6 @@ use std::fs::File as StdFile;
use std::{collections::HashMap, path::Path};
use tar::Archive;
use tokio::{fs::File, io::AsyncWriteExt};
-use crate::pkgtoolkit::archive::ArchiveOperations;
-use crate::pkgtoolkit::install::InstallOperations;
-
pub struct I2PPackage {
pub config: Config,
@@ -44,9 +43,7 @@ impl I2PPackage {
fn create_proxy_client(&self) -> Result<reqwest::Client, Box<dyn std::error::Error>> {
let proxy_url = format!("http://127.0.0.1:{}", self.config.repo.i2p_http_proxy_port);
let proxy = reqwest::Proxy::http(&proxy_url)?;
- let client = reqwest::Client::builder()
- .proxy(proxy)
- .build()?;
+ let client = reqwest::Client::builder().proxy(proxy).build()?;
Ok(client)
}
@@ -182,7 +179,6 @@ impl I2PPackage {
file_path: &Path,
description: &str,
) -> Result<(), Box<dyn std::error::Error>> {
-
let head_response = client.head(url).send().await?;
let content_length: u64 = head_response
.headers()
@@ -275,7 +271,7 @@ impl I2PPackage {
// Install the package
log::info!("Installing package '{}'...", package_name);
let mut package = package_info.clone();
-
+
match package.install() {
Ok(_) => {
log::info!("Package '{}' installed successfully.", package_name);
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))?;
diff --git a/tests/pkgtoolkit_funcs.rs b/tests/pkgtoolkit_funcs.rs
index bc9c22a..27cfcba 100644
--- a/tests/pkgtoolkit_funcs.rs
+++ b/tests/pkgtoolkit_funcs.rs
@@ -90,9 +90,7 @@ mode = "755"
let file = fs::File::create(&archive_path).unwrap();
let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default());
let mut tar_builder = tar::Builder::new(gz_encoder);
- tar_builder
- .append_dir_all(pkg_name, &temp_pkg_dir)
- .unwrap();
+ tar_builder.append_dir_all(pkg_name, &temp_pkg_dir).unwrap();
tar_builder.into_inner().unwrap().finish().unwrap();
let result = Package::check(archive_path.to_str().unwrap().to_string());
@@ -123,9 +121,7 @@ mode = "755"
let file = fs::File::create(&archive_path).unwrap();
let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default());
let mut tar_builder = tar::Builder::new(gz_encoder);
- tar_builder
- .append_dir_all(pkg_name, &temp_pkg_dir)
- .unwrap();
+ tar_builder.append_dir_all(pkg_name, &temp_pkg_dir).unwrap();
tar_builder.into_inner().unwrap().finish().unwrap();
let result = Package::check(archive_path.to_str().unwrap().to_string());
@@ -160,9 +156,7 @@ mode = "755"
let file = fs::File::create(&archive_path).unwrap();
let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default());
let mut tar_builder = tar::Builder::new(gz_encoder);
- tar_builder
- .append_dir_all(pkg_name, &temp_pkg_dir)
- .unwrap();
+ tar_builder.append_dir_all(pkg_name, &temp_pkg_dir).unwrap();
tar_builder.into_inner().unwrap().finish().unwrap();
let result = Package::check(archive_path.to_str().unwrap().to_string());
@@ -219,9 +213,7 @@ mode = "755"
let file = fs::File::create(&archive_path).unwrap();
let gz_encoder = flate2::write::GzEncoder::new(file, flate2::Compression::default());
let mut tar_builder = tar::Builder::new(gz_encoder);
- tar_builder
- .append_dir_all(pkg_name, &temp_pkg_dir)
- .unwrap();
+ tar_builder.append_dir_all(pkg_name, &temp_pkg_dir).unwrap();
tar_builder.into_inner().unwrap().finish().unwrap();
let result = Package::check(archive_path.to_str().unwrap().to_string());