- Remove 7 unused dependencies: apt-pkg-native, pkg-config, walkdir, lazy_static, futures, async-trait, cap-std - Delete dead code: Remove unused parallel.rs module - Clean build artifacts: Remove debian/cargo/, debian/.debhelper/, and other build files - Update .gitignore: Comprehensive patterns for build artifacts, test files, and temporary files - Move documentation: Relocate project docs to docs/ directory - Remove test artifacts: Clean up test files and package archives - Update Cargo.toml: Streamline dependencies and remove unused features - Verify build: Ensure project still compiles after cleanup This commit significantly reduces project size and improves build efficiency.
240 lines
8.9 KiB
Rust
240 lines
8.9 KiB
Rust
//! Package manager integration for apt-ostree compose
|
|
|
|
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
use apt_ostree::lib::error::{AptOstreeError, AptOstreeResult};
|
|
use super::treefile::Repository;
|
|
|
|
/// Package manager for APT operations
|
|
pub struct PackageManager {
|
|
build_root: PathBuf,
|
|
apt_config_dir: PathBuf,
|
|
sources_list_path: PathBuf,
|
|
preferences_path: PathBuf,
|
|
}
|
|
|
|
impl PackageManager {
|
|
/// Create a new package manager instance
|
|
pub fn new(_options: &crate::commands::compose::ComposeOptions) -> AptOstreeResult<Self> {
|
|
let build_root = PathBuf::from("/tmp/apt-ostree-build");
|
|
let apt_config_dir = build_root.join("etc/apt");
|
|
let sources_list_path = apt_config_dir.join("sources.list");
|
|
let preferences_path = apt_config_dir.join("preferences");
|
|
|
|
Ok(Self {
|
|
build_root,
|
|
apt_config_dir,
|
|
sources_list_path,
|
|
preferences_path,
|
|
})
|
|
}
|
|
|
|
/// Set up package sources from treefile repositories
|
|
pub async fn setup_package_sources(&self, repositories: &[Repository]) -> AptOstreeResult<()> {
|
|
println!("Setting up package sources...");
|
|
|
|
// Ensure APT config directory exists
|
|
std::fs::create_dir_all(&self.apt_config_dir)
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to create APT config directory: {}", e)))?;
|
|
|
|
// Write sources.list
|
|
let mut sources_content = String::new();
|
|
for repo in repositories {
|
|
sources_content.push_str(&format!("{}\n", repo.url));
|
|
}
|
|
|
|
std::fs::write(&self.sources_list_path, sources_content)
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to write sources.list: {}", e)))?;
|
|
|
|
// Create preferences file for package pinning if needed
|
|
let preferences_content = "# Package preferences for apt-ostree compose\n";
|
|
std::fs::write(&self.preferences_path, preferences_content)
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to write preferences: {}", e)))?;
|
|
|
|
println!("✅ Package sources configured successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Update package cache
|
|
pub async fn update_cache(&self) -> AptOstreeResult<()> {
|
|
println!("Updating package cache...");
|
|
|
|
// Use chroot to run apt-get update in the build environment
|
|
let output = Command::new("chroot")
|
|
.arg(&self.build_root)
|
|
.arg("apt-get")
|
|
.arg("update")
|
|
.output()
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to run apt-get update: {}", e)))?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
return Err(AptOstreeError::System(format!("apt-get update failed: {}", stderr)));
|
|
}
|
|
|
|
println!("✅ Package cache updated successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Install a package using APT
|
|
pub async fn install_package(&self, package: &str) -> AptOstreeResult<()> {
|
|
println!("Installing package: {}", package);
|
|
|
|
// Use chroot to run apt-get install in the build environment
|
|
let output = Command::new("chroot")
|
|
.arg(&self.build_root)
|
|
.arg("apt-get")
|
|
.arg("install")
|
|
.arg("-y") // Non-interactive
|
|
.arg("--no-install-recommends") // Don't install recommended packages
|
|
.arg(package)
|
|
.output()
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to run apt-get install: {}", e)))?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
return Err(AptOstreeError::System(format!("apt-get install {} failed: {}", package, stderr)));
|
|
}
|
|
|
|
println!("✅ Package {} installed successfully", package);
|
|
Ok(())
|
|
}
|
|
|
|
/// Resolve package dependencies
|
|
pub async fn resolve_dependencies(&self, packages: &[String]) -> AptOstreeResult<Vec<String>> {
|
|
println!("Resolving package dependencies...");
|
|
|
|
let mut all_packages = Vec::new();
|
|
|
|
for package in packages {
|
|
// Use apt-cache to get dependencies
|
|
let output = Command::new("chroot")
|
|
.arg(&self.build_root)
|
|
.arg("apt-cache")
|
|
.arg("depends")
|
|
.arg(package)
|
|
.output()
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to get dependencies for {}: {}", package, e)))?;
|
|
|
|
if output.status.success() {
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
for line in stdout.lines() {
|
|
if line.starts_with(" ") && !line.contains("PreDepends:") {
|
|
let dep = line.trim();
|
|
if !all_packages.contains(&dep.to_string()) {
|
|
all_packages.push(dep.to_string());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add original packages
|
|
for package in packages {
|
|
if !all_packages.contains(package) {
|
|
all_packages.push(package.clone());
|
|
}
|
|
}
|
|
|
|
println!("✅ Resolved {} packages (including dependencies)", all_packages.len());
|
|
Ok(all_packages)
|
|
}
|
|
|
|
/// Run post-installation scripts
|
|
pub async fn run_post_install_scripts(&self) -> AptOstreeResult<()> {
|
|
println!("Running post-installation scripts...");
|
|
|
|
// Run dpkg configure -a to configure all packages
|
|
let output = Command::new("chroot")
|
|
.arg(&self.build_root)
|
|
.arg("dpkg")
|
|
.arg("--configure")
|
|
.arg("-a")
|
|
.output()
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to run dpkg configure: {}", e)))?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
println!("Warning: dpkg configure had issues: {}", stderr);
|
|
}
|
|
|
|
println!("✅ Post-installation scripts completed");
|
|
Ok(())
|
|
}
|
|
|
|
/// Update package database
|
|
pub async fn update_package_database(&self) -> AptOstreeResult<()> {
|
|
println!("Updating package database...");
|
|
|
|
// Update package lists
|
|
self.update_cache().await?;
|
|
|
|
// Clean up any broken packages
|
|
let output = Command::new("chroot")
|
|
.arg(&self.build_root)
|
|
.arg("apt-get")
|
|
.arg("check")
|
|
.output()
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to run apt-get check: {}", e)))?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
println!("Warning: apt-get check had issues: {}", stderr);
|
|
}
|
|
|
|
println!("✅ Package database updated successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Initialize base system using debootstrap
|
|
pub async fn initialize_base_system(&self, base_image: &str) -> AptOstreeResult<()> {
|
|
println!("Initializing base system using debootstrap...");
|
|
|
|
// Extract Debian release from base image (e.g., "debian:trixie" -> "trixie")
|
|
let release = if base_image.contains(':') {
|
|
base_image.split(':').nth(1).unwrap_or("trixie")
|
|
} else {
|
|
base_image
|
|
};
|
|
|
|
// Use debootstrap to create base system
|
|
let output = Command::new("debootstrap")
|
|
.arg("--variant=minbase")
|
|
.arg("--include=apt,dpkg")
|
|
.arg(release)
|
|
.arg(&self.build_root)
|
|
.arg("http://deb.debian.org/debian")
|
|
.output()
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to run debootstrap: {}", e)))?;
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
return Err(AptOstreeError::System(format!("debootstrap failed: {}", stderr)));
|
|
}
|
|
|
|
println!("✅ Base system initialized successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Clean up package manager state
|
|
pub async fn cleanup(&self) -> AptOstreeResult<()> {
|
|
println!("Cleaning up package manager state...");
|
|
|
|
// Remove APT cache to reduce image size
|
|
let cache_dir = self.build_root.join("var/cache/apt");
|
|
if cache_dir.exists() {
|
|
std::fs::remove_dir_all(&cache_dir)
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to remove APT cache: {}", e)))?;
|
|
}
|
|
|
|
// Remove APT lists
|
|
let lists_dir = self.build_root.join("var/lib/apt/lists");
|
|
if lists_dir.exists() {
|
|
std::fs::remove_dir_all(&lists_dir)
|
|
.map_err(|e| AptOstreeError::System(format!("Failed to remove APT lists: {}", e)))?;
|
|
}
|
|
|
|
println!("✅ Package manager cleanup completed");
|
|
Ok(())
|
|
}
|
|
}
|