feat: initial implementation of Depot package manager

- Implement source-based package management with support for archives and Git
- Add multi-system build support (Autotools, CMake, Meson, Rust/Cargo, Custom)
- Implement atomic installation logic using transactions and fakeroot
- Add dependency resolution for build-time and runtime requirements
- Implement package indexing and local repository management
- Add comprehensive configuration system with system/package overrides
- Include Project guidelines (AGENTS.md) and README.md
This commit is contained in:
2026-02-16 11:35:23 -06:00
parent 94044a48c3
commit 00ca2ebac6
29 changed files with 9385 additions and 69 deletions
+101
View File
@@ -0,0 +1,101 @@
//! Build system abstraction
mod autotools;
mod bin;
mod cmake;
mod custom;
mod meson;
mod rust;
use crate::cross::CrossConfig;
use crate::package::{BuildType, PackageSpec};
use anyhow::Result;
use std::path::Path;
use std::process::Command;
/// Prepare a Command with a hermetic environment and some essential variables preserved.
pub fn prepare_command(cmd: &mut Command, env_vars: &[(&str, String)]) {
cmd.env_clear();
// Preserve essential environment variables
for var in &["PATH", "LANG", "HOME", "SHELL", "DESTDIR"] {
if let Ok(val) = std::env::var(var) {
cmd.env(var, val);
}
}
// Set requested environment variables
for (key, val) in env_vars {
cmd.env(key, val);
}
}
/// Build a package using the appropriate build system
pub fn build(
spec: &PackageSpec,
src_dir: &Path,
destdir: &Path,
cross: Option<&CrossConfig>,
) -> Result<()> {
if let Some(cc) = cross {
println!(
"Cross-compiling for {} with {:?}...",
cc.prefix, spec.build.build_type
);
} else {
println!("Building with {:?}...", spec.build.build_type);
}
// Clean destdir to prevent stale files/directories (e.g., directories where symlinks should be)
if destdir.exists() {
std::fs::remove_dir_all(destdir)?;
}
match spec.build.build_type {
BuildType::Autotools => autotools::build(spec, src_dir, destdir, cross),
BuildType::CMake => cmake::build(spec, src_dir, destdir, cross),
BuildType::Meson => meson::build(spec, src_dir, destdir, cross),
BuildType::Custom => custom::build(spec, src_dir, destdir, cross),
BuildType::Rust => rust::build(spec, src_dir, destdir, cross),
BuildType::Bin => bin::build(spec, src_dir, destdir, cross),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prepare_command() {
let mut cmd = Command::new("ls");
// Set an env var that should be cleared
cmd.env("FORBIDDEN", "value");
// Set PATH manually in the current process to ensure it's picked up if it exists
unsafe {
std::env::set_var("PATH", "/usr/bin");
std::env::set_var("HOME", "/home/test");
}
prepare_command(&mut cmd, &[("MYVAR", "myval".to_string())]);
let envs: std::collections::HashMap<_, _> = cmd.get_envs().collect();
assert!(envs.get(std::ffi::OsStr::new("PATH")).is_some());
assert!(envs.get(std::ffi::OsStr::new("HOME")).is_some());
assert!(envs.get(std::ffi::OsStr::new("FORBIDDEN")).is_none());
assert_eq!(
envs.get(std::ffi::OsStr::new("MYVAR")),
Some(&Some(std::ffi::OsString::from("myval").as_os_str()))
);
}
#[test]
fn test_prepare_command_preserves_destdir() {
let mut cmd = std::process::Command::new("ls");
unsafe {
std::env::set_var("DESTDIR", "/tmp/dest");
}
prepare_command(&mut cmd, &[]);
let envs: std::collections::HashMap<_, _> = cmd.get_envs().collect();
assert_eq!(
envs.get(std::ffi::OsStr::new("DESTDIR")),
Some(&Some(std::ffi::OsString::from("/tmp/dest").as_os_str()))
);
}
}